WIP: ELF Module for XTLDR #8
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,3 +2,6 @@
|
|||||||
.vscode
|
.vscode
|
||||||
build
|
build
|
||||||
build-*
|
build-*
|
||||||
|
|
||||||
|
# TODO: Don't forget to remove this ;)
|
||||||
|
bootdata/xtldr/kernel.elf
|
@@ -1 +1,2 @@
|
|||||||
set_install_file(xtldr.ini efi/boot/xtldr)
|
set_install_file(xtldr.ini efi/boot/xtldr)
|
||||||
|
set_install_file(kernel.elf exectos/boot)
|
||||||
|
@@ -37,6 +37,14 @@ SystemPath=multi(0)disk(0)rdisk(0)partition(1)/ExectOS
|
|||||||
KernelFile=xtoskrnl.exe
|
KernelFile=xtoskrnl.exe
|
||||||
Parameters=DEBUG=COM1,115200
|
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]
|
[Windows]
|
||||||
SystemName="Microsoft Windows 2000"
|
SystemName="Microsoft Windows 2000"
|
||||||
SystemType=NT50
|
SystemType=NT50
|
||||||
|
@@ -606,4 +606,115 @@ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY
|
|||||||
ULONG Reserved;
|
ULONG Reserved;
|
||||||
} PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY;
|
} PECOFF_IMAGE_RESOURCE_DATA_ENTRY, *PPECOFF_IMAGE_RESOURCE_DATA_ENTRY;
|
||||||
|
|
||||||
|
/* ELF identities */
|
||||||
|
typedef enum _ELF_IMAGE_IDENTITY
|
||||||
|
|||||||
|
{
|
||||||
|
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_IMAGE_IDENTITY, *PELF_IMAGE_IDENTITY;
|
||||||
|
|
||||||
|
/* ELF Program header types */
|
||||||
|
typedef enum _ELF_IMAGE_PROGRAM_HEADER_TYPE
|
||||||
belliash
commented
_ELF_IMAGE_PROGRAM_TYPE ? _ELF_IMAGE_PROGRAM_TYPE ?
|
|||||||
|
{
|
||||||
|
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_IMAGE_PROGRAM_HEADER_TYPE, *PELF_IMAGE_PROGRAM_HEADER_TYPE;
|
||||||
|
|
||||||
|
/* ELF image representation structure */
|
||||||
|
typedef struct _ELF_IMAGE_CONTEXT
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
PELF_IMAGE_HEADER32 Header32;
|
||||||
|
PELF_IMAGE_HEADER64 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 _ELF_IMAGE_HEADER32
|
||||||
belliash
commented
Maybe _ELF_IMAGE_HEADER32? Maybe _ELF_IMAGE_HEADER32?
|
|||||||
|
{
|
||||||
|
/* 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;
|
||||||
|
} ELF_IMAGE_HEADER32, *PELF_IMAGE_HEADER32;
|
||||||
|
|
||||||
|
/* 64-bit ELF image header structure */
|
||||||
|
typedef struct _ELF_IMAGE_HEADER64
|
||||||
belliash
commented
_ELF_IMAGE_HEADER64 ? _ELF_IMAGE_HEADER64 ?
|
|||||||
|
{
|
||||||
|
/* 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;
|
||||||
|
} ELF_IMAGE_HEADER64, *PELF_IMAGE_HEADER64;
|
||||||
|
|
||||||
|
/* 32-bit ELF program header structure */
|
||||||
|
typedef struct _ELF_IMAGE_PROGRAM_HEADER32
|
||||||
belliash
commented
_ELF_IMAGE_PROGRAM_HEADER32? _ELF_IMAGE_PROGRAM_HEADER32?
|
|||||||
|
{
|
||||||
|
UINT32 p_type;
|
||||||
|
UINT32 p_offset;
|
||||||
|
UINT32 p_vaddr;
|
||||||
|
UINT32 p_paddr;
|
||||||
|
UINT32 p_filesz;
|
||||||
|
UINT32 p_memsz;
|
||||||
|
UINT32 p_flags;
|
||||||
|
UINT32 p_align;
|
||||||
|
} ELF_IMAGE_PROGRAM_HEADER32, *PELF_IMAGE_PROGRAM_HEADER32;
|
||||||
|
|
||||||
|
/* 64-bit ELF program header structure */
|
||||||
|
typedef struct _ELF_IMAGE_PROGRAM_HEADER64
|
||||||
belliash
commented
_ELF_IMAGE_PROGRAM_HEADER64? _ELF_IMAGE_PROGRAM_HEADER64?
|
|||||||
|
{
|
||||||
|
UINT32 p_type;
|
||||||
|
UINT32 p_flags;
|
||||||
|
ULONG p_offset;
|
||||||
|
ULONG p_vaddr;
|
||||||
|
ULONG p_paddr;
|
||||||
|
ULONG p_filesz;
|
||||||
|
ULONG p_memsz;
|
||||||
|
ULONG p_align;
|
||||||
|
} ELF_IMAGE_PROGRAM_HEADER64, *PELF_IMAGE_PROGRAM_HEADER64;
|
||||||
|
|
||||||
#endif /* __XTDK_XTIMAGE_H */
|
#endif /* __XTDK_XTIMAGE_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_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_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 _EFI_UNIVERSA_GRAPHICS_BLT_OPERATION EFI_UNIVERSA_GRAPHICS_BLT_OPERATION, *PEFI_UNIVERSA_GRAPHICS_BLT_OPERATION;
|
||||||
|
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 _KAPC_ENVIRONMENT KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
|
||||||
typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE;
|
typedef enum _KDPC_IMPORTANCE KDPC_IMPORTANCE, *PKDPC_IMPORTANCE;
|
||||||
typedef enum _KEVENT_TYPE KEVENT_TYPE, *PKEVENT_TYPE;
|
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_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_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 _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 _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 _EPROCESS EPROCESS, *PEPROCESS;
|
||||||
typedef struct _ETHREAD ETHREAD, *PETHREAD;
|
typedef struct _ETHREAD ETHREAD, *PETHREAD;
|
||||||
typedef struct _EX_RUNDOWN_REFERENCE EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE;
|
typedef struct _EX_RUNDOWN_REFERENCE EX_RUNDOWN_REFERENCE, *PEX_RUNDOWN_REFERENCE;
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
add_subdirectory(beep)
|
add_subdirectory(beep)
|
||||||
add_subdirectory(dummy)
|
add_subdirectory(dummy)
|
||||||
|
add_subdirectory(elf)
|
||||||
|
add_subdirectory(multiboot2)
|
||||||
add_subdirectory(fb_o)
|
add_subdirectory(fb_o)
|
||||||
add_subdirectory(pecoff_o)
|
add_subdirectory(pecoff_o)
|
||||||
add_subdirectory(xtos_o)
|
add_subdirectory(xtos_o)
|
||||||
|
26
xtldr/modules/elf/CMakeLists.txt
Normal file
26
xtldr/modules/elf/CMakeLists.txt
Normal file
@@ -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)
|
||||||
belliash
commented
libxtos should not be needed, is it? libxtos should not be needed, is it?
|
|||||||
|
|
||||||
|
# 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)
|
379
xtldr/modules/elf/elf.c
Normal file
379
xtldr/modules/elf/elf.c
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtldr/modules/elf/elf.c
|
||||||
|
* DESCRIPTION: ELF executable file format support module
|
||||||
|
* DEVELOPERS: Jozef Nagy <schkwve@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
/* ELF module information */
|
||||||
belliash
commented
ELF module information? Looks like a typo. ELF module information? Looks like a typo.
|
|||||||
|
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");
|
||||||
belliash
commented
I suggest to print status code as well where possible. I suggest to print status code as well where possible.
|
|||||||
|
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(ELF_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 = (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
|
||||||
|
{
|
||||||
belliash
commented
XTBL_EXECUTABLE_IMAGE_PROTOCOL expects some validation routine. Could you reconsider creating ElfVerifyImage() routine and just calling it from ElfLoadImage()? XTBL_EXECUTABLE_IMAGE_PROTOCOL expects some validation routine. Could you reconsider creating ElfVerifyImage() routine and just calling it from ElfLoadImage()?
|
|||||||
|
ImageData->VirtualAddress = (PVOID)(UINT_PTR)Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
/* PT_DYNAMIC will be used for relocations */
|
||||||
|
if(ProgramHeaders[Count].p_type == PT_LOAD)
|
||||||
|
{
|
||||||
|
/* 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, 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)
|
||||||
|
{
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
XtLdrProtocol->Debug.Print(L"Read %d pages (%d bytes) to %lx\n", PageCount, ZeroCount, (UINT64)ProgramHeaders[Count].p_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
47
xtldr/modules/elf/includes/elf.h
Normal file
47
xtldr/modules/elf/includes/elf.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtldr/modules/elf/includes/elf.h
|
||||||
|
* DESCRIPTION: ELF executable file format support header
|
||||||
|
* DEVELOPERS: Jozef Nagy <schkwve@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XTLDR_MODULES_ELF_H
|
||||||
belliash
commented
__XTLDR_MODULES_ELF_H ? __XTLDR_MODULES_ELF_H ?
|
|||||||
|
#define __XTLDR_MODULES_ELF_H
|
||||||
|
|
||||||
|
#include <xtblapi.h>
|
||||||
|
|
||||||
|
/* 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_H */
|
||||||
belliash
commented
__XTLDR_MODULES_ELF_H ? __XTLDR_MODULES_ELF_H ?
|
26
xtldr/modules/multiboot2/CMakeLists.txt
Normal file
26
xtldr/modules/multiboot2/CMakeLists.txt
Normal file
@@ -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)
|
63
xtldr/modules/multiboot2/includes/multiboot2.h
Normal file
63
xtldr/modules/multiboot2/includes/multiboot2.h
Normal file
@@ -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 <belliash@codingworkshop.eu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XTLDR_MODULES_XTOS_H
|
||||||
|
#define __XTLDR_MODULES_XTOS_H
|
||||||
|
|
||||||
|
#include <xtblapi.h>
|
||||||
|
|
||||||
|
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 */
|
331
xtldr/modules/multiboot2/multiboot2.c
Normal file
331
xtldr/modules/multiboot2/multiboot2.c
Normal file
@@ -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 <schkwve@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <multiboot2.h>
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
Reference in New Issue
Block a user
Maybe _ELF_IMAGE_IDENTITY ?