WIP: ELF Module for XTLDR #8

Closed
Ghost wants to merge 5 commits from (deleted):master into master
12 changed files with 1004 additions and 0 deletions

3
.gitignore vendored
View File

@@ -2,3 +2,6 @@
.vscode
build
build-*
# TODO: Don't forget to remove this ;)
bootdata/xtldr/kernel.elf

View File

@@ -1 +1,2 @@
set_install_file(xtldr.ini efi/boot/xtldr)
set_install_file(kernel.elf exectos/boot)

View File

@@ -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

View File

@@ -606,4 +606,115 @@ typedef struct _PECOFF_IMAGE_RESOURCE_DATA_ENTRY
ULONG Reserved;
} 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
{
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
{
/* 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
{
/* 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
{
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
{
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 */

View File

@@ -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_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;
@@ -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 _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;

View File

@@ -1,5 +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)

View 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)
Review

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
View 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 */
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");
Review

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
{
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);
}

View 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
#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 */

View 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)

View 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 */

View 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);
}