1530d68baSNigel Croxon #include "lib.h"
2530d68baSNigel Croxon
3530d68baSNigel Croxon #include "efiprot.h"
4*773f30afSJiaqing Zhao #include "efishell.h"
5530d68baSNigel Croxon #include "efishellintf.h"
6530d68baSNigel Croxon
7530d68baSNigel Croxon #ifndef MAX_ARGV_CONTENTS_SIZE
8530d68baSNigel Croxon # define MAX_CMDLINE_SIZE 1024
9530d68baSNigel Croxon #endif
10530d68baSNigel Croxon #ifndef MAX_ARGC
11530d68baSNigel Croxon # define MAX_CMDLINE_ARGC 32
12530d68baSNigel Croxon #endif
13530d68baSNigel Croxon
14530d68baSNigel Croxon /*
15530d68baSNigel Croxon Parse LoadedImage options area, called only in case the regular
16530d68baSNigel Croxon shell protos are not available.
17530d68baSNigel Croxon
18530d68baSNigel Croxon Format of LoadedImage->LoadOptions appears to be a
19530d68baSNigel Croxon single-space-separated list of args (looks like the shell already
20530d68baSNigel Croxon pre-parses the input, it apparently folds several consecutive spaces
21530d68baSNigel Croxon into one):
22530d68baSNigel Croxon argv[0] space argv[1] (etc.) argv[N] space \0 cwd \0 other data
23530d68baSNigel Croxon For safety, we support the trailing \0 without a space before, as
24530d68baSNigel Croxon well as several consecutive spaces (-> several args).
25530d68baSNigel Croxon */
26530d68baSNigel Croxon static
27530d68baSNigel Croxon INTN
GetShellArgcArgvFromLoadedImage(EFI_HANDLE ImageHandle,CHAR16 ** ResultArgv[])28530d68baSNigel Croxon GetShellArgcArgvFromLoadedImage(
29530d68baSNigel Croxon EFI_HANDLE ImageHandle,
30530d68baSNigel Croxon CHAR16 **ResultArgv[]
31530d68baSNigel Croxon )
32530d68baSNigel Croxon {
33530d68baSNigel Croxon EFI_STATUS Status;
34087d22afSNigel Croxon void *LoadedImage = NULL;
35530d68baSNigel Croxon static CHAR16 ArgvContents[MAX_CMDLINE_SIZE];
36530d68baSNigel Croxon static CHAR16 *Argv[MAX_CMDLINE_ARGC], *ArgStart, *c;
37530d68baSNigel Croxon UINTN Argc = 0, BufLen;
38530d68baSNigel Croxon
39530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6,
40530d68baSNigel Croxon ImageHandle,
41530d68baSNigel Croxon &LoadedImageProtocol,
42530d68baSNigel Croxon &LoadedImage,
43530d68baSNigel Croxon ImageHandle,
44530d68baSNigel Croxon NULL,
45530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL
46530d68baSNigel Croxon );
47530d68baSNigel Croxon if (EFI_ERROR(Status))
48530d68baSNigel Croxon return -1;
49530d68baSNigel Croxon
50087d22afSNigel Croxon BufLen = ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptionsSize;
51530d68baSNigel Croxon if (BufLen < 2) /* We are expecting at least a \0 */
52530d68baSNigel Croxon return -1;
53530d68baSNigel Croxon else if (BufLen > sizeof(ArgvContents))
54530d68baSNigel Croxon BufLen = sizeof(ArgvContents);
55530d68baSNigel Croxon
56087d22afSNigel Croxon CopyMem(ArgvContents, ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptions, BufLen);
57530d68baSNigel Croxon ArgvContents[MAX_CMDLINE_SIZE - 1] = L'\0';
58530d68baSNigel Croxon
59530d68baSNigel Croxon for (c = ArgStart = ArgvContents ; *c != L'\0' ; ++c) {
60530d68baSNigel Croxon if (*c == L' ') {
61530d68baSNigel Croxon *c = L'\0';
62530d68baSNigel Croxon if (Argc < MAX_CMDLINE_ARGC) Argv[Argc++] = ArgStart;
63530d68baSNigel Croxon ArgStart = c + 1;
64530d68baSNigel Croxon }
65530d68baSNigel Croxon }
66530d68baSNigel Croxon
67530d68baSNigel Croxon if ((*ArgStart != L'\0') && (Argc < MAX_CMDLINE_ARGC))
68530d68baSNigel Croxon Argv[Argc++] = ArgStart;
69530d68baSNigel Croxon
70530d68baSNigel Croxon // Print(L"Got argc/argv from loaded image proto\n");
71530d68baSNigel Croxon *ResultArgv = Argv;
72530d68baSNigel Croxon return Argc;
73530d68baSNigel Croxon }
74530d68baSNigel Croxon
GetShellArgcArgv(EFI_HANDLE ImageHandle,CHAR16 ** Argv[])75530d68baSNigel Croxon INTN GetShellArgcArgv(EFI_HANDLE ImageHandle, CHAR16 **Argv[])
76530d68baSNigel Croxon {
77530d68baSNigel Croxon // Code inspired from EDK2's
78530d68baSNigel Croxon // ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c (BSD)
79530d68baSNigel Croxon EFI_STATUS Status;
80530d68baSNigel Croxon static const EFI_GUID ShellInterfaceProtocolGuid
81530d68baSNigel Croxon = SHELL_INTERFACE_PROTOCOL_GUID;
82530d68baSNigel Croxon EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL;
83530d68baSNigel Croxon EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL;
84530d68baSNigel Croxon
85530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6,
86530d68baSNigel Croxon ImageHandle,
87*773f30afSJiaqing Zhao (EFI_GUID*)&ShellParametersProtocolGuid,
88530d68baSNigel Croxon (VOID **)&EfiShellParametersProtocol,
89530d68baSNigel Croxon ImageHandle,
90530d68baSNigel Croxon NULL,
91530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL
92530d68baSNigel Croxon );
93530d68baSNigel Croxon if (!EFI_ERROR(Status))
94530d68baSNigel Croxon {
95530d68baSNigel Croxon // use shell 2.0 interface
96530d68baSNigel Croxon // Print(L"Got argc/argv from shell intf proto\n");
97530d68baSNigel Croxon *Argv = EfiShellParametersProtocol->Argv;
98530d68baSNigel Croxon return EfiShellParametersProtocol->Argc;
99530d68baSNigel Croxon }
100530d68baSNigel Croxon
101530d68baSNigel Croxon // try to get shell 1.0 interface instead.
102530d68baSNigel Croxon Status = uefi_call_wrapper(BS->OpenProtocol, 6,
103530d68baSNigel Croxon ImageHandle,
10409027207SNigel Croxon (EFI_GUID*)&ShellInterfaceProtocolGuid,
105530d68baSNigel Croxon (VOID **)&EfiShellInterfaceProtocol,
106530d68baSNigel Croxon ImageHandle,
107530d68baSNigel Croxon NULL,
108530d68baSNigel Croxon EFI_OPEN_PROTOCOL_GET_PROTOCOL
109530d68baSNigel Croxon );
110530d68baSNigel Croxon if (!EFI_ERROR(Status))
111530d68baSNigel Croxon {
112530d68baSNigel Croxon // Print(L"Got argc/argv from shell params proto\n");
113530d68baSNigel Croxon *Argv = EfiShellInterfaceProtocol->Argv;
114530d68baSNigel Croxon return EfiShellInterfaceProtocol->Argc;
115530d68baSNigel Croxon }
116530d68baSNigel Croxon
117530d68baSNigel Croxon // shell 1.0 and 2.0 interfaces failed
118530d68baSNigel Croxon return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv);
119530d68baSNigel Croxon }
120