+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "FdtPlatform.h"\r
-\r
-#include <Library/PcdLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/BdsLib.h>\r
-\r
-#include <Protocol/DevicePath.h>\r
-\r
-//\r
-// Internal variables\r
-//\r
-\r
-STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolSetFdt = {\r
- L"setfdt", // Name of the command\r
- ShellDynCmdSetFdtHandler, // Handler\r
- ShellDynCmdSetFdtGetHelp // GetHelp\r
-};\r
-\r
-STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolDumpFdt = {\r
- L"dumpfdt", // Name of the command\r
- ShellDynCmdDumpFdtHandler, // Handler\r
- ShellDynCmdDumpFdtGetHelp // GetHelp\r
-};\r
-\r
-STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid = {\r
- 0x8afa7610, 0x62b1, 0x46aa,\r
- {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}\r
- };\r
-\r
-EFI_HANDLE mFdtPlatformDxeHiiHandle;\r
-\r
-/**\r
- Install the FDT specified by its device path in text form.\r
-\r
- @param[in] TextDevicePath Device path of the FDT to install in text form\r
-\r
- @retval EFI_SUCCESS The FDT was installed.\r
- @retval EFI_NOT_FOUND Failed to locate a protocol or a file.\r
- @retval EFI_INVALID_PARAMETER Invalid device path.\r
- @retval EFI_UNSUPPORTED Device path not supported.\r
- @retval EFI_OUT_OF_RESOURCES An allocation failed.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-InstallFdt (\r
- IN CONST CHAR16* TextDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
- EFI_DEVICE_PATH *DevicePath;\r
- EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
- UINTN FdtBlobSize;\r
- UINTN NumPages;\r
- EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase;\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiDevicePathFromTextProtocolGuid,\r
- NULL,\r
- (VOID **)&EfiDevicePathFromTextProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n"));\r
- return Status;\r
- }\r
-\r
- DevicePath = (EFI_DEVICE_PATH*)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (TextDevicePath);\r
- if (DevicePath == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Load the FDT given its device path.\r
- // This operation may fail if the device path is not supported.\r
- //\r
- FdtBlobBase = 0;\r
- NumPages = 0;\r
- Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Ensure that the FDT header is valid and that the Size of the Device Tree\r
- // is smaller than the size of the read file\r
- //\r
- if (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) != 0 ||\r
- (UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) > FdtBlobSize) {\r
- DEBUG ((EFI_D_ERROR, "InstallFdt() - loaded FDT binary image seems corrupt\n"));\r
- Status = EFI_LOAD_ERROR;\r
- goto Error;\r
- }\r
-\r
- //\r
- // Store the FDT as Runtime Service Data to prevent the Kernel from\r
- // overwritting its data.\r
- //\r
- NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
- Status = gBS->AllocatePages (\r
- AllocateAnyPages, EfiRuntimeServicesData,\r
- NumPages, &FdtConfigurationTableBase\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
- CopyMem (\r
- (VOID*)(UINTN)FdtConfigurationTableBase,\r
- (VOID*)(UINTN)FdtBlobBase,\r
- FdtBlobSize\r
- );\r
-\r
- //\r
- // Install the FDT into the Configuration Table\r
- //\r
- Status = gBS->InstallConfigurationTable (\r
- &gFdtTableGuid,\r
- (VOID*)(UINTN)FdtConfigurationTableBase\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->FreePages (FdtConfigurationTableBase, NumPages);\r
- }\r
-\r
-Error:\r
- if (FdtBlobBase != 0) {\r
- gBS->FreePages (FdtBlobBase, NumPages);\r
- }\r
- FreePool (DevicePath);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Main entry point of the FDT platform driver.\r
-\r
- @param[in] ImageHandle The firmware allocated handle for the present driver\r
- UEFI image.\r
- @param[in] *SystemTable A pointer to the EFI System table.\r
-\r
- @retval EFI_SUCCESS The driver was initialized.\r
- @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or\r
- there was not enough memory in pool to install\r
- the Shell Dynamic Command protocol.\r
- @retval EFI_LOAD_ERROR Unable to add the HII package.\r
-\r
-**/\r
-EFI_STATUS\r
-FdtPlatformEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
-\r
- //\r
- // Install the Device Tree from its expected location\r
- //\r
- Status = RunFdtInstallation (NULL);\r
-\r
- if (FeaturePcdGet (PcdOverridePlatformFdt) || FeaturePcdGet (PcdDumpFdtShellCommand)) {\r
- //\r
- // Register the strings for the user interface in the HII Database.\r
- // This shows the way to the multi-language support, even if\r
- // only the English language is actually supported. The strings to register\r
- // are stored in the "ShellSetFdtStrings[]" array. This array is\r
- // built by the building process from the "*.uni" file associated to\r
- // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build\r
- // folder under your package's DEBUG folder and you will find the array\r
- // defined in a xxxStrDefs.h file.\r
- //\r
- mFdtPlatformDxeHiiHandle = HiiAddPackages (\r
- &mFdtPlatformDxeHiiGuid,\r
- ImageHandle,\r
- FdtPlatformDxeStrings,\r
- NULL\r
- );\r
- }\r
-\r
- //\r
- // If the development features are enabled, install the dynamic shell\r
- // command "setfdt" to be able to define a device path for the FDT\r
- // that has precedence over the device paths defined by\r
- // "PcdFdtDevicePaths".\r
- //\r
-\r
- if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
- if (mFdtPlatformDxeHiiHandle != NULL) {\r
- // We install dynamic EFI command on separate handles as we cannot register\r
- // more than one protocol of the same protocol interface on the same handle.\r
- Handle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle,\r
- &gEfiShellDynamicCommandProtocolGuid,\r
- &mShellDynCmdProtocolSetFdt,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- HiiRemovePackages (mFdtPlatformDxeHiiHandle);\r
- }\r
- } else {\r
- Status = EFI_LOAD_ERROR;\r
- }\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_WARN,\r
- "Unable to install \"setfdt\" EFI Shell command - %r \n",\r
- Status\r
- ));\r
- }\r
- }\r
-\r
- if (FeaturePcdGet (PcdDumpFdtShellCommand)) {\r
- if (mFdtPlatformDxeHiiHandle != NULL) {\r
- // We install dynamic EFI command on separate handles as we cannot register\r
- // more than one protocol of the same protocol interface on the same handle.\r
- Handle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle,\r
- &gEfiShellDynamicCommandProtocolGuid,\r
- &mShellDynCmdProtocolDumpFdt,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- HiiRemovePackages (mFdtPlatformDxeHiiHandle);\r
- }\r
- } else {\r
- Status = EFI_LOAD_ERROR;\r
- }\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_WARN,\r
- "Unable to install \"dumpfdt\" EFI Shell command - %r \n",\r
- Status\r
- ));\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Run the FDT installation process.\r
-\r
- Loop in priority order over the device paths from which the FDT has\r
- been asked to be retrieved for. For each device path, try to install\r
- the FDT. Stop as soon as an installation succeeds.\r
-\r
- @param[in] SuccessfullDevicePath If not NULL, address where to store the\r
- pointer to the text device path from\r
- which the FDT was successfully retrieved.\r
- Not used if the FDT installation failed.\r
- The returned address is the address of\r
- an allocated buffer that has to be\r
- freed by the caller.\r
-\r
- @retval EFI_SUCCESS The FDT was installed.\r
- @retval EFI_NOT_FOUND Failed to locate a protocol or a file.\r
- @retval EFI_INVALID_PARAMETER Invalid device path.\r
- @retval EFI_UNSUPPORTED Device path not supported.\r
- @retval EFI_OUT_OF_RESOURCES An allocation failed.\r
-\r
-**/\r
-EFI_STATUS\r
-RunFdtInstallation (\r
- OUT CHAR16 **SuccessfullDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN DataSize;\r
- CHAR16 *TextDevicePath;\r
- CHAR16 *TextDevicePathStart;\r
- CHAR16 *TextDevicePathSeparator;\r
- UINTN TextDevicePathLen;\r
-\r
- TextDevicePath = NULL;\r
- //\r
- // For development purpose, if enabled through the "PcdOverridePlatformFdt"\r
- // feature PCD, try first to install the FDT specified by the device path in\r
- // text form stored in the "Fdt" UEFI variable.\r
- //\r
- if (FeaturePcdGet (PcdOverridePlatformFdt)) {\r
- DataSize = 0;\r
- Status = gRT->GetVariable (\r
- L"Fdt",\r
- &gFdtVariableGuid,\r
- NULL,\r
- &DataSize,\r
- NULL\r
- );\r
-\r
- //\r
- // Keep going only if the "Fdt" variable is defined.\r
- //\r
-\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- TextDevicePath = AllocatePool (DataSize);\r
- if (TextDevicePath == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- Status = gRT->GetVariable (\r
- L"Fdt",\r
- &gFdtVariableGuid,\r
- NULL,\r
- &DataSize,\r
- TextDevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (TextDevicePath);\r
- goto Error;\r
- }\r
-\r
- Status = InstallFdt (TextDevicePath);\r
- if (!EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_WARN,\r
- "Installation of the FDT using the device path <%s> completed.\n",\r
- TextDevicePath\r
- ));\r
- goto Done;\r
- }\r
- DEBUG ((\r
- EFI_D_ERROR,\r
- "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",\r
- Status\r
- ));\r
- FreePool (TextDevicePath);\r
- }\r
- }\r
-\r
- //\r
- // Loop over the device path list provided by "PcdFdtDevicePaths". The device\r
- // paths are in text form and separated by a semi-colon.\r
- //\r
-\r
- Status = EFI_NOT_FOUND;\r
- for (TextDevicePathStart = (CHAR16*)PcdGetPtr (PcdFdtDevicePaths);\r
- *TextDevicePathStart != L'\0' ; ) {\r
- TextDevicePathSeparator = StrStr (TextDevicePathStart, L";");\r
-\r
- //\r
- // Last device path of the list\r
- //\r
- if (TextDevicePathSeparator == NULL) {\r
- TextDevicePathLen = StrLen (TextDevicePathStart);\r
- } else {\r
- TextDevicePathLen = (UINTN)(TextDevicePathSeparator - TextDevicePathStart);\r
- }\r
-\r
- TextDevicePath = AllocateCopyPool (\r
- (TextDevicePathLen + 1) * sizeof (CHAR16),\r
- TextDevicePathStart\r
- );\r
- if (TextDevicePath == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
- TextDevicePath[TextDevicePathLen] = L'\0';\r
-\r
- Status = InstallFdt (TextDevicePath);\r
- if (!EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> completed.\n",\r
- TextDevicePath\r
- ));\r
- goto Done;\r
- }\r
-\r
- DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> failed - %r.\n",\r
- TextDevicePath, Status\r
- ));\r
- FreePool (TextDevicePath);\r
-\r
- if (TextDevicePathSeparator == NULL) {\r
- goto Error;\r
- }\r
- TextDevicePathStart = TextDevicePathSeparator + 1;\r
- }\r
-\r
-Error:\r
-Done:\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Failed to install the FDT - %r.\n", Status));\r
- return Status;\r
- }\r
-\r
- if (SuccessfullDevicePath != NULL) {\r
- *SuccessfullDevicePath = TextDevicePath;\r
- } else {\r
- FreePool (TextDevicePath);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Transcode one of the EFI return code used by the model into an EFI Shell return code.\r
-\r
- @param[in] Status EFI return code.\r
-\r
- @return Transcoded EFI Shell return code.\r
-\r
-**/\r
-SHELL_STATUS\r
-EfiCodeToShellCode (\r
- IN EFI_STATUS Status\r
- )\r
-{\r
- SHELL_STATUS ShellStatus;\r
-\r
- switch (Status) {\r
- case EFI_SUCCESS :\r
- ShellStatus = SHELL_SUCCESS;\r
- break;\r
-\r
- case EFI_INVALID_PARAMETER :\r
- ShellStatus = SHELL_INVALID_PARAMETER;\r
- break;\r
-\r
- case EFI_UNSUPPORTED :\r
- ShellStatus = SHELL_UNSUPPORTED;\r
- break;\r
-\r
- case EFI_DEVICE_ERROR :\r
- ShellStatus = SHELL_DEVICE_ERROR;\r
- break;\r
-\r
- case EFI_WRITE_PROTECTED :\r
- case EFI_SECURITY_VIOLATION :\r
- ShellStatus = SHELL_ACCESS_DENIED;\r
- break;\r
-\r
- case EFI_OUT_OF_RESOURCES :\r
- ShellStatus = SHELL_OUT_OF_RESOURCES;\r
- break;\r
-\r
- case EFI_NOT_FOUND :\r
- ShellStatus = SHELL_NOT_FOUND;\r
- break;\r
-\r
- default :\r
- ShellStatus = SHELL_ABORTED;\r
- }\r
-\r
- return ShellStatus;\r
-}\r