EmbeddedPkg/FdtPlatformDxe: Move 'setfdt' Shell command into a separate file

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
Reviewed-by: Ronald Cron <Ronald.Cron@arm.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17302 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
index 35a5fba..38f3100 100644
--- a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
+++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c
@@ -11,59 +11,18 @@
   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

 

 **/

-#include <Uefi.h>

 

-#include <Library/UefiLib.h>

-#include <Library/DebugLib.h>

-#include <Library/UefiBootServicesTableLib.h>

-#include <Library/UefiRuntimeServicesTableLib.h>

+#include "FdtPlatform.h"

+

 #include <Library/PcdLib.h>

 #include <Library/DevicePathLib.h>

-#include <Library/MemoryAllocationLib.h>

-#include <Library/HiiLib.h>

 #include <Library/BdsLib.h>

-#include <Library/ShellLib.h>

 

-#include <Protocol/DevicePathToText.h>

-#include <Protocol/DevicePathFromText.h>

 #include <Protocol/DevicePath.h>

-#include <Protocol/EfiShell.h>

-#include <Protocol/EfiShellDynamicCommand.h>

-

-#include <Guid/Fdt.h>

 

 #include <libfdt.h>

 

 //

-// Internal types

-//

-

-STATIC SHELL_STATUS EFIAPI ShellDynCmdSetFdtHandler (

-  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

-  IN EFI_SYSTEM_TABLE                    *SystemTable,

-  IN EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters,

-  IN EFI_SHELL_PROTOCOL                  *Shell

-  );

-

-STATIC CHAR16* EFIAPI ShellDynCmdSetFdtGetHelp (

-  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

-  IN CONST CHAR8                         *Language

-  );

-

-STATIC VOID DisplayFdtDevicePaths (

-  VOID

-  );

-

-STATIC SHELL_STATUS UpdateFdtTextDevicePath (

-  IN EFI_SHELL_PROTOCOL  *Shell,

-  IN CONST CHAR16        *FilePath

-  );

-

-STATIC SHELL_STATUS EfiCodeToShellCode (

-  IN EFI_STATUS  Status

-  );

-

-//

 // Internal variables

 //

 

@@ -77,12 +36,8 @@
                          0x8afa7610, 0x62b1, 0x46aa,

                          {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c}

                          };

-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {

-  {L"-i", TypeFlag },

-  {NULL , TypeMax  }

-};

 

-STATIC EFI_HANDLE  mFdtPlatformDxeHiiHandle;

+EFI_HANDLE mFdtPlatformDxeHiiHandle;

 

 /**

   Install the FDT specified by its device path in text form.

@@ -225,7 +180,7 @@
     // Register the strings for the user interface in the HII Database.

     // This shows the way to the multi-language support, even if

     // only the English language is actually supported. The strings to register

-    // are stored in the "FdtPlatformDxeStrings[]" array. This array is

+    // are stored in the "ShellSetFdtStrings[]" array. This array is

     // built by the building process from the "*.uni" file associated to

     // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build

     // folder under your package's DEBUG folder and you will find the array

@@ -285,7 +240,6 @@
   @retval  EFI_OUT_OF_RESOURCES   An allocation failed.

 

 **/

-STATIC

 EFI_STATUS

 RunFdtInstallation (

   OUT CHAR16  **SuccessfullDevicePath

@@ -421,457 +375,6 @@
 }

 

 /**

-  This is the shell command "setfdt" handler function. This function handles

-  the command when it is invoked in the shell.

-

-  @param[in]  This             The instance of the

-                               EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

-  @param[in]  SystemTable      The pointer to the UEFI system table.

-  @param[in]  ShellParameters  The parameters associated with the command.

-  @param[in]  Shell            The instance of the shell protocol used in the

-                               context of processing this command.

-

-  @return  SHELL_SUCCESS            The operation was successful.

-  @return  SHELL_ABORTED            Operation aborted due to internal error.

-  @return  SHELL_INVALID_PARAMETER  The parameters of the command are not valid.

-  @return  SHELL_INVALID_PARAMETER  The EFI Shell file path is not valid.

-  @return  SHELL_NOT_FOUND          Failed to locate a protocol or a file.

-  @return  SHELL_UNSUPPORTED        Device path not supported.

-  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.

-  @return  SHELL_DEVICE_ERROR       The "Fdt" variable could not be saved due to a hardware failure.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable is read-only.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable cannot be deleted.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable could not be written due to security violation.

-

-**/

-STATIC

-SHELL_STATUS

-EFIAPI

-ShellDynCmdSetFdtHandler (

-  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

-  IN EFI_SYSTEM_TABLE                    *SystemTable,

-  IN EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters,

-  IN EFI_SHELL_PROTOCOL                  *Shell

-  )

-{

-  SHELL_STATUS  ShellStatus;

-  EFI_STATUS    Status;

-  LIST_ENTRY    *ParamPackage;

-  BOOLEAN       FilePath;

-  CONST CHAR16  *ValueStr;

-  CHAR16        *TextDevicePath;

-

-  ShellStatus  = SHELL_SUCCESS;

-  ParamPackage = NULL;

-  FilePath     = FALSE;

-

-  //

-  // Install the Shell and Shell Parameters Protocols on the driver

-  // image. This is necessary for the initialisation of the Shell

-  // Library to succeed in the next step.

-  //

-  Status = gBS->InstallMultipleProtocolInterfaces (

-                  &gImageHandle,

-                  &gEfiShellProtocolGuid, Shell,

-                  &gEfiShellParametersProtocolGuid, ShellParameters,

-                  NULL

-                  );

-  if (EFI_ERROR (Status)) {

-    return SHELL_ABORTED;

-  }

-

-  //

-  // Initialise the Shell Library as we are going to use it.

-  // Assert that the return code is EFI_SUCCESS as it should.

-  // To anticipate any change is the codes returned by

-  // ShellInitialize(), leave in case of error.

-  //

-  Status = ShellInitialize ();

-  if (EFI_ERROR (Status)) {

-    ASSERT_EFI_ERROR (Status);

-    return SHELL_ABORTED;

-  }

-

-  Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);

-  if (!EFI_ERROR (Status)) {

-    switch (ShellCommandLineGetCount (ParamPackage)) {

-    case 1:

-      //

-      // Case "setfdt" or "setfdt -i"

-      //

-      if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) {

-        DisplayFdtDevicePaths ();

-      }

-      break;

-

-    case 2:

-      //

-      // Case "setfdt file_path"    or

-      //      "setfdt -i file_path" or

-      //      "setfdt file_path -i"

-      //

-      FilePath = TRUE;

-      break;

-

-    default:

-      Status = EFI_INVALID_PARAMETER;

-    }

-  }

-  if (EFI_ERROR (Status)) {

-    ShellStatus = EfiCodeToShellCode (Status);

-    ShellPrintHiiEx (

-      -1, -1, NULL,

-      STRING_TOKEN (STR_SETFDT_ERROR),

-      mFdtPlatformDxeHiiHandle,

-      Status

-      );

-    goto Error;

-  }

-

-  //

-  // Update the preferred device path for the FDT if asked for.

-  //

-  if (FilePath) {

-    ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);

-    ShellPrintHiiEx (

-      -1, -1, NULL,

-      STRING_TOKEN (STR_SETFDT_UPDATING),

-      mFdtPlatformDxeHiiHandle

-      );

-    ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr);

-    if (ShellStatus != SHELL_SUCCESS) {

-      goto Error;

-    }

-  }

-

-  //

-  // Run the FDT installation process if asked for.

-  //

-  if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {

-    ShellPrintHiiEx (

-      -1, -1, NULL,

-      STRING_TOKEN (STR_SETFDT_INSTALLING),

-      mFdtPlatformDxeHiiHandle

-      );

-    Status = RunFdtInstallation (&TextDevicePath);

-    ShellStatus = EfiCodeToShellCode (Status);

-    if (!EFI_ERROR (Status)) {

-      ShellPrintHiiEx (

-        -1, -1, NULL,

-        STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED),

-        mFdtPlatformDxeHiiHandle,

-        TextDevicePath

-        );

-      FreePool (TextDevicePath);

-    } else {

-      if (Status == EFI_INVALID_PARAMETER) {

-        ShellPrintHiiEx (

-          -1, -1, NULL,

-          STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH),

-          mFdtPlatformDxeHiiHandle

-          );

-      } else {

-        ShellPrintHiiEx (

-          -1, -1, NULL,

-          STRING_TOKEN (STR_SETFDT_ERROR),

-          mFdtPlatformDxeHiiHandle,

-          Status

-          );

-      }

-      DisplayFdtDevicePaths ();

-    }

-  }

-

-Error:

-  gBS->UninstallMultipleProtocolInterfaces (

-         gImageHandle,

-         &gEfiShellProtocolGuid, Shell,

-         &gEfiShellParametersProtocolGuid, ShellParameters,

-         NULL

-         );

-  ShellCommandLineFreeVarList (ParamPackage);

-

-  return ShellStatus;

-}

-

-/**

-  This is the shell command "setfdt" help handler function. This

-  function returns the formatted help for the "setfdt" command.

-  The format matchs that in Appendix B of the revision 2.1 of the

-  UEFI Shell Specification.

-

-  @param[in]  This      The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

-  @param[in]  Language  The pointer to the language string to use.

-

-  @return  CHAR16*  Pool allocated help string, must be freed by caller.

-**/

-STATIC

-CHAR16*

-EFIAPI

-ShellDynCmdSetFdtGetHelp (

-  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

-  IN CONST CHAR8                         *Language

-  )

-{

-  //

-  // This allocates memory. The caller has to free the allocated memory.

-  //

-  return HiiGetString (

-                mFdtPlatformDxeHiiHandle,

-                STRING_TOKEN (STR_GET_HELP_SETFDT),

-                Language

-                );

-}

-

-/**

-  Display FDT device paths.

-

-  Display in text form the device paths used to install the FDT from the

-  highest to the lowest priority.

-

-**/

-STATIC

-VOID

-DisplayFdtDevicePaths (

-  VOID

-  )

-{

-  EFI_STATUS  Status;

-  UINTN       DataSize;

-  CHAR16      *TextDevicePath;

-  CHAR16      *TextDevicePaths;

-  CHAR16      *TextDevicePathSeparator;

-

-  ShellPrintHiiEx (

-    -1, -1, NULL,

-    STRING_TOKEN (STR_SETFDT_DEVICE_PATH_LIST),

-    mFdtPlatformDxeHiiHandle

-    );

-

-  if (FeaturePcdGet (PcdOverridePlatformFdt)) {

-    DataSize = 0;

-    Status = gRT->GetVariable (

-                    L"Fdt",

-                    &gFdtVariableGuid,

-                    NULL,

-                    &DataSize,

-                    NULL

-                    );

-

-    //

-    // Keep going only if the "Fdt" variable is defined.

-    //

-

-    if (Status == EFI_BUFFER_TOO_SMALL) {

-      TextDevicePath = AllocatePool (DataSize);

-      if (TextDevicePath == NULL) {

-        return;

-      }

-

-      Status = gRT->GetVariable (

-                      L"Fdt",

-                      &gFdtVariableGuid,

-                      NULL,

-                      &DataSize,

-                      TextDevicePath

-                      );

-      if (!EFI_ERROR (Status)) {

-        ShellPrintHiiEx (

-          -1, -1, NULL,

-          STRING_TOKEN (STR_SETFDT_DEVICE_PATH),

-          mFdtPlatformDxeHiiHandle,

-          TextDevicePath

-          );

-      }

-

-      FreePool (TextDevicePath);

-    }

-  }

-

-  //

-  // Loop over the device path list provided by "PcdFdtDevicePaths". The device

-  // paths are in text form and separated by a semi-colon.

-  //

-

-  TextDevicePaths = AllocateCopyPool (

-                      StrSize ((CHAR16*)PcdGetPtr (PcdFdtDevicePaths)),

-                      (CHAR16*)PcdGetPtr (PcdFdtDevicePaths)

-                      );

-  if (TextDevicePaths == NULL) {

-    return;

-  }

-

-  for (TextDevicePath = TextDevicePaths;

-       *TextDevicePath != L'\0'        ; ) {

-    TextDevicePathSeparator = StrStr (TextDevicePath, L";");

-

-    if (TextDevicePathSeparator != NULL) {

-      *TextDevicePathSeparator = L'\0';

-    }

-

-    ShellPrintHiiEx (

-      -1, -1, NULL,

-      STRING_TOKEN (STR_SETFDT_DEVICE_PATH),

-      mFdtPlatformDxeHiiHandle,

-      TextDevicePath

-      );

-

-    if (TextDevicePathSeparator == NULL) {

-      break;

-    }

-    TextDevicePath = TextDevicePathSeparator + 1;

-  }

-

-  FreePool (TextDevicePaths);

-

-}

-

-/**

-  Update the text device path stored in the "Fdt" UEFI variable given

-  an EFI Shell file path or a text device path.

-

-  This function is a subroutine of the ShellDynCmdSetFdtHandler() function

-  to make its code easier to read.

-

-  @param[in]  Shell          The instance of the shell protocol used in the

-                             context of processing the "setfdt" command.

-  @param[in]  FilePath       EFI Shell path or the device path to the FDT file.

-

-  @return  SHELL_SUCCESS            The text device path was succesfully updated.

-  @return  SHELL_INVALID_PARAMETER  The Shell file path is not valid.

-  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.

-  @return  SHELL_DEVICE_ERROR       The "Fdt" variable could not be saved due to a hardware failure.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable is read-only.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable cannot be deleted.

-  @return  SHELL_ACCESS_DENIED      The "Fdt" variable could not be written due to security violation.

-  @return  SHELL_NOT_FOUND          Device path to text protocol not found.

-  @return  SHELL_ABORTED            Operation aborted.

-

-**/

-STATIC

-SHELL_STATUS

-UpdateFdtTextDevicePath (

-  IN EFI_SHELL_PROTOCOL  *Shell,

-  IN CONST CHAR16        *FilePath

-  )

-{

-  EFI_STATUS                          Status;

-  EFI_DEVICE_PATH                     *DevicePath;

-  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL    *EfiDevicePathToTextProtocol;

-  CHAR16                              *TextDevicePath;

-  CHAR16                              *FdtVariableValue;

-  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *EfiDevicePathFromTextProtocol;

-  SHELL_STATUS                        ShellStatus;

-

-  ASSERT (FilePath != NULL);

-  DevicePath       = NULL;

-  TextDevicePath   = NULL;

-  FdtVariableValue = NULL;

-

-  if (*FilePath != L'\0') {

-    DevicePath = Shell->GetDevicePathFromFilePath (FilePath);

-    if (DevicePath != NULL) {

-      Status = gBS->LocateProtocol (

-                      &gEfiDevicePathToTextProtocolGuid,

-                      NULL,

-                      (VOID **)&EfiDevicePathToTextProtocol

-                      );

-      if (EFI_ERROR (Status)) {

-        goto Error;

-      }

-

-      TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText (

-                                                      DevicePath,

-                                                      FALSE,

-                                                      FALSE

-                                                      );

-      if (TextDevicePath == NULL) {

-        Status = EFI_OUT_OF_RESOURCES;

-        goto Error;

-      }

-      FdtVariableValue = TextDevicePath;

-    } else {

-      //

-      // Try to convert back the EFI Device Path String into a EFI device Path

-      // to ensure the format is valid

-      //

-      Status = gBS->LocateProtocol (

-                      &gEfiDevicePathFromTextProtocolGuid,

-                      NULL,

-                      (VOID **)&EfiDevicePathFromTextProtocol

-                      );

-      if (EFI_ERROR (Status)) {

-        goto Error;

-      }

-

-      DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (

-                                                    FilePath

-                                                    );

-      if (DevicePath == NULL) {

-        Status = EFI_INVALID_PARAMETER;

-        goto Error;

-      }

-      FdtVariableValue = (CHAR16*)FilePath;

-    }

-  }

-

-  Status = gRT->SetVariable (

-                  (CHAR16*)L"Fdt",

-                  &gFdtVariableGuid,

-                  EFI_VARIABLE_RUNTIME_ACCESS    |

-                  EFI_VARIABLE_NON_VOLATILE      |

-                  EFI_VARIABLE_BOOTSERVICE_ACCESS ,

-                  (FdtVariableValue != NULL) ?

-                  StrSize (FdtVariableValue) : 0,

-                  FdtVariableValue

-                  );

-

-Error:

-  ShellStatus = EfiCodeToShellCode (Status);

-  if (!EFI_ERROR (Status)) {

-    if (FdtVariableValue != NULL) {

-      ShellPrintHiiEx (

-        -1, -1, NULL,

-        STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED),

-        mFdtPlatformDxeHiiHandle,

-        FdtVariableValue

-        );

-    } else {

-      ShellPrintHiiEx (

-        -1, -1, NULL,

-        STRING_TOKEN (STR_SETFDT_UPDATE_DELETED),

-        mFdtPlatformDxeHiiHandle

-        );

-    }

-  } else {

-    if (Status == EFI_INVALID_PARAMETER) {

-      ShellPrintHiiEx (

-        -1, -1, NULL,

-        STRING_TOKEN (STR_SETFDT_INVALID_PATH),

-        mFdtPlatformDxeHiiHandle,

-        FilePath

-        );

-    } else {

-      ShellPrintHiiEx (

-        -1, -1, NULL,

-        STRING_TOKEN (STR_SETFDT_ERROR),

-        mFdtPlatformDxeHiiHandle,

-        Status

-        );

-    }

-  }

-

-  if (DevicePath != NULL) {

-    FreePool (DevicePath);

-  }

-  if (TextDevicePath != NULL) {

-    FreePool (TextDevicePath);

-  }

-

-  return ShellStatus;

-}

-

-/**

   Transcode one of the EFI return code used by the model into an EFI Shell return code.

 

   @param[in]  Status  EFI return code.

@@ -879,7 +382,6 @@
   @return  Transcoded EFI Shell return code.

 

 **/

-STATIC

 SHELL_STATUS

 EfiCodeToShellCode (

   IN EFI_STATUS  Status

diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.h b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.h
new file mode 100644
index 0000000..297927a
--- /dev/null
+++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.h
@@ -0,0 +1,130 @@
+/** @file

+

+  Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#ifndef __FDT_PLATFORM_DXE_H__

+#define __FDT_PLATFORM_DXE_H__

+

+#include <Uefi.h>

+

+#include <Protocol/DevicePathToText.h>

+#include <Protocol/DevicePathFromText.h>

+#include <Protocol/EfiShell.h>

+#include <Protocol/EfiShellDynamicCommand.h>

+

+#include <Library/DebugLib.h>

+#include <Library/HiiLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/ShellLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+

+#include <Guid/Fdt.h>

+

+#include <libfdt.h>

+

+extern EFI_HANDLE mFdtPlatformDxeHiiHandle;

+

+/**

+  Transcode one of the EFI return code used by the model into an EFI Shell return code.

+

+  @param[in]  Status  EFI return code.

+

+  @return  Transcoded EFI Shell return code.

+

+**/

+SHELL_STATUS

+EfiCodeToShellCode (

+  IN EFI_STATUS  Status

+  );

+

+/**

+  Run the FDT installation process.

+

+  Loop in priority order over the device paths from which the FDT has

+  been asked to be retrieved for. For each device path, try to install

+  the FDT. Stop as soon as an installation succeeds.

+

+  @param[in]  SuccessfullDevicePath  If not NULL, address where to store the

+                                     pointer to the text device path from

+                                     which the FDT was successfully retrieved.

+                                     Not used if the FDT installation failed.

+                                     The returned address is the address of

+                                     an allocated buffer that has to be

+                                     freed by the caller.

+

+  @retval  EFI_SUCCESS            The FDT was installed.

+  @retval  EFI_NOT_FOUND          Failed to locate a protocol or a file.

+  @retval  EFI_INVALID_PARAMETER  Invalid device path.

+  @retval  EFI_UNSUPPORTED        Device path not supported.

+  @retval  EFI_OUT_OF_RESOURCES   An allocation failed.

+

+**/

+EFI_STATUS

+RunFdtInstallation (

+  OUT CHAR16  **SuccessfullDevicePath

+  );

+

+/**

+  This is the shell command "setfdt" handler function. This function handles

+  the command when it is invoked in the shell.

+

+  @param[in]  This             The instance of the

+                               EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+  @param[in]  SystemTable      The pointer to the UEFI system table.

+  @param[in]  ShellParameters  The parameters associated with the command.

+  @param[in]  Shell            The instance of the shell protocol used in the

+                               context of processing this command.

+

+  @return  SHELL_SUCCESS            The operation was successful.

+  @return  SHELL_ABORTED            Operation aborted due to internal error.

+  @return  SHELL_INVALID_PARAMETER  The parameters of the command are not valid.

+  @return  SHELL_INVALID_PARAMETER  The EFI Shell file path is not valid.

+  @return  SHELL_NOT_FOUND          Failed to locate a protocol or a file.

+  @return  SHELL_UNSUPPORTED        Device path not supported.

+  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.

+  @return  SHELL_DEVICE_ERROR       The "Fdt" variable could not be saved due to a hardware failure.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable is read-only.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable cannot be deleted.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable could not be written due to security violation.

+

+**/

+SHELL_STATUS

+EFIAPI

+ShellDynCmdSetFdtHandler (

+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

+  IN EFI_SYSTEM_TABLE                    *SystemTable,

+  IN EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters,

+  IN EFI_SHELL_PROTOCOL                  *Shell

+  );

+

+/**

+  This is the shell command "setfdt" help handler function. This

+  function returns the formatted help for the "setfdt" command.

+  The format matchs that in Appendix B of the revision 2.1 of the

+  UEFI Shell Specification.

+

+  @param[in]  This      The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+  @param[in]  Language  The pointer to the language string to use.

+

+  @return  CHAR16*  Pool allocated help string, must be freed by caller.

+**/

+CHAR16*

+EFIAPI

+ShellDynCmdSetFdtGetHelp (

+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

+  IN CONST CHAR8                         *Language

+  );

+

+#endif /* __FDT_PLATFORM_DXE_H__ */

diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf
index 64d14a2..3558958 100644
--- a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf
+++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf
@@ -24,6 +24,7 @@
 [Sources.common]

   FdtPlatform.c

   FdtPlatformDxe.uni

+  ShellSetFdt.c

 

 [Packages]

   EmbeddedPkg/EmbeddedPkg.dec

diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c b/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c
new file mode 100644
index 0000000..9be23c8
--- /dev/null
+++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c
@@ -0,0 +1,468 @@
+/** @file

+

+  Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "FdtPlatform.h"

+

+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {

+  {L"-i", TypeFlag },

+  {NULL , TypeMax  }

+};

+

+/**

+  Display FDT device paths.

+

+  Display in text form the device paths used to install the FDT from the

+  highest to the lowest priority.

+

+**/

+STATIC

+VOID

+DisplayFdtDevicePaths (

+  VOID

+  )

+{

+  EFI_STATUS  Status;

+  UINTN       DataSize;

+  CHAR16      *TextDevicePath;

+  CHAR16      *TextDevicePaths;

+  CHAR16      *TextDevicePathSeparator;

+

+  ShellPrintHiiEx (

+    -1, -1, NULL,

+    STRING_TOKEN (STR_SETFDT_DEVICE_PATH_LIST),

+    mFdtPlatformDxeHiiHandle

+    );

+

+  if (FeaturePcdGet (PcdOverridePlatformFdt)) {

+    DataSize = 0;

+    Status = gRT->GetVariable (

+                    L"Fdt",

+                    &gFdtVariableGuid,

+                    NULL,

+                    &DataSize,

+                    NULL

+                    );

+

+    //

+    // Keep going only if the "Fdt" variable is defined.

+    //

+

+    if (Status == EFI_BUFFER_TOO_SMALL) {

+      TextDevicePath = AllocatePool (DataSize);

+      if (TextDevicePath == NULL) {

+        return;

+      }

+

+      Status = gRT->GetVariable (

+                      L"Fdt",

+                      &gFdtVariableGuid,

+                      NULL,

+                      &DataSize,

+                      TextDevicePath

+                      );

+      if (!EFI_ERROR (Status)) {

+        ShellPrintHiiEx (

+          -1, -1, NULL,

+          STRING_TOKEN (STR_SETFDT_DEVICE_PATH),

+          mFdtPlatformDxeHiiHandle,

+          TextDevicePath

+          );

+      }

+

+      FreePool (TextDevicePath);

+    }

+  }

+

+  //

+  // Loop over the device path list provided by "PcdFdtDevicePaths". The device

+  // paths are in text form and separated by a semi-colon.

+  //

+

+  TextDevicePaths = AllocateCopyPool (

+                      StrSize ((CHAR16*)PcdGetPtr (PcdFdtDevicePaths)),

+                      (CHAR16*)PcdGetPtr (PcdFdtDevicePaths)

+                      );

+  if (TextDevicePaths == NULL) {

+    return;

+  }

+

+  for (TextDevicePath = TextDevicePaths;

+       *TextDevicePath != L'\0'        ; ) {

+    TextDevicePathSeparator = StrStr (TextDevicePath, L";");

+

+    if (TextDevicePathSeparator != NULL) {

+      *TextDevicePathSeparator = L'\0';

+    }

+

+    ShellPrintHiiEx (

+      -1, -1, NULL,

+      STRING_TOKEN (STR_SETFDT_DEVICE_PATH),

+      mFdtPlatformDxeHiiHandle,

+      TextDevicePath

+      );

+

+    if (TextDevicePathSeparator == NULL) {

+      break;

+    }

+    TextDevicePath = TextDevicePathSeparator + 1;

+  }

+

+  FreePool (TextDevicePaths);

+}

+

+/**

+  Update the text device path stored in the "Fdt" UEFI variable given

+  an EFI Shell file path or a text device path.

+

+  This function is a subroutine of the ShellDynCmdSetFdtHandler() function

+  to make its code easier to read.

+

+  @param[in]  Shell          The instance of the shell protocol used in the

+                             context of processing the "setfdt" command.

+  @param[in]  FilePath       EFI Shell path or the device path to the FDT file.

+

+  @return  SHELL_SUCCESS            The text device path was succesfully updated.

+  @return  SHELL_INVALID_PARAMETER  The Shell file path is not valid.

+  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.

+  @return  SHELL_DEVICE_ERROR       The "Fdt" variable could not be saved due to a hardware failure.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable is read-only.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable cannot be deleted.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable could not be written due to security violation.

+  @return  SHELL_NOT_FOUND          Device path to text protocol not found.

+  @return  SHELL_ABORTED            Operation aborted.

+

+**/

+STATIC

+SHELL_STATUS

+UpdateFdtTextDevicePath (

+  IN EFI_SHELL_PROTOCOL  *Shell,

+  IN CONST CHAR16        *FilePath

+  )

+{

+  EFI_STATUS                          Status;

+  EFI_DEVICE_PATH                     *DevicePath;

+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL    *EfiDevicePathToTextProtocol;

+  CHAR16                              *TextDevicePath;

+  CHAR16                              *FdtVariableValue;

+  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL  *EfiDevicePathFromTextProtocol;

+  SHELL_STATUS                        ShellStatus;

+

+  ASSERT (FilePath != NULL);

+  DevicePath       = NULL;

+  TextDevicePath   = NULL;

+  FdtVariableValue = NULL;

+

+  if (*FilePath != L'\0') {

+    DevicePath = Shell->GetDevicePathFromFilePath (FilePath);

+    if (DevicePath != NULL) {

+      Status = gBS->LocateProtocol (

+                      &gEfiDevicePathToTextProtocolGuid,

+                      NULL,

+                      (VOID **)&EfiDevicePathToTextProtocol

+                      );

+      if (EFI_ERROR (Status)) {

+        goto Error;

+      }

+

+      TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText (

+                                                      DevicePath,

+                                                      FALSE,

+                                                      FALSE

+                                                      );

+      if (TextDevicePath == NULL) {

+        Status = EFI_OUT_OF_RESOURCES;

+        goto Error;

+      }

+      FdtVariableValue = TextDevicePath;

+    } else {

+      //

+      // Try to convert back the EFI Device Path String into a EFI device Path

+      // to ensure the format is valid

+      //

+      Status = gBS->LocateProtocol (

+                      &gEfiDevicePathFromTextProtocolGuid,

+                      NULL,

+                      (VOID **)&EfiDevicePathFromTextProtocol

+                      );

+      if (EFI_ERROR (Status)) {

+        goto Error;

+      }

+

+      DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (

+                                                    FilePath

+                                                    );

+      if (DevicePath == NULL) {

+        Status = EFI_INVALID_PARAMETER;

+        goto Error;

+      }

+      FdtVariableValue = (CHAR16*)FilePath;

+    }

+  }

+

+  Status = gRT->SetVariable (

+                  (CHAR16*)L"Fdt",

+                  &gFdtVariableGuid,

+                  EFI_VARIABLE_RUNTIME_ACCESS    |

+                  EFI_VARIABLE_NON_VOLATILE      |

+                  EFI_VARIABLE_BOOTSERVICE_ACCESS ,

+                  (FdtVariableValue != NULL) ?

+                  StrSize (FdtVariableValue) : 0,

+                  FdtVariableValue

+                  );

+

+Error:

+  ShellStatus = EfiCodeToShellCode (Status);

+  if (!EFI_ERROR (Status)) {

+    if (FdtVariableValue != NULL) {

+      ShellPrintHiiEx (

+        -1, -1, NULL,

+        STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED),

+        mFdtPlatformDxeHiiHandle,

+        FdtVariableValue

+        );

+    } else {

+      ShellPrintHiiEx (

+        -1, -1, NULL,

+        STRING_TOKEN (STR_SETFDT_UPDATE_DELETED),

+        mFdtPlatformDxeHiiHandle

+        );

+    }

+  } else {

+    if (Status == EFI_INVALID_PARAMETER) {

+      ShellPrintHiiEx (

+        -1, -1, NULL,

+        STRING_TOKEN (STR_SETFDT_INVALID_PATH),

+        mFdtPlatformDxeHiiHandle,

+        FilePath

+        );

+    } else {

+      ShellPrintHiiEx (

+        -1, -1, NULL,

+        STRING_TOKEN (STR_SETFDT_ERROR),

+        mFdtPlatformDxeHiiHandle,

+        Status

+        );

+    }

+  }

+

+  if (DevicePath != NULL) {

+    FreePool (DevicePath);

+  }

+  if (TextDevicePath != NULL) {

+    FreePool (TextDevicePath);

+  }

+

+  return ShellStatus;

+}

+

+/**

+  This is the shell command "setfdt" handler function. This function handles

+  the command when it is invoked in the shell.

+

+  @param[in]  This             The instance of the

+                               EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+  @param[in]  SystemTable      The pointer to the UEFI system table.

+  @param[in]  ShellParameters  The parameters associated with the command.

+  @param[in]  Shell            The instance of the shell protocol used in the

+                               context of processing this command.

+

+  @return  SHELL_SUCCESS            The operation was successful.

+  @return  SHELL_ABORTED            Operation aborted due to internal error.

+  @return  SHELL_INVALID_PARAMETER  The parameters of the command are not valid.

+  @return  SHELL_INVALID_PARAMETER  The EFI Shell file path is not valid.

+  @return  SHELL_NOT_FOUND          Failed to locate a protocol or a file.

+  @return  SHELL_UNSUPPORTED        Device path not supported.

+  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.

+  @return  SHELL_DEVICE_ERROR       The "Fdt" variable could not be saved due to a hardware failure.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable is read-only.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable cannot be deleted.

+  @return  SHELL_ACCESS_DENIED      The "Fdt" variable could not be written due to security violation.

+

+**/

+SHELL_STATUS

+EFIAPI

+ShellDynCmdSetFdtHandler (

+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

+  IN EFI_SYSTEM_TABLE                    *SystemTable,

+  IN EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters,

+  IN EFI_SHELL_PROTOCOL                  *Shell

+  )

+{

+  SHELL_STATUS  ShellStatus;

+  EFI_STATUS    Status;

+  LIST_ENTRY    *ParamPackage;

+  BOOLEAN       FilePath;

+  CONST CHAR16  *ValueStr;

+  CHAR16        *TextDevicePath;

+

+  ShellStatus  = SHELL_SUCCESS;

+  ParamPackage = NULL;

+  FilePath     = FALSE;

+

+  //

+  // Install the Shell and Shell Parameters Protocols on the driver

+  // image. This is necessary for the initialisation of the Shell

+  // Library to succeed in the next step.

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &gImageHandle,

+                  &gEfiShellProtocolGuid, Shell,

+                  &gEfiShellParametersProtocolGuid, ShellParameters,

+                  NULL

+                  );

+  if (EFI_ERROR (Status)) {

+    return SHELL_ABORTED;

+  }

+

+  //

+  // Initialise the Shell Library as we are going to use it.

+  // Assert that the return code is EFI_SUCCESS as it should.

+  // To anticipate any change is the codes returned by

+  // ShellInitialize(), leave in case of error.

+  //

+  Status = ShellInitialize ();

+  if (EFI_ERROR (Status)) {

+    ASSERT_EFI_ERROR (Status);

+    return SHELL_ABORTED;

+  }

+

+  Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);

+  if (!EFI_ERROR (Status)) {

+    switch (ShellCommandLineGetCount (ParamPackage)) {

+    case 1:

+      //

+      // Case "setfdt" or "setfdt -i"

+      //

+      if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) {

+        DisplayFdtDevicePaths ();

+      }

+      break;

+

+    case 2:

+      //

+      // Case "setfdt file_path"    or

+      //      "setfdt -i file_path" or

+      //      "setfdt file_path -i"

+      //

+      FilePath = TRUE;

+      break;

+

+    default:

+      Status = EFI_INVALID_PARAMETER;

+    }

+  }

+  if (EFI_ERROR (Status)) {

+    ShellStatus = EfiCodeToShellCode (Status);

+    ShellPrintHiiEx (

+      -1, -1, NULL,

+      STRING_TOKEN (STR_SETFDT_ERROR),

+      mFdtPlatformDxeHiiHandle,

+      Status

+      );

+    goto Error;

+  }

+

+  //

+  // Update the preferred device path for the FDT if asked for.

+  //

+  if (FilePath) {

+    ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);

+    ShellPrintHiiEx (

+      -1, -1, NULL,

+      STRING_TOKEN (STR_SETFDT_UPDATING),

+      mFdtPlatformDxeHiiHandle

+      );

+    ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr);

+    if (ShellStatus != SHELL_SUCCESS) {

+      goto Error;

+    }

+  }

+

+  //

+  // Run the FDT installation process if asked for.

+  //

+  if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {

+    ShellPrintHiiEx (

+      -1, -1, NULL,

+      STRING_TOKEN (STR_SETFDT_INSTALLING),

+      mFdtPlatformDxeHiiHandle

+      );

+    Status = RunFdtInstallation (&TextDevicePath);

+    ShellStatus = EfiCodeToShellCode (Status);

+    if (!EFI_ERROR (Status)) {

+      ShellPrintHiiEx (

+        -1, -1, NULL,

+        STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED),

+        mFdtPlatformDxeHiiHandle,

+        TextDevicePath

+        );

+      FreePool (TextDevicePath);

+    } else {

+      if (Status == EFI_INVALID_PARAMETER) {

+        ShellPrintHiiEx (

+          -1, -1, NULL,

+          STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH),

+          mFdtPlatformDxeHiiHandle

+          );

+      } else {

+        ShellPrintHiiEx (

+          -1, -1, NULL,

+          STRING_TOKEN (STR_SETFDT_ERROR),

+          mFdtPlatformDxeHiiHandle,

+          Status

+          );

+      }

+      DisplayFdtDevicePaths ();

+    }

+  }

+

+Error:

+  gBS->UninstallMultipleProtocolInterfaces (

+         gImageHandle,

+         &gEfiShellProtocolGuid, Shell,

+         &gEfiShellParametersProtocolGuid, ShellParameters,

+         NULL

+         );

+  ShellCommandLineFreeVarList (ParamPackage);

+

+  return ShellStatus;

+}

+

+/**

+  This is the shell command "setfdt" help handler function. This

+  function returns the formatted help for the "setfdt" command.

+  The format matchs that in Appendix B of the revision 2.1 of the

+  UEFI Shell Specification.

+

+  @param[in]  This      The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+  @param[in]  Language  The pointer to the language string to use.

+

+  @return  CHAR16*  Pool allocated help string, must be freed by caller.

+**/

+CHAR16*

+EFIAPI

+ShellDynCmdSetFdtGetHelp (

+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,

+  IN CONST CHAR8                         *Language

+  )

+{

+  //

+  // This allocates memory. The caller has to free the allocated memory.

+  //

+  return HiiGetString (

+                mFdtPlatformDxeHiiHandle,

+                STRING_TOKEN (STR_GET_HELP_SETFDT),

+                Language

+                );

+}