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