]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
EmbeddedPkg : Add FdtPlatformDxe driver
[mirror_edk2.git] / EmbeddedPkg / Drivers / FdtPlatformDxe / FdtPlatform.c
diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
new file mode 100644 (file)
index 0000000..8608fcf
--- /dev/null
@@ -0,0 +1,742 @@
+/** @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