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