--- /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
+#include <Uefi.h>\r
+\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+\r
+#include <Library/BdsLib.h>\r
+\r
+#include <Protocol/DevicePathFromText.h>\r
+#include <Protocol/DevicePath.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/Fdt.h>\r
+\r
+#include <libfdt.h>\r
+\r
+//\r
+// Internal types\r
+//\r
+STATIC VOID OnEndOfDxe (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+STATIC EFI_STATUS RunFdtInstallation (\r
+ VOID\r
+ );\r
+STATIC EFI_STATUS InstallFdt (\r
+ IN CONST CHAR16* TextDevicePath\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.\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_EVENT EndOfDxeEvent;\r
+\r
+ //\r
+ // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.\r
+ // The "OnEndOfDxe()" function is declared as the call back function.\r
+ // It will be called at the end of the DXE phase when an event of the\r
+ // same group is signalled to inform about the end of the DXE phase.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ OnEndOfDxe,\r
+ NULL,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Notification function of the event defined as belonging to the\r
+ EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in\r
+ the entry point of the driver.\r
+\r
+ This function is called when an event belonging to the\r
+ EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an\r
+ event is signalled once at the end of the dispatching of all\r
+ drivers (end of the so called DXE phase).\r
+\r
+ @param[in] Event Event declared in the entry point of the driver whose\r
+ notification function is being invoked.\r
+ @param[in] Context NULL\r
+\r
+**/\r
+STATIC\r
+VOID\r
+OnEndOfDxe (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ RunFdtInstallation ();\r
+ gBS->CloseEvent (Event);\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
+ @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
+STATIC\r
+EFI_STATUS\r
+RunFdtInstallation (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN DataSize;\r
+ VOID *Data;\r
+ CHAR16 *TextDevicePathStart;\r
+ CHAR16 *TextDevicePathSeparator;\r
+ UINTN TextDevicePathLen;\r
+ CHAR16 *TextDevicePath;\r
+\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
+ Data = NULL;\r
+ DataSize = 0;\r
+ Status = gRT->GetVariable (\r
+ L"Fdt",\r
+ &gFdtVariableGuid,\r
+ NULL,\r
+ &DataSize,\r
+ Data\r
+ );\r
+\r
+ //\r
+ // Keep going only if the "Fdt" variable is defined.\r
+ //\r
+\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ Data = AllocatePool (DataSize);\r
+ if (Data == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ Status = gRT->GetVariable (\r
+ L"Fdt",\r
+ &gFdtVariableGuid,\r
+ NULL,\r
+ &DataSize,\r
+ Data\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = InstallFdt ((CHAR16*)Data);\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_WARN,\r
+ "Installation of the FDT using the device path <%s> completed.\n",\r
+ (CHAR16*)Data\r
+ ));\r
+ }\r
+ }\r
+ FreePool (Data);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n",\r
+ Status\r
+ ));\r
+ } else {\r
+ return Status;\r
+ }\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_SUCCESS;\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
+ TextDevicePath = TextDevicePathStart;\r
+ } else {\r
+ TextDevicePathLen = (UINTN)(TextDevicePathSeparator - TextDevicePathStart);\r
+ TextDevicePath = AllocateCopyPool (\r
+ (TextDevicePathLen + 1) * sizeof (CHAR16),\r
+ TextDevicePathStart\r
+ );\r
+ if (TextDevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ DEBUG ((EFI_D_ERROR, "Memory allocation error during FDT installation process.\n"));\r
+ break;\r
+ }\r
+ TextDevicePath[TextDevicePathLen] = L'\0';\r
+ }\r
+\r
+ Status = InstallFdt (TextDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> failed - %r.\n",\r
+ TextDevicePath, Status\r
+ ));\r
+ } else {\r
+ DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> completed.\n",\r
+ TextDevicePath\r
+ ));\r
+ }\r
+\r
+ if (TextDevicePathSeparator == NULL) {\r
+ break;\r
+ } else {\r
+ FreePool (TextDevicePath);\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ TextDevicePathStart = TextDevicePathSeparator + 1;\r
+ }\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Failed to install the FDT - %r.\n", Status));\r
+ }\r
+\r
+ return Status;\r
+}\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 NbPages;\r
+ EFI_PHYSICAL_ADDRESS RsFdtBlobBase;\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
+ NbPages = 0;\r
+ Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ // Check the FDT header is valid. We only make this check in DEBUG mode in\r
+ // case the FDT header change on production device and this ASSERT() becomes\r
+ // not valid.\r
+ ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0);\r
+\r
+ //\r
+ // Ensure the Size of the Device Tree is smaller than the size of the read file\r
+ //\r
+ ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize);\r
+\r
+ //\r
+ // Store the FDT as Runtime Service Data to prevent the Kernel from\r
+ // overwritting its data.\r
+ //\r
+ NbPages = EFI_SIZE_TO_PAGES (FdtBlobSize);\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages, EfiRuntimeServicesData,\r
+ NbPages, &RsFdtBlobBase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ CopyMem (\r
+ (VOID*)((UINTN)RsFdtBlobBase),\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)RsFdtBlobBase)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePages (RsFdtBlobBase, NbPages);\r
+ }\r
+\r
+Error :\r
+\r
+ if (FdtBlobBase != 0) {\r
+ gBS->FreePages (FdtBlobBase, NbPages);\r
+ }\r
+ FreePool (DevicePath);\r
+\r
+ return Status;\r
+}\r
+\r
+=======\r
+\r
+/**\r
+ This is the shell command "setfdt" handler function. This function handles\r
+ the command when it is invoked in the shell.\r
+\r
+ @param[in] This The instance of the\r
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] SystemTable The pointer to the UEFI system table.\r
+ @param[in] ShellParameters The parameters associated with the command.\r
+ @param[in] Shell The instance of the shell protocol used in the\r
+ context of processing this command.\r
+\r
+ @return SHELL_SUCCESS The operation was successful.\r
+ @return SHELL_ABORTED Operation aborted due to internal error.\r
+ @return SHELL_INVALID_PARAMETER The parameters of the command are not valid.\r
+ @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid.\r
+ @return SHELL_NOT_FOUND Failed to locate a protocol or a file.\r
+ @return SHELL_UNSUPPORTED Device path not supported.\r
+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
+ @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.\r
+\r
+**/\r
+STATIC\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellDynCmdSetFdtHandler (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN EFI_SYSTEM_TABLE *SystemTable,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
+ IN EFI_SHELL_PROTOCOL *Shell\r
+ )\r
+{\r
+ SHELL_STATUS ShellStatus;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *ParamPackage;\r
+ BOOLEAN FilePath;\r
+ CONST CHAR16 *ValueStr;\r
+\r
+ ShellStatus = SHELL_SUCCESS;\r
+ ParamPackage = NULL;\r
+ FilePath = FALSE;\r
+\r
+ //\r
+ // Install the Shell and Shell Parameters Protocols on the driver\r
+ // image. This is necessary for the initialisation of the Shell\r
+ // Library to succeed in the next step.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &gImageHandle,\r
+ &gEfiShellProtocolGuid, Shell,\r
+ &gEfiShellParametersProtocolGuid, ShellParameters,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return SHELL_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Initialise the Shell Library as we are going to use it.\r
+ // Assert that the return code is EFI_SUCCESS as it should.\r
+ // To anticipate any change is the codes returned by\r
+ // ShellInitialize(), leave in case of error.\r
+ //\r
+ Status = ShellInitialize ();\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return SHELL_ABORTED;\r
+ }\r
+\r
+ Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);\r
+ if (!EFI_ERROR (Status)) {\r
+ switch (ShellCommandLineGetCount (ParamPackage)) {\r
+ case 1:\r
+ //\r
+ // Case "setfdt -i"\r
+ //\r
+ if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case 2:\r
+ //\r
+ // Case "setfdt file_path" or\r
+ // "setfdt -i file_path" or\r
+ // "setfdt file_path -i"\r
+ //\r
+ FilePath = TRUE;\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ ShellStatus = EfiCodeToShellCode (Status);\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_ERROR),\r
+ mFdtPlatformDxeHiiHandle,\r
+ Status\r
+ );\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Update the preferred device path for the FDT if asked for.\r
+ //\r
+ if (FilePath) {\r
+ ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_UPDATING),\r
+ mFdtPlatformDxeHiiHandle\r
+ );\r
+ ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr);\r
+ if (ShellStatus != SHELL_SUCCESS) {\r
+ goto Error;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Run the FDT installation process if asked for.\r
+ //\r
+ if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_INSTALLING),\r
+ mFdtPlatformDxeHiiHandle\r
+ );\r
+ Status = RunFdtInstallation ();\r
+ ShellStatus = EfiCodeToShellCode (Status);\r
+ if (!EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED),\r
+ mFdtPlatformDxeHiiHandle\r
+ );\r
+ } else {\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH),\r
+ mFdtPlatformDxeHiiHandle\r
+ );\r
+ } else {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_ERROR),\r
+ mFdtPlatformDxeHiiHandle,\r
+ Status\r
+ );\r
+ }\r
+ }\r
+ }\r
+\r
+Error:\r
+\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ gImageHandle,\r
+ &gEfiShellProtocolGuid, Shell,\r
+ &gEfiShellParametersProtocolGuid, ShellParameters,\r
+ NULL\r
+ );\r
+ ShellCommandLineFreeVarList (ParamPackage);\r
+\r
+ return ShellStatus;\r
+}\r
+\r
+/**\r
+ This is the shell command "setfdt" help handler function. This\r
+ function returns the formatted help for the "setfdt" command.\r
+ The format matchs that in Appendix B of the revision 2.1 of the\r
+ UEFI Shell Specification.\r
+\r
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.\r
+ @param[in] Language The pointer to the language string to use.\r
+\r
+ @return CHAR16* Pool allocated help string, must be freed by caller.\r
+**/\r
+STATIC\r
+CHAR16*\r
+EFIAPI\r
+ShellDynCmdSetFdtGetHelp (\r
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,\r
+ IN CONST CHAR8 *Language\r
+ )\r
+{\r
+ //\r
+ // This allocates memory. The caller has to free the allocated memory.\r
+ //\r
+ return HiiGetString (\r
+ mFdtPlatformDxeHiiHandle,\r
+ STRING_TOKEN (STR_GET_HELP_SETFDT),\r
+ Language\r
+ );\r
+}\r
+\r
+/**\r
+ Update the text device path stored in the "Fdt" UEFI variable given\r
+ an EFI Shell file path or a text device path.\r
+\r
+ This function is a subroutine of the ShellDynCmdSetFdtHandler() function\r
+ to make its code easier to read.\r
+\r
+ @param[in] Shell The instance of the shell protocol used in the\r
+ context of processing the "setfdt" command.\r
+ @param[in] FilePath EFI Shell path or the device path to the FDT file.\r
+\r
+ @return SHELL_SUCCESS The text device path was succesfully updated.\r
+ @return SHELL_INVALID_PARAMETER The Shell file path is not valid.\r
+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r
+ @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted.\r
+ @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation.\r
+ @return SHELL_NOT_FOUND Device path to text protocol not found.\r
+ @return SHELL_ABORTED Operation aborted.\r
+\r
+**/\r
+STATIC\r
+SHELL_STATUS\r
+UpdateFdtTextDevicePath (\r
+ IN EFI_SHELL_PROTOCOL *Shell,\r
+ IN CONST CHAR16 *FilePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH *DevicePath;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *EfiDevicePathToTextProtocol;\r
+ CHAR16 *TextDevicePath;\r
+ CHAR16 *FdtVariableValue;\r
+ EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
+ SHELL_STATUS ShellStatus;\r
+\r
+ ASSERT (FilePath != NULL);\r
+ TextDevicePath = NULL;\r
+ FdtVariableValue = NULL;\r
+\r
+ DevicePath = Shell->GetDevicePathFromFilePath (FilePath);\r
+ if (DevicePath != NULL) {\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **)&EfiDevicePathToTextProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText (\r
+ DevicePath,\r
+ FALSE,\r
+ FALSE\r
+ );\r
+ if (TextDevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ FdtVariableValue = TextDevicePath;\r
+ } else {\r
+ //\r
+ // Try to convert back the EFI Device Path String into a EFI device Path\r
+ // to ensure the format is valid\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathFromTextProtocolGuid,\r
+ NULL,\r
+ (VOID **)&EfiDevicePathFromTextProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (\r
+ FilePath\r
+ );\r
+ if (DevicePath == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Error;\r
+ }\r
+ FdtVariableValue = (CHAR16*)FilePath;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ (CHAR16*)L"Fdt",\r
+ &gFdtVariableGuid,\r
+ EFI_VARIABLE_RUNTIME_ACCESS |\r
+ EFI_VARIABLE_NON_VOLATILE |\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS ,\r
+ StrSize (FdtVariableValue),\r
+ FdtVariableValue\r
+ );\r
+\r
+Error:\r
+ ShellStatus = EfiCodeToShellCode (Status);\r
+ if (!EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED),\r
+ mFdtPlatformDxeHiiHandle,\r
+ FdtVariableValue\r
+ );\r
+ } else {\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_INVALID_PATH),\r
+ mFdtPlatformDxeHiiHandle,\r
+ FilePath\r
+ );\r
+ } else {\r
+ ShellPrintHiiEx (\r
+ -1, -1, NULL,\r
+ STRING_TOKEN (STR_SETFDT_ERROR),\r
+ mFdtPlatformDxeHiiHandle,\r
+ Status\r
+ );\r
+ }\r
+ }\r
+\r
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+ if (TextDevicePath != NULL) {\r
+ FreePool (TextDevicePath);\r
+ }\r
+\r
+ return ShellStatus;\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
+STATIC\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
+>>>>>>> 4ac4fed... EmbeddedPkg/FdtPlatformDxe: Fix typo issue\r