1*530d68baSNigel Croxon #include "lib.h" 2*530d68baSNigel Croxon 3*530d68baSNigel Croxon #include "efiprot.h" 4*530d68baSNigel Croxon #include "efishellintf.h" 5*530d68baSNigel Croxon #include "efishellparm.h" 6*530d68baSNigel Croxon 7*530d68baSNigel Croxon #ifndef MAX_ARGV_CONTENTS_SIZE 8*530d68baSNigel Croxon # define MAX_CMDLINE_SIZE 1024 9*530d68baSNigel Croxon #endif 10*530d68baSNigel Croxon #ifndef MAX_ARGC 11*530d68baSNigel Croxon # define MAX_CMDLINE_ARGC 32 12*530d68baSNigel Croxon #endif 13*530d68baSNigel Croxon 14*530d68baSNigel Croxon /* 15*530d68baSNigel Croxon Parse LoadedImage options area, called only in case the regular 16*530d68baSNigel Croxon shell protos are not available. 17*530d68baSNigel Croxon 18*530d68baSNigel Croxon Format of LoadedImage->LoadOptions appears to be a 19*530d68baSNigel Croxon single-space-separated list of args (looks like the shell already 20*530d68baSNigel Croxon pre-parses the input, it apparently folds several consecutive spaces 21*530d68baSNigel Croxon into one): 22*530d68baSNigel Croxon argv[0] space argv[1] (etc.) argv[N] space \0 cwd \0 other data 23*530d68baSNigel Croxon For safety, we support the trailing \0 without a space before, as 24*530d68baSNigel Croxon well as several consecutive spaces (-> several args). 25*530d68baSNigel Croxon */ 26*530d68baSNigel Croxon static 27*530d68baSNigel Croxon INTN 28*530d68baSNigel Croxon GetShellArgcArgvFromLoadedImage( 29*530d68baSNigel Croxon EFI_HANDLE ImageHandle, 30*530d68baSNigel Croxon CHAR16 **ResultArgv[] 31*530d68baSNigel Croxon ) 32*530d68baSNigel Croxon { 33*530d68baSNigel Croxon EFI_STATUS Status; 34*530d68baSNigel Croxon EFI_LOADED_IMAGE *LoadedImage = NULL; 35*530d68baSNigel Croxon static CHAR16 ArgvContents[MAX_CMDLINE_SIZE]; 36*530d68baSNigel Croxon static CHAR16 *Argv[MAX_CMDLINE_ARGC], *ArgStart, *c; 37*530d68baSNigel Croxon UINTN Argc = 0, BufLen; 38*530d68baSNigel Croxon 39*530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6, 40*530d68baSNigel Croxon ImageHandle, 41*530d68baSNigel Croxon &LoadedImageProtocol, 42*530d68baSNigel Croxon &LoadedImage, 43*530d68baSNigel Croxon ImageHandle, 44*530d68baSNigel Croxon NULL, 45*530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL 46*530d68baSNigel Croxon ); 47*530d68baSNigel Croxon if (EFI_ERROR(Status)) 48*530d68baSNigel Croxon return -1; 49*530d68baSNigel Croxon 50*530d68baSNigel Croxon BufLen = LoadedImage->LoadOptionsSize; 51*530d68baSNigel Croxon if (BufLen < 2) /* We are expecting at least a \0 */ 52*530d68baSNigel Croxon return -1; 53*530d68baSNigel Croxon else if (BufLen > sizeof(ArgvContents)) 54*530d68baSNigel Croxon BufLen = sizeof(ArgvContents); 55*530d68baSNigel Croxon 56*530d68baSNigel Croxon CopyMem(ArgvContents, LoadedImage->LoadOptions, BufLen); 57*530d68baSNigel Croxon ArgvContents[MAX_CMDLINE_SIZE - 1] = L'\0'; 58*530d68baSNigel Croxon 59*530d68baSNigel Croxon for (c = ArgStart = ArgvContents ; *c != L'\0' ; ++c) { 60*530d68baSNigel Croxon if (*c == L' ') { 61*530d68baSNigel Croxon *c = L'\0'; 62*530d68baSNigel Croxon if (Argc < MAX_CMDLINE_ARGC) Argv[Argc++] = ArgStart; 63*530d68baSNigel Croxon ArgStart = c + 1; 64*530d68baSNigel Croxon } 65*530d68baSNigel Croxon } 66*530d68baSNigel Croxon 67*530d68baSNigel Croxon if ((*ArgStart != L'\0') && (Argc < MAX_CMDLINE_ARGC)) 68*530d68baSNigel Croxon Argv[Argc++] = ArgStart; 69*530d68baSNigel Croxon 70*530d68baSNigel Croxon // Print(L"Got argc/argv from loaded image proto\n"); 71*530d68baSNigel Croxon *ResultArgv = Argv; 72*530d68baSNigel Croxon return Argc; 73*530d68baSNigel Croxon } 74*530d68baSNigel Croxon 75*530d68baSNigel Croxon INTN GetShellArgcArgv(EFI_HANDLE ImageHandle, CHAR16 **Argv[]) 76*530d68baSNigel Croxon { 77*530d68baSNigel Croxon // Code inspired from EDK2's 78*530d68baSNigel Croxon // ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c (BSD) 79*530d68baSNigel Croxon EFI_STATUS Status; 80*530d68baSNigel Croxon static const EFI_GUID EfiShellParametersProtocolGuid 81*530d68baSNigel Croxon = EFI_SHELL_PARAMETERS_PROTOCOL_GUID; 82*530d68baSNigel Croxon static const EFI_GUID ShellInterfaceProtocolGuid 83*530d68baSNigel Croxon = SHELL_INTERFACE_PROTOCOL_GUID; 84*530d68baSNigel Croxon EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL; 85*530d68baSNigel Croxon EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL; 86*530d68baSNigel Croxon 87*530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6, 88*530d68baSNigel Croxon ImageHandle, 89*530d68baSNigel Croxon &EfiShellParametersProtocolGuid, 90*530d68baSNigel Croxon (VOID **)&EfiShellParametersProtocol, 91*530d68baSNigel Croxon ImageHandle, 92*530d68baSNigel Croxon NULL, 93*530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL 94*530d68baSNigel Croxon ); 95*530d68baSNigel Croxon if (!EFI_ERROR(Status)) 96*530d68baSNigel Croxon { 97*530d68baSNigel Croxon // use shell 2.0 interface 98*530d68baSNigel Croxon // Print(L"Got argc/argv from shell intf proto\n"); 99*530d68baSNigel Croxon *Argv = EfiShellParametersProtocol->Argv; 100*530d68baSNigel Croxon return EfiShellParametersProtocol->Argc; 101*530d68baSNigel Croxon } 102*530d68baSNigel Croxon 103*530d68baSNigel Croxon // try to get shell 1.0 interface instead. 104*530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6, 105*530d68baSNigel Croxon ImageHandle, 106*530d68baSNigel Croxon &ShellInterfaceProtocolGuid, 107*530d68baSNigel Croxon (VOID **)&EfiShellInterfaceProtocol, 108*530d68baSNigel Croxon ImageHandle, 109*530d68baSNigel Croxon NULL, 110*530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL 111*530d68baSNigel Croxon ); 112*530d68baSNigel Croxon if (!EFI_ERROR(Status)) 113*530d68baSNigel Croxon { 114*530d68baSNigel Croxon // Print(L"Got argc/argv from shell params proto\n"); 115*530d68baSNigel Croxon *Argv = EfiShellInterfaceProtocol->Argv; 116*530d68baSNigel Croxon return EfiShellInterfaceProtocol->Argc; 117*530d68baSNigel Croxon } 118*530d68baSNigel Croxon 119*530d68baSNigel Croxon // shell 1.0 and 2.0 interfaces failed 120*530d68baSNigel Croxon return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv); 121*530d68baSNigel Croxon } 122