[FREELDR] Fix calculation of page lookup table (#761)
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 18 Aug 2018 10:16:33 +0000 (12:16 +0200)
committerGitHub <noreply@github.com>
Sat, 18 Aug 2018 10:16:33 +0000 (12:16 +0200)
On x64 we only map 1GB of pages, so adjust MM_MAX_PAGE accordingly and also respect that value when searching for the best location of the page lookup table.
CORE-11048 #resolve

boot/freeldr/freeldr/include/mm.h
boot/freeldr/freeldr/lib/mm/meminit.c

index d29fe60..adc13d0 100644 (file)
@@ -58,8 +58,7 @@ typedef struct _FREELDR_MEMORY_DESCRIPTOR
 #define MM_PAGE_SIZE    4096
 #define MM_PAGE_MASK    0xFFF
 #define MM_PAGE_SHIFT    12
-// FIXME: freeldr implementation uses ULONG for page numbers
-#define MM_MAX_PAGE        0xFFFFFFFFFFFFF
+#define MM_MAX_PAGE     0x3FFFF /* freeldr only maps 1 GB */
 
 #define MM_SIZE_TO_PAGES(a)  \
     ( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) )
index bbf7a57..164236c 100644 (file)
@@ -415,13 +415,15 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount)
 {
     const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
     SIZE_T PageLookupTableSize;
-    PFN_NUMBER PageLookupTablePages;
-    PFN_NUMBER PageLookupTableStartPage = 0;
+    PFN_NUMBER RequiredPages;
+    PFN_NUMBER CandidateBasePage = 0;
+    PFN_NUMBER CandidatePageCount;
+    PFN_NUMBER PageLookupTableEndPage;
     PVOID PageLookupTableMemAddress = NULL;
 
     // Calculate how much pages we need to keep the page lookup table
     PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM);
-    PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE;
+    RequiredPages = PageLookupTableSize / MM_PAGE_SIZE;
 
     // Search the highest memory block big enough to contain lookup table
     while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
@@ -429,22 +431,28 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount)
         // Continue, if memory is not free
         if (MemoryDescriptor->MemoryType != LoaderFree) continue;
 
-        // Continue, if the block is not big enough?
-        if (MemoryDescriptor->PageCount < PageLookupTablePages) continue;
+        // Continue, if the block is not big enough
+        if (MemoryDescriptor->PageCount < RequiredPages) continue;
 
         // Continue, if it is not at a higher address than previous address
-        if (MemoryDescriptor->BasePage < PageLookupTableStartPage) continue;
+        if (MemoryDescriptor->BasePage < CandidateBasePage) continue;
 
         // Continue, if the address is too high
-        if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) continue;
+        if (MemoryDescriptor->BasePage + RequiredPages >= MM_MAX_PAGE) continue;
 
         // Memory block is more suitable than the previous one
-        PageLookupTableStartPage = MemoryDescriptor->BasePage;
-        PageLookupTableMemAddress = (PVOID)((ULONG_PTR)
-            (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE
-            - PageLookupTableSize);
+        CandidateBasePage = MemoryDescriptor->BasePage;
+        CandidatePageCount = MemoryDescriptor->PageCount;
     }
 
+    // Calculate the end address for the lookup table
+    PageLookupTableEndPage = min(CandidateBasePage + CandidatePageCount,
+                                 MM_MAX_PAGE);
+
+    // Calculate the virtual address
+    PageLookupTableMemAddress = (PVOID)((PageLookupTableEndPage * PAGE_SIZE)
+                                        - PageLookupTableSize);
+
     TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress);
 
     return PageLookupTableMemAddress;