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