Fix PFN calculation truncation for memory above 4GB to prevent memory descriptor aliasing on PAE systems
All checks were successful
Builds / ExectOS (i686, debug) (push) Successful in 31s
Builds / ExectOS (amd64, debug) (push) Successful in 34s
Builds / ExectOS (amd64, release) (push) Successful in 1m2s
Builds / ExectOS (i686, release) (push) Successful in 1m1s

This commit is contained in:
2026-02-09 23:17:58 +01:00
parent 53f7945771
commit e2da6220f2

View File

@@ -194,49 +194,63 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress, IN PVOID *VirtualAddress,
OUT PLIST_ENTRY MemoryDescriptorList) OUT PLIST_ENTRY MemoryDescriptorList)
{ {
PLOADER_MEMORY_DESCRIPTOR Descriptor;
PXTBL_MEMORY_MAPPING MemoryMapping;
EFI_PHYSICAL_ADDRESS Address; EFI_PHYSICAL_ADDRESS Address;
PLIST_ENTRY ListEntry;
EFI_STATUS Status; EFI_STATUS Status;
ULONGLONG Pages; ULONGLONG Pages;
/* Calculate the number of pages required to store the memory descriptor array */
Pages = (ULONGLONG)EFI_SIZE_TO_PAGES((PageMap->MapSize + 1) * sizeof(LOADER_MEMORY_DESCRIPTOR)); Pages = (ULONGLONG)EFI_SIZE_TO_PAGES((PageMap->MapSize + 1) * sizeof(LOADER_MEMORY_DESCRIPTOR));
/* Allocate physical pages to hold the memory descriptor list */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address); Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
if(Status != STATUS_EFI_SUCCESS) if(Status != STATUS_EFI_SUCCESS)
{ {
/* Page allocation failed, return the status code */
return Status; return Status;
} }
/* Create a virtual memory mapping for the allocated descriptor buffer */
Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData);
if(Status != STATUS_EFI_SUCCESS) if(Status != STATUS_EFI_SUCCESS)
{ {
/* Release the allocated pages as the virtual mapping failed and return status code */
XtLdrProtocol->Memory.FreePages(Address, Pages); XtLdrProtocol->Memory.FreePages(Address, Pages);
return Status; return Status;
} }
PVOID PhysicalBase = (PVOID)Address; /* Initialize the descriptor pointer to the start of the allocated physical buffer */
Descriptor = (PLOADER_MEMORY_DESCRIPTOR)Address;
PLIST_ENTRY ListEntry; /* Get the first entry from the internal boot loader memory map */
ListEntry = PageMap->MemoryMap.Flink; ListEntry = PageMap->MemoryMap.Flink;
/* Iterate through the internal memory map and populate the loader descriptor list */
while(ListEntry != &PageMap->MemoryMap) while(ListEntry != &PageMap->MemoryMap)
{ {
PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); /* Retrieve the internal memory mapping record from the current list entry */
PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; /* Transfer memory type and address information to the kernel descriptor */
MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; Descriptor->MemoryType = MemoryMapping->MemoryType;
MemoryDescriptor->PageCount = MemoryMapping->NumberOfPages; Descriptor->BasePage = (UINT_PTR)(MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE);
Descriptor->PageCount = (ULONG)MemoryMapping->NumberOfPages;
XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); /* Link the entry */
XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &Descriptor->ListEntry);
Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); /* Move to the next slot in the allocated buffer */
Descriptor++;
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); /* Convert all physical link pointers in the list to their corresponding virtual addresses */
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, (PVOID)Address, *VirtualAddress);
/* Calculate next valid virtual address */ /* Advance the virtual address pointer to the next available free region and return success */
*VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE);
return STATUS_EFI_SUCCESS; return STATUS_EFI_SUCCESS;
} }