]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c
EmbeddedPkg: import Lan91x Ethernet controller driver
[mirror_edk2.git] / EmbeddedPkg / Drivers / FdtPlatformDxe / ShellSetFdt.c
1 /** @file
2
3 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
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 "FdtPlatform.h"
16
17 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
18 {L"-i", TypeFlag },
19 {NULL , TypeMax }
20 };
21
22 /**
23 Display FDT device paths.
24
25 Display in text form the device paths used to install the FDT from the
26 highest to the lowest priority.
27
28 **/
29 STATIC
30 VOID
31 DisplayFdtDevicePaths (
32 VOID
33 )
34 {
35 EFI_STATUS Status;
36 UINTN DataSize;
37 CHAR16 *TextDevicePath;
38 CHAR16 *TextDevicePaths;
39 CHAR16 *TextDevicePathSeparator;
40
41 ShellPrintHiiEx (
42 -1, -1, NULL,
43 STRING_TOKEN (STR_SETFDT_DEVICE_PATH_LIST),
44 mFdtPlatformDxeHiiHandle
45 );
46
47 if (FeaturePcdGet (PcdOverridePlatformFdt)) {
48 DataSize = 0;
49 Status = gRT->GetVariable (
50 L"Fdt",
51 &gFdtVariableGuid,
52 NULL,
53 &DataSize,
54 NULL
55 );
56
57 //
58 // Keep going only if the "Fdt" variable is defined.
59 //
60
61 if (Status == EFI_BUFFER_TOO_SMALL) {
62 TextDevicePath = AllocatePool (DataSize);
63 if (TextDevicePath == NULL) {
64 return;
65 }
66
67 Status = gRT->GetVariable (
68 L"Fdt",
69 &gFdtVariableGuid,
70 NULL,
71 &DataSize,
72 TextDevicePath
73 );
74 if (!EFI_ERROR (Status)) {
75 ShellPrintHiiEx (
76 -1, -1, NULL,
77 STRING_TOKEN (STR_SETFDT_DEVICE_PATH),
78 mFdtPlatformDxeHiiHandle,
79 TextDevicePath
80 );
81 }
82
83 FreePool (TextDevicePath);
84 }
85 }
86
87 //
88 // Loop over the device path list provided by "PcdFdtDevicePaths". The device
89 // paths are in text form and separated by a semi-colon.
90 //
91
92 TextDevicePaths = AllocateCopyPool (
93 StrSize ((CHAR16*)PcdGetPtr (PcdFdtDevicePaths)),
94 (CHAR16*)PcdGetPtr (PcdFdtDevicePaths)
95 );
96 if (TextDevicePaths == NULL) {
97 return;
98 }
99
100 for (TextDevicePath = TextDevicePaths;
101 *TextDevicePath != L'\0' ; ) {
102 TextDevicePathSeparator = StrStr (TextDevicePath, L";");
103
104 if (TextDevicePathSeparator != NULL) {
105 *TextDevicePathSeparator = L'\0';
106 }
107
108 ShellPrintHiiEx (
109 -1, -1, NULL,
110 STRING_TOKEN (STR_SETFDT_DEVICE_PATH),
111 mFdtPlatformDxeHiiHandle,
112 TextDevicePath
113 );
114
115 if (TextDevicePathSeparator == NULL) {
116 break;
117 }
118 TextDevicePath = TextDevicePathSeparator + 1;
119 }
120
121 FreePool (TextDevicePaths);
122 }
123
124 /**
125 Update the text device path stored in the "Fdt" UEFI variable given
126 an EFI Shell file path or a text device path.
127
128 This function is a subroutine of the ShellDynCmdSetFdtHandler() function
129 to make its code easier to read.
130
131 @param[in] Shell The instance of the shell protocol used in the
132 context of processing the "setfdt" command.
133 @param[in] FilePath EFI Shell path or the device path to the FDT file.
134
135 @return SHELL_SUCCESS The text device path was succesfully updated.
136 @return SHELL_INVALID_PARAMETER The Shell file path is not valid.
137 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
138 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.
139 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.
140 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.
141 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.
142 @return SHELL_NOT_FOUND Device path to text protocol not found.
143 @return SHELL_ABORTED Operation aborted.
144
145 **/
146 STATIC
147 SHELL_STATUS
148 UpdateFdtTextDevicePath (
149 IN EFI_SHELL_PROTOCOL *Shell,
150 IN CONST CHAR16 *FilePath
151 )
152 {
153 EFI_STATUS Status;
154 EFI_DEVICE_PATH *DevicePath;
155 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *EfiDevicePathToTextProtocol;
156 CHAR16 *TextDevicePath;
157 CHAR16 *FdtVariableValue;
158 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
159 SHELL_STATUS ShellStatus;
160
161 ASSERT (FilePath != NULL);
162 DevicePath = NULL;
163 TextDevicePath = NULL;
164 FdtVariableValue = NULL;
165
166 if (*FilePath != L'\0') {
167 DevicePath = Shell->GetDevicePathFromFilePath (FilePath);
168 if (DevicePath != NULL) {
169 Status = gBS->LocateProtocol (
170 &gEfiDevicePathToTextProtocolGuid,
171 NULL,
172 (VOID **)&EfiDevicePathToTextProtocol
173 );
174 if (EFI_ERROR (Status)) {
175 goto Error;
176 }
177
178 TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText (
179 DevicePath,
180 FALSE,
181 FALSE
182 );
183 if (TextDevicePath == NULL) {
184 Status = EFI_OUT_OF_RESOURCES;
185 goto Error;
186 }
187 FdtVariableValue = TextDevicePath;
188 } else {
189 //
190 // Try to convert back the EFI Device Path String into a EFI device Path
191 // to ensure the format is valid
192 //
193 Status = gBS->LocateProtocol (
194 &gEfiDevicePathFromTextProtocolGuid,
195 NULL,
196 (VOID **)&EfiDevicePathFromTextProtocol
197 );
198 if (EFI_ERROR (Status)) {
199 goto Error;
200 }
201
202 DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (
203 FilePath
204 );
205 if (DevicePath == NULL) {
206 Status = EFI_INVALID_PARAMETER;
207 goto Error;
208 }
209 FdtVariableValue = (CHAR16*)FilePath;
210 }
211 }
212
213 Status = gRT->SetVariable (
214 (CHAR16*)L"Fdt",
215 &gFdtVariableGuid,
216 EFI_VARIABLE_RUNTIME_ACCESS |
217 EFI_VARIABLE_NON_VOLATILE |
218 EFI_VARIABLE_BOOTSERVICE_ACCESS ,
219 (FdtVariableValue != NULL) ?
220 StrSize (FdtVariableValue) : 0,
221 FdtVariableValue
222 );
223
224 Error:
225 ShellStatus = EfiCodeToShellCode (Status);
226 if (!EFI_ERROR (Status)) {
227 if (FdtVariableValue != NULL) {
228 ShellPrintHiiEx (
229 -1, -1, NULL,
230 STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED),
231 mFdtPlatformDxeHiiHandle,
232 FdtVariableValue
233 );
234 } else {
235 ShellPrintHiiEx (
236 -1, -1, NULL,
237 STRING_TOKEN (STR_SETFDT_UPDATE_DELETED),
238 mFdtPlatformDxeHiiHandle
239 );
240 }
241 } else {
242 if (Status == EFI_INVALID_PARAMETER) {
243 ShellPrintHiiEx (
244 -1, -1, NULL,
245 STRING_TOKEN (STR_SETFDT_INVALID_PATH),
246 mFdtPlatformDxeHiiHandle,
247 FilePath
248 );
249 } else {
250 ShellPrintHiiEx (
251 -1, -1, NULL,
252 STRING_TOKEN (STR_SETFDT_ERROR),
253 mFdtPlatformDxeHiiHandle,
254 Status
255 );
256 }
257 }
258
259 if (DevicePath != NULL) {
260 FreePool (DevicePath);
261 }
262 if (TextDevicePath != NULL) {
263 FreePool (TextDevicePath);
264 }
265
266 return ShellStatus;
267 }
268
269 /**
270 This is the shell command "setfdt" handler function. This function handles
271 the command when it is invoked in the shell.
272
273 @param[in] This The instance of the
274 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
275 @param[in] SystemTable The pointer to the UEFI system table.
276 @param[in] ShellParameters The parameters associated with the command.
277 @param[in] Shell The instance of the shell protocol used in the
278 context of processing this command.
279
280 @return SHELL_SUCCESS The operation was successful.
281 @return SHELL_ABORTED Operation aborted due to internal error.
282 @return SHELL_INVALID_PARAMETER The parameters of the command are not valid.
283 @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid.
284 @return SHELL_NOT_FOUND Failed to locate a protocol or a file.
285 @return SHELL_UNSUPPORTED Device path not supported.
286 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
287 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.
288 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.
289 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.
290 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.
291
292 **/
293 SHELL_STATUS
294 EFIAPI
295 ShellDynCmdSetFdtHandler (
296 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
297 IN EFI_SYSTEM_TABLE *SystemTable,
298 IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
299 IN EFI_SHELL_PROTOCOL *Shell
300 )
301 {
302 SHELL_STATUS ShellStatus;
303 EFI_STATUS Status;
304 LIST_ENTRY *ParamPackage;
305 BOOLEAN FilePath;
306 CONST CHAR16 *ValueStr;
307 CHAR16 *TextDevicePath;
308
309 ShellStatus = SHELL_SUCCESS;
310 ParamPackage = NULL;
311 FilePath = FALSE;
312
313 //
314 // Install the Shell and Shell Parameters Protocols on the driver
315 // image. This is necessary for the initialisation of the Shell
316 // Library to succeed in the next step.
317 //
318 Status = gBS->InstallMultipleProtocolInterfaces (
319 &gImageHandle,
320 &gEfiShellProtocolGuid, Shell,
321 &gEfiShellParametersProtocolGuid, ShellParameters,
322 NULL
323 );
324 if (EFI_ERROR (Status)) {
325 return SHELL_ABORTED;
326 }
327
328 //
329 // Initialise the Shell Library as we are going to use it.
330 // Assert that the return code is EFI_SUCCESS as it should.
331 // To anticipate any change is the codes returned by
332 // ShellInitialize(), leave in case of error.
333 //
334 Status = ShellInitialize ();
335 if (EFI_ERROR (Status)) {
336 ASSERT_EFI_ERROR (Status);
337 return SHELL_ABORTED;
338 }
339
340 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
341 if (!EFI_ERROR (Status)) {
342 switch (ShellCommandLineGetCount (ParamPackage)) {
343 case 1:
344 //
345 // Case "setfdt" or "setfdt -i"
346 //
347 if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) {
348 DisplayFdtDevicePaths ();
349 }
350 break;
351
352 case 2:
353 //
354 // Case "setfdt file_path" or
355 // "setfdt -i file_path" or
356 // "setfdt file_path -i"
357 //
358 FilePath = TRUE;
359 break;
360
361 default:
362 Status = EFI_INVALID_PARAMETER;
363 }
364 }
365 if (EFI_ERROR (Status)) {
366 ShellStatus = EfiCodeToShellCode (Status);
367 ShellPrintHiiEx (
368 -1, -1, NULL,
369 STRING_TOKEN (STR_SETFDT_ERROR),
370 mFdtPlatformDxeHiiHandle,
371 Status
372 );
373 goto Error;
374 }
375
376 //
377 // Update the preferred device path for the FDT if asked for.
378 //
379 if (FilePath) {
380 ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);
381 ShellPrintHiiEx (
382 -1, -1, NULL,
383 STRING_TOKEN (STR_SETFDT_UPDATING),
384 mFdtPlatformDxeHiiHandle
385 );
386 ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr);
387 if (ShellStatus != SHELL_SUCCESS) {
388 goto Error;
389 }
390 }
391
392 //
393 // Run the FDT installation process if asked for.
394 //
395 if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
396 ShellPrintHiiEx (
397 -1, -1, NULL,
398 STRING_TOKEN (STR_SETFDT_INSTALLING),
399 mFdtPlatformDxeHiiHandle
400 );
401 Status = RunFdtInstallation (&TextDevicePath);
402 ShellStatus = EfiCodeToShellCode (Status);
403 if (!EFI_ERROR (Status)) {
404 ShellPrintHiiEx (
405 -1, -1, NULL,
406 STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED),
407 mFdtPlatformDxeHiiHandle,
408 TextDevicePath
409 );
410 FreePool (TextDevicePath);
411 } else {
412 if (Status == EFI_INVALID_PARAMETER) {
413 ShellPrintHiiEx (
414 -1, -1, NULL,
415 STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH),
416 mFdtPlatformDxeHiiHandle
417 );
418 } else {
419 ShellPrintHiiEx (
420 -1, -1, NULL,
421 STRING_TOKEN (STR_SETFDT_ERROR),
422 mFdtPlatformDxeHiiHandle,
423 Status
424 );
425 }
426 DisplayFdtDevicePaths ();
427 }
428 }
429
430 Error:
431 gBS->UninstallMultipleProtocolInterfaces (
432 gImageHandle,
433 &gEfiShellProtocolGuid, Shell,
434 &gEfiShellParametersProtocolGuid, ShellParameters,
435 NULL
436 );
437 ShellCommandLineFreeVarList (ParamPackage);
438
439 return ShellStatus;
440 }
441
442 /**
443 This is the shell command "setfdt" help handler function. This
444 function returns the formatted help for the "setfdt" command.
445 The format matchs that in Appendix B of the revision 2.1 of the
446 UEFI Shell Specification.
447
448 @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
449 @param[in] Language The pointer to the language string to use.
450
451 @return CHAR16* Pool allocated help string, must be freed by caller.
452 **/
453 CHAR16*
454 EFIAPI
455 ShellDynCmdSetFdtGetHelp (
456 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
457 IN CONST CHAR8 *Language
458 )
459 {
460 //
461 // This allocates memory. The caller has to free the allocated memory.
462 //
463 return HiiGetString (
464 mFdtPlatformDxeHiiHandle,
465 STRING_TOKEN (STR_GET_HELP_SETFDT),
466 Language
467 );
468 }