From 3d7f1060859b69ef0c33d699fa9d8e9f2a383241 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 5 May 2015 15:27:41 +0000 Subject: [PATCH] EmbeddedPkg/FdtPlatformDxe: Move 'setfdt' Shell command into a separate file Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin Reviewed-by: Ronald Cron git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17302 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Drivers/FdtPlatformDxe/FdtPlatform.c | 506 +----------------- .../Drivers/FdtPlatformDxe/FdtPlatform.h | 130 +++++ .../Drivers/FdtPlatformDxe/FdtPlatformDxe.inf | 1 + .../Drivers/FdtPlatformDxe/ShellSetFdt.c | 468 ++++++++++++++++ 4 files changed, 603 insertions(+), 502 deletions(-) create mode 100644 EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.h create mode 100644 EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c diff --git a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c index 35a5fbacc2..38f31005f3 100644 --- a/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c +++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.c @@ -11,58 +11,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#include -#include -#include -#include -#include +#include "FdtPlatform.h" + #include #include -#include -#include #include -#include -#include -#include #include -#include -#include - -#include #include -// -// 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 @@ STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid = { 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 @@ FdtPlatformEntryPoint ( // 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 @@ FdtPlatformEntryPoint ( @retval EFI_OUT_OF_RESOURCES An allocation failed. **/ -STATIC EFI_STATUS RunFdtInstallation ( OUT CHAR16 **SuccessfullDevicePath @@ -420,457 +374,6 @@ Done: return EFI_SUCCESS; } -/** - 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. @@ -879,7 +382,6 @@ Error: @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 0000000000..297927aaac --- /dev/null +++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatform.h @@ -0,0 +1,130 @@ +/** @file + + Copyright (c) 2015, ARM Ltd. All rights reserved.
+ + 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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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 64d14a26e7..3558958f84 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 0000000000..9be23c8455 --- /dev/null +++ b/EmbeddedPkg/Drivers/FdtPlatformDxe/ShellSetFdt.c @@ -0,0 +1,468 @@ +/** @file + + Copyright (c) 2015, ARM Ltd. All rights reserved.
+ + 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 + ); +} -- 2.39.2