Author: fireball
Date: Sun Sep 2 00:54:02 2007
New Revision: 28751
URL:
http://svn.reactos.org/svn/reactos?rev=28751&view=rev
Log:
- Finish the memory map code, so it now actually creates a real memory map, with all
reserved, unusable pages marked
- Add a memory type enum and use it in memory descriptors
- Improvements in KiRosFrldrLpbToNtLpb() (separate the code into different functions,
bugfixes)
Modified:
trunk/reactos/include/reactos/arc/arc.h
trunk/reactos/ntoskrnl/ke/freeldr.c (contents, props changed)
trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/include/reactos/arc/arc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/arc/arc.h?…
==============================================================================
--- trunk/reactos/include/reactos/arc/arc.h (original)
+++ trunk/reactos/include/reactos/arc/arc.h Sun Sep 2 00:54:02 2007
@@ -86,6 +86,27 @@
LoaderMaximum
} TYPE_OF_MEMORY;
+typedef enum _MEMORY_TYPE
+{
+ MemoryExceptionBlock,
+ MemorySystemBlock,
+ MemoryFree,
+ MemoryBad,
+ MemoryLoadedProgram,
+ MemoryFirmwareTemporary,
+ MemoryFirmwarePermanent,
+ MemoryFreeContiguous,
+ MemorySpecialMemory,
+ MemoryMaximum
+} MEMORY_TYPE;
+
+typedef struct _MEMORY_DESCRIPTOR
+{
+ MEMORY_TYPE MemoryType;
+ ULONG BasePage;
+ ULONG PageCount;
+} MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR;
+
typedef struct _MEMORY_ALLOCATION_DESCRIPTOR
{
LIST_ENTRY ListEntry;
Modified: trunk/reactos/ntoskrnl/ke/freeldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/freeldr.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/freeldr.c (original)
+++ trunk/reactos/ntoskrnl/ke/freeldr.c Sun Sep 2 00:54:02 2007
@@ -11,6 +11,12 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+typedef struct _BIOS_MEMORY_DESCRIPTOR
+{
+ ULONG BlockBase;
+ ULONG BlockSize;
+} BIOS_MEMORY_DESCRIPTOR, *PBIOS_MEMORY_DESCRIPTOR;
/* GLOBALS *******************************************************************/
@@ -39,7 +45,7 @@
CHAR BldrNtHalPath[64]; // 0x025C
CHAR BldrNtBootPath[64]; // 0x029C
LDR_DATA_TABLE_ENTRY BldrModules[64]; // 0x02DC
-MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[64]; // 0x14DC
+MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[60]; // 0x14DC
WCHAR BldrModuleStrings[64][260]; // 0x19DC
WCHAR BldrModuleStringsFull[64][260]; // 0x9BDC
NLS_DATA_BLOCK BldrNlsDataBlock; // 0x11DDC
@@ -49,6 +55,14 @@
ARC_DISK_SIGNATURE BldrDiskInfo[32]; // 0x1413C
// 0x1443C
+/* BIOS Memory Map */
+BIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptors[16] = {{0}};
+PBIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptorList = BiosMemoryDescriptors;
+
+/* ARC Memory Map */
+ULONG NumberDescriptors = 0;
+MEMORY_DESCRIPTOR MDArray[60] = {{0}};
+
/* FUNCTIONS *****************************************************************/
PMEMORY_ALLOCATION_DESCRIPTOR
@@ -56,8 +70,794 @@
KiRosGetMdFromArray(VOID)
{
/* Return the next MD from the list, but make sure we don't overflow */
- if (BldrCurrentMd > 64) KEBUGCHECK(0);
+ if (BldrCurrentMd > 60) KEBUGCHECK(0);
return &BldrMemoryDescriptors[BldrCurrentMd++];
+}
+
+VOID
+NTAPI
+KiRosAddBiosBlock(ULONG Address,
+ ULONG Size)
+{
+ PBIOS_MEMORY_DESCRIPTOR BiosBlock = BiosMemoryDescriptorList;
+
+ /* Loop our BIOS Memory Descriptor List */
+ while (BiosBlock->BlockSize > 0)
+ {
+ /* Check if we've found a matching head block */
+ if (Address + Size == BiosBlock->BlockBase)
+ {
+ /* Simply enlarge and rebase it */
+ BiosBlock->BlockBase = Address;
+ BiosBlock->BlockSize += Size;
+ break;
+ }
+
+ /* Check if we've found a matching tail block */
+ if (Address == (BiosBlock->BlockBase + BiosBlock->BlockSize))
+ {
+ /* Simply enlarge it */
+ BiosBlock->BlockSize += Size;
+ break;
+ }
+
+ /* Nothing suitable found, try the next block */
+ BiosBlock++;
+ }
+
+ /* No usable blocks found, found a free block instead */
+ if (!BiosBlock->BlockSize)
+ {
+ /* Write our data */
+ BiosBlock->BlockBase = Address;
+ BiosBlock->BlockSize = Size;
+
+ /* Create a new block and mark it as the end of the array */
+ BiosBlock++;
+ BiosBlock->BlockBase = BiosBlock->BlockSize = 0L;
+ }
+}
+
+VOID
+NTAPI
+KiRosBuildBiosMemoryMap(VOID)
+{
+ ULONG j;
+ ULONG BlockBegin, BlockEnd;
+
+ /* Loop the BIOS Memory Map */
+ for (j = 0; j < KeMemoryMapRangeCount; j++)
+ {
+ /* Get the start and end addresses */
+ BlockBegin = KeMemoryMap[j].BaseAddrLow;
+ BlockEnd = KeMemoryMap[j].BaseAddrLow + KeMemoryMap[j].LengthLow - 1;
+
+ /* Make sure this isn't a > 4GB descriptor */
+ if (!KeMemoryMap[j].BaseAddrHigh)
+ {
+ /* Make sure we don't overflow */
+ if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
+
+ /* Check if this is free memory */
+ if (KeMemoryMap[j].Type == 1)
+ {
+ /* Add it to our BIOS descriptors */
+ KiRosAddBiosBlock(BlockBegin, BlockEnd - BlockBegin + 1);
+ }
+ }
+ }
+}
+
+NTSTATUS
+NTAPI
+KiRosAllocateArcDescriptor(IN ULONG PageBegin,
+ IN ULONG PageEnd,
+ IN MEMORY_TYPE MemoryType)
+{
+ ULONG i;
+
+ /* Loop all our descriptors */
+ for (i = 0; i < NumberDescriptors; i++)
+ {
+ /* Attempt to fing a free block that describes our region */
+ if ((MDArray[i].MemoryType == MemoryFree) &&
+ (MDArray[i].BasePage <= PageBegin) &&
+ (MDArray[i].BasePage + MDArray[i].PageCount > PageBegin) &&
+ (MDArray[i].BasePage + MDArray[i].PageCount >= PageEnd))
+ {
+ /* Found one! */
+ break;
+ }
+ }
+
+ /* Check if we found no free blocks, and fail if so */
+ if (i == NumberDescriptors) return ENOMEM;
+
+ /* Check if the block has our base address */
+ if (MDArray[i].BasePage == PageBegin)
+ {
+ /* Check if it also has our ending address */
+ if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
+ {
+ /* Then convert this region into our new memory type */
+ MDArray[i].MemoryType = MemoryType;
+ }
+ else
+ {
+ /* Otherwise, make sure we have enough descriptors */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Cut this descriptor short */
+ MDArray[i].BasePage = PageEnd;
+ MDArray[i].PageCount -= (PageEnd - PageBegin);
+
+ /* And allocate a new descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
+ }
+ }
+ else if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
+ {
+ /* This block has our end address, make sure we have a free block */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Rebase this descriptor */
+ MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
+
+ /* And allocate a new descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
+ }
+ else
+ {
+ /* We'll need two descriptors, make sure they're available */
+ if ((NumberDescriptors + 1) >= 60) return ENOMEM;
+
+ /* Allocate a free memory descriptor for what follows us */
+ MDArray[NumberDescriptors].BasePage = PageEnd;
+ MDArray[NumberDescriptors].PageCount = MDArray[i].PageCount -
+ (PageEnd - MDArray[i].BasePage);
+ MDArray[NumberDescriptors].MemoryType = MemoryFree;
+ NumberDescriptors++;
+
+ /* Cut down the current free descriptor */
+ MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
+
+ /* Allocate a new memory descriptor for our memory range */
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ NumberDescriptors++;
+ }
+
+ /* Everything went well */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+KiRosConfigureArcDescriptor(IN ULONG PageBegin,
+ IN ULONG PageEnd,
+ IN TYPE_OF_MEMORY MemoryType)
+{
+ ULONG i;
+ ULONG BlockBegin, BlockEnd;
+ MEMORY_TYPE BlockType;
+ BOOLEAN Combined = FALSE;
+
+ /* If this descriptor seems bogus, just return */
+ if (PageEnd <= PageBegin) return STATUS_SUCCESS;
+
+ /* Loop every ARC descriptor, trying to find one we can modify */
+ for (i = 0; i < NumberDescriptors; i++)
+ {
+ /* Get its settings */
+ BlockBegin = MDArray[i].BasePage;
+ BlockEnd = MDArray[i].BasePage + MDArray[i].PageCount;
+ BlockType = MDArray[i].MemoryType;
+
+ /* Check if we can fit inside this block */
+ if (BlockBegin < PageBegin)
+ {
+ /* Check if we are larger then it */
+ if ((BlockEnd > PageBegin) && (BlockEnd <= PageEnd))
+ {
+ /* Make it end where we start */
+ BlockEnd = PageBegin;
+ }
+
+ /* Check if it ends after we do */
+ if (BlockEnd > PageEnd)
+ {
+ /* Make sure we can allocate a descriptor */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Create a descriptor for whatever memory we're not part of */
+ MDArray[NumberDescriptors].MemoryType = BlockType;
+ MDArray[NumberDescriptors].BasePage = PageEnd;
+ MDArray[NumberDescriptors].PageCount = BlockEnd - PageEnd;
+ NumberDescriptors++;
+
+ /* The next block ending is now where we begin */
+ BlockEnd = PageBegin;
+ }
+ }
+ else
+ {
+ /* Check if the blog begins inside our range */
+ if (BlockBegin < PageEnd)
+ {
+ /* Check if it ends before we do */
+ if (BlockEnd < PageEnd)
+ {
+ /* Then make it disappear */
+ BlockEnd = BlockBegin;
+ }
+ else
+ {
+ /* Otherwise make it start where we end */
+ BlockBegin = PageEnd;
+ }
+ }
+ }
+
+ /* Check if the block matches us, and we haven't tried combining yet */
+ if ((BlockType == MemoryType) && !(Combined))
+ {
+ /* Check if it starts where we end */
+ if (BlockBegin == PageEnd)
+ {
+ /* Make it start with us, and combine us */
+ BlockBegin = PageBegin;
+ Combined = TRUE;
+ }
+ else if (BlockEnd == PageBegin)
+ {
+ /* Otherwise, it ends where we begin, combine its ending */
+ BlockEnd = PageEnd;
+ Combined = TRUE;
+ }
+ }
+
+ /* Check the original block data matches with what we came up with */
+ if ((MDArray[i].BasePage == BlockBegin) &&
+ (MDArray[i].PageCount == BlockEnd - BlockBegin))
+ {
+ /* Then skip it */
+ continue;
+ }
+
+ /* Otherwise, set our new settings for this block */
+ MDArray[i].BasePage = BlockBegin;
+ MDArray[i].PageCount = BlockEnd - BlockBegin;
+
+ /* Check if we are killing the block */
+ if (BlockBegin == BlockEnd)
+ {
+ /* Delete this block and restart the loop properly */
+ NumberDescriptors--;
+ if (i < NumberDescriptors) MDArray[i] = MDArray[NumberDescriptors];
+ i--;
+ }
+ }
+
+ /* If we got here without combining, we need to allocate a new block */
+ if (!(Combined) && (MemoryType < LoaderMaximum))
+ {
+ /* Make sure there's enough descriptors */
+ if (NumberDescriptors == 60) return ENOMEM;
+
+ /* Allocate a new block with our data */
+ MDArray[NumberDescriptors].MemoryType = MemoryType;
+ MDArray[NumberDescriptors].BasePage = PageBegin;
+ MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
+ NumberDescriptors++;
+ }
+
+ /* Changes complete, return success */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildOsMemoryMap(VOID)
+{
+ PBIOS_MEMORY_DESCRIPTOR MdBlock;
+ ULONG BlockStart, BlockEnd, BiasedStart, BiasedEnd, PageStart, PageEnd;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG BiosPage = 0xA0;
+
+ /* Loop the BIOS Memory Descriptor List */
+ MdBlock = BiosMemoryDescriptorList;
+ while (MdBlock->BlockSize)
+ {
+ /* Get the statrt and end addresses */
+ BlockStart = MdBlock->BlockBase;
+ BlockEnd = BlockStart + MdBlock->BlockSize - 1;
+
+ /* Align them to page boundaries */
+ BiasedStart = BlockStart & (PAGE_SIZE - 1);
+ if (BiasedStart) BlockStart = BlockStart + PAGE_SIZE - BiasedStart;
+ BiasedEnd = (BlockEnd + 1) & (ULONG)(PAGE_SIZE - 1);
+ if (BiasedEnd) BlockEnd -= BiasedEnd;
+
+ /* Get the actual page numbers */
+ PageStart = BlockStart >> PAGE_SHIFT;
+ PageEnd = (BlockEnd + 1) >> PAGE_SHIFT;
+
+ /* If we're starting at page 0, then put the BIOS page at the end */
+ if (!PageStart) BiosPage = PageEnd;
+
+ /* Check if we did any alignment */
+ if (BiasedStart)
+ {
+ /* Mark that region as reserved */
+ Status = KiRosConfigureArcDescriptor(PageStart - 1,
+ PageStart,
+ MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) break;
+ }
+
+ /* Check if we did any alignment */
+ if (BiasedEnd)
+ {
+ /* Mark that region as reserved */
+ Status = KiRosConfigureArcDescriptor(PageEnd - 1,
+ PageEnd,
+ MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) break;
+
+ /* If the bios page was the last page, use the next one instead */
+ if (BiosPage == PageEnd) BiosPage += 1;
+ }
+
+ /* Check if the page is below the 16MB Memory hole */
+ if (PageEnd <= 0xFC0)
+ {
+ /* It is, mark the memory a free */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderFree);
+ }
+ else if (PageStart >= 0x1000)
+ {
+ /* It's over 16MB, so that memory gets marked as reserve */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderReserve);
+ }
+ else
+ {
+ /* Check if it starts below the memory hole */
+ if (PageStart < 0xFC0)
+ {
+ /* Mark that part as free */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ 0xFC0,
+ MemoryFree);
+ if (Status != STATUS_SUCCESS) break;
+
+ /* And update the page start for the code below */
+ PageStart = 0xFC0;
+ }
+
+ /* Any code in the memory hole region ends up as reserve */
+ Status = KiRosConfigureArcDescriptor(PageStart,
+ PageEnd,
+ LoaderReserve);
+ }
+
+ /* If we failed, break out, otherwise, go to the next BIOS block */
+ if (Status != STATUS_SUCCESS) break;
+ MdBlock++;
+ }
+
+ /* If anything failed until now, return error code */
+ if (Status != STATUS_SUCCESS) return Status;
+
+ /* Set the top 16MB region as reserved */
+ Status = KiRosConfigureArcDescriptor(0xFC0, 0x1000, MemorySpecialMemory);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ /* Setup the BIOS region as reserved */
+ KiRosConfigureArcDescriptor(0xA0, 0x100, LoaderMaximum);
+ KiRosConfigureArcDescriptor(BiosPage, 0x100, MemoryFirmwarePermanent);
+
+ /* Build an entry for the IVT */
+ Status = KiRosAllocateArcDescriptor(0, 1, MemoryFirmwarePermanent);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ /* Build an entry for the KPCR (which we put in page 1) */
+ Status = KiRosAllocateArcDescriptor(1, 2, LoaderMemoryData);
+ if (Status != STATUS_SUCCESS) return Status;
+
+ /* Build an entry for the PDE and return the status */
+ Status = KiRosAllocateArcDescriptor(KeRosLoaderBlock->
+ PageDirectoryStart >> PAGE_SHIFT,
+ KeRosLoaderBlock->
+ PageDirectoryEnd >> PAGE_SHIFT,
+ LoaderMemoryData);
+ return Status;
+}
+
+VOID
+NTAPI
+KiRosBuildReservedMemoryMap(VOID)
+{
+ ULONG j;
+ ULONG BlockBegin, BlockEnd, BiasedPage;
+
+ /* Loop the BIOS Memory Map */
+ for (j = 0; j < KeMemoryMapRangeCount; j++)
+ {
+ /* Get the start and end addresses */
+ BlockBegin = KeMemoryMap[j].BaseAddrLow;
+ BlockEnd = BlockBegin + KeMemoryMap[j].LengthLow - 1;
+
+ /* Make sure it wasn't a > 4GB descriptor */
+ if (!KeMemoryMap[j].BaseAddrHigh)
+ {
+ /* Make sure it doesn't overflow */
+ if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
+
+ /* Check if this was free memory */
+ if (KeMemoryMap[j].Type == 1)
+ {
+ /* Get the page-aligned addresses */
+ BiasedPage = BlockBegin & (PAGE_SIZE - 1);
+ BlockBegin >>= PAGE_SHIFT;
+ if (BiasedPage) BlockBegin++;
+ BlockEnd = (BlockEnd >> PAGE_SHIFT) + 1;
+
+ /* Check if the block is within the 16MB memory hole */
+ if ((BlockBegin < 0xFC0) && (BlockEnd >= 0xFC0))
+ {
+ /* Don't allow it to cross this boundary */
+ BlockBegin = 0xFC0;
+ }
+
+ /* Check if the boundary is across 16MB */
+ if ((BlockEnd > 0xFFF) && (BlockBegin <= 0xFFF))
+ {
+ /* Don't let it cross */
+ BlockEnd = 0xFFF;
+ }
+
+ /* Check if the block describes the memory hole */
+ if ((BlockBegin >= 0xFC0) && (BlockEnd <= 0xFFF))
+ {
+ /* Set this region as temporary */
+ KiRosConfigureArcDescriptor(BlockBegin,
+ BlockEnd,
+ MemoryFirmwareTemporary);
+ }
+ }
+ else
+ {
+ /* Get the page-aligned addresses */
+ BlockBegin >>= PAGE_SHIFT;
+ BiasedPage = (BlockEnd + 1) & (PAGE_SIZE - 1);
+ BlockEnd >>= PAGE_SHIFT;
+ if (BiasedPage) BlockEnd++;
+
+ /* Set this memory as reserved */
+ KiRosConfigureArcDescriptor(BlockBegin,
+ BlockEnd + 1,
+ MemorySpecialMemory);
+ }
+ }
+ }
+}
+
+VOID
+NTAPI
+KiRosInsertNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+{
+ PLIST_ENTRY ListHead, PreviousEntry, NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor = NULL, NextDescriptor = NULL;
+
+ /* Loop the memory descriptor list */
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ PreviousEntry = ListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptor and check if it's below ours */
+ NextDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+ if (NewDescriptor->BasePage < NextDescriptor->BasePage) break;
+
+ /* It isn't, save the previous entry and descriptor, and try again */
+ PreviousEntry = NextEntry;
+ Descriptor = NextDescriptor;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* So we found the right spot to insert. Is this free memory? */
+ if (NewDescriptor->MemoryType != LoaderFree)
+ {
+ /* It isn't, so insert us before the last descriptor */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
+ else
+ {
+ /* We're free memory. Check if the entry we found is also free memory */
+ if ((PreviousEntry != ListHead) &&
+ ((Descriptor->MemoryType == LoaderFree) ||
+ (Descriptor->MemoryType == LoaderReserve)) &&
+ ((Descriptor->BasePage + Descriptor->PageCount) ==
+ NewDescriptor->BasePage))
+ {
+ /* It's free memory, and we're right after it. Enlarge that block */
+ Descriptor->PageCount += NewDescriptor->PageCount;
+ NewDescriptor = Descriptor;
+ }
+ else
+ {
+ /* Our range scan't be combined, so just insert us separately */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
+
+ /* Check if we merged with an existing free memory block */
+ if ((NextEntry != ListHead) &&
+ ((NextDescriptor->MemoryType == LoaderFree) ||
+ (NextDescriptor->MemoryType == LoaderReserve)) &&
+ ((NewDescriptor->BasePage + NewDescriptor->PageCount) ==
+ NextDescriptor->BasePage))
+ {
+ /* Update our own block */
+ NewDescriptor->PageCount += NextDescriptor->PageCount;
+
+ /* Remove the next block */
+ RemoveEntryList(&NextDescriptor->ListEntry);
+ }
+ }
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor, NextDescriptor = NULL;
+ LONG Delta;
+ TYPE_OF_MEMORY CurrentType;
+ BOOLEAN UseNext;
+
+ /* Check how many pages we'll be consuming */
+ Delta = BasePage - MemoryDescriptor->BasePage;
+ if (!(Delta) && (PageCount == MemoryDescriptor->PageCount))
+ {
+ /* We can simply convert the current descriptor into our new type */
+ MemoryDescriptor->MemoryType = MemoryType;
+ }
+ else
+ {
+ /* Get the current memory type of the descriptor, and reserve it */
+ CurrentType = MemoryDescriptor->MemoryType;
+ MemoryDescriptor->MemoryType = LoaderSpecialMemory;
+
+ /* Check if we'll need another descriptor for what's left of memory */
+ UseNext = ((BasePage != MemoryDescriptor->BasePage) &&
+ (Delta + PageCount != MemoryDescriptor->PageCount));
+
+ /* Get a descriptor */
+ Descriptor = KiRosGetMdFromArray();
+ if (!Descriptor) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Check if we are using another descriptor */
+ if (UseNext)
+ {
+ /* Allocate that one too */
+ NextDescriptor = KiRosGetMdFromArray();
+ if (!NextDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Build the descriptor we got */
+ Descriptor->MemoryType = MemoryType;
+ Descriptor->BasePage = BasePage;
+ Descriptor->PageCount = PageCount;
+
+ /* Check if we're starting at the same place as the old one */
+ if (BasePage == MemoryDescriptor->BasePage)
+ {
+ /* Simply decrease the old descriptor and rebase it */
+ MemoryDescriptor->BasePage += PageCount;
+ MemoryDescriptor->PageCount -= PageCount;
+ MemoryDescriptor->MemoryType = CurrentType;
+ }
+ else if (Delta + PageCount == MemoryDescriptor->PageCount)
+ {
+ /* We finish where the old one did, shorten it */
+ MemoryDescriptor->PageCount -= PageCount;
+ MemoryDescriptor->MemoryType = CurrentType;
+ }
+ else
+ {
+ /* We're inside the current block, mark our free region */
+ NextDescriptor->MemoryType = LoaderFree;
+ NextDescriptor->BasePage = BasePage + PageCount;
+ NextDescriptor->PageCount = MemoryDescriptor->PageCount -
+ (PageCount + Delta);
+
+ /* And cut down the current descriptor */
+ MemoryDescriptor->PageCount = Delta;
+ MemoryDescriptor->MemoryType = CurrentType;
+
+ /* Finally, insert our new free descriptor into the list */
+ KiRosInsertNtDescriptor(NextDescriptor);
+ }
+
+ /* Insert the descriptor we allocated */
+ KiRosInsertNtDescriptor(Descriptor);
+ }
+
+ /* Return success */
+ return STATUS_SUCCESS;
+}
+
+PMEMORY_ALLOCATION_DESCRIPTOR
+NTAPI
+KiRosFindNtDescriptor(IN ULONG BasePage)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
+ PLIST_ENTRY NextEntry, ListHead;
+
+ /* Scan the memory descriptor list */
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptor */
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Check if it can contain our memory range */
+ if ((MdBlock->BasePage <= BasePage) &&
+ (MdBlock->BasePage + MdBlock->PageCount > BasePage))
+ {
+ /* It can, break out */
+ break;
+ }
+
+ /* Go to the next descriptor */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Return the descriptor we found, if any */
+ return MdBlock;
+}
+
+NTSTATUS
+NTAPI
+KiRosAllocateNtDescriptor(IN TYPE_OF_MEMORY MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount,
+ IN ULONG Alignment,
+ OUT PULONG ReturnedBase)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
+ ULONG AlignedBase, AlignedLimit;
+ PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock;
+ ULONG ActiveAlignedBase = 0;
+ PLIST_ENTRY NextEntry, ListHead;
+
+ /* If no information was given, make some assumptions */
+ if (!Alignment) Alignment = 1;
+ if (!PageCount) PageCount = 1;
+
+ /* Start looking for a matching descvriptor */
+ do
+ {
+ /* Calculate the limit of the range */
+ AlignedLimit = PageCount + BasePage;
+
+ /* Find a descriptor that already contains our base address */
+ MdBlock = KiRosFindNtDescriptor(BasePage);
+ if (MdBlock)
+ {
+ /* If it contains our limit as well, break out early */
+ if ((MdBlock->PageCount + MdBlock->BasePage) > AlignedLimit) break;
+ }
+
+ /* Loop the memory list */
+ ActiveMdBlock = NULL;
+ ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the current descriptors */
+ MdBlock = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /* Align the base address and our limit */
+ AlignedBase = (MdBlock->BasePage + (Alignment - 1)) &~ Alignment;
+ AlignedLimit = MdBlock->PageCount -
+ AlignedBase +
+ MdBlock->BasePage;
+
+ /* Check if this is a free block that can satisfy us */
+ if ((MdBlock->MemoryType == LoaderFree) &&
+ (AlignedLimit <= MdBlock->PageCount) &&
+ (PageCount <= AlignedLimit))
+ {
+ /* It is, stop searching */
+ ActiveMdBlock = MdBlock;
+ ActiveAlignedBase = AlignedBase;
+ break;
+ }
+
+ /* Try the next block */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* See if we came up with an adequate block */
+ if (ActiveMdBlock)
+ {
+ /* Generate a descriptor in it */
+ *ReturnedBase = AlignedBase;
+ return KiRosBuildNtDescriptor(ActiveMdBlock,
+ MemoryType,
+ ActiveAlignedBase,
+ PageCount);
+ }
+ } while (TRUE);
+
+ /* We found a matching block, generate a descriptor with it */
+ *ReturnedBase = BasePage;
+ return KiRosBuildNtDescriptor(MdBlock, MemoryType, BasePage, PageCount);
+}
+
+NTSTATUS
+NTAPI
+KiRosBuildArcMemoryList(VOID)
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ MEMORY_DESCRIPTOR *Memory;
+ ULONG i;
+
+ /* Loop all BIOS Memory Descriptors */
+ for (i = 0; i < NumberDescriptors; i++)
+ {
+ /* Get the current descriptor */
+ Memory = &MDArray[i];
+
+ /* Allocate an NT Memory Descriptor */
+ Descriptor = KiRosGetMdFromArray();
+ if (!Descriptor) return ENOMEM;
+
+ /* Copy the memory type */
+ Descriptor->MemoryType = Memory->MemoryType;
+ if (Memory->MemoryType == MemoryFreeContiguous)
+ {
+ /* Convert this to free */
+ Descriptor->MemoryType = LoaderFree;
+ }
+ else if (Memory->MemoryType == MemorySpecialMemory)
+ {
+ /* Convert this to special memory */
+ Descriptor->MemoryType = LoaderSpecialMemory;
+ }
+
+ /* Copy the range data */
+ Descriptor->BasePage = Memory->BasePage;
+ Descriptor->PageCount = Memory->PageCount;
+
+ /* Insert the descriptor */
+ if (Descriptor->PageCount) KiRosInsertNtDescriptor(Descriptor);
+ }
+
+ /* All went well */
+ return STATUS_SUCCESS;
}
VOID
@@ -67,7 +867,6 @@
{
PLOADER_PARAMETER_BLOCK LoaderBlock;
PLDR_DATA_TABLE_ENTRY LdrEntry;
- PMEMORY_ALLOCATION_DESCRIPTOR MdEntry;
PLOADER_MODULE RosEntry;
ULONG i, j, ModSize;
PVOID ModStart;
@@ -79,15 +878,16 @@
WCHAR PathToDrivers[] = L"\\SystemRoot\\System32\\drivers\\";
WCHAR PathToSystem32[] = L"\\SystemRoot\\System32\\";
CHAR DriverNameLow[256];
+ ULONG Base;
/* First get some kernel-loader globals */
AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE :
FALSE;
- MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
- MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
+ MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
+ MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
/* Set the NT Loader block and initialize it */
- *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
+ *NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
/* Set the NLS Data block */
@@ -105,63 +905,17 @@
InitializeListHead(&LoaderBlock->BootDriverListHead);
InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
- /* Create one large blob of free memory */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderFree;
- MdEntry->BasePage = 0;
- MdEntry->PageCount = MmFreeLdrMemHigher / 4;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
-
- /*
- * FIXME: Instead of just "inserting" MDs into the list,
- * we need to make then be "consumed" from the Free Descriptor.
- * This will happen soon (and also ensure a sorted list).
- */
-
- /* Loop the BIOS Memory Map */
- for (j = 0; j < KeMemoryMapRangeCount; j++)
- {
- /* Check if this is a reserved entry */
- if (KeMemoryMap[j].Type == 2)
- {
- /* It is, build an entry for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderSpecialMemory;
- MdEntry->BasePage = KeMemoryMap[j].BaseAddrLow >> PAGE_SHIFT;
- MdEntry->PageCount = (KeMemoryMap[j].LengthLow + PAGE_SIZE - 1) >>
PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
- }
- }
-
- /* Page 0 is reserved: build an entry for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderFirmwarePermanent;
- MdEntry->BasePage = 0;
- MdEntry->PageCount = 1;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
-
- /* Build an entry for the KPCR (which we put in page 1) */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderMemoryData;
- MdEntry->BasePage = 1;
- MdEntry->PageCount = 1;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
-
- /* Build an entry for the PDE */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderMemoryData;
- MdEntry->BasePage = (ULONG_PTR)MmGetPageDirectory() >> PAGE_SHIFT;
- MdEntry->PageCount = (MmFreeLdrPageDirectoryEnd -
- (ULONG_PTR)MmGetPageDirectory()) / PAGE_SIZE;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
-
- /* Mark Video ROM as reserved */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderFirmwarePermanent;
- MdEntry->BasePage = 0xA0000 >> PAGE_SHIFT;
- MdEntry->PageCount = (0xE8000 - 0xA0000) / PAGE_SIZE;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
+ /* Build the free memory map, which uses BIOS Descriptors */
+ KiRosBuildBiosMemoryMap();
+
+ /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
+ KiRosBuildOsMemoryMap();
+
+ /* Build entries for the reserved map, which uses ARC Descriptors */
+ KiRosBuildReservedMemoryMap();
+
+ /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
+ KiRosBuildArcMemoryList();
/* Loop boot driver list */
for (i = 0; i < RosLoaderBlock->ModsCount; i++)
@@ -180,12 +934,12 @@
LoaderBlock->NlsData->AnsiCodePageData = ModStart;
/* Create an MD for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderNlsData;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
continue;
}
else if (!_stricmp(DriverName, "oem.nls"))
@@ -195,12 +949,12 @@
LoaderBlock->NlsData->OemCodePageData = ModStart;
/* Create an MD for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderNlsData;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
continue;
}
else if (!_stricmp(DriverName, "casemap.nls"))
@@ -210,12 +964,12 @@
LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
/* Create an MD for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderNlsData;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderNlsData,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
continue;
}
@@ -232,12 +986,12 @@
LoaderBlock->SetupLdrBlock = NULL;
/* Create an MD for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderRegistryData;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderRegistryData,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
continue;
}
@@ -246,13 +1000,11 @@
!(_stricmp(DriverName, "hardware.hiv")))
{
/* Create an MD for it */
- ModStart = RVA(ModStart, KSEG0_BASE);
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderRegistryData;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderRegistryData,
+ (ULONG_PTR)ModStart >> PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
continue;
}
@@ -260,32 +1012,32 @@
if (!(_stricmp(DriverName, "ntoskrnl.exe")))
{
/* Create an MD for it */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderSystemCode;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderSystemCode,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
}
else if (!(_stricmp(DriverName, "hal.dll")))
{
/* Create an MD for the HAL */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderHalCode;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderHalCode,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
}
else
{
/* Create an MD for any driver */
- MdEntry = KiRosGetMdFromArray();
- MdEntry->MemoryType = LoaderBootDriver;
- MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
PAGE_SHIFT;
- MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
- &MdEntry->ListEntry);
+ KiRosAllocateNtDescriptor(LoaderBootDriver,
+ ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
+ PAGE_SHIFT,
+ (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
+ 0,
+ &Base);
}
/* Lowercase the drivername so we can check its extension later */
@@ -361,7 +1113,9 @@
/* Save the number of pages the kernel images take */
LoaderBlock->Extension->LoaderPagesSpanned =
- MmFreeLdrLastKrnlPhysAddr - MmFreeLdrFirstKrnlPhysAddr;
+ PAGE_ROUND_UP(KeRosLoaderBlock->
+ ModsAddr[KeRosLoaderBlock->ModsCount - 1].ModEnd) -
+ KeRosLoaderBlock->ModsAddr[0].ModStart;
LoaderBlock->Extension->LoaderPagesSpanned /= PAGE_SIZE;
/* Now setup the setup block if we have one */
@@ -452,16 +1206,15 @@
/* Save pointer to ROS Block */
KeRosLoaderBlock = LoaderBlock;
-
- /* Save memory manager data */
MmFreeLdrLastKernelAddress = PAGE_ROUND_UP(KeRosLoaderBlock->
ModsAddr[KeRosLoaderBlock->
ModsCount - 1].
- ModEnd);
+ ModEnd);
MmFreeLdrFirstKrnlPhysAddr = KeRosLoaderBlock->ModsAddr[0].ModStart -
KSEG0_BASE;
MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress - KSEG0_BASE;
+ /* Save memory manager data */
KeMemoryMapRangeCount = 0;
if (LoaderBlock->Flags & MB_FLAGS_MMAP_INFO)
{
Propchange: trunk/reactos/ntoskrnl/ke/freeldr.c
------------------------------------------------------------------------------
--- svn:needs-lock (original)
+++ svn:needs-lock (removed)
@@ -1,1 +1,0 @@
-*
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c Sun Sep 2 00:54:02 2007
@@ -326,7 +326,8 @@
"MemoryData ", // not used
"NlsData ", // used
"SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
+ "BBTMemory ",
+ "LoaderReserve "// == Bad
};
VOID