3 Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
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
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.
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>
24 #include <Library/BdsLib.h>
26 #include <Protocol/DevicePathFromText.h>
27 #include <Protocol/DevicePath.h>
29 #include <Guid/EventGroup.h>
37 STATIC VOID
OnEndOfDxe (
41 STATIC EFI_STATUS
RunFdtInstallation (
44 STATIC EFI_STATUS
InstallFdt (
45 IN CONST CHAR16
* TextDevicePath
49 Main entry point of the FDT platform driver.
51 @param[in] ImageHandle The firmware allocated handle for the present driver
53 @param[in] *SystemTable A pointer to the EFI System table.
55 @retval EFI_SUCCESS The driver was initialized.
56 @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated.
60 FdtPlatformEntryPoint (
61 IN EFI_HANDLE ImageHandle
,
62 IN EFI_SYSTEM_TABLE
*SystemTable
66 EFI_EVENT EndOfDxeEvent
;
69 // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.
70 // The "OnEndOfDxe()" function is declared as the call back function.
71 // It will be called at the end of the DXE phase when an event of the
72 // same group is signalled to inform about the end of the DXE phase.
74 Status
= gBS
->CreateEventEx (
79 &gEfiEndOfDxeEventGroupGuid
,
87 Notification function of the event defined as belonging to the
88 EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
89 the entry point of the driver.
91 This function is called when an event belonging to the
92 EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an
93 event is signalled once at the end of the dispatching of all
94 drivers (end of the so called DXE phase).
96 @param[in] Event Event declared in the entry point of the driver whose
97 notification function is being invoked.
98 @param[in] Context NULL
108 RunFdtInstallation ();
109 gBS
->CloseEvent (Event
);
113 Run the FDT installation process.
115 Loop in priority order over the device paths from which the FDT has
116 been asked to be retrieved for. For each device path, try to install
117 the FDT. Stop as soon as an installation succeeds.
119 @retval EFI_SUCCESS The FDT was installed.
120 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
121 @retval EFI_INVALID_PARAMETER Invalid device path.
122 @retval EFI_UNSUPPORTED Device path not supported.
123 @retval EFI_OUT_OF_RESOURCES An allocation failed.
135 CHAR16
*TextDevicePathStart
;
136 CHAR16
*TextDevicePathSeparator
;
137 UINTN TextDevicePathLen
;
138 CHAR16
*TextDevicePath
;
141 // For development purpose, if enabled through the "PcdOverridePlatformFdt"
142 // feature PCD, try first to install the FDT specified by the device path in
143 // text form stored in the "Fdt" UEFI variable.
145 if (FeaturePcdGet (PcdOverridePlatformFdt
)) {
148 Status
= gRT
->GetVariable (
157 // Keep going only if the "Fdt" variable is defined.
160 if (Status
== EFI_BUFFER_TOO_SMALL
) {
161 Data
= AllocatePool (DataSize
);
163 Status
= EFI_OUT_OF_RESOURCES
;
165 Status
= gRT
->GetVariable (
172 if (!EFI_ERROR (Status
)) {
173 Status
= InstallFdt ((CHAR16
*)Data
);
174 if (!EFI_ERROR (Status
)) {
177 "Installation of the FDT using the device path <%s> completed.\n",
185 if (EFI_ERROR (Status
)) {
188 "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",
198 // Loop over the device path list provided by "PcdFdtDevicePaths". The device
199 // paths are in text form and separated by a semi-colon.
202 Status
= EFI_SUCCESS
;
203 for (TextDevicePathStart
= (CHAR16
*)PcdGetPtr (PcdFdtDevicePaths
);
204 *TextDevicePathStart
!= L
'\0' ; ) {
205 TextDevicePathSeparator
= StrStr (TextDevicePathStart
, L
";");
208 // Last device path of the list
210 if (TextDevicePathSeparator
== NULL
) {
211 TextDevicePath
= TextDevicePathStart
;
213 TextDevicePathLen
= (UINTN
)(TextDevicePathSeparator
- TextDevicePathStart
);
214 TextDevicePath
= AllocateCopyPool (
215 (TextDevicePathLen
+ 1) * sizeof (CHAR16
),
218 if (TextDevicePath
== NULL
) {
219 Status
= EFI_OUT_OF_RESOURCES
;
220 DEBUG ((EFI_D_ERROR
, "Memory allocation error during FDT installation process.\n"));
223 TextDevicePath
[TextDevicePathLen
] = L
'\0';
226 Status
= InstallFdt (TextDevicePath
);
227 if (EFI_ERROR (Status
)) {
228 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> failed - %r.\n",
229 TextDevicePath
, Status
232 DEBUG ((EFI_D_WARN
, "Installation of the FDT using the device path <%s> completed.\n",
237 if (TextDevicePathSeparator
== NULL
) {
240 FreePool (TextDevicePath
);
241 if (!EFI_ERROR (Status
)) {
244 TextDevicePathStart
= TextDevicePathSeparator
+ 1;
248 if (EFI_ERROR (Status
)) {
249 DEBUG ((EFI_D_ERROR
, "Failed to install the FDT - %r.\n", Status
));
256 Install the FDT specified by its device path in text form.
258 @param[in] TextDevicePath Device path of the FDT to install in text form
260 @retval EFI_SUCCESS The FDT was installed.
261 @retval EFI_NOT_FOUND Failed to locate a protocol or a file.
262 @retval EFI_INVALID_PARAMETER Invalid device path.
263 @retval EFI_UNSUPPORTED Device path not supported.
264 @retval EFI_OUT_OF_RESOURCES An allocation failed.
269 IN CONST CHAR16
* TextDevicePath
273 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*EfiDevicePathFromTextProtocol
;
274 EFI_DEVICE_PATH
*DevicePath
;
275 EFI_PHYSICAL_ADDRESS FdtBlobBase
;
278 EFI_PHYSICAL_ADDRESS RsFdtBlobBase
;
280 Status
= gBS
->LocateProtocol (
281 &gEfiDevicePathFromTextProtocolGuid
,
283 (VOID
**)&EfiDevicePathFromTextProtocol
285 if (EFI_ERROR (Status
)) {
286 DEBUG ((EFI_D_ERROR
, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));
290 DevicePath
= (EFI_DEVICE_PATH
*)EfiDevicePathFromTextProtocol
->ConvertTextToDevicePath (TextDevicePath
);
291 if (DevicePath
== NULL
) {
292 return EFI_INVALID_PARAMETER
;
296 // Load the FDT given its device path.
297 // This operation may fail if the device path is not supported.
301 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
, &FdtBlobBase
, &FdtBlobSize
);
302 if (EFI_ERROR (Status
)) {
306 // Check the FDT header is valid. We only make this check in DEBUG mode in
307 // case the FDT header change on production device and this ASSERT() becomes
309 ASSERT (fdt_check_header ((VOID
*)(UINTN
)FdtBlobBase
) == 0);
312 // Ensure the Size of the Device Tree is smaller than the size of the read file
314 ASSERT ((UINTN
)fdt_totalsize ((VOID
*)(UINTN
)FdtBlobBase
) <= FdtBlobSize
);
317 // Store the FDT as Runtime Service Data to prevent the Kernel from
318 // overwritting its data.
320 NbPages
= EFI_SIZE_TO_PAGES (FdtBlobSize
);
321 Status
= gBS
->AllocatePages (
322 AllocateAnyPages
, EfiRuntimeServicesData
,
323 NbPages
, &RsFdtBlobBase
325 if (EFI_ERROR (Status
)) {
329 (VOID
*)((UINTN
)RsFdtBlobBase
),
330 (VOID
*)((UINTN
)FdtBlobBase
),
335 // Install the FDT into the Configuration Table
337 Status
= gBS
->InstallConfigurationTable (
339 (VOID
*)((UINTN
)RsFdtBlobBase
)
341 if (EFI_ERROR (Status
)) {
342 gBS
->FreePages (RsFdtBlobBase
, NbPages
);
347 if (FdtBlobBase
!= 0) {
348 gBS
->FreePages (FdtBlobBase
, NbPages
);
350 FreePool (DevicePath
);
358 This is the shell command "setfdt" handler function. This function handles
359 the command when it is invoked in the shell.
361 @param[in] This The instance of the
362 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
363 @param[in] SystemTable The pointer to the UEFI system table.
364 @param[in] ShellParameters The parameters associated with the command.
365 @param[in] Shell The instance of the shell protocol used in the
366 context of processing this command.
368 @return SHELL_SUCCESS The operation was successful.
369 @return SHELL_ABORTED Operation aborted due to internal error.
370 @return SHELL_INVALID_PARAMETER The parameters of the command are not valid.
371 @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid.
372 @return SHELL_NOT_FOUND Failed to locate a protocol or a file.
373 @return SHELL_UNSUPPORTED Device path not supported.
374 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
375 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.
376 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.
377 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.
378 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.
384 ShellDynCmdSetFdtHandler (
385 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL
*This
,
386 IN EFI_SYSTEM_TABLE
*SystemTable
,
387 IN EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
388 IN EFI_SHELL_PROTOCOL
*Shell
391 SHELL_STATUS ShellStatus
;
393 LIST_ENTRY
*ParamPackage
;
395 CONST CHAR16
*ValueStr
;
397 ShellStatus
= SHELL_SUCCESS
;
402 // Install the Shell and Shell Parameters Protocols on the driver
403 // image. This is necessary for the initialisation of the Shell
404 // Library to succeed in the next step.
406 Status
= gBS
->InstallMultipleProtocolInterfaces (
408 &gEfiShellProtocolGuid
, Shell
,
409 &gEfiShellParametersProtocolGuid
, ShellParameters
,
412 if (EFI_ERROR (Status
)) {
413 return SHELL_ABORTED
;
417 // Initialise the Shell Library as we are going to use it.
418 // Assert that the return code is EFI_SUCCESS as it should.
419 // To anticipate any change is the codes returned by
420 // ShellInitialize(), leave in case of error.
422 Status
= ShellInitialize ();
423 if (EFI_ERROR (Status
)) {
424 ASSERT_EFI_ERROR (Status
);
425 return SHELL_ABORTED
;
428 Status
= ShellCommandLineParse (ParamList
, &ParamPackage
, NULL
, TRUE
);
429 if (!EFI_ERROR (Status
)) {
430 switch (ShellCommandLineGetCount (ParamPackage
)) {
435 if (!ShellCommandLineGetFlag (ParamPackage
, L
"-i")) {
436 Status
= EFI_INVALID_PARAMETER
;
442 // Case "setfdt file_path" or
443 // "setfdt -i file_path" or
444 // "setfdt file_path -i"
450 Status
= EFI_INVALID_PARAMETER
;
453 if (EFI_ERROR (Status
)) {
454 ShellStatus
= EfiCodeToShellCode (Status
);
457 STRING_TOKEN (STR_SETFDT_ERROR
),
458 mFdtPlatformDxeHiiHandle
,
465 // Update the preferred device path for the FDT if asked for.
468 ValueStr
= ShellCommandLineGetRawValue (ParamPackage
, 1);
471 STRING_TOKEN (STR_SETFDT_UPDATING
),
472 mFdtPlatformDxeHiiHandle
474 ShellStatus
= UpdateFdtTextDevicePath (Shell
, ValueStr
);
475 if (ShellStatus
!= SHELL_SUCCESS
) {
481 // Run the FDT installation process if asked for.
483 if (ShellCommandLineGetFlag (ParamPackage
, L
"-i")) {
486 STRING_TOKEN (STR_SETFDT_INSTALLING
),
487 mFdtPlatformDxeHiiHandle
489 Status
= RunFdtInstallation ();
490 ShellStatus
= EfiCodeToShellCode (Status
);
491 if (!EFI_ERROR (Status
)) {
494 STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED
),
495 mFdtPlatformDxeHiiHandle
498 if (Status
== EFI_INVALID_PARAMETER
) {
501 STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH
),
502 mFdtPlatformDxeHiiHandle
507 STRING_TOKEN (STR_SETFDT_ERROR
),
508 mFdtPlatformDxeHiiHandle
,
517 gBS
->UninstallMultipleProtocolInterfaces (
519 &gEfiShellProtocolGuid
, Shell
,
520 &gEfiShellParametersProtocolGuid
, ShellParameters
,
523 ShellCommandLineFreeVarList (ParamPackage
);
529 This is the shell command "setfdt" help handler function. This
530 function returns the formatted help for the "setfdt" command.
531 The format matchs that in Appendix B of the revision 2.1 of the
532 UEFI Shell Specification.
534 @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
535 @param[in] Language The pointer to the language string to use.
537 @return CHAR16* Pool allocated help string, must be freed by caller.
542 ShellDynCmdSetFdtGetHelp (
543 IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL
*This
,
544 IN CONST CHAR8
*Language
548 // This allocates memory. The caller has to free the allocated memory.
550 return HiiGetString (
551 mFdtPlatformDxeHiiHandle
,
552 STRING_TOKEN (STR_GET_HELP_SETFDT
),
558 Update the text device path stored in the "Fdt" UEFI variable given
559 an EFI Shell file path or a text device path.
561 This function is a subroutine of the ShellDynCmdSetFdtHandler() function
562 to make its code easier to read.
564 @param[in] Shell The instance of the shell protocol used in the
565 context of processing the "setfdt" command.
566 @param[in] FilePath EFI Shell path or the device path to the FDT file.
568 @return SHELL_SUCCESS The text device path was succesfully updated.
569 @return SHELL_INVALID_PARAMETER The Shell file path is not valid.
570 @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
571 @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.
572 @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.
573 @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.
574 @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.
575 @return SHELL_NOT_FOUND Device path to text protocol not found.
576 @return SHELL_ABORTED Operation aborted.
581 UpdateFdtTextDevicePath (
582 IN EFI_SHELL_PROTOCOL
*Shell
,
583 IN CONST CHAR16
*FilePath
587 EFI_DEVICE_PATH
*DevicePath
;
588 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*EfiDevicePathToTextProtocol
;
589 CHAR16
*TextDevicePath
;
590 CHAR16
*FdtVariableValue
;
591 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*EfiDevicePathFromTextProtocol
;
592 SHELL_STATUS ShellStatus
;
594 ASSERT (FilePath
!= NULL
);
595 TextDevicePath
= NULL
;
596 FdtVariableValue
= NULL
;
598 DevicePath
= Shell
->GetDevicePathFromFilePath (FilePath
);
599 if (DevicePath
!= NULL
) {
600 Status
= gBS
->LocateProtocol (
601 &gEfiDevicePathToTextProtocolGuid
,
603 (VOID
**)&EfiDevicePathToTextProtocol
605 if (EFI_ERROR (Status
)) {
609 TextDevicePath
= EfiDevicePathToTextProtocol
->ConvertDevicePathToText (
614 if (TextDevicePath
== NULL
) {
615 Status
= EFI_OUT_OF_RESOURCES
;
618 FdtVariableValue
= TextDevicePath
;
621 // Try to convert back the EFI Device Path String into a EFI device Path
622 // to ensure the format is valid
624 Status
= gBS
->LocateProtocol (
625 &gEfiDevicePathFromTextProtocolGuid
,
627 (VOID
**)&EfiDevicePathFromTextProtocol
629 if (EFI_ERROR (Status
)) {
633 DevicePath
= EfiDevicePathFromTextProtocol
->ConvertTextToDevicePath (
636 if (DevicePath
== NULL
) {
637 Status
= EFI_INVALID_PARAMETER
;
640 FdtVariableValue
= (CHAR16
*)FilePath
;
643 Status
= gRT
->SetVariable (
646 EFI_VARIABLE_RUNTIME_ACCESS
|
647 EFI_VARIABLE_NON_VOLATILE
|
648 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
649 StrSize (FdtVariableValue
),
654 ShellStatus
= EfiCodeToShellCode (Status
);
655 if (!EFI_ERROR (Status
)) {
658 STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED
),
659 mFdtPlatformDxeHiiHandle
,
663 if (Status
== EFI_INVALID_PARAMETER
) {
666 STRING_TOKEN (STR_SETFDT_INVALID_PATH
),
667 mFdtPlatformDxeHiiHandle
,
673 STRING_TOKEN (STR_SETFDT_ERROR
),
674 mFdtPlatformDxeHiiHandle
,
680 if (DevicePath
!= NULL
) {
681 FreePool (DevicePath
);
683 if (TextDevicePath
!= NULL
) {
684 FreePool (TextDevicePath
);
691 Transcode one of the EFI return code used by the model into an EFI Shell return code.
693 @param[in] Status EFI return code.
695 @return Transcoded EFI Shell return code.
704 SHELL_STATUS ShellStatus
;
708 ShellStatus
= SHELL_SUCCESS
;
711 case EFI_INVALID_PARAMETER
:
712 ShellStatus
= SHELL_INVALID_PARAMETER
;
715 case EFI_UNSUPPORTED
:
716 ShellStatus
= SHELL_UNSUPPORTED
;
719 case EFI_DEVICE_ERROR
:
720 ShellStatus
= SHELL_DEVICE_ERROR
;
723 case EFI_WRITE_PROTECTED
:
724 case EFI_SECURITY_VIOLATION
:
725 ShellStatus
= SHELL_ACCESS_DENIED
;
728 case EFI_OUT_OF_RESOURCES
:
729 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
733 ShellStatus
= SHELL_NOT_FOUND
;
737 ShellStatus
= SHELL_ABORTED
;
742 >>>>>>> 4ac4fed
... EmbeddedPkg
/FdtPlatformDxe
: Fix typo issue