diff options
author | Steve McIntyre <steve@einval.com> | 2021-03-23 23:49:46 +0000 |
---|---|---|
committer | Steve McIntyre <steve@einval.com> | 2021-03-23 23:49:46 +0000 |
commit | 1251a7ba86fc40a6aad8b4fecdbca2b61808d9fa (patch) | |
tree | 2125fda549aaca55cb49a48d54be77dec7fbf3df /gnu-efi/lib/cmdline.c | |
parent | 85b409232ce89b34626df9d72abedf5d4f5ccef6 (diff) | |
parent | 031e5cce385d3f96b1caa1d53495332a7eb03749 (diff) | |
download | efi-boot-shim-debian/15.3-1.tar.gz efi-boot-shim-debian/15.3-1.zip |
Update upstream source from tag 'upstream/15.3'debian/15.3-1
Update to upstream version '15.3'
with Debian dir 1b484f1c1ac270604a5a1451b34de4b0865c6211
Diffstat (limited to 'gnu-efi/lib/cmdline.c')
-rw-r--r-- | gnu-efi/lib/cmdline.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/gnu-efi/lib/cmdline.c b/gnu-efi/lib/cmdline.c new file mode 100644 index 00000000..f21c44cb --- /dev/null +++ b/gnu-efi/lib/cmdline.c @@ -0,0 +1,121 @@ +#include "lib.h" + +#include "efiprot.h" +#include "efishellintf.h" +#include "efishellparm.h" + +#ifndef MAX_ARGV_CONTENTS_SIZE +# define MAX_CMDLINE_SIZE 1024 +#endif +#ifndef MAX_ARGC +# define MAX_CMDLINE_ARGC 32 +#endif + +/* + Parse LoadedImage options area, called only in case the regular + shell protos are not available. + + Format of LoadedImage->LoadOptions appears to be a + single-space-separated list of args (looks like the shell already + pre-parses the input, it apparently folds several consecutive spaces + into one): + argv[0] space argv[1] (etc.) argv[N] space \0 cwd \0 other data + For safety, we support the trailing \0 without a space before, as + well as several consecutive spaces (-> several args). +*/ +static +INTN +GetShellArgcArgvFromLoadedImage( + EFI_HANDLE ImageHandle, + CHAR16 **ResultArgv[] + ) +{ + EFI_STATUS Status; + void *LoadedImage = NULL; + static CHAR16 ArgvContents[MAX_CMDLINE_SIZE]; + static CHAR16 *Argv[MAX_CMDLINE_ARGC], *ArgStart, *c; + UINTN Argc = 0, BufLen; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + &LoadedImageProtocol, + &LoadedImage, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) + return -1; + + BufLen = ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptionsSize; + if (BufLen < 2) /* We are expecting at least a \0 */ + return -1; + else if (BufLen > sizeof(ArgvContents)) + BufLen = sizeof(ArgvContents); + + CopyMem(ArgvContents, ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptions, BufLen); + ArgvContents[MAX_CMDLINE_SIZE - 1] = L'\0'; + + for (c = ArgStart = ArgvContents ; *c != L'\0' ; ++c) { + if (*c == L' ') { + *c = L'\0'; + if (Argc < MAX_CMDLINE_ARGC) Argv[Argc++] = ArgStart; + ArgStart = c + 1; + } + } + + if ((*ArgStart != L'\0') && (Argc < MAX_CMDLINE_ARGC)) + Argv[Argc++] = ArgStart; + + // Print(L"Got argc/argv from loaded image proto\n"); + *ResultArgv = Argv; + return Argc; +} + +INTN GetShellArgcArgv(EFI_HANDLE ImageHandle, CHAR16 **Argv[]) +{ + // Code inspired from EDK2's + // ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c (BSD) + EFI_STATUS Status; + static const EFI_GUID EfiShellParametersProtocolGuid + = EFI_SHELL_PARAMETERS_PROTOCOL_GUID; + static const EFI_GUID ShellInterfaceProtocolGuid + = SHELL_INTERFACE_PROTOCOL_GUID; + EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL; + EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + (EFI_GUID*)&EfiShellParametersProtocolGuid, + (VOID **)&EfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // use shell 2.0 interface + // Print(L"Got argc/argv from shell intf proto\n"); + *Argv = EfiShellParametersProtocol->Argv; + return EfiShellParametersProtocol->Argc; + } + + // try to get shell 1.0 interface instead. + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + (EFI_GUID*)&ShellInterfaceProtocolGuid, + (VOID **)&EfiShellInterfaceProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // Print(L"Got argc/argv from shell params proto\n"); + *Argv = EfiShellInterfaceProtocol->Argv; + return EfiShellInterfaceProtocol->Argc; + } + + // shell 1.0 and 2.0 interfaces failed + return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv); +} |