diff --git a/xtldr/modules/CMakeLists.txt b/xtldr/modules/CMakeLists.txt index 375c1d7..705ca81 100644 --- a/xtldr/modules/CMakeLists.txt +++ b/xtldr/modules/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(beep) +add_subdirectory(chainldr) add_subdirectory(dummy) add_subdirectory(fb_o) add_subdirectory(pecoff_o) diff --git a/xtldr/modules/chainldr/CMakeLists.txt b/xtldr/modules/chainldr/CMakeLists.txt new file mode 100644 index 0000000..5fcb8de --- /dev/null +++ b/xtldr/modules/chainldr/CMakeLists.txt @@ -0,0 +1,27 @@ +# XTLDR Chain Loader Module +PROJECT(XTLDR_CHAINLDR) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTLDR_CHAINLDR_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTLDR_CHAINLDR_SOURCE + ${XTLDR_CHAINLDR_SOURCE_DIR}/chainldr.c + ${XTLDR_CHAINLDR_SOURCE_DIR}/globals.c) + +# Link module executable +add_executable(chainldr ${XTLDR_CHAINLDR_SOURCE}) + +# Add linker libraries +target_link_libraries(chainldr libxtldr libxtos) + +# Set proper binary name and install target +set_target_properties(chainldr PROPERTIES SUFFIX .efi) +set_install_target(chainldr efi/boot/xtldr/modules) + +# Set module entrypoint and subsystem +set_entrypoint(chainldr "XtLdrModuleMain") +set_linker_map(chainldr TRUE) +set_subsystem(chainldr efi_boot_service_driver) diff --git a/xtldr/modules/chainldr/chainldr.c b/xtldr/modules/chainldr/chainldr.c new file mode 100644 index 0000000..2ba93ac --- /dev/null +++ b/xtldr/modules/chainldr/chainldr.c @@ -0,0 +1,160 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/chainldr/chainldr.c + * DESCRIPTION: XTLDR Chain Loader + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* ChainLoader module information */ +XTBL_MODINFO = L"XTLDR Chain Loader"; + +/** + * Chainloads another boot loader. + * + * @param Parameters + * Input parameters with detailed system configuration. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +ChBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters) +{ + EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + EFI_MEMMAP_DEVICE_PATH MemoryDevicePath[2]; + PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; + EFI_HANDLE DiskHandle, LoaderHandle; + PEFI_FILE_HANDLE FsHandle, BootDir; + EFI_STATUS Status; + SIZE_T LoaderSize; + PVOID LoaderData; + + /* Check if image file is provided */ + if(Parameters->KernelFile == NULL) + { + /* No image filename provided, return error code */ + XtLdrProtocol->Debug.Print(L"ERROR: No EFI image filename provided\n"); + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Open EFI volume */ + Status = XtLdrProtocol->Disk.OpenVolume(NULL, &DiskHandle, &FsHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open a volume, return error code */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume (Status Code: 0x%lx)\n", Status); + return Status; + } + + /* Open boot directory and close FS handle */ + Status = FsHandle->Open(FsHandle, &BootDir, Parameters->EfiPath, EFI_FILE_MODE_READ, 0); + FsHandle->Close(FsHandle); + + /* Check if system path directory opened successfully */ + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open directory */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory (Status Code: 0x%lx)\n", Status); + + /* Close volume and return error code */ + XtLdrProtocol->Disk.CloseVolume(DiskHandle); + return Status; + } + + /* Read EFI image file from disk and close both directory and EFI volume */ + Status = XtLdrProtocol->Disk.ReadFile(BootDir, Parameters->KernelFile, &LoaderData, &LoaderSize); + BootDir->Close(BootDir); + XtLdrProtocol->Disk.CloseVolume(DiskHandle); + + /* Setup device path for EFI image */ + MemoryDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH); + MemoryDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8; + MemoryDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH; + MemoryDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP; + MemoryDevicePath[0].MemoryType = EfiLoaderData; + MemoryDevicePath[0].StartingAddress = (UINT_PTR)LoaderData; + MemoryDevicePath[0].EndingAddress = (UINT_PTR)LoaderData + LoaderSize; + MemoryDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); + MemoryDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8; + MemoryDevicePath[1].Header.Type = EFI_END_DEVICE_PATH; + MemoryDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP; + + /* Load EFI image */ + Status = XtLdrProtocol->Util.LoadEfiImage((PEFI_DEVICE_PATH_PROTOCOL)MemoryDevicePath, + LoaderData, LoaderSize, &LoaderHandle); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to chainload EFI binary, return error code */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to chainload '%S' (Status Code: 0x%lx)\n", + Parameters->KernelFile, Status); + return Status; + } + + /* Access loaded image protocol */ + Status = XtLdrProtocol->Protocol.OpenHandle(LoaderHandle, (PVOID *)&LoadedImage, &LIPGuid); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open EFI_LOADED_IMAGE_PROTOCOL, return error code */ + XtLdrProtocol->Debug.Print(L"ERROR: Unable to access binary interface (Status Code: 0x%lx)\n", Status); + return Status; + } + + /* Check if parameters provided */ + if(Parameters->Parameters) + { + /* Pass arguments to chainloaded image */ + LoadedImage->LoadOptionsSize = RtlWideStringLength(Parameters->Parameters, 0) * sizeof(WCHAR); + LoadedImage->LoadOptions = Parameters->Parameters; + } + + /* Set device handle as LoadImage() is not going to do it */ + LoadedImage->DeviceHandle = DiskHandle; + + /* Chainload EFI image */ + return XtLdrProtocol->Util.StartEfiImage(LoaderHandle); +} + +/** + * 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_CHAIN_BOOT_PROTOCOL_GUID; + EFI_STATUS Status; + + /* Open the XTLDR protocol */ + Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open the protocol, return error */ + return STATUS_EFI_PROTOCOL_ERROR; + } + + /* Set routines available via ChainLoader boot protocol */ + ChBootProtocol.BootSystem = ChBootSystem; + + /* Register XTOS boot protocol */ + XtLdrProtocol->Boot.RegisterProtocol(L"CHAINLOADER", &Guid); + + /* Install XTOS protocol */ + return XtLdrProtocol->Protocol.Install(&ChBootProtocol, &Guid); +} diff --git a/xtldr/modules/chainldr/globals.c b/xtldr/modules/chainldr/globals.c new file mode 100644 index 0000000..fb3e1c1 --- /dev/null +++ b/xtldr/modules/chainldr/globals.c @@ -0,0 +1,16 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/chainldr/globals.c + * DESCRIPTION: XTLDR Chain Loader global variables + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/* ChainLoader Boot Protocol */ +XTBL_BOOT_PROTOCOL ChBootProtocol; + +/* XTLDR protocol handler */ +PXTBL_LOADER_PROTOCOL XtLdrProtocol; diff --git a/xtldr/modules/chainldr/includes/chainldr.h b/xtldr/modules/chainldr/includes/chainldr.h new file mode 100644 index 0000000..9fdf0c5 --- /dev/null +++ b/xtldr/modules/chainldr/includes/chainldr.h @@ -0,0 +1,26 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/chainldr/includes/chainldr.h + * DESCRIPTION: XTLDR Chain Loader header file + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_CHAINLDR_CHAINLDR_H +#define __XTLDR_CHAINLDR_CHAINLDR_H + +#include +#include + + +/* ChainLoader module routines forward references */ +XTCDECL +EFI_STATUS +ChBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters); + +XTCDECL +EFI_STATUS +XtLdrModuleMain(IN EFI_HANDLE ImageHandle, + IN PEFI_SYSTEM_TABLE SystemTable); + +#endif/* __XTLDR_CHAINLDR_CHAINLDR_H */ diff --git a/xtldr/modules/chainldr/includes/globals.h b/xtldr/modules/chainldr/includes/globals.h new file mode 100644 index 0000000..b47c032 --- /dev/null +++ b/xtldr/modules/chainldr/includes/globals.h @@ -0,0 +1,21 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtldr/modules/chainldr/includes/globals.h + * DESCRIPTION: XTLDR Chain Loader global variables + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTLDR_CHAINLDR_GLOBALS_H +#define __XTLDR_CHAINLDR_GLOBALS_H + +#include + + +/* ChainLoader Boot Protocol */ +EXTERN XTBL_BOOT_PROTOCOL ChBootProtocol; + +/* XTLDR protocol handler */ +EXTERN PXTBL_LOADER_PROTOCOL XtLdrProtocol; + +#endif/* __XTLDR_CHAINLDR_GLOBALS_H */