diff --git a/boot/xtldr/includes/xtldr.hh b/boot/xtldr/includes/xtldr.hh index 8d8101c..cb91068 100644 --- a/boot/xtldr/includes/xtldr.hh +++ b/boot/xtldr/includes/xtldr.hh @@ -168,7 +168,6 @@ class Memory STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages, IN EFI_PHYSICAL_ADDRESS Memory); STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory); - STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL VOID GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap, OUT PULONG NumberOfMappings); STATIC XTCDECL EFI_STATUS GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap); @@ -178,7 +177,8 @@ class Memory IN SHORT PageMapLevel, IN PAGE_SIZE PageSize); STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR BaseAddress); + IN OUT PVOID *MemoryMapAddress, + IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, @@ -188,15 +188,20 @@ class Memory IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); + STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress, + IN PVOID PhysicalBase, + IN PVOID VirtualBase); + STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, + IN OUT PLIST_ENTRY ListHead, + IN PVOID PhysicalBase, + IN PVOID VirtualBase); private: + STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL EFI_STATUS GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, IN PVOID PageTable, IN SIZE_T Entry, OUT PVOID *NextPageTable); - STATIC XTCDECL EFI_STATUS MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PEFI_MEMORY_DESCRIPTOR Descriptor, - IN ULONG_PTR BaseAddress); STATIC XTCDECL EFI_STATUS SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR SelfMapAddress); }; diff --git a/boot/xtldr/memory.cc b/boot/xtldr/memory.cc index c0ad17f..6591833 100644 --- a/boot/xtldr/memory.cc +++ b/boot/xtldr/memory.cc @@ -4,7 +4,6 @@ * FILE: xtldr/memory.cc * DESCRIPTION: XT Boot Loader memory management * DEVELOPERS: Rafal Kupiec - * Aiken Harris */ #include @@ -309,69 +308,17 @@ Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap, PageMap->PageSize = PageSize; } -/** - * Maps memory descriptor to the page mapping structure. - * - * @param PageMap - * Supplies a pointer to the page mapping structure. - * - * @param Descriptor - * Supplies a pointer to EFI memory descriptor, which will be mapped. - * - * @param BaseAddress - * Supplies a base address, where EFI memory will be mapped. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Memory::MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN PEFI_MEMORY_DESCRIPTOR Descriptor, - IN ULONG_PTR BaseAddress) -{ - LOADER_MEMORY_TYPE MemoryType; - - /* Skip EFI reserved memory */ - if(Descriptor->Type == EfiReservedMemoryType) - { - /* Skip EFI reserved memory */ - return STATUS_EFI_SUCCESS; - } - - /* Convert EFI memory type into XTLDR memory type */ - MemoryType = Memory::GetLoaderMemoryType((EFI_MEMORY_TYPE)Descriptor->Type); - - /* Do memory mappings depending on memory type */ - if(MemoryType == LoaderFirmwareTemporary) - { - /* Map EFI firmware code */ - return Memory::MapVirtualMemory(PageMap, Descriptor->PhysicalStart, - Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); - } - else if(MemoryType != LoaderFree) - { - /* Add any non-free memory mappings based on provided base address */ - return Memory::MapVirtualMemory(PageMap, (BaseAddress | Descriptor->PhysicalStart), Descriptor->PhysicalStart, - Descriptor->NumberOfPages, MemoryType); - } - else - { - /* Map all other memory as loader free */ - return Memory::MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, - Descriptor->NumberOfPages, LoaderFree); - } -} - /** * Adds EFI memory mapping to the page mapping structure. * * @param PageMap * Supplies a pointer to the page mapping structure. * - * @param BaseAddress - * Supplies a base address, where EFI memory will be mapped. + * @param MemoryMapAddress + * Supplies a virtual address, where EFI memory will be mapped. + * + * @param GetMemoryTypeRoutine + * Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type. * * @return This routine returns a status code. * @@ -380,15 +327,27 @@ Memory::MapDescriptor(IN OUT PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONG_PTR BaseAddress) + IN OUT PVOID *MemoryMapAddress, + IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine) { + ULONGLONG MaxAddress, VirtualAddress; PEFI_MEMORY_DESCRIPTOR Descriptor; + LOADER_MEMORY_TYPE MemoryType; PEFI_MEMORY_MAP MemoryMap; SIZE_T DescriptorCount; - ULONGLONG MaxAddress; EFI_STATUS Status; SIZE_T Index; + /* Set virtual address as specified in argument */ + VirtualAddress = (ULONGLONG)*MemoryMapAddress; + + /* Check if custom memory type routine is specified */ + if(GetMemoryTypeRoutine == NULLPTR) + { + /* Use default memory type routine */ + GetMemoryTypeRoutine = GetLoaderMemoryType; + } + /* Allocate and zero-fill buffer for EFI memory map */ AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap); RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP)); @@ -434,17 +393,49 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Check if memory descriptor exceeds the lowest physical page */ if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MaxAddress) { - /* Truncate memory descriptor to maximum supported address */ + /* Truncate memory descriptor to the lowest supported physical page */ Descriptor->NumberOfPages = (((ULONGLONG)MaxAddress) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT; } } - /* Map this descriptor and make sure it succeeded */ - Status = MapDescriptor(PageMap, Descriptor, BaseAddress); - if(Status != STATUS_EFI_SUCCESS) { - /* Mapping failed */ - return Status; + /* Skip EFI reserved memory */ + if(Descriptor->Type == EfiReservedMemoryType) + { + /* Go to the next descriptor */ + Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize); + continue; + } + + /* Convert EFI memory type into XTLDR memory type */ + MemoryType = GetMemoryTypeRoutine((EFI_MEMORY_TYPE)Descriptor->Type); + + /* Do memory mappings depending on memory type */ + if(MemoryType == LoaderFirmwareTemporary) + { + /* Map EFI firmware code */ + Status = MapVirtualMemory(PageMap, Descriptor->PhysicalStart, + Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType); + } + else if(MemoryType != LoaderFree) + { + /* Add any non-free memory mapping */ + Status = MapVirtualMemory(PageMap, VirtualAddress, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, MemoryType); + } + else + { + /* Map all other memory as loader free */ + Status = MapVirtualMemory(PageMap, (ULONGLONG)NULLPTR, Descriptor->PhysicalStart, + Descriptor->NumberOfPages, LoaderFree); + } + + /* Make sure memory mapping succeeded */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Mapping failed */ + return Status; + } } /* Grab next descriptor */ @@ -468,6 +459,7 @@ Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, } /* Store next valid virtual address and return success */ + *MemoryMapAddress = (PVOID)VirtualAddress; return STATUS_EFI_SUCCESS; } @@ -657,3 +649,105 @@ Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, /* Return success */ return STATUS_EFI_SUCCESS; } + +/** + * Converts physical address to virtual address based on physical base and virtual base. + * + * @param PhysicalAddress + * Specifies physical address that will be converted to virtual address. + * + * @param PhysicalBase + * Supplies a physical base address. + * + * @param VirtualBase + * Supplies a virtual base address. + * + * @return This routine returns a mapped virtual address. + * + * @since XT 1.0 + */ +XTCDECL +PVOID +Memory::PhysicalAddressToVirtual(IN PVOID PhysicalAddress, + IN PVOID PhysicalBase, + IN PVOID VirtualBase) +{ + /* Convert physical address to virtual address */ + return (PUCHAR)VirtualBase + ((PUCHAR)PhysicalAddress - (PUCHAR)PhysicalBase); +} + +/** + * Converts whole linked list addressing from physical to virtual for future use after enabling paging. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @param ListHead + * Supplies a pointer to a structure that serves as the list header. + * + * @param PhysicalBase + * Supplies a physical base address. + * + * @param VirtualBase + * Supplies a virtual base address. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Memory::PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap, + IN OUT PLIST_ENTRY ListHead, + IN PVOID PhysicalBase, + IN PVOID VirtualBase) +{ + 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 all elements */ + ListEntry = ListHead->Flink; + while(ListEntry != ListHead) + { + /* Save physical address of the next element */ + NextEntry = ListEntry->Flink; + + /* Convert the address of this element to VirtualAddress */ + if(ListEntry->Blink == ListHead) + { + /* Find virtual address of list head */ + ListEntry->Blink = (PLIST_ENTRY)GetVirtualAddress(PageMap, ListEntry->Blink); + } + else + { + /* Convert list entry */ + ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink, (PVOID)PhysicalBase, VirtualBase); + } + if(ListEntry->Flink == ListHead) + { + /* Convert list head */ + ListEntry->Flink = ListHead->Flink->Blink; + } + else + { + /* Convert list entry */ + ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink, (PVOID)PhysicalBase, VirtualBase); + } + + /* Get to the next element*/ + ListEntry = NextEntry; + } + + /* Convert list head */ + ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink, (PVOID)PhysicalBase, VirtualBase); + ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink, (PVOID)PhysicalBase, VirtualBase); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} diff --git a/boot/xtldr/modules/xtos_o/amd64/memory.cc b/boot/xtldr/modules/xtos_o/amd64/memory.cc index c5afa07..02335aa 100644 --- a/boot/xtldr/modules/xtos_o/amd64/memory.cc +++ b/boot/xtldr/modules/xtos_o/amd64/memory.cc @@ -156,20 +156,6 @@ Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) return STATUS_EFI_SUCCESS; } -/** - * Returns the base address of the memory mapping. - * - * @return This routine returns the base address of the memory mapping. - * - * @since XT 1.0 - */ -XTCDECL -ULONG_PTR -Xtos::GetBaseMappingAddress(VOID) -{ - return KSEG0_BASE; -} - /** * Maps the page table for hardware layer addess space. * diff --git a/boot/xtldr/modules/xtos_o/i686/memory.cc b/boot/xtldr/modules/xtos_o/i686/memory.cc index 08cf608..44ee233 100644 --- a/boot/xtldr/modules/xtos_o/i686/memory.cc +++ b/boot/xtldr/modules/xtos_o/i686/memory.cc @@ -44,20 +44,6 @@ Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) return 2; } -/** - * Returns the base address of the memory mapping. - * - * @return This routine returns the base address of the memory mapping. - * - * @since XT 1.0 - */ -XTCDECL -ULONG_PTR -Xtos::GetBaseMappingAddress(VOID) -{ - return KSEG0_BASE; -} - /** * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. * diff --git a/boot/xtldr/modules/xtos_o/includes/xtos.hh b/boot/xtldr/modules/xtos_o/includes/xtos.hh index 8d4b31e..4d70606 100644 --- a/boot/xtldr/modules/xtos_o/includes/xtos.hh +++ b/boot/xtldr/modules/xtos_o/includes/xtos.hh @@ -33,34 +33,44 @@ class Xtos IN PEFI_SYSTEM_TABLE SystemTable); private: + STATIC XTCDECL EFI_STATUS AddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, + IN PVOID VirtualAddress, + IN PVOID PhysicalAddress, + IN UINT NumberOfPages, + IN LOADER_MEMORY_TYPE MemoryType); + STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters); STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap); - STATIC XTCDECL ULONG_PTR GetBaseMappingAddress(VOID); STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, 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 GetVirtualAddress(IN PLIST_ENTRY MemoryMappings, + IN PVOID PhysicalAddress, + OUT PVOID *VirtualAddress); STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, + IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters); + STATIC XTCDECL EFI_STATUS InitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, + IN OUT PVOID *MemoryMapAddress); 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, - IN ULONGLONG Address, - 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 MapVirtualMemory(IN PLIST_ENTRY MemoryMappings, + IN UINT_PTR VirtualAddress, + IN UINT_PTR PhysicalAddress, + IN UINT NumberOfPages, + IN OUT PVOID *PtePointer); 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 2edc751..3482003 100644 --- a/boot/xtldr/modules/xtos_o/xtos.cc +++ b/boot/xtldr/modules/xtos_o/xtos.cc @@ -191,6 +191,7 @@ 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; @@ -205,7 +206,7 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, return Status; } - Status = MapMemory(PageMap, Address, Pages, LoaderMemoryData, TRUE); + Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, Address, Pages, LoaderMemoryData); if(Status != STATUS_EFI_SUCCESS) { XtLdrProtocol->Memory.FreePages(Address, Pages); @@ -213,14 +214,13 @@ 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)CurrentDescriptor; + PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address; MemoryDescriptor->MemoryType = MemoryMapping->MemoryType; MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE; @@ -228,11 +228,11 @@ Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry); - CurrentDescriptor = (PUINT8)CurrentDescriptor + sizeof(LOADER_MEMORY_DESCRIPTOR); + Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR); ListEntry = ListEntry->Flink; } - PhysicalListToVirtual(MemoryDescriptorList); + XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress); return STATUS_EFI_SUCCESS; } @@ -240,6 +240,7 @@ 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; @@ -256,6 +257,7 @@ 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)); @@ -264,14 +266,19 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, { return Status; } - - Status = MapMemory(PageMap, Address, Pages, LoaderFirmwarePermanent, TRUE); + 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; XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI)); @@ -287,7 +294,7 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI); /* Get APIC and XSDP/RSDP addresses */ - AcpiProtocol->GetApicBase((PVOID *)&AcpiResource->ApicBase); + AcpiProtocol->GetApicBase(&AcpiResource->ApicBase); AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress); /* No need to map ACPI */ @@ -326,19 +333,21 @@ Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize); /* Rewrite framebuffer address by using virtual address */ - FrameBufferResource->Header.VirtualAddress = PhysicalAddressToVirtual(FrameBufferResource->Header.PhysicalAddress); + FrameBufferResource->Header.VirtualAddress = *VirtualAddress; /* Map frame buffer memory */ XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)FrameBufferResource->Header.VirtualAddress, (ULONGLONG)FrameBufferResource->Header.PhysicalAddress, - FrameBufferPages, LoaderHardwareCachedMemory); + FrameBufferPages, LoaderFirmwarePermanent); /* Close FrameBuffer protocol */ XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); + *VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE); + XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry); - PhysicalListToVirtual(SystemResourcesList); + XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, PhysicalBase, VirtualBase); return STATUS_EFI_SUCCESS; } @@ -360,7 +369,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; EFI_HANDLE ProtocolHandle; - EFI_PHYSICAL_ADDRESS ApicBaseAddress; + PVOID ApicBaseAddress; EFI_STATUS Status; /* Open ACPI protocol */ @@ -372,7 +381,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Get APIC base address */ - Status = AcpiProtocol->GetApicBase((PVOID *)&ApicBaseAddress); + Status = AcpiProtocol->GetApicBase(&ApicBaseAddress); if(Status != STATUS_EFI_SUCCESS) { /* Failed to get APIC base address */ @@ -380,21 +389,18 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) } /* Map APIC base address */ - XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent); + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, APIC_BASE, (ULONGLONG)ApicBaseAddress, 1, LoaderFirmwarePermanent); return STATUS_EFI_SUCCESS; } /** * Initializes and maps the kernel initialization block. * - * @param PageMap - * Supplies a pointer to the page map. + * @param MemoryMappings + * Supplies a pointer to linked list containing all memory mappings. * - * @param KernelParameters - * Returns a pointer to the kernel initialization block. - * - * @param Parameters - * Supplies a list of input parameters passed to the kernel. + * @param VirtualAddress + * Supplies a pointer to the next valid, free and available virtual address. * * @return This routine returns a status code. * @@ -403,7 +409,7 @@ Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) XTCDECL EFI_STATUS Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - OUT PKERNEL_INITIALIZATION_BLOCK *KernelParameters, + IN PVOID *VirtualAddress, IN PXTBL_BOOT_PARAMETERS Parameters) { PKERNEL_INITIALIZATION_BLOCK LoaderBlock; @@ -411,7 +417,6 @@ 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); @@ -444,29 +449,25 @@ 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)(LoaderBlockVa + sizeof(KERNEL_INITIALIZATION_BLOCK)); + LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK)); XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)), Parameters->Parameters, ParametersSize); /* Map kernel initialization block */ - Status = MapMemory(PageMap, (ULONGLONG)LoaderBlock, BlockPages, LoaderSystemBlock, TRUE); - if(Status != STATUS_EFI_SUCCESS) - { - return Status; - } + XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (ULONGLONG)*VirtualAddress, (ULONGLONG)LoaderBlock, + BlockPages, LoaderSystemBlock); + + /* Calculate next valid virtual address */ + *VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE); XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead); - GetSystemResourcesList(PageMap, &LoaderBlock->SystemResourcesListHead); + GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); /* Initialize memory descriptor list */ XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead); - GetMemoryDescriptorList(PageMap, &LoaderBlock->MemoryDescriptorListHead); + GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); /* Return success */ return STATUS_EFI_SUCCESS; @@ -507,12 +508,12 @@ Xtos::InitializeModule(IN EFI_HANDLE ImageHandle, * @param FileName * An on disk filename of the module that will be loaded. * + * @param VirtualAddress + * Optional virtual address pointing to the memory area where PE/COFF file will be loaded. + * * @param MemoryType * Supplies the type of memory to be assigned to the memory descriptor. * - * @param PageMap - * Supplies pointer to the memory area where memory mappings will be stored. - * * @param ImageContext * Supplies pointer to the memory area where loaded PE/COFF image context will be stored. * @@ -524,8 +525,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; @@ -544,8 +545,8 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } - /* Load the PE/COFF image file into memory */ - Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, NULLPTR, (PVOID*)ImageContext); + /* Load the PE/COFF image file */ + Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ @@ -553,15 +554,6 @@ Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, return Status; } - /* Relocate the PE/COFF image file */ - Status = PeCoffProtocol->RelocateImage(*ImageContext, GetBaseMappingAddress() | (ULONGLONG)(*ImageContext)->PhysicalAddress); - if(Status != STATUS_EFI_SUCCESS) - { - /* Unable to relocate the file */ - XtLdrProtocol->Debug.Print(L"ERROR: Failed to relocate '%S'\n", FileName); - return Status; - } - /* Close image file */ ModuleHandle->Close(ModuleHandle); @@ -583,133 +575,9 @@ 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, - PhysicalAddressToVirtual((*ImageContext)->VirtualAddress)); - - /* Return success */ - return STATUS_EFI_SUCCESS; -} - -/** - * Adds a physical to virtual address mapping. - * - * @param PageMap - * Supplies a pointer to the page mapping structure. - * - * @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. - * - * @param KernelMapping - * Supplies a flag that indicates if mapping should be done in kernel mode or if identity mapping should be used. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -Xtos::MapMemory(IN OUT PXTBL_PAGE_MAPPING PageMap, - IN ULONGLONG Address, - IN ULONG NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType, - IN BOOLEAN KernelMapping) -{ - ULONGLONG BaseAddress; - - /* Check if kernel mode mapping */ - if(KernelMapping) - { - /* Map memory based on kernel base address */ - BaseAddress = GetBaseMappingAddress(); - } - else - { - /* Use identity mapping */ - BaseAddress = (ULONGLONG)NULLPTR; - } - - /* Map memory and return status code */ - 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 | GetBaseMappingAddress()); -} - -/** - * 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); + XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName, + (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); /* Return success */ return STATUS_EFI_SUCCESS; @@ -739,6 +607,7 @@ 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; @@ -759,23 +628,39 @@ 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); - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, GetBaseMappingAddress()); + Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); if(Status != STATUS_EFI_SUCCESS) { return Status; } /* Load the kernel */ - Status = LoadModule(BootDir, Parameters->KernelFile, LoaderSystemCode, &PageMap, &ImageContext); + Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Failed to load the kernel */ return Status; } + /* Add kernel image memory mapping */ + Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, (ULONGLONG)ImageContext->VirtualAddress, + (ULONGLONG)ImageContext->PhysicalAddress, ImageContext->ImagePages, + LoaderSystemCode); + if(Status != STATUS_EFI_SUCCESS) + { + 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) @@ -785,8 +670,11 @@ 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, &KernelParameters, Parameters); + Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); if(Status != STATUS_EFI_SUCCESS) { /* Failed to setup kernel initialization block */ diff --git a/boot/xtldr/protocol.cc b/boot/xtldr/protocol.cc index e8221d0..6593e4a 100644 --- a/boot/xtldr/protocol.cc +++ b/boot/xtldr/protocol.cc @@ -1066,6 +1066,8 @@ Protocol::InstallXtLoaderProtocol() LoaderProtocol.Memory.MapPage = Memory::MapPage; LoaderProtocol.Memory.MapVirtualMemory = Memory::MapVirtualMemory; LoaderProtocol.Memory.MoveMemory = RTL::Memory::MoveMemory; + LoaderProtocol.Memory.PhysicalAddressToVirtual = Memory::PhysicalAddressToVirtual; + LoaderProtocol.Memory.PhysicalListToVirtual = Memory::PhysicalListToVirtual; LoaderProtocol.Memory.SetMemory = RTL::Memory::SetMemory; LoaderProtocol.Memory.ZeroMemory = RTL::Memory::ZeroMemory; LoaderProtocol.Protocol.Close = CloseProtocol; diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index ccb7d9d..1299161 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -108,6 +108,9 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0xFFFFF80000000000 +/* XTOS Kernel address base */ +#define KSEG0_KERNEL_BASE 0x0000000800000000 + /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x8000 diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 1851c8a..1f7f948 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -100,19 +100,21 @@ typedef VOID (XTCDECL *PBL_LLIST_INITIALIZE_HEAD)(IN PLIST_ENTRY ListHead); typedef VOID (XTCDECL *PBL_LLIST_INSERT_HEAD)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_INSERT_TAIL)(IN OUT PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry); typedef VOID (XTCDECL *PBL_LLIST_REMOVE_ENTRY)(IN PLIST_ENTRY Entry); -typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONG_PTR BaseAddress); +typedef EFI_STATUS (XTCDECL *PBL_MAP_EFI_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN OUT PVOID *MemoryMapAddress, IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine); typedef EFI_STATUS (XTCDECL *PBL_MAP_PAGE)(IN PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages); typedef EFI_STATUS (XTCDECL *PBL_MAP_VIRTUAL_MEMORY)(IN OUT PXTBL_PAGE_MAPPING PageMap, IN ULONGLONG VirtualAddress, IN ULONGLONG PhysicalAddress, IN ULONGLONG NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType); typedef VOID (XTAPI *PBL_MOVE_MEMORY)(IN OUT PVOID Destination, IN PCVOID Source, IN SIZE_T Length); typedef EFI_STATUS (XTCDECL *PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL)(OUT PEFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); typedef EFI_STATUS (XTCDECL *PBL_OPEN_PROTOCOL_HANDLE)(IN EFI_HANDLE Handle, OUT PVOID *ProtocolHandler, IN PEFI_GUID ProtocolGuid); +typedef PVOID (XTCDECL *PBL_PHYSICAL_ADDRESS_TO_VIRTUAL)(IN PVOID PhysicalAddress, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef UCHAR (XTCDECL *PBL_IOPORT_READ_8)(IN USHORT Port); typedef USHORT (XTCDECL *PBL_IOPORT_READ_16)(IN USHORT Port); typedef ULONG (XTCDECL *PBL_IOPORT_READ_32)(IN USHORT Port); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_8)(IN USHORT Port, IN UCHAR Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_16)(IN USHORT Port, IN USHORT Value); typedef VOID (XTCDECL *PBL_IOPORT_WRITE_32)(IN USHORT Port, IN ULONG Value); +typedef EFI_STATUS (XTCDECL *PBL_PHYSICAL_LIST_TO_VIRTUAL)(IN PXTBL_PAGE_MAPPING PageMap, IN OUT PLIST_ENTRY ListHead, IN PVOID PhysicalBase, IN PVOID VirtualBase); typedef EFI_STATUS (XTCDECL *PBL_POWER_SYSTEM)(); typedef EFI_STATUS (XTCDECL *PBL_READ_FILE)(IN PEFI_FILE_HANDLE DirHandle, IN PCWSTR FileName, OUT PVOID *FileData, OUT PSIZE_T FileSize); typedef EFI_STATUS (XTCDECL *PBL_REGISTER_BOOT_PROTOCOL)(IN PCWSTR SystemType, IN PEFI_GUID BootProtocolGuid); @@ -459,6 +461,8 @@ typedef struct _XTBL_LOADER_PROTOCOL PBL_MAP_PAGE MapPage; PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory; PBL_MOVE_MEMORY MoveMemory; + PBL_PHYSICAL_ADDRESS_TO_VIRTUAL PhysicalAddressToVirtual; + PBL_PHYSICAL_LIST_TO_VIRTUAL PhysicalListToVirtual; PBL_SET_MEMORY SetMemory; PBL_ZERO_MEMORY ZeroMemory; } Memory; diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index 32697c4..f62ff74 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -128,6 +128,9 @@ /* Static Kernel-Mode address start */ #define KSEG0_BASE 0x80000000 +/* XTOS Kernel address base */ +#define KSEG0_KERNEL_BASE 0x01800000 + /* XTOS Kernel stack size */ #define KERNEL_STACK_SIZE 0x4000