diff options
Diffstat (limited to 'ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c')
| -rw-r--r-- | ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c | 3942 |
1 files changed, 1971 insertions, 1971 deletions
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c index 0b94d9f5a1..80e9799077 100644 --- a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c +++ b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c @@ -1,1971 +1,1971 @@ -/** @file
- Main file for BCFG command.
-
- (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Uefi.h>
-
-#include <Guid/GlobalVariable.h>
-#include <Guid/ShellLibHiiGuid.h>
-
-#include <Protocol/Shell.h>
-#include <Protocol/ShellParameters.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/UnicodeCollation.h>
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PcdLib.h>
-#include <Library/ShellCommandLib.h>
-#include <Library/ShellLib.h>
-#include <Library/SortLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/HiiLib.h>
-#include <Library/FileHandleLib.h>
-#include <Library/PrintLib.h>
-#include <Library/HandleParsingLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/UefiBootManagerLib.h>
-
-STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
-STATIC EFI_HII_HANDLE gShellBcfgHiiHandle = NULL;
-
-typedef enum {
- BcfgTargetBootOrder = 0,
- BcfgTargetDriverOrder = 1,
- BcfgTargetMax = 2
-} BCFG_OPERATION_TARGET;
-
-typedef enum {
- BcfgTypeDump = 0,
- BcfgTypeAdd = 1,
- BcfgTypeAddp = 2,
- BcfgTypeAddh = 3,
- BcfgTypeRm = 4,
- BcfgTypeMv = 5,
- BcfgTypeOpt = 6,
- BcfgTypeMod = 7,
- BcfgTypeModf = 8,
- BcfgTypeModp = 9,
- BcfgTypeModh = 10,
- BcfgTypeMax = 11
-} BCFG_OPERATION_TYPE;
-
-typedef struct {
- BCFG_OPERATION_TARGET Target;
- BCFG_OPERATION_TYPE Type;
- UINT16 Number1;
- UINT16 Number2;
- UINTN HandleIndex;
- CHAR16 *FileName;
- CHAR16 *Description;
- UINT16 *Order;
- CONST CHAR16 *OptData;
-} BGFG_OPERATION;
-
-/**
- Update the optional data for a boot or driver option.
-
- If optional data exists it will be changed.
-
- @param[in] Index The boot or driver option index update.
- @param[in] DataSize The size in bytes of Data.
- @param[in] Data The buffer for the optional data.
- @param[in] Target The target of the operation.
-
- @retval EFI_SUCCESS The data was successfully updated.
- @retval other A error occurred.
-**/
-EFI_STATUS
-UpdateOptionalData (
- UINT16 Index,
- UINTN DataSize,
- UINT8 *Data,
- IN CONST BCFG_OPERATION_TARGET Target
- )
-{
- EFI_STATUS Status;
- CHAR16 VariableName[12];
- UINTN OriginalSize;
- UINT8 *OriginalData;
- UINTN NewSize;
- UINT8 *NewData;
- UINTN OriginalOptionDataSize;
-
- UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", Index);
-
- OriginalSize = 0;
- OriginalData = NULL;
- NewData = NULL;
- NewSize = 0;
-
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &OriginalSize,
- OriginalData
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- OriginalData = AllocateZeroPool (OriginalSize);
- if (OriginalData == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
-
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &OriginalSize,
- OriginalData
- );
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // Allocate new struct and discard old optional data.
- //
- ASSERT (OriginalData != NULL);
- OriginalOptionDataSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (((CHAR16 *)(OriginalData + sizeof (UINT32) + sizeof (UINT16))));
- OriginalOptionDataSize += (*(UINT16 *)(OriginalData + sizeof (UINT32)));
- OriginalOptionDataSize -= OriginalSize;
- NewSize = OriginalSize - OriginalOptionDataSize + DataSize;
- NewData = AllocatePool (NewSize);
- if (NewData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize);
- CopyMem (NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);
- }
- }
-
- if (!EFI_ERROR (Status)) {
- //
- // put the data back under the variable
- //
- Status = gRT->SetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- NewSize,
- NewData
- );
- }
-
- SHELL_FREE_NON_NULL (OriginalData);
- SHELL_FREE_NON_NULL (NewData);
- return (Status);
-}
-
-/**
- This function will get a CRC for a boot option.
-
- @param[in, out] Crc The CRC value to return.
- @param[in] BootIndex The boot option index to CRC.
-
- @retval EFI_SUCCESS The CRC was successfully returned.
- @retval other A error occurred.
-**/
-EFI_STATUS
-GetBootOptionCrc (
- UINT32 *Crc,
- UINT16 BootIndex
- )
-{
- CHAR16 VariableName[12];
- EFI_STATUS Status;
- UINT8 *Buffer;
- UINTN BufferSize;
-
- Buffer = NULL;
- BufferSize = 0;
-
- //
- // Get the data Buffer
- //
- UnicodeSPrint (VariableName, sizeof (VariableName), L"%Boot%04x", BootIndex);
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &BufferSize,
- NULL
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- Buffer = AllocateZeroPool (BufferSize);
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &BufferSize,
- Buffer
- );
- }
-
- //
- // Get the CRC computed
- //
- if (!EFI_ERROR (Status)) {
- Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);
- }
-
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_SUCCESS;
-}
-
-/**
- This function will populate the device path protocol parameter based on TheHandle.
-
- @param[in] TheHandle Driver handle.
- @param[in, out] FilePath On a successful return the device path to the handle.
-
- @retval EFI_SUCCESS The device path was successfully returned.
- @retval other A error from gBS->HandleProtocol.
-
- @sa HandleProtocol
-**/
-EFI_STATUS
-GetDevicePathForDriverHandle (
- IN EFI_HANDLE TheHandle,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
- )
-{
- EFI_STATUS Status;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
-
- Status = gBS->OpenProtocol (
- TheHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->OpenProtocol (
- LoadedImage->DeviceHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&ImageDevicePath,
- gImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- // *DevPath = DuplicateDevicePath (ImageDevicePath);
- // *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
- *FilePath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
- gBS->CloseProtocol (
- LoadedImage->DeviceHandle,
- &gEfiDevicePathProtocolGuid,
- gImageHandle,
- NULL
- );
- }
-
- gBS->CloseProtocol (
- TheHandle,
- &gEfiLoadedImageProtocolGuid,
- gImageHandle,
- NULL
- );
- }
-
- return (Status);
-}
-
-/**
- Function to get Device Path by a handle.
-
- @param[in] TheHandle Use it to get DevicePath.
- @param[in] Target Boot option target.
- @param[in, out] DevicePath On a successful return the device path to the handle.
-
- @retval SHELL_INVALID_PARAMETER The handle was NULL.
- @retval SHELL_NOT_FOUND Not found device path by handle.
- @retval SHELL_SUCCESS Get device path successfully.
-**/
-SHELL_STATUS
-GetDevicePathByHandle (
- IN EFI_HANDLE TheHandle,
- IN BCFG_OPERATION_TARGET Target,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
- )
-{
- EFI_STATUS Status;
- SHELL_STATUS ShellStatus;
-
- UINTN DriverBindingHandleCount;
- UINTN ParentControllerHandleCount;
- UINTN ChildControllerHandleCount;
-
- ShellStatus = SHELL_SUCCESS;
-
- if (TheHandle == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
- return SHELL_INVALID_PARAMETER;
- }
-
- Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL);
- if (EFI_ERROR (Status)) {
- DriverBindingHandleCount = 0;
- }
-
- Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL);
- if (EFI_ERROR (Status)) {
- ParentControllerHandleCount = 0;
- }
-
- Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL);
- if (EFI_ERROR (Status)) {
- ChildControllerHandleCount = 0;
- }
-
- Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID **)DevicePath);
-
- if ((DriverBindingHandleCount > 0) ||
- (ParentControllerHandleCount > 0) ||
- (ChildControllerHandleCount > 0) ||
- !EFI_ERROR (Status)
- )
- {
- //
- // The handle points to a real controller which has a device path.
- //
- if (Target == BcfgTargetDriverOrder) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_PARAM_INV),
- gShellBcfgHiiHandle,
- L"bcfg",
- L"Handle should point to driver image."
- );
- ShellStatus = SHELL_NOT_FOUND;
- }
- } else {
- //
- // The handle points to a driver image.
- //
- if (Target == BcfgTargetBootOrder) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_PARAM_INV),
- gShellBcfgHiiHandle,
- L"bcfg",
- L"Handle should point to controller."
- );
- ShellStatus = SHELL_NOT_FOUND;
- } else {
- if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) {
- ShellStatus = SHELL_NOT_FOUND;
- }
- }
- }
-
- return (ShellStatus);
-}
-
-/**
- Function to modify an option.
-
- @param[in] BcfgOperation Pointer to BCFG operation.
- @param[in] OrderCount The number if items in CurrentOrder.
-
- @retval SHELL_SUCCESS The operation was successful.
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
- @retval SHELL_OUT_OF_RESOUCES A memory allocation failed.
-**/
-SHELL_STATUS
-BcfgMod (
- IN CONST BGFG_OPERATION *BcfgOperation,
- IN CONST UINTN OrderCount
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE CurHandle;
- SHELL_STATUS ShellStatus;
- CHAR16 OptionStr[40];
- EFI_SHELL_FILE_INFO *FileList;
- EFI_SHELL_FILE_INFO *Arg;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker;
- EFI_BOOT_MANAGER_LOAD_OPTION LoadOption;
-
- ShellStatus = SHELL_SUCCESS;
- FileList = NULL;
- DevicePath = NULL;
- DevicePathBuffer = NULL;
-
- ZeroMem (&LoadOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
-
- if (((BcfgOperation->Type == BcfgTypeMod) && (BcfgOperation->Description == NULL)) ||
- ((BcfgOperation->Type == BcfgTypeModf) && (BcfgOperation->FileName == NULL)) ||
- ((BcfgOperation->Type == BcfgTypeModp) && (BcfgOperation->FileName == NULL)) ||
- ((BcfgOperation->Type == BcfgTypeModh) && (BcfgOperation->HandleIndex == 0)) ||
- (BcfgOperation->Number1 > OrderCount)
- )
- {
- return (SHELL_INVALID_PARAMETER);
- }
-
- if (BcfgOperation->Type == BcfgTypeModh) {
- CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex);
- ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer);
- if (ShellStatus == SHELL_SUCCESS) {
- DevicePath = DuplicateDevicePath (DevicePathBuffer);
- }
- } else if ((BcfgOperation->Type == BcfgTypeModf) || (BcfgOperation->Type == BcfgTypeModp)) {
- //
- // Get Device Path by FileName.
- //
- ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList);
- if (FileList == NULL) {
- //
- // The name of file matched nothing.
- //
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
- //
- // If the name of file expanded to multiple names, it's fail.
- //
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
- if (EFI_ERROR (Arg->Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
- if (DevicePathBuffer == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
- ShellStatus = SHELL_UNSUPPORTED;
- }
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- if (BcfgOperation->Type == BcfgTypeModp) {
- ShellStatus = SHELL_INVALID_PARAMETER;
- DevicePathWalker = DevicePathBuffer;
- while (!IsDevicePathEnd (DevicePathWalker)) {
- if ((DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP)
- )
- {
- //
- // We found the portion of device path starting with the hard driver partition.
- //
- ShellStatus = SHELL_SUCCESS;
- DevicePath = DuplicateDevicePath (DevicePathWalker);
- break;
- } else {
- DevicePathWalker = NextDevicePathNode (DevicePathWalker);
- }
- }
- } else {
- DevicePath = DuplicateDevicePath (DevicePathBuffer);
- }
-
- FreePool (DevicePathBuffer);
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- if (BcfgOperation->Target == BcfgTargetBootOrder) {
- UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]);
- } else {
- UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]);
- }
-
- Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle);
- ShellStatus = SHELL_NOT_FOUND;
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- if (BcfgOperation->Type == BcfgTypeMod) {
- SHELL_FREE_NON_NULL (LoadOption.Description);
- LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description);
- } else {
- SHELL_FREE_NON_NULL (LoadOption.FilePath);
- LoadOption.FilePath = DuplicateDevicePath (DevicePath);
- }
-
- Status = EfiBootManagerLoadOptionToVariable (&LoadOption);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
-
- EfiBootManagerFreeLoadOption (&LoadOption);
-
- if (DevicePath != NULL) {
- FreePool (DevicePath);
- }
-
- if (FileList != NULL) {
- ShellCloseFileMetaArg (&FileList);
- }
-
- return (ShellStatus);
-}
-
-/**
- Function to add a option.
-
- @param[in] Position The position to add Target at.
- @param[in] File The file to make the target.
- @param[in] Desc The description text.
- @param[in] CurrentOrder The pointer to the current order of items.
- @param[in] OrderCount The number if items in CurrentOrder.
- @param[in] Target The info on the option to add.
- @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
- @param[in] UsePath TRUE to convert to devicepath.
- @param[in] HandleNumber The handle number to add.
-
- @retval SHELL_SUCCESS The operation was successful.
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
-**/
-SHELL_STATUS
-BcfgAdd (
- IN UINTN Position,
- IN CONST CHAR16 *File,
- IN CONST CHAR16 *Desc,
- IN CONST UINT16 *CurrentOrder,
- IN CONST UINTN OrderCount,
- IN CONST BCFG_OPERATION_TARGET Target,
- IN CONST BOOLEAN UseHandle,
- IN CONST BOOLEAN UsePath,
- IN CONST UINTN HandleNumber
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevPath;
- EFI_DEVICE_PATH_PROTOCOL *FilePath;
- CHAR16 *Str;
- UINT8 *TempByteBuffer;
- UINT8 *TempByteStart;
- EFI_SHELL_FILE_INFO *Arg;
- EFI_SHELL_FILE_INFO *FileList;
- CHAR16 OptionStr[40];
- UINTN DescSize, FilePathSize;
- BOOLEAN Found;
- UINTN TargetLocation;
- UINTN Index;
- EFI_HANDLE *Handles;
- EFI_HANDLE CurHandle;
- UINTN DriverBindingHandleCount;
- UINTN ParentControllerHandleCount;
- UINTN ChildControllerHandleCount;
- SHELL_STATUS ShellStatus;
- UINT16 *NewOrder;
-
- if (!UseHandle) {
- if ((File == NULL) || (Desc == NULL)) {
- return (SHELL_INVALID_PARAMETER);
- }
- } else {
- if (HandleNumber == 0) {
- return (SHELL_INVALID_PARAMETER);
- }
- }
-
- if (Position > OrderCount) {
- Position = OrderCount;
- }
-
- Str = NULL;
- FilePath = NULL;
- FileList = NULL;
- Handles = NULL;
- ShellStatus = SHELL_SUCCESS;
- TargetLocation = 0xFFFF;
-
- if (UseHandle) {
- CurHandle = ConvertHandleIndexToHandle (HandleNumber);
- if (CurHandle == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- if (Target == BcfgTargetBootOrder) {
- //
- // Make sure that the handle should point to a real controller
- //
- Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
- CurHandle,
- &DriverBindingHandleCount,
- NULL
- );
-
- Status = PARSE_HANDLE_DATABASE_PARENTS (
- CurHandle,
- &ParentControllerHandleCount,
- NULL
- );
-
- Status = ParseHandleDatabaseForChildControllers (
- CurHandle,
- &ChildControllerHandleCount,
- NULL
- );
-
- if ( (DriverBindingHandleCount > 0)
- || (ParentControllerHandleCount > 0)
- || (ChildControllerHandleCount > 0))
- {
- FilePath = NULL;
- Status = gBS->HandleProtocol (
- CurHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&FilePath
- );
- }
-
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- } else {
- //
- // Make sure that the handle should point to driver, not a controller.
- //
- Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
- CurHandle,
- &DriverBindingHandleCount,
- NULL
- );
-
- Status = PARSE_HANDLE_DATABASE_PARENTS (
- CurHandle,
- &ParentControllerHandleCount,
- NULL
- );
-
- Status = ParseHandleDatabaseForChildControllers (
- CurHandle,
- &ChildControllerHandleCount,
- NULL
- );
-
- Status = gBS->HandleProtocol (
- CurHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&FilePath
- );
-
- if ( (DriverBindingHandleCount > 0)
- || (ParentControllerHandleCount > 0)
- || (ChildControllerHandleCount > 0)
- || !EFI_ERROR (Status))
- {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- //
- // Get the DevicePath from the loaded image information.
- //
- Status = GetDevicePathForDriverHandle (CurHandle, &FilePath);
- }
- }
- }
- } else {
- //
- // Get file info
- //
- ShellOpenFileMetaArg ((CHAR16 *)File, EFI_FILE_MODE_READ, &FileList);
-
- if (FileList == NULL) {
- //
- // If filename matched nothing fail
- //
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
- //
- // If filename expanded to multiple names, fail
- //
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link);
- if (EFI_ERROR (Arg->Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- //
- // Build FilePath to the filename
- //
-
- //
- // get the device path
- //
- DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName);
- if (DevicePath == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
- ShellStatus = SHELL_UNSUPPORTED;
- } else {
- if (UsePath) {
- DevPath = DevicePath;
- ShellStatus = SHELL_INVALID_PARAMETER;
- while (!IsDevicePathEnd (DevPath)) {
- if ((DevicePathType (DevPath) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (DevPath) == MEDIA_HARDDRIVE_DP))
- {
- //
- // If we find it use it instead
- //
- ShellStatus = SHELL_SUCCESS;
- FilePath = DuplicateDevicePath (DevPath);
- break;
- }
-
- DevPath = NextDevicePathNode (DevPath);
- }
- } else {
- FilePath = DuplicateDevicePath (DevicePath);
- }
-
- FreePool (DevicePath);
- }
- }
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- //
- // Find a free target ,a brute force implementation
- //
- Found = FALSE;
- for (TargetLocation = 0; TargetLocation < 0xFFFF; TargetLocation++) {
- Found = TRUE;
- for (Index = 0; Index < OrderCount; Index++) {
- if (CurrentOrder[Index] == TargetLocation) {
- Found = FALSE;
- break;
- }
- }
-
- if (Found) {
- break;
- }
- }
-
- if (TargetLocation == 0xFFFF) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg");
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- //
- // Add the option
- //
- DescSize = StrSize (Desc);
- FilePathSize = GetDevicePathSize (FilePath);
-
- TempByteBuffer = AllocateZeroPool (sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize);
- if (TempByteBuffer != NULL) {
- TempByteStart = TempByteBuffer;
- *((UINT32 *)TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
- TempByteBuffer += sizeof (UINT32);
-
- *((UINT16 *)TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
- TempByteBuffer += sizeof (UINT16);
-
- CopyMem (TempByteBuffer, Desc, DescSize);
- TempByteBuffer += DescSize;
- ASSERT (FilePath != NULL);
- CopyMem (TempByteBuffer, FilePath, FilePathSize);
-
- UnicodeSPrint (OptionStr, sizeof (OptionStr), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", TargetLocation);
- Status = gRT->SetVariable (
- OptionStr,
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize,
- TempByteStart
- );
-
- FreePool (TempByteStart);
- } else {
- Status = EFI_OUT_OF_RESOURCES;
- }
-
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
- } else {
- NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0]));
- if (NewOrder != NULL) {
- CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0]));
-
- //
- // Insert target into order list
- //
- for (Index = OrderCount; Index > Position; Index--) {
- NewOrder[Index] = NewOrder[Index - 1];
- }
-
- NewOrder[Position] = (UINT16)TargetLocation;
- Status = gRT->SetVariable (
- Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder",
- &gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- (OrderCount + 1) * sizeof (UINT16),
- NewOrder
- );
-
- FreePool (NewOrder);
-
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
- }
- }
- }
- }
-
- //
- // If always Free FilePath, will free devicepath in system when use "addh"
- //
- if ((FilePath != NULL) && !UseHandle) {
- FreePool (FilePath);
- }
-
- if (Str != NULL) {
- FreePool (Str);
- }
-
- if (Handles != NULL) {
- FreePool (Handles);
- }
-
- if (FileList != NULL) {
- ShellCloseFileMetaArg (&FileList);
- }
-
- return (ShellStatus);
-}
-
-/**
- Function to remove an item.
-
- @param[in] Target The target item to move.
- @param[in] CurrentOrder The pointer to the current order of items.
- @param[in] OrderCount The number if items in CurrentOrder.
- @param[in] Location The current location of the Target.
-
- @retval SHELL_SUCCESS The operation was successful.
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
-**/
-SHELL_STATUS
-BcfgRemove (
- IN CONST BCFG_OPERATION_TARGET Target,
- IN CONST UINT16 *CurrentOrder,
- IN CONST UINTN OrderCount,
- IN CONST UINT16 Location
- )
-{
- CHAR16 VariableName[12];
- UINT16 *NewOrder;
- EFI_STATUS Status;
- UINTN NewCount;
-
- UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", CurrentOrder[Location]);
- Status = gRT->SetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- 0,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
- return (SHELL_INVALID_PARAMETER);
- }
-
- NewOrder = AllocateZeroPool (OrderCount*sizeof (CurrentOrder[0]));
- if (NewOrder != NULL) {
- NewCount = OrderCount;
- CopyMem (NewOrder, CurrentOrder, OrderCount*sizeof (CurrentOrder[0]));
- CopyMem (NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof (CurrentOrder[0]));
- NewCount--;
-
- Status = gRT->SetVariable (
- Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- NewCount*sizeof (NewOrder[0]),
- NewOrder
- );
- FreePool (NewOrder);
- } else {
- Status = EFI_OUT_OF_RESOURCES;
- }
-
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder");
- return (SHELL_INVALID_PARAMETER);
- }
-
- return (SHELL_SUCCESS);
-}
-
-/**
- Function to move a item to another location.
-
- @param[in] Target The target item to move.
- @param[in] CurrentOrder The pointer to the current order of items.
- @param[in] OrderCount The number if items in CurrentOrder.
- @param[in] OldLocation The current location of the Target.
- @param[in] NewLocation The desired location of the Target.
-
- @retval SHELL_SUCCESS The operation was successful.
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
-**/
-SHELL_STATUS
-BcfgMove (
- IN CONST BCFG_OPERATION_TARGET Target,
- IN CONST UINT16 *CurrentOrder,
- IN CONST UINTN OrderCount,
- IN CONST UINT16 OldLocation,
- IN UINT16 NewLocation
- )
-{
- UINT16 *NewOrder;
- EFI_STATUS Status;
- UINT16 Temp;
-
- NewOrder = AllocateCopyPool (OrderCount*sizeof (CurrentOrder[0]), CurrentOrder);
- if (NewOrder == NULL) {
- return (SHELL_OUT_OF_RESOURCES);
- }
-
- //
- // correct the new location
- //
- if (NewLocation >= OrderCount) {
- if (OrderCount > 0) {
- NewLocation = (UINT16)OrderCount - 1;
- } else {
- NewLocation = 0;
- }
- }
-
- Temp = CurrentOrder[OldLocation];
- CopyMem (NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof (CurrentOrder[0]));
- CopyMem (NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof (CurrentOrder[0]));
- NewOrder[NewLocation] = Temp;
-
- Status = gRT->SetVariable (
- Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- OrderCount*sizeof (CurrentOrder[0]),
- NewOrder
- );
-
- FreePool (NewOrder);
-
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder");
- return (SHELL_INVALID_PARAMETER);
- }
-
- return (SHELL_SUCCESS);
-}
-
-/**
- Function to add optional data to an option.
-
- @param[in] OptData The optional data to add.
- @param[in] CurrentOrder The pointer to the current order of items.
- @param[in] OrderCount The number if items in CurrentOrder.
- @param[in] Target The target of the operation.
-
- @retval SHELL_SUCCESS The operation was succesful.
-**/
-SHELL_STATUS
-BcfgAddOpt (
- IN CONST CHAR16 *OptData,
- IN CONST UINT16 *CurrentOrder,
- IN CONST UINTN OrderCount,
- IN CONST BCFG_OPERATION_TARGET Target
- )
-{
- EFI_KEY_OPTION NewKeyOption;
- EFI_KEY_OPTION *KeyOptionBuffer;
- SHELL_STATUS ShellStatus;
- EFI_STATUS Status;
- UINT16 OptionIndex;
- UINT16 LoopCounter;
- UINT64 Intermediate;
- CONST CHAR16 *Temp;
- CONST CHAR16 *Walker;
- CHAR16 *FileName;
- CHAR16 *Temp2;
- CHAR16 *Data;
- UINT32 KeyIndex;
- CHAR16 VariableName[12];
- VOID *VariableData;
-
- SHELL_FILE_HANDLE FileHandle;
-
- Status = EFI_SUCCESS;
- ShellStatus = SHELL_SUCCESS;
- Walker = OptData;
- FileName = NULL;
- Data = NULL;
- KeyOptionBuffer = NULL;
- VariableData = NULL;
-
- ZeroMem (&NewKeyOption, sizeof (EFI_KEY_OPTION));
- ZeroMem (VariableName, sizeof (VariableName));
-
- while (Walker[0] == L' ') {
- Walker++;
- }
-
- //
- // Get the index of the variable we are changing.
- //
- Status = ShellConvertStringToUint64 (Walker, &Intermediate, TRUE, TRUE);
- if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL) || (((UINT16)Intermediate) > ((UINT16)OrderCount))) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
- ShellStatus = SHELL_INVALID_PARAMETER;
- return (ShellStatus);
- }
-
- OptionIndex = (UINT16)Intermediate;
-
- Temp = StrStr (Walker, L" ");
- if (Temp != NULL) {
- Walker = Temp;
- }
-
- while (Walker[0] == L' ') {
- Walker++;
- }
-
- //
- // determine whether we have file with data, quote delimited information, or a hot-key
- //
- if (Walker[0] == L'\"') {
- //
- // quoted filename or quoted information.
- //
- Temp = StrStr (Walker+1, L"\"");
- if ((Temp == NULL) || (StrLen (Temp) != 1)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- FileName = StrnCatGrow (&FileName, NULL, Walker+1, 0);
- if (FileName == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- return (ShellStatus);
- }
-
- Temp2 = StrStr (FileName, L"\"");
- ASSERT (Temp2 != NULL);
- Temp2[0] = CHAR_NULL;
- Temp2++;
- if (StrLen (Temp2) > 0) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- if (EFI_ERROR (ShellFileExists (Walker))) {
- //
- // Not a file. must be misc information.
- //
- Data = FileName;
- FileName = NULL;
- } else {
- FileName = StrnCatGrow (&FileName, NULL, Walker, 0);
- }
- }
- } else {
- //
- // filename or hot key information.
- //
- if (StrStr (Walker, L" ") == NULL) {
- //
- // filename
- //
- if (EFI_ERROR (ShellFileExists (Walker))) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- FileName = StrnCatGrow (&FileName, NULL, Walker, 0);
- }
- } else {
- if (Target != BcfgTargetBootOrder) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- //
- // Get hot key information
- //
- Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
- if (EFI_ERROR (Status) || (((UINT32)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
- Temp = StrStr (Walker, L" ");
- if (Temp != NULL) {
- Walker = Temp;
- }
-
- while (Walker[0] == L' ') {
- Walker++;
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- //
- // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
- // Re-allocate with the added information.
- //
- KeyOptionBuffer = AllocatePool (sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount));
- if (KeyOptionBuffer == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- return ShellStatus;
- }
-
- CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof (EFI_KEY_OPTION));
- }
-
- for (LoopCounter = 0; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {
- //
- // ScanCode
- //
- Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
- if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
- Temp = StrStr (Walker, L" ");
- if (Temp != NULL) {
- Walker = Temp;
- }
-
- while (Walker[0] == L' ') {
- Walker++;
- }
-
- //
- // UnicodeChar
- //
- Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE);
- if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
- Temp = StrStr (Walker, L" ");
- if (Temp != NULL) {
- Walker = Temp;
- }
-
- while (Walker[0] == L' ') {
- Walker++;
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- //
- // Now do the BootOption / BootOptionCrc
- //
- ASSERT (OptionIndex <= OrderCount);
- KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
- Status = GetBootOptionCrc (&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
-
- if (ShellStatus == SHELL_SUCCESS) {
- for (Temp2 = NULL, KeyIndex = 0; KeyIndex <= 0xFFFF; KeyIndex++) {
- UnicodeSPrint (VariableName, sizeof (VariableName), L"Key%04x", KeyIndex);
- Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL);
- if (Status == EFI_NOT_FOUND) {
- break;
- }
-
- if (!EFI_ERROR (Status)) {
- SHELL_FREE_NON_NULL (VariableData);
- }
- }
-
- if (KeyIndex <= 0xFFFF) {
- Status = gRT->SetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
- sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),
- KeyOptionBuffer
- );
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- ASSERT (FileName == NULL && Data == NULL);
- }
- }
- }
-
- //
- // Shouldn't be possible to have have both. Neither is ok though.
- //
- ASSERT (FileName == NULL || Data == NULL);
-
- if ((ShellStatus == SHELL_SUCCESS) && ((FileName != NULL) || (Data != NULL))) {
- if (FileName != NULL) {
- //
- // Open the file and populate the data buffer.
- //
- Status = ShellOpenFileByName (
- FileName,
- &FileHandle,
- EFI_FILE_MODE_READ,
- 0
- );
- if (!EFI_ERROR (Status)) {
- Status = ShellGetFileSize (FileHandle, &Intermediate);
- }
-
- Data = AllocateZeroPool ((UINTN)Intermediate);
- if (Data == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- }
-
- if (!EFI_ERROR (Status)) {
- Status = ShellReadFile (FileHandle, (UINTN *)&Intermediate, Data);
- }
- } else {
- Intermediate = StrSize (Data);
- }
-
- if (!EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS) && (Data != NULL)) {
- Status = UpdateOptionalData (CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8 *)Data, Target);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
-
- if (EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
-
- SHELL_FREE_NON_NULL (Data);
- SHELL_FREE_NON_NULL (KeyOptionBuffer);
- SHELL_FREE_NON_NULL (FileName);
- return ShellStatus;
-}
-
-/**
- Function to dump the Bcfg information.
-
- @param[in] Op The operation.
- @param[in] OrderCount How many to dump.
- @param[in] CurrentOrder The pointer to the current order of items.
- @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
-
- @retval SHELL_SUCCESS The dump was successful.
- @retval SHELL_INVALID_PARAMETER A parameter was invalid.
-**/
-SHELL_STATUS
-BcfgDisplayDump (
- IN CONST CHAR16 *Op,
- IN CONST UINTN OrderCount,
- IN CONST UINT16 *CurrentOrder,
- IN CONST BOOLEAN VerboseOutput
- )
-{
- EFI_STATUS Status;
- UINT8 *Buffer;
- UINTN BufferSize;
- CHAR16 VariableName[12];
- UINTN LoopVar;
- CHAR16 *DevPathString;
- VOID *FilePathList;
- UINTN Errors;
- EFI_LOAD_OPTION *LoadOption;
- CHAR16 *Description;
- UINTN DescriptionSize;
- UINTN OptionalDataOffset;
-
- if (OrderCount == 0) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg");
- return (SHELL_SUCCESS);
- }
-
- Errors = 0;
-
- for (LoopVar = 0; LoopVar < OrderCount; LoopVar++) {
- Buffer = NULL;
- BufferSize = 0;
- DevPathString = NULL;
-
- UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
-
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &BufferSize,
- Buffer
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- Buffer = AllocateZeroPool (BufferSize);
- Status = gRT->GetVariable (
- VariableName,
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &BufferSize,
- Buffer
- );
- }
-
- if (EFI_ERROR (Status) || (Buffer == NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
- ++Errors;
- goto Cleanup;
- }
-
- //
- // We expect the Attributes, FilePathListLength, and L'\0'-terminated
- // Description fields to be present.
- //
- if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_BCFG_VAR_CORRUPT),
- gShellBcfgHiiHandle,
- L"bcfg",
- VariableName
- );
- ++Errors;
- goto Cleanup;
- }
-
- LoadOption = (EFI_LOAD_OPTION *)Buffer;
- Description = (CHAR16 *)(Buffer + sizeof (EFI_LOAD_OPTION));
- DescriptionSize = StrSize (Description);
-
- if (LoadOption->FilePathListLength != 0) {
- FilePathList = (UINT8 *)Description + DescriptionSize;
- DevPathString = ConvertDevicePathToText (FilePathList, TRUE, FALSE);
- }
-
- OptionalDataOffset = sizeof *LoadOption + DescriptionSize +
- LoadOption->FilePathListLength;
-
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_BCFG_LOAD_OPTIONS),
- gShellBcfgHiiHandle,
- LoopVar,
- VariableName,
- Description,
- DevPathString,
- OptionalDataOffset >= BufferSize ? L'N' : L'Y'
- );
- if (VerboseOutput && (OptionalDataOffset < BufferSize)) {
- DumpHex (
- 2, // Indent
- 0, // Offset (displayed)
- BufferSize - OptionalDataOffset, // DataSize
- Buffer + OptionalDataOffset // UserData
- );
- }
-
-Cleanup:
- if (Buffer != NULL) {
- FreePool (Buffer);
- }
-
- if (DevPathString != NULL) {
- FreePool (DevPathString);
- }
- }
-
- return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS;
-}
-
-/**
- Function to initialize the BCFG operation structure.
-
- @param[in] Struct The stuct to initialize.
-**/
-VOID
-InitBcfgStruct (
- IN BGFG_OPERATION *Struct
- )
-{
- ASSERT (Struct != NULL);
- Struct->Target = BcfgTargetMax;
- Struct->Type = BcfgTypeMax;
- Struct->Number1 = 0;
- Struct->Number2 = 0;
- Struct->HandleIndex = 0;
- Struct->FileName = NULL;
- Struct->Description = NULL;
- Struct->Order = NULL;
- Struct->OptData = NULL;
-}
-
-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
- { L"-v", TypeFlag },
- { L"-opt", TypeMaxValue },
- { NULL, TypeMax }
-};
-
-/**
- Function for 'bcfg' command.
-
- @param[in] ImageHandle Handle to the Image (NULL if Internal).
- @param[in] SystemTable Pointer to the System Table (NULL if Internal).
-**/
-SHELL_STATUS
-EFIAPI
-ShellCommandRunBcfg (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- LIST_ENTRY *Package;
- CHAR16 *ProblemParam;
- SHELL_STATUS ShellStatus;
- UINTN ParamNumber;
- CONST CHAR16 *CurrentParam;
- BGFG_OPERATION CurrentOperation;
- UINTN Length;
- UINT64 Intermediate;
- UINT16 Count;
-
- Length = 0;
- ProblemParam = NULL;
- Package = NULL;
- ShellStatus = SHELL_SUCCESS;
-
- InitBcfgStruct (&CurrentOperation);
-
- //
- // initialize the shell lib (we must be in non-auto-init...)
- //
- Status = ShellInitialize ();
- ASSERT_EFI_ERROR (Status);
-
- Status = CommandInit ();
- ASSERT_EFI_ERROR (Status);
-
- //
- // parse the command line
- //
- Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
- if (EFI_ERROR (Status)) {
- if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam);
- FreePool (ProblemParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (FALSE);
- }
- } else {
- //
- // Read in if we are doing -OPT
- //
- if (ShellCommandLineGetFlag (Package, L"-opt")) {
- CurrentOperation.OptData = ShellCommandLineGetValue (Package, L"-opt");
- if (CurrentOperation.OptData == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeOpt;
- }
-
- //
- // small block to read the target of the operation
- //
- if (((ShellCommandLineGetCount (Package) < 3) && (CurrentOperation.Type != BcfgTypeOpt)) ||
- ((ShellCommandLineGetCount (Package) < 2) && (CurrentOperation.Type == BcfgTypeOpt))
- )
- {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"driver") == 0) {
- CurrentOperation.Target = BcfgTargetDriverOrder;
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"boot") == 0) {
- CurrentOperation.Target = BcfgTargetBootOrder;
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- //
- // Read in the boot or driver order environment variable (not needed for opt)
- //
- if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) {
- Length = 0;
- Status = gRT->GetVariable (
- CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &Length,
- CurrentOperation.Order
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- CurrentOperation.Order = AllocateZeroPool (Length+(4*sizeof (CurrentOperation.Order[0])));
- if (CurrentOperation.Order == NULL) {
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- } else {
- Status = gRT->GetVariable (
- CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder",
- (EFI_GUID *)&gEfiGlobalVariableGuid,
- NULL,
- &Length,
- CurrentOperation.Order
- );
- }
- }
- }
-
- Count = (UINT16)(Length / sizeof (CurrentOperation.Order[0]));
-
- //
- // large block to read the type of operation and verify parameter types for the info.
- //
- if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) {
- for (ParamNumber = 2; ParamNumber < ShellCommandLineGetCount (Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
- CurrentParam = ShellCommandLineGetRawValue (Package, ParamNumber);
- if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"dump") == 0) {
- CurrentOperation.Type = BcfgTypeDump;
- if (ShellCommandLineGetCount (Package) > 3) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- } else if (ShellCommandLineGetFlag (Package, L"-v")) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"add") == 0) {
- if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeAdd;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- ASSERT (CurrentOperation.FileName == NULL);
- CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- ASSERT (CurrentOperation.Description == NULL);
- CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addp") == 0) {
- if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeAddp;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- ASSERT (CurrentOperation.FileName == NULL);
- CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- ASSERT (CurrentOperation.Description == NULL);
- CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addh") == 0) {
- if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeAddh;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.HandleIndex = (UINT16)Intermediate;
- ASSERT (CurrentOperation.Description == NULL);
- CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"rm") == 0) {
- if ((ParamNumber + 1) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeRm;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mv") == 0) {
- if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
-
- CurrentOperation.Type = BcfgTypeMv;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number2 = (UINT16)Intermediate;
- }
-
- if ( (CurrentOperation.Number2 == CurrentOperation.Number1)
- || (CurrentOperation.Number2 >= Count)
- )
- {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mod") == 0) {
- if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentOperation.Type = BcfgTypeMod;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (CurrentOperation.Description == NULL);
- CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modf") == 0) {
- if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentOperation.Type = BcfgTypeModf;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (CurrentOperation.FileName == NULL);
- CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modp") == 0) {
- if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentOperation.Type = BcfgTypeModp;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- ASSERT (CurrentOperation.FileName == NULL);
- CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0);
- }
- }
- }
- } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modh") == 0) {
- if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentOperation.Type = BcfgTypeModh;
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.Number1 = (UINT16)Intermediate;
- if (CurrentOperation.Number1 >= Count) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber);
- if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE);
- CurrentOperation.HandleIndex = (UINT16)Intermediate;
- }
- }
- }
- }
- } else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
- ShellStatus = SHELL_INVALID_PARAMETER;
- }
- }
- }
-
- if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax) && (CurrentOperation.Type < BcfgTypeMax)) {
- //
- // we have all the info. Do the work
- //
- switch (CurrentOperation.Type) {
- case BcfgTypeDump:
- ShellStatus = BcfgDisplayDump (
- CurrentOperation.Target == BcfgTargetBootOrder ? L"Boot" : L"Driver",
- Count,
- CurrentOperation.Order,
- ShellCommandLineGetFlag (Package, L"-v")
- );
- break;
- case BcfgTypeMv:
- ShellStatus = BcfgMove (
- CurrentOperation.Target,
- CurrentOperation.Order,
- Count,
- CurrentOperation.Number1,
- CurrentOperation.Number2
- );
- break;
- case BcfgTypeRm:
- ShellStatus = BcfgRemove (
- CurrentOperation.Target,
- CurrentOperation.Order,
- Count,
- CurrentOperation.Number1
- );
- break;
- case BcfgTypeAdd:
- case BcfgTypeAddp:
- case BcfgTypeAddh:
- ShellStatus = BcfgAdd (
- CurrentOperation.Number1,
- CurrentOperation.FileName,
- CurrentOperation.Description == NULL ? L"" : CurrentOperation.Description,
- CurrentOperation.Order,
- Count,
- CurrentOperation.Target,
- (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
- (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
- CurrentOperation.HandleIndex
- );
- break;
- case BcfgTypeMod:
- case BcfgTypeModf:
- case BcfgTypeModp:
- case BcfgTypeModh:
- ShellStatus = BcfgMod (&CurrentOperation, Count);
- break;
- case BcfgTypeOpt:
- ShellStatus = BcfgAddOpt (
- CurrentOperation.OptData,
- CurrentOperation.Order,
- Count,
- CurrentOperation.Target
- );
- break;
- default:
- ASSERT (FALSE);
- }
- }
- }
-
- if (Package != NULL) {
- ShellCommandLineFreeVarList (Package);
- }
-
- if (CurrentOperation.FileName != NULL) {
- FreePool (CurrentOperation.FileName);
- }
-
- if (CurrentOperation.Description != NULL) {
- FreePool (CurrentOperation.Description);
- }
-
- if (CurrentOperation.Order != NULL) {
- FreePool (CurrentOperation.Order);
- }
-
- return (ShellStatus);
-}
-
-/**
- Function to get the filename with help context if HII will not be used.
-
- @return The filename with help text in it.
-**/
-CONST CHAR16 *
-EFIAPI
-ShellCommandGetManFileNameBcfg (
- VOID
- )
-{
- return (mFileName);
-}
-
-/**
- "Constructor" for the library.
-
- This will register the handler for the bcfg command.
-
- @param[in] ImageHandle the image handle of the process
- @param[in] SystemTable the EFI System Table pointer
- @param[in] Name the profile name to use
-
- @retval EFI_SUCCESS the shell command handlers were installed successfully
- @retval EFI_UNSUPPORTED the shell level required was not found.
-**/
-EFI_STATUS
-EFIAPI
-BcfgLibraryRegisterBcfgCommand (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable,
- IN CONST CHAR16 *Name
- )
-{
- if (gShellBcfgHiiHandle != NULL) {
- return (EFI_SUCCESS);
- }
-
- gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);
- if (gShellBcfgHiiHandle == NULL) {
- return (EFI_DEVICE_ERROR);
- }
-
- //
- // install our shell command handler
- //
- ShellCommandRegisterCommandName (L"bcfg", ShellCommandRunBcfg, ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN (STR_GET_HELP_BCFG));
-
- return (EFI_SUCCESS);
-}
-
-/**
- Destructor for the library. free any resources.
-
- @param ImageHandle The image handle of the process.
- @param SystemTable The EFI System Table pointer.
-**/
-EFI_STATUS
-EFIAPI
-BcfgLibraryUnregisterBcfgCommand (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- if (gShellBcfgHiiHandle != NULL) {
- HiiRemovePackages (gShellBcfgHiiHandle);
- }
-
- gShellBcfgHiiHandle = NULL;
- return (EFI_SUCCESS);
-}
+/** @file + Main file for BCFG command. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR> + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi.h> + +#include <Guid/GlobalVariable.h> +#include <Guid/ShellLibHiiGuid.h> + +#include <Protocol/Shell.h> +#include <Protocol/ShellParameters.h> +#include <Protocol/DevicePath.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/UnicodeCollation.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/ShellCommandLib.h> +#include <Library/ShellLib.h> +#include <Library/SortLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/HiiLib.h> +#include <Library/FileHandleLib.h> +#include <Library/PrintLib.h> +#include <Library/HandleParsingLib.h> +#include <Library/DevicePathLib.h> +#include <Library/UefiBootManagerLib.h> + +STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; +STATIC EFI_HII_HANDLE gShellBcfgHiiHandle = NULL; + +typedef enum { + BcfgTargetBootOrder = 0, + BcfgTargetDriverOrder = 1, + BcfgTargetMax = 2 +} BCFG_OPERATION_TARGET; + +typedef enum { + BcfgTypeDump = 0, + BcfgTypeAdd = 1, + BcfgTypeAddp = 2, + BcfgTypeAddh = 3, + BcfgTypeRm = 4, + BcfgTypeMv = 5, + BcfgTypeOpt = 6, + BcfgTypeMod = 7, + BcfgTypeModf = 8, + BcfgTypeModp = 9, + BcfgTypeModh = 10, + BcfgTypeMax = 11 +} BCFG_OPERATION_TYPE; + +typedef struct { + BCFG_OPERATION_TARGET Target; + BCFG_OPERATION_TYPE Type; + UINT16 Number1; + UINT16 Number2; + UINTN HandleIndex; + CHAR16 *FileName; + CHAR16 *Description; + UINT16 *Order; + CONST CHAR16 *OptData; +} BGFG_OPERATION; + +/** + Update the optional data for a boot or driver option. + + If optional data exists it will be changed. + + @param[in] Index The boot or driver option index update. + @param[in] DataSize The size in bytes of Data. + @param[in] Data The buffer for the optional data. + @param[in] Target The target of the operation. + + @retval EFI_SUCCESS The data was successfully updated. + @retval other A error occurred. +**/ +EFI_STATUS +UpdateOptionalData ( + UINT16 Index, + UINTN DataSize, + UINT8 *Data, + IN CONST BCFG_OPERATION_TARGET Target + ) +{ + EFI_STATUS Status; + CHAR16 VariableName[12]; + UINTN OriginalSize; + UINT8 *OriginalData; + UINTN NewSize; + UINT8 *NewData; + UINTN OriginalOptionDataSize; + + UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", Index); + + OriginalSize = 0; + OriginalData = NULL; + NewData = NULL; + NewSize = 0; + + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &OriginalSize, + OriginalData + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + OriginalData = AllocateZeroPool (OriginalSize); + if (OriginalData == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &OriginalSize, + OriginalData + ); + } + + if (!EFI_ERROR (Status)) { + // + // Allocate new struct and discard old optional data. + // + ASSERT (OriginalData != NULL); + OriginalOptionDataSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (((CHAR16 *)(OriginalData + sizeof (UINT32) + sizeof (UINT16)))); + OriginalOptionDataSize += (*(UINT16 *)(OriginalData + sizeof (UINT32))); + OriginalOptionDataSize -= OriginalSize; + NewSize = OriginalSize - OriginalOptionDataSize + DataSize; + NewData = AllocatePool (NewSize); + if (NewData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize); + CopyMem (NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize); + } + } + + if (!EFI_ERROR (Status)) { + // + // put the data back under the variable + // + Status = gRT->SetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + NewSize, + NewData + ); + } + + SHELL_FREE_NON_NULL (OriginalData); + SHELL_FREE_NON_NULL (NewData); + return (Status); +} + +/** + This function will get a CRC for a boot option. + + @param[in, out] Crc The CRC value to return. + @param[in] BootIndex The boot option index to CRC. + + @retval EFI_SUCCESS The CRC was successfully returned. + @retval other A error occurred. +**/ +EFI_STATUS +GetBootOptionCrc ( + UINT32 *Crc, + UINT16 BootIndex + ) +{ + CHAR16 VariableName[12]; + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + + Buffer = NULL; + BufferSize = 0; + + // + // Get the data Buffer + // + UnicodeSPrint (VariableName, sizeof (VariableName), L"%Boot%04x", BootIndex); + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + NULL + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool (BufferSize); + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + } + + // + // Get the CRC computed + // + if (!EFI_ERROR (Status)) { + Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc); + } + + SHELL_FREE_NON_NULL (Buffer); + return EFI_SUCCESS; +} + +/** + This function will populate the device path protocol parameter based on TheHandle. + + @param[in] TheHandle Driver handle. + @param[in, out] FilePath On a successful return the device path to the handle. + + @retval EFI_SUCCESS The device path was successfully returned. + @retval other A error from gBS->HandleProtocol. + + @sa HandleProtocol +**/ +EFI_STATUS +GetDevicePathForDriverHandle ( + IN EFI_HANDLE TheHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&ImageDevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // *DevPath = DuplicateDevicePath (ImageDevicePath); + // *FilePath = DuplicateDevicePath (LoadedImage->FilePath); + *FilePath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath); + gBS->CloseProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + gImageHandle, + NULL + ); + } + + gBS->CloseProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + gImageHandle, + NULL + ); + } + + return (Status); +} + +/** + Function to get Device Path by a handle. + + @param[in] TheHandle Use it to get DevicePath. + @param[in] Target Boot option target. + @param[in, out] DevicePath On a successful return the device path to the handle. + + @retval SHELL_INVALID_PARAMETER The handle was NULL. + @retval SHELL_NOT_FOUND Not found device path by handle. + @retval SHELL_SUCCESS Get device path successfully. +**/ +SHELL_STATUS +GetDevicePathByHandle ( + IN EFI_HANDLE TheHandle, + IN BCFG_OPERATION_TARGET Target, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + + UINTN DriverBindingHandleCount; + UINTN ParentControllerHandleCount; + UINTN ChildControllerHandleCount; + + ShellStatus = SHELL_SUCCESS; + + if (TheHandle == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + return SHELL_INVALID_PARAMETER; + } + + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL); + if (EFI_ERROR (Status)) { + DriverBindingHandleCount = 0; + } + + Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL); + if (EFI_ERROR (Status)) { + ParentControllerHandleCount = 0; + } + + Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL); + if (EFI_ERROR (Status)) { + ChildControllerHandleCount = 0; + } + + Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID **)DevicePath); + + if ((DriverBindingHandleCount > 0) || + (ParentControllerHandleCount > 0) || + (ChildControllerHandleCount > 0) || + !EFI_ERROR (Status) + ) + { + // + // The handle points to a real controller which has a device path. + // + if (Target == BcfgTargetDriverOrder) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PARAM_INV), + gShellBcfgHiiHandle, + L"bcfg", + L"Handle should point to driver image." + ); + ShellStatus = SHELL_NOT_FOUND; + } + } else { + // + // The handle points to a driver image. + // + if (Target == BcfgTargetBootOrder) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PARAM_INV), + gShellBcfgHiiHandle, + L"bcfg", + L"Handle should point to controller." + ); + ShellStatus = SHELL_NOT_FOUND; + } else { + if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) { + ShellStatus = SHELL_NOT_FOUND; + } + } + } + + return (ShellStatus); +} + +/** + Function to modify an option. + + @param[in] BcfgOperation Pointer to BCFG operation. + @param[in] OrderCount The number if items in CurrentOrder. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_OUT_OF_RESOUCES A memory allocation failed. +**/ +SHELL_STATUS +BcfgMod ( + IN CONST BGFG_OPERATION *BcfgOperation, + IN CONST UINTN OrderCount + ) +{ + EFI_STATUS Status; + EFI_HANDLE CurHandle; + SHELL_STATUS ShellStatus; + CHAR16 OptionStr[40]; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Arg; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer; + EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker; + EFI_BOOT_MANAGER_LOAD_OPTION LoadOption; + + ShellStatus = SHELL_SUCCESS; + FileList = NULL; + DevicePath = NULL; + DevicePathBuffer = NULL; + + ZeroMem (&LoadOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); + + if (((BcfgOperation->Type == BcfgTypeMod) && (BcfgOperation->Description == NULL)) || + ((BcfgOperation->Type == BcfgTypeModf) && (BcfgOperation->FileName == NULL)) || + ((BcfgOperation->Type == BcfgTypeModp) && (BcfgOperation->FileName == NULL)) || + ((BcfgOperation->Type == BcfgTypeModh) && (BcfgOperation->HandleIndex == 0)) || + (BcfgOperation->Number1 > OrderCount) + ) + { + return (SHELL_INVALID_PARAMETER); + } + + if (BcfgOperation->Type == BcfgTypeModh) { + CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex); + ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer); + if (ShellStatus == SHELL_SUCCESS) { + DevicePath = DuplicateDevicePath (DevicePathBuffer); + } + } else if ((BcfgOperation->Type == BcfgTypeModf) || (BcfgOperation->Type == BcfgTypeModp)) { + // + // Get Device Path by FileName. + // + ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL) { + // + // The name of file matched nothing. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // If the name of file expanded to multiple names, it's fail. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link); + if (EFI_ERROR (Arg->Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName); + if (DevicePathBuffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Type == BcfgTypeModp) { + ShellStatus = SHELL_INVALID_PARAMETER; + DevicePathWalker = DevicePathBuffer; + while (!IsDevicePathEnd (DevicePathWalker)) { + if ((DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP) + ) + { + // + // We found the portion of device path starting with the hard driver partition. + // + ShellStatus = SHELL_SUCCESS; + DevicePath = DuplicateDevicePath (DevicePathWalker); + break; + } else { + DevicePathWalker = NextDevicePathNode (DevicePathWalker); + } + } + } else { + DevicePath = DuplicateDevicePath (DevicePathBuffer); + } + + FreePool (DevicePathBuffer); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Target == BcfgTargetBootOrder) { + UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]); + } else { + UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]); + } + + Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Type == BcfgTypeMod) { + SHELL_FREE_NON_NULL (LoadOption.Description); + LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description); + } else { + SHELL_FREE_NON_NULL (LoadOption.FilePath); + LoadOption.FilePath = DuplicateDevicePath (DevicePath); + } + + Status = EfiBootManagerLoadOptionToVariable (&LoadOption); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + EfiBootManagerFreeLoadOption (&LoadOption); + + if (DevicePath != NULL) { + FreePool (DevicePath); + } + + if (FileList != NULL) { + ShellCloseFileMetaArg (&FileList); + } + + return (ShellStatus); +} + +/** + Function to add a option. + + @param[in] Position The position to add Target at. + @param[in] File The file to make the target. + @param[in] Desc The description text. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Target The info on the option to add. + @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc. + @param[in] UsePath TRUE to convert to devicepath. + @param[in] HandleNumber The handle number to add. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgAdd ( + IN UINTN Position, + IN CONST CHAR16 *File, + IN CONST CHAR16 *Desc, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST BOOLEAN UseHandle, + IN CONST BOOLEAN UsePath, + IN CONST UINTN HandleNumber + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + CHAR16 *Str; + UINT8 *TempByteBuffer; + UINT8 *TempByteStart; + EFI_SHELL_FILE_INFO *Arg; + EFI_SHELL_FILE_INFO *FileList; + CHAR16 OptionStr[40]; + UINTN DescSize, FilePathSize; + BOOLEAN Found; + UINTN TargetLocation; + UINTN Index; + EFI_HANDLE *Handles; + EFI_HANDLE CurHandle; + UINTN DriverBindingHandleCount; + UINTN ParentControllerHandleCount; + UINTN ChildControllerHandleCount; + SHELL_STATUS ShellStatus; + UINT16 *NewOrder; + + if (!UseHandle) { + if ((File == NULL) || (Desc == NULL)) { + return (SHELL_INVALID_PARAMETER); + } + } else { + if (HandleNumber == 0) { + return (SHELL_INVALID_PARAMETER); + } + } + + if (Position > OrderCount) { + Position = OrderCount; + } + + Str = NULL; + FilePath = NULL; + FileList = NULL; + Handles = NULL; + ShellStatus = SHELL_SUCCESS; + TargetLocation = 0xFFFF; + + if (UseHandle) { + CurHandle = ConvertHandleIndexToHandle (HandleNumber); + if (CurHandle == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (Target == BcfgTargetBootOrder) { + // + // Make sure that the handle should point to a real controller + // + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + CurHandle, + &DriverBindingHandleCount, + NULL + ); + + Status = PARSE_HANDLE_DATABASE_PARENTS ( + CurHandle, + &ParentControllerHandleCount, + NULL + ); + + Status = ParseHandleDatabaseForChildControllers ( + CurHandle, + &ChildControllerHandleCount, + NULL + ); + + if ( (DriverBindingHandleCount > 0) + || (ParentControllerHandleCount > 0) + || (ChildControllerHandleCount > 0)) + { + FilePath = NULL; + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&FilePath + ); + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // Make sure that the handle should point to driver, not a controller. + // + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + CurHandle, + &DriverBindingHandleCount, + NULL + ); + + Status = PARSE_HANDLE_DATABASE_PARENTS ( + CurHandle, + &ParentControllerHandleCount, + NULL + ); + + Status = ParseHandleDatabaseForChildControllers ( + CurHandle, + &ChildControllerHandleCount, + NULL + ); + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&FilePath + ); + + if ( (DriverBindingHandleCount > 0) + || (ParentControllerHandleCount > 0) + || (ChildControllerHandleCount > 0) + || !EFI_ERROR (Status)) + { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Get the DevicePath from the loaded image information. + // + Status = GetDevicePathForDriverHandle (CurHandle, &FilePath); + } + } + } + } else { + // + // Get file info + // + ShellOpenFileMetaArg ((CHAR16 *)File, EFI_FILE_MODE_READ, &FileList); + + if (FileList == NULL) { + // + // If filename matched nothing fail + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // If filename expanded to multiple names, fail + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link); + if (EFI_ERROR (Arg->Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Build FilePath to the filename + // + + // + // get the device path + // + DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName); + if (DevicePath == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName); + ShellStatus = SHELL_UNSUPPORTED; + } else { + if (UsePath) { + DevPath = DevicePath; + ShellStatus = SHELL_INVALID_PARAMETER; + while (!IsDevicePathEnd (DevPath)) { + if ((DevicePathType (DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevPath) == MEDIA_HARDDRIVE_DP)) + { + // + // If we find it use it instead + // + ShellStatus = SHELL_SUCCESS; + FilePath = DuplicateDevicePath (DevPath); + break; + } + + DevPath = NextDevicePathNode (DevPath); + } + } else { + FilePath = DuplicateDevicePath (DevicePath); + } + + FreePool (DevicePath); + } + } + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Find a free target ,a brute force implementation + // + Found = FALSE; + for (TargetLocation = 0; TargetLocation < 0xFFFF; TargetLocation++) { + Found = TRUE; + for (Index = 0; Index < OrderCount; Index++) { + if (CurrentOrder[Index] == TargetLocation) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + + if (TargetLocation == 0xFFFF) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg"); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Add the option + // + DescSize = StrSize (Desc); + FilePathSize = GetDevicePathSize (FilePath); + + TempByteBuffer = AllocateZeroPool (sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize); + if (TempByteBuffer != NULL) { + TempByteStart = TempByteBuffer; + *((UINT32 *)TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes + TempByteBuffer += sizeof (UINT32); + + *((UINT16 *)TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength + TempByteBuffer += sizeof (UINT16); + + CopyMem (TempByteBuffer, Desc, DescSize); + TempByteBuffer += DescSize; + ASSERT (FilePath != NULL); + CopyMem (TempByteBuffer, FilePath, FilePathSize); + + UnicodeSPrint (OptionStr, sizeof (OptionStr), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", TargetLocation); + Status = gRT->SetVariable ( + OptionStr, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT32) + sizeof (UINT16) + DescSize + FilePathSize, + TempByteStart + ); + + FreePool (TempByteStart); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr); + } else { + NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0])); + if (NewOrder != NULL) { + CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0])); + + // + // Insert target into order list + // + for (Index = OrderCount; Index > Position; Index--) { + NewOrder[Index] = NewOrder[Index - 1]; + } + + NewOrder[Position] = (UINT16)TargetLocation; + Status = gRT->SetVariable ( + Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + (OrderCount + 1) * sizeof (UINT16), + NewOrder + ); + + FreePool (NewOrder); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Print (L"bcfg: Add %s as %x\n", OptionStr, Position); + } + } + } + } + + // + // If always Free FilePath, will free devicepath in system when use "addh" + // + if ((FilePath != NULL) && !UseHandle) { + FreePool (FilePath); + } + + if (Str != NULL) { + FreePool (Str); + } + + if (Handles != NULL) { + FreePool (Handles); + } + + if (FileList != NULL) { + ShellCloseFileMetaArg (&FileList); + } + + return (ShellStatus); +} + +/** + Function to remove an item. + + @param[in] Target The target item to move. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Location The current location of the Target. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgRemove ( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 Location + ) +{ + CHAR16 VariableName[12]; + UINT16 *NewOrder; + EFI_STATUS Status; + UINTN NewCount; + + UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", CurrentOrder[Location]); + Status = gRT->SetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + return (SHELL_INVALID_PARAMETER); + } + + NewOrder = AllocateZeroPool (OrderCount*sizeof (CurrentOrder[0])); + if (NewOrder != NULL) { + NewCount = OrderCount; + CopyMem (NewOrder, CurrentOrder, OrderCount*sizeof (CurrentOrder[0])); + CopyMem (NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof (CurrentOrder[0])); + NewCount--; + + Status = gRT->SetVariable ( + Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder", + (EFI_GUID *)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + NewCount*sizeof (NewOrder[0]), + NewOrder + ); + FreePool (NewOrder); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder"); + return (SHELL_INVALID_PARAMETER); + } + + return (SHELL_SUCCESS); +} + +/** + Function to move a item to another location. + + @param[in] Target The target item to move. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] OldLocation The current location of the Target. + @param[in] NewLocation The desired location of the Target. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgMove ( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 OldLocation, + IN UINT16 NewLocation + ) +{ + UINT16 *NewOrder; + EFI_STATUS Status; + UINT16 Temp; + + NewOrder = AllocateCopyPool (OrderCount*sizeof (CurrentOrder[0]), CurrentOrder); + if (NewOrder == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + // + // correct the new location + // + if (NewLocation >= OrderCount) { + if (OrderCount > 0) { + NewLocation = (UINT16)OrderCount - 1; + } else { + NewLocation = 0; + } + } + + Temp = CurrentOrder[OldLocation]; + CopyMem (NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof (CurrentOrder[0])); + CopyMem (NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof (CurrentOrder[0])); + NewOrder[NewLocation] = Temp; + + Status = gRT->SetVariable ( + Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder", + (EFI_GUID *)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + OrderCount*sizeof (CurrentOrder[0]), + NewOrder + ); + + FreePool (NewOrder); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder"); + return (SHELL_INVALID_PARAMETER); + } + + return (SHELL_SUCCESS); +} + +/** + Function to add optional data to an option. + + @param[in] OptData The optional data to add. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Target The target of the operation. + + @retval SHELL_SUCCESS The operation was succesful. +**/ +SHELL_STATUS +BcfgAddOpt ( + IN CONST CHAR16 *OptData, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BCFG_OPERATION_TARGET Target + ) +{ + EFI_KEY_OPTION NewKeyOption; + EFI_KEY_OPTION *KeyOptionBuffer; + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + UINT16 OptionIndex; + UINT16 LoopCounter; + UINT64 Intermediate; + CONST CHAR16 *Temp; + CONST CHAR16 *Walker; + CHAR16 *FileName; + CHAR16 *Temp2; + CHAR16 *Data; + UINT32 KeyIndex; + CHAR16 VariableName[12]; + VOID *VariableData; + + SHELL_FILE_HANDLE FileHandle; + + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + Walker = OptData; + FileName = NULL; + Data = NULL; + KeyOptionBuffer = NULL; + VariableData = NULL; + + ZeroMem (&NewKeyOption, sizeof (EFI_KEY_OPTION)); + ZeroMem (VariableName, sizeof (VariableName)); + + while (Walker[0] == L' ') { + Walker++; + } + + // + // Get the index of the variable we are changing. + // + Status = ShellConvertStringToUint64 (Walker, &Intermediate, TRUE, TRUE); + if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL) || (((UINT16)Intermediate) > ((UINT16)OrderCount))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + return (ShellStatus); + } + + OptionIndex = (UINT16)Intermediate; + + Temp = StrStr (Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + + while (Walker[0] == L' ') { + Walker++; + } + + // + // determine whether we have file with data, quote delimited information, or a hot-key + // + if (Walker[0] == L'\"') { + // + // quoted filename or quoted information. + // + Temp = StrStr (Walker+1, L"\""); + if ((Temp == NULL) || (StrLen (Temp) != 1)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileName = StrnCatGrow (&FileName, NULL, Walker+1, 0); + if (FileName == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + return (ShellStatus); + } + + Temp2 = StrStr (FileName, L"\""); + ASSERT (Temp2 != NULL); + Temp2[0] = CHAR_NULL; + Temp2++; + if (StrLen (Temp2) > 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (EFI_ERROR (ShellFileExists (Walker))) { + // + // Not a file. must be misc information. + // + Data = FileName; + FileName = NULL; + } else { + FileName = StrnCatGrow (&FileName, NULL, Walker, 0); + } + } + } else { + // + // filename or hot key information. + // + if (StrStr (Walker, L" ") == NULL) { + // + // filename + // + if (EFI_ERROR (ShellFileExists (Walker))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileName = StrnCatGrow (&FileName, NULL, Walker, 0); + } + } else { + if (Target != BcfgTargetBootOrder) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Get hot key information + // + Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status) || (((UINT32)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate; + Temp = StrStr (Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + + while (Walker[0] == L' ') { + Walker++; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct. + // Re-allocate with the added information. + // + KeyOptionBuffer = AllocatePool (sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount)); + if (KeyOptionBuffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + return ShellStatus; + } + + CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof (EFI_KEY_OPTION)); + } + + for (LoopCounter = 0; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) { + // + // ScanCode + // + Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate) || (StrStr (Walker, L" ") == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate; + Temp = StrStr (Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + + while (Walker[0] == L' ') { + Walker++; + } + + // + // UnicodeChar + // + Status = ShellConvertStringToUint64 (Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status) || (((UINT16)Intermediate) != Intermediate)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + ((EFI_INPUT_KEY *)(((UINT8 *)KeyOptionBuffer) + sizeof (EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate; + Temp = StrStr (Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + + while (Walker[0] == L' ') { + Walker++; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Now do the BootOption / BootOptionCrc + // + ASSERT (OptionIndex <= OrderCount); + KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex]; + Status = GetBootOptionCrc (&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + for (Temp2 = NULL, KeyIndex = 0; KeyIndex <= 0xFFFF; KeyIndex++) { + UnicodeSPrint (VariableName, sizeof (VariableName), L"Key%04x", KeyIndex); + Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL); + if (Status == EFI_NOT_FOUND) { + break; + } + + if (!EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (VariableData); + } + } + + if (KeyIndex <= 0xFFFF) { + Status = gRT->SetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (EFI_KEY_OPTION) + (sizeof (EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), + KeyOptionBuffer + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + ASSERT (FileName == NULL && Data == NULL); + } + } + } + + // + // Shouldn't be possible to have have both. Neither is ok though. + // + ASSERT (FileName == NULL || Data == NULL); + + if ((ShellStatus == SHELL_SUCCESS) && ((FileName != NULL) || (Data != NULL))) { + if (FileName != NULL) { + // + // Open the file and populate the data buffer. + // + Status = ShellOpenFileByName ( + FileName, + &FileHandle, + EFI_FILE_MODE_READ, + 0 + ); + if (!EFI_ERROR (Status)) { + Status = ShellGetFileSize (FileHandle, &Intermediate); + } + + Data = AllocateZeroPool ((UINTN)Intermediate); + if (Data == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } + + if (!EFI_ERROR (Status)) { + Status = ShellReadFile (FileHandle, (UINTN *)&Intermediate, Data); + } + } else { + Intermediate = StrSize (Data); + } + + if (!EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS) && (Data != NULL)) { + Status = UpdateOptionalData (CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8 *)Data, Target); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + if (EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + SHELL_FREE_NON_NULL (Data); + SHELL_FREE_NON_NULL (KeyOptionBuffer); + SHELL_FREE_NON_NULL (FileName); + return ShellStatus; +} + +/** + Function to dump the Bcfg information. + + @param[in] Op The operation. + @param[in] OrderCount How many to dump. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] VerboseOutput TRUE for extra output. FALSE otherwise. + + @retval SHELL_SUCCESS The dump was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgDisplayDump ( + IN CONST CHAR16 *Op, + IN CONST UINTN OrderCount, + IN CONST UINT16 *CurrentOrder, + IN CONST BOOLEAN VerboseOutput + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + CHAR16 VariableName[12]; + UINTN LoopVar; + CHAR16 *DevPathString; + VOID *FilePathList; + UINTN Errors; + EFI_LOAD_OPTION *LoadOption; + CHAR16 *Description; + UINTN DescriptionSize; + UINTN OptionalDataOffset; + + if (OrderCount == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg"); + return (SHELL_SUCCESS); + } + + Errors = 0; + + for (LoopVar = 0; LoopVar < OrderCount; LoopVar++) { + Buffer = NULL; + BufferSize = 0; + DevPathString = NULL; + + UnicodeSPrint (VariableName, sizeof (VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]); + + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool (BufferSize); + Status = gRT->GetVariable ( + VariableName, + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + } + + if (EFI_ERROR (Status) || (Buffer == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ++Errors; + goto Cleanup; + } + + // + // We expect the Attributes, FilePathListLength, and L'\0'-terminated + // Description fields to be present. + // + if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_BCFG_VAR_CORRUPT), + gShellBcfgHiiHandle, + L"bcfg", + VariableName + ); + ++Errors; + goto Cleanup; + } + + LoadOption = (EFI_LOAD_OPTION *)Buffer; + Description = (CHAR16 *)(Buffer + sizeof (EFI_LOAD_OPTION)); + DescriptionSize = StrSize (Description); + + if (LoadOption->FilePathListLength != 0) { + FilePathList = (UINT8 *)Description + DescriptionSize; + DevPathString = ConvertDevicePathToText (FilePathList, TRUE, FALSE); + } + + OptionalDataOffset = sizeof *LoadOption + DescriptionSize + + LoadOption->FilePathListLength; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_BCFG_LOAD_OPTIONS), + gShellBcfgHiiHandle, + LoopVar, + VariableName, + Description, + DevPathString, + OptionalDataOffset >= BufferSize ? L'N' : L'Y' + ); + if (VerboseOutput && (OptionalDataOffset < BufferSize)) { + DumpHex ( + 2, // Indent + 0, // Offset (displayed) + BufferSize - OptionalDataOffset, // DataSize + Buffer + OptionalDataOffset // UserData + ); + } + +Cleanup: + if (Buffer != NULL) { + FreePool (Buffer); + } + + if (DevPathString != NULL) { + FreePool (DevPathString); + } + } + + return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS; +} + +/** + Function to initialize the BCFG operation structure. + + @param[in] Struct The stuct to initialize. +**/ +VOID +InitBcfgStruct ( + IN BGFG_OPERATION *Struct + ) +{ + ASSERT (Struct != NULL); + Struct->Target = BcfgTargetMax; + Struct->Type = BcfgTypeMax; + Struct->Number1 = 0; + Struct->Number2 = 0; + Struct->HandleIndex = 0; + Struct->FileName = NULL; + Struct->Description = NULL; + Struct->Order = NULL; + Struct->OptData = NULL; +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + { L"-v", TypeFlag }, + { L"-opt", TypeMaxValue }, + { NULL, TypeMax } +}; + +/** + Function for 'bcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunBcfg ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamNumber; + CONST CHAR16 *CurrentParam; + BGFG_OPERATION CurrentOperation; + UINTN Length; + UINT64 Intermediate; + UINT16 Count; + + Length = 0; + ProblemParam = NULL; + Package = NULL; + ShellStatus = SHELL_SUCCESS; + + InitBcfgStruct (&CurrentOperation); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize (); + ASSERT_EFI_ERROR (Status); + + Status = CommandInit (); + ASSERT_EFI_ERROR (Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam); + FreePool (ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (FALSE); + } + } else { + // + // Read in if we are doing -OPT + // + if (ShellCommandLineGetFlag (Package, L"-opt")) { + CurrentOperation.OptData = ShellCommandLineGetValue (Package, L"-opt"); + if (CurrentOperation.OptData == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeOpt; + } + + // + // small block to read the target of the operation + // + if (((ShellCommandLineGetCount (Package) < 3) && (CurrentOperation.Type != BcfgTypeOpt)) || + ((ShellCommandLineGetCount (Package) < 2) && (CurrentOperation.Type == BcfgTypeOpt)) + ) + { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"driver") == 0) { + CurrentOperation.Target = BcfgTargetDriverOrder; + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)ShellCommandLineGetRawValue (Package, 1), L"boot") == 0) { + CurrentOperation.Target = BcfgTargetBootOrder; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + // + // Read in the boot or driver order environment variable (not needed for opt) + // + if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) { + Length = 0; + Status = gRT->GetVariable ( + CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder", + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + CurrentOperation.Order = AllocateZeroPool (Length+(4*sizeof (CurrentOperation.Order[0]))); + if (CurrentOperation.Order == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + Status = gRT->GetVariable ( + CurrentOperation.Target == BcfgTargetBootOrder ? (CHAR16 *)L"BootOrder" : (CHAR16 *)L"DriverOrder", + (EFI_GUID *)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order + ); + } + } + } + + Count = (UINT16)(Length / sizeof (CurrentOperation.Order[0])); + + // + // large block to read the type of operation and verify parameter types for the info. + // + if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax)) { + for (ParamNumber = 2; ParamNumber < ShellCommandLineGetCount (Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) { + CurrentParam = ShellCommandLineGetRawValue (Package, ParamNumber); + if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"dump") == 0) { + CurrentOperation.Type = BcfgTypeDump; + if (ShellCommandLineGetCount (Package) > 3) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else if (ShellCommandLineGetFlag (Package, L"-v")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"add") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeAdd; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + ASSERT (CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addp") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeAddp; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + ASSERT (CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"addh") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeAddh; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.HandleIndex = (UINT16)Intermediate; + ASSERT (CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"rm") == 0) { + if ((ParamNumber + 1) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeRm; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mv") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + CurrentOperation.Type = BcfgTypeMv; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number2 = (UINT16)Intermediate; + } + + if ( (CurrentOperation.Number2 == CurrentOperation.Number1) + || (CurrentOperation.Number2 >= Count) + ) + { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"mod") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeMod; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modf") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModf; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modp") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModp; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)CurrentParam, L"modh") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModh; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if ((CurrentParam == NULL) || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.HandleIndex = (UINT16)Intermediate; + } + } + } + } + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + + if ((ShellStatus == SHELL_SUCCESS) && (CurrentOperation.Target < BcfgTargetMax) && (CurrentOperation.Type < BcfgTypeMax)) { + // + // we have all the info. Do the work + // + switch (CurrentOperation.Type) { + case BcfgTypeDump: + ShellStatus = BcfgDisplayDump ( + CurrentOperation.Target == BcfgTargetBootOrder ? L"Boot" : L"Driver", + Count, + CurrentOperation.Order, + ShellCommandLineGetFlag (Package, L"-v") + ); + break; + case BcfgTypeMv: + ShellStatus = BcfgMove ( + CurrentOperation.Target, + CurrentOperation.Order, + Count, + CurrentOperation.Number1, + CurrentOperation.Number2 + ); + break; + case BcfgTypeRm: + ShellStatus = BcfgRemove ( + CurrentOperation.Target, + CurrentOperation.Order, + Count, + CurrentOperation.Number1 + ); + break; + case BcfgTypeAdd: + case BcfgTypeAddp: + case BcfgTypeAddh: + ShellStatus = BcfgAdd ( + CurrentOperation.Number1, + CurrentOperation.FileName, + CurrentOperation.Description == NULL ? L"" : CurrentOperation.Description, + CurrentOperation.Order, + Count, + CurrentOperation.Target, + (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh), + (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp), + CurrentOperation.HandleIndex + ); + break; + case BcfgTypeMod: + case BcfgTypeModf: + case BcfgTypeModp: + case BcfgTypeModh: + ShellStatus = BcfgMod (&CurrentOperation, Count); + break; + case BcfgTypeOpt: + ShellStatus = BcfgAddOpt ( + CurrentOperation.OptData, + CurrentOperation.Order, + Count, + CurrentOperation.Target + ); + break; + default: + ASSERT (FALSE); + } + } + } + + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + + if (CurrentOperation.FileName != NULL) { + FreePool (CurrentOperation.FileName); + } + + if (CurrentOperation.Description != NULL) { + FreePool (CurrentOperation.Description); + } + + if (CurrentOperation.Order != NULL) { + FreePool (CurrentOperation.Order); + } + + return (ShellStatus); +} + +/** + Function to get the filename with help context if HII will not be used. + + @return The filename with help text in it. +**/ +CONST CHAR16 * +EFIAPI +ShellCommandGetManFileNameBcfg ( + VOID + ) +{ + return (mFileName); +} + +/** + "Constructor" for the library. + + This will register the handler for the bcfg command. + + @param[in] ImageHandle the image handle of the process + @param[in] SystemTable the EFI System Table pointer + @param[in] Name the profile name to use + + @retval EFI_SUCCESS the shell command handlers were installed successfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryRegisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN CONST CHAR16 *Name + ) +{ + if (gShellBcfgHiiHandle != NULL) { + return (EFI_SUCCESS); + } + + gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL); + if (gShellBcfgHiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handler + // + ShellCommandRegisterCommandName (L"bcfg", ShellCommandRunBcfg, ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN (STR_GET_HELP_BCFG)); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryUnregisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellBcfgHiiHandle != NULL) { + HiiRemovePackages (gShellBcfgHiiHandle); + } + + gShellBcfgHiiHandle = NULL; + return (EFI_SUCCESS); +} |
