Skip to content

Commit 6da9353

Browse files
authored
[FREELDR] Fix calculation of page lookup table (reactos#761)
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
1 parent 27c3a4d commit 6da9353

File tree

2 files changed

+20
-13
lines changed

2 files changed

+20
-13
lines changed

boot/freeldr/freeldr/include/mm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ typedef struct _FREELDR_MEMORY_DESCRIPTOR
5858
#define MM_PAGE_SIZE 4096
5959
#define MM_PAGE_MASK 0xFFF
6060
#define MM_PAGE_SHIFT 12
61-
// FIXME: freeldr implementation uses ULONG for page numbers
62-
#define MM_MAX_PAGE 0xFFFFFFFFFFFFF
61+
#define MM_MAX_PAGE 0x3FFFF /* freeldr only maps 1 GB */
6362

6463
#define MM_SIZE_TO_PAGES(a) \
6564
( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) )

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -415,36 +415,44 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount)
415415
{
416416
const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
417417
SIZE_T PageLookupTableSize;
418-
PFN_NUMBER PageLookupTablePages;
419-
PFN_NUMBER PageLookupTableStartPage = 0;
418+
PFN_NUMBER RequiredPages;
419+
PFN_NUMBER CandidateBasePage = 0;
420+
PFN_NUMBER CandidatePageCount;
421+
PFN_NUMBER PageLookupTableEndPage;
420422
PVOID PageLookupTableMemAddress = NULL;
421423

422424
// Calculate how much pages we need to keep the page lookup table
423425
PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM);
424-
PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE;
426+
RequiredPages = PageLookupTableSize / MM_PAGE_SIZE;
425427

426428
// Search the highest memory block big enough to contain lookup table
427429
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
428430
{
429431
// Continue, if memory is not free
430432
if (MemoryDescriptor->MemoryType != LoaderFree) continue;
431433

432-
// Continue, if the block is not big enough?
433-
if (MemoryDescriptor->PageCount < PageLookupTablePages) continue;
434+
// Continue, if the block is not big enough
435+
if (MemoryDescriptor->PageCount < RequiredPages) continue;
434436

435437
// Continue, if it is not at a higher address than previous address
436-
if (MemoryDescriptor->BasePage < PageLookupTableStartPage) continue;
438+
if (MemoryDescriptor->BasePage < CandidateBasePage) continue;
437439

438440
// Continue, if the address is too high
439-
if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) continue;
441+
if (MemoryDescriptor->BasePage + RequiredPages >= MM_MAX_PAGE) continue;
440442

441443
// Memory block is more suitable than the previous one
442-
PageLookupTableStartPage = MemoryDescriptor->BasePage;
443-
PageLookupTableMemAddress = (PVOID)((ULONG_PTR)
444-
(MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE
445-
- PageLookupTableSize);
444+
CandidateBasePage = MemoryDescriptor->BasePage;
445+
CandidatePageCount = MemoryDescriptor->PageCount;
446446
}
447447

448+
// Calculate the end address for the lookup table
449+
PageLookupTableEndPage = min(CandidateBasePage + CandidatePageCount,
450+
MM_MAX_PAGE);
451+
452+
// Calculate the virtual address
453+
PageLookupTableMemAddress = (PVOID)((PageLookupTableEndPage * PAGE_SIZE)
454+
- PageLookupTableSize);
455+
448456
TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress);
449457

450458
return PageLookupTableMemAddress;

0 commit comments

Comments
 (0)