Fix PFN calculation truncation for memory above 4GB to prevent memory descriptor aliasing on PAE systems
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user