| /** @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 optioanl data. | |
| @param[in] Target The target of the operation. | |
| @retval EFI_SUCCESS The data was sucessfully 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 sucessfully 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 sucessful return the device path to the handle. | |
| @retval EFI_SUCCESS The device path was sucessfully 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); | |
| } | |
| /** | |
| Functino 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 sucessful 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); | |
| } | |
| /** | |
| Funciton 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); | |
| } | |
| /** | |
| Funciton 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 sucessfully | |
| @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); | |
| } |