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

View File

@ -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__ */

View File

@ -24,6 +24,7 @@
[Sources.common]
FdtPlatform.c
FdtPlatformDxe.uni
ShellSetFdt.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec

View File

@ -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
);
}