cmdline.c revision 1.1.1.2 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