[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / mm / meminit.c
index b9e8877..dd8c0d6 100644 (file)
 
 DBG_DEFAULT_CHANNEL(MEMORY);
 
+PVOID    PageLookupTableAddress = NULL;
+PFN_NUMBER TotalPagesInLookupTable = 0;
+PFN_NUMBER FreePagesInLookupTable = 0;
+PFN_NUMBER LastFreePageHint = 0;
+PFN_NUMBER MmLowestPhysicalPage = 0xFFFFFFFF;
+PFN_NUMBER MmHighestPhysicalPage = 0;
+
+PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap;
+ULONG BiosMemoryMapEntryCount;
+SIZE_T FrLdrImageSize;
+
 #if DBG
 typedef struct
 {
@@ -50,20 +61,42 @@ FREELDR_MEMORY_TYPE MemoryTypeArray[] =
     { LoaderReserve, "Reserve" },
 };
 ULONG MemoryTypeCount = sizeof(MemoryTypeArray) / sizeof(MemoryTypeArray[0]);
-#endif
 
-PVOID  PageLookupTableAddress = NULL;
-PFN_NUMBER TotalPagesInLookupTable = 0;
-PFN_NUMBER FreePagesInLookupTable = 0;
-PFN_NUMBER LastFreePageHint = 0;
-PFN_NUMBER MmLowestPhysicalPage = 0xFFFFFFFF;
-PFN_NUMBER MmHighestPhysicalPage = 0;
+PCSTR
+MmGetSystemMemoryMapTypeString(
+    TYPE_OF_MEMORY Type)
+{
+    ULONG Index;
 
-PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap;
-ULONG BiosMemoryMapEntryCount;
+    for (Index = 1; Index < MemoryTypeCount; Index++)
+    {
+        if (MemoryTypeArray[Index].Type == Type)
+        {
+            return MemoryTypeArray[Index].TypeString;
+        }
+    }
+
+    return MemoryTypeArray[0].TypeString;
+}
 
-extern ULONG_PTR       MmHeapPointer;
-extern ULONG_PTR       MmHeapStart;
+VOID
+DbgDumpMemoryMap(
+    PFREELDR_MEMORY_DESCRIPTOR List)
+{
+    ULONG i;
+
+    DbgPrint("Dumping Memory map:\n");
+    for (i = 0; List[i].PageCount != 0; i++)
+    {
+        DbgPrint("%02d %08x - %08x: %s\n",
+                 i,
+                 List[i].BasePage * PAGE_SIZE,
+                 (List[i].BasePage + List[i].PageCount) * PAGE_SIZE,
+                 MmGetSystemMemoryMapTypeString(List[i].MemoryType));
+    }
+    DbgPrint("\n");
+}
+#endif
 
 ULONG
 AddMemoryDescriptor(
@@ -73,78 +106,117 @@ AddMemoryDescriptor(
     IN PFN_NUMBER PageCount,
     IN TYPE_OF_MEMORY MemoryType)
 {
-    ULONG i, c;
-    PFN_NUMBER NextBase;
-    TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n",
-          BasePage, BasePage + PageCount, PageCount);
+    ULONG Index, DescriptCount;
+    PFN_NUMBER EndPage;
+    TRACE("AddMemoryDescriptor(0x%Ix, 0x%Ix, %u)\n",
+          BasePage, PageCount, MemoryType);
 
-    /* Scan through all existing descriptors */
-    for (i = 0, c = 0; (c < MaxCount) && (List[c].PageCount != 0); c++)
+    EndPage = BasePage + PageCount;
+
+    /* Skip over all descriptor below the new range */
+    Index = 0;
+    while ((List[Index].PageCount != 0) &&
+           ((List[Index].BasePage + List[Index].PageCount) <= BasePage))
     {
-        /* Count entries completely below the new range */
-        if (List[i].BasePage + List[i].PageCount <= BasePage) i++;
+        Index++;
     }
 
-    /* Check if the list is full */
-    if (c >= MaxCount) return c;
-
-    /* Is there an existing descriptor starting before the new range */
-    while ((i < c) && (List[i].BasePage <= BasePage))
+    /* Count the descriptors */
+    DescriptCount = Index;
+    while (List[DescriptCount].PageCount != 0)
     {
-        /* The end of the existing one is the minimum for the new range */
-        NextBase = List[i].BasePage + List[i].PageCount;
-
-        /* Bail out, if everything is trimmed away */
-        if ((BasePage + PageCount) <= NextBase) return c;
-
-        /* Trim the naew range at the lower end */
-        PageCount -= (NextBase - BasePage);
-        BasePage = NextBase;
-
-        /* Go to the next entry and repeat */
-        i++;
+        DescriptCount++;
     }
 
-    ASSERT(PageCount > 0);
-
-    /* Are there still entries above? */
-    if (i < c)
+    /* Check if the existing range conflicts with the new range */
+    while ((List[Index].PageCount != 0) &&
+           (List[Index].BasePage < EndPage))
     {
-        /* Shift the following entries one up */
-        RtlMoveMemory(&List[i+1], &List[i], (c - i) * sizeof(List[0]));
-
-        /* Insert the new range */
-        List[i].BasePage = BasePage;
-        List[i].PageCount = min(PageCount, List[i+1].BasePage - BasePage);
-        List[i].MemoryType = MemoryType;
-        c++;
-
-        TRACE("Inserting at i=%ld: (0x%lx:0x%lx)\n",
-              i, List[i].BasePage, List[i].PageCount);
-
-        /* Check if the range was trimmed */
-        if (PageCount > List[i].PageCount)
+        TRACE("AddMemoryDescriptor conflict @%lu: new=[%lx:%lx], existing=[%lx,%lx]\n",
+              Index, BasePage, PageCount, List[Index].BasePage, List[Index].PageCount);
+
+        /*
+         * We have 4 overlapping cases:
+         *
+         * Case              (a)       (b)       (c)       (d)
+         * Existing range  |---|     |-----|    |---|      |---|
+         * New range         |---|    |---|    |-----|   |---|
+         *
+         */
+
+        /* Check if the existing range starts before the new range (a)/(b) */
+        if (List[Index].BasePage < BasePage)
+        {
+            /* Check if the existing range extends beyond the new range (b) */
+            if (List[Index].BasePage + List[Index].PageCount > EndPage)
+            {
+                /* Split the descriptor */
+                RtlMoveMemory(&List[Index + 1],
+                              &List[Index],
+                              (DescriptCount - Index) * sizeof(List[0]));
+                List[Index + 1].BasePage = EndPage;
+                List[Index + 1].PageCount = List[Index].BasePage +
+                                            List[Index].PageCount -
+                                            List[Index + 1].BasePage;
+                List[Index].PageCount = BasePage - List[Index].BasePage;
+                Index++;
+                DescriptCount++;
+                break;
+            }
+            else
+            {
+                /* Crop the existing range and continue with the next range */
+                List[Index].PageCount = BasePage - List[Index].BasePage;
+                Index++;
+            }
+        }
+        /* Check if the existing range is fully covered by the new range (c) */
+        else if ((List[Index].BasePage + List[Index].PageCount) <=
+                 EndPage)
+        {
+            /* Delete this descriptor */
+            RtlMoveMemory(&List[Index],
+                          &List[Index + 1],
+                          (DescriptCount - Index) * sizeof(List[0]));
+            DescriptCount--;
+        }
+        /* Otherwise the existing range ends after the new range (d) */
+        else
         {
-            /* Recursively process the trimmed part */
-            c = AddMemoryDescriptor(List,
-                                    MaxCount,
-                                    BasePage + List[i].PageCount,
-                                    PageCount - List[i].PageCount,
-                                    MemoryType);
+            /* Crop the existing range at the start and bail out */
+            List[Index].PageCount -= EndPage - List[Index].BasePage;
+            List[Index].BasePage = EndPage;
+            break;
         }
     }
-    else
+
+    /* Make sure we can still add a new descriptor */
+    if (DescriptCount >= MaxCount)
     {
-        /* We can simply add the range here */
-        TRACE("Adding i=%ld: (0x%lx:0x%lx)\n", i, BasePage, PageCount);
-        List[i].BasePage = BasePage;
-        List[i].PageCount = PageCount;
-        List[i].MemoryType = MemoryType;
-        c++;
+        FrLdrBugCheckWithMessage(
+            MEMORY_INIT_FAILURE,
+            __FILE__,
+            __LINE__,
+            "Ran out of static memory descriptors!");
     }
 
-    /* Return the new count */
-    return c;
+    /* Insert the new descriptor */
+    if (Index < DescriptCount)
+    {
+        RtlMoveMemory(&List[Index + 1],
+                      &List[Index],
+                      (DescriptCount - Index) * sizeof(List[0]));
+    }
+
+    List[Index].BasePage = BasePage;
+    List[Index].PageCount = PageCount;
+    List[Index].MemoryType = MemoryType;
+    DescriptCount++;
+
+#if 0 // only enable on demand!
+    DbgDumpMemoryMap(List);
+#endif
+    return DescriptCount;
 }
 
 const FREELDR_MEMORY_DESCRIPTOR*
@@ -162,8 +234,8 @@ ArcGetMemoryDescriptor(const FREELDR_MEMORY_DESCRIPTOR* Current)
     }
 }
 
-
-BOOLEAN
+static
+VOID
 MmCheckFreeldrImageFile()
 {
     PIMAGE_NT_HEADERS NtHeaders;
@@ -174,8 +246,12 @@ MmCheckFreeldrImageFile()
     NtHeaders = RtlImageNtHeader(&__ImageBase);
     if (!NtHeaders)
     {
-        ERR("Coult not get NtHeaders!\n");
-        return FALSE;
+        ERR("Could not get NtHeaders!\n");
+        FrLdrBugCheckWithMessage(
+            FREELDR_IMAGE_CORRUPTION,
+            __FILE__,
+            __LINE__,
+            "Could not get NtHeaders!\n");
     }
 
     /* Check the file header */
@@ -184,9 +260,24 @@ MmCheckFreeldrImageFile()
         (FileHeader->NumberOfSections != FREELDR_SECTION_COUNT) ||
         (FileHeader->PointerToSymbolTable != 0) ||
         (FileHeader->NumberOfSymbols != 0) ||
-        (FileHeader->SizeOfOptionalHeader != 0xE0))
+        (FileHeader->SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)))
     {
-        return FALSE;
+        ERR("FreeLdr FileHeader is invalid.\n");
+        FrLdrBugCheckWithMessage(
+            FREELDR_IMAGE_CORRUPTION,
+            __FILE__,
+            __LINE__,
+            "FreeLdr FileHeader is invalid.\n"
+            "Machine == 0x%lx, expected 0x%lx\n"
+            "NumberOfSections == 0x%lx, expected 0x%lx\n"
+            "PointerToSymbolTable == 0x%lx, expected 0\n"
+            "NumberOfSymbols == 0x%lx, expected 0\n"
+            "SizeOfOptionalHeader == 0x%lx, expected 0x%lx\n",
+            FileHeader->Machine, IMAGE_FILE_MACHINE_NATIVE,
+            FileHeader->NumberOfSections, FREELDR_SECTION_COUNT,
+            FileHeader->PointerToSymbolTable,
+            FileHeader->NumberOfSymbols,
+            FileHeader->SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER));
     }
 
     /* Check the optional header */
@@ -197,90 +288,87 @@ MmCheckFreeldrImageFile()
         (OptionalHeader->SizeOfImage > MAX_FREELDR_PE_SIZE) ||
         (OptionalHeader->SectionAlignment != OptionalHeader->FileAlignment))
     {
-        return FALSE;
+        ERR("FreeLdr OptionalHeader is invalid.\n");
+        FrLdrBugCheckWithMessage(
+            FREELDR_IMAGE_CORRUPTION,
+            __FILE__,
+            __LINE__,
+            "FreeLdr OptionalHeader is invalid.\n"
+            "Magic == 0x%lx, expected 0x%lx\n"
+            "Subsystem == 0x%lx, expected 1 (native)\n"
+            "ImageBase == 0x%lx, expected 0x%lx\n"
+            "SizeOfImage == 0x%lx, maximum 0x%lx\n"
+            "SectionAlignment 0x%lx doesn't match FileAlignment 0x%lx\n",
+            OptionalHeader->Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC,
+            OptionalHeader->Subsystem,
+            OptionalHeader->ImageBase, FREELDR_PE_BASE,
+            OptionalHeader->SizeOfImage, MAX_FREELDR_PE_SIZE,
+            OptionalHeader->SectionAlignment, OptionalHeader->FileAlignment);
     }
 
-    return TRUE;
+    /* Calculate the full image size */
+    FrLdrImageSize = (ULONG_PTR)&__ImageBase + OptionalHeader->SizeOfImage - FREELDR_BASE;
 }
 
 BOOLEAN MmInitializeMemoryManager(VOID)
 {
 #if DBG
-       const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
+    const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
 #endif
 
-       TRACE("Initializing Memory Manager.\n");
+    TRACE("Initializing Memory Manager.\n");
 
-       /* Check the freeldr binary */
-       if (!MmCheckFreeldrImageFile())
-       {
-               FrLdrBugCheck(FREELDR_IMAGE_CORRUPTION);
-       }
+    /* Check the freeldr binary */
+    MmCheckFreeldrImageFile();
 
     BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount);
 
 #if DBG
-       // Dump the system memory map
-       TRACE("System Memory Map (Base Address, Length, Type):\n");
-       while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
-       {
-               TRACE("%x\t %x\t %s\n",
-                       MemoryDescriptor->BasePage * MM_PAGE_SIZE,
-                       MemoryDescriptor->PageCount * MM_PAGE_SIZE,
-                       MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType));
-       }
+    // Dump the system memory map
+    TRACE("System Memory Map (Base Address, Length, Type):\n");
+    while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
+    {
+        TRACE("%x\t %x\t %s\n",
+            MemoryDescriptor->BasePage * MM_PAGE_SIZE,
+            MemoryDescriptor->PageCount * MM_PAGE_SIZE,
+            MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType));
+    }
 #endif
 
-       // Find address for the page lookup table
-       TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles();
-       PageLookupTableAddress = MmFindLocationForPageLookupTable(TotalPagesInLookupTable);
-       LastFreePageHint = MmHighestPhysicalPage;
+    // Find address for the page lookup table
+    TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles();
+    PageLookupTableAddress = MmFindLocationForPageLookupTable(TotalPagesInLookupTable);
+    LastFreePageHint = MmHighestPhysicalPage;
 
-       if (PageLookupTableAddress == 0)
-       {
-               // If we get here then we probably couldn't
-               // find a contiguous chunk of memory big
-               // enough to hold the page lookup table
-               printf("Error initializing memory manager!\n");
-               return FALSE;
-       }
+    if (PageLookupTableAddress == 0)
+    {
+        // If we get here then we probably couldn't
+        // find a contiguous chunk of memory big
+        // enough to hold the page lookup table
+        printf("Error initializing memory manager!\n");
+        return FALSE;
+    }
 
-       // Initialize the page lookup table
-       MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
+    // Initialize the page lookup table
+    MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
 
-       MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable);
+    MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable);
 
-       FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress,
+    FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress,
                                                         TotalPagesInLookupTable);
 
-       MmInitializeHeap(PageLookupTableAddress);
+    MmInitializeHeap(PageLookupTableAddress);
 
-       TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable);
+    TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable);
 
 
-       return TRUE;
+    return TRUE;
 }
 
-#if DBG
-PCSTR MmGetSystemMemoryMapTypeString(TYPE_OF_MEMORY Type)
-{
-       ULONG           Index;
-
-       for (Index=1; Index<MemoryTypeCount; Index++)
-       {
-               if (MemoryTypeArray[Index].Type == Type)
-               {
-                       return MemoryTypeArray[Index].TypeString;
-               }
-       }
-
-       return MemoryTypeArray[0].TypeString;
-}
-#endif
 
 PFN_NUMBER MmGetPageNumberFromAddress(PVOID Address)
 {
-       return ((ULONG_PTR)Address) / MM_PAGE_SIZE;
+    return ((ULONG_PTR)Address) / MM_PAGE_SIZE;
 }
 
 PFN_NUMBER MmGetAddressablePageCountIncludingHoles(VOID)
@@ -407,9 +495,9 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount)
 
 VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER StartPage, PFN_NUMBER PageCount, TYPE_OF_MEMORY PageAllocated)
 {
-       PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER Index;
-       TRACE("MmMarkPagesInLookupTable()\n");
+    PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER Index;
+    TRACE("MmMarkPagesInLookupTable()\n");
 
     /* Validate the range */
     if ((StartPage < MmLowestPhysicalPage) ||
@@ -421,186 +509,186 @@ VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER StartPage, PFN_N
     }
 
     StartPage -= MmLowestPhysicalPage;
-       for (Index=StartPage; Index<(StartPage+PageCount); Index++)
-       {
+    for (Index=StartPage; Index<(StartPage+PageCount); Index++)
+    {
 #if 0
-               if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
-               {
-                       TRACE("Index = 0x%x StartPage = 0x%x PageCount = 0x%x\n", Index, StartPage, PageCount);
-               }
+        if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
+        {
+            TRACE("Index = 0x%x StartPage = 0x%x PageCount = 0x%x\n", Index, StartPage, PageCount);
+        }
 #endif
-               RealPageLookupTable[Index].PageAllocated = PageAllocated;
-               RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0;
-       }
-       TRACE("MmMarkPagesInLookupTable() Done\n");
+        RealPageLookupTable[Index].PageAllocated = PageAllocated;
+        RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0;
+    }
+    TRACE("MmMarkPagesInLookupTable() Done\n");
 }
 
 VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER StartPage, PFN_NUMBER PageCount, TYPE_OF_MEMORY MemoryType)
 {
-       PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER                                      Index;
+    PPAGE_LOOKUP_TABLE_ITEM        RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER                    Index;
 
     StartPage -= MmLowestPhysicalPage;
-       for (Index=StartPage; Index<(StartPage+PageCount); Index++)
-       {
-               RealPageLookupTable[Index].PageAllocated = MemoryType;
-               RealPageLookupTable[Index].PageAllocationLength = (Index == StartPage) ? PageCount : 0;
-       }
+    for (Index=StartPage; Index<(StartPage+PageCount); Index++)
+    {
+        RealPageLookupTable[Index].PageAllocated = MemoryType;
+        RealPageLookupTable[Index].PageAllocationLength = (Index == StartPage) ? PageCount : 0;
+    }
 }
 
 PFN_NUMBER MmCountFreePagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount)
 {
-       PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER                                                      Index;
-       PFN_NUMBER                                                      FreePageCount;
-
-       FreePageCount = 0;
-       for (Index=0; Index<TotalPageCount; Index++)
-       {
-               if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
-               {
-                       FreePageCount++;
-               }
-       }
-
-       return FreePageCount;
+    PPAGE_LOOKUP_TABLE_ITEM        RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER                            Index;
+    PFN_NUMBER                            FreePageCount;
+
+    FreePageCount = 0;
+    for (Index=0; Index<TotalPageCount; Index++)
+    {
+        if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
+        {
+            FreePageCount++;
+        }
+    }
+
+    return FreePageCount;
 }
 
 PFN_NUMBER MmFindAvailablePages(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PFN_NUMBER PagesNeeded, BOOLEAN FromEnd)
 {
-       PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER AvailablePagesSoFar;
-       PFN_NUMBER Index;
-
-       if (LastFreePageHint > TotalPageCount)
-       {
-               LastFreePageHint = TotalPageCount;
-       }
-
-       AvailablePagesSoFar = 0;
-       if (FromEnd)
-       {
-               /* Allocate "high" (from end) pages */
-               for (Index=LastFreePageHint-1; Index>0; Index--)
-               {
-                       if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
-                       {
-                               AvailablePagesSoFar = 0;
-                               continue;
-                       }
-                       else
-                       {
-                               AvailablePagesSoFar++;
-                       }
-
-                       if (AvailablePagesSoFar >= PagesNeeded)
-                       {
-                               return Index + MmLowestPhysicalPage;
-                       }
-               }
-       }
-       else
-       {
-               TRACE("Alloc low memory, LastFreePageHint 0x%x, TPC 0x%x\n", LastFreePageHint, TotalPageCount);
-               /* Allocate "low" pages */
-               for (Index=1; Index < LastFreePageHint; Index++)
-               {
-                       if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
-                       {
-                               AvailablePagesSoFar = 0;
-                               continue;
-                       }
-                       else
-                       {
-                               AvailablePagesSoFar++;
-                       }
-
-                       if (AvailablePagesSoFar >= PagesNeeded)
-                       {
-                               return Index - AvailablePagesSoFar + 1 + MmLowestPhysicalPage;
-                       }
-               }
-       }
-
-       return 0;
+    PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER AvailablePagesSoFar;
+    PFN_NUMBER Index;
+
+    if (LastFreePageHint > TotalPageCount)
+    {
+        LastFreePageHint = TotalPageCount;
+    }
+
+    AvailablePagesSoFar = 0;
+    if (FromEnd)
+    {
+        /* Allocate "high" (from end) pages */
+        for (Index=LastFreePageHint-1; Index>0; Index--)
+        {
+            if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+            {
+                AvailablePagesSoFar = 0;
+                continue;
+            }
+            else
+            {
+                AvailablePagesSoFar++;
+            }
+
+            if (AvailablePagesSoFar >= PagesNeeded)
+            {
+                return Index + MmLowestPhysicalPage;
+            }
+        }
+    }
+    else
+    {
+        TRACE("Alloc low memory, LastFreePageHint 0x%x, TPC 0x%x\n", LastFreePageHint, TotalPageCount);
+        /* Allocate "low" pages */
+        for (Index=1; Index < LastFreePageHint; Index++)
+        {
+            if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+            {
+                AvailablePagesSoFar = 0;
+                continue;
+            }
+            else
+            {
+                AvailablePagesSoFar++;
+            }
+
+            if (AvailablePagesSoFar >= PagesNeeded)
+            {
+                return Index - AvailablePagesSoFar + 1 + MmLowestPhysicalPage;
+            }
+        }
+    }
+
+    return 0;
 }
 
 PFN_NUMBER MmFindAvailablePagesBeforePage(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PFN_NUMBER PagesNeeded, PFN_NUMBER LastPage)
 {
-       PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER                                      AvailablePagesSoFar;
-       PFN_NUMBER                                      Index;
-
-       if (LastPage > TotalPageCount)
-       {
-               return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE);
-       }
-
-       AvailablePagesSoFar = 0;
-       for (Index=LastPage-1; Index>0; Index--)
-       {
-               if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
-               {
-                       AvailablePagesSoFar = 0;
-                       continue;
-               }
-               else
-               {
-                       AvailablePagesSoFar++;
-               }
-
-               if (AvailablePagesSoFar >= PagesNeeded)
-               {
-                       return Index + MmLowestPhysicalPage;
-               }
-       }
-
-       return 0;
+    PPAGE_LOOKUP_TABLE_ITEM        RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER                    AvailablePagesSoFar;
+    PFN_NUMBER                    Index;
+
+    if (LastPage > TotalPageCount)
+    {
+        return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE);
+    }
+
+    AvailablePagesSoFar = 0;
+    for (Index=LastPage-1; Index>0; Index--)
+    {
+        if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+        {
+            AvailablePagesSoFar = 0;
+            continue;
+        }
+        else
+        {
+            AvailablePagesSoFar++;
+        }
+
+        if (AvailablePagesSoFar >= PagesNeeded)
+        {
+            return Index + MmLowestPhysicalPage;
+        }
+    }
+
+    return 0;
 }
 
 VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, PFN_NUMBER TotalPageCount)
 {
-       PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER                                                      Index;
-
-       for (Index=TotalPageCount-1; Index>0; Index--)
-       {
-               if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
-               {
-                       LastFreePageHint = Index + 1 + MmLowestPhysicalPage;
-                       break;
-               }
-       }
+    PPAGE_LOOKUP_TABLE_ITEM        RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER                            Index;
+
+    for (Index=TotalPageCount-1; Index>0; Index--)
+    {
+        if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
+        {
+            LastFreePageHint = Index + 1 + MmLowestPhysicalPage;
+            break;
+        }
+    }
 }
 
 BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PVOID PageAddress, PFN_NUMBER PageCount)
 {
-       PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
-       PFN_NUMBER                                                      StartPage;
-       PFN_NUMBER                                                      Index;
+    PPAGE_LOOKUP_TABLE_ITEM        RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+    PFN_NUMBER                            StartPage;
+    PFN_NUMBER                            Index;
 
-       StartPage = MmGetPageNumberFromAddress(PageAddress);
+    StartPage = MmGetPageNumberFromAddress(PageAddress);
 
-       if (StartPage < MmLowestPhysicalPage) return FALSE;
+    if (StartPage < MmLowestPhysicalPage) return FALSE;
 
     StartPage -= MmLowestPhysicalPage;
 
-       // Make sure they aren't trying to go past the
-       // end of availabe memory
-       if ((StartPage + PageCount) > TotalPageCount)
-       {
-               return FALSE;
-       }
-
-       for (Index = StartPage; Index < (StartPage + PageCount); Index++)
-       {
-               // If this page is allocated then there obviously isn't
-               // memory availabe so return FALSE
-               if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
-               {
-                       return FALSE;
-               }
-       }
-
-       return TRUE;
+    // Make sure they aren't trying to go past the
+    // end of availabe memory
+    if ((StartPage + PageCount) > TotalPageCount)
+    {
+        return FALSE;
+    }
+
+    for (Index = StartPage; Index < (StartPage + PageCount); Index++)
+    {
+        // If this page is allocated then there obviously isn't
+        // memory availabe so return FALSE
+        if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+        {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
 }