diff --git a/xtldr/modules/xtos_o/CMakeLists.txt b/xtldr/modules/xtos_o/CMakeLists.txt index 57bda16..b292deb 100644 --- a/xtldr/modules/xtos_o/CMakeLists.txt +++ b/xtldr/modules/xtos_o/CMakeLists.txt @@ -8,8 +8,9 @@ include_directories( # Specify list of source code files list(APPEND XTLDR_XTOS_O_SOURCE - ${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.c - ${XTLDR_XTOS_O_SOURCE_DIR}/xtos.c) + ${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.cc + ${XTLDR_XTOS_O_SOURCE_DIR}/data.cc + ${XTLDR_XTOS_O_SOURCE_DIR}/xtos.cc) # Link bootloader executable add_executable(xtos_o ${XTLDR_XTOS_O_SOURCE}) diff --git a/xtldr/modules/xtos_o/amd64/memory.c b/xtldr/modules/xtos_o/amd64/memory.cc similarity index 96% rename from xtldr/modules/xtos_o/amd64/memory.c rename to xtldr/modules/xtos_o/amd64/memory.cc index 55f8ec8..82c1ba0 100644 --- a/xtldr/modules/xtos_o/amd64/memory.c +++ b/xtldr/modules/xtos_o/amd64/memory.cc @@ -1,13 +1,13 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/amd64/memory.c + * FILE: xtldr/amd64/memory.cc * DESCRIPTION: EFI memory management for AMD64 target * DEVELOPERS: Rafal Kupiec * Aiken Harris */ -#include +#include /** @@ -22,7 +22,7 @@ */ XTCDECL ULONG -XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) +Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) { CPUID_REGISTERS CpuRegisters; @@ -56,6 +56,99 @@ XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) return 4; } +/** + * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TrampolineAddress; + PXT_TRAMPOLINE_ENTRY TrampolineEntry; + ULONG_PTR TrampolineSize; + + /* 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) + { + /* Set the address of the trampoline code below 1MB */ + TrampolineAddress = MM_TRAMPOLINE_ADDRESS; + + /* Calculate the size of the trampoline code */ + TrampolineSize = (ULONG_PTR)ArEnableExtendedPhysicalAddressingEnd - (ULONG_PTR)ArEnableExtendedPhysicalAddressing; + + /* Allocate pages for the trampoline */ + Status = XtLdrProtocol->Memory.AllocatePages(AllocateAddress, EFI_SIZE_TO_PAGES(TrampolineSize), &TrampolineAddress); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory for trampoline code */ + XtLdrProtocol->Debug.Print(L"Failed to allocate memory for trampoline code (Status code: %zX)\n", Status); + return Status; + } + + /* Set the trampoline entry point and copy its code into the allocated buffer */ + TrampolineEntry = (PXT_TRAMPOLINE_ENTRY)(UINT_PTR)TrampolineAddress; + RtlCopyMemory((PVOID)TrampolineEntry, (PVOID)ArEnableExtendedPhysicalAddressing, TrampolineSize); + } + + /* Exit EFI Boot Services */ + XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); + Status = XtLdrProtocol->Util.ExitBootServices(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to exit boot services */ + XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); + return STATUS_EFI_ABORTED; + } + + /* Check the configured page map level to set the LA57 state accordingly */ + if(PageMap->PageMapLevel == 5) + { + /* Enable Linear Address 57-bit (LA57) extension */ + XtLdrProtocol->Debug.Print(L"Enabling Linear Address 57-bit (LA57)\n"); + + /* Execute the trampoline to enable LA57 and write PML5 to CR3 */ + TrampolineEntry((UINT64)PageMap->PtePointer); + } + else + { + /* Disable Linear Address 57-bit (LA57) extension */ + XtLdrProtocol->Debug.Print(L"Disabling Linear Address 57-bit (LA57)\n"); + + /* Write PML4 to CR3 and enable paging */ + ArWriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); + ArWriteControlRegister(0, ArReadControlRegister(0) | CR0_PG); + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Maps the page table for hardware layer addess space. * @@ -68,7 +161,7 @@ XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) */ XTCDECL EFI_STATUS -XtpMapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) +Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) { PHARDWARE_PTE P5eBase, PdeBase, PpeBase, PxeBase; EFI_PHYSICAL_ADDRESS Address; @@ -196,96 +289,3 @@ XtpMapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) /* 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 PageMap - * Supplies a pointer to the page mapping structure. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -XtEnablePaging(IN PXTBL_PAGE_MAPPING PageMap) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS TrampolineAddress; - PXT_TRAMPOLINE_ENTRY TrampolineEntry; - ULONG_PTR TrampolineSize; - - /* 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 = XtpMapHardwareMemoryPool(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) - { - /* Set the address of the trampoline code below 1MB */ - TrampolineAddress = MM_TRAMPOLINE_ADDRESS; - - /* Calculate the size of the trampoline code */ - TrampolineSize = (ULONG_PTR)ArEnableExtendedPhysicalAddressingEnd - (ULONG_PTR)ArEnableExtendedPhysicalAddressing; - - /* Allocate pages for the trampoline */ - Status = XtLdrProtocol->Memory.AllocatePages(AllocateAddress, EFI_SIZE_TO_PAGES(TrampolineSize), &TrampolineAddress); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to allocate memory for trampoline code */ - XtLdrProtocol->Debug.Print(L"Failed to allocate memory for trampoline code (Status code: %zX)\n", Status); - return Status; - } - - /* Set the trampoline entry point and copy its code into the allocated buffer */ - TrampolineEntry = (PXT_TRAMPOLINE_ENTRY)(UINT_PTR)TrampolineAddress; - RtlCopyMemory(TrampolineEntry, ArEnableExtendedPhysicalAddressing, TrampolineSize); - } - - /* Exit EFI Boot Services */ - XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); - Status = XtLdrProtocol->Util.ExitBootServices(); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to exit boot services */ - XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); - return STATUS_EFI_ABORTED; - } - - /* Check the configured page map level to set the LA57 state accordingly */ - if(PageMap->PageMapLevel == 5) - { - /* Enable Linear Address 57-bit (LA57) extension */ - XtLdrProtocol->Debug.Print(L"Enabling Linear Address 57-bit (LA57)\n"); - - /* Execute the trampoline to enable LA57 and write PML5 to CR3 */ - TrampolineEntry((UINT64)PageMap->PtePointer); - } - else - { - /* Disable Linear Address 57-bit (LA57) extension */ - XtLdrProtocol->Debug.Print(L"Disabling Linear Address 57-bit (LA57)\n"); - - /* Write PML4 to CR3 and enable paging */ - ArWriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); - ArWriteControlRegister(0, ArReadControlRegister(0) | CR0_PG); - } - - /* Return success */ - return STATUS_EFI_SUCCESS; -} diff --git a/xtldr/modules/xtos_o/data.cc b/xtldr/modules/xtos_o/data.cc new file mode 100644 index 0000000..9a66a53 --- /dev/null +++ b/xtldr/modules/xtos_o/data.cc @@ -0,0 +1,19 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/xtos/data.cc + * DESCRIPTION: XTOS module global and static data + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* XTOS Boot Protocol */ +XTBL_BOOT_PROTOCOL Xtos::BootProtocol; + +/* XTOS PE/COFF Image Protocol */ +PXTBL_EXECUTABLE_IMAGE_PROTOCOL Xtos::PeCoffProtocol; + +/* EFI XT Loader Protocol */ +PXTBL_LOADER_PROTOCOL Xtos::XtLdrProtocol; diff --git a/xtldr/modules/xtos_o/i686/memory.c b/xtldr/modules/xtos_o/i686/memory.cc similarity index 95% rename from xtldr/modules/xtos_o/i686/memory.c rename to xtldr/modules/xtos_o/i686/memory.cc index 959ac8c..b0b4203 100644 --- a/xtldr/modules/xtos_o/i686/memory.c +++ b/xtldr/modules/xtos_o/i686/memory.cc @@ -1,12 +1,12 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/i686/memory.c + * FILE: xtldr/i686/memory.cc * DESCRIPTION: EFI memory management for i686 target * DEVELOPERS: Rafal Kupiec */ -#include +#include /** @@ -21,7 +21,7 @@ */ XTCDECL ULONG -XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) +Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters) { CPUID_REGISTERS CpuRegisters; @@ -44,6 +44,77 @@ XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) return 2; } +/** + * Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well. + * + * @param PageMap + * Supplies a pointer to the page mapping structure. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap) +{ + EFI_STATUS Status; + + /* Build page map */ + Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, MM_PTE_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 layer (Status code: %zX)\n", Status); + return Status; + } + + /* Exit EFI Boot Services */ + XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n"); + Status = XtLdrProtocol->Util.ExitBootServices(); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to exit boot services */ + XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); + return STATUS_EFI_ABORTED; + } + + /* Disable paging */ + ArWriteControlRegister(0, ArReadControlRegister(0) & ~CR0_PG); + + /* Check the configured page map level to set the PAE state accordingly */ + if(PageMap->PageMapLevel == 3) + { + /* Enable Physical Address Extension (PAE) */ + XtLdrProtocol->Debug.Print(L"Enabling Physical Address Extension (PAE)\n"); + ArWriteControlRegister(4, ArReadControlRegister(4) | CR4_PAE); + } + else + { + /* Disable Physical Address Extension (PAE) */ + XtLdrProtocol->Debug.Print(L"Disabling Physical Address Extension (PAE)\n"); + ArWriteControlRegister(4, ArReadControlRegister(4) & ~CR4_PAE); + } + + /* Write page mappings to CR3 */ + ArWriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); + + /* Enable paging */ + ArWriteControlRegister(0, ArReadControlRegister(0) | CR0_PG); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Maps the page table for hardware layer addess space. * @@ -56,7 +127,7 @@ XtpDeterminePagingLevel(IN CONST PWCHAR Parameters) */ XTCDECL EFI_STATUS -XtpMapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) +Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) { EFI_PHYSICAL_ADDRESS Address; PHARDWARE_LEGACY_PTE LegacyPdeBase; @@ -108,74 +179,3 @@ XtpMapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap) /* 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 PageMap - * Supplies a pointer to the page mapping structure. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -XtEnablePaging(IN PXTBL_PAGE_MAPPING PageMap) -{ - EFI_STATUS Status; - - /* Build page map */ - Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, MM_PTE_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 = XtpMapHardwareMemoryPool(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"); - Status = XtLdrProtocol->Util.ExitBootServices(); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to exit boot services */ - XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status); - return STATUS_EFI_ABORTED; - } - - /* Disable paging */ - ArWriteControlRegister(0, ArReadControlRegister(0) & ~CR0_PG); - - /* Check the configured page map level to set the PAE state accordingly */ - if(PageMap->PageMapLevel == 3) - { - /* Enable Physical Address Extension (PAE) */ - XtLdrProtocol->Debug.Print(L"Enabling Physical Address Extension (PAE)\n"); - ArWriteControlRegister(4, ArReadControlRegister(4) | CR4_PAE); - } - else - { - /* Disable Physical Address Extension (PAE) */ - XtLdrProtocol->Debug.Print(L"Disabling Physical Address Extension (PAE)\n"); - ArWriteControlRegister(4, ArReadControlRegister(4) & ~CR4_PAE); - } - - /* Write page mappings to CR3 */ - ArWriteControlRegister(3, (UINT_PTR)PageMap->PtePointer); - - /* Enable paging */ - ArWriteControlRegister(0, ArReadControlRegister(0) | CR0_PG); - - /* Return success */ - return STATUS_EFI_SUCCESS; -} diff --git a/xtldr/modules/xtos_o/includes/xtos.h b/xtldr/modules/xtos_o/includes/xtos.h deleted file mode 100644 index 2f4da6a..0000000 --- a/xtldr/modules/xtos_o/includes/xtos.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * PROJECT: ExectOS - * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/xtos/includes/xtos.h - * DESCRIPTION: XTOS boot protocol support header - * DEVELOPERS: Rafal Kupiec - */ - -#ifndef __XTLDR_MODULES_XTOS_H -#define __XTLDR_MODULES_XTOS_H - -#include - - -typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR DriverName); -typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock); -typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)(); -typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)(); - -/* XT framebuffer support protocol */ -typedef struct _XT_FRAMEBUFFER_PROTOCOL -{ - PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; - PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; - PXT_FRAMEBUFFER_INITIALIZE Initialize; - PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation; -} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL; - -/* EFI XT Loader Protocol */ -EXTERN PXTBL_LOADER_PROTOCOL XtLdrProtocol; - -/* XTOS trampoline end address to calculate trampoline size */ -EXTERN PVOID ArEnableExtendedPhysicalAddressingEnd[]; - -/* XTOS kernel entry point */ -typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); - -/* XTOS trampoline entry point */ -typedef VOID (*PXT_TRAMPOLINE_ENTRY)(UINT64 PageMap); - -/* XTOS boot protocol related routines forward references */ -XTCDECL -EFI_STATUS -XtAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings, - IN PVOID VirtualAddress, - IN PVOID PhysicalAddress, - IN UINT NumberOfPages, - IN LOADER_MEMORY_TYPE MemoryType); - -XTCDECL -EFI_STATUS -XtBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); - -XTCDECL -LOADER_MEMORY_TYPE -XtConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); - -XTCDECL -ULONG -XtpDeterminePagingLevel(IN CONST PWCHAR Parameters); - -XTCDECL -EFI_STATUS -XtEnablePaging(IN PXTBL_PAGE_MAPPING PageMap); - -XTCDECL -EFI_STATUS -XtGetVirtualAddress(IN PLIST_ENTRY MemoryMappings, - IN PVOID PhysicalAddress, - OUT PVOID *VirtualAddress); - -XTCDECL -EFI_STATUS -XtInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, - IN OUT PVOID *MemoryMapAddress); - -XTCDECL -EFI_STATUS -XtMapVirtualMemory(IN PLIST_ENTRY MemoryMappings, - IN UINT_PTR VirtualAddress, - IN UINT_PTR PhysicalAddress, - IN UINT NumberOfPages, - IN OUT PVOID *PtePointer); - -XTCDECL -EFI_STATUS -XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, - IN PXTBL_BOOT_PARAMETERS Parameters); - - -XTCDECL -EFI_STATUS -XtpInitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap); - -XTCDECL -EFI_STATUS -XtpInitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, - IN PXTBL_BOOT_PARAMETERS Parameters); - -XTCDECL -EFI_STATUS -XtpLoadModule(IN PEFI_FILE_HANDLE BootDir, - IN PWCHAR FileName, - IN PVOID VirtualAddress, - IN LOADER_MEMORY_TYPE MemoryType, - OUT PPECOFF_IMAGE_CONTEXT *ImageContext); - -XTCDECL -EFI_STATUS -XtpMapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); - -XTCDECL -EFI_STATUS -BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, - IN PEFI_SYSTEM_TABLE SystemTable); - -#endif /* __XTLDR_MODULES_XTOS_H */ diff --git a/xtldr/modules/xtos_o/includes/xtos.hh b/xtldr/modules/xtos_o/includes/xtos.hh new file mode 100644 index 0000000..7222b1f --- /dev/null +++ b/xtldr/modules/xtos_o/includes/xtos.hh @@ -0,0 +1,81 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/xtos/includes/xtos.hh + * DESCRIPTION: XTOS boot protocol support header + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_MODULES_XTOS_HH +#define __XTLDR_MODULES_XTOS_HH + +#include + + +/* XTOS kernel entry point */ +typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); + +/* XTOS trampoline entry point */ +typedef VOID (*PXT_TRAMPOLINE_ENTRY)(UINT64 PageMap); + +/* XTOS trampoline end address to calculate trampoline size */ +XTCLINK PVOID ArEnableExtendedPhysicalAddressingEnd[]; + + +/* XTOS module for XTLDR */ +class Xtos +{ + private: + STATIC XTBL_BOOT_PROTOCOL BootProtocol; + STATIC PXTBL_EXECUTABLE_IMAGE_PROTOCOL PeCoffProtocol; + STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol; + + public: + STATIC XTCDECL EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); + STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle, + 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 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, + 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, + OUT PPECOFF_IMAGE_CONTEXT *ImageContext); + STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap); + 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); +}; + +#endif /* __XTLDR_MODULES_XTOS_HH */ diff --git a/xtldr/modules/xtos_o/xtos.c b/xtldr/modules/xtos_o/xtos.cc similarity index 85% rename from xtldr/modules/xtos_o/xtos.c rename to xtldr/modules/xtos_o/xtos.cc index 85495d5..54031a8 100644 --- a/xtldr/modules/xtos_o/xtos.c +++ b/xtldr/modules/xtos_o/xtos.cc @@ -1,12 +1,12 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/xtos/xtos.c + * FILE: xtldr/modules/xtos/xtos.cc * DESCRIPTION: XTOS boot protocol support * DEVELOPERS: Rafal Kupiec */ -#include +#include /* XTOS module information */ @@ -16,14 +16,139 @@ MODULE_DEPENDENCY(L"acpi framebuf pecoff"); MODULE_LICENSE(L"GPLv3"); MODULE_VERSION(L"0.1"); -/* EFI XT Loader Protocol */ -PXTBL_LOADER_PROTOCOL XtLdrProtocol; -/* XTOS PE/COFF Image Protocol */ -PXTBL_EXECUTABLE_IMAGE_PROTOCOL XtPeCoffProtocol; +/** + * Starts the operating system according to the provided parameters using XTOS boot protocol. + * + * @param Parameters + * Input parameters with detailed system configuration like boot device or kernel path. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) +{ + EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID; + EFI_HANDLE DiskHandle, ProtocolHandle; + PEFI_FILE_HANDLE FsHandle, BootDir; + PWCHAR SystemPath; + EFI_STATUS Status; -/* XTOS Boot Protocol */ -XTBL_BOOT_PROTOCOL XtBootProtocol; + /* Print debug message */ + XtLdrProtocol->Debug.Print(L"XTOS boot protocol activated\n"); + + /* Open the XT PE/COFF protocol */ + Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&PeCoffProtocol, &PeCoffProtocolGuid); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open loader protocol */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n"); + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Check device path */ + if(Parameters->DevicePath == NULLPTR) + { + /* No device path set */ + XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n"); + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Check if system path is set */ + if(Parameters->SystemPath != NULLPTR) + { + /* Make sure system path begins with backslash, the only separator supported by EFI */ + if(Parameters->SystemPath[0] == '/') + { + /* Replace directory separator if needed */ + Parameters->SystemPath[0] = '\\'; + } + + /* Validate system path */ + SystemPath = &Parameters->SystemPath[1]; + while(*SystemPath) + { + /* Make sure it does not point to any subdirectory and not contains special characters */ + if(((*SystemPath | 32) - 'a' >= 26) && ((*SystemPath - '0') >= 10)) + { + /* Invalid path specified */ + XtLdrProtocol->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n"); + return STATUS_EFI_INVALID_PARAMETER; + } + /* Check next character in the path */ + SystemPath++; + } + } + else + { + /* Fallback to '/ExectOS' by default */ + XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n"); + Parameters->SystemPath = (PWCHAR)L"\\ExectOS"; + } + + /* Check if kernel file is set */ + if(Parameters->KernelFile == NULLPTR) + { + /* No kernel filename set, fallback to default */ + XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n"); + Parameters->KernelFile = (PWCHAR)L"xtoskrnl.exe"; + } + + /* Check if provided any kernel boot arguments */ + if(Parameters->Parameters == NULLPTR) + { + /* No argument supplied */ + Parameters->Parameters = (PWCHAR)L""; + } + + /* Print a debug message */ + XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n" + L"[XTOS] System Path: %S\n" + L"[XTOS] Kernel File: %S\n" + L"[XTOS] Boot Arguments: %S\n", + Parameters->ArcName, Parameters->SystemPath, + Parameters->KernelFile, Parameters->Parameters); + + /* Open EFI volume */ + Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open a volume */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n"); + return Status; + } + + /* System path has to point to the boot directory */ + RtlConcatenateWideString(Parameters->SystemPath, (PWCHAR)L"\\Boot", 0); + + /* Open XTOS system boot directory */ + Status = FsHandle->Open(FsHandle, &BootDir, Parameters->SystemPath, EFI_FILE_MODE_READ, 0); + FsHandle->Close(FsHandle); + + /* Check if system path directory opened successfully */ + if(Status == STATUS_EFI_NOT_FOUND) + { + /* Directory not found, nothing to load */ + XtLdrProtocol->Debug.Print(L"ERROR: System boot directory not found\n"); + + /* Close volume */ + XtLdrProtocol->Disk.CloseVolume(&DiskHandle); + return Status; + } + else if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open directory */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n"); + XtLdrProtocol->Disk.CloseVolume(&DiskHandle); + return Status; + } + + /* Start boot sequence */ + return RunBootSequence(BootDir, Parameters); +} /** * Returns information about frame buffer in XTOS compatible format. @@ -37,10 +162,10 @@ XTBL_BOOT_PROTOCOL XtBootProtocol; */ XTCDECL VOID -XtGetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, - IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, - IN PULONG_PTR FrameBufferSize, - IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo) +Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, + IN PEFI_PHYSICAL_ADDRESS FrameBufferBase, + IN PULONG_PTR FrameBufferSize, + IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo) { /* Fill in frame buffer resource */ FrameBufferResource->Header.PhysicalAddress = (PVOID)*FrameBufferBase; @@ -65,9 +190,9 @@ XtGetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource, XTCDECL EFI_STATUS -XtGetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, - OUT PLIST_ENTRY MemoryDescriptorList) +Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, + OUT PLIST_ENTRY MemoryDescriptorList) { EFI_PHYSICAL_ADDRESS Address; EFI_STATUS Status; @@ -114,9 +239,9 @@ XtGetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap, XTCDECL EFI_STATUS -XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, - OUT PLIST_ENTRY SystemResourcesList) +Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, + OUT PLIST_ENTRY SystemResourcesList) { XTSTATUS Status; EFI_HANDLE ProtocolHandle; @@ -152,7 +277,7 @@ XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, VirtualBase = *VirtualAddress; /* Calculate next valid virtual address */ - *VirtualAddress += (UINT_PTR)(Pages * EFI_PAGE_SIZE); + *VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE); AcpiResource = (PSYSTEM_RESOURCE_ACPI)Address; @@ -178,7 +303,7 @@ XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, RtlInsertTailList(SystemResourcesList, &AcpiResource->Header.ListEntry); /* Close FrameBuffer protocol */ - XtLdrProtocol->Protocol.Close(ProtocolHandle, &FrameBufGuid); + XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); Address = Address + sizeof(SYSTEM_RESOURCE_ACPI); @@ -196,7 +321,7 @@ XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, { /* Store information about FrameBuffer device */ - XtGetDisplayInformation(FrameBufferResource, &FbAddress, &FbSize, &FbModeInfo); + GetDisplayInformation(FrameBufferResource, &FbAddress, &FbSize, &FbModeInfo); } } if(Status != STATUS_EFI_SUCCESS) @@ -216,9 +341,9 @@ XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, FrameBufferPages, LoaderFirmwarePermanent); /* Close FrameBuffer protocol */ - XtLdrProtocol->Protocol.Close(ProtocolHandle, &FrameBufGuid); + XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid); - *VirtualAddress += (UINT_PTR)(FrameBufferPages * EFI_PAGE_SIZE); + *VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE); RtlInsertTailList(SystemResourcesList, &FrameBufferResource->Header.ListEntry); @@ -227,261 +352,6 @@ XtGetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap, return STATUS_EFI_SUCCESS; } -/** - * Starts the operating system according to the provided parameters using XTOS boot protocol. - * - * @param Parameters - * Input parameters with detailed system configuration like boot device or kernel path. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -XtBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) -{ - EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID; - EFI_HANDLE DiskHandle, ProtocolHandle; - PEFI_FILE_HANDLE FsHandle, BootDir; - PWCHAR SystemPath; - EFI_STATUS Status; - - /* Print debug message */ - XtLdrProtocol->Debug.Print(L"XTOS boot protocol activated\n"); - - /* Open the XT PE/COFF protocol */ - Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&XtPeCoffProtocol, &PeCoffProtocolGuid); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open loader protocol */ - XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n"); - return STATUS_EFI_PROTOCOL_ERROR; - } - - /* Check device path */ - if(Parameters->DevicePath == NULLPTR) - { - /* No device path set */ - XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n"); - return STATUS_EFI_INVALID_PARAMETER; - } - - /* Check if system path is set */ - if(Parameters->SystemPath != NULLPTR) - { - /* Make sure system path begins with backslash, the only separator supported by EFI */ - if(Parameters->SystemPath[0] == '/') - { - /* Replace directory separator if needed */ - Parameters->SystemPath[0] = '\\'; - } - - /* Validate system path */ - SystemPath = &Parameters->SystemPath[1]; - while(*SystemPath) - { - /* Make sure it does not point to any subdirectory and not contains special characters */ - if(((*SystemPath | 32) - 'a' >= 26) && ((*SystemPath - '0') >= 10)) - { - /* Invalid path specified */ - XtLdrProtocol->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n"); - return STATUS_EFI_INVALID_PARAMETER; - } - /* Check next character in the path */ - SystemPath++; - } - } - else - { - /* Fallback to '/ExectOS' by default */ - XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n"); - Parameters->SystemPath = L"\\ExectOS"; - } - - /* Check if kernel file is set */ - if(Parameters->KernelFile == NULLPTR) - { - /* No kernel filename set, fallback to default */ - XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n"); - Parameters->KernelFile = L"xtoskrnl.exe"; - } - - /* Check if provided any kernel boot arguments */ - if(Parameters->Parameters == NULLPTR) - { - /* No argument supplied */ - Parameters->Parameters = L""; - } - - /* Print a debug message */ - XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n" - L"[XTOS] System Path: %S\n" - L"[XTOS] Kernel File: %S\n" - L"[XTOS] Boot Arguments: %S\n", - Parameters->ArcName, Parameters->SystemPath, - Parameters->KernelFile, Parameters->Parameters); - - /* Open EFI volume */ - Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open a volume */ - XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n"); - return Status; - } - - /* System path has to point to the boot directory */ - RtlConcatenateWideString(Parameters->SystemPath, L"\\Boot", 0); - - /* Open XTOS system boot directory */ - Status = FsHandle->Open(FsHandle, &BootDir, Parameters->SystemPath, EFI_FILE_MODE_READ, 0); - FsHandle->Close(FsHandle); - - /* Check if system path directory opened successfully */ - if(Status == STATUS_EFI_NOT_FOUND) - { - /* Directory not found, nothing to load */ - XtLdrProtocol->Debug.Print(L"ERROR: System boot directory not found\n"); - - /* Close volume */ - XtLdrProtocol->Disk.CloseVolume(DiskHandle); - return Status; - } - else if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open directory */ - XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n"); - XtLdrProtocol->Disk.CloseVolume(DiskHandle); - return Status; - } - - /* Start boot sequence */ - return XtpBootSequence(BootDir, Parameters); -} - -/** - * This routine initiates an XTOS boot sequence. - * - * @param BootDir - * An EFI handle to the XTOS boot directory. - * - * @param Parameters - * Input parameters with detailed system configuration like boot device or kernel path. - * - * @return This routine returns a status code. - * - * @since XT 1.0 - */ -XTCDECL -EFI_STATUS -XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, - IN PXTBL_BOOT_PARAMETERS Parameters) -{ - EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; - EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; - PKERNEL_INITIALIZATION_BLOCK KernelParameters; - 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; - XTBL_PAGE_MAPPING PageMap; - - /* Initialize XTOS startup sequence */ - XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); - - /* Load FrameBuffer protocol */ - Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid); - if(Status == STATUS_EFI_SUCCESS) - { - /* Make sure FrameBuffer is initialized */ - FrameBufProtocol->Initialize(); - FrameBufProtocol->SetScreenResolution(0, 0); - } - - /* 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, XtpDeterminePagingLevel(Parameters->Parameters), Size4K); - - Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR); - if(Status != STATUS_EFI_SUCCESS) - { - return Status; - } - - /* Load the kernel */ - Status = XtpLoadModule(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, ImageContext->VirtualAddress, - ImageContext->PhysicalAddress, ImageContext->ImagePages, 0); - if(Status != STATUS_EFI_SUCCESS) - { - return Status; - } - - /* Set next valid virtual address right after the kernel */ - VirtualAddress += ImageContext->ImagePages * EFI_PAGE_SIZE; - - /* Find and map APIC base address */ - Status = XtpInitializeApicBase(&PageMap); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to setup kernel initialization block */ - XtLdrProtocol->Debug.Print(L"Failed to initialize APIC (Status Code: 0x%zX)\n", Status); - 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 = XtpInitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to setup kernel initialization block */ - XtLdrProtocol->Debug.Print(L"Failed to setup kernel initialization block (Status Code: 0x%zX)\n", Status); - return Status; - } - - /* Get kernel entry point */ - XtPeCoffProtocol->GetEntryPoint(ImageContext, (PVOID)&KernelEntryPoint); - - /* Close boot directory handle */ - BootDir->Close(BootDir); - - /* Enable paging */ - XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&ImageProtocol, &LoadedImageGuid); - Status = XtEnablePaging(&PageMap); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to enable paging */ - XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: 0x%zX)\n", Status); - return Status; - } - - /* Call XTOS kernel */ - XtLdrProtocol->Debug.Print(L"Booting the XTOS kernel\n"); - KernelEntryPoint(KernelParameters); - - /* Return success */ - return STATUS_EFI_SUCCESS; -} - /** * Checks if APIC is present in the system and finds its base address. * @@ -494,7 +364,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, */ XTCDECL EFI_STATUS -XtpInitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) +Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) { EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID; PXTBL_ACPI_PROTOCOL AcpiProtocol; @@ -538,9 +408,9 @@ XtpInitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap) */ XTCDECL EFI_STATUS -XtpInitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, - IN PVOID *VirtualAddress, - IN PXTBL_BOOT_PARAMETERS Parameters) +Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, + IN PVOID *VirtualAddress, + IN PXTBL_BOOT_PARAMETERS Parameters) { PKERNEL_INITIALIZATION_BLOCK LoaderBlock; EFI_PHYSICAL_ADDRESS Address; @@ -573,7 +443,7 @@ XtpInitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, LoaderBlock->ProtocolVersion = BOOT_PROTOCOL_VERSION; /* Set LoaderInformation block properties */ - LoaderBlock->LoaderInformation.DbgPrint = XtLdrProtocol->Debug.Print; + LoaderBlock->LoaderInformation.DbgPrint = (PVOID)XtLdrProtocol->Debug.Print; /* Attempt to find virtual address of the EFI Runtime Services */ // Status = XtLdrProtocol->GetVirtualAddress(MemoryMappings, &EfiSystemTable->RuntimeServices->Hdr, &RuntimeServices); @@ -601,19 +471,45 @@ XtpInitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, BlockPages, LoaderSystemBlock); /* Calculate next valid virtual address */ - *VirtualAddress += (UINT_PTR)(BlockPages * EFI_PAGE_SIZE); + *VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE); RtlInitializeListHead(&LoaderBlock->SystemResourcesListHead); - XtGetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); + GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead); /* Initialize memory descriptor list */ RtlInitializeListHead(&LoaderBlock->MemoryDescriptorListHead); - XtGetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); + GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead); /* Return success */ return STATUS_EFI_SUCCESS; } +XTCDECL +EFI_STATUS +Xtos::InitializeModule(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID; + EFI_STATUS Status; + + /* Open the XTLDR protocol */ + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open loader protocol */ + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Set routines available via XTOS boot protocol */ + BootProtocol.BootSystem = Xtos::BootSystem; + + /* Register XTOS boot protocol */ + XtLdrProtocol->Boot.RegisterProtocol(L"XTOS", &Guid); + + /* Install XTOS protocol */ + return XtLdrProtocol->Protocol.Install(&BootProtocol, &Guid); +} + /** * Loads XTOS PE/COFF module. * @@ -638,11 +534,11 @@ XtpInitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap, */ XTCDECL EFI_STATUS -XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, - IN PWCHAR FileName, - IN PVOID VirtualAddress, - IN LOADER_MEMORY_TYPE MemoryType, - OUT PPECOFF_IMAGE_CONTEXT *ImageContext) +Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir, + IN PWCHAR FileName, + IN PVOID VirtualAddress, + IN LOADER_MEMORY_TYPE MemoryType, + OUT PPECOFF_IMAGE_CONTEXT *ImageContext) { PEFI_FILE_HANDLE ModuleHandle; USHORT MachineType, SubSystem; @@ -661,7 +557,7 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, } /* Load the PE/COFF image file */ - Status = XtPeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID)ImageContext); + Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext); if(Status != STATUS_EFI_SUCCESS) { /* Unable to load the file */ @@ -673,7 +569,7 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, ModuleHandle->Close(ModuleHandle); /* Check PE/COFF image machine type compatibility */ - XtPeCoffProtocol->GetMachineType(*ImageContext, &MachineType); + PeCoffProtocol->GetMachineType(*ImageContext, &MachineType); if(MachineType != _ARCH_IMAGE_MACHINE_TYPE) { /* Machine type mismatch */ @@ -682,7 +578,7 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, } /* Check PE/COFF image subsystem */ - XtPeCoffProtocol->GetSubSystem(*ImageContext, &SubSystem); + PeCoffProtocol->GetSubSystem(*ImageContext, &SubSystem); if(SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_KERNEL && SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_APPLICATION && SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_DRIVER) @@ -698,6 +594,129 @@ XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, return STATUS_EFI_SUCCESS; } +/** + * This routine initiates an XTOS boot sequence. + * + * @param BootDir + * An EFI handle to the XTOS boot directory. + * + * @param Parameters + * Input parameters with detailed system configuration like boot device or kernel path. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir, + IN PXTBL_BOOT_PARAMETERS Parameters) +{ + EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID; + PKERNEL_INITIALIZATION_BLOCK KernelParameters; + 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; + XTBL_PAGE_MAPPING PageMap; + + /* Initialize XTOS startup sequence */ + XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); + + /* Load FrameBuffer protocol */ + Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid); + if(Status == STATUS_EFI_SUCCESS) + { + /* Make sure FrameBuffer is initialized */ + FrameBufProtocol->Initialize(); + FrameBufProtocol->SetScreenResolution(0, 0); + } + + /* 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, &VirtualMemoryArea, NULLPTR); + if(Status != STATUS_EFI_SUCCESS) + { + return Status; + } + + /* Load the kernel */ + 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, ImageContext->VirtualAddress, + ImageContext->PhysicalAddress, ImageContext->ImagePages, + LoaderExceptionBlock); // 0 is LoaderExceptionBlock?! Should be 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) + { + /* Failed to setup kernel initialization block */ + XtLdrProtocol->Debug.Print(L"Failed to initialize APIC (Status Code: 0x%zX)\n", Status); + 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); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to setup kernel initialization block */ + XtLdrProtocol->Debug.Print(L"Failed to setup kernel initialization block (Status Code: 0x%zX)\n", Status); + return Status; + } + + /* Get kernel entry point */ + PeCoffProtocol->GetEntryPoint(ImageContext, (PVOID*)&KernelEntryPoint); + + /* Close boot directory handle */ + BootDir->Close(BootDir); + + /* Enable paging */ + XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&ImageProtocol, &LoadedImageGuid); + Status = EnablePaging(&PageMap); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to enable paging */ + XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: 0x%zX)\n", Status); + return Status; + } + + /* Call XTOS kernel */ + XtLdrProtocol->Debug.Print(L"Booting the XTOS kernel\n"); + KernelEntryPoint(KernelParameters); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * This routine is the entry point of the XT EFI boot loader module. * @@ -716,23 +735,6 @@ EFI_STATUS XtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable) { - EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID; - EFI_STATUS Status; - - /* Open the XTLDR protocol */ - Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); - if(Status != STATUS_EFI_SUCCESS) - { - /* Failed to open loader protocol */ - return STATUS_EFI_PROTOCOL_ERROR; - } - - /* Set routines available via XTOS boot protocol */ - XtBootProtocol.BootSystem = XtBootSystem; - - /* Register XTOS boot protocol */ - XtLdrProtocol->Boot.RegisterProtocol(L"XTOS", &Guid); - - /* Install XTOS protocol */ - return XtLdrProtocol->Protocol.Install(&XtBootProtocol, &Guid); + /* Initialize XTOS module */ + return Xtos::InitializeModule(ImageHandle, SystemTable); }