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