From 5dfa8aeac4c7e36fdaeee73c6900c4ae21361983 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 10 Jan 2024 17:40:59 +0100 Subject: [PATCH 1/5] Added elf_o module --- sdk/xtdk/xtimage.h | 110 +++++++++ sdk/xtdk/xtstruct.h | 5 + xtldr/modules/elf_o/CMakeLists.txt | 26 ++ xtldr/modules/elf_o/elf.c | 371 +++++++++++++++++++++++++++++ xtldr/modules/elf_o/includes/elf.h | 47 ++++ 5 files changed, 559 insertions(+) create mode 100644 xtldr/modules/elf_o/CMakeLists.txt create mode 100644 xtldr/modules/elf_o/elf.c create mode 100644 xtldr/modules/elf_o/includes/elf.h diff --git a/sdk/xtdk/xtimage.h b/sdk/xtdk/xtimage.h index 047c352..451ec33 100644 --- a/sdk/xtdk/xtimage.h +++ b/sdk/xtdk/xtimage.h @@ -606,4 +606,114 @@ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY ULONG Reserved; } PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY; +/* TODO: Name these enumerations */ +typedef enum _ELF_IDENT +{ + EI_MAG0 = 0, + EI_MAG1 = 1, + EI_MAG2 = 2, + EI_MAG3 = 3, + EI_CLASS = 4, + EI_DATA = 5, + EI_VERSION = 6, + EI_OSABI = 7, + EI_ABIVERSION = 8 +} ELF_IDENT; + +typedef enum _ELF_PT +{ + PT_NULL = 0, + PT_LOAD = 1, + PT_DYNAMIC = 2, + PT_INTERP = 3, + PT_NOTE = 4, + PT_SHLIB = 5, + PT_PHDR = 6, + PT_TLS = 7 +} ELF_PT; + +/* ELF image representation structure */ +typedef struct _ELF_IMAGE_CONTEXT +{ + union + { + PELF32_HEADER Header32; + PELF64_HEADER Header64; + }; + PVOID Data; + PVOID EntryPoint; + UINT64 FileSize; + UINT ImagePages; + UINT ImageSize; + LOADER_MEMORY_TYPE MemoryType; + PVOID PhysicalAddress; + PVOID VirtualAddress; +} ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; + +/* 32-bit ELF image header structure */ +typedef struct _ELF32_HEADER +{ + /* NOTE: EI_NIDENT seems to always be defined as 16. */ + UCHAR e_ident[16]; + UINT16 e_type; + UINT16 e_machine; + UINT32 e_version; + UINT32 e_entry; + UINT32 e_phoff; + UINT32 e_shoff; + UINT32 e_flags; + UINT16 e_ehsize; + UINT16 e_phentsize; + UINT16 e_phnum; + UINT16 e_shentsize; + UINT16 e_shnum; + UINT16 e_shstrndx; +} ELF32_HEADER, *PELF32_HEADER; + +/* 64-bit ELF image header structure */ +typedef struct _ELF64_HEADER +{ + /* NOTE: EI_NIDENT seems to always be defined as 16. */ + UCHAR e_ident[16]; + UINT16 e_type; + UINT16 e_machine; + UINT32 e_version; + ULONG e_entry; + ULONG e_phoff; + ULONG e_shoff; + UINT32 e_flags; + UINT16 e_ehsize; + UINT16 e_phentsize; + UINT16 e_phnum; + UINT16 e_shentsize; + UINT16 e_shnum; + UINT16 e_shstrndx; +} ELF64_HEADER, *PELF64_HEADER; + +/* 32-bit ELF program header structure */ +typedef struct _ELF32_PROGRAM_HEADER +{ + UINT32 p_type; + UINT32 p_offset; + UINT32 p_vaddr; + UINT32 p_paddr; + UINT32 p_filesz; + UINT32 p_memsz; + UINT32 p_flags; + UINT32 p_align; +} ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; + +/* 64-bit ELF program header structure */ +typedef struct _ELF64_PROGRAM_HEADER +{ + UINT32 p_type; + UINT32 p_flags; + ULONG p_offset; + ULONG p_vaddr; + ULONG p_paddr; + ULONG p_filesz; + ULONG p_memsz; + ULONG p_align; +} ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; + #endif /* __XTDK_XTIMAGE_H */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index dcc19ab..c9ed7a8 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -254,6 +254,11 @@ typedef struct _PECOFF_IMAGE_ROM_HEADER PECOFF_IMAGE_ROM_HEADER, *PPECOFF_IMAGE_ typedef struct _PECOFF_IMAGE_ROM_OPTIONAL_HEADER PECOFF_IMAGE_ROM_OPTIONAL_HEADER, *PPECOFF_IMAGE_ROM_OPTIONAL_HEADER; typedef struct _PECOFF_IMAGE_SECTION_HEADER PECOFF_IMAGE_SECTION_HEADER, *PPECOFF_IMAGE_SECTION_HEADER; typedef struct _PECOFF_IMAGE_VXD_HEADER PECOFF_IMAGE_VXD_HEADER, *PPECOFF_IMAGE_VXD_HEADER; +typedef struct _ELF_IMAGE_CONTEXT ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; +typedef struct _ELF32_HEADER ELF32_HEADER, *PELF32_HEADER; +typedef struct _ELF64_HEADER ELF64_HEADER, *PELF64_HEADER; +typedef struct _ELF32_PROGRAM_HEADER ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; +typedef struct _ELF64_PROGRAM_HEADER ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; typedef struct _STRING STRING, *PSTRING; diff --git a/xtldr/modules/elf_o/CMakeLists.txt b/xtldr/modules/elf_o/CMakeLists.txt new file mode 100644 index 0000000..2cf25fb --- /dev/null +++ b/xtldr/modules/elf_o/CMakeLists.txt @@ -0,0 +1,26 @@ +# XT Boot Loader +PROJECT(XTLDR_ELF_O) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_ELF_O_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_ELF_O_SOURCE + ${XTLDR_ELF_O_SOURCE_DIR}/elf.c) + +# Link bootloader executable +add_executable(elf_o ${XTLDR_ELF_O_SOURCE}) + +# Add linker libraries +target_link_libraries(elf_o libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(elf_o PROPERTIES SUFFIX .efi) +set_install_target(elf_o efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(elf_o "XtLdrModuleMain") +set_linker_map(elf_o TRUE) +set_subsystem(elf_o efi_boot_service_driver) diff --git a/xtldr/modules/elf_o/elf.c b/xtldr/modules/elf_o/elf.c new file mode 100644 index 0000000..bf5282e --- /dev/null +++ b/xtldr/modules/elf_o/elf.c @@ -0,0 +1,371 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/elf_o/elf.c + * DESCRIPTION: ELF executable file format support module + * DEVELOPERS: Jozef Nagy + */ + +#include + +/* ELF_O module information */ +XTBL_MODINFO = L"ELF executable file format support"; + +/* EFI XT Loader Protocol */ +PXTBL_LOADER_PROTOCOL XtLdrProtocol; + +/* XTOS ELF Image Protocol */ +XTBL_EXECUTABLE_IMAGE_PROTOCOL XtElfProtocol; + +/** + * Returns the address of the entry point. + * + * @param Image + * A pointer to the ELF context structure representing the loaded image. + * + * @param EntryPoint + * A pointer to the memory area where address of the image entry point will be stored. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +ElfGetEntryPoint(IN PVOID ImagePointer, + OUT PVOID *EntryPoint) +{ + PELF_IMAGE_CONTEXT Image = ImagePointer; + + /* Validate input data */ + if(!Image) + { + /* Invalid parameter passed */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Save entry point and return success */ + *EntryPoint = Image->EntryPoint; + return STATUS_EFI_SUCCESS; +} + +XTCDECL +EFI_STATUS +ElfGetMachineType(IN PVOID ImagePointer, + OUT PUSHORT MachineType) +{ + PELF_IMAGE_CONTEXT Image = ImagePointer; + + *MachineType = Image->Header32->e_machine; + return STATUS_EFI_SUCCESS; +} + +XTCDECL +EFI_STATUS +ElfGetSubSystem(IN PVOID ImagePointer, + OUT PUSHORT SubSystem) +{ + PELF_IMAGE_CONTEXT Image = ImagePointer; + + *SubSystem = Image->Header32->e_ident[EI_OSABI]; + return STATUS_EFI_SUCCESS; +} + +XTCDECL +EFI_STATUS +ElfRelocateImage(IN PVOID ImagePointer, + IN EFI_VIRTUAL_ADDRESS Address) +{ + /* No relocation yet */ + return STATUS_EFI_SUCCESS; +} + +/** + * Loads an ELF image file. + * + * @param FileHandle + * The handle of the opened ELF file. + * + * @param MemoryType + * Supplies the type of memory to be assigned to the memory descriptor. + * + * @param VirtualAddress + * Optional virtual address pointing to the memory area where ELF file will be loaded. + * + * @param Image + * Supplies pointer to the memory area where loaded ELF image context will be stored. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, + IN LOADER_MEMORY_TYPE MemoryType, + IN PVOID VirtualAddress, + OUT PVOID *ImagePointer) +{ + EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID; + PELF_IMAGE_CONTEXT ImageData; + EFI_PHYSICAL_ADDRESS Address; + PEFI_FILE_INFO FileInfo; + UINT_PTR ReadSize; + EFI_STATUS Status; + // UINT SectionSize; + SIZE_T Pages; + PUCHAR Data; + + /* Set required size for getting file information */ + ReadSize = sizeof(EFI_FILE_INFO) + 32; + + /* Allocate necessary amount of memory */ + Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); + return Status; + } + + /* First attempt to get file information */ + Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + if(Status == STATUS_EFI_BUFFER_TOO_SMALL) + { + /* Buffer it too small, but EFI tells the required size, let's reallocate */ + XtLdrProtocol->Memory.FreePool(&FileInfo); + Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); + return Status; + } + + /* Second attempt to get file information */ + Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo); + } + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to get file information */ + XtLdrProtocol->Debug.Print(L"ERROR: Failed to get file information\n"); + return Status; + } + + /* Allocate memory for storing image data */ + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + XtLdrProtocol->Debug.Print(L"ERROR: Memory pool allocation failure\n"); + return Status; + } + + /* Store file size and memory type, nullify data and free up memory */ + ImageData->Data = NULL; + ImageData->FileSize = FileInfo->FileSize; + ImageData->MemoryType = MemoryType; + XtLdrProtocol->Memory.FreePool(FileInfo); + + /* Calculate number of pages */ + Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize); + + /* Allocate pages */ + Status = XtLdrProtocol->Memory.AllocatePages(Pages, &Address); + if(Status != STATUS_EFI_SUCCESS) + { + /* Pages allocation failure */ + XtLdrProtocol->Debug.Print(L"ERROR: Pages allocation failure\n"); + XtLdrProtocol->Memory.FreePool(ImageData); + return Status; + } + + /* Read ELF image */ + ReadSize = Pages * EFI_PAGE_SIZE; + Data = (PUCHAR)(UINT_PTR)Address; + Status = FileHandle->Read(FileHandle, &ReadSize, Data); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read data */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to read ELF image file\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data); + XtLdrProtocol->Memory.FreePool(ImageData); + return Status; + } + + /* Extract header */ + ImageData->Header32 = (PELF32_HEADER)Data; + ImageData->Header64 = (PELF64_HEADER)Data; + + /* Validate ELF file */ + if(ImageData->Header32->e_ident[EI_MAG0] != 0x7F || + ImageData->Header32->e_ident[EI_MAG1] != 0x45 || + ImageData->Header32->e_ident[EI_MAG2] != 0x4C || + ImageData->Header32->e_ident[EI_MAG3] != 0x46) + { + /* ELF file header is invalid */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Check architecture */ + if(ImageData->Header32->e_ident[EI_CLASS] == 1) + { + /* 32-bit executable */ + + /* Set entry point */ + ImageData->EntryPoint = (PVOID)(UINT_PTR)ImageData->Header32->e_entry; + + /* Load individual segments according to program headers */ + PELF32_PROGRAM_HEADER ProgramHeaders = (PELF32_PROGRAM_HEADER)(Data + ImageData->Header32->e_phoff); + for (UINT Count = 0; Count < ImageData->Header32->e_phnum; Count++) + { + /* PT_DYNAMIC will be used for relocations */ + if(ProgramHeaders[Count].p_type == PT_LOAD) + { + UINT32 PageCount = EFI_SIZE_TO_PAGES((UINT32)ProgramHeaders[Count].p_memsz); + + Status = XtLdrProtocol->Memory.AllocatePages(PageCount, (PEFI_PHYSICAL_ADDRESS)&PageCount); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory */ + XtLdrProtocol->Debug.Print(L"ERROR: Page allocation failure\n"); + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Read segment into memory */ + Status = FileHandle->SetPosition(FileHandle, (UINT64)&ProgramHeaders[Count].p_offset); + Status = FileHandle->Read(FileHandle, (PUINT_PTR)&ProgramHeaders[Count].p_filesz, &ProgramHeaders[Count].p_paddr); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read data */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to load ELF segment into memory!\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)&ProgramHeaders[Count].p_paddr); + return Status; + } + + /* If memory size is larger than file size, zero the memory out */ + UINT32 ZeroCount = ProgramHeaders[Count].p_memsz - ProgramHeaders[Count].p_filesz; + if(ZeroCount > 0) + { + UINT_PTR ZeroedMemoryStart = (UINT_PTR)ProgramHeaders[Count].p_paddr + (UINT_PTR)ProgramHeaders[Count].p_filesz; + RtlZeroMemory((PVOID)ZeroedMemoryStart, ZeroCount); + } + } + } + } + else if(ImageData->Header32->e_ident[EI_CLASS] == 2) + { + /* 64-bit executable */ + + /* Set entry point */ + ImageData->EntryPoint = (PVOID)(UINT_PTR)ImageData->Header64->e_entry; + + /* Load individual segments according to program headers */ + PELF64_PROGRAM_HEADER ProgramHeaders = (PELF64_PROGRAM_HEADER)(Data + ImageData->Header64->e_phoff); + for (UINT Count = 0; Count < ImageData->Header64->e_phnum; Count++) + { + /* PT_DYNAMIC will be used for relocations */ + if(ProgramHeaders[Count].p_type == PT_LOAD) + { + /* Set PhysicalAddress and VirtualAddress to the lowest address present */ + ImageData->PhysicalAddress = (UINT_PTR)ImageData->PhysicalAddress < ProgramHeaders[Count].p_paddr ? + ImageData->PhysicalAddress : + (PVOID)(UINT_PTR)(UINT64)ProgramHeaders[Count].p_paddr; + + ImageData->VirtualAddress = (UINT_PTR)ImageData->VirtualAddress < ProgramHeaders[Count].p_vaddr ? + ImageData->VirtualAddress : + (PVOID)(UINT_PTR)(UINT64)ProgramHeaders[Count].p_vaddr; + + /* Allocate memory for the program headers */ + UINT32 PageCount = EFI_SIZE_TO_PAGES((UINT32)ProgramHeaders[Count].p_memsz); + + Status = XtLdrProtocol->Memory.AllocatePages(PageCount, (PEFI_PHYSICAL_ADDRESS)&PageCount); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory */ + XtLdrProtocol->Debug.Print(L"ERROR: Page allocation failure\n"); + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Read segment into memory */ + Status = FileHandle->SetPosition(FileHandle, (UINT64)&ProgramHeaders[Count].p_offset); + Status = FileHandle->Read(FileHandle, (PUINT_PTR)&ProgramHeaders[Count].p_filesz, &ProgramHeaders[Count].p_paddr); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to read data */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to load ELF segment into memory!\n"); + XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)&ProgramHeaders[Count].p_paddr); + return Status; + } + + /* If memory size is larger than file size, zero the memory out */ + UINT32 ZeroCount = ProgramHeaders[Count].p_memsz - ProgramHeaders[Count].p_filesz; + if(ZeroCount > 0) + { + UINT_PTR ZeroedMemoryStart = (UINT_PTR)ProgramHeaders[Count].p_paddr + (UINT_PTR)ProgramHeaders[Count].p_filesz; + RtlZeroMemory((PVOID)ZeroedMemoryStart, ZeroCount); + } + } + } + } + else + { + /* Invalid executable */ + XtLdrProtocol->Debug.Print(L"ERROR: ELF executable has invalid architecture\n"); + return STATUS_EFI_UNSUPPORTED; + } + + /* Check endianness */ + if(ImageData->Header32->e_ident[EI_DATA] != 1) + { + /* Big-endian */ + XtLdrProtocol->Debug.Print(L"ERROR: XTLDR only supports LSB (little-endian) ELF executables\n"); + return STATUS_EFI_UNSUPPORTED; + } + + /* Store image data */ + *ImagePointer = ImageData; + + /* Return SUCCESS */ + return STATUS_EFI_SUCCESS; +} + +/** + * This routine is the entry point of the XT EFI boot loader module. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param SystemTable + * Provides the EFI system table. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable) +{ + EFI_GUID Guid = XT_ELF_IMAGE_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 ELF image protocol */ + XtElfProtocol.GetEntryPoint = ElfGetEntryPoint; + XtElfProtocol.GetMachineType = ElfGetMachineType; + XtElfProtocol.GetSubSystem = ElfGetSubSystem; + XtElfProtocol.LoadImage = ElfLoadImage; + XtElfProtocol.RelocateImage = ElfRelocateImage; + + /* Register ELF protocol */ + return XtLdrProtocol->Protocol.Install(&XtElfProtocol, &Guid); +} diff --git a/xtldr/modules/elf_o/includes/elf.h b/xtldr/modules/elf_o/includes/elf.h new file mode 100644 index 0000000..c234f0e --- /dev/null +++ b/xtldr/modules/elf_o/includes/elf.h @@ -0,0 +1,47 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/elf_o/includes/elf.h + * DESCRIPTION: ELF executable file format support header + * DEVELOPERS: Jozef Nagy + */ + +#ifndef __XTLDR_MODULES_ELF_O_H +#define __XTLDR_MODULES_ELF_O_H + +#include + +/* ELF image protocol related routines forward references */ +XTCDECL +EFI_STATUS +ElfGetEntryPoint(IN PVOID ImagePointer, + OUT PVOID *EntryPoint); + +XTCDECL +EFI_STATUS +ElfGetMachineType(IN PVOID ImagePointer, + OUT PUSHORT MachineType); + +XTCDECL +EFI_STATUS +ElfGetSubSystem(IN PVOID ImagePointer, + OUT PUSHORT SubSystem); + +XTCDECL +EFI_STATUS +ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, + IN LOADER_MEMORY_TYPE MemoryType, + IN PVOID VirtualAddress, + OUT PVOID *ImagePointer); + +XTCDECL +EFI_STATUS +ElfRelocateImage(IN PVOID ImagePointer, + IN EFI_VIRTUAL_ADDRESS Address); + +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif /* __XTLDR_MODULES_ELF_O_H */ -- 2.50.1 From fe142416ee81b9be8ee4422224ad32cd1cee2201 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 10 Jan 2024 18:08:17 +0100 Subject: [PATCH 2/5] Clean up xtimage.h and xtstruct.h --- sdk/xtdk/xtimage.h | 3 ++- sdk/xtdk/xtstruct.h | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sdk/xtdk/xtimage.h b/sdk/xtdk/xtimage.h index 451ec33..312b0e9 100644 --- a/sdk/xtdk/xtimage.h +++ b/sdk/xtdk/xtimage.h @@ -606,7 +606,7 @@ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY ULONG Reserved; } PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY; -/* TODO: Name these enumerations */ +/* ELF identities */ typedef enum _ELF_IDENT { EI_MAG0 = 0, @@ -620,6 +620,7 @@ typedef enum _ELF_IDENT EI_ABIVERSION = 8 } ELF_IDENT; +/* ELF Program header types */ typedef enum _ELF_PT { PT_NULL = 0, diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index c9ed7a8..a834378 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -39,6 +39,8 @@ typedef enum _EFI_TIMER_DELAY EFI_TIMER_DELAY, *PEFI_TIMER_DELAY; typedef enum _EFI_UART_PARITY_TYPE EFI_UART_PARITY_TYPE, *PEFI_UART_PARITY_TYPE; typedef enum _EFI_UART_STOP_BITS_TYPE EFI_UART_STOP_BITS_TYPE, *PEFI_UART_STOP_BITS_TYPE; typedef enum _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION; +typedef enum _ELF_IDENT ELF_IDENT, *PELF_IDENT; +typedef enum _ELF_PT ELF_PT, *PELF_PT; typedef enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE; typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE; @@ -199,6 +201,11 @@ typedef struct _EFI_USB_DEVICE_PATH EFI_USB_DEVICE_PATH, *PEFI_USB_DEVICE_PATH; typedef struct _EFI_USB_WWID_DEVICE_PATH EFI_USB_WWID_DEVICE_PATH, *PEFI_USB_WWID_DEVICE_PATH; typedef struct _EFI_VENDOR_DEVICE_PATH EFI_VENDOR_DEVICE_PATH, *PEFI_VENDOR_DEVICE_PATH; typedef struct _EFI_VLAN_DEVICE_PATH EFI_VLAN_DEVICE_PATH, *PEFI_VLAN_DEVICE_PATH; +typedef struct _ELF_IMAGE_CONTEXT ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; +typedef struct _ELF32_HEADER ELF32_HEADER, *PELF32_HEADER; +typedef struct _ELF64_HEADER ELF64_HEADER, *PELF64_HEADER; +typedef struct _ELF32_PROGRAM_HEADER ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; +typedef struct _ELF64_PROGRAM_HEADER ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; typedef struct _EPROCESS EPROCESS, *PEPROCESS; typedef struct _ETHREAD ETHREAD, *PETHREAD; typedef struct _EX_RUNDOWN_REFERENCE EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE; @@ -254,11 +261,6 @@ typedef struct _PECOFF_IMAGE_ROM_HEADER PECOFF_IMAGE_ROM_HEADER, *PPECOFF_IMAGE_ typedef struct _PECOFF_IMAGE_ROM_OPTIONAL_HEADER PECOFF_IMAGE_ROM_OPTIONAL_HEADER, *PPECOFF_IMAGE_ROM_OPTIONAL_HEADER; typedef struct _PECOFF_IMAGE_SECTION_HEADER PECOFF_IMAGE_SECTION_HEADER, *PPECOFF_IMAGE_SECTION_HEADER; typedef struct _PECOFF_IMAGE_VXD_HEADER PECOFF_IMAGE_VXD_HEADER, *PPECOFF_IMAGE_VXD_HEADER; -typedef struct _ELF_IMAGE_CONTEXT ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; -typedef struct _ELF32_HEADER ELF32_HEADER, *PELF32_HEADER; -typedef struct _ELF64_HEADER ELF64_HEADER, *PELF64_HEADER; -typedef struct _ELF32_PROGRAM_HEADER ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; -typedef struct _ELF64_PROGRAM_HEADER ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; typedef struct _STRING STRING, *PSTRING; -- 2.50.1 From c4f77f4809ba9fc3be3f7931a519550391c0993f Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 10 Jan 2024 18:22:13 +0100 Subject: [PATCH 3/5] Rename elf_o to elf --- xtldr/modules/CMakeLists.txt | 1 + xtldr/modules/elf/CMakeLists.txt | 26 +++++++++++++++++++++ xtldr/modules/{elf_o => elf}/elf.c | 2 +- xtldr/modules/{elf_o => elf}/includes/elf.h | 2 +- xtldr/modules/elf_o/CMakeLists.txt | 26 --------------------- 5 files changed, 29 insertions(+), 28 deletions(-) create mode 100644 xtldr/modules/elf/CMakeLists.txt rename xtldr/modules/{elf_o => elf}/elf.c (99%) rename xtldr/modules/{elf_o => elf}/includes/elf.h (95%) delete mode 100644 xtldr/modules/elf_o/CMakeLists.txt diff --git a/xtldr/modules/CMakeLists.txt b/xtldr/modules/CMakeLists.txt index 375c1d7..e329643 100644 --- a/xtldr/modules/CMakeLists.txt +++ b/xtldr/modules/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(beep) add_subdirectory(dummy) +add_subdirectory(elf) add_subdirectory(fb_o) add_subdirectory(pecoff_o) add_subdirectory(xtos_o) diff --git a/xtldr/modules/elf/CMakeLists.txt b/xtldr/modules/elf/CMakeLists.txt new file mode 100644 index 0000000..b705b69 --- /dev/null +++ b/xtldr/modules/elf/CMakeLists.txt @@ -0,0 +1,26 @@ +# XT Boot Loader +PROJECT(XTLDR_ELF) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_ELF_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_ELF_SOURCE + ${XTLDR_ELF_SOURCE_DIR}/elf.c) + +# Link bootloader executable +add_executable(elf ${XTLDR_ELF_SOURCE}) + +# Add linker libraries +target_link_libraries(elf libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(elf PROPERTIES SUFFIX .efi) +set_install_target(elf efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(elf "XtLdrModuleMain") +set_linker_map(elf TRUE) +set_subsystem(elf efi_boot_service_driver) diff --git a/xtldr/modules/elf_o/elf.c b/xtldr/modules/elf/elf.c similarity index 99% rename from xtldr/modules/elf_o/elf.c rename to xtldr/modules/elf/elf.c index bf5282e..dc63e3c 100644 --- a/xtldr/modules/elf_o/elf.c +++ b/xtldr/modules/elf/elf.c @@ -1,7 +1,7 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/elf_o/elf.c + * FILE: xtldr/modules/elf/elf.c * DESCRIPTION: ELF executable file format support module * DEVELOPERS: Jozef Nagy */ diff --git a/xtldr/modules/elf_o/includes/elf.h b/xtldr/modules/elf/includes/elf.h similarity index 95% rename from xtldr/modules/elf_o/includes/elf.h rename to xtldr/modules/elf/includes/elf.h index c234f0e..56d6ee4 100644 --- a/xtldr/modules/elf_o/includes/elf.h +++ b/xtldr/modules/elf/includes/elf.h @@ -1,7 +1,7 @@ /** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory - * FILE: xtldr/modules/elf_o/includes/elf.h + * FILE: xtldr/modules/elf/includes/elf.h * DESCRIPTION: ELF executable file format support header * DEVELOPERS: Jozef Nagy */ diff --git a/xtldr/modules/elf_o/CMakeLists.txt b/xtldr/modules/elf_o/CMakeLists.txt deleted file mode 100644 index 2cf25fb..0000000 --- a/xtldr/modules/elf_o/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# XT Boot Loader -PROJECT(XTLDR_ELF_O) - -# Specify include directories -include_directories( - ${EXECTOS_SOURCE_DIR}/sdk/xtdk - ${XTLDR_ELF_O_SOURCE_DIR}/includes) - -# Specify list of source code files -list(APPEND XTLDR_ELF_O_SOURCE - ${XTLDR_ELF_O_SOURCE_DIR}/elf.c) - -# Link bootloader executable -add_executable(elf_o ${XTLDR_ELF_O_SOURCE}) - -# Add linker libraries -target_link_libraries(elf_o libxtos libxtldr) - -# Set proper binary name and install target -set_target_properties(elf_o PROPERTIES SUFFIX .efi) -set_install_target(elf_o efi/boot/xtldr/modules) - -# Set module entrypoint and subsystem -set_entrypoint(elf_o "XtLdrModuleMain") -set_linker_map(elf_o TRUE) -set_subsystem(elf_o efi_boot_service_driver) -- 2.50.1 From 01358b0e558f76be03df25f61db53ba4b58f92b4 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Fri, 12 Jan 2024 21:33:46 +0100 Subject: [PATCH 4/5] Cleanup of ELF structures and typo fixes --- .gitignore | 3 +++ sdk/xtdk/xtimage.h | 28 ++++++++++++------------ sdk/xtdk/xtstruct.h | 12 +++++------ xtldr/modules/CMakeLists.txt | 1 + xtldr/modules/elf/elf.c | 37 ++++++++++++++++++-------------- xtldr/modules/elf/includes/elf.h | 6 +++--- 6 files changed, 48 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 4ea88da..d194e52 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ .vscode build build-* + +# TODO: Don't forget to remove this ;) +xtldr/modules/multiboot2 \ No newline at end of file diff --git a/sdk/xtdk/xtimage.h b/sdk/xtdk/xtimage.h index 312b0e9..146930c 100644 --- a/sdk/xtdk/xtimage.h +++ b/sdk/xtdk/xtimage.h @@ -607,7 +607,7 @@ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY } PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY; /* ELF identities */ -typedef enum _ELF_IDENT +typedef enum _ELF_IMAGE_IDENTITY { EI_MAG0 = 0, EI_MAG1 = 1, @@ -618,10 +618,10 @@ typedef enum _ELF_IDENT EI_VERSION = 6, EI_OSABI = 7, EI_ABIVERSION = 8 -} ELF_IDENT; +} ELF_IMAGE_IDENTITY, *PELF_IMAGE_IDENTITY; /* ELF Program header types */ -typedef enum _ELF_PT +typedef enum _ELF_IMAGE_PROGRAM_HEADER_TYPE { PT_NULL = 0, PT_LOAD = 1, @@ -631,15 +631,15 @@ typedef enum _ELF_PT PT_SHLIB = 5, PT_PHDR = 6, PT_TLS = 7 -} ELF_PT; +} ELF_IMAGE_PROGRAM_HEADER_TYPE, *PELF_IMAGE_PROGRAM_HEADER_TYPE; /* ELF image representation structure */ typedef struct _ELF_IMAGE_CONTEXT { union { - PELF32_HEADER Header32; - PELF64_HEADER Header64; + PELF_IMAGE_HEADER32 Header32; + PELF_IMAGE_HEADER64 Header64; }; PVOID Data; PVOID EntryPoint; @@ -652,7 +652,7 @@ typedef struct _ELF_IMAGE_CONTEXT } ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; /* 32-bit ELF image header structure */ -typedef struct _ELF32_HEADER +typedef struct _ELF_IMAGE_HEADER32 { /* NOTE: EI_NIDENT seems to always be defined as 16. */ UCHAR e_ident[16]; @@ -669,10 +669,10 @@ typedef struct _ELF32_HEADER UINT16 e_shentsize; UINT16 e_shnum; UINT16 e_shstrndx; -} ELF32_HEADER, *PELF32_HEADER; +} ELF_IMAGE_HEADER32, *PELF_IMAGE_HEADER32; /* 64-bit ELF image header structure */ -typedef struct _ELF64_HEADER +typedef struct _ELF_IMAGE_HEADER64 { /* NOTE: EI_NIDENT seems to always be defined as 16. */ UCHAR e_ident[16]; @@ -689,10 +689,10 @@ typedef struct _ELF64_HEADER UINT16 e_shentsize; UINT16 e_shnum; UINT16 e_shstrndx; -} ELF64_HEADER, *PELF64_HEADER; +} ELF_IMAGE_HEADER64, *PELF_IMAGE_HEADER64; /* 32-bit ELF program header structure */ -typedef struct _ELF32_PROGRAM_HEADER +typedef struct _ELF_IMAGE_PROGRAM_HEADER32 { UINT32 p_type; UINT32 p_offset; @@ -702,10 +702,10 @@ typedef struct _ELF32_PROGRAM_HEADER UINT32 p_memsz; UINT32 p_flags; UINT32 p_align; -} ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; +} ELF_IMAGE_PROGRAM_HEADER32, *PELF_IMAGE_PROGRAM_HEADER32; /* 64-bit ELF program header structure */ -typedef struct _ELF64_PROGRAM_HEADER +typedef struct _ELF_IMAGE_PROGRAM_HEADER64 { UINT32 p_type; UINT32 p_flags; @@ -715,6 +715,6 @@ typedef struct _ELF64_PROGRAM_HEADER ULONG p_filesz; ULONG p_memsz; ULONG p_align; -} ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; +} ELF_IMAGE_PROGRAM_HEADER64, *PELF_IMAGE_PROGRAM_HEADER64; #endif /* __XTDK_XTIMAGE_H */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index a834378..66cfc27 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -39,8 +39,8 @@ typedef enum _EFI_TIMER_DELAY EFI_TIMER_DELAY, *PEFI_TIMER_DELAY; typedef enum _EFI_UART_PARITY_TYPE EFI_UART_PARITY_TYPE, *PEFI_UART_PARITY_TYPE; typedef enum _EFI_UART_STOP_BITS_TYPE EFI_UART_STOP_BITS_TYPE, *PEFI_UART_STOP_BITS_TYPE; typedef enum _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION; -typedef enum _ELF_IDENT ELF_IDENT, *PELF_IDENT; -typedef enum _ELF_PT ELF_PT, *PELF_PT; +typedef enum _ELF_IMAGE_IDENTITY ELF_IMAGE_IDENTITY, *PELF_IMAGE_IDENTITY; +typedef enum _ELF_IMAGE_PROGRAM_HEADER_TYPE ELF_IMAGE_PROGRAM_HEADER_TYPE, *PELF_IMAGE_PROGRAM_HEADER_TYPE; typedef enum _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE; typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE; @@ -202,10 +202,10 @@ typedef struct _EFI_USB_WWID_DEVICE_PATH EFI_USB_WWID_DEVICE_PATH, *PEFI_USB_WWI typedef struct _EFI_VENDOR_DEVICE_PATH EFI_VENDOR_DEVICE_PATH, *PEFI_VENDOR_DEVICE_PATH; typedef struct _EFI_VLAN_DEVICE_PATH EFI_VLAN_DEVICE_PATH, *PEFI_VLAN_DEVICE_PATH; typedef struct _ELF_IMAGE_CONTEXT ELF_IMAGE_CONTEXT, *PELF_IMAGE_CONTEXT; -typedef struct _ELF32_HEADER ELF32_HEADER, *PELF32_HEADER; -typedef struct _ELF64_HEADER ELF64_HEADER, *PELF64_HEADER; -typedef struct _ELF32_PROGRAM_HEADER ELF32_PROGRAM_HEADER, *PELF32_PROGRAM_HEADER; -typedef struct _ELF64_PROGRAM_HEADER ELF64_PROGRAM_HEADER, *PELF64_PROGRAM_HEADER; +typedef struct _ELF_IMAGE_HEADER32 ELF_IMAGE_HEADER32, *PELF_IMAGE_HEADER32; +typedef struct _ELF_IMAGE_HEADER64 ELF_IMAGE_HEADER64, *PELF_IMAGE_HEADER64; +typedef struct _ELF_IMAGE_PROGRAM_HEADER32 ELF_IMAGE_PROGRAM_HEADER32, *PELF_IMAGE_PROGRAM_HEADER32; +typedef struct _ELF_IMAGE_PROGRAM_HEADER64 ELF_IMAGE_PROGRAM_HEADER64, *PELF_IMAGE_PROGRAM_HEADER64; typedef struct _EPROCESS EPROCESS, *PEPROCESS; typedef struct _ETHREAD ETHREAD, *PETHREAD; typedef struct _EX_RUNDOWN_REFERENCE EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE; diff --git a/xtldr/modules/CMakeLists.txt b/xtldr/modules/CMakeLists.txt index e329643..900fff2 100644 --- a/xtldr/modules/CMakeLists.txt +++ b/xtldr/modules/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(beep) add_subdirectory(dummy) add_subdirectory(elf) +add_subdirectory(multiboot2) add_subdirectory(fb_o) add_subdirectory(pecoff_o) add_subdirectory(xtos_o) diff --git a/xtldr/modules/elf/elf.c b/xtldr/modules/elf/elf.c index dc63e3c..0af7365 100644 --- a/xtldr/modules/elf/elf.c +++ b/xtldr/modules/elf/elf.c @@ -8,7 +8,7 @@ #include -/* ELF_O module information */ +/* ELF module information */ XTBL_MODINFO = L"ELF executable file format support"; /* EFI XT Loader Protocol */ @@ -153,7 +153,7 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* Allocate memory for storing image data */ - Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData); + Status = XtLdrProtocol->Memory.AllocatePool(sizeof(ELF_IMAGE_CONTEXT), (PVOID *)&ImageData); if(Status != STATUS_EFI_SUCCESS) { /* Memory allocation failure */ @@ -194,8 +194,19 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* Extract header */ - ImageData->Header32 = (PELF32_HEADER)Data; - ImageData->Header64 = (PELF64_HEADER)Data; + ImageData->Header32 = (PELF_IMAGE_HEADER32)Data; + ImageData->Header64 = (PELF_IMAGE_HEADER64)Data; + + /* Set physical and virtual addresses */ + ImageData->PhysicalAddress = (PVOID)(UINT_PTR)Address; + if(VirtualAddress) + { + ImageData->VirtualAddress = VirtualAddress; + } + else + { + ImageData->VirtualAddress = (PVOID)(UINT_PTR)Address; + } /* Validate ELF file */ if(ImageData->Header32->e_ident[EI_MAG0] != 0x7F || @@ -211,12 +222,13 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, if(ImageData->Header32->e_ident[EI_CLASS] == 1) { /* 32-bit executable */ + XtLdrProtocol->Debug.Print(L"Kernel is a 32-bit executable\n"); /* Set entry point */ ImageData->EntryPoint = (PVOID)(UINT_PTR)ImageData->Header32->e_entry; /* Load individual segments according to program headers */ - PELF32_PROGRAM_HEADER ProgramHeaders = (PELF32_PROGRAM_HEADER)(Data + ImageData->Header32->e_phoff); + PELF_IMAGE_PROGRAM_HEADER32 ProgramHeaders = (PELF_IMAGE_PROGRAM_HEADER32)(Data + ImageData->Header32->e_phoff); for (UINT Count = 0; Count < ImageData->Header32->e_phnum; Count++) { /* PT_DYNAMIC will be used for relocations */ @@ -256,26 +268,19 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, else if(ImageData->Header32->e_ident[EI_CLASS] == 2) { /* 64-bit executable */ + XtLdrProtocol->Debug.Print(L"Kernel is a 64-bit executable\n"); /* Set entry point */ ImageData->EntryPoint = (PVOID)(UINT_PTR)ImageData->Header64->e_entry; + XtLdrProtocol->Debug.Print(L"Entry point: 0x%lx (0x%lx)\n", ImageData->EntryPoint, ImageData->Header64->e_entry); /* Load individual segments according to program headers */ - PELF64_PROGRAM_HEADER ProgramHeaders = (PELF64_PROGRAM_HEADER)(Data + ImageData->Header64->e_phoff); + PELF_IMAGE_PROGRAM_HEADER64 ProgramHeaders = (PELF_IMAGE_PROGRAM_HEADER64)(Data + ImageData->Header64->e_phoff); for (UINT Count = 0; Count < ImageData->Header64->e_phnum; Count++) { /* PT_DYNAMIC will be used for relocations */ if(ProgramHeaders[Count].p_type == PT_LOAD) { - /* Set PhysicalAddress and VirtualAddress to the lowest address present */ - ImageData->PhysicalAddress = (UINT_PTR)ImageData->PhysicalAddress < ProgramHeaders[Count].p_paddr ? - ImageData->PhysicalAddress : - (PVOID)(UINT_PTR)(UINT64)ProgramHeaders[Count].p_paddr; - - ImageData->VirtualAddress = (UINT_PTR)ImageData->VirtualAddress < ProgramHeaders[Count].p_vaddr ? - ImageData->VirtualAddress : - (PVOID)(UINT_PTR)(UINT64)ProgramHeaders[Count].p_vaddr; - /* Allocate memory for the program headers */ UINT32 PageCount = EFI_SIZE_TO_PAGES((UINT32)ProgramHeaders[Count].p_memsz); @@ -289,7 +294,7 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, /* Read segment into memory */ Status = FileHandle->SetPosition(FileHandle, (UINT64)&ProgramHeaders[Count].p_offset); - Status = FileHandle->Read(FileHandle, (PUINT_PTR)&ProgramHeaders[Count].p_filesz, &ProgramHeaders[Count].p_paddr); + Status = FileHandle->Read(FileHandle, (PUINT_PTR)&ProgramHeaders[Count].p_filesz, (PVOID)(UINT_PTR)ProgramHeaders[Count].p_paddr); if(Status != STATUS_EFI_SUCCESS) { /* Failed to read data */ diff --git a/xtldr/modules/elf/includes/elf.h b/xtldr/modules/elf/includes/elf.h index 56d6ee4..fcbe3a9 100644 --- a/xtldr/modules/elf/includes/elf.h +++ b/xtldr/modules/elf/includes/elf.h @@ -6,8 +6,8 @@ * DEVELOPERS: Jozef Nagy */ -#ifndef __XTLDR_MODULES_ELF_O_H -#define __XTLDR_MODULES_ELF_O_H +#ifndef __XTLDR_MODULES_ELF_H +#define __XTLDR_MODULES_ELF_H #include @@ -44,4 +44,4 @@ EFI_STATUS BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, IN PEFI_SYSTEM_TABLE SystemTable); -#endif /* __XTLDR_MODULES_ELF_O_H */ +#endif /* __XTLDR_MODULES_ELF_H */ -- 2.50.1 From 592261310c3698e61c2b7754b706313bfa1e8656 Mon Sep 17 00:00:00 2001 From: Jozef Nagy Date: Wed, 17 Jan 2024 15:35:43 +0100 Subject: [PATCH 5/5] Added test multiboot2 module for XTLDR and relevant XTLDR configuration --- .gitignore | 2 +- bootdata/xtldr/CMakeLists.txt | 1 + bootdata/xtldr/xtldr.ini | 8 + xtldr/modules/elf/elf.c | 5 +- xtldr/modules/multiboot2/CMakeLists.txt | 26 ++ .../modules/multiboot2/includes/multiboot2.h | 63 ++++ xtldr/modules/multiboot2/multiboot2.c | 331 ++++++++++++++++++ 7 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 xtldr/modules/multiboot2/CMakeLists.txt create mode 100644 xtldr/modules/multiboot2/includes/multiboot2.h create mode 100644 xtldr/modules/multiboot2/multiboot2.c diff --git a/.gitignore b/.gitignore index d194e52..fe26926 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ build build-* # TODO: Don't forget to remove this ;) -xtldr/modules/multiboot2 \ No newline at end of file +bootdata/xtldr/kernel.elf \ No newline at end of file diff --git a/bootdata/xtldr/CMakeLists.txt b/bootdata/xtldr/CMakeLists.txt index 9dcfcfb..5212662 100644 --- a/bootdata/xtldr/CMakeLists.txt +++ b/bootdata/xtldr/CMakeLists.txt @@ -1 +1,2 @@ set_install_file(xtldr.ini efi/boot/xtldr) +set_install_file(kernel.elf exectos/boot) diff --git a/bootdata/xtldr/xtldr.ini b/bootdata/xtldr/xtldr.ini index 31dfdfd..a21027c 100644 --- a/bootdata/xtldr/xtldr.ini +++ b/bootdata/xtldr/xtldr.ini @@ -37,6 +37,14 @@ SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS KernelFile=xtoskrnl.exe Parameters=DEBUG=COM1,115200 +[ELFTest] +SystemName="ELF Test" +SystemType=MULTIBOOT2 +BootModules=multiboot2 +SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS +KernelFile=kernel.elf +Parameters= + [Windows] SystemName="Microsoft Windows 2000" SystemType=NT50 diff --git a/xtldr/modules/elf/elf.c b/xtldr/modules/elf/elf.c index 0af7365..94035fe 100644 --- a/xtldr/modules/elf/elf.c +++ b/xtldr/modules/elf/elf.c @@ -275,6 +275,7 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, XtLdrProtocol->Debug.Print(L"Entry point: 0x%lx (0x%lx)\n", ImageData->EntryPoint, ImageData->Header64->e_entry); /* Load individual segments according to program headers */ + XtLdrProtocol->Debug.Print(L"Program header count: %d\n", ImageData->Header64->e_phnum); PELF_IMAGE_PROGRAM_HEADER64 ProgramHeaders = (PELF_IMAGE_PROGRAM_HEADER64)(Data + ImageData->Header64->e_phoff); for (UINT Count = 0; Count < ImageData->Header64->e_phnum; Count++) { @@ -293,7 +294,7 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, } /* Read segment into memory */ - Status = FileHandle->SetPosition(FileHandle, (UINT64)&ProgramHeaders[Count].p_offset); + Status = FileHandle->SetPosition(FileHandle, ProgramHeaders[Count].p_offset); Status = FileHandle->Read(FileHandle, (PUINT_PTR)&ProgramHeaders[Count].p_filesz, (PVOID)(UINT_PTR)ProgramHeaders[Count].p_paddr); if(Status != STATUS_EFI_SUCCESS) { @@ -310,6 +311,8 @@ ElfLoadImage(IN PEFI_FILE_HANDLE FileHandle, UINT_PTR ZeroedMemoryStart = (UINT_PTR)ProgramHeaders[Count].p_paddr + (UINT_PTR)ProgramHeaders[Count].p_filesz; RtlZeroMemory((PVOID)ZeroedMemoryStart, ZeroCount); } + + XtLdrProtocol->Debug.Print(L"Read %d pages (%d bytes) to %lx\n", PageCount, ZeroCount, (UINT64)ProgramHeaders[Count].p_offset); } } } diff --git a/xtldr/modules/multiboot2/CMakeLists.txt b/xtldr/modules/multiboot2/CMakeLists.txt new file mode 100644 index 0000000..1ae62b0 --- /dev/null +++ b/xtldr/modules/multiboot2/CMakeLists.txt @@ -0,0 +1,26 @@ +# XT Boot Loader +PROJECT(XTLDR_MULTIBOOT2) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_MULTIBOOT2_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_MULTIBOOT2_SOURCE + ${XTLDR_MULTIBOOT2_SOURCE_DIR}/multiboot2.c) + +# Link bootloader executable +add_executable(multiboot2 ${XTLDR_MULTIBOOT2_SOURCE}) + +# Add linker libraries +target_link_libraries(multiboot2 libxtos libxtldr) + +# Set proper binary name and install target +set_target_properties(multiboot2 PROPERTIES SUFFIX .efi) +set_install_target(multiboot2 efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(multiboot2 "XtLdrModuleMain") +set_linker_map(multiboot2 TRUE) +set_subsystem(multiboot2 efi_boot_service_driver) diff --git a/xtldr/modules/multiboot2/includes/multiboot2.h b/xtldr/modules/multiboot2/includes/multiboot2.h new file mode 100644 index 0000000..e9e74c3 --- /dev/null +++ b/xtldr/modules/multiboot2/includes/multiboot2.h @@ -0,0 +1,63 @@ +/** + * 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 kernel entry point */ +typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters); + +/* XTOS boot protocol related routines forward references */ +XTCDECL +EFI_STATUS +Multiboot2BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +EFI_STATUS +XtpBootSequence(IN PEFI_FILE_HANDLE BootDir, + IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +EFI_STATUS +XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings, + 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 PELF_IMAGE_CONTEXT *ImageContext); + +XTCDECL +EFI_STATUS +BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif /* __XTLDR_MODULES_XTOS_H */ diff --git a/xtldr/modules/multiboot2/multiboot2.c b/xtldr/modules/multiboot2/multiboot2.c new file mode 100644 index 0000000..2da40b5 --- /dev/null +++ b/xtldr/modules/multiboot2/multiboot2.c @@ -0,0 +1,331 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/multiboot2/multiboot2.c + * DESCRIPTION: Multiboot2 boot protocol support + * DEVELOPERS: Jozef Nagy + */ + +#include + +/* XTOS module information */ +XTBL_MODINFO = L"Multiboot2 boot protocol support"; +XTBL_MODDEPS = {L"elf"}; + +/* EFI XT Loader Protocol */ +PXTBL_LOADER_PROTOCOL XtLdrProtocol; + +/* XTOS ELF Image Protocol */ +PXTBL_EXECUTABLE_IMAGE_PROTOCOL XtElfProtocol; + +/* XTOS Boot Protocol */ +XTBL_BOOT_PROTOCOL Multiboot2BootProtocol; + +/* XTOS Page Map */ +PVOID XtPageMap; + +/** + * 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 +Multiboot2BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) +{ + EFI_GUID ElfProtocolGuid = XT_ELF_IMAGE_PROTOCOL_GUID; + EFI_HANDLE DiskHandle, ProtocolHandle; + PEFI_FILE_HANDLE FsHandle, BootDir; + PWCHAR SystemPath; + EFI_STATUS Status; + + /* Print debug message */ + XtLdrProtocol->Debug.Print(L"Multiboot2 boot protocol activated\n"); + + /* Open the XT ELF protocol */ + Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&XtElfProtocol, &ElfProtocolGuid); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open loader protocol */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to load ELF image protocol\n"); + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Check device path */ + if(Parameters->DevicePath == NULL) + { + /* 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 != NULL) + { + /* 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 == NULL) + { + /* No kernel filename set, fallback to default */ + XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n"); + Parameters->KernelFile = L"kernel.elf"; + } + + /* Check if provided any kernel boot arguments */ + if(Parameters->Parameters == NULL) + { + /* 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(NULL, &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; + PKERNEL_INITIALIZATION_BLOCK KernelParameters; + PELF_IMAGE_CONTEXT ImageContext = NULL; + PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol; + PVOID VirtualAddress, VirtualMemoryArea; + PXT_ENTRY_POINT KernelEntryPoint; + LIST_ENTRY MemoryMappings; + EFI_HANDLE ProtocolHandle; + EFI_STATUS Status; + + /* Initialize XTOS startup sequence */ + XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n"); + + /* Set base virtual memory area for the kernel mappings */ + VirtualMemoryArea = (PVOID)KSEG0_BASE; + VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE); + + /* Load the kernel */ + Status = XtpLoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to load the kernel */ + return Status; + } + + /* Get kernel entry point */ + XtElfProtocol->GetEntryPoint(ImageContext, (PVOID)&KernelEntryPoint); + + /* Close boot directory handle */ + BootDir->Close(BootDir); + + /* Call XTOS kernel */ + XtLdrProtocol->Debug.Print(L"Booting the ELF Multiboot2 kernel\n"); + KernelEntryPoint(KernelParameters); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Loads XTOS ELF module. + * + * @param SystemDir + * An EFI handle to the opened system directory containing a module that will be loaded. + * + * @param FileName + * An on disk filename of the module that will be loaded. + * + * @param VirtualAddress + * Optional virtual address pointing to the memory area where ELF file will be loaded. + * + * @param MemoryType + * Supplies the type of memory to be assigned to the memory descriptor. + * + * @param ImageContext + * Supplies pointer to the memory area where loaded ELF image context will be stored. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +XtpLoadModule(IN PEFI_FILE_HANDLE SystemDir, + IN PWCHAR FileName, + IN PVOID VirtualAddress, + IN LOADER_MEMORY_TYPE MemoryType, + OUT PELF_IMAGE_CONTEXT *ImageContext) +{ + PEFI_FILE_HANDLE ModuleHandle; + USHORT MachineType, SubSystem; + EFI_STATUS Status; + + /* Print debug message */ + XtLdrProtocol->Debug.Print(L"Loading %S... \n", FileName); + + /* Open module file */ + Status = SystemDir->Open(SystemDir, &ModuleHandle, FileName, EFI_FILE_MODE_READ, 0); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to open the file */ + XtLdrProtocol->Debug.Print(L"ERROR: Failed to open '%S'\n", FileName); + return Status; + } + + /* Load the ELF image file */ + Status = XtElfProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID)ImageContext); + if(Status != STATUS_EFI_SUCCESS) + { + /* Unable to load the file */ + XtLdrProtocol->Debug.Print(L"ERROR: Failed to load '%S'\n", FileName); + return Status; + } + + /* Close image file */ + ModuleHandle->Close(ModuleHandle); + + /* Check ELF image machine type compatibility */ + XtElfProtocol->GetMachineType(*ImageContext, &MachineType); + if(MachineType != 0x03 && + MachineType != 0x32 && + MachineType != 0x3E) + { + /* Machine type mismatch */ + XtLdrProtocol->Debug.Print(L"ERROR: Loaded incompatible ELF image (machine type mismatch)\n"); + return STATUS_EFI_INCOMPATIBLE_VERSION; + } + + /* Print debug message */ + XtLdrProtocol->Debug.Print(L"Loaded %S at PA: 0x%lx, VA: 0x%lx\n", FileName, + (*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * This routine is the entry point of the XT EFI boot loader module. + * + * @param ImageHandle + * Firmware-allocated handle that identifies the image. + * + * @param SystemTable + * Provides the EFI system table. + * + * @return This routine returns status code. + * + * @since XT 1.0 + */ +XTCDECL +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 Multiboot2 boot protocol */ + Multiboot2BootProtocol.BootSystem = Multiboot2BootSystem; + + /* Register XTOS boot protocol */ + XtLdrProtocol->Boot.RegisterProtocol(L"MULTIBOOT2", &Guid); + + /* Install XTOS protocol */ + return XtLdrProtocol->Protocol.Install(&Multiboot2BootProtocol, &Guid); +} -- 2.50.1