]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg: Add a new library for "bcfg" command
authorJaben Carsey <jaben.carsey@intel.com>
Wed, 10 Sep 2014 20:30:38 +0000 (20:30 +0000)
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 10 Sep 2014 20:30:38 +0000 (20:30 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
Reviewed-by: Chris Phillips <chrisp@hp.com>
Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com>
Reviewed by: Tapan Shah <tapandshah@hp.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16092 6f19259b-4bc3-4df7-8a09-765794883524

ShellPkg/Include/Guid/ShellLibHiiGuid.h
ShellPkg/Include/Library/BcfgCommandLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni [new file with mode: 0644]
ShellPkg/ShellPkg.dec
ShellPkg/ShellPkg.dsc

index 26d3279d46a41658b29dbf55d966a7d4fc6a75d4..dc694f2915c3aeb9bb8cd3632bc2860662571abd 100644 (file)
   { \\r
     0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \\r
   }\r
+#define SHELL_BCFG_HII_GUID \\r
+  { \\r
+    0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \\r
+  }\r
 \r
 extern EFI_GUID gHandleParsingHiiGuid;\r
 extern EFI_GUID gShellDebug1HiiGuid;\r
@@ -63,5 +67,6 @@ extern EFI_GUID gShellLevel1HiiGuid;
 extern EFI_GUID gShellLevel2HiiGuid;\r
 extern EFI_GUID gShellLevel3HiiGuid;\r
 extern EFI_GUID gShellNetwork1HiiGuid;\r
+extern EFI_GUID gShellBcfgHiiGuid;\r
 \r
 #endif\r
diff --git a/ShellPkg/Include/Library/BcfgCommandLib.h b/ShellPkg/Include/Library/BcfgCommandLib.h
new file mode 100644 (file)
index 0000000..9f7454a
--- /dev/null
@@ -0,0 +1,52 @@
+/** @file\r
+  Header file for BCFG command library.\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _BCFG_COMMAND_LIB_H_\r
+#define _BCFG_COMMAND_LIB_H_\r
+\r
+/**\r
+  "Constructor" for the library.\r
+\r
+  This will register the handler for the bcfg command.\r
+\r
+  @param[in] ImageHandle    the image handle of the process\r
+  @param[in] SystemTable    the EFI System Table pointer\r
+  @param[in] Name           the profile name to use\r
+\r
+  @retval EFI_SUCCESS        the shell command handlers were installed sucessfully\r
+  @retval EFI_UNSUPPORTED    the shell level required was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BcfgLibraryRegisterBcfgCommand (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable,\r
+  IN CONST CHAR16      *Name\r
+  );\r
+\r
+/**\r
+  "Destructor" for the library.  free any resources.\r
+\r
+  @param ImageHandle            The image handle of the process.\r
+  @param SystemTable            The EFI System Table pointer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BcfgLibraryUnregisterBcfgCommand (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
new file mode 100644 (file)
index 0000000..d62b569
--- /dev/null
@@ -0,0 +1,1541 @@
+/** @file\r
+  Main file for BCFG command.\r
+\r
+  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <Uefi.h>\r
+#include <ShellBase.h>\r
+\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/ShellLibHiiGuid.h>\r
+\r
+#include <Protocol/EfiShell.h>\r
+#include <Protocol/EfiShellParameters.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/UnicodeCollation.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/ShellCommandLib.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/SortLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/FileHandleLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HandleParsingLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";\r
+STATIC EFI_HANDLE gShellBcfgHiiHandle  = NULL;\r
+\r
+typedef enum {\r
+  BcfgTargetBootOrder    = 0,\r
+  BcfgTargetDriverOrder  = 1,\r
+  BcfgTargetMax          = 2\r
+} BCFG_OPERATION_TARGET;\r
+\r
+typedef enum {\r
+  BcfgTypeDump       = 0,\r
+  BcfgTypeAdd        = 1,\r
+  BcfgTypeAddp       = 2,\r
+  BcfgTypeAddh       = 3,\r
+  BcfgTypeRm         = 4,\r
+  BcfgTypeMv         = 5,\r
+  BcfgTypeOpt        = 6,\r
+  BcfgTypeMax        = 7\r
+} BCFG_OPERATION_TYPE;\r
+\r
+typedef struct {\r
+  BCFG_OPERATION_TARGET Target;\r
+  BCFG_OPERATION_TYPE   Type;\r
+  UINT16                Number1;\r
+  UINT16                Number2;\r
+  UINTN                 HandleIndex;\r
+  CHAR16                *FileName;\r
+  CHAR16                *Description;\r
+  UINT16                *Order;\r
+  CONST CHAR16          *OptData;\r
+} BGFG_OPERATION;\r
+\r
+/**\r
+  Update the optional data for a boot or driver option.\r
+\r
+  If optional data exists it will be changed.\r
+\r
+  @param[in]      Index     The boot or driver option index update.\r
+  @param[in]      DataSize  The size in bytes of Data.\r
+  @param[in]      Data      The buffer for the optioanl data.\r
+  @param[in]      Target    The target of the operation.\r
+\r
+  @retval EFI_SUCCESS       The data was sucessfully updated.\r
+  @retval other             A error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UpdateOptionalData(\r
+  UINT16                          Index, \r
+  UINTN                           DataSize, \r
+  UINT8                           *Data,\r
+  IN CONST BCFG_OPERATION_TARGET  Target\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      VariableName[12];\r
+  UINTN       OriginalSize;\r
+  UINT8       *OriginalData;\r
+  UINTN       NewSize;\r
+  UINT8       *NewData;\r
+  UINTN       OriginalOptionDataSize;\r
+\r
+  UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index);\r
+  \r
+  OriginalSize = 0;\r
+  OriginalData = NULL;\r
+  NewData      = NULL;\r
+  NewSize      = 0;\r
+\r
+  Status = gRT->GetVariable(\r
+      VariableName,\r
+      (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+      NULL,\r
+      &OriginalSize,\r
+      OriginalData);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    OriginalData = AllocateZeroPool(OriginalSize);\r
+    if (OriginalData == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
+    Status = gRT->GetVariable(\r
+        VariableName,\r
+        (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+        NULL,\r
+        &OriginalSize,\r
+        OriginalData);\r
+  }\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    //\r
+    // Allocate new struct and discard old optional data.\r
+    //\r
+    ASSERT (OriginalData != NULL);\r
+    OriginalOptionDataSize  = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16))));\r
+    OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32)));\r
+    OriginalOptionDataSize -= OriginalSize;\r
+    NewSize = OriginalSize - OriginalOptionDataSize + DataSize;\r
+    NewData = AllocateCopyPool(NewSize, OriginalData);\r
+    if (NewData == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    //\r
+    // put the data back under the variable\r
+    //\r
+    Status = gRT->SetVariable(\r
+      VariableName, \r
+      (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+      EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+      NewSize,\r
+      NewData);\r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(OriginalData);\r
+  SHELL_FREE_NON_NULL(NewData);\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  This function will get a CRC for a boot option.\r
+\r
+  @param[in, out] Crc         The CRC value to return.\r
+  @param[in]      BootIndex   The boot option index to CRC.\r
+\r
+  @retval EFI_SUCCESS           The CRC was sucessfully returned.\r
+  @retval other                 A error occured.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetBootOptionCrc(\r
+  UINT32      *Crc, \r
+  UINT16      BootIndex\r
+  )\r
+{\r
+  CHAR16      VariableName[12];\r
+  EFI_STATUS  Status;\r
+  UINT8       *Buffer;\r
+  UINTN       BufferSize;\r
+\r
+  Buffer      = NULL;\r
+  BufferSize  = 0;\r
+\r
+  //\r
+  // Get the data Buffer\r
+  //\r
+  UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex);\r
+  Status = gRT->GetVariable(\r
+      VariableName,\r
+      (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+      NULL,\r
+      &BufferSize,\r
+      NULL);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    Buffer = AllocateZeroPool(BufferSize);\r
+    Status = gRT->GetVariable(\r
+        VariableName,\r
+        (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+        NULL,\r
+        &BufferSize,\r
+        Buffer);\r
+  }\r
+\r
+  //\r
+  // Get the CRC computed\r
+  //\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);\r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(Buffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function will populate the device path protocol parameter based on TheHandle.\r
+\r
+  @param[in]      TheHandle     Driver handle.\r
+  @param[in, out] FilePath      On a sucessful return the device path to the handle.\r
+\r
+  @retval EFI_SUCCESS           The device path was sucessfully returned.\r
+  @retval other                 A error from gBS->HandleProtocol.\r
+\r
+  @sa HandleProtocol\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetDevicePathForDriverHandle (\r
+  IN EFI_HANDLE                   TheHandle,\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ImageDevicePath;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                TheHandle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                (VOID**)&LoadedImage,\r
+                gImageHandle,\r
+                NULL,\r
+                EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+               );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                  LoadedImage->DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID**)&ImageDevicePath,\r
+                  gImageHandle,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                 );\r
+    if (!EFI_ERROR (Status)) {\r
+//      *DevPath  = DuplicateDevicePath (ImageDevicePath);\r
+//      *FilePath = DuplicateDevicePath (LoadedImage->FilePath);\r
+        *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);\r
+      gBS->CloseProtocol(\r
+                  LoadedImage->DeviceHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  gImageHandle,\r
+                  NULL);\r
+    }\r
+    gBS->CloseProtocol(\r
+                TheHandle,\r
+                &gEfiLoadedImageProtocolGuid,\r
+                gImageHandle,\r
+                NULL);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Function to add a option.\r
+\r
+  @param[in] Position       The position to add Target at.\r
+  @param[in] File           The file to make the target.\r
+  @param[in] Desc           The description text.\r
+  @param[in] CurrentOrder   The pointer to the current order of items.\r
+  @param[in] OrderCount     The number if items in CurrentOrder.\r
+  @param[in] Target         The info on the option to add.\r
+  @param[in] UseHandle      TRUE to use HandleNumber, FALSE to use File and Desc.\r
+  @param[in] UsePath        TRUE to convert to devicepath.\r
+  @param[in] HandleNumber   The handle number to add.\r
+\r
+  @retval SHELL_SUCCESS             The operation was successful.\r
+  @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+BcfgAdd(\r
+  IN       UINTN                  Position,\r
+  IN CONST CHAR16                 *File,\r
+  IN CONST CHAR16                 *Desc,\r
+  IN CONST UINT16                 *CurrentOrder,\r
+  IN CONST UINTN                  OrderCount,\r
+  IN CONST BCFG_OPERATION_TARGET  Target,\r
+  IN CONST BOOLEAN                UseHandle,\r
+  IN CONST BOOLEAN                UsePath,\r
+  IN CONST UINTN                  HandleNumber\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
+  CHAR16                    *Str;\r
+  UINT8                     *TempByteBuffer;\r
+  UINT8                     *TempByteStart;\r
+  EFI_SHELL_FILE_INFO       *Arg;\r
+  EFI_SHELL_FILE_INFO       *FileList;\r
+  CHAR16                    OptionStr[40];\r
+  UINTN                     DescSize, FilePathSize;\r
+  BOOLEAN                   Found;\r
+  UINTN                     TargetLocation;\r
+  UINTN                     Index;\r
+  EFI_HANDLE                *Handles;\r
+  EFI_HANDLE                CurHandle;\r
+  UINTN                     DriverBindingHandleCount;\r
+  UINTN                     ParentControllerHandleCount;\r
+  UINTN                     ChildControllerHandleCount;\r
+  SHELL_STATUS              ShellStatus;\r
+  UINT16                    *NewOrder;\r
+\r
+  if (!UseHandle) {\r
+    if (File == NULL || Desc == NULL) {\r
+      return (SHELL_INVALID_PARAMETER);\r
+    }\r
+  } else {\r
+    if (HandleNumber == 0) {\r
+      return (SHELL_INVALID_PARAMETER);\r
+    }\r
+  }\r
+\r
+  if (Position > OrderCount) {\r
+    Position =  OrderCount;\r
+  }\r
+\r
+  Str             = NULL;\r
+  FilePath        = NULL;\r
+  FileList        = NULL;\r
+  Handles         = NULL;\r
+  ShellStatus     = SHELL_SUCCESS;\r
+  TargetLocation  = 0xFFFF;\r
+\r
+  if (UseHandle) {\r
+    CurHandle = ConvertHandleIndexToHandle(HandleNumber);\r
+    if (CurHandle == NULL) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Handle Number");\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else {\r
+      if (Target == BcfgTargetBootOrder) {\r
+        //\r
+        //Make sure that the handle should point to a real controller\r
+        //\r
+        Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (\r
+                   CurHandle,\r
+                   &DriverBindingHandleCount,\r
+                   NULL);\r
+\r
+        Status = PARSE_HANDLE_DATABASE_PARENTS (\r
+                   CurHandle,\r
+                   &ParentControllerHandleCount,\r
+                   NULL);\r
+\r
+        Status = ParseHandleDatabaseForChildControllers (\r
+                   CurHandle,\r
+                   &ChildControllerHandleCount,\r
+                   NULL);\r
+\r
+        if (DriverBindingHandleCount > 0\r
+              || ParentControllerHandleCount > 0\r
+              || ChildControllerHandleCount > 0) {\r
+          FilePath = NULL;\r
+          Status = gBS->HandleProtocol (\r
+                     CurHandle,\r
+                     &gEfiDevicePathProtocolGuid,\r
+                     (VOID**)&FilePath);\r
+        }\r
+        if (EFI_ERROR (Status)) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, HandleNumber);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }\r
+      } else {\r
+        //\r
+        //Make sure that the handle should point to driver, not a controller.\r
+        //\r
+        Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (\r
+                   CurHandle,\r
+                   &DriverBindingHandleCount,\r
+                   NULL);\r
+\r
+        Status = PARSE_HANDLE_DATABASE_PARENTS (\r
+                   CurHandle,\r
+                   &ParentControllerHandleCount,\r
+                   NULL);\r
+\r
+        Status = ParseHandleDatabaseForChildControllers (\r
+                   CurHandle,\r
+                   &ChildControllerHandleCount,\r
+                   NULL);\r
+\r
+        Status = gBS->HandleProtocol (\r
+                   CurHandle,\r
+                   &gEfiDevicePathProtocolGuid,\r
+                   (VOID**)&FilePath);\r
+\r
+        if (DriverBindingHandleCount > 0\r
+              || ParentControllerHandleCount > 0\r
+              || ChildControllerHandleCount > 0\r
+              || !EFI_ERROR(Status) ) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Handle Number");\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        } else {\r
+          //\r
+          // Get the DevicePath from the loaded image information.\r
+          //\r
+          Status = GetDevicePathForDriverHandle(CurHandle, &FilePath);\r
+        }\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // Get file info\r
+    //\r
+    ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);\r
+\r
+    if (FileList == NULL) {\r
+      //\r
+      // If filename matched nothing fail\r
+      //\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, File);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
+      //\r
+      // If filename expanded to multiple names, fail\r
+      //\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, File);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else {\r
+      Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);\r
+      if (EFI_ERROR(Arg->Status)) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, File, Arg->Status);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      } else {\r
+        //\r
+        // Build FilePath to the filename\r
+        //\r
+\r
+        //\r
+        // get the device path\r
+        //\r
+        DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);\r
+        if (DevicePath == NULL) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, Arg->FullName);\r
+          ShellStatus = SHELL_UNSUPPORTED;\r
+        } else {\r
+/*\r
+          if (UsePath) {\r
+            DevPath = DevicePath;\r
+            while (!IsDevicePathEnd(DevPath)) {\r
+              if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&\r
+                (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {\r
+\r
+                //\r
+                // If we find it use it instead\r
+                //\r
+                DevicePath = DevPath;\r
+                break;\r
+              }\r
+              DevPath = NextDevicePathNode(DevPath);\r
+            }\r
+            //\r
+            // append the file\r
+            //\r
+            for(StringWalker=Arg->FullName; *StringWalker != CHAR_NULL && *StringWalker != ':'; StringWalker++);\r
+            FileNode = FileDevicePath(NULL, StringWalker+1);\r
+            FilePath = AppendDevicePath(DevicePath, FileNode);\r
+            FreePool(FileNode);\r
+          } else {\r
+*/\r
+            FilePath = DuplicateDevicePath(DevicePath);\r
+/*\r
+          }\r
+*/\r
+          FreePool(DevicePath);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  if (ShellStatus == SHELL_SUCCESS) {\r
+    //\r
+    // Find a free target ,a brute force implementation\r
+    //\r
+    Found = FALSE;\r
+    for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {\r
+      Found = TRUE;\r
+      for (Index=0; Index < OrderCount; Index++) {\r
+        if (CurrentOrder[Index] == TargetLocation) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (TargetLocation == 0xFFFF) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle);\r
+    } else {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);\r
+    }\r
+  }\r
+\r
+  if (ShellStatus == SHELL_SUCCESS) {\r
+    //\r
+    // Add the option\r
+    //\r
+    DescSize = StrSize(Desc);\r
+    FilePathSize = GetDevicePathSize (FilePath);\r
+\r
+    TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);\r
+    if (TempByteBuffer != NULL) {\r
+      TempByteStart  = TempByteBuffer;\r
+      *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE;      // Attributes\r
+      TempByteBuffer += sizeof (UINT32);\r
+\r
+      *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize;    // FilePathListLength\r
+      TempByteBuffer += sizeof (UINT16);\r
+\r
+      CopyMem (TempByteBuffer, Desc, DescSize);\r
+      TempByteBuffer += DescSize;\r
+      ASSERT (FilePath != NULL);\r
+      CopyMem (TempByteBuffer, FilePath, FilePathSize);\r
+\r
+      UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);\r
+      Status = gRT->SetVariable (\r
+            OptionStr,\r
+            &gEfiGlobalVariableGuid,\r
+            EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+            sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,\r
+            TempByteStart\r
+           );\r
+\r
+      FreePool(TempByteStart);\r
+    } else {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, OptionStr, Status);\r
+    } else {\r
+      NewOrder = AllocateZeroPool((OrderCount+1)*sizeof(NewOrder[0]));\r
+      ASSERT(NewOrder != NULL);\r
+      CopyMem(NewOrder, CurrentOrder, (OrderCount)*sizeof(NewOrder[0]));\r
+\r
+      //\r
+      // Insert target into order list\r
+      //\r
+      for (Index=OrderCount; Index > Position; Index--) {\r
+        NewOrder[Index] = NewOrder[Index-1];\r
+      }\r
+\r
+      NewOrder[Position] = (UINT16) TargetLocation;\r
+      Status = gRT->SetVariable (\r
+        Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder",\r
+        &gEfiGlobalVariableGuid,\r
+        EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+        (OrderCount+1) * sizeof(UINT16),\r
+        NewOrder\r
+       );\r
+\r
+      FreePool(NewOrder);\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?L"BootOrder":L"DriverOrder", Status);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      } else {\r
+        Print (L"bcfg: Add %s as %x\n", OptionStr, Position);\r
+      }\r
+    }\r
+  }\r
+\r
+//\r
+//If always Free FilePath, will free devicepath in system when use "addh"\r
+//\r
+  if (FilePath!=NULL && !UseHandle) {\r
+    FreePool (FilePath);\r
+  }\r
+\r
+  if (Str != NULL) {\r
+    FreePool(Str);\r
+  }\r
+\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  if (FileList != NULL) {\r
+    ShellCloseFileMetaArg (&FileList);\r
+  }\r
+\r
+  return (ShellStatus);\r
+}\r
+\r
+/**\r
+  Funciton to remove an item.\r
+\r
+  @param[in] Target         The target item to move.\r
+  @param[in] CurrentOrder   The pointer to the current order of items.\r
+  @param[in] OrderCount     The number if items in CurrentOrder.\r
+  @param[in] Location       The current location of the Target.\r
+\r
+  @retval SHELL_SUCCESS             The operation was successful.\r
+  @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+BcfgRemove(\r
+  IN CONST BCFG_OPERATION_TARGET  Target,\r
+  IN CONST UINT16                 *CurrentOrder,\r
+  IN CONST UINTN                  OrderCount,\r
+  IN CONST UINT16                 Location\r
+  )\r
+{\r
+  CHAR16      VariableName[12];\r
+  UINT16      *NewOrder;\r
+  EFI_STATUS  Status;\r
+  UINTN       NewCount;\r
+\r
+  UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);\r
+  Status = gRT->SetVariable(\r
+    VariableName,\r
+    (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+    EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+    0,\r
+    NULL);\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
+    return (SHELL_INVALID_PARAMETER);\r
+  }\r
+  NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));\r
+  if (NewOrder != NULL) {\r
+    NewCount = OrderCount;\r
+    CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));\r
+    CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));\r
+    NewCount--;\r
+\r
+    Status = gRT->SetVariable(\r
+      Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
+      (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+      EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+      NewCount*sizeof(NewOrder[0]),\r
+      NewOrder);\r
+    FreePool(NewOrder);\r
+  } else {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+  }\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
+    return (SHELL_INVALID_PARAMETER);\r
+  }\r
+  return (SHELL_SUCCESS);\r
+}\r
+\r
+/**\r
+  Funciton to move a item to another location.\r
+\r
+  @param[in] Target         The target item to move.\r
+  @param[in] CurrentOrder   The pointer to the current order of items.\r
+  @param[in] OrderCount     The number if items in CurrentOrder.\r
+  @param[in] OldLocation    The current location of the Target.\r
+  @param[in] NewLocation    The desired location of the Target.\r
+\r
+  @retval SHELL_SUCCESS             The operation was successful.\r
+  @retval SHELL_INVALID_PARAMETER   A parameter was invalid.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+BcfgMove(\r
+  IN CONST BCFG_OPERATION_TARGET  Target,\r
+  IN CONST UINT16                 *CurrentOrder,\r
+  IN CONST UINTN                  OrderCount,\r
+  IN CONST UINT16                 OldLocation,\r
+  IN       UINT16                 NewLocation\r
+  )\r
+{\r
+  UINT16            *NewOrder;\r
+  EFI_STATUS        Status;\r
+  UINT16            Temp;\r
+\r
+  NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder);\r
+  if (NewOrder == NULL) {\r
+    return (SHELL_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  //\r
+  // correct the new location\r
+  //\r
+  if (NewLocation >= OrderCount) {\r
+    if (OrderCount > 0) {\r
+      NewLocation = (UINT16)OrderCount - 1;\r
+    } else {\r
+      NewLocation = 0;\r
+    }\r
+  }\r
+\r
+  Temp = CurrentOrder[OldLocation];\r
+  CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));\r
+  CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));\r
+  NewOrder[NewLocation] = Temp;\r
+\r
+  Status = gRT->SetVariable(\r
+    Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
+    (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+    EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+    OrderCount*sizeof(CurrentOrder[0]),\r
+    NewOrder);\r
+\r
+  FreePool(NewOrder);\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", Status);\r
+    return (SHELL_INVALID_PARAMETER);\r
+  }\r
+  return (SHELL_SUCCESS);\r
+}\r
+\r
+/**\r
+  Function to add optional data to an option.\r
+\r
+  @param[in] OptData      The optional data to add.\r
+  @param[in] CurrentOrder The pointer to the current order of items.\r
+  @param[in] OrderCount   The number if items in CurrentOrder.\r
+  @param[in] Target       The target of the operation.\r
+\r
+  @retval SHELL_SUCCESS   The operation was succesful.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+BcfgAddOpt(\r
+  IN CONST CHAR16                 *OptData,\r
+  IN CONST UINT16                 *CurrentOrder,\r
+  IN CONST UINTN                  OrderCount,\r
+  IN CONST BCFG_OPERATION_TARGET  Target\r
+  )\r
+{\r
+  EFI_KEY_OPTION  NewKeyOption;\r
+  EFI_KEY_OPTION *KeyOptionBuffer;\r
+  SHELL_STATUS    ShellStatus;\r
+  EFI_STATUS      Status;\r
+  UINT16          OptionIndex;\r
+  UINT16          LoopCounter;\r
+  UINT64          Intermediate;\r
+  CONST CHAR16    *Temp;\r
+  CONST CHAR16    *Walker;\r
+  CHAR16          *FileName;\r
+  CHAR16          *Temp2;\r
+  CHAR16          *Data;\r
+  UINT16          KeyIndex;\r
+  CHAR16          VariableName[12];\r
+\r
+  SHELL_FILE_HANDLE FileHandle;\r
+\r
+  Status          = EFI_SUCCESS;\r
+  ShellStatus     = SHELL_SUCCESS;\r
+  Walker          = OptData;\r
+  FileName        = NULL;\r
+  Data            = NULL;\r
+  KeyOptionBuffer = NULL;\r
+\r
+  ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));\r
+\r
+  while(Walker[0] == L' ') {\r
+    Walker++;\r
+  }\r
+\r
+  //\r
+  // Get the index of the variable we are changing.\r
+  //\r
+  Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
+  if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Option Index");\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    return (ShellStatus);\r
+  }\r
+  OptionIndex = (UINT16)Intermediate;\r
+\r
+  Temp = StrStr(Walker, L" ");\r
+  if (Temp != NULL) {\r
+    Walker = Temp;\r
+  }\r
+  while(Walker[0] == L' ') {\r
+    Walker++;\r
+  }\r
+\r
+  //\r
+  // determine whether we have file with data, quote delimited information, or a hot-key \r
+  //\r
+  if (Walker[0] == L'\"') {\r
+    //\r
+    // quoted filename or quoted information.\r
+    //\r
+    Temp = StrStr(Walker+1, L"\"");\r
+    if (Temp == NULL || StrLen(Temp) != 1) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else {\r
+      FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);\r
+      if (FileName == NULL) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle);\r
+        ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+        return (ShellStatus);\r
+      }\r
+      Temp2 = StrStr(FileName, L"\"");\r
+      ASSERT(Temp2 != NULL);\r
+      Temp2[0] = CHAR_NULL;\r
+      Temp2++;\r
+      if (StrLen(Temp2)>0) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      }\r
+      if (EFI_ERROR(ShellFileExists(Walker))) {\r
+        //\r
+        // Not a file.  must be misc information.\r
+        //\r
+        Data     = FileName;\r
+        FileName = NULL;\r
+      } else {\r
+        FileName = StrnCatGrow(&FileName, NULL, Walker, 0);\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // filename or hot key information.\r
+    //\r
+    if (StrStr(Walker, L" ") == NULL) {\r
+      //\r
+      // filename\r
+      //\r
+      if (EFI_ERROR(ShellFileExists(Walker))) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, Walker);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      } else {\r
+        FileName = StrnCatGrow(&FileName, NULL, Walker, 0);\r
+      }\r
+    } else {\r
+      if (Target != BcfgTargetBootOrder) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      }\r
+\r
+      if (ShellStatus == SHELL_SUCCESS) {\r
+        //\r
+        // Get hot key information\r
+        //\r
+        Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
+        if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }\r
+        NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;\r
+        Temp = StrStr(Walker, L" ");\r
+        if (Temp != NULL) {\r
+          Walker = Temp;\r
+        }\r
+        while(Walker[0] == L' ') {\r
+          Walker++;\r
+        }\r
+      }\r
+\r
+      if (ShellStatus == SHELL_SUCCESS) {\r
+        //\r
+        // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.  \r
+        // Re-allocate with the added information.\r
+        //\r
+        KeyOptionBuffer = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption);\r
+        if (KeyOptionBuffer == NULL) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle);\r
+          ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+        }\r
+      }\r
+      for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {\r
+        //\r
+        // ScanCode\r
+        //\r
+        Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
+        if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }\r
+        ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;\r
+        Temp = StrStr(Walker, L" ");\r
+        if (Temp != NULL) {\r
+          Walker = Temp;\r
+        }\r
+        while(Walker[0] == L' ') {\r
+          Walker++;\r
+        }\r
+\r
+        //\r
+        // UnicodeChar\r
+        //\r
+        Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);\r
+        if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, Walker);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }\r
+        ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;\r
+        Temp = StrStr(Walker, L" ");\r
+        if (Temp != NULL) {\r
+          Walker = Temp;\r
+        }\r
+        while(Walker[0] == L' ') {\r
+          Walker++;\r
+        }\r
+      }\r
+\r
+      if (ShellStatus == SHELL_SUCCESS) {\r
+        //\r
+        // Now do the BootOption / BootOptionCrc\r
+        //\r
+        ASSERT (OptionIndex <= OrderCount);\r
+        KeyOptionBuffer->BootOption    = CurrentOrder[OptionIndex];\r
+        Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);\r
+        if (EFI_ERROR(Status)) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"Option Index");\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }        \r
+      }\r
+\r
+      if (ShellStatus == SHELL_SUCCESS) {\r
+        for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex < 0xFFFF ; KeyIndex++) {\r
+          UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);\r
+          Status = gRT->GetVariable(\r
+              VariableName,\r
+              (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+              NULL,\r
+              (UINTN*)&Intermediate,\r
+              NULL);\r
+          if (Status == EFI_NOT_FOUND) {\r
+            break;\r
+          }\r
+        }\r
+        Status = gRT->SetVariable(\r
+          VariableName,\r
+          (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,\r
+          sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),\r
+          KeyOptionBuffer);\r
+        if (EFI_ERROR(Status)) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }   \r
+        ASSERT(FileName == NULL && Data == NULL);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Shouldn't be possible to have have both. Neither is ok though.\r
+  //\r
+  ASSERT(FileName == NULL || Data == NULL);\r
+\r
+  if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {\r
+    if (FileName != NULL) {\r
+      //\r
+      // Open the file and populate the data buffer.\r
+      //\r
+      Status = ShellOpenFileByName(\r
+        FileName,\r
+        &FileHandle,\r
+        EFI_FILE_MODE_READ,\r
+        0);\r
+      if (!EFI_ERROR(Status)) {\r
+        Status = ShellGetFileSize(FileHandle, &Intermediate);\r
+      }\r
+      Data = AllocateZeroPool((UINTN)Intermediate);\r
+      if (Data == NULL) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle);\r
+        ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+      }\r
+      if (!EFI_ERROR(Status)) {\r
+        Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);\r
+      }\r
+    } else {\r
+      Intermediate = StrSize(Data);\r
+    }\r
+\r
+    if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {\r
+      Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);\r
+      if (EFI_ERROR(Status)) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      }   \r
+    }\r
+    if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    }   \r
+  }\r
+\r
+  SHELL_FREE_NON_NULL(Data);\r
+  SHELL_FREE_NON_NULL(KeyOptionBuffer);\r
+  SHELL_FREE_NON_NULL(FileName);\r
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  Function to dump the Bcfg information.\r
+\r
+  @param[in] Op             The operation.\r
+  @param[in] OrderCount     How many to dump.\r
+  @param[in] CurrentOrder   The pointer to the current order of items.\r
+  @param[in] VerboseOutput  TRUE for extra output.  FALSE otherwise.\r
+\r
+  @retval SHELL_SUCCESS           The dump was successful.\r
+  @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+BcfgDisplayDump(\r
+  IN CONST CHAR16   *Op,\r
+  IN CONST UINTN    OrderCount,\r
+  IN CONST UINT16   *CurrentOrder,\r
+  IN CONST BOOLEAN  VerboseOutput\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       *Buffer;\r
+  UINTN       BufferSize;\r
+  CHAR16      VariableName[12];\r
+  UINTN       LoopVar;\r
+  UINTN       LoopVar2;\r
+  CHAR16      *DevPathString;\r
+  VOID        *DevPath;\r
+\r
+  if (OrderCount == 0) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle);\r
+    return (SHELL_SUCCESS);\r
+  }\r
+\r
+  for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {\r
+    Buffer      = NULL;\r
+    BufferSize  = 0;\r
+    UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);\r
+\r
+    Status = gRT->GetVariable(\r
+        VariableName,\r
+        (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+        NULL,\r
+        &BufferSize,\r
+        Buffer);\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      Buffer = AllocateZeroPool(BufferSize);\r
+      Status = gRT->GetVariable(\r
+          VariableName,\r
+          (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+          NULL,\r
+          &BufferSize,\r
+          Buffer);\r
+    }\r
+\r
+    if (EFI_ERROR(Status) || Buffer == NULL) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, VariableName, Status);\r
+      return (SHELL_INVALID_PARAMETER);\r
+    }\r
+\r
+    if ((*(UINT16*)(Buffer+4)) != 0) {\r
+      DevPath = AllocateZeroPool(*(UINT16*)(Buffer+4));\r
+      if (DevPath == NULL) {\r
+        DevPathString = NULL;\r
+      } else {\r
+        CopyMem(DevPath, Buffer+6+StrSize((CHAR16*)(Buffer+6)), *(UINT16*)(Buffer+4));\r
+        DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);\r
+      }\r
+    } else {\r
+      DevPath       = NULL;\r
+      DevPathString = NULL;\r
+    }\r
+    ShellPrintHiiEx(\r
+      -1,\r
+      -1,\r
+      NULL,\r
+      STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),\r
+      gShellBcfgHiiHandle,\r
+      LoopVar,\r
+      VariableName,\r
+      (CHAR16*)(Buffer+6),\r
+      DevPathString,\r
+      (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6) <= BufferSize?L'N':L'Y');\r
+    if (VerboseOutput) {\r
+      for (LoopVar2 = (StrSize((CHAR16*)(Buffer+6)) + *(UINT16*)(Buffer+4) + 6);LoopVar2<BufferSize;LoopVar2++){\r
+        ShellPrintEx(\r
+          -1,\r
+          -1,\r
+          NULL,\r
+          L"%02x",\r
+          Buffer[LoopVar2]);\r
+      }\r
+      ShellPrintEx(\r
+        -1,\r
+        -1,\r
+        NULL,\r
+        L"\r\n");\r
+    }\r
+\r
+    if (Buffer != NULL) {\r
+      FreePool(Buffer);\r
+    }\r
+    if (DevPath != NULL) {\r
+      FreePool(DevPath);\r
+    }\r
+    if (DevPathString != NULL) {\r
+      FreePool(DevPathString);\r
+    }\r
+  }\r
+  return (SHELL_SUCCESS);\r
+}\r
+\r
+/**\r
+  Function to initialize the BCFG operation structure.\r
+\r
+  @param[in] Struct   The stuct to initialize.\r
+**/\r
+VOID\r
+EFIAPI\r
+InitBcfgStruct(\r
+  IN BGFG_OPERATION *Struct\r
+  )\r
+{\r
+  ASSERT(Struct != NULL);\r
+  Struct->Target      = BcfgTargetMax;\r
+  Struct->Type        = BcfgTypeMax;\r
+  Struct->Number1     = 0;\r
+  Struct->Number2     = 0;\r
+  Struct->HandleIndex = 0;\r
+  Struct->FileName    = NULL;\r
+  Struct->Description = NULL;\r
+  Struct->Order       = NULL;\r
+  Struct->OptData     = NULL;\r
+}\r
+\r
+\r
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
+  {L"-v", TypeFlag},\r
+  {L"-opt", TypeMaxValue},\r
+  {NULL, TypeMax}\r
+  };\r
+\r
+/**\r
+  Function for 'bcfg' command.\r
+\r
+  @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
+  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunBcfg (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  LIST_ENTRY            *Package;\r
+  CHAR16                *ProblemParam;\r
+  SHELL_STATUS          ShellStatus;\r
+  UINTN                 ParamNumber;\r
+  CONST CHAR16          *CurrentParam;\r
+  BGFG_OPERATION        CurrentOperation;\r
+  UINTN                 Length;\r
+  UINT64                Intermediate;\r
+  UINT16                Count;\r
+\r
+  Length              = 0;\r
+  ProblemParam        = NULL;\r
+  Package             = NULL;\r
+  ShellStatus         = SHELL_SUCCESS;\r
+\r
+  InitBcfgStruct(&CurrentOperation);\r
+\r
+  //\r
+  // initialize the shell lib (we must be in non-auto-init...)\r
+  //\r
+  Status = ShellInitialize();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  Status = CommandInit();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // parse the command line\r
+  //\r
+  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
+  if (EFI_ERROR(Status)) {\r
+    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, ProblemParam);\r
+      FreePool(ProblemParam);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else {\r
+      ASSERT(FALSE);\r
+    }\r
+  } else {\r
+    //\r
+    // Read in if we are doing -OPT\r
+    //\r
+    if (ShellCommandLineGetFlag(Package, L"-opt")) {\r
+      CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");\r
+      if (CurrentOperation.OptData == NULL) {\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellBcfgHiiHandle, L"-opt");\r
+        ShellStatus = SHELL_INVALID_PARAMETER;\r
+      }\r
+      CurrentOperation.Type = BcfgTypeOpt;\r
+    }\r
+\r
+    //\r
+    // small block to read the target of the operation\r
+    //\r
+    if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||\r
+        (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)\r
+       ){\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {\r
+      CurrentOperation.Target = BcfgTargetDriverOrder;\r
+    } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {\r
+      CurrentOperation.Target = BcfgTargetBootOrder;\r
+    } else {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    }\r
+\r
+\r
+    //\r
+    // Read in the boot or driver order environment variable (not needed for opt)\r
+    //\r
+    if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {\r
+      Length = 0;\r
+      Status = gRT->GetVariable(\r
+        CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
+        (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+        NULL,\r
+        &Length,\r
+        CurrentOperation.Order);\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));\r
+        if (CurrentOperation.Order == NULL) {\r
+          ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+        } else {\r
+          Status = gRT->GetVariable(\r
+            CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",\r
+            (EFI_GUID*)&gEfiGlobalVariableGuid,\r
+            NULL,\r
+            &Length,\r
+            CurrentOperation.Order);\r
+        }\r
+      }\r
+    }\r
+\r
+    Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0]));\r
+\r
+    //\r
+    // large block to read the type of operation and verify parameter types for the info.\r
+    //\r
+    if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {\r
+      for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {\r
+        CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);\r
+        if        (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0)    {\r
+          CurrentOperation.Type = BcfgTypeDump;\r
+        } else if (ShellCommandLineGetFlag(Package, L"-v")) {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"-v (without dump)");\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0)     {\r
+          if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          }\r
+          CurrentOperation.Type = BcfgTypeAdd;\r
+          CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+          if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          } else {\r
+            Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+            CurrentOperation.Number1     = (UINT16)Intermediate;\r
+            ASSERT(CurrentOperation.FileName == NULL);\r
+            CurrentOperation.FileName    = StrnCatGrow(&CurrentOperation.FileName   , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
+            ASSERT(CurrentOperation.Description == NULL);\r
+            CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
+          }\r
+        } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0)    {\r
+          if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          }\r
+          CurrentOperation.Type = BcfgTypeAddp;\r
+          CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+          if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          } else {\r
+            Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+            CurrentOperation.Number1     = (UINT16)Intermediate;\r
+            ASSERT(CurrentOperation.FileName == NULL);\r
+            CurrentOperation.FileName    = StrnCatGrow(&CurrentOperation.FileName   , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
+            ASSERT(CurrentOperation.Description == NULL);\r
+            CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
+          }\r
+        } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0)    {\r
+          if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          }\r
+          CurrentOperation.Type = BcfgTypeAddh;\r
+          CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+          if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          } else {\r
+            Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+            CurrentOperation.Number1     = (UINT16)Intermediate;\r
+            CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+            if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+              ShellStatus = SHELL_INVALID_PARAMETER;\r
+            } else {\r
+              Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+              CurrentOperation.HandleIndex = (UINT16)Intermediate;\r
+              ASSERT(CurrentOperation.Description == NULL);\r
+              CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);\r
+            }\r
+          }\r
+        } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0)      {\r
+          if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          }\r
+          CurrentOperation.Type = BcfgTypeRm;\r
+          CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+          if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          } else {\r
+            Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+            CurrentOperation.Number1     = (UINT16)Intermediate;\r
+            if (CurrentOperation.Number1 > Count){\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
+              ShellStatus = SHELL_INVALID_PARAMETER;\r
+            }\r
+          }\r
+        } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0)      {\r
+          if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          }\r
+          CurrentOperation.Type = BcfgTypeMv;\r
+          CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+          if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+            ShellStatus = SHELL_INVALID_PARAMETER;\r
+          } else {\r
+            Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+            CurrentOperation.Number1     = (UINT16)Intermediate;\r
+            if (CurrentOperation.Number1 > Count){\r
+              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
+              ShellStatus = SHELL_INVALID_PARAMETER;\r
+            } else {\r
+              CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);\r
+              if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {\r
+                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+                ShellStatus = SHELL_INVALID_PARAMETER;\r
+              } else {\r
+                Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);\r
+                CurrentOperation.Number2     = (UINT16)Intermediate;\r
+              }\r
+              if (CurrentOperation.Number2 == CurrentOperation.Number1\r
+                ||CurrentOperation.Number2 >= Count\r
+               ){\r
+                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, Count);\r
+                ShellStatus = SHELL_INVALID_PARAMETER;\r
+              }\r
+            }\r
+          }\r
+        } else {\r
+          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, CurrentParam);\r
+          ShellStatus = SHELL_INVALID_PARAMETER;\r
+        }\r
+      }\r
+    }\r
+    if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {\r
+      //\r
+      // we have all the info.  Do the work\r
+      //\r
+      switch (CurrentOperation.Type) {\r
+        case   BcfgTypeDump:\r
+          ShellStatus = BcfgDisplayDump(\r
+            CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",\r
+            Count,\r
+            CurrentOperation.Order,\r
+            ShellCommandLineGetFlag(Package, L"-v"));\r
+          break;\r
+        case   BcfgTypeMv:\r
+          ShellStatus = BcfgMove(\r
+            CurrentOperation.Target,\r
+            CurrentOperation.Order,\r
+            Count,\r
+            CurrentOperation.Number1,\r
+            CurrentOperation.Number2);\r
+          break;\r
+        case   BcfgTypeRm:\r
+          ShellStatus = BcfgRemove(\r
+            CurrentOperation.Target,\r
+            CurrentOperation.Order,\r
+            Count,\r
+            CurrentOperation.Number1);\r
+          break;\r
+        case   BcfgTypeAdd:\r
+        case   BcfgTypeAddp:\r
+        case   BcfgTypeAddh:\r
+          ShellStatus = BcfgAdd(\r
+            CurrentOperation.Number1,\r
+            CurrentOperation.FileName,\r
+            CurrentOperation.Description==NULL?L"":CurrentOperation.Description,\r
+            CurrentOperation.Order,\r
+            Count,\r
+            CurrentOperation.Target,\r
+            (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),\r
+            (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),\r
+            CurrentOperation.HandleIndex);\r
+          break;\r
+        case   BcfgTypeOpt:\r
+          ShellStatus = BcfgAddOpt(\r
+            CurrentOperation.OptData,\r
+            CurrentOperation.Order,\r
+            Count,\r
+            CurrentOperation.Target);\r
+          break;\r
+        default:\r
+          ASSERT(FALSE);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Package != NULL) {\r
+    ShellCommandLineFreeVarList (Package);\r
+  }\r
+  if (CurrentOperation.FileName != NULL) {\r
+    FreePool(CurrentOperation.FileName);\r
+  }\r
+  if (CurrentOperation.Description != NULL) {\r
+    FreePool(CurrentOperation.Description);\r
+  }\r
+  if (CurrentOperation.Order != NULL) {\r
+    FreePool(CurrentOperation.Order);\r
+  }\r
+\r
+  return (ShellStatus);\r
+}\r
+\r
+\r
+/**\r
+  Function to get the filename with help context if HII will not be used.\r
+\r
+  @return   The filename with help text in it.\r
+**/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellCommandGetManFileNameBcfg (\r
+  VOID\r
+  )\r
+{\r
+  return (mFileName);\r
+}\r
+\r
+/**\r
+  "Constructor" for the library.\r
+\r
+  This will register the handler for the bcfg command.\r
+\r
+  @param[in] ImageHandle    the image handle of the process\r
+  @param[in] SystemTable    the EFI System Table pointer\r
+  @param[in] Name           the profile name to use\r
+\r
+  @retval EFI_SUCCESS        the shell command handlers were installed sucessfully\r
+  @retval EFI_UNSUPPORTED    the shell level required was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BcfgLibraryRegisterBcfgCommand (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable,\r
+  IN CONST CHAR16      *Name\r
+  )\r
+{\r
+  if (gShellBcfgHiiHandle) {\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);\r
+  if (gShellBcfgHiiHandle == NULL) {\r
+    return (EFI_DEVICE_ERROR);\r
+  }\r
+\r
+  //\r
+  // install our shell command handler\r
+  //\r
+  ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG));\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Destructor for the library.  free any resources.\r
+\r
+  @param ImageHandle            The image handle of the process.\r
+  @param SystemTable            The EFI System Table pointer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BcfgLibraryUnregisterBcfgCommand (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  if (gShellBcfgHiiHandle != NULL) {\r
+    HiiRemovePackages(gShellBcfgHiiHandle);\r
+  }\r
+  gShellBcfgHiiHandle = NULL;\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
new file mode 100644 (file)
index 0000000..596bb35
--- /dev/null
@@ -0,0 +1,46 @@
+##  @file\r
+#  Provides shell install1 functions\r
+#\r
+#  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved. <BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = UefiShellBcfgCommandLib\r
+  FILE_GUID                      = F6A3BF5D-4095-4E4F-9670-408770C2DBDF\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = BcfgCommandLib|UEFI_APPLICATION UEFI_DRIVER\r
+\r
+[Sources.common]\r
+  UefiShellBcfgCommandLib.c\r
+  UefiShellBcfgCommandLib.uni\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  ShellCommandLib\r
+  ShellLib\r
+  UefiLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  SortLib\r
+  PrintLib\r
+\r
+[Guids]\r
+  gShellBcfgHiiGuid\r
diff --git a/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni
new file mode 100644 (file)
index 0000000..2a3c232
Binary files /dev/null and b/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni differ
index 909dd7aa97f94889946b2572269b0185486097b2..90eb08ab85c4a8c494bed457583023d16acdcd0b 100644 (file)
@@ -46,6 +46,9 @@
   ## @libraryclass   Provides path manipulation functions\r
   PathLib|Include/Library/PathLib.h\r
 \r
+  ## @libraryclass   provides BCFG command\r
+  BcfgCommandLib|Include/Library/BcfgCommandLib.h\r
+\r
 [Guids]\r
   gEfiShellEnvironment2ExtGuid    = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}}\r
   gEfiShellPkgTokenSpaceGuid      = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}}\r
@@ -60,6 +63,7 @@
   gShellLevel2HiiGuid             = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae}}\r
   gShellLevel3HiiGuid             = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f}}\r
   gShellNetwork1HiiGuid           = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}\r
+  gShellBcfgHiiGuid               = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}}\r
 \r
 [Protocols]\r
   gEfiShellProtocolGuid               = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}}\r
index 3284c1cdc56a2e8aab256bd69392bad4e9cb78b6..39fe936f4e6919376eb493398f676191232d2879 100644 (file)
@@ -1,7 +1,7 @@
 ##  @file\r
 # Shell Package\r
 #\r
-# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #    This program and the accompanying materials\r
 #    are licensed and made available under the terms and conditions of the BSD License\r
@@ -49,6 +49,7 @@
   \r
   PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
   PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf\r
+  BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf\r
 \r
 [LibraryClasses.ARM]\r
   #\r