Home | History | Annotate | Line # | Download | only in lib
cmdline.c revision 1.1
      1  1.1  jmcneill /*	$NetBSD: cmdline.c,v 1.1 2018/08/16 18:17:47 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  jmcneill #include "efishellintf.h"
      7  1.1  jmcneill #include "efishellparm.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 EfiShellParametersProtocolGuid
     83  1.1  jmcneill       = EFI_SHELL_PARAMETERS_PROTOCOL_GUID;
     84  1.1  jmcneill   static const EFI_GUID ShellInterfaceProtocolGuid
     85  1.1  jmcneill       = SHELL_INTERFACE_PROTOCOL_GUID;
     86  1.1  jmcneill   EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL;
     87  1.1  jmcneill   EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL;
     88  1.1  jmcneill 
     89  1.1  jmcneill   Status = uefi_call_wrapper(BS->OpenProtocol, 6,
     90  1.1  jmcneill                              ImageHandle,
     91  1.1  jmcneill                              (EFI_GUID*)&EfiShellParametersProtocolGuid,
     92  1.1  jmcneill                              (VOID **)&EfiShellParametersProtocol,
     93  1.1  jmcneill                              ImageHandle,
     94  1.1  jmcneill                              NULL,
     95  1.1  jmcneill                              EFI_OPEN_PROTOCOL_GET_PROTOCOL
     96  1.1  jmcneill                              );
     97  1.1  jmcneill   if (!EFI_ERROR(Status))
     98  1.1  jmcneill   {
     99  1.1  jmcneill     // use shell 2.0 interface
    100  1.1  jmcneill     // Print(L"Got argc/argv from shell intf proto\n");
    101  1.1  jmcneill     *Argv = EfiShellParametersProtocol->Argv;
    102  1.1  jmcneill     return EfiShellParametersProtocol->Argc;
    103  1.1  jmcneill   }
    104  1.1  jmcneill 
    105  1.1  jmcneill   // try to get shell 1.0 interface instead.
    106  1.1  jmcneill   Status = uefi_call_wrapper(BS->OpenProtocol, 6,
    107  1.1  jmcneill                              ImageHandle,
    108  1.1  jmcneill                              (EFI_GUID*)&ShellInterfaceProtocolGuid,
    109  1.1  jmcneill                              (VOID **)&EfiShellInterfaceProtocol,
    110  1.1  jmcneill                              ImageHandle,
    111  1.1  jmcneill                              NULL,
    112  1.1  jmcneill                              EFI_OPEN_PROTOCOL_GET_PROTOCOL
    113  1.1  jmcneill                              );
    114  1.1  jmcneill   if (!EFI_ERROR(Status))
    115  1.1  jmcneill   {
    116  1.1  jmcneill     // Print(L"Got argc/argv from shell params proto\n");
    117  1.1  jmcneill     *Argv = EfiShellInterfaceProtocol->Argv;
    118  1.1  jmcneill     return EfiShellInterfaceProtocol->Argc;
    119  1.1  jmcneill   }
    120  1.1  jmcneill 
    121  1.1  jmcneill   // shell 1.0 and 2.0 interfaces failed
    122  1.1  jmcneill   return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv);
    123  1.1  jmcneill }
    124