From ae243a9d073f2d391bfa13cbcccbeb4d71ba5305 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Mon, 27 May 2024 21:54:21 +0200 Subject: [PATCH] Map memory for hardware layer on amd64 --- xtldr/modules/xtos_o/amd64/memory.c | 134 +++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 11 deletions(-) diff --git a/xtldr/modules/xtos_o/amd64/memory.c b/xtldr/modules/xtos_o/amd64/memory.c index 3d30786..0ae55a3 100644 --- a/xtldr/modules/xtos_o/amd64/memory.c +++ b/xtldr/modules/xtos_o/amd64/memory.c @@ -9,20 +9,123 @@ #include +/** + * Maps the page table for hardware layer addess space. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtMapHalMemory(IN PXTBL_PAGE_MAPPING PageMap) +{ + PHARDWARE_PTE PdeBase, PpeBase, PxeBase; + EFI_PHYSICAL_ADDRESS Address; + XTSTATUS Status; + + /* Check page map level */ + if(PageMap->PageMapLevel > 4) + { + /* PML5 (LA57) is not supported yet */ + return STATUS_EFI_UNSUPPORTED; + } + + /* Get PXE (PML4) base address */ + PxeBase = ((PHARDWARE_PTE)(PageMap->PtePointer)); + + /* Check if PXE entry already exists */ + if(!PxeBase[(MM_HAL_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid) + { + /* No valid PXE, allocate memory */ + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, return error */ + return Status; + } + + /* Zero fill memory used by PXE */ + RtlZeroMemory((PVOID)Address, EFI_PAGE_SIZE); + + /* Make PXE valid */ + PxeBase[(MM_HAL_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid = 1; + PxeBase[(MM_HAL_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE; + PxeBase[(MM_HAL_VA_START >> MM_PXI_SHIFT) & 0x1FF].Writable = 1; + + /* Set PPE base address */ + PpeBase = (PHARDWARE_PTE)(UINT_PTR)Address; + } + else + { + /* Set PPE base address based on existing PXE */ + PpeBase = (PHARDWARE_PTE)((PxeBase[(MM_HAL_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT); + } + + /* Check if PPE entry already exists */ + if(!PpeBase[(MM_HAL_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid) + { + /* No valid PPE, allocate memory */ + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, return error */ + return Status; + } + + /* Zero fill memory used by PPE */ + RtlZeroMemory((PVOID)Address, EFI_PAGE_SIZE); + + /* Make PPE valid */ + PpeBase[(MM_HAL_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid = 1; + PpeBase[(MM_HAL_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE; + PpeBase[(MM_HAL_VA_START >> MM_PPI_SHIFT) & 0x1FF].Writable = 1; + + /* Set PDE base address */ + PdeBase = (PHARDWARE_PTE)Address; + } + else + { + /* Set PDE base address, based on existing PPE */ + PdeBase = (PHARDWARE_PTE)((PpeBase[(MM_HAL_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT); + } + + /* Loop through 2 PDE entries */ + for(UINT Index = 0 ; Index < 2 ; Index++) + { + /* Check if PDE entry already exists */ + if(!PdeBase[((MM_HAL_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid) + { + /* No valid PDE, allocate memory */ + Status = XtLdrProtocol->Memory.AllocatePages(1, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, return error */ + return Status; + } + + /* Zero fill memory used by PDE */ + RtlZeroMemory((PVOID)Address, EFI_PAGE_SIZE); + + /* Make PDE valid */ + PdeBase[((MM_HAL_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid = 1; + PdeBase[((MM_HAL_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].PageFrameNumber = Address / EFI_PAGE_SIZE; + PdeBase[((MM_HAL_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Writable = 1; + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * - * @param MemoryMappings - * Supplies a pointer to linked list containing all memory mappings. - * - * @param VirtualAddress - * Supplies a pointer to the next valid, free and available virtual address. - * - * @param ImageProtocol - * A pointer to the EFI loaded image protocol with information about where in memory the loader code was placed. - * - * @param PtePointer - * Supplies a pointer to memory area containing a Page Table Entries (PTE). + * @param PageMap + * Supplies a pointer to the page mapping structure. * * @return This routine returns a status code. * @@ -43,6 +146,15 @@ XtEnablePaging(IN PXTBL_PAGE_MAPPING PageMap) return Status; } + /* Map memory for hardware layer */ + Status = XtMapHalMemory(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; + } + /* Exit EFI Boot Services */ XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); Status = XtLdrProtocol->Util.ExitBootServices();