]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Application/LinuxLoader/LinuxLoaderEfiApp.c
57a9cd38cf68270a3f1dbc1974bcf47a5782d610
[mirror_edk2.git] / ArmPkg / Application / LinuxLoader / LinuxLoaderEfiApp.c
1 /** @file
2 *
3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include "LinuxLoader.h"
16
17 /**
18 Extract the next item from the command line.
19
20 The items are separated by spaces. Quotation marks (") are used for argument
21 grouping and the escaping character is "^" as for the EFI Shell command lines.
22
23 @param[in out] CommandLine Command line pointer.
24 @param[out] Item Pointer to the allocated buffer where the
25 item is stored.
26
27 @retval EFI_SUCCESS The token was found and extracted.
28 @retval EFI_NOT_FOUND No item found.
29 @retval EFI_OUT_OF_RESOURCES The memory allocation failed.
30
31 **/
32 STATIC
33 EFI_STATUS
34 ExtractNextItem (
35 IN OUT CONST CHAR16 **CommandLine,
36 OUT CHAR16 **Item
37 )
38 {
39 CONST CHAR16 *Walker;
40 VOID *Buffer;
41 CHAR16 *WritePtr;
42 BOOLEAN InQuotedString;
43 BOOLEAN Interpret;
44
45 for (Walker = *CommandLine; *Walker == L' '; Walker++) {
46 ;
47 }
48
49 Buffer = AllocatePool (StrSize (Walker));
50 if (Buffer == NULL) {
51 return EFI_OUT_OF_RESOURCES;
52 }
53
54 for (WritePtr = Buffer, Interpret = TRUE, InQuotedString = FALSE;
55 ((*Walker != L' ') || InQuotedString) && (*Walker != L'\0');
56 Walker++
57 ) {
58 if (Interpret) {
59 if (*Walker == L'^') {
60 Interpret = FALSE;
61 continue;
62 }
63 if (*Walker == L'"') {
64 InQuotedString = !InQuotedString;
65 continue;
66 }
67 } else {
68 Interpret = TRUE;
69 }
70 *(WritePtr++) = *Walker;
71 }
72
73 if (WritePtr == Buffer) {
74 FreePool (Buffer);
75 return EFI_NOT_FOUND;
76 }
77
78 *WritePtr = L'\0';
79 *CommandLine = Walker;
80 *Item = Buffer;
81
82 return EFI_SUCCESS;
83 }
84
85 /**
86 Check if an item of the command line is a flag or not.
87
88 @param[in] Item Command line item.
89
90 @retval TRUE The item is a flag.
91 @retval FALSE The item is not a flag.
92
93 **/
94 STATIC
95 BOOLEAN
96 IsFlag (
97 IN CONST CHAR16 *Item
98 )
99 {
100 return ((Item[0] == L'-') && (Item[2] == L'\0'));
101 }
102
103 /**
104 Process the application command line.
105
106 @param[out] KernelTextDevicePath A pointer to the buffer where the device
107 path to the Linux kernel is stored. The
108 address of the buffer is NULL in case of
109 an error. Otherwise, the returned address
110 is the address of a buffer allocated with
111 a call to AllocatePool() that has to be
112 freed by the caller.
113 @param[out] FdtTextDevicePath A pointer to the buffer where the device
114 path to the FDT is stored. The address of
115 the buffer is NULL in case of an error or
116 if the device path to the FDT is not
117 defined. Otherwise, the returned address
118 is the address of a buffer allocated with
119 a call to AllocatePool() that has to be
120 freed by the caller.
121 @param[out] InitrdTextDevicePath A pointer to the buffer where the device
122 path to the RAM root file system is stored.
123 The address of the buffer is NULL in case
124 of an error or if the device path to the
125 RAM root file system is not defined.
126 Otherwise, the returned address is the
127 address of a buffer allocated with a call
128 to AllocatePool() that has to be freed by
129 the caller.
130 @param[out] LinuxCommandLine A pointer to the buffer where the Linux
131 kernel command line is stored. The address
132 of the buffer is NULL in case of an error
133 or if the Linux command line is not
134 defined. Otherwise, the returned address
135 is the address of a buffer allocated with
136 a call to AllocatePool() that has to be
137 freed by the caller.
138
139 @param[out] AtagMachineType Value of the ARM Machine Type
140
141 @retval EFI_SUCCESS The processing was successfull.
142 @retval EFI_NOT_FOUND EFI_LOADED_IMAGE_PROTOCOL not found.
143 @retval EFI_NOT_FOUND Path to the Linux kernel not found.
144 @retval EFI_INVALID_PARAMETER At least one parameter is not valid or there is a
145 conflict between two parameters.
146 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
147
148 **/
149 EFI_STATUS
150 ProcessAppCommandLine (
151 OUT CHAR16 **KernelTextDevicePath,
152 OUT CHAR16 **FdtTextDevicePath,
153 OUT CHAR16 **InitrdTextDevicePath,
154 OUT CHAR16 **LinuxCommandLine,
155 OUT UINTN *AtagMachineType
156 )
157 {
158 EFI_STATUS Status;
159 EFI_STATUS Status2;
160 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
161 CONST CHAR16 *Walker;
162 CHAR16 *Item;
163 CHAR16 Flag;
164 BOOLEAN HasAtagSupport;
165 BOOLEAN HasFdtSupport;
166
167 *KernelTextDevicePath = NULL;
168 *FdtTextDevicePath = NULL;
169 *InitrdTextDevicePath = NULL;
170 *LinuxCommandLine = NULL;
171 *AtagMachineType = ARM_FDT_MACHINE_TYPE;
172
173 HasAtagSupport = FALSE;
174 HasFdtSupport = FALSE;
175
176 Status = gBS->HandleProtocol (
177 gImageHandle,
178 &gEfiLoadedImageProtocolGuid,
179 (VOID**)&LoadedImage
180 );
181 if (EFI_ERROR (Status)) {
182 ASSERT_EFI_ERROR (Status);
183 return Status;
184 }
185
186 Walker = (CHAR16*)LoadedImage->LoadOptions;
187 if (Walker == NULL) {
188 PrintHelp (NULL);
189 return EFI_INVALID_PARAMETER;
190 }
191
192 //
193 // Get the device path to the Linux kernel.
194 //
195
196 Status = ExtractNextItem (&Walker, &Item);
197 if (!EFI_ERROR (Status)) {
198 if (!IsFlag (Item)) {
199 *KernelTextDevicePath = Item;
200 } else {
201 PrintHii (NULL, STRING_TOKEN (STR_MISSING_KERNEL_PATH));
202 FreePool (Item);
203 return EFI_NOT_FOUND;
204 }
205 } else {
206 if (Status != EFI_NOT_FOUND) {
207 return Status;
208 }
209 PrintHelp (NULL);
210 return EFI_INVALID_PARAMETER;
211 }
212
213 Status = EFI_INVALID_PARAMETER;
214 while (*Walker != L'\0') {
215 Status2 = ExtractNextItem (&Walker, &Item);
216 if (Status2 == EFI_NOT_FOUND) {
217 break;
218 }
219 if (EFI_ERROR (Status2)) {
220 Status = Status2;
221 goto Error;
222 }
223
224 if (!IsFlag (Item)) {
225 PrintHii (NULL, STRING_TOKEN (STR_INVALID_FLAG), Item[0], Item[1]);
226 FreePool (Item);
227 goto Error;
228 }
229 Flag = Item[1];
230 FreePool (Item);
231
232 Status2 = ExtractNextItem (&Walker, &Item);
233 if (Status2 == EFI_NOT_FOUND) {
234 PrintHii (NULL, STRING_TOKEN (STR_MISSING_VALUE), Flag);
235 goto Error;
236 }
237 if (EFI_ERROR (Status2)) {
238 Status = Status2;
239 goto Error;
240 }
241 if (IsFlag (Item)) {
242 PrintHii (NULL, STRING_TOKEN (STR_MISSING_VALUE), Flag);
243 FreePool (Item);
244 goto Error;
245 }
246
247 switch (Flag) {
248 case L'a':
249 if (HasFdtSupport) {
250 PrintHii (NULL, STRING_TOKEN (STR_ATAG_FDT_CONFLICT));
251 goto Error;
252 }
253 *AtagMachineType = StrDecimalToUintn (Item);
254 HasAtagSupport = TRUE;
255 break;
256 case L'd':
257 *FdtTextDevicePath = Item;
258 if (HasAtagSupport) {
259 PrintHii (NULL, STRING_TOKEN (STR_ATAG_FDT_CONFLICT));
260 goto Error;
261 }
262 HasFdtSupport = TRUE;
263 break;
264
265 case L'c':
266 *LinuxCommandLine = Item;
267 break;
268
269 case L'f':
270 *InitrdTextDevicePath = Item;
271 break;
272
273 default:
274 PrintHii (NULL, STRING_TOKEN (STR_INVALID_FLAG), L'-', Flag);
275 FreePool (Item);
276 goto Error;
277 }
278 }
279
280 Status = EFI_SUCCESS;
281
282 Error:
283 if (EFI_ERROR (Status)) {
284 if (*KernelTextDevicePath != NULL) {
285 FreePool (*KernelTextDevicePath);
286 *KernelTextDevicePath = NULL;
287 }
288 if (*FdtTextDevicePath != NULL) {
289 FreePool (*FdtTextDevicePath);
290 *FdtTextDevicePath = NULL;
291 }
292 if (*InitrdTextDevicePath != NULL) {
293 FreePool (*InitrdTextDevicePath);
294 *InitrdTextDevicePath = NULL;
295 }
296 if (*LinuxCommandLine != NULL) {
297 FreePool (*LinuxCommandLine);
298 *LinuxCommandLine = NULL;
299 }
300 }
301
302 return Status;
303 }