summaryrefslogtreecommitdiffstats
path: root/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c')
-rw-r--r--EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c b/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c
new file mode 100644
index 0000000000..9be23c8455
--- /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
+ );
+}