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