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?r... ============================================================================== --- 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=2... ============================================================================== --- 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=28... ============================================================================== --- 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