]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
ArmPlatformPkg/FdtPlatformDxe: 'setfdt' command, add display of FDT device paths.
[mirror_edk2.git] / EmbeddedPkg / Drivers / FdtPlatformDxe / FdtPlatform.c
CommitLineData
158497a0
RC
1/** @file\r
2\r
3 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\r
4\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14#include <Uefi.h>\r
15\r
16#include <Library/UefiLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiBootServicesTableLib.h>\r
19#include <Library/UefiRuntimeServicesTableLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/DevicePathLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
3c1e53ce 23#include <Library/HiiLib.h>\r
158497a0 24#include <Library/BdsLib.h>\r
3c1e53ce 25#include <Library/ShellLib.h>\r
158497a0 26\r
3c1e53ce 27#include <Protocol/DevicePathToText.h>\r
158497a0
RC
28#include <Protocol/DevicePathFromText.h>\r
29#include <Protocol/DevicePath.h>\r
3c1e53ce
RC
30#include <Protocol/EfiShell.h>\r
31#include <Protocol/EfiShellDynamicCommand.h>\r
158497a0 32\r
158497a0
RC
33#include <Guid/Fdt.h>\r
34\r
35#include <libfdt.h>\r
36\r
37//\r
38// Internal types\r
39//\r
3c1e53ce 40\r
3c1e53ce
RC
41STATIC SHELL_STATUS EFIAPI ShellDynCmdSetFdtHandler (\r
42 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
43 IN EFI_SYSTEM_TABLE *SystemTable,\r
44 IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
45 IN EFI_SHELL_PROTOCOL *Shell\r
46 );\r
47\r
48STATIC CHAR16* EFIAPI ShellDynCmdSetFdtGetHelp (\r
49 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
50 IN CONST CHAR8 *Language\r
51 );\r
52\r
4589ffaa
RC
53STATIC VOID DisplayFdtDevicePaths (\r
54 VOID\r
55 );\r
56\r
3c1e53ce
RC
57STATIC SHELL_STATUS UpdateFdtTextDevicePath (\r
58 IN EFI_SHELL_PROTOCOL *Shell,\r
59 IN CONST CHAR16 *FilePath\r
60 );\r
61\r
62STATIC SHELL_STATUS EfiCodeToShellCode (\r
63 IN EFI_STATUS Status\r
64 );\r
65\r
66//\r
67// Internal variables\r
68//\r
69\r
70STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolSetFdt = {\r
71 L"setfdt", // Name of the command\r
72 ShellDynCmdSetFdtHandler, // Handler\r
73 ShellDynCmdSetFdtGetHelp // GetHelp\r
74};\r
75\r
76STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid = {\r
77 0x8afa7610, 0x62b1, 0x46aa,\r
78 {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}\r
79 };\r
80STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
81 {L"-i", TypeFlag },\r
82 {NULL , TypeMax }\r
83};\r
84\r
85STATIC EFI_HANDLE mFdtPlatformDxeHiiHandle;\r
86\r
cd66c5a2
OM
87/**\r
88 Install the FDT specified by its device path in text form.\r
89\r
90 @param[in] TextDevicePath Device path of the FDT to install in text form\r
91\r
92 @retval EFI_SUCCESS The FDT was installed.\r
93 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.\r
94 @retval EFI_INVALID_PARAMETER Invalid device path.\r
95 @retval EFI_UNSUPPORTED Device path not supported.\r
96 @retval EFI_OUT_OF_RESOURCES An allocation failed.\r
97**/\r
98STATIC\r
99EFI_STATUS\r
100InstallFdt (\r
101 IN CONST CHAR16* TextDevicePath\r
102 )\r
103{\r
104 EFI_STATUS Status;\r
105 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
106 EFI_DEVICE_PATH *DevicePath;\r
107 EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
108 UINTN FdtBlobSize;\r
109 UINTN NumPages;\r
110 EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase;\r
111\r
112 Status = gBS->LocateProtocol (\r
113 &gEfiDevicePathFromTextProtocolGuid,\r
114 NULL,\r
115 (VOID **)&EfiDevicePathFromTextProtocol\r
116 );\r
117 if (EFI_ERROR (Status)) {\r
118 DEBUG ((EFI_D_ERROR, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));\r
119 return Status;\r
120 }\r
121\r
122 DevicePath = (EFI_DEVICE_PATH*)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (TextDevicePath);\r
123 if (DevicePath == NULL) {\r
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126\r
127 //\r
128 // Load the FDT given its device path.\r
129 // This operation may fail if the device path is not supported.\r
130 //\r
131 FdtBlobBase = 0;\r
132 NumPages = 0;\r
133 Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
134 if (EFI_ERROR (Status)) {\r
135 goto Error;\r
136 }\r
137\r
138 // Check the FDT header is valid. We only make this check in DEBUG mode in\r
139 // case the FDT header change on production device and this ASSERT() becomes\r
140 // not valid.\r
141 ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);\r
142\r
143 //\r
144 // Ensure the Size of the Device Tree is smaller than the size of the read file\r
145 //\r
146 ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);\r
147\r
148 //\r
149 // Store the FDT as Runtime Service Data to prevent the Kernel from\r
150 // overwritting its data.\r
151 //\r
152 NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
153 Status = gBS->AllocatePages (\r
154 AllocateAnyPages, EfiRuntimeServicesData,\r
155 NumPages, &FdtConfigurationTableBase\r
156 );\r
157 if (EFI_ERROR (Status)) {\r
158 goto Error;\r
159 }\r
160 CopyMem (\r
161 (VOID*)(UINTN)FdtConfigurationTableBase,\r
162 (VOID*)(UINTN)FdtBlobBase,\r
163 FdtBlobSize\r
164 );\r
165\r
166 //\r
167 // Install the FDT into the Configuration Table\r
168 //\r
169 Status = gBS->InstallConfigurationTable (\r
170 &gFdtTableGuid,\r
171 (VOID*)(UINTN)FdtConfigurationTableBase\r
172 );\r
173 if (EFI_ERROR (Status)) {\r
174 gBS->FreePages (FdtConfigurationTableBase, NumPages);\r
175 }\r
176\r
177Error:\r
178 if (FdtBlobBase != 0) {\r
179 gBS->FreePages (FdtBlobBase, NumPages);\r
180 }\r
181 FreePool (DevicePath);\r
182\r
183 return Status;\r
184}\r
185\r
158497a0
RC
186/**\r
187 Main entry point of the FDT platform driver.\r
188\r
189 @param[in] ImageHandle The firmware allocated handle for the present driver\r
190 UEFI image.\r
191 @param[in] *SystemTable A pointer to the EFI System table.\r
192\r
193 @retval EFI_SUCCESS The driver was initialized.\r
3c1e53ce
RC
194 @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or\r
195 there was not enough memory in pool to install\r
196 the Shell Dynamic Command protocol.\r
197 @retval EFI_LOAD_ERROR Unable to add the HII package.\r
158497a0
RC
198\r
199**/\r
200EFI_STATUS\r
201FdtPlatformEntryPoint (\r
202 IN EFI_HANDLE ImageHandle,\r
203 IN EFI_SYSTEM_TABLE *SystemTable\r
204 )\r
205{\r
206 EFI_STATUS Status;\r
158497a0
RC
207\r
208 //\r
cd66c5a2 209 // Install the Device Tree from its expected location\r
158497a0 210 //\r
cd66c5a2 211 Status = RunFdtInstallation (NULL);\r
3c1e53ce
RC
212 if (EFI_ERROR (Status)) {\r
213 return Status;\r
214 }\r
215\r
216 //\r
217 // If the development features are enabled, install the dynamic shell\r
218 // command "setfdt" to be able to define a device path for the FDT\r
219 // that has precedence over the device paths defined by\r
220 // "PcdFdtDevicePaths".\r
221 //\r
222\r
223 if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
224 //\r
225 // Register the strings for the user interface in the HII Database.\r
226 // This shows the way to the multi-language support, even if\r
227 // only the English language is actually supported. The strings to register\r
228 // are stored in the "FdtPlatformDxeStrings[]" array. This array is\r
229 // built by the building process from the "*.uni" file associated to\r
230 // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build\r
231 // folder under your package's DEBUG folder and you will find the array\r
232 // defined in a xxxStrDefs.h file.\r
233 //\r
234 mFdtPlatformDxeHiiHandle = HiiAddPackages (\r
235 &mFdtPlatformDxeHiiGuid,\r
236 ImageHandle,\r
237 FdtPlatformDxeStrings,\r
238 NULL\r
239 );\r
240\r
241 if (mFdtPlatformDxeHiiHandle != NULL) {\r
242 Status = gBS->InstallMultipleProtocolInterfaces (\r
243 &ImageHandle,\r
244 &gEfiShellDynamicCommandProtocolGuid,\r
245 &mShellDynCmdProtocolSetFdt,\r
246 NULL\r
247 );\r
248 if (EFI_ERROR (Status)) {\r
249 HiiRemovePackages (mFdtPlatformDxeHiiHandle);\r
250 }\r
251 } else {\r
252 Status = EFI_LOAD_ERROR;\r
253 }\r
254 if (EFI_ERROR (Status)) {\r
255 DEBUG ((\r
256 EFI_D_WARN,\r
257 "Unable to install \"setfdt\" EFI Shell command - %r \n",\r
258 Status\r
259 ));\r
260 }\r
261 }\r
262\r
158497a0
RC
263 return Status;\r
264}\r
265\r
158497a0
RC
266/**\r
267 Run the FDT installation process.\r
268\r
269 Loop in priority order over the device paths from which the FDT has\r
270 been asked to be retrieved for. For each device path, try to install\r
271 the FDT. Stop as soon as an installation succeeds.\r
272\r
273 @retval EFI_SUCCESS The FDT was installed.\r
274 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.\r
275 @retval EFI_INVALID_PARAMETER Invalid device path.\r
276 @retval EFI_UNSUPPORTED Device path not supported.\r
277 @retval EFI_OUT_OF_RESOURCES An allocation failed.\r
278\r
279**/\r
280STATIC\r
281EFI_STATUS\r
282RunFdtInstallation (\r
283 VOID\r
284 )\r
285{\r
286 EFI_STATUS Status;\r
287 UINTN DataSize;\r
288 VOID *Data;\r
289 CHAR16 *TextDevicePathStart;\r
290 CHAR16 *TextDevicePathSeparator;\r
291 UINTN TextDevicePathLen;\r
292 CHAR16 *TextDevicePath;\r
293\r
294 //\r
295 // For development purpose, if enabled through the "PcdOverridePlatformFdt"\r
296 // feature PCD, try first to install the FDT specified by the device path in\r
297 // text form stored in the "Fdt" UEFI variable.\r
298 //\r
299 if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
300 Data = NULL;\r
301 DataSize = 0;\r
302 Status = gRT->GetVariable (\r
303 L"Fdt",\r
304 &gFdtVariableGuid,\r
305 NULL,\r
306 &DataSize,\r
307 Data\r
308 );\r
309\r
310 //\r
311 // Keep going only if the "Fdt" variable is defined.\r
312 //\r
313\r
314 if (Status == EFI_BUFFER_TOO_SMALL) {\r
315 Data = AllocatePool (DataSize);\r
316 if (Data == NULL) {\r
317 Status = EFI_OUT_OF_RESOURCES;\r
318 } else {\r
319 Status = gRT->GetVariable (\r
320 L"Fdt",\r
321 &gFdtVariableGuid,\r
322 NULL,\r
323 &DataSize,\r
324 Data\r
325 );\r
326 if (!EFI_ERROR (Status)) {\r
327 Status = InstallFdt ((CHAR16*)Data);\r
328 if (!EFI_ERROR (Status)) {\r
329 DEBUG ((\r
330 EFI_D_WARN,\r
331 "Installation of the FDT using the device path <%s> completed.\n",\r
332 (CHAR16*)Data\r
333 ));\r
334 }\r
335 }\r
336 FreePool (Data);\r
337 }\r
338\r
339 if (EFI_ERROR (Status)) {\r
340 DEBUG ((\r
341 EFI_D_ERROR,\r
342 "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",\r
343 Status\r
344 ));\r
345 } else {\r
346 return Status;\r
347 }\r
348 }\r
349 }\r
350\r
351 //\r
352 // Loop over the device path list provided by "PcdFdtDevicePaths". The device\r
353 // paths are in text form and separated by a semi-colon.\r
354 //\r
355\r
356 Status = EFI_SUCCESS;\r
357 for (TextDevicePathStart = (CHAR16*)PcdGetPtr (PcdFdtDevicePaths);\r
358 *TextDevicePathStart != L'\0' ; ) {\r
359 TextDevicePathSeparator = StrStr (TextDevicePathStart, L";");\r
360\r
361 //\r
362 // Last device path of the list\r
363 //\r
364 if (TextDevicePathSeparator == NULL) {\r
365 TextDevicePath = TextDevicePathStart;\r
366 } else {\r
367 TextDevicePathLen = (UINTN)(TextDevicePathSeparator - TextDevicePathStart);\r
368 TextDevicePath = AllocateCopyPool (\r
369 (TextDevicePathLen + 1) * sizeof (CHAR16),\r
370 TextDevicePathStart\r
371 );\r
372 if (TextDevicePath == NULL) {\r
373 Status = EFI_OUT_OF_RESOURCES;\r
374 DEBUG ((EFI_D_ERROR, "Memory allocation error during FDT installation process.\n"));\r
375 break;\r
376 }\r
377 TextDevicePath[TextDevicePathLen] = L'\0';\r
378 }\r
379\r
380 Status = InstallFdt (TextDevicePath);\r
381 if (EFI_ERROR (Status)) {\r
382 DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> failed - %r.\n",\r
383 TextDevicePath, Status\r
384 ));\r
385 } else {\r
386 DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> completed.\n",\r
387 TextDevicePath\r
388 ));\r
389 }\r
390\r
391 if (TextDevicePathSeparator == NULL) {\r
392 break;\r
393 } else {\r
394 FreePool (TextDevicePath);\r
395 if (!EFI_ERROR (Status)) {\r
396 break;\r
397 }\r
398 TextDevicePathStart = TextDevicePathSeparator + 1;\r
399 }\r
400 }\r
401\r
402 if (EFI_ERROR (Status)) {\r
403 DEBUG ((EFI_D_ERROR, "Failed to install the FDT - %r.\n", Status));\r
404 }\r
405\r
406 return Status;\r
407}\r
408\r
158497a0
RC
409/**\r
410 This is the shell command "setfdt" handler function. This function handles\r
411 the command when it is invoked in the shell.\r
412\r
413 @param[in] This The instance of the\r
414 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
415 @param[in] SystemTable The pointer to the UEFI system table.\r
416 @param[in] ShellParameters The parameters associated with the command.\r
417 @param[in] Shell The instance of the shell protocol used in the\r
418 context of processing this command.\r
419\r
420 @return SHELL_SUCCESS The operation was successful.\r
421 @return SHELL_ABORTED Operation aborted due to internal error.\r
422 @return SHELL_INVALID_PARAMETER The parameters of the command are not valid.\r
423 @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid.\r
424 @return SHELL_NOT_FOUND Failed to locate a protocol or a file.\r
425 @return SHELL_UNSUPPORTED Device path not supported.\r
426 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
427 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.\r
428 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.\r
429 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.\r
430 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.\r
431\r
432**/\r
433STATIC\r
434SHELL_STATUS\r
435EFIAPI\r
436ShellDynCmdSetFdtHandler (\r
437 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
438 IN EFI_SYSTEM_TABLE *SystemTable,\r
439 IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
440 IN EFI_SHELL_PROTOCOL *Shell\r
441 )\r
442{\r
443 SHELL_STATUS ShellStatus;\r
444 EFI_STATUS Status;\r
445 LIST_ENTRY *ParamPackage;\r
446 BOOLEAN FilePath;\r
447 CONST CHAR16 *ValueStr;\r
448\r
449 ShellStatus = SHELL_SUCCESS;\r
450 ParamPackage = NULL;\r
451 FilePath = FALSE;\r
452\r
453 //\r
454 // Install the Shell and Shell Parameters Protocols on the driver\r
455 // image. This is necessary for the initialisation of the Shell\r
456 // Library to succeed in the next step.\r
457 //\r
458 Status = gBS->InstallMultipleProtocolInterfaces (\r
459 &gImageHandle,\r
460 &gEfiShellProtocolGuid, Shell,\r
461 &gEfiShellParametersProtocolGuid, ShellParameters,\r
462 NULL\r
463 );\r
464 if (EFI_ERROR (Status)) {\r
465 return SHELL_ABORTED;\r
466 }\r
467\r
468 //\r
469 // Initialise the Shell Library as we are going to use it.\r
470 // Assert that the return code is EFI_SUCCESS as it should.\r
471 // To anticipate any change is the codes returned by\r
472 // ShellInitialize(), leave in case of error.\r
473 //\r
474 Status = ShellInitialize ();\r
475 if (EFI_ERROR (Status)) {\r
476 ASSERT_EFI_ERROR (Status);\r
477 return SHELL_ABORTED;\r
478 }\r
479\r
480 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);\r
481 if (!EFI_ERROR (Status)) {\r
482 switch (ShellCommandLineGetCount (ParamPackage)) {\r
483 case 1:\r
484 //\r
4589ffaa 485 // Case "setfdt" or "setfdt -i"\r
158497a0
RC
486 //\r
487 if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) {\r
4589ffaa 488 DisplayFdtDevicePaths ();\r
158497a0
RC
489 }\r
490 break;\r
491\r
492 case 2:\r
493 //\r
494 // Case "setfdt file_path" or\r
495 // "setfdt -i file_path" or\r
496 // "setfdt file_path -i"\r
497 //\r
498 FilePath = TRUE;\r
499 break;\r
500\r
501 default:\r
502 Status = EFI_INVALID_PARAMETER;\r
503 }\r
504 }\r
505 if (EFI_ERROR (Status)) {\r
506 ShellStatus = EfiCodeToShellCode (Status);\r
507 ShellPrintHiiEx (\r
508 -1, -1, NULL,\r
509 STRING_TOKEN (STR_SETFDT_ERROR),\r
510 mFdtPlatformDxeHiiHandle,\r
511 Status\r
512 );\r
513 goto Error;\r
514 }\r
515\r
516 //\r
517 // Update the preferred device path for the FDT if asked for.\r
518 //\r
519 if (FilePath) {\r
520 ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);\r
521 ShellPrintHiiEx (\r
522 -1, -1, NULL,\r
523 STRING_TOKEN (STR_SETFDT_UPDATING),\r
524 mFdtPlatformDxeHiiHandle\r
525 );\r
526 ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr);\r
527 if (ShellStatus != SHELL_SUCCESS) {\r
528 goto Error;\r
529 }\r
530 }\r
531\r
532 //\r
533 // Run the FDT installation process if asked for.\r
534 //\r
535 if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {\r
536 ShellPrintHiiEx (\r
537 -1, -1, NULL,\r
538 STRING_TOKEN (STR_SETFDT_INSTALLING),\r
539 mFdtPlatformDxeHiiHandle\r
540 );\r
541 Status = RunFdtInstallation ();\r
542 ShellStatus = EfiCodeToShellCode (Status);\r
543 if (!EFI_ERROR (Status)) {\r
544 ShellPrintHiiEx (\r
545 -1, -1, NULL,\r
546 STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED),\r
547 mFdtPlatformDxeHiiHandle\r
548 );\r
549 } else {\r
550 if (Status == EFI_INVALID_PARAMETER) {\r
551 ShellPrintHiiEx (\r
552 -1, -1, NULL,\r
553 STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH),\r
554 mFdtPlatformDxeHiiHandle\r
555 );\r
556 } else {\r
557 ShellPrintHiiEx (\r
558 -1, -1, NULL,\r
559 STRING_TOKEN (STR_SETFDT_ERROR),\r
560 mFdtPlatformDxeHiiHandle,\r
561 Status\r
562 );\r
563 }\r
4589ffaa 564 DisplayFdtDevicePaths ();\r
158497a0
RC
565 }\r
566 }\r
567\r
568Error:\r
158497a0
RC
569 gBS->UninstallMultipleProtocolInterfaces (\r
570 gImageHandle,\r
571 &gEfiShellProtocolGuid, Shell,\r
572 &gEfiShellParametersProtocolGuid, ShellParameters,\r
573 NULL\r
574 );\r
575 ShellCommandLineFreeVarList (ParamPackage);\r
576\r
577 return ShellStatus;\r
578}\r
579\r
580/**\r
581 This is the shell command "setfdt" help handler function. This\r
582 function returns the formatted help for the "setfdt" command.\r
583 The format matchs that in Appendix B of the revision 2.1 of the\r
584 UEFI Shell Specification.\r
585\r
586 @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
587 @param[in] Language The pointer to the language string to use.\r
588\r
589 @return CHAR16* Pool allocated help string, must be freed by caller.\r
590**/\r
591STATIC\r
592CHAR16*\r
593EFIAPI\r
594ShellDynCmdSetFdtGetHelp (\r
595 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
596 IN CONST CHAR8 *Language\r
597 )\r
598{\r
599 //\r
600 // This allocates memory. The caller has to free the allocated memory.\r
601 //\r
602 return HiiGetString (\r
603 mFdtPlatformDxeHiiHandle,\r
604 STRING_TOKEN (STR_GET_HELP_SETFDT),\r
605 Language\r
606 );\r
607}\r
608\r
4589ffaa
RC
609/**\r
610 Display FDT device paths.\r
611\r
612 Display in text form the device paths used to install the FDT from the\r
613 highest to the lowest priority.\r
614\r
615**/\r
616STATIC\r
617VOID\r
618DisplayFdtDevicePaths (\r
619 VOID\r
620 )\r
621{\r
622 EFI_STATUS Status;\r
623 UINTN DataSize;\r
624 CHAR16 *TextDevicePath;\r
625 CHAR16 *TextDevicePaths;\r
626 CHAR16 *TextDevicePathSeparator;\r
627\r
628 ShellPrintHiiEx (\r
629 -1, -1, NULL,\r
630 STRING_TOKEN (STR_SETFDT_DEVICE_PATH_LIST),\r
631 mFdtPlatformDxeHiiHandle\r
632 );\r
633\r
634 if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
635 DataSize = 0;\r
636 Status = gRT->GetVariable (\r
637 L"Fdt",\r
638 &gFdtVariableGuid,\r
639 NULL,\r
640 &DataSize,\r
641 NULL\r
642 );\r
643\r
644 //\r
645 // Keep going only if the "Fdt" variable is defined.\r
646 //\r
647\r
648 if (Status == EFI_BUFFER_TOO_SMALL) {\r
649 TextDevicePath = AllocatePool (DataSize);\r
650 if (TextDevicePath == NULL) {\r
651 return;\r
652 }\r
653\r
654 Status = gRT->GetVariable (\r
655 L"Fdt",\r
656 &gFdtVariableGuid,\r
657 NULL,\r
658 &DataSize,\r
659 TextDevicePath\r
660 );\r
661 if (!EFI_ERROR (Status)) {\r
662 ShellPrintHiiEx (\r
663 -1, -1, NULL,\r
664 STRING_TOKEN (STR_SETFDT_DEVICE_PATH),\r
665 mFdtPlatformDxeHiiHandle,\r
666 TextDevicePath\r
667 );\r
668 }\r
669\r
670 FreePool (TextDevicePath);\r
671 }\r
672 }\r
673\r
674 //\r
675 // Loop over the device path list provided by "PcdFdtDevicePaths". The device\r
676 // paths are in text form and separated by a semi-colon.\r
677 //\r
678\r
679 TextDevicePaths = AllocateCopyPool (\r
680 StrSize ((CHAR16*)PcdGetPtr (PcdFdtDevicePaths)),\r
681 (CHAR16*)PcdGetPtr (PcdFdtDevicePaths)\r
682 );\r
683 if (TextDevicePaths == NULL) {\r
684 return;\r
685 }\r
686\r
687 for (TextDevicePath = TextDevicePaths;\r
688 *TextDevicePath != L'\0' ; ) {\r
689 TextDevicePathSeparator = StrStr (TextDevicePath, L";");\r
690\r
691 if (TextDevicePathSeparator != NULL) {\r
692 *TextDevicePathSeparator = L'\0';\r
693 }\r
694\r
695 ShellPrintHiiEx (\r
696 -1, -1, NULL,\r
697 STRING_TOKEN (STR_SETFDT_DEVICE_PATH),\r
698 mFdtPlatformDxeHiiHandle,\r
699 TextDevicePath\r
700 );\r
701\r
702 if (TextDevicePathSeparator == NULL) {\r
703 break;\r
704 }\r
705 TextDevicePath = TextDevicePathSeparator + 1;\r
706 }\r
707\r
708 FreePool (TextDevicePaths);\r
709\r
710}\r
711\r
158497a0
RC
712/**\r
713 Update the text device path stored in the "Fdt" UEFI variable given\r
714 an EFI Shell file path or a text device path.\r
715\r
716 This function is a subroutine of the ShellDynCmdSetFdtHandler() function\r
717 to make its code easier to read.\r
718\r
719 @param[in] Shell The instance of the shell protocol used in the\r
720 context of processing the "setfdt" command.\r
721 @param[in] FilePath EFI Shell path or the device path to the FDT file.\r
722\r
723 @return SHELL_SUCCESS The text device path was succesfully updated.\r
724 @return SHELL_INVALID_PARAMETER The Shell file path is not valid.\r
725 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
726 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.\r
727 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.\r
728 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.\r
729 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.\r
730 @return SHELL_NOT_FOUND Device path to text protocol not found.\r
731 @return SHELL_ABORTED Operation aborted.\r
732\r
733**/\r
734STATIC\r
735SHELL_STATUS\r
736UpdateFdtTextDevicePath (\r
737 IN EFI_SHELL_PROTOCOL *Shell,\r
738 IN CONST CHAR16 *FilePath\r
739 )\r
740{\r
741 EFI_STATUS Status;\r
742 EFI_DEVICE_PATH *DevicePath;\r
743 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *EfiDevicePathToTextProtocol;\r
744 CHAR16 *TextDevicePath;\r
745 CHAR16 *FdtVariableValue;\r
746 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
747 SHELL_STATUS ShellStatus;\r
748\r
749 ASSERT (FilePath != NULL);\r
750 TextDevicePath = NULL;\r
751 FdtVariableValue = NULL;\r
752\r
753 DevicePath = Shell->GetDevicePathFromFilePath (FilePath);\r
754 if (DevicePath != NULL) {\r
755 Status = gBS->LocateProtocol (\r
756 &gEfiDevicePathToTextProtocolGuid,\r
757 NULL,\r
758 (VOID **)&EfiDevicePathToTextProtocol\r
759 );\r
760 if (EFI_ERROR (Status)) {\r
761 goto Error;\r
762 }\r
763\r
764 TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText (\r
765 DevicePath,\r
766 FALSE,\r
767 FALSE\r
768 );\r
769 if (TextDevicePath == NULL) {\r
770 Status = EFI_OUT_OF_RESOURCES;\r
771 goto Error;\r
772 }\r
773 FdtVariableValue = TextDevicePath;\r
774 } else {\r
775 //\r
776 // Try to convert back the EFI Device Path String into a EFI device Path\r
777 // to ensure the format is valid\r
778 //\r
779 Status = gBS->LocateProtocol (\r
780 &gEfiDevicePathFromTextProtocolGuid,\r
781 NULL,\r
782 (VOID **)&EfiDevicePathFromTextProtocol\r
783 );\r
784 if (EFI_ERROR (Status)) {\r
785 goto Error;\r
786 }\r
787\r
788 DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
789 FilePath\r
790 );\r
791 if (DevicePath == NULL) {\r
792 Status = EFI_INVALID_PARAMETER;\r
793 goto Error;\r
794 }\r
795 FdtVariableValue = (CHAR16*)FilePath;\r
796 }\r
797\r
798 Status = gRT->SetVariable (\r
799 (CHAR16*)L"Fdt",\r
800 &gFdtVariableGuid,\r
801 EFI_VARIABLE_RUNTIME_ACCESS |\r
802 EFI_VARIABLE_NON_VOLATILE |\r
803 EFI_VARIABLE_BOOTSERVICE_ACCESS ,\r
804 StrSize (FdtVariableValue),\r
805 FdtVariableValue\r
806 );\r
807\r
808Error:\r
809 ShellStatus = EfiCodeToShellCode (Status);\r
810 if (!EFI_ERROR (Status)) {\r
811 ShellPrintHiiEx (\r
812 -1, -1, NULL,\r
813 STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED),\r
814 mFdtPlatformDxeHiiHandle,\r
815 FdtVariableValue\r
816 );\r
817 } else {\r
818 if (Status == EFI_INVALID_PARAMETER) {\r
819 ShellPrintHiiEx (\r
820 -1, -1, NULL,\r
821 STRING_TOKEN (STR_SETFDT_INVALID_PATH),\r
822 mFdtPlatformDxeHiiHandle,\r
823 FilePath\r
824 );\r
825 } else {\r
826 ShellPrintHiiEx (\r
827 -1, -1, NULL,\r
828 STRING_TOKEN (STR_SETFDT_ERROR),\r
829 mFdtPlatformDxeHiiHandle,\r
830 Status\r
831 );\r
832 }\r
833 }\r
834\r
835 if (DevicePath != NULL) {\r
836 FreePool (DevicePath);\r
837 }\r
838 if (TextDevicePath != NULL) {\r
839 FreePool (TextDevicePath);\r
840 }\r
841\r
842 return ShellStatus;\r
843}\r
844\r
845/**\r
846 Transcode one of the EFI return code used by the model into an EFI Shell return code.\r
847\r
848 @param[in] Status EFI return code.\r
849\r
850 @return Transcoded EFI Shell return code.\r
851\r
852**/\r
853STATIC\r
854SHELL_STATUS\r
855EfiCodeToShellCode (\r
856 IN EFI_STATUS Status\r
857 )\r
858{\r
859 SHELL_STATUS ShellStatus;\r
860\r
861 switch (Status) {\r
862 case EFI_SUCCESS :\r
863 ShellStatus = SHELL_SUCCESS;\r
864 break;\r
865\r
866 case EFI_INVALID_PARAMETER :\r
867 ShellStatus = SHELL_INVALID_PARAMETER;\r
868 break;\r
869\r
870 case EFI_UNSUPPORTED :\r
871 ShellStatus = SHELL_UNSUPPORTED;\r
872 break;\r
873\r
874 case EFI_DEVICE_ERROR :\r
875 ShellStatus = SHELL_DEVICE_ERROR;\r
876 break;\r
877\r
878 case EFI_WRITE_PROTECTED :\r
879 case EFI_SECURITY_VIOLATION :\r
880 ShellStatus = SHELL_ACCESS_DENIED;\r
881 break;\r
882\r
883 case EFI_OUT_OF_RESOURCES :\r
884 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
885 break;\r
886\r
887 case EFI_NOT_FOUND :\r
888 ShellStatus = SHELL_NOT_FOUND;\r
889 break;\r
890\r
891 default :\r
892 ShellStatus = SHELL_ABORTED;\r
893 }\r
894\r
895 return ShellStatus;\r
896}\r