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
This commit is contained in:
Olivier Martin
2015-05-05 15:27:41 +00:00
committed by oliviermartin
parent 016740256a
commit 3d7f106085
4 changed files with 603 additions and 502 deletions

View File

@@ -11,58 +11,17 @@
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 @@ 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