From 5500192575925bc303b8f14d5b3660c5653e10f7 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 11 Jan 2026 23:14:10 +0100 Subject: [PATCH] Remove manual virtual address tracking from boot sequence --- boot/xtldr/modules/xtos_o/includes/xtos.hh | 8 +- boot/xtldr/modules/xtos_o/xtos.cc | 167 ++++++++++++++------- 2 files changed, 114 insertions(+), 61 deletions(-) diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index ea37111..e917d10 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -40,19 +40,17 @@ 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, OUT PLIST_ENTRY MemoryDescriptorList); STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, + OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, IN PXTBL_BOOT_PARAMETERS Parameters); STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir, IN PWCHAR FileName, - IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, + IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext); STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, @@ -60,6 +58,8 @@ class Xtos IN ULONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType, IN BOOLEAN KernelMapping); + STATIC XTCDECL PVOID PhysicalAddressToVirtual(PVOID PhysicalAddress); + STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead); STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir, IN PXTBL_BOOT_PARAMETERS Parameters); }; diff --git a/boot/xtldr/modules/xtos_o/xtos.cc b/boot/xtldr/modules/xtos_o/xtos.cc index e35331e..57d943b 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -191,7 +191,6 @@ Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource XTCDECL EFI_STATUS Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY MemoryDescriptorList) { EFI_PHYSICAL_ADDRESS Address; @@ -206,7 +205,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); + Status = MapMemory(PageMap, Address, Pages, LoaderMemoryData, TRUE); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -214,13 +213,14 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, } PVOID PhysicalBase = (PVOID)Address; + PVOID CurrentDescriptor = PhysicalBase; PLIST_ENTRY ListEntry; ListEntry = PageMap->MemoryMap.Flink; while(ListEntry != &PageMap->MemoryMap) { PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry); - PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; + PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)CurrentDescriptor; MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; @@ -228,11 +228,12 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); - Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); + CurrentDescriptor = (PUINT8)CurrentDescriptor + sizeof(LOADER_MEMORY_DESCRIPTOR); ListEntry = ListEntry->Flink; } - XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); + XtLdrProtocol->Debug.Print(L"Address: %llX, Pages: %llu\n", (ULONGLONG)PhysicalBase, Pages); + PhysicalListToVirtual(MemoryDescriptorList); return STATUS_EFI_SUCCESS; } @@ -240,7 +241,6 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, OUT PLIST_ENTRY SystemResourcesList) { XTSTATUS Status; @@ -257,7 +257,6 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, 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)); @@ -267,19 +266,13 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderFirmwarePermanent); + Status = MapMemory(PageMap, Address, Pages, LoaderFirmwarePermanent, TRUE); 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; XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI)); @@ -295,7 +288,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); /* Get APIC and XSDP/RSDP addresses */ - AcpiProtocol->GetApicBase(&AcpiResource->ApicBase); + AcpiProtocol->GetApicBase((PVOID *)&AcpiResource->ApicBase); AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress); /* No need to map ACPI */ @@ -334,21 +327,19 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize); /* Rewrite framebuffer address by using virtual address */ - FrameBufferResource->Header.VirtualAddress = *VirtualAddress; + FrameBufferResource->Header.VirtualAddress = PhysicalAddressToVirtual(FrameBufferResource->Header.PhysicalAddress); /* Map frame buffer memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress, (ULONGLONG)FrameBufferResource->Header.PhysicalAddress, - FrameBufferPages, LoaderFirmwarePermanent); + FrameBufferPages, LoaderHardwareCachedMemory); /* Close FrameBuffer protocol */ 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); + PhysicalListToVirtual(SystemResourcesList); return STATUS_EFI_SUCCESS; } @@ -370,7 +361,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; EFI_HANDLE ProtocolHandle; - PVOID ApicBaseAddress; + EFI_PHYSICAL_ADDRESS ApicBaseAddress; EFI_STATUS Status; /* Open ACPI protocol */ @@ -382,7 +373,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Get APIC base address */ - Status = AcpiProtocol->GetApicBase(&ApicBaseAddress); + Status = AcpiProtocol->GetApicBase((PVOID *)&ApicBaseAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get APIC base address */ @@ -390,7 +381,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Map APIC base address */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } @@ -410,7 +401,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) XTCDECL EFI_STATUS Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, + OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, IN PXTBL_BOOT_PARAMETERS Parameters) { PKERNEL_INITIALIZATION_BLOCK LoaderBlock; @@ -418,6 +409,7 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, EFI_STATUS Status; UINT BlockPages; UINT ParametersSize; + ULONGLONG LoaderBlockVa; /* Calculate size of parameters */ ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR); @@ -450,25 +442,29 @@ Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, // LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision; LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR; + /* Get the KSEG0-based virtual address for the loader block */ + LoaderBlockVa = (ULONGLONG)PhysicalAddressToVirtual(LoaderBlock); + *KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)LoaderBlockVa; + /* Copy parameters to kernel initialization block */ - LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK)); + LoaderBlock->KernelParameters = (PWCHAR)(LoaderBlockVa + sizeof(KERNEL_INITIALIZATION_BLOCK)); XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)), 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); + Status = MapMemory(PageMap, (ULONGLONG)LoaderBlock, BlockPages, LoaderSystemBlock, TRUE); + if(Status != STATUS_EFI_SUCCESS) + { + return Status; + } XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead); - GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); + GetSystemResourcesList(PageMap, &LoaderBlock->SystemResourcesListHead); /* Initialize memory descriptor list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); - GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); + GetMemoryDescriptorList(PageMap, &LoaderBlock->MemoryDescriptorListHead); /* Return success */ return STATUS_EFI_SUCCESS; @@ -526,8 +522,8 @@ XTCDECL EFI_STATUS Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, IN PWCHAR FileName, - IN PVOID VirtualAddress, IN LOADER_MEMORY_TYPE MemoryType, + IN OUT PXTBL_PAGE_MAPPING PageMap, OUT PPECOFF_IMAGE_CONTEXT *ImageContext) { PEFI_FILE_HANDLE ModuleHandle; @@ -585,9 +581,22 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n"); } + /* Ensure that page map is provided */ + if(PageMap != NULLPTR) + { + /* Add kernel image memory mapping */ + Status = MapMemory(PageMap, (ULONGLONG)(*ImageContext)->PhysicalAddress, + (*ImageContext)->ImagePages, LoaderSystemCode, TRUE); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to map kernel image memory */ + return Status; + } + } + /* Print debug message */ - XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, - (*ImageContext)->PhysicalAddress, KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); + XtLdrProtocol->Debug.Print(L"Loaded '%S' at PA: %P, VA: %P\n", FileName, (*ImageContext)->PhysicalAddress, + KSEG0_BASE + (ULONGLONG)(*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; @@ -641,6 +650,69 @@ Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, return XtLdrProtocol->Memory.MapVirtualMemory(PageMap, BaseAddress + Address, Address, NumberOfPages, MemoryType); } +/** + * Converts physical address to virtual address. + * + * @param PhysicalAddress + * Specifies physical address that will be converted to virtual address. + * + * @return This routine returns a mapped virtual address. + * + * @since XT 1.0 + */ +XTCDECL +PVOID +Xtos::PhysicalAddressToVirtual(PVOID PhysicalAddress) +{ + return (PVOID)((ULONG_PTR)PhysicalAddress | KSEG0_BASE); +} + +/** + * Converts whole linked list addressing from physical to virtual for future use after enabling paging. + * + * @param ListHead + * Supplies a pointer to a structure that serves as the list header. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::PhysicalListToVirtual(IN OUT PLIST_ENTRY ListHead) +{ + PLIST_ENTRY ListEntry, NextEntry; + + /* Make sure list is properly initialized */ + if(ListHead->Flink == 0 || ListHead->Blink == 0) + { + /* List not initialized, return error code */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Iterate through the list */ + ListEntry = ListHead->Flink; + while(ListEntry != ListHead) + { + /* Store the next entry */ + NextEntry = ListEntry->Flink; + + /* Convert the list entry */ + ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink); + ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink); + + /* Get the next element */ + ListEntry = NextEntry; + } + + /* Convert the list head */ + ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink); + ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * This routine initiates an XTOS boot sequence. * @@ -665,7 +737,6 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol; PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR; PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; - PVOID VirtualAddress, VirtualMemoryArea; PXT_ENTRY_POINT KernelEntryPoint; EFI_HANDLE ProtocolHandle; EFI_STATUS Status; @@ -686,13 +757,10 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); - /* Set base virtual memory area for the kernel mappings */ - VirtualMemoryArea = (PVOID)KSEG0_BASE; - VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE); - /* Initialize virtual memory mappings */ XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K); + PVOID VirtualMemoryArea = (PVOID)KSEG0_BASE; Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { @@ -700,25 +768,13 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, } /* Load the kernel */ - Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); + Status = LoadModule(BootDir, Parameters->KernelFile, LoaderSystemCode, &PageMap, &ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load the kernel */ return Status; } - /* Add kernel image memory mapping */ - Status = MapMemory(&PageMap, (ULONGLONG)ImageContext->PhysicalAddress, - ImageContext->ImagePages, LoaderSystemCode, TRUE); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to map kernel image memory */ - return Status; - } - - /* Set next valid virtual address right after the kernel */ - VirtualAddress = (PUINT8)VirtualAddress + (ImageContext->ImagePages * EFI_PAGE_SIZE); - /* Find and map APIC base address */ Status = InitializeApicBase(&PageMap); if(Status != STATUS_EFI_SUCCESS) @@ -728,11 +784,8 @@ Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, return Status; } - /* Store virtual address of kernel initialization block for future kernel call */ - KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress; - /* Setup and map kernel initialization block */ - Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); + Status = InitializeLoaderBlock(&PageMap, &KernelParameters, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */