Initial modules support
All checks were successful
Builds / ExectOS (amd64) (push) Successful in 30s
Builds / ExectOS (i686) (push) Successful in 27s

This commit is contained in:
2023-12-30 00:57:01 +01:00
parent e686b6f342
commit ea32946bbd
12 changed files with 468 additions and 5 deletions

View File

@@ -9,6 +9,14 @@
#include <xtldr.h>
XTCDECL
EFI_STATUS
BlLoadModule(IN PWCHAR Module);
XTCDECL
EFI_STATUS
BlLoadModules(IN PWCHAR ModulesList);
/**
* Initializes a list of operating systems for XTLDR boot menu.
*
@@ -96,6 +104,266 @@ BlInitializeBootMenuList(OUT PXTBL_BOOTMENU_ITEM MenuEntries,
MenuEntries = OsList;
}
/**
* Loads all necessary modules and invokes boot protocol.
*
* @param OptionsList
* Supplies a pointer to list of options associated with chosen boot menu entry.
*
* @return This routine returns a status code.
*
* @since XT 1.0
*/
XTCDECL
EFI_STATUS
BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList)
{
PWCHAR ModulesList, ProtocolName;
PLIST_ENTRY OptionsListEntry;
PXTBL_CONFIG_ENTRY Option;
EFI_STATUS Status;
/* Set default values */
ModulesList = NULL;
ProtocolName = NULL;
/* Iterate through all options provided by boot menu entry */
OptionsListEntry = OptionsList->Flink;
while(OptionsListEntry != OptionsList)
{
/* Get option */
Option = CONTAIN_RECORD(OptionsListEntry, XTBL_CONFIG_ENTRY, Flink);
/* Look for boot protocol and modules list */
if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMTYPE", 0) == 0)
{
/* Boot protocol found */
ProtocolName = Option->Value;
}
else if(RtlCompareWideStringInsensitive(Option->Name, L"BOOTMODULES", 0) == 0)
{
/* Set protocol name */
ModulesList = Option->Value;
}
/* Move to the next option entry */
OptionsListEntry = OptionsListEntry->Flink;
}
/* Load all necessary modules */
Status = BlLoadModules(ModulesList);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to load modules, print error message and return status code */
BlDebugPrint(L"Failed to load XTLDR modules\n");
return Status;
}
for(;;);
/* This point should never be reached */
return STATUS_EFI_SUCCESS;
}
XTCDECL
EFI_STATUS
BlLoadModules(IN PWCHAR ModulesList)
{
PWCHAR LastModule, Module;
EFI_STATUS Status;
if(ModulesList != NULL)
{
/* Tokenize provided list of modules */
Module = RtlTokenizeWideString(ModulesList, L" ", &LastModule);
/* Iterate over all arguments passed to boot loader */
while(Module != NULL)
{
Status = BlLoadModule(Module);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to load module, print error message and return status code */
BlDebugPrint(L"Failed to load module '%S', status = 0x%lx\n", Module, Status);
// return Status;
}
/* Take next module from the list */
Module = RtlTokenizeWideString(NULL, L" ", &LastModule);
}
}
/* Return success */
return STATUS_EFI_SUCCESS;
}
XTCDECL
EFI_STATUS
BlLoadModule(IN PWCHAR ModuleName)
{
EFI_MEMMAP_DEVICE_PATH ModuleDevicePath[2];
PEFI_FILE_HANDLE DirHandle, FsHandle;
EFI_HANDLE DiskHandle, ModuleHandle;
PPECOFF_IMAGE_SECTION_HEADER SectionHeader;
PPECOFF_IMAGE_DOS_HEADER DosHeader;
PPECOFF_IMAGE_PE_HEADER PeHeader;
PLIST_ENTRY ModuleListEntry;
WCHAR ModuleFileName[1024];
USHORT SectionIndex;
SIZE_T ModuleSize;
EFI_STATUS Status;
PVOID ModuleData;
PWCHAR DepsData;
PXTBL_MODULE_INFO ModuleInfo;
ModuleListEntry = BlpLoadedModules.Flink;
while(ModuleListEntry != &BlpLoadedModules)
{
/* Get module information */
ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink);
if(RtlCompareWideStringInsensitive(ModuleInfo->ModuleName, ModuleName, 0) == 0)
{
/* Module already loaded */
BlDebugPrint(L"Module '%S' already loaded\n", ModuleName);
return STATUS_EFI_SUCCESS;
}
/* Move to the module */
ModuleListEntry = ModuleListEntry->Flink;
}
/* Print debug message */
BlDebugPrint(L"Loading module '%S' ...\n", ModuleName);
/* Set module path */
RtlCopyMemory(ModuleFileName, ModuleName, sizeof(ModuleFileName) / sizeof(WCHAR));
RtlConcatenateWideString(ModuleFileName, L".EFI", 0);
/* Open EFI volume */
Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to open a volume */
return Status;
}
/* Open XTLDR modules directory and close the FS immediately */
Status = FsHandle->Open(FsHandle, &DirHandle, XTBL_MODULES_DIRECTORY_PATH, EFI_FILE_MODE_READ, 0);
FsHandle->Close(FsHandle);
/* Check if directory opened successfully */
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to open directory */
BlCloseVolume(DiskHandle);
return Status;
}
/* Read module file from disk and close EFI volume */
Status = BlReadFile(DirHandle, ModuleFileName, &ModuleData, &ModuleSize);
BlCloseVolume(DiskHandle);
/* Make sure module file was read successfully */
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to read file */
return Status;
}
/* Allocate memory for new option */
Status = BlMemoryAllocatePool(sizeof(XTBL_MODULE_INFO), (PVOID*)&ModuleInfo);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to allocate memory */
return Status;
}
RtlZeroMemory(ModuleInfo, sizeof(XTBL_MODULE_INFO));
/* Setup PE/COFF EFI image headers */
DosHeader = (PPECOFF_IMAGE_DOS_HEADER)ModuleData;
PeHeader = (PPECOFF_IMAGE_PE_HEADER)(ModuleData + DosHeader->e_lfanew);
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader +
PeHeader->FileHeader.SizeOfOptionalHeader);
/* Look for .moddeps section */
for(SectionIndex = 0; SectionIndex < PeHeader->FileHeader.NumberOfSections; SectionIndex++)
{
/* Check section name */
if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".moddeps", 8) == 0)
{
/* Store address of .moddeps data segment */
DepsData = ModuleData + SectionHeader[SectionIndex].PointerToRawData;
/* Iterate over all dependencies stored */
while(*DepsData != 0)
{
/* Load dependency module */
BlDebugPrint(L"Module '%S' requires '%S' ...\n", ModuleName, DepsData);
Status = BlLoadModule(DepsData);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to load module, print error message and return status code */
BlDebugPrint(L"Failed to load dependency module '%S', status = 0x%lx\n", DepsData, Status);
return STATUS_EFI_UNSUPPORTED;
}
/* Add dependency module name to the list */
RtlConcatenateWideString(ModuleInfo->Dependencies, DepsData, RtlWideStringLength(DepsData, 0));
RtlConcatenateWideString(ModuleInfo->Dependencies, L" ", 1);
/* Get next dependency module name */
DepsData += 8;
}
}
else if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".modinfo", 8) == 0)
{
/* Store module description */
ModuleInfo->ModuleDescription = ModuleData + SectionHeader[SectionIndex].PointerToRawData;
}
}
/* Store module name */
ModuleInfo->ModuleName = ModuleName;
/* Setup module device path */
ModuleDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH);
ModuleDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8;
ModuleDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH;
ModuleDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP;
ModuleDevicePath[0].MemoryType = EfiLoaderData;
ModuleDevicePath[0].StartingAddress = (UINT_PTR)ModuleData;
ModuleDevicePath[0].EndingAddress = (UINT_PTR)ModuleData + ModuleSize;
ModuleDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL);
ModuleDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8;
ModuleDevicePath[1].Header.Type = EFI_END_DEVICE_PATH;
ModuleDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP;
/* Load EFI image */
Status = EfiSystemTable->BootServices->LoadImage(FALSE, EfiImageHandle, (PEFI_DEVICE_PATH_PROTOCOL)ModuleDevicePath,
ModuleData, ModuleSize, &ModuleHandle);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to load module image */
return Status;
}
/* Start EFI image */
Status = EfiSystemTable->BootServices->StartImage(ModuleHandle, NULL, NULL);
if(Status != STATUS_EFI_SUCCESS)
{
/* Failed to start module image */
return Status;
}
/* Add module to the list of loaded modules */
RtlInsertTailList(&BlpLoadedModules, &ModuleInfo->Flink);
/* Return success */
return STATUS_EFI_SUCCESS;
}
/**
* This routine is the entry point of the XT EFI boot loader.
*
@@ -187,6 +455,41 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
return Status;
}
BlLoadModules(BlGetConfigValue(L"MODULES"));
BlLoadModule(L"DUMMY");
BlConsolePrint(L"\n\n\n\n\n\n\n\nList of loaded modules:");
PLIST_ENTRY ModuleListEntry;
PXTBL_MODULE_INFO ModuleInfo;
ModuleListEntry = BlpLoadedModules.Flink;
while(ModuleListEntry != &BlpLoadedModules)
{
/* Get module information */
ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink);
/* Module already loaded */
BlConsolePrint(L"\n%.8S", ModuleInfo->ModuleName);
if(ModuleInfo->ModuleDescription != 0)
{
BlConsolePrint(L" (%S)", ModuleInfo->ModuleDescription);
}
if(ModuleInfo->Dependencies[0] != 0)
{
BlConsolePrint(L"\n - Uses: %S", ModuleInfo->Dependencies);
}
/* Move to the module */
ModuleListEntry = ModuleListEntry->Flink;
}
BlConsolePrint(L"\n\n END OF LIST\n");
for(;;);
for(;;)
{
if(BlpStatus.BootMenu != NULL)