summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ShellPkg/Include/Guid/ShellLibHiiGuid.h5
-rw-r--r--ShellPkg/Include/Library/BcfgCommandLib.h52
-rw-r--r--ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c1541
-rw-r--r--ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf46
-rw-r--r--ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.unibin0 -> 17972 bytes
-rw-r--r--ShellPkg/ShellPkg.dec4
-rw-r--r--ShellPkg/ShellPkg.dsc3
7 files changed, 1650 insertions, 1 deletions
diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index 26d3279d46..dc694f2915 100644
--- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -54,6 +54,10 @@
{ \
0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \
}
+#define SHELL_BCFG_HII_GUID \
+ { \
+ 0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \
+ }
extern EFI_GUID gHandleParsingHiiGuid;
extern EFI_GUID gShellDebug1HiiGuid;
@@ -63,5 +67,6 @@ extern EFI_GUID gShellLevel1HiiGuid;
extern EFI_GUID gShellLevel2HiiGuid;
extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;
+extern EFI_GUID gShellBcfgHiiGuid;
#endif
diff --git a/ShellPkg/Include/Library/BcfgCommandLib.h b/ShellPkg/Include/Library/BcfgCommandLib.h
new file mode 100644
index 0000000000..9f7454a9d7
--- /dev/null
+++ b/ShellPkg/Include/Library/BcfgCommandLib.h
@@ -0,0 +1,52 @@
+/** @file
+ Header file for BCFG command library.
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BCFG_COMMAND_LIB_H_
+#define _BCFG_COMMAND_LIB_H_
+
+/**
+ "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
+ );
+
+/**
+ "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
+ );
+
+#endif
+
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
new file mode 100644
index 0000000000..d62b569ab3
--- /dev/null
+++ b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
@@ -0,0 +1,1541 @@
+/** @file
+ Main file for BCFG command.
+
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.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>
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+STATIC EFI_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,
+ BcfgTypeMax = 7
+} 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 occured.
+**/
+EFI_STATUS
+EFIAPI
+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 = AllocateCopyPool(NewSize, OriginalData);
+ if (NewData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ 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 occured.
+**/
+EFI_STATUS
+EFIAPI
+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
+EFIAPI
+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 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
+EFIAPI
+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 *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_PROBLEM), gShellBcfgHiiHandle, 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, 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_PROBLEM), gShellBcfgHiiHandle, 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, 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, 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, File, Arg->Status);
+ 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, Arg->FullName);
+ ShellStatus = SHELL_UNSUPPORTED;
+ } else {
+/*
+ if (UsePath) {
+ DevPath = DevicePath;
+ while (!IsDevicePathEnd(DevPath)) {
+ if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
+
+ //
+ // If we find it use it instead
+ //
+ DevicePath = DevPath;
+ break;
+ }
+ DevPath = NextDevicePathNode(DevPath);
+ }
+ //
+ // append the file
+ //
+ for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++);
+ FileNode = FileDevicePath(NULL, StringWalker+1);
+ FilePath = AppendDevicePath(DevicePath, FileNode);
+ FreePool(FileNode);
+ } 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);
+ } 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, OptionStr, Status);
+ } else {
+ NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));
+ ASSERT(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, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);
+ 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
+EFIAPI
+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, VariableName, Status);
+ 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, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
+ 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
+EFIAPI
+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, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);
+ 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
+EFIAPI
+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;
+ UINT16 KeyIndex;
+ CHAR16 VariableName[12];
+
+ SHELL_FILE_HANDLE FileHandle;
+
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+ Walker = OptData;
+ FileName = NULL;
+ Data = NULL;
+ KeyOptionBuffer = NULL;
+
+ ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));
+
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+
+ //
+ // Get the index of the variable we are changing.
+ //
+ Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
+ if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, 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_PROBLEM), gShellBcfgHiiHandle, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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 = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption);
+ if (KeyOptionBuffer == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle);
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ }
+ }
+ 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_PROBLEM), gShellBcfgHiiHandle, 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_PROBLEM), gShellBcfgHiiHandle, 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_PROBLEM), gShellBcfgHiiHandle, 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 = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ (UINTN*)&Intermediate,
+ NULL);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ }
+ 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, VariableName, Status);
+ 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);
+ 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, VariableName, Status);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);
+ 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
+EFIAPI
+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;
+ UINTN LoopVar2;
+ CHAR16 *DevPathString;
+ VOID *DevPath;
+
+ if (OrderCount == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle);
+ return (SHELL_SUCCESS);
+ }
+
+ for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
+ Buffer = NULL;
+ BufferSize = 0;
+ 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, VariableName, Status);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if ((*(UINT16*)(Buffer+4)) != 0) {
+ DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));
+ if (DevPath == NULL) {
+ DevPathString = NULL;
+ } else {
+ CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));
+ DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);
+ }
+ } else {
+ DevPath = NULL;
+ DevPathString = NULL;
+ }
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
+ gShellBcfgHiiHandle,
+ LoopVar,
+ VariableName,
+ (CHAR16*)(Buffer+6),
+ DevPathString,
+ (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');
+ if (VerboseOutput) {
+ for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){
+ ShellPrintEx(
+ -1,
+ -1,
+ NULL,
+ L"%02x",
+ Buffer[LoopVar2]);
+ }
+ ShellPrintEx(
+ -1,
+ -1,
+ NULL,
+ L"\r\n");
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ if (DevPath != NULL) {
+ FreePool(DevPath);
+ }
+ if (DevPathString != NULL) {
+ FreePool(DevPathString);
+ }
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function to initialize the BCFG operation structure.
+
+ @param[in] Struct The stuct to initialize.
+**/
+VOID
+EFIAPI
+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, 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_PROBLEM_VAL), gShellBcfgHiiHandle, 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);
+ 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);
+ 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;
+ } else if (ShellCommandLineGetFlag(Package, L"-v")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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_PROBLEM), gShellBcfgHiiHandle, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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, 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);
+ 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_PROBLEM), gShellBcfgHiiHandle, 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, 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_PROBLEM), gShellBcfgHiiHandle, 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, Count);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, 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 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) {
+ 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);
+}
+
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
new file mode 100644
index 0000000000..596bb35096
--- /dev/null
+++ b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Provides shell install1 functions
+#
+# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellBcfgCommandLib
+ FILE_GUID = F6A3BF5D-4095-4E4F-9670-408770C2DBDF
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BcfgCommandLib|UEFI_APPLICATION UEFI_DRIVER
+
+[Sources.common]
+ UefiShellBcfgCommandLib.c
+ UefiShellBcfgCommandLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Guids]
+ gShellBcfgHiiGuid
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni
new file mode 100644
index 0000000000..2a3c232dfc
--- /dev/null
+++ b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni
Binary files differ
diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
index 909dd7aa97..90eb08ab85 100644
--- a/ShellPkg/ShellPkg.dec
+++ b/ShellPkg/ShellPkg.dec
@@ -46,6 +46,9 @@
## @libraryclass Provides path manipulation functions
PathLib|Include/Library/PathLib.h
+ ## @libraryclass provides BCFG command
+ BcfgCommandLib|Include/Library/BcfgCommandLib.h
+
[Guids]
gEfiShellEnvironment2ExtGuid = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}}
gEfiShellPkgTokenSpaceGuid = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}}
@@ -60,6 +63,7 @@
gShellLevel2HiiGuid = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae}}
gShellLevel3HiiGuid = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f}}
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}
+ gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}}
[Protocols]
gEfiShellProtocolGuid = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}}
diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 3284c1cdc5..39fe936f4e 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -1,7 +1,7 @@
## @file
# Shell Package
#
-# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -49,6 +49,7 @@
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
[LibraryClasses.ARM]
#