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