From 89c18bbce684f3bdb5fcd42df2b0dedcab26a04b Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Wed, 17 Jan 2024 14:42:07 +0100 Subject: [PATCH] Initial paging support --- sdk/xtdk/bltypes.h | 17 ++ sdk/xtdk/xtfw.h | 1 + sdk/xtdk/xtstruct.h | 1 + xtldr/CMakeLists.txt | 1 + xtldr/arch/amd64/memory.c | 115 ++++++++++ xtldr/arch/i686/memory.c | 97 +++++++++ xtldr/includes/xtldr.h | 37 ++++ xtldr/memory.c | 427 ++++++++++++++++++++++++++++++++++++++ xtldr/protocol.c | 4 + 9 files changed, 700 insertions(+) create mode 100644 xtldr/arch/amd64/memory.c create mode 100644 xtldr/arch/i686/memory.c diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 3d27fe4..58a3e84 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -92,9 +92,13 @@ typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory); typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_MAP MemoryMap); typedef PLIST_ENTRY (*PBL_GET_MODULES_LIST)(); typedef INT_PTR (*PBL_GET_SECURE_BOOT_STATUS)(); +typedef VOID (*PBL_INITIALIZE_PAGE_MAP)(OUT PXTBL_PAGE_MAPPING PageMap, IN SHORT PageMapLevel, IN PVOID *MemoryMapAddress); typedef EFI_STATUS (*PBL_INSTALL_XT_PROTOCOL)(IN PVOID Interface, IN PEFI_GUID Guid); typedef EFI_STATUS (*PBL_INVOKE_BOOT_PROTOCOL)(IN PLIST_ENTRY OptionsList); typedef EFI_STATUS (*PBL_LOCATE_PROTOCOL_HANDLES)(OUT PEFI_HANDLE *Handles, OUT PUINT_PTR Count, IN PEFI_GUID ProtocolGuid); +typedef EFI_STATUS (*PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress); +typedef EFI_STATUS (*PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages); +typedef EFI_STATUS (*PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef EFI_STATUS (*PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (*PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (*PBL_OPEN_PROTOCOL_HANDLE)(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); @@ -191,6 +195,15 @@ typedef struct _XTBL_MODULE_INFO PEFI_IMAGE_UNLOAD UnloadModule; } XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; +/* Boot Loader page mapping information */ +typedef struct _XTBL_PAGE_MAPPING +{ + LIST_ENTRY MemoryMap; + PVOID PtePointer; + PVOID MemoryMapAddress; + SHORT PageMapLevel; +} XTBL_PAGE_MAPPING, *PXTBL_PAGE_MAPPING; + /* XTLDR Status data */ typedef struct _XTBL_STATUS { @@ -268,6 +281,10 @@ typedef struct _XTBL_LOADER_PROTOCOL PBL_FREE_PAGES FreePages; PBL_FREE_POOL FreePool; PBL_GET_MEMORY_MAP GetMemoryMap; + PBL_INITIALIZE_PAGE_MAP InitializePageMap; + PBL_MAP_EFI_MEMORY MapEfiMemory; + PBL_MAP_PAGE MapPage; + PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; PBL_SET_MEMORY SetMemory; PBL_ZERO_MEMORY ZeroMemory; } Memory; diff --git a/sdk/xtdk/xtfw.h b/sdk/xtdk/xtfw.h index 613e2ab..5ad745d 100644 --- a/sdk/xtdk/xtfw.h +++ b/sdk/xtdk/xtfw.h @@ -111,6 +111,7 @@ typedef struct _LOADER_INFORMATION_BLOCK LOADER_GRAPHICS_INFORMATION_BLOCK FrameBuffer; } LOADER_INFORMATION_BLOCK, *PLOADER_INFORMATION_BLOCK; +/* Boot Loader memory mapping information */ typedef struct _LOADER_MEMORY_MAPPING { LIST_ENTRY ListEntry; diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index c7455c7..6f18808 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -281,6 +281,7 @@ typedef struct _XTBL_KNOWN_BOOT_PROTOCOL XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_ typedef struct _XTBL_LOADER_PROTOCOL XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; typedef struct _XTBL_MODULE_DEPS XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; typedef struct _XTBL_MODULE_INFO XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; +typedef struct _XTBL_PAGE_MAPPING XTBL_PAGE_MAPPING, *PXTBL_PAGE_MAPPING; typedef struct _XTBL_STATUS XTBL_STATUS, *PXTBL_STATUS; /* Unions forward references */ diff --git a/xtldr/CMakeLists.txt b/xtldr/CMakeLists.txt index 680f6fe..3a59a5e 100644 --- a/xtldr/CMakeLists.txt +++ b/xtldr/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND LIBXTLDR_SOURCE # Specify list of source code files list(APPEND XTLDR_SOURCE + ${XTLDR_SOURCE_DIR}/arch/${ARCH}/memory.c ${XTLDR_SOURCE_DIR}/config.c ${XTLDR_SOURCE_DIR}/console.c ${XTLDR_SOURCE_DIR}/debug.c diff --git a/xtldr/arch/amd64/memory.c b/xtldr/arch/amd64/memory.c new file mode 100644 index 0000000..a566c52 --- /dev/null +++ b/xtldr/arch/amd64/memory.c @@ -0,0 +1,115 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/arch/amd64/memory.c + * DESCRIPTION: XT Boot Loader AMD64 specific memory management + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Does the actual virtual memory mapping. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param VirtualAddress + * Supplies a virtual address of the mapping. + * + * @param PhysicalAddress + * Supplies a physical address of the mapping. + * + * @param NumberOfPages + * Supplies a number of the pages of the mapping. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMapPage(IN PXTBL_PAGE_MAPPING PageMap, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages) +{ + SIZE_T Pml1Entry, Pml2Entry, Pml3Entry, Pml4Entry, Pml5Entry; + PHARDWARE_PTE Pml1, Pml2, Pml3, Pml4, Pml5; + SIZE_T PageFrameNumber; + EFI_STATUS Status; + + /* Set the Page Frame Number (PFN) */ + PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT; + + /* Do the recursive mapping */ + while(NumberOfPages > 0) + { + /* Calculate the indices in the various Page Tables from the virtual address */ + Pml5Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 48)) >> 48; + Pml4Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 39)) >> 39; + Pml3Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 30)) >> 30; + Pml2Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 21)) >> 21; + Pml1Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 12)) >> 12; + + /* Check page map level */ + if(PageMap->PageMapLevel == 5) + { + /* Five level Page Map */ + Pml5 = ((PHARDWARE_PTE)(PageMap->PtePointer)); + + /* Get PML4 */ + Status = BlpGetNextPageTable(PageMap, Pml5, Pml5Entry, &Pml4); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + } + else + { + /* Four level Page Map */ + Pml4 = ((PHARDWARE_PTE)(PageMap->PtePointer)); + } + + /* Get PML3 */ + Status = BlpGetNextPageTable(PageMap, Pml4, Pml4Entry, &Pml3); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + + /* Get PML 2 */ + Status = BlpGetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + + /* Get PML1 */ + Status = BlpGetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + + /* Set paging entry settings */ + Pml1[Pml1Entry].PageFrameNumber = PageFrameNumber; + Pml1[Pml1Entry].Valid = 1; + Pml1[Pml1Entry].Write = 1; + + /* Take next virtual address and PFN */ + VirtualAddress += EFI_PAGE_SIZE; + PageFrameNumber++; + + /* Decrease number of pages left */ + NumberOfPages--; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/arch/i686/memory.c b/xtldr/arch/i686/memory.c new file mode 100644 index 0000000..fe89608 --- /dev/null +++ b/xtldr/arch/i686/memory.c @@ -0,0 +1,97 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/arch/i686/memory.c + * DESCRIPTION: XT Boot Loader i686 specific memory management + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Does the actual virtual memory mapping. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param VirtualAddress + * Supplies a virtual address of the mapping. + * + * @param PhysicalAddress + * Supplies a physical address of the mapping. + * + * @param NumberOfPages + * Supplies a number of the pages of the mapping. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMapPage(IN PXTBL_PAGE_MAPPING PageMap, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages) +{ + SIZE_T Pml1Entry, Pml2Entry, Pml3Entry; + PHARDWARE_PTE Pml1, Pml2, Pml3; + SIZE_T PageFrameNumber; + EFI_STATUS Status; + + /* Set the Page Frame Number (PFN) */ + PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT; + + /* Do the recursive mapping */ + while(NumberOfPages > 0) + { + /* Calculate the indices in the various Page Tables from the virtual address */ + Pml3Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 30)) >> 30; + Pml2Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 21)) >> 21; + Pml1Entry = (VirtualAddress & ((ULONGLONG)0x1FF << 12)) >> 12; + + /* Check page map level */ + if(PageMap->PageMapLevel == 3) + { + /* Three level Page Map */ + Pml3 = ((PHARDWARE_PTE)(PageMap->PtePointer)); + + /* Get PML2 */ + Status = BlpGetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + } + else + { + /* Two level Page Map */ + Pml2 = ((PHARDWARE_PTE)(PageMap->PtePointer)); + } + + /* Get PML1 */ + Status = BlpGetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + + /* Set paging entry settings */ + Pml1[Pml1Entry].PageFrameNumber = PageFrameNumber; + Pml1[Pml1Entry].Valid = 1; + Pml1[Pml1Entry].Write = 1; + + /* Take next virtual address and PFN */ + VirtualAddress += EFI_PAGE_SIZE; + PageFrameNumber++; + + /* Decrease number of pages left */ + NumberOfPages--; + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/includes/xtldr.h b/xtldr/includes/xtldr.h index a1d6a30..e777b13 100644 --- a/xtldr/includes/xtldr.h +++ b/xtldr/includes/xtldr.h @@ -154,6 +154,12 @@ XTCDECL VOID BlInitializeConsole(); +XTCDECL +VOID +BlInitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, + IN SHORT PageMapLevel, + IN PVOID *MemoryMapAddress); + XTCDECL EFI_STATUS BlInstallProtocol(IN PVOID Interface, @@ -177,6 +183,26 @@ BlLocateProtocolHandles(OUT PEFI_HANDLE *Handles, OUT PUINT_PTR Count, IN PEFI_GUID ProtocolGuid); +XTCDECL +EFI_STATUS +BlMapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN OUT PVOID *DesiredVirtualAddress); + +XTCDECL +EFI_STATUS +BlMapPage(IN PXTBL_PAGE_MAPPING PageMap, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages); + +XTCDECL +EFI_STATUS +BlMapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType); + XTCDECL EFI_STATUS BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, @@ -356,6 +382,17 @@ BlpFindParentBlockDevice(IN PLIST_ENTRY BlockDevices, IN PEFI_BLOCK_DEVICE_DATA ChildNode, OUT PEFI_BLOCK_DEVICE_DATA ParentNode); +XTCDECL +LOADER_MEMORY_TYPE +BlpGetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); + +XTCDECL +EFI_STATUS +BlpGetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, + IN PHARDWARE_PTE PageTable, + IN SIZE_T Entry, + OUT PHARDWARE_PTE *NextPageTable); + XTCDECL EFI_STATUS BlpInitializeDebugConsole(); diff --git a/xtldr/memory.c b/xtldr/memory.c index f818455..f56a9e2 100644 --- a/xtldr/memory.c +++ b/xtldr/memory.c @@ -153,3 +153,430 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap) /* Return success */ return STATUS_EFI_SUCCESS; } + +/** + * Initializes the page mapping structures. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param PageMapLevel + * Specifies a number of of paging structures levels. + * + * @param MemoryMapAddress + * Supplies an address of the mapped virtual memory area. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlInitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, + IN SHORT PageMapLevel, + IN PVOID *MemoryMapAddress) +{ + /* Initialize memory mappings */ + RtlInitializeListHead(&PageMap->MemoryMap); + + /* Set page map level and memory map address */ + PageMap->PageMapLevel = PageMapLevel; + PageMap->MemoryMapAddress = &MemoryMapAddress; +} + +/** + * Adds EFI memory mapping to the page mapping structure. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param DesiredVirtualAddress + * Supplies a desired virtual address, where EFI memory will be mapped. + * If not specified, memory map address will be used. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN OUT PVOID *DesiredVirtualAddress) +{ + PEFI_MEMORY_DESCRIPTOR Descriptor; + LOADER_MEMORY_TYPE MemoryType; + PEFI_MEMORY_MAP MemoryMap; + SIZE_T DescriptorCount; + PUCHAR VirtualAddress; + EFI_STATUS Status; + SIZE_T Index; + + /* Set initial virtual address */ + if(*DesiredVirtualAddress != NULL) + { + /* Set virtual address as specified in argument */ + VirtualAddress = *DesiredVirtualAddress; + } + else + { + /* Otherwise, set virtual address as specified in page map */ + VirtualAddress = PageMap->MemoryMapAddress; + } + + /* Allocate and zero-fill buffer for EFI memory map */ + BlAllocateMemoryPool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); + RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); + + /* Get EFI memory map */ + Status = BlGetMemoryMap(MemoryMap); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to get EFI memory map */ + return Status; + } + + /* Calculate descriptors count and get first one */ + Descriptor = MemoryMap->Map; + DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize; + + /* Iterate through all descriptors from the memory map */ + for(Index = 0; Index < DescriptorCount; Index++) + { + /* Make sure descriptor does not go beyond lowest physical page */ + if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1) + { + /* Convert EFI memory type into XTLDR memory type */ + MemoryType = BlpGetLoaderMemoryType(Descriptor->Type); + + /* Do memory mappings depending on memory type */ + if(MemoryType == LoaderFirmwareTemporary) + { + /* Map EFI firmware code */ + Status = BlMapVirtualMemory(PageMap, (PVOID)Descriptor->PhysicalStart, + (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + } + else if(MemoryType != LoaderFree) + { + /* Add any non-free memory mapping */ + Status = BlMapVirtualMemory(PageMap, VirtualAddress, (PVOID)Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + + /* Calculate next valid virtual address */ + VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE; + } + else + { + /* Map all other memory as loader free */ + Status = BlMapVirtualMemory(PageMap, NULL, (PVOID)Descriptor->PhysicalStart, + Descriptor->NumberOfPages, LoaderFree); + } + + /* Make sure memory mapping succeeded */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping failed */ + return Status; + } + + /* Grab next descriptor */ + Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Adds a physical to virtual address mappings. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param VirtualAddress + * Supplies a virtual address where the physical address should be mapped. + * + * @param PhysicalAddress + * Supplies a physical address which will be mapped. + * + * @param NumberOfPages + * Supplies a number of pages that will be mapped. + * + * @param MemoryType + * Supplies the type of mapped memory that will be assigned to the memory descriptor. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlMapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType) +{ + PLOADER_MEMORY_MAPPING Mapping1, Mapping2, Mapping3; + PVOID PhysicalAddressEnd, PhysicalAddress2End; + PLIST_ENTRY ListEntry, MappingListEntry; + SIZE_T NumberOfMappedPages; + EFI_STATUS Status; + + /* Allocate memory for new mapping */ + Status = BlAllocateMemoryPool(sizeof(LOADER_MEMORY_MAPPING), (PVOID *)&Mapping1); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields */ + Mapping1->PhysicalAddress = PhysicalAddress; + Mapping1->VirtualAddress = VirtualAddress; + Mapping1->NumberOfPages = NumberOfPages; + Mapping1->MemoryType = MemoryType; + + /* Calculate the end of the physical address */ + PhysicalAddressEnd = (PUINT8)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1; + + /* Iterate through all the mappings already set to insert new mapping at the correct place */ + ListEntry = PageMap->MemoryMap.Flink; + while(ListEntry != &PageMap->MemoryMap) + { + /* Take a mapping from the list and calculate its end of physical address */ + Mapping2 = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry); + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1 ; + + /* Check if they overlap */ + if(PhysicalAddressEnd > Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Calculate number of pages for this mapping */ + NumberOfMappedPages = ((PUINT8)PhysicalAddress2End - (PUINT8)PhysicalAddressEnd) / EFI_PAGE_SIZE; + if(NumberOfMappedPages > 0) + { + /* Pages associated to the mapping, allocate memory for it */ + Status = BlAllocateMemoryPool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields and insert it on the top */ + Mapping3->PhysicalAddress = (PUINT8)PhysicalAddressEnd + 1; + Mapping3->VirtualAddress = NULL; + Mapping3->NumberOfPages = NumberOfMappedPages; + Mapping3->MemoryType = Mapping2->MemoryType; + RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); + } + + /* Calculate number of pages and the end of the physical address */ + Mapping2->NumberOfPages = ((PUINT8)PhysicalAddressEnd + 1 - + (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; + } + + /* Check if they overlap */ + if(Mapping1->PhysicalAddress > Mapping2->PhysicalAddress && Mapping1->PhysicalAddress < PhysicalAddress2End) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Calculate number of pages for this mapping */ + NumberOfMappedPages = ((PUINT8)PhysicalAddress2End + 1 - (PUINT8)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE; + if(NumberOfMappedPages > 0) + { + /* Pages associated to the mapping, allocate memory for it */ + Status = BlAllocateMemoryPool(sizeof(LOADER_MEMORY_MAPPING), (PVOID*)&Mapping3); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Set mapping fields and insert it on the top */ + Mapping3->PhysicalAddress = Mapping1->PhysicalAddress; + Mapping3->VirtualAddress = NULL; + Mapping3->NumberOfPages = NumberOfMappedPages; + Mapping3->MemoryType = Mapping2->MemoryType; + RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry); + } + + /* Calculate number of pages and the end of the physical address */ + Mapping2->NumberOfPages = ((PUINT8)Mapping1->PhysicalAddress - + (PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE; + PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1; + } + + /* Check if mapping is really needed */ + if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) || + (Mapping2->NumberOfPages == 0)) + { + /* Make sure it's memory type is LoaderFree */ + if(Mapping2->MemoryType != LoaderFree) + { + /* LoaderFree memory type is strictly expected */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Store address of the next mapping */ + MappingListEntry = ListEntry->Flink; + + /* Remove mapping from the list and free up it's memory */ + RtlRemoveEntryList(&Mapping2->ListEntry); + Status = BlFreeMemoryPool(Mapping2); + ListEntry = MappingListEntry; + + /* Go to the next mapping */ + continue; + } + + /* Determine physical address order */ + if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress) + { + /* Insert new mapping in front */ + RtlInsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry); + return STATUS_EFI_SUCCESS; + } + + /* Get next mapping from the list */ + ListEntry = ListEntry->Flink; + } + + /* Insert new mapping to the list */ + RtlInsertTailList(&PageMap->MemoryMap, &Mapping1->ListEntry); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Converts EFI memory type to XTLDR memory type. + * + * @param EfiMemoryType + * Specifies EFI memory type. + * + * @return This routine returns a mapped XTLDR memory type. + * + * @since XT 1.0 + */ +XTCDECL +LOADER_MEMORY_TYPE +BlpGetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType) +{ + LOADER_MEMORY_TYPE MemoryType; + + /* Check EFI memory type and convert to XTLDR memory type */ + switch(EfiMemoryType) + { + case EfiACPIMemoryNVS: + case EfiACPIReclaimMemory: + case EfiPalCode: + MemoryType = LoaderSpecialMemory; + break; + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + MemoryType = LoaderFirmwarePermanent; + break; + case EfiBootServicesData: + case EfiLoaderCode: + case EfiLoaderData: + MemoryType = LoaderFirmwareTemporary; + break; + case EfiUnusableMemory: + MemoryType = LoaderBad; + break; + default: + MemoryType = LoaderFree; + break; + } + + /* Return XTLDR memory type */ + return MemoryType; +} + +/** + * Returns next level of the Page Table. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param PageTable + * Supplies a pointer to the current Page Table. + * + * @param Entry + * Supplies an index of the current Page Table entry. + * + * @param NextPageTable + * Supplies a pointer to the memory area where the next Page Table level is returned. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpGetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, + IN PHARDWARE_PTE PageTable, + IN SIZE_T Entry, + OUT PHARDWARE_PTE *NextPageTable) +{ + EFI_PHYSICAL_ADDRESS Address; + ULONGLONG PmlPointer; + EFI_STATUS Status; + + /* Check if this is a valid table */ + if(PageTable[Entry].Valid) + { + /* Get PML pointer */ + PmlPointer = PageTable[Entry].PageFrameNumber; + PmlPointer <<= EFI_PAGE_SHIFT; + } + else + { + /* Allocate pages for new PML entry */ + Status = BlAllocateMemoryPages(1, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Add new memory mapping */ + Status = BlMapVirtualMemory(PageMap, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory mapping failure */ + return Status; + } + + /* Fill allocated memory with zeros */ + RtlZeroMemory((PVOID)(ULONGLONG)Address, EFI_PAGE_SIZE); + + /* Set paging entry settings */ + PageTable[Entry].PageFrameNumber = Address / EFI_PAGE_SIZE; + PageTable[Entry].Valid = 1; + PageTable[Entry].Write = 1; + PmlPointer = (ULONGLONG)Address; + } + + /* Set next Page Map Level (PML) */ + *NextPageTable = (PHARDWARE_PTE)(ULONGLONG)PmlPointer; + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/xtldr/protocol.c b/xtldr/protocol.c index ea43515..db62936 100644 --- a/xtldr/protocol.c +++ b/xtldr/protocol.c @@ -631,6 +631,10 @@ BlpInstallXtLoaderProtocol() BlpLdrProtocol.Memory.FreePages = BlFreeMemoryPages; BlpLdrProtocol.Memory.FreePool = BlFreeMemoryPool; BlpLdrProtocol.Memory.GetMemoryMap = BlGetMemoryMap; + BlpLdrProtocol.Memory.InitializePageMap = BlInitializePageMap; + BlpLdrProtocol.Memory.MapEfiMemory = BlMapEfiMemory; + BlpLdrProtocol.Memory.MapPage = BlMapPage; + BlpLdrProtocol.Memory.MapVirtualMemory = BlMapVirtualMemory; BlpLdrProtocol.Memory.SetMemory = RtlSetMemory; BlpLdrProtocol.Memory.ZeroMemory = RtlZeroMemory; BlpLdrProtocol.Protocol.Close = BlCloseProtocol;