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