Fix critical memory corruption bug caused by overwriting active page tables marked as free memory
Some checks failed
Builds / ExectOS (i686, debug) (push) Failing after 28s
Builds / ExectOS (amd64, release) (push) Failing after 29s
Builds / ExectOS (i686, release) (push) Failing after 34s
Builds / ExectOS (amd64, debug) (push) Failing after 38s

This commit is contained in:
2026-03-12 19:02:58 +01:00
parent 5fe0740c2e
commit 21b3b269a7
8 changed files with 304 additions and 156 deletions

View File

@@ -28,13 +28,12 @@ EFI_STATUS
Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
IN ULONG_PTR SelfMapAddress)
{
PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry;
PXTBL_MEMORY_MAPPING Mapping;
PLIST_ENTRY ModulesList, ModulesListEntry;
PXTBL_MODULE_INFO ModuleInfo;
EFI_PHYSICAL_ADDRESS Address;
PVOID LoaderBase;
ULONGLONG LoaderSize;
EFI_STATUS Status;
PVOID LoaderBase;
/* Allocate pages for the Page Map */
Status = AllocatePages(AllocateAnyPages, 1, &Address);
@@ -117,6 +116,28 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
return STATUS_EFI_PROTOCOL_ERROR;
}
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* Iterates through the memory map and physically maps all virtual addresses to page tables.
*
* @param PageMap
* Supplies a pointer to the page mapping structure.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTCDECL
EFI_STATUS
Memory::CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap)
{
PXTBL_MEMORY_MAPPING Mapping;
PLIST_ENTRY ListEntry;
EFI_STATUS Status;
/* Iterate through and map all the mappings*/
Debug::Print(L"Mapping and dumping EFI memory:\n");
ListEntry = PageMap->MemoryMap.Flink;

View File

@@ -25,13 +25,12 @@ EFI_STATUS
Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
IN ULONG_PTR SelfMapAddress)
{
PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry;
EFI_PHYSICAL_ADDRESS Address, DirectoryAddress;
PLIST_ENTRY ModulesList, ModulesListEntry;
PXTBL_MODULE_INFO ModuleInfo;
PXTBL_MEMORY_MAPPING Mapping;
PVOID LoaderBase;
ULONGLONG LoaderSize;
EFI_STATUS Status;
PVOID LoaderBase;
ULONG Index;
/* Check the page map level to determine which paging structure to create */
@@ -45,6 +44,14 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
return Status;
}
/* Add new memory mapping for the page map itself */
Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory mapping failure */
return Status;
}
/* Assign the allocated page to the page map and zero it out */
PageMap->PtePointer = (PVOID)(UINT_PTR)Address;
RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE);
@@ -57,6 +64,14 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
return Status;
}
/* Add new memory mapping for the Page Directories (PDs) */
Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, DirectoryAddress, 4, LoaderMemoryData);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory mapping failure */
return Status;
}
/* Zero-fill the allocated memory for the Page Directories */
RTL::Memory::ZeroMemory((PVOID)DirectoryAddress, EFI_PAGE_SIZE * 4);
@@ -79,6 +94,14 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
return Status;
}
/* Add new memory mapping for the page map itself */
Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory mapping failure */
return Status;
}
/* Assign the allocated page to the page map and zero it out */
PageMap->PtePointer = (PVOID)(UINT_PTR)Address;
RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE);
@@ -144,6 +167,28 @@ Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
return STATUS_EFI_PROTOCOL_ERROR;
}
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* Iterates through the memory map and physically maps all virtual addresses to page tables.
*
* @param PageMap
* Supplies a pointer to the page mapping structure.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTCDECL
EFI_STATUS
Memory::CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap)
{
PXTBL_MEMORY_MAPPING Mapping;
PLIST_ENTRY ListEntry;
EFI_STATUS Status;
/* Iterate through and map all the mappings*/
Debug::Print(L"Mapping and dumping EFI memory:\n");
ListEntry = PageMap->MemoryMap.Flink;

View File

@@ -165,6 +165,7 @@ class Memory
OUT PVOID *Memory);
STATIC XTCDECL EFI_STATUS BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
IN ULONG_PTR SelfMapAddress);
STATIC XTCDECL EFI_STATUS CommitPageMap(IN PXTBL_PAGE_MAPPING PageMap);
STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages,
IN EFI_PHYSICAL_ADDRESS Memory);
STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory);

View File

@@ -10,6 +10,34 @@
#include <xtos.hh>
XTCDECL
EFI_STATUS
Xtos::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap)
{
EFI_STATUS Status;
/* Build page map */
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, (PageMap->PageMapLevel > 4) ? MM_P5E_LA57_BASE : MM_PXE_BASE);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Map memory for hardware layer */
Status = MapHardwareMemoryPool(PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to map memory for hardware layer */
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware leyer (Status code: %zX)\n", Status);
return Status;
}
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* Determines the appropriate EFI memory mapping strategy for the AMD64 architecture.
*
@@ -91,24 +119,6 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
ULONG_PTR TrampolineSize;
PVOID TrampolineCode;
/* Build page map */
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, (PageMap->PageMapLevel > 4) ? MM_P5E_LA57_BASE : MM_PXE_BASE);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Map memory for hardware layer */
Status = MapHardwareMemoryPool(PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to map memory for hardware layer */
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware leyer (Status code: %zX)\n", Status);
return Status;
}
/* Check the configured page map level to set the LA57 state accordingly */
if(PageMap->PageMapLevel == 5)
{
@@ -188,6 +198,7 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
PHARDWARE_PTE P5eBase, PdeBase, PpeBase, PxeBase;
EFI_PHYSICAL_ADDRESS Address;
EFI_STATUS Status;
ULONG Index;
if(PageMap->PageMapLevel == 5)
{
@@ -205,6 +216,9 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
return Status;
}
/* Map hardware memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
/* Zero fill memory used by P5E */
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
@@ -239,6 +253,9 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
return Status;
}
/* Map hardware memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
/* Zero fill memory used by PXE */
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
@@ -267,6 +284,9 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
return Status;
}
/* Map hardware memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
/* Zero fill memory used by PPE */
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
@@ -285,7 +305,7 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
}
/* Loop through 2 PDE entries */
for(UINT Index = 0 ; Index < 2 ; Index++)
for(Index = 0 ; Index < 2 ; Index++)
{
/* Check if PDE entry already exists */
if(!PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid)
@@ -298,6 +318,9 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
return Status;
}
/* Map hardware memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
/* Zero fill memory used by PDE */
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);

View File

@@ -9,6 +9,47 @@
#include <xtos.hh>
XTCDECL
EFI_STATUS
Xtos::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap)
{
ULONG_PTR SelfMapAddress;
EFI_STATUS Status;
/* Initialize self map address */
if(PageMap->PageMapLevel == 3)
{
/* For PML3 (PAE) use PTE base address */
SelfMapAddress = MM_PTE_BASE;
}
else
{
/* For PML2 (PAE disabled) use legacy PDE base address */
SelfMapAddress = MM_PDE_LEGACY_BASE;
}
/* Build page map */
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, SelfMapAddress);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Map memory for hardware layer */
Status = MapHardwareMemoryPool(PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to map memory for hardware layer */
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware layer (Status code: %zX)\n", Status);
return Status;
}
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* Determines the appropriate EFI memory mapping strategy for the i686 architecture.
*
@@ -74,37 +115,6 @@ EFI_STATUS
Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
{
EFI_STATUS Status;
ULONG_PTR SelfMapAddress;
/* Initialize self map address */
if(PageMap->PageMapLevel == 3)
{
/* For PML3 (PAE) use PTE base address */
SelfMapAddress = MM_PTE_BASE;
}
else
{
/* For PML2 (PAE disabled) use legacy PDE base address */
SelfMapAddress = MM_PDE_LEGACY_BASE;
}
/* Build page map */
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, SelfMapAddress);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Map memory for hardware layer */
Status = MapHardwareMemoryPool(PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to map memory for hardware layer */
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware layer (Status code: %zX)\n", Status);
return Status;
}
/* Exit EFI Boot Services */
XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n");
@@ -173,6 +183,9 @@ Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
/* Zero fill allocated memory */
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
/* Map hardware memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Address, 1, LoaderMemoryData);
/* Check if PAE is enabled (3-level paging) */
if(PageMap->PageMapLevel == 3)
{

View File

@@ -38,6 +38,7 @@ class Xtos
IN PVOID PhysicalAddress,
IN UINT NumberOfPages,
IN LOADER_MEMORY_TYPE MemoryType);
STATIC XTCDECL EFI_STATUS BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap);
STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType);
STATIC XTCDECL BOOLEAN DetermineMappingStrategy();
STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters);
@@ -47,10 +48,13 @@ class Xtos
IN PULONG_PTR FrameBufferSize,
IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo);
STATIC XTCDECL EFI_STATUS GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress,
IN EFI_PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
OUT PLIST_ENTRY MemoryDescriptorList);
STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress,
IN EFI_PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
IN PVOID FrameBufferVirtualBase,
OUT PLIST_ENTRY SystemResourcesList);
STATIC XTCDECL EFI_STATUS GetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
IN PVOID PhysicalAddress,

View File

@@ -191,38 +191,16 @@ Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource
XTCDECL
EFI_STATUS
Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress,
IN EFI_PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
OUT PLIST_ENTRY MemoryDescriptorList)
{
PLOADER_MEMORY_DESCRIPTOR Descriptor;
PXTBL_MEMORY_MAPPING MemoryMapping;
EFI_PHYSICAL_ADDRESS Address;
PLIST_ENTRY ListEntry;
EFI_STATUS Status;
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));
/* Allocate physical pages to hold the memory descriptor list */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
if(Status != STATUS_EFI_SUCCESS)
{
/* Page allocation failed, return the status code */
return Status;
}
/* Create a virtual memory mapping for the allocated descriptor buffer */
Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData);
if(Status != STATUS_EFI_SUCCESS)
{
/* Release the allocated pages as the virtual mapping failed and return status code */
XtLdrProtocol->Memory.FreePages(Address, Pages);
return Status;
}
/* Initialize the descriptor pointer to the start of the allocated physical buffer */
Descriptor = (PLOADER_MEMORY_DESCRIPTOR)Address;
Descriptor = (PLOADER_MEMORY_DESCRIPTOR)PhysicalBase;
/* Get the first entry from the internal boot loader memory map */
ListEntry = PageMap->MemoryMap.Flink;
@@ -247,17 +225,18 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
}
/* Convert all physical link pointers in the list to their corresponding virtual addresses */
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, (PVOID)Address, *VirtualAddress);
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, (PVOID)PhysicalBase, VirtualBase);
/* Advance the virtual address pointer to the next available free region and return success */
*VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE);
/* Return success */
return STATUS_EFI_SUCCESS;
}
XTCDECL
EFI_STATUS
Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress,
IN EFI_PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
IN PVOID FrameBufferVirtualBase,
OUT PLIST_ENTRY SystemResourcesList)
{
XTSTATUS Status;
@@ -268,39 +247,18 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol;
XTBL_FRAMEBUFFER_MODE_INFORMATION FbModeInfo;
EFI_PHYSICAL_ADDRESS FbAddress;
EFI_PHYSICAL_ADDRESS OriginalPhysicalBase;
ULONG_PTR FbSize;
UINT FrameBufferPages;
PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource;
PSYSTEM_RESOURCE_ACPI AcpiResource;
ULONGLONG Pages;
EFI_PHYSICAL_ADDRESS Address;
PVOID PhysicalBase, VirtualBase;
Pages = (ULONGLONG)EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER));
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
if(Status != STATUS_EFI_SUCCESS)
{
return Status;
}
Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent);
if(Status != STATUS_EFI_SUCCESS)
{
XtLdrProtocol->Memory.FreePages(Address, Pages);
return Status;
}
PhysicalBase = (PVOID)Address;
VirtualBase = *VirtualAddress;
/* Calculate next valid virtual address */
*VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE);
AcpiResource = (PSYSTEM_RESOURCE_ACPI)Address;
/* Save original physical base */
OriginalPhysicalBase = PhysicalBase;
AcpiResource = (PSYSTEM_RESOURCE_ACPI)PhysicalBase;
XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI));
/* Load FrameBuffer protocol */
/* Load ACPI protocol */
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&AcpiProtocol, &AcpiGuid);
if(Status != STATUS_EFI_SUCCESS)
{
@@ -319,13 +277,11 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &AcpiResource->Header.ListEntry);
/* Close FrameBuffer protocol */
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
Address = Address + sizeof(SYSTEM_RESOURCE_ACPI);
FrameBufferResource = (PSYSTEM_RESOURCE_FRAMEBUFFER)Address;
/* Close ACPI protocol */
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &AcpiGuid);
PhysicalBase = PhysicalBase + sizeof(SYSTEM_RESOURCE_ACPI);
FrameBufferResource = (PSYSTEM_RESOURCE_FRAMEBUFFER)PhysicalBase;
XtLdrProtocol->Memory.ZeroMemory(FrameBufferResource, sizeof(SYSTEM_RESOURCE_FRAMEBUFFER));
/* Load FrameBuffer protocol */
@@ -346,26 +302,16 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
return Status;
}
/* Calculate pages needed to map framebuffer */
FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize);
/* Rewrite framebuffer address by using virtual address */
FrameBufferResource->Header.VirtualAddress = *VirtualAddress;
/* Map frame buffer memory */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress,
(ULONGLONG)FrameBufferResource->Header.PhysicalAddress,
FrameBufferPages, LoaderFirmwarePermanent);
/* Close FrameBuffer protocol */
/* Assign the pre-mapped virtual address to the resource block */
FrameBufferResource->Header.VirtualAddress = FrameBufferVirtualBase;
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
*VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE);
XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry);
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, PhysicalBase, VirtualBase);
/* Convert list pointers to virtual */
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, (PVOID)OriginalPhysicalBase, VirtualBase);
/* Return success */
return STATUS_EFI_SUCCESS;
}
@@ -426,34 +372,97 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap)
XTCDECL
EFI_STATUS
Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap,
IN PVOID *VirtualAddress,
IN OUT PVOID *VirtualAddress,
IN PXTBL_BOOT_PARAMETERS Parameters)
{
EFI_PHYSICAL_ADDRESS FbPhysicalAddress, PhysicalBlock, PhysicalDescriptor, PhysicalResources;
PVOID FbVirtualAddress, VirtualBlock, VirtualResources, VirtualDescriptor;
UINT BlockPages, DescriptorPages, FbPages, ParametersSize, ResourcesPages;
XTBL_FRAMEBUFFER_MODE_INFORMATION FbModeInfo;
PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol;
PKERNEL_INITIALIZATION_BLOCK LoaderBlock;
EFI_PHYSICAL_ADDRESS Address;
EFI_HANDLE ProtocolHandle;
EFI_STATUS Status;
UINT BlockPages;
UINT ParametersSize;
ULONG_PTR FbSize;
EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID;
/* Initialize Framebuffer information */
FbPhysicalAddress = 0;
FbSize = 0;
FbVirtualAddress = NULLPTR;
FbPages = 0;
/* Calculate size of parameters */
ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR);
/* Calculate number of pages needed for initialization block */
BlockPages = EFI_SIZE_TO_PAGES(sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize);
ResourcesPages = EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER));
/* Allocate memory for kernel initialization block */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, BlockPages, &Address);
/* Query Framebuffer size for allocation */
if(XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid) == STATUS_EFI_SUCCESS)
{
/* Get FrameBuffer information */
FrameBufProtocol->GetDisplayInformation(&FbPhysicalAddress, &FbSize, &FbModeInfo);
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
}
FbPages = EFI_SIZE_TO_PAGES(FbSize);
/* Add padding to MapSize to account for the ledger mappings */
DescriptorPages = EFI_SIZE_TO_PAGES((PageMap->MapSize + 16) * sizeof(LOADER_MEMORY_DESCRIPTOR));
/* Allocate memory for the kernel initialization block and boot parameters */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, BlockPages, &PhysicalBlock);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory allocation failure */
/* Memory allocation failure, return status code */
return Status;
}
/* Initialize and zero-fill kernel initialization block */
LoaderBlock = (PKERNEL_INITIALIZATION_BLOCK)(UINT_PTR)Address;
XtLdrProtocol->Memory.ZeroMemory(LoaderBlock, sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize);
/* Allocate memory for the system resources data structures */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, ResourcesPages, &PhysicalResources);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory allocation failure, return status code */
return Status;
}
/* Allocate memory for the memory descriptor list */
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, DescriptorPages, &PhysicalDescriptor);
if(Status != STATUS_EFI_SUCCESS)
{
/* Memory allocation failure, return status code */
return Status;
}
/* Map the Kernel Initialization Block into virtual memory and advance the virtual address pointer */
VirtualBlock = *VirtualAddress;
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualBlock, PhysicalBlock, BlockPages, LoaderSystemBlock);
*VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE);
/* Map the system resources physical memory into virtual address space and update the allocation pointer */
VirtualResources = *VirtualAddress;
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualResources, PhysicalResources, ResourcesPages, LoaderFirmwarePermanent);
*VirtualAddress = (PUINT8)*VirtualAddress + (ResourcesPages * EFI_PAGE_SIZE);
/* Check if a framebuffer was detected and requires memory mapping */
if(FbPages > 0)
{
/* Map the framebuffer physical memory range into virtual address space */
FbVirtualAddress = *VirtualAddress;
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FbVirtualAddress, FbPhysicalAddress, FbPages, LoaderFirmwarePermanent);
*VirtualAddress = (PUINT8)*VirtualAddress + (FbPages * EFI_PAGE_SIZE);
}
/* Map the allocated physical memory for memory descriptors into the virtual address space */
VirtualDescriptor = *VirtualAddress;
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)VirtualDescriptor, PhysicalDescriptor, DescriptorPages, LoaderMemoryData);
*VirtualAddress = (PUINT8)*VirtualAddress + (DescriptorPages * EFI_PAGE_SIZE);
/* Set basic loader block properties */
XtLdrProtocol->Memory.ZeroMemory((PVOID)PhysicalBlock, sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize);
LoaderBlock = (PKERNEL_INITIALIZATION_BLOCK)PhysicalBlock;
LoaderBlock->BlockSize = sizeof(KERNEL_INITIALIZATION_BLOCK);
LoaderBlock->BlockVersion = INITIALIZATION_BLOCK_VERSION;
LoaderBlock->ProtocolVersion = BOOT_PROTOCOL_VERSION;
@@ -467,24 +476,30 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap,
LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR;
/* Copy parameters to kernel initialization block */
LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK));
LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)VirtualBlock + sizeof(KERNEL_INITIALIZATION_BLOCK));
XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)),
Parameters->Parameters,
ParametersSize);
Parameters->Parameters, ParametersSize);
/* Map kernel initialization block */
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, (ULONGLONG)LoaderBlock,
BlockPages, LoaderSystemBlock);
/* Calculate next valid virtual address */
*VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE);
/* HACK: Commit page map to avoid memory leaks (AGAIN!) */
XtLdrProtocol->Memory.CommitPageMap(PageMap);
/* Initialize system resources list */
XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead);
GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead);
Status = GetSystemResourcesList(PageMap, PhysicalResources, VirtualResources, FbVirtualAddress, &LoaderBlock->SystemResourcesListHead);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to initialize system resources list, return status code */
return Status;
}
/* Initialize memory descriptor list */
XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead);
GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead);
Status = GetMemoryDescriptorList(PageMap, PhysicalDescriptor, VirtualDescriptor, &LoaderBlock->MemoryDescriptorListHead);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to initialize memory descriptor list, return status code */
return Status;
}
/* Set boot image size */
LoaderBlock->BootImageSize = (PFN_NUMBER)(((ULONGLONG)*VirtualAddress - KSEG0_BASE) / EFI_PAGE_SIZE);
@@ -702,6 +717,22 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir,
return Status;
}
/* Build page map */
Status = BuildPageMap(&PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Commit mappings */
Status = XtLdrProtocol->Memory.CommitPageMap(&PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
XtLdrProtocol->Debug.Print(L"Failed to commit hardware mappings (Pass 1)\n");
return Status;
}
/* Store virtual address of kernel initialization block for future kernel call */
KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress;
@@ -714,6 +745,15 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir,
return Status;
}
/* HACK: Commit mappings again to include the kernel initialization block */
Status = XtLdrProtocol->Memory.CommitPageMap(&PageMap);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to build page map */
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
return Status;
}
/* Get kernel entry point */
PeCoffProtocol->GetEntryPoint(ImageContext, (PVOID*)&KernelEntryPoint);

View File

@@ -1054,6 +1054,7 @@ Protocol::InstallXtLoaderProtocol()
LoaderProtocol.Memory.AllocatePages = Memory::AllocatePages;
LoaderProtocol.Memory.AllocatePool = Memory::AllocatePool;
LoaderProtocol.Memory.BuildPageMap = Memory::BuildPageMap;
LoaderProtocol.Memory.CommitPageMap = Memory::CommitPageMap;
LoaderProtocol.Memory.CompareMemory = RTL::Memory::CompareMemory;
LoaderProtocol.Memory.CopyMemory = RTL::Memory::CopyMemory;
LoaderProtocol.Memory.FreePages = Memory::FreePages;