From 17c50ea9127de02fe79c3d5e7e9fa32b795af2ca Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Wed, 28 Feb 2024 23:28:33 +0100 Subject: [PATCH] Redesign a way of storing module information; this allows to store more data in a single section, like license or a list of authors, as well as solves the problem with different module name lengths --- sdk/xtdk/bltarget.h | 14 +- sdk/xtdk/bltypes.h | 10 + sdk/xtdk/xtstruct.h | 1 + xtldr/includes/xtldr.h | 13 ++ xtldr/modules/acpi/acpi.c | 5 +- xtldr/modules/beep/beep.c | 7 +- xtldr/modules/chainldr/chainldr.c | 5 +- xtldr/modules/dummy/dummy.c | 5 +- xtldr/modules/framebuf/framebuf.c | 5 +- xtldr/modules/pecoff/pecoff.c | 5 +- xtldr/modules/xtos_o/xtos.c | 7 +- xtldr/protocol.c | 332 ++++++++++++++++++++++++++---- 12 files changed, 354 insertions(+), 55 deletions(-) diff --git a/sdk/xtdk/bltarget.h b/sdk/xtdk/bltarget.h index 95b6091..5548da0 100644 --- a/sdk/xtdk/bltarget.h +++ b/sdk/xtdk/bltarget.h @@ -12,9 +12,17 @@ #include -/* Boot Loader module segment macros */ -#define XTBL_MODDEPS SEGMENT(".moddeps") CONST WCHAR XtBlpDeps[][9] -#define XTBL_MODINFO SEGMENT(".modinfo") CONST WCHAR XtBlpInfo[] +/* Boot Loader module information macros */ +#define MODULE_AUTHOR(_author) XTBL_MODULE_INFO(author, author, _author) +#define MODULE_DEPENDENCY(_softdeps) XTBL_MODULE_INFO(softdeps, softdeps, _softdeps) +#define MODULE_DESCRIPTION(_description) XTBL_MODULE_INFO(description, description, _description) +#define MODULE_LICENSE(_license) XTBL_MODULE_INFO(license, license, _license) +#define MODULE_VERSION(_version) XTBL_MODULE_INFO(version, version, _version) + +/* Boot Loader module information segment macro */ +#define XTBL_MODULE_INFO(Tag, Name, Data) STATIC CONST WCHAR UNIQUE(Name)[] \ + USED SEGMENT(".modinfo") ALIGN(1) \ + = STRINGIFY(Tag) "=" Data /* XTLDR directories */ #define XTBL_LOADER_DIRECTORY_PATH L"\\EFI\\BOOT\\XTLDR\\" diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 04b3e38..2ad09a5 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -190,6 +190,13 @@ typedef struct _XTBL_MEMORY_MAPPING LOADER_MEMORY_TYPE MemoryType; } XTBL_MEMORY_MAPPING, *PXTBL_MEMORY_MAPPING; +/* XTLDR Module dependencies data */ +typedef struct _XTBL_MODULE_AUTHORS +{ + LIST_ENTRY Flink; + PWCHAR AuthorName; +} XTBL_MODULE_AUTHORS, *PXTBL_MODULE_AUTHORS; + /* XTLDR Module dependencies data */ typedef struct _XTBL_MODULE_DEPS { @@ -203,6 +210,9 @@ typedef struct _XTBL_MODULE_INFO LIST_ENTRY Flink; PWCHAR ModuleName; PWCHAR ModuleDescription; + PWCHAR License; + PWCHAR Version; + LIST_ENTRY Authors; LIST_ENTRY Dependencies; PVOID ModuleBase; ULONGLONG ModuleSize; diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index a0a135d..9f998f8 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -282,6 +282,7 @@ typedef struct _XTBL_FRAMEBUFFER_PROTOCOL XTBL_FRAMEBUFFER_PROTOCOL, *PXTBL_FRAM typedef struct _XTBL_KNOWN_BOOT_PROTOCOL XTBL_KNOWN_BOOT_PROTOCOL, *PXTBL_KNOWN_BOOT_PROTOCOL; typedef struct _XTBL_LOADER_PROTOCOL XTBL_LOADER_PROTOCOL, *PXTBL_LOADER_PROTOCOL; typedef struct _XTBL_MEMORY_MAPPING XTBL_MEMORY_MAPPING, *PXTBL_MEMORY_MAPPING; +typedef struct _XTBL_MODULE_AUTHORS XTBL_MODULE_AUTHORS, *PXTBL_MODULE_AUTHORS; typedef struct _XTBL_MODULE_DEPS XTBL_MODULE_DEPS, *PXTBL_MODULE_DEPS; typedef struct _XTBL_MODULE_INFO XTBL_MODULE_INFO, *PXTBL_MODULE_INFO; typedef struct _XTBL_PAGE_MAPPING XTBL_PAGE_MAPPING, *PXTBL_PAGE_MAPPING; diff --git a/xtldr/includes/xtldr.h b/xtldr/includes/xtldr.h index 1daf189..8b10200 100644 --- a/xtldr/includes/xtldr.h +++ b/xtldr/includes/xtldr.h @@ -444,6 +444,19 @@ XTCDECL LOADER_MEMORY_TYPE BlpGetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType); +XTCDECL +EFI_STATUS +BlpGetModuleInformation(IN PWCHAR SectionData, + IN ULONG SectionSize, + OUT PXTBL_MODULE_INFO ModuleInfo); + +XTCDECL +EFI_STATUS +BlpGetModuleInfoStrings(IN PWCHAR SectionData, + IN ULONG SectionSize, + OUT PWCHAR **ModInfo, + OUT PULONG InfoCount); + XTCDECL EFI_STATUS BlpGetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap, diff --git a/xtldr/modules/acpi/acpi.c b/xtldr/modules/acpi/acpi.c index ab27870..55ae86e 100644 --- a/xtldr/modules/acpi/acpi.c +++ b/xtldr/modules/acpi/acpi.c @@ -10,7 +10,10 @@ /* Dummy module information */ -XTBL_MODINFO = L"ACPI support"; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"ACPI support"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Attempts to get XSDP. If it is not found or checksum mismatch, it will try to get RSDP instead. diff --git a/xtldr/modules/beep/beep.c b/xtldr/modules/beep/beep.c index ca583d4..ef3d5fd 100644 --- a/xtldr/modules/beep/beep.c +++ b/xtldr/modules/beep/beep.c @@ -9,8 +9,11 @@ #include -/* Dummy module information */ -XTBL_MODINFO = L"Plays a GRUB compatible tune via PC speaker"; +/* Beep module information */ +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"Plays a GRUB compatible tune via PC speaker"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Disables the PC speaker. diff --git a/xtldr/modules/chainldr/chainldr.c b/xtldr/modules/chainldr/chainldr.c index f9e71e8..88c2b77 100644 --- a/xtldr/modules/chainldr/chainldr.c +++ b/xtldr/modules/chainldr/chainldr.c @@ -10,7 +10,10 @@ /* ChainLoader module information */ -XTBL_MODINFO = L"XTLDR Chain Loader"; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"XTLDR Chain Loader"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Chainloads another boot loader. diff --git a/xtldr/modules/dummy/dummy.c b/xtldr/modules/dummy/dummy.c index 9d7e677..dc37eca 100644 --- a/xtldr/modules/dummy/dummy.c +++ b/xtldr/modules/dummy/dummy.c @@ -10,7 +10,10 @@ /* Dummy module information */ -XTBL_MODINFO = L"XTLDR Dummy Module"; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"XTLDR Dummy Module"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Stub boot routine. diff --git a/xtldr/modules/framebuf/framebuf.c b/xtldr/modules/framebuf/framebuf.c index ad43f2e..d5ab242 100644 --- a/xtldr/modules/framebuf/framebuf.c +++ b/xtldr/modules/framebuf/framebuf.c @@ -10,7 +10,10 @@ /* PE/COFF_O module information */ -XTBL_MODINFO = L"EFI FB (FrameBuffer) support"; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"EFI FB (FrameBuffer) support"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Provides an EFI Frame Buffer protocol driver name used for initialization. diff --git a/xtldr/modules/pecoff/pecoff.c b/xtldr/modules/pecoff/pecoff.c index d883c6c..d520bb3 100644 --- a/xtldr/modules/pecoff/pecoff.c +++ b/xtldr/modules/pecoff/pecoff.c @@ -10,7 +10,10 @@ /* PE/COFF_O module information */ -XTBL_MODINFO = L"Basic PE/COFF executable file format support"; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"Basic PE/COFF executable file format support"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /** * Returns the address of the entry point. diff --git a/xtldr/modules/xtos_o/xtos.c b/xtldr/modules/xtos_o/xtos.c index 8056d8d..b7adbb9 100644 --- a/xtldr/modules/xtos_o/xtos.c +++ b/xtldr/modules/xtos_o/xtos.c @@ -10,8 +10,11 @@ /* XTOS module information */ -XTBL_MODINFO = L"XTOS boot protocol support"; -XTBL_MODDEPS = {L"acpi", L"framebuf", L"pecoff"}; +MODULE_AUTHOR(L"Rafal Kupiec "); +MODULE_DESCRIPTION(L"XTOS boot protocol support"); +MODULE_DEPENDENCY(L"acpi framebuf pecoff"); +MODULE_LICENSE(L"GPLv3"); +MODULE_VERSION(L"0.1"); /* EFI XT Loader Protocol */ PXTBL_LOADER_PROTOCOL XtLdrProtocol; diff --git a/xtldr/protocol.c b/xtldr/protocol.c index f941bae..c5a5ee5 100644 --- a/xtldr/protocol.c +++ b/xtldr/protocol.c @@ -129,6 +129,7 @@ EFI_STATUS BlLoadModule(IN PWCHAR ModuleName) { EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + PLIST_ENTRY DepsListEntry, ModuleListEntry; EFI_MEMMAP_DEVICE_PATH ModuleDevicePath[2]; PEFI_LOADED_IMAGE_PROTOCOL LoadedImage; PEFI_FILE_HANDLE DirHandle, FsHandle; @@ -136,15 +137,14 @@ BlLoadModule(IN PWCHAR ModuleName) PPECOFF_IMAGE_SECTION_HEADER SectionHeader; PPECOFF_IMAGE_DOS_HEADER DosHeader; PPECOFF_IMAGE_PE_HEADER PeHeader; - PXTBL_MODULE_DEPS ModuleDependencies; + PXTBL_MODULE_DEPS ModuleDependency; PXTBL_MODULE_INFO ModuleInfo; - PLIST_ENTRY ModuleListEntry; WCHAR ModuleFileName[24]; USHORT SectionIndex; + PWCHAR SectionData; SIZE_T ModuleSize; EFI_STATUS Status; PVOID ModuleData; - PWCHAR DepsData; ModuleListEntry = BlpLoadedModules.Flink; while(ModuleListEntry != &BlpLoadedModules) @@ -217,9 +217,8 @@ BlLoadModule(IN PWCHAR ModuleName) return Status; } - /* Zero module information block and initialize dependencies list */ + /* Zero module information block */ RtlZeroMemory(ModuleInfo, sizeof(XTBL_MODULE_INFO)); - RtlInitializeListHead(&ModuleInfo->Dependencies); /* Setup PE/COFF EFI image headers */ DosHeader = (PPECOFF_IMAGE_DOS_HEADER)ModuleData; @@ -227,51 +226,44 @@ BlLoadModule(IN PWCHAR ModuleName) SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&PeHeader->OptionalHeader + PeHeader->FileHeader.SizeOfOptionalHeader); - /* Look for .moddeps and .modinfo sections */ + /* Look for .modinfo section */ for(SectionIndex = 0; SectionIndex < PeHeader->FileHeader.NumberOfSections; SectionIndex++) { - /* Check section name */ - if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".moddeps", 8) == 0) + if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".modinfo", 8) == 0) { - /* Store address of .moddeps data segment */ - DepsData = ModuleData + SectionHeader[SectionIndex].PointerToRawData; + /* Module information section found */ + SectionData = ModuleData + SectionHeader[SectionIndex].PointerToRawData; - /* Iterate over all dependencies stored */ - while(*DepsData != 0) + /* Get module information */ + Status = BlpGetModuleInformation(SectionData, SectionHeader[SectionIndex].SizeOfRawData, ModuleInfo); + if(Status != STATUS_EFI_SUCCESS) { - /* 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 Code: 0x%zX)\n", DepsData, Status); - return STATUS_EFI_UNSUPPORTED; - } - - /* Allocate memory for module dependency */ - Status = BlAllocateMemoryPool(sizeof(XTBL_MODULE_DEPS), (PVOID*)&ModuleDependencies); - if(Status == STATUS_EFI_SUCCESS) - { - /* Memory allocated successfully, store module's dependency */ - ModuleDependencies->ModuleName = DepsData; - RtlInsertTailList(&ModuleInfo->Dependencies, &ModuleDependencies->Flink); - } - - /* Get next dependency module name */ - DepsData += 9; + /* Failed to read module information */ + return Status; } } - else if(RtlCompareString((PCHAR)SectionHeader[SectionIndex].Name, ".modinfo", 8) == 0) - { - /* Store module description */ - ModuleInfo->ModuleDescription = ModuleData + SectionHeader[SectionIndex].PointerToRawData; - } } - /* Finally, store module name */ - ModuleInfo->ModuleName = ModuleName; + /* Iterate through module dependencies */ + DepsListEntry = ModuleInfo->Dependencies.Flink; + while(DepsListEntry != &ModuleInfo->Dependencies) + { + /* Get module dependency information */ + ModuleDependency = CONTAIN_RECORD(DepsListEntry, XTBL_MODULE_DEPS, Flink); + + /* Load dependency module */ + BlDebugPrint(L"Module '%S' requires '%S' ...\n", ModuleName, ModuleDependency->ModuleName); + Status = BlLoadModule(ModuleDependency->ModuleName); + 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 Code: 0x%zX)\n", ModuleDependency->ModuleName, Status); + return STATUS_EFI_UNSUPPORTED; + } + + /* Move to the next dependency */ + DepsListEntry = DepsListEntry->Flink; + } /* Setup module device path */ ModuleDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH); @@ -287,6 +279,7 @@ BlLoadModule(IN PWCHAR ModuleName) ModuleDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP; /* Load EFI image */ + BlDebugPrint(L"Starting module '%S' ...\n", ModuleName); Status = BlLoadEfiImage((PEFI_DEVICE_PATH_PROTOCOL)ModuleDevicePath, ModuleData, ModuleSize, &ModuleHandle); if(Status != STATUS_EFI_SUCCESS) { @@ -326,7 +319,8 @@ BlLoadModule(IN PWCHAR ModuleName) EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL); } - /* Save module information */ + /* Save additional module information, not found in '.modinfo' section */ + ModuleInfo->ModuleName = ModuleName; ModuleInfo->ModuleBase = LoadedImage->ImageBase; ModuleInfo->ModuleSize = LoadedImage->ImageSize; ModuleInfo->Revision = LoadedImage->Revision; @@ -383,7 +377,7 @@ BlLoadModules(IN PWCHAR ModulesList) if(Status != STATUS_EFI_SUCCESS) { /* Failed to load module, print error message and set new return value */ - BlDebugPrint(L"ERROR: Failed to load module '%S', (Status Code: 0x%zX)\n", Module, Status); + BlDebugPrint(L"ERROR: Failed to load module '%S' (Status Code: 0x%zX)\n", Module, Status); ReturnStatus = STATUS_EFI_LOAD_ERROR; } @@ -589,6 +583,258 @@ BlRegisterBootProtocol(IN PWCHAR SystemType, return STATUS_EFI_SUCCESS; } +/** + * Reads information from the '.modinfo' section and populates the module information structure. + * + * @param SectionData + * Supplies a pointer to the module's information section data. + * + * @param SectionSize + * Supplies an expected size of the section data. + * + * @param ModuleInfo + * Supplies a pointer to the module information structure that will be filled by data from module's info section. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpGetModuleInformation(IN PWCHAR SectionData, + IN ULONG SectionSize, + OUT PXTBL_MODULE_INFO ModuleInfo) +{ + PXTBL_MODULE_DEPS ModuleDependencies; + PXTBL_MODULE_AUTHORS ModuleAuthors; + PWCHAR Dependency, Key, LastStr; + ULONG Index, Count; + EFI_STATUS Status; + PWCHAR *Strings; + + /* Initialize authors and dependencies lists */ + RtlInitializeListHead(&ModuleInfo->Authors); + RtlInitializeListHead(&ModuleInfo->Dependencies); + + /* Get information strings from '.modinfo' section */ + Status = BlpGetModuleInfoStrings(SectionData, SectionSize, &Strings, &Count); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to get information strings */ + return Status; + } + + /* Parse information strings */ + for(Index = 0; Index < Count; Index++) + { + /* Store the key */ + Key = Strings[Index]; + + /* Find the end of the key and the beginning of the value */ + while(*Strings[Index] != L'=' && *Strings[Index] != L'\0' && *Strings[Index] != L'\n') + { + /* Move to the next character */ + Strings[Index]++; + } + + /* Make sure value is NULL-terminated */ + *Strings[Index] = L'\0'; + Strings[Index]++; + + /* Parse information string key */ + if(RtlCompareWideString(Key, L"author", 6) == 0) + { + /* Allocate memory for module author */ + Status = BlAllocateMemoryPool(sizeof(XTBL_MODULE_AUTHORS), (PVOID*)&ModuleAuthors); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Store module's author */ + ModuleAuthors->AuthorName = Strings[Index]; + RtlInsertTailList(&ModuleInfo->Authors, &ModuleAuthors->Flink); + } + else if(RtlCompareWideString(Key, L"description", 11) == 0) + { + /* Store module's description */ + ModuleInfo->ModuleDescription = Strings[Index]; + } + else if(RtlCompareWideString(Key, L"license", 7) == 0) + { + /* Store module's license */ + ModuleInfo->License = Strings[Index]; + } + else if(RtlCompareWideString(Key, L"softdeps", 6) == 0) + { + /* Tokenize value to get module's single dependency */ + Dependency = RtlTokenizeWideString(Strings[Index], L" ", &LastStr); + while(Dependency != NULL) + { + /* Allocate memory for module dependency */ + Status = BlAllocateMemoryPool(sizeof(XTBL_MODULE_DEPS), (PVOID*)&ModuleDependencies); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure */ + return Status; + } + + /* Store module's dependency */ + ModuleDependencies->ModuleName = Dependency; + RtlInsertTailList(&ModuleInfo->Dependencies, &ModuleDependencies->Flink); + + /* Get next dependency from single value if available */ + Dependency = RtlTokenizeWideString(NULL, L" ", &LastStr); + } + } + else if(RtlCompareWideString(Key, L"version", 7) == 0) + { + /* Store module's version */ + ModuleInfo->Version = Strings[Index]; + } + } + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + +/** + * Reads raw data from the '.modinfo' section and populates an array of strings. + * + * @param SectionData + * Supplies a pointer to the module's information section data. + * + * @param SectionSize + * Supplies an expected size of the section data. + * + * @param ModInfo + * Supplies a pointer to memory area, where an array of strings read from the section will be stored. + * + * @param InfoCount + * Supplies a pointer to variable that will receive the number of strings found in the section. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +BlpGetModuleInfoStrings(IN PWCHAR SectionData, + IN ULONG SectionSize, + OUT PWCHAR **ModInfo, + OUT PULONG InfoCount) +{ + ULONG Count, Index, ArrayIndex; + PCWSTR InfoStrings; + EFI_STATUS Status; + PWCHAR *Array; + PWCHAR String; + + /* Check input parameters */ + InfoStrings = SectionData; + if(!InfoStrings || !SectionSize) + { + /* Invalid input parameters */ + return STATUS_EFI_INVALID_PARAMETER; + } + + /* Skip zero padding */ + while(InfoStrings[0] == L'\0' && SectionSize > 1) + { + /* Get next character and decrement section size */ + InfoStrings++; + SectionSize--; + } + + /* Make sure there is at least one string available */ + if(SectionSize <= 1) + { + /* No strings found */ + return STATUS_EFI_END_OF_FILE; + } + + /* Count number of strings */ + Index = 0; + Count = 0; + while(Index < SectionSize) + { + /* Get to the next string */ + if(InfoStrings[Index] != L'\0') + { + /* Get next character */ + Index++; + continue; + } + + /* Skip zero padding */ + while(InfoStrings[Index] == L'\0' && Index < SectionSize) + { + /* Get next character */ + Index++; + } + + /* New string found, increment counter */ + Count++; + } + + /* Make sure there is no missing string */ + if(InfoStrings[Index - 1] != L'\0') + { + /* One more string available */ + Count++; + } + + /* Allocate memory for array of strings */ + Status = BlAllocateMemoryPool(SectionSize + 1 + sizeof(PWCHAR) * (Count + 1), (PVOID *)&Array); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory */ + return STATUS_EFI_OUT_OF_RESOURCES; + } + + /* Cioy strings read from '.modinfo' section */ + String = (PWCHAR)(Array + Count + 1); + RtlCopyMemory(String, InfoStrings, SectionSize); + + /* Make sure last string is NULL-terminated */ + String[SectionSize] = L'\0'; + Array[Count] = NULL; + Array[0] = String; + + /* Parse strings into array */ + Index = 0; + ArrayIndex = 1; + while(Index < SectionSize && ArrayIndex < Count) + { + /* Get to the next string */ + if(String[Index] != L'\0') + { + /* Get next character */ + Index++; + continue; + } + + /* Skip zero padding */ + while(InfoStrings[Index] == L'\0' && Index < SectionSize) + { + /* Get next character */ + Index++; + } + + /* Push string into array */ + Array[ArrayIndex] = &String[Index]; + ArrayIndex++; + } + + /* Return array of strings and its size */ + *ModInfo = Array; + *InfoCount = Count; + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * This routine installs XTLDR protocol for further usage by modules. *