diff --git a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
index 42a13495c76..19842ed4ef6 100644
--- a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
+++ b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
@@ -73,6 +73,7 @@
conversion.c
peloader.c
winldr.c
+ wlmemory.c
wlregistry.c
@@ -81,6 +82,7 @@
conversion.c
peloader.c
winldr.c
+ wlmemory.c
wlregistry.c
diff --git a/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
index bd111ef09bf..ef6a18dfdfb 100644
--- a/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
+++ b/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
@@ -1,9 +1,9 @@
/*
* PROJECT: EFI Windows Loader
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: freeldr/winldr/wlmemory.c
+ * FILE: freeldr/amd64/wlmemory.c
* PURPOSE: Memory related routines
- * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ***************************************************************/
@@ -13,8 +13,7 @@
#include
#include
-extern ULONG TotalNLSSize;
-extern ULONG LoaderPagesSpanned;
+//extern ULONG LoaderPagesSpanned;
// This is needed because headers define wrong one for ReactOS
#undef KIP0PCRADDRESS
@@ -22,52 +21,6 @@ extern ULONG LoaderPagesSpanned;
#define HYPER_SPACE_ENTRY 0x300
-PCHAR MemTypeDesc[] = {
- "ExceptionBlock ", // ?
- "SystemBlock ", // ?
- "Free ",
- "Bad ", // used
- "LoadedProgram ", // == Free
- "FirmwareTemporary ", // == Free
- "FirmwarePermanent ", // == Bad
- "OsloaderHeap ", // used
- "OsloaderStack ", // == Free
- "SystemCode ",
- "HalCode ",
- "BootDriver ", // not used
- "ConsoleInDriver ", // ?
- "ConsoleOutDriver ", // ?
- "StartupDpcStack ", // ?
- "StartupKernelStack", // ?
- "StartupPanicStack ", // ?
- "StartupPcrPage ", // ?
- "StartupPdrPage ", // ?
- "RegistryData ", // used
- "MemoryData ", // not used
- "NlsData ", // used
- "SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
- };
-
-VOID
-WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
-
-
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type);
-VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
-
-VOID
-WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
-
-VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-
// This is needed only for SetProcessorContext routine
#pragma pack(2)
typedef struct
@@ -79,91 +32,284 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
/* GLOBALS ***************************************************************/
-PHARDWARE_PTE PDE;
-PHARDWARE_PTE HalPageTable;
-
-PUCHAR PhysicalPageTablesBuffer;
-PUCHAR KernelPageTablesBuffer;
-ULONG PhysicalPageTables;
-ULONG KernelPageTables;
-
-MEMORY_ALLOCATION_DESCRIPTOR *Mad;
-ULONG MadCount = 0;
+//PHARDWARE_PTE PDE;
+//PHARDWARE_PTE HalPageTable;
+PPAGE_DIRECTORY_AMD64 pPML4;
/* FUNCTIONS **************************************************************/
BOOLEAN
MempAllocatePageTables()
{
+ ULONG KernelPages;
+ PVOID UserSharedData;
+
+ DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n");
+
+ /* Allocate a page for the PML4 */
+ pPML4 = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+ if (!pPML4)
+ {
+ DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n");
+ return FALSE;
+ }
+
+ // FIXME: Physical PTEs = FirmwareTemporary ?
+
+ /* Zero the PML4 */
+ RtlZeroMemory(pPML4, PAGE_SIZE);
+
+ /* The page tables are located at 0xfffff68000000000
+ * We create a recursive self mapping through all 4 levels at
+ * virtual address 0xfffff6fb7dbedf68 */
+ pPML4->Pde[VAtoPXI(PXE_BASE)].Valid = 1;
+ pPML4->Pde[VAtoPXI(PXE_BASE)].Write = 1;
+ pPML4->Pde[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(pPML4);
+
+ // FIXME: map PDE's for hals memory mapping
+
+ DPRINTM(DPRINT_WINDOWS,">>> leave MempAllocatePageTables\n");
return TRUE;
}
-VOID
-MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
+PPAGE_DIRECTORY_AMD64
+MempGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir, ULONG Index)
{
+ PPAGE_DIRECTORY_AMD64 pSubDir;
+ if (!pDir)
+ return NULL;
+
+ if (!pDir->Pde[Index].Valid)
+ {
+ pSubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderSpecialMemory);
+ if (!pSubDir)
+ return NULL;
+ RtlZeroMemory(pSubDir, PAGE_SIZE);
+ pDir->Pde[Index].PageFrameNumber = PtrToPfn(pSubDir);
+ pDir->Pde[Index].Valid = 1;
+ pDir->Pde[Index].Write = 1;
+ }
+ else
+ {
+ pSubDir = (PPAGE_DIRECTORY_AMD64)((ULONGLONG)(pDir->Pde[Index].PageFrameNumber) * PAGE_SIZE);
+ }
+ return pSubDir;
+}
+
+BOOLEAN
+MempMapSinglePage(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress)
+{
+ PPAGE_DIRECTORY_AMD64 pDir3, pDir2, pDir1;
+ ULONG Index;
+
+ pDir3 = MempGetOrCreatePageDir(pPML4, VAtoPXI(VirtualAddress));
+ pDir2 = MempGetOrCreatePageDir(pDir3, VAtoPPI(VirtualAddress));
+ pDir1 = MempGetOrCreatePageDir(pDir2, VAtoPDI(VirtualAddress));
+
+ if (!pDir1)
+ return FALSE;
+
+ Index = VAtoPTI(VirtualAddress);
+ if (pDir1->Pde[Index].Valid)
+ {
+ return FALSE;
+ }
+
+ pDir1->Pde[Index].Valid = 1;
+ pDir1->Pde[Index].Write = 1;
+ pDir1->Pde[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+
+ return TRUE;
+}
+
+ULONG
+MempMapRangeOfPages(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress, ULONG cPages)
+{
+ ULONG i;
+
+ for (i = 0; i < cPages; i++)
+ {
+ if (!FrLdrMapSinglePage(VirtualAddress, PhysicalAddress))
+ {
+ return i;
+ }
+ VirtualAddress += PAGE_SIZE;
+ PhysicalAddress += PAGE_SIZE;
+ }
+ return i;
}
BOOLEAN
MempSetupPaging(IN ULONG StartPage,
IN ULONG NumberOfPages)
{
+ DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld)\n", StartPage, NumberOfPages);
+
+ if (MempMapRangeOfPages(StartPage * PAGE_SIZE,
+ StartPage * PAGE_SIZE,
+ NumberOfPages) != NumberOfPages)
+ {
+ DPRINTM(DPRINT_WINDOWS,"Failed to map pages\n");
+ return FALSE;
+ }
return TRUE;
}
VOID
-MempDisablePages()
+MempUnmapPage(ULONG Page)
{
-
+ // DPRINTM(DPRINT_WINDOWS,">>> MempUnmapPage\n");
}
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type)
-{
-
-}
-
-#ifdef _M_IX86
VOID
WinLdrpMapApic()
{
+ BOOLEAN LocalAPIC;
+ LARGE_INTEGER MsrValue;
+ ULONG CpuInfo[4];
+ ULONG64 APICAddress;
+ DPRINTM(DPRINT_WINDOWS,">>> WinLdrpMapApic\n");
+
+ /* Check if we have a local APIC */
+ __cpuid((int*)CpuInfo, 1);
+ LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
+
+ /* If there is no APIC, just return */
+ if (!LocalAPIC)
+ {
+ DPRINTM(DPRINT_WINDOWS,"No APIC found.\n");
+ return;
+ }
+
+ /* Read the APIC Address */
+ MsrValue.QuadPart = __readmsr(0x1B);
+ APICAddress = (MsrValue.LowPart & 0xFFFFF000);
+
+ DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
+ APICAddress);
+
+ /* Map it */
+ MempMapSinglePage(APIC_BASE, APICAddress);
}
-#else
-VOID
-WinLdrpMapApic()
-{
- /* Implement it for another arch */
-}
-#endif
BOOLEAN
-WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG PcrBasePage,
- ULONG TssBasePage,
- PVOID GdtIdt)
+WinLdrMapSpecialPages(ULONG PcrBasePage)
{
-return 1;
+ /* Map the PCR page */
+ if (!MempMapSinglePage(PcrBasePage * PAGE_SIZE, KIP0PCRADDRESS))
+ {
+ DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage);
+ return FALSE;
+ }
+
+ /* Map KI_USER_SHARED_DATA */
+ if (!MempMapSinglePage((PcrBasePage+1) * PAGE_SIZE, KI_USER_SHARED_DATA))
+ {
+ DPRINTM(DPRINT_WINDOWS, "Could not map KI_USER_SHARED_DATA\n");
+ return FALSE;
+ }
+
+ /* Map the APIC page */
+ WinLdrpMapApic();
+
+ return TRUE;
}
-// Two special things this func does: it sorts descriptors,
-// and it merges free ones
VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+WinLdrSetupGdt(PVOID GdtBase, ULONG64 TssBase)
{
+ PKGDTENTRY64 Entry;
+ KDESCRIPTOR GdtDesc;
+
+ /* Setup KGDT_64_R0_CODE */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_CODE);
+ *(PULONG64)Entry = 0x00209b0000000000ULL;
+
+ /* Setup KGDT_64_R0_SS */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_SS);
+ *(PULONG64)Entry = 0x00cf93000000ffffULL;
+
+ /* Setup KGDT_64_DATA */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_64_DATA);
+ *(PULONG64)Entry = 0x00cff3000000ffffULL;
+
+ /* Setup KGDT_64_R3_CODE */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R3_CODE);
+ *(PULONG64)Entry = 0x0020fb0000000000ULL;
+
+ /* Setup KGDT_32_R3_TEB */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_32_R3_TEB);
+ *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
+
+ /* Setup TSS entry */
+ Entry = KiGetGdtEntry(GdtBase, KGDT_TSS);
+ KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
+
+ /* Setup GDT descriptor */
+ GdtDesc.Base = GdtBase;
+ GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
+
+ /* Set the new Gdt */
+ __lgdt(&GdtDesc.Limit);
+ DbgPrint("Gdtr.Base = %p, num = %ld\n", GdtDesc.Base, NUM_GDT);
}
VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
+WinLdrSetupIdt(PVOID IdtBase)
{
+ KDESCRIPTOR IdtDesc, OldIdt;
+
+ /* Get old IDT */
+ __sidt(&OldIdt);
+
+ /* Copy the old IDT */
+ RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
+
+ /* Setup the new IDT descriptor */
+ IdtDesc.Base = IdtBase;
+ IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
+
+ /* Set the new IDT */
+ __lidt(&IdtDesc.Limit);
+ DbgPrint("Idtr.Base = %p\n", IdtDesc.Base);
}
+VOID
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
+{
+ /* Disable Interrupts */
+ _disable();
+
+ /* Re-initalize EFLAGS */
+ __writeeflags(0);
+
+ /* Set the new PML4 */
+ __writecr3((ULONGLONG)pPML4);
+
+ // Enable paging by modifying CR0
+ __writecr0(__readcr0() | CR0_PG);
+
+ // Kernel expects the PCR to be zero-filled on startup
+ // FIXME: Why zero it here when we can zero it right after allocation?
+ RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
+
+ RtlZeroMemory(GdtIdt, PAGE_SIZE);
+
+ WinLdrSetupGdt(GdtIdt, Tss);
+
+ WinLdrSetupIdt(GdtIdt);
+
+}
+
+VOID
+MempDump()
+{
+}
+
diff --git a/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
index 313413e5451..6eb8b34224f 100644
--- a/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
+++ b/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
@@ -1,7 +1,7 @@
/*
* PROJECT: EFI Windows Loader
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: freeldr/winldr/wlmemory.c
+ * FILE: freeldr/winldr/i386/wlmemory.c
* PURPOSE: Memory related routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
@@ -22,52 +22,6 @@ extern ULONG LoaderPagesSpanned;
#define HYPER_SPACE_ENTRY 0x300
-PCHAR MemTypeDesc[] = {
- "ExceptionBlock ", // ?
- "SystemBlock ", // ?
- "Free ",
- "Bad ", // used
- "LoadedProgram ", // == Free
- "FirmwareTemporary ", // == Free
- "FirmwarePermanent ", // == Bad
- "OsloaderHeap ", // used
- "OsloaderStack ", // == Free
- "SystemCode ",
- "HalCode ",
- "BootDriver ", // not used
- "ConsoleInDriver ", // ?
- "ConsoleOutDriver ", // ?
- "StartupDpcStack ", // ?
- "StartupKernelStack", // ?
- "StartupPanicStack ", // ?
- "StartupPcrPage ", // ?
- "StartupPdrPage ", // ?
- "RegistryData ", // used
- "MemoryData ", // not used
- "NlsData ", // used
- "SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
- };
-
-VOID
-WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
-
-
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type);
-VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
-
-VOID
-WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
-
-VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-
// This is needed only for SetProcessorContext routine
#pragma pack(2)
typedef struct
@@ -87,10 +41,6 @@ PUCHAR KernelPageTablesBuffer;
ULONG PhysicalPageTables;
ULONG KernelPageTables;
-MEMORY_ALLOCATION_DESCRIPTOR *Mad;
-ULONG MadCount = 0;
-
-
/* FUNCTIONS **************************************************************/
BOOLEAN
@@ -253,133 +203,24 @@ MempSetupPaging(IN ULONG StartPage,
}
VOID
-MempDisablePages()
+MempUnmapPage(ULONG Page)
{
- ULONG i;
+ PHARDWARE_PTE KernelPT;
+ ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
- //
- // We need to delete kernel mapping from memory areas which are
- // marked as Special or Permanent memory (thus non-accessible)
- //
+ if (PDE[Entry].Valid)
+ {
+ KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
- for (i=0; i LoaderPagesSpanned)
- EndPage = LoaderPagesSpanned;
- }
-
- for (Page = StartPage; Page < EndPage; Page++)
- {
- PHARDWARE_PTE KernelPT;
- ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
-
- if (PDE[Entry].Valid)
- {
- KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-
- if (KernelPT)
- {
- KernelPT[Page & 0x3ff].PageFrameNumber = 0;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- }
- }
- }
- }
+ if (KernelPT)
+ {
+ KernelPT[Page & 0x3ff].PageFrameNumber = 0;
+ KernelPT[Page & 0x3ff].Valid = 0;
+ KernelPT[Page & 0x3ff].Write = 0;
+ }
+ }
}
-VOID
-MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type)
-{
- BOOLEAN Status;
-
- //
- // Check for some weird stuff at the top
- //
- if (BasePage + PageCount > 0xF0000)
- {
- //
- // Just skip this, without even adding to MAD list
- //
- return;
- }
-
- //
- // Set Base page, page count and type
- //
- Mad[MadCount].BasePage = BasePage;
- Mad[MadCount].PageCount = PageCount;
- Mad[MadCount].MemoryType = Type;
-
- //
- // Check if it's more than the allowed for OS loader
- // if yes - don't map the pages, just add as FirmwareTemporary
- //
- if (BasePage + PageCount > LoaderPagesSpanned)
- {
- if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
- Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
- Mad[MadCount].MemoryType != LoaderFree)
- {
- DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
- BasePage, PageCount, Mad[MadCount].MemoryType);
- Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
- }
-
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- return;
- }
-
- //
- // Add descriptor
- //
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- //
- // Map it (don't map low 1Mb because it was already contigiously
- // mapped in WinLdrTurnOnPaging)
- //
- if (BasePage >= 0x100)
- {
- Status = MempSetupPaging(BasePage, PageCount);
- if (!Status)
- {
- DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
- return;
- }
- }
-}
-
-#ifdef _M_IX86
VOID
WinLdrpMapApic()
{
@@ -410,149 +251,10 @@ WinLdrpMapApic()
HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
}
-#else
-VOID
-WinLdrpMapApic()
-{
- /* Implement it for another arch */
-}
-#endif
BOOLEAN
-WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG PcrBasePage,
- ULONG TssBasePage,
- PVOID GdtIdt)
+WinLdrMapSpecialPages(ULONG PcrBasePage)
{
- ULONG i, PagesCount, MemoryMapSizeInPages;
- ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
- PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
- ULONG NoEntries;
- PKTSS Tss;
- BOOLEAN Status;
-
- //
- // Creating a suitable memory map for the Windows can be tricky, so let's
- // give a few advices:
- // 1) One must not map the whole available memory pages to PDE!
- // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
- // thus occupying 4, 6 or 8 PDE entries for identical mapping,
- // the same quantity for KSEG0_BASE mapping, one more entry for
- // hyperspace and one more entry for HAL physical pages mapping.
- // 2) Memory descriptors must map *the whole* physical memory
- // showing any memory above 16/24/32 as FirmwareTemporary
- //
- // 3) Overall memory blocks count must not exceed 30 (?? why?)
- //
-
- //
- // During MmInitMachineDependent, the kernel zeroes PDE at the following address
- // 0xC0300000 - 0xC03007FC
- //
- // Then it finds the best place for non-paged pool:
- // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
- //
-
- // Before we start mapping pages, create a block of memory, which will contain
- // PDE and PTEs
- if (MempAllocatePageTables() == FALSE)
- return FALSE;
-
- // Allocate memory for memory allocation descriptors
- Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
-
- // Setup an entry for each descriptor
- MemoryMap = MmGetMemoryMap(&NoEntries);
- if (MemoryMap == NULL)
- {
- UiMessageBox("Can not retrieve the current memory map");
- return FALSE;
- }
-
- // Calculate parameters of the memory map
- MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
- MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
-
- DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
-
- // Always contigiously map low 1Mb of memory
- Status = MempSetupPaging(0, 0x100);
- if (!Status)
- {
- DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
- return FALSE;
- }
-
- // Construct a good memory map from what we've got,
- // but mark entries which the memory allocation bitmap takes
- // as free entries (this is done in order to have the ability
- // to place mem alloc bitmap outside lower 16Mb zone)
- PagesCount = 1;
- LastPageIndex = 0;
- LastPageType = MemoryMap[0].PageAllocated;
- for(i=1;i= MemoryMapStartPage &&
- i < (MemoryMapStartPage+MemoryMapSizeInPages))
- {
- // Exclude it if current page belongs to the memory map
- MemoryMap[i].PageAllocated = LoaderFree;
- }
-
- // Process entry
- if (MemoryMap[i].PageAllocated == LastPageType &&
- (i != NoEntries-1) )
- {
- PagesCount++;
- }
- else
- {
- // Add the resulting region
- MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
-
- // Reset our counter vars
- LastPageIndex = i;
- LastPageType = MemoryMap[i].PageAllocated;
- PagesCount = 1;
- }
- }
-
- // TEMP, DEBUG!
- // adding special reserved memory zones for vmware workstation
-#if 0
- {
- Mad[MadCount].BasePage = 0xfec00;
- Mad[MadCount].PageCount = 0x10;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfee00;
- Mad[MadCount].PageCount = 0x1;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfffe0;
- Mad[MadCount].PageCount = 0x20;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
- }
-#endif
-
- DPRINTM(DPRINT_WINDOWS, "MadCount: %d\n", MadCount);
-
- WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
-
- // Map our loader image, so we can continue running
- /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
- if (!Status)
- {
- UiMessageBox("Error during MempSetupPaging");
- return;
- }*/
//VideoDisplayString(L"Hello from VGA, going into the kernel\n");
DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
@@ -574,37 +276,21 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
//VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
//DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase);
- Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
+ return TRUE;
+}
- // Unmap what is not needed from kernel page table
- MempDisablePages();
- // Fill the memory descriptor list and
- //PrepareMemoryDescriptorList();
- DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
- List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
-
-#if DBG
- {
- ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
- int j;
-
- DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
-
- for (i=0; i<128; i++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
-
- for (j=0; j<8; j++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
- }
-
- DPRINTM(DPRINT_WINDOWS, "\n");
- }
- }
-#endif
+VOID
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
+{
+ GDTIDT GdtDesc, IdtDesc, OldIdt;
+ PKGDTENTRY pGdt;
+ PKIDTENTRY pIdt;
+ ULONG Ldt = 0;
+ //ULONG i;
+ DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
+ GdtIdt, Pcr, Tss);
// Enable paging
//BS->ExitBootServices(ImageHandle,MapKey);
@@ -621,93 +307,6 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
// Enable paging by modifying CR0
__writecr0(__readcr0() | CR0_PG);
- // Set processor context
- WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
-
- // Zero KI_USER_SHARED_DATA page
- memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
-
- return TRUE;
-}
-
-// Two special things this func does: it sorts descriptors,
-// and it merges free ones
-VOID
-WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
-{
- PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
- PLIST_ENTRY PreviousEntry, NextEntry;
- PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
-
- DPRINTM(DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
- NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
-
- /* Find a place where to insert the new descriptor to */
- PreviousEntry = ListHead;
- NextEntry = ListHead->Flink;
- while (NextEntry != ListHead)
- {
- NextDescriptor = CONTAINING_RECORD(NextEntry,
- MEMORY_ALLOCATION_DESCRIPTOR,
- ListEntry);
- if (NewDescriptor->BasePage < NextDescriptor->BasePage)
- break;
-
- PreviousEntry = NextEntry;
- PreviousDescriptor = NextDescriptor;
- NextEntry = NextEntry->Flink;
- }
-
- /* Don't forget about merging free areas */
- if (NewDescriptor->MemoryType != LoaderFree)
- {
- /* Just insert, nothing to merge */
- InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
- }
- else
- {
- /* Previous block also free? */
- if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
- ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
- NewDescriptor->BasePage))
- {
- /* Just enlarge previous descriptor's PageCount */
- PreviousDescriptor->PageCount += NewDescriptor->PageCount;
- NewDescriptor = PreviousDescriptor;
- }
- else
- {
- /* Nope, just insert */
- InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
- }
-
- /* Next block is free ?*/
- if ((NextEntry != ListHead) &&
- (NextDescriptor->MemoryType == LoaderFree) &&
- ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
- {
- /* Enlarge next descriptor's PageCount */
- NewDescriptor->PageCount += NextDescriptor->PageCount;
- RemoveEntryList(&NextDescriptor->ListEntry);
- }
- }
-
- return;
-}
-
-VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
-{
- GDTIDT GdtDesc, IdtDesc, OldIdt;
- PKGDTENTRY pGdt;
- PKIDTENTRY pIdt;
- ULONG Ldt = 0;
- //ULONG i;
-
- DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
- GdtIdt, Pcr, Tss);
-
// Kernel expects the PCR to be zero-filled on startup
// FIXME: Why zero it here when we can zero it right after allocation?
RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
@@ -937,3 +536,25 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
ret
*/
}
+
+VOID
+MempDump()
+{
+ ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
+ int j;
+
+ DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
+
+ for (i=0; i<128; i++)
+ {
+ DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
+
+ for (j=0; j<8; j++)
+ {
+ DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
+ }
+
+ DPRINTM(DPRINT_WINDOWS, "\n");
+ }
+}
+
diff --git a/reactos/boot/freeldr/freeldr/windows/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
new file mode 100644
index 00000000000..2ed849ad545
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
@@ -0,0 +1,432 @@
+/*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/wlmemory.c
+ * PURPOSE: Memory related routines
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+
+#include
+#include
+
+extern ULONG LoaderPagesSpanned;
+
+// This is needed because headers define wrong one for ReactOS
+#undef KIP0PCRADDRESS
+#define KIP0PCRADDRESS 0xffdff000
+
+PCHAR MemTypeDesc[] = {
+ "ExceptionBlock ", // ?
+ "SystemBlock ", // ?
+ "Free ",
+ "Bad ", // used
+ "LoadedProgram ", // == Free
+ "FirmwareTemporary ", // == Free
+ "FirmwarePermanent ", // == Bad
+ "OsloaderHeap ", // used
+ "OsloaderStack ", // == Free
+ "SystemCode ",
+ "HalCode ",
+ "BootDriver ", // not used
+ "ConsoleInDriver ", // ?
+ "ConsoleOutDriver ", // ?
+ "StartupDpcStack ", // ?
+ "StartupKernelStack", // ?
+ "StartupPanicStack ", // ?
+ "StartupPcrPage ", // ?
+ "StartupPdrPage ", // ?
+ "RegistryData ", // used
+ "MemoryData ", // not used
+ "NlsData ", // used
+ "SpecialMemory ", // == Bad
+ "BBTMemory " // == Bad
+ };
+
+VOID
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+VOID
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG BasePage,
+ ULONG PageCount,
+ ULONG Type);
+VOID
+WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
+
+VOID
+WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
+
+VOID
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
+
+BOOLEAN
+MempAllocatePageTables();
+
+BOOLEAN
+MempSetupPaging(IN ULONG StartPage,
+ IN ULONG NumberOfPages);
+
+BOOLEAN
+WinLdrMapSpecialPages(ULONG PcrBasePage);
+
+VOID
+MempUnmapPage(ULONG Page);
+
+VOID
+MempDump();
+
+/* GLOBALS ***************************************************************/
+
+MEMORY_ALLOCATION_DESCRIPTOR *Mad;
+ULONG MadCount = 0;
+
+/* FUNCTIONS **************************************************************/
+
+VOID
+MempDisablePages()
+{
+ ULONG i;
+
+ //
+ // We need to delete kernel mapping from memory areas which are
+ // marked as Special or Permanent memory (thus non-accessible)
+ //
+
+ for (i=0; i LoaderPagesSpanned)
+ EndPage = LoaderPagesSpanned;
+ }
+
+ for (Page = StartPage; Page < EndPage; Page++)
+ {
+ MempUnmapPage(Page);
+ }
+ }
+ }
+}
+
+VOID
+MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG BasePage,
+ ULONG PageCount,
+ ULONG Type)
+{
+ BOOLEAN Status;
+
+ //
+ // Check for some weird stuff at the top
+ //
+ if (BasePage + PageCount > 0xF0000)
+ {
+ //
+ // Just skip this, without even adding to MAD list
+ //
+ return;
+ }
+
+ //
+ // Set Base page, page count and type
+ //
+ Mad[MadCount].BasePage = BasePage;
+ Mad[MadCount].PageCount = PageCount;
+ Mad[MadCount].MemoryType = Type;
+
+ //
+ // Check if it's more than the allowed for OS loader
+ // if yes - don't map the pages, just add as FirmwareTemporary
+ //
+ if (BasePage + PageCount > LoaderPagesSpanned)
+ {
+ if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
+ Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
+ Mad[MadCount].MemoryType != LoaderFree)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
+ BasePage, PageCount, Mad[MadCount].MemoryType);
+ Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
+ }
+
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ return;
+ }
+
+ //
+ // Add descriptor
+ //
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ //
+ // Map it (don't map low 1Mb because it was already contigiously
+ // mapped in WinLdrTurnOnPaging)
+ //
+ if (BasePage >= 0x100)
+ {
+ Status = MempSetupPaging(BasePage, PageCount);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
+ return;
+ }
+ }
+}
+
+BOOLEAN
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG PcrBasePage,
+ ULONG TssBasePage,
+ PVOID GdtIdt)
+{
+ ULONG i, PagesCount, MemoryMapSizeInPages;
+ ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
+ PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
+ ULONG NoEntries;
+ PKTSS Tss;
+ BOOLEAN Status;
+
+ //
+ // Creating a suitable memory map for the Windows can be tricky, so let's
+ // give a few advices:
+ // 1) One must not map the whole available memory pages to PDE!
+ // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
+ // thus occupying 4, 6 or 8 PDE entries for identical mapping,
+ // the same quantity for KSEG0_BASE mapping, one more entry for
+ // hyperspace and one more entry for HAL physical pages mapping.
+ // 2) Memory descriptors must map *the whole* physical memory
+ // showing any memory above 16/24/32 as FirmwareTemporary
+ //
+ // 3) Overall memory blocks count must not exceed 30 (?? why?)
+ //
+
+ //
+ // During MmInitMachineDependent, the kernel zeroes PDE at the following address
+ // 0xC0300000 - 0xC03007FC
+ //
+ // Then it finds the best place for non-paged pool:
+ // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
+ //
+
+ // Before we start mapping pages, create a block of memory, which will contain
+ // PDE and PTEs
+ if (MempAllocatePageTables() == FALSE)
+ return FALSE;
+
+ // Allocate memory for memory allocation descriptors
+ Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
+
+ // Setup an entry for each descriptor
+ MemoryMap = MmGetMemoryMap(&NoEntries);
+ if (MemoryMap == NULL)
+ {
+ UiMessageBox("Can not retrieve the current memory map");
+ return FALSE;
+ }
+
+ // Calculate parameters of the memory map
+ MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
+ MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
+
+ DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
+
+ // Always contigiously map low 1Mb of memory
+ Status = MempSetupPaging(0, 0x100);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
+ return FALSE;
+ }
+
+ // Construct a good memory map from what we've got,
+ // but mark entries which the memory allocation bitmap takes
+ // as free entries (this is done in order to have the ability
+ // to place mem alloc bitmap outside lower 16Mb zone)
+ PagesCount = 1;
+ LastPageIndex = 0;
+ LastPageType = MemoryMap[0].PageAllocated;
+ for(i=1;i= MemoryMapStartPage &&
+ i < (MemoryMapStartPage+MemoryMapSizeInPages))
+ {
+ // Exclude it if current page belongs to the memory map
+ MemoryMap[i].PageAllocated = LoaderFree;
+ }
+
+ // Process entry
+ if (MemoryMap[i].PageAllocated == LastPageType &&
+ (i != NoEntries-1) )
+ {
+ PagesCount++;
+ }
+ else
+ {
+ // Add the resulting region
+ MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
+
+ // Reset our counter vars
+ LastPageIndex = i;
+ LastPageType = MemoryMap[i].PageAllocated;
+ PagesCount = 1;
+ }
+ }
+
+ // TEMP, DEBUG!
+ // adding special reserved memory zones for vmware workstation
+#if 0
+ {
+ Mad[MadCount].BasePage = 0xfec00;
+ Mad[MadCount].PageCount = 0x10;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ Mad[MadCount].BasePage = 0xfee00;
+ Mad[MadCount].PageCount = 0x1;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ Mad[MadCount].BasePage = 0xfffe0;
+ Mad[MadCount].PageCount = 0x20;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+ }
+#endif
+
+ DPRINTM(DPRINT_WINDOWS, "MadCount: %d\n", MadCount);
+
+ WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
+
+ // Map our loader image, so we can continue running
+ /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
+ if (!Status)
+ {
+ UiMessageBox("Error during MempSetupPaging");
+ return;
+ }*/
+
+ /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
+ WinLdrMapSpecialPages(PcrBasePage);
+
+ Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
+
+ // Unmap what is not needed from kernel page table
+ MempDisablePages();
+
+ // Fill the memory descriptor list and
+ //PrepareMemoryDescriptorList();
+ DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
+ List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
+
+#if DBG
+ MempDump();
+#endif
+
+ // Set processor context
+ WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
+
+ // Zero KI_USER_SHARED_DATA page
+ memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
+
+ return TRUE;
+}
+
+// Two special things this func does: it sorts descriptors,
+// and it merges free ones
+VOID
+WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+{
+ PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
+ PLIST_ENTRY PreviousEntry, NextEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
+
+ DPRINTM(DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
+ NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
+
+ /* Find a place where to insert the new descriptor to */
+ PreviousEntry = ListHead;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ NextDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+ if (NewDescriptor->BasePage < NextDescriptor->BasePage)
+ break;
+
+ PreviousEntry = NextEntry;
+ PreviousDescriptor = NextDescriptor;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Don't forget about merging free areas */
+ if (NewDescriptor->MemoryType != LoaderFree)
+ {
+ /* Just insert, nothing to merge */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
+ else
+ {
+ /* Previous block also free? */
+ if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
+ ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
+ NewDescriptor->BasePage))
+ {
+ /* Just enlarge previous descriptor's PageCount */
+ PreviousDescriptor->PageCount += NewDescriptor->PageCount;
+ NewDescriptor = PreviousDescriptor;
+ }
+ else
+ {
+ /* Nope, just insert */
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
+ }
+
+ /* Next block is free ?*/
+ if ((NextEntry != ListHead) &&
+ (NextDescriptor->MemoryType == LoaderFree) &&
+ ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
+ {
+ /* Enlarge next descriptor's PageCount */
+ NewDescriptor->PageCount += NextDescriptor->PageCount;
+ RemoveEntryList(&NextDescriptor->ListEntry);
+ }
+ }
+
+ return;
+}
+