]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Move BdsDxe and GenericBdsLib to IntelFrameworkModulePkg, these modules need dependen...
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 23 Jan 2009 07:24:55 +0000 (07:24 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 23 Jan 2009 07:24:55 +0000 (07:24 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7354 6f19259b-4bc3-4df7-8a09-765794883524

51 files changed:
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Language.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Language.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/String.c [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/String.h [new file with mode: 0644]
IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni [new file with mode: 0644]

index 03e93e548465b7509a23b982ba5e1542076ef55b..a890146ed302f6b9b331c5ad9088c99239111300 100644 (file)
   S3Lib|IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf\r
   RecoveryLib|IntelFrameworkModulePkg/Library/PeiRecoveryLib/PeiRecoveryLib.inf\r
   DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+  IfrSupportLib|MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrSupportLib.inf\r
+  ExtendedIfrSupportLib|MdeModulePkg/Library/ExtendedIfrSupportLib/ExtendedIfrSupportLib.inf\r
+  GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+  ExtendedHiiLib|MdeModulePkg/Library/ExtendedHiiLib/ExtendedHiiLib.inf\r
+  PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf\r
   \r
 [LibraryClasses.common.PEIM]\r
   HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
   IntelFrameworkModulePkg/Library/SmmRuntimeDxeReportStatusCodeLibFramework/SmmRuntimeDxeReportStatusCodeLibFramework.inf\r
   IntelFrameworkModulePkg/Library/BaseReportStatusCodeLib/BaseReportStatusCodeLib.inf\r
   IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf\r
-\r
+  IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+  \r
   IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
   IntelFrameworkModulePkg/Universal/PcatSingleSegmentPciCfgPei/PcatSingleSegmentPciCfgPei.inf\r
   IntelFrameworkModulePkg/Universal/VariablePei/VariablePei.inf\r
   IntelFrameworkModulePkg/Universal/Legacy8259Dxe/8259.inf\r
-\r
+  IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf\r
+  \r
 [Components.IA32]\r
   IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DxeStatusCode.inf\r
 \r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c
new file mode 100644 (file)
index 0000000..d273e3f
--- /dev/null
@@ -0,0 +1,1911 @@
+/** @file\r
+  BDS Lib functions which relate with create or process the boot option.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+BOOLEAN mEnumBootDevice = FALSE;\r
+\r
+///\r
+/// This GUID is used for an EFI Variable that stores the front device pathes\r
+/// for a partial device path that starts with the HD node.\r
+///\r
+EFI_GUID  mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
+\r
+\r
+\r
+/**\r
+  Boot the legacy system with the boot option\r
+\r
+  @param  Option                 The legacy boot option which have BBS device path\r
+\r
+  @retval EFI_UNSUPPORTED        There is no legacybios protocol, do not support\r
+                                 legacy boot.\r
+  @retval EFI_STATUS             Return the status of LegacyBios->LegacyBoot ().\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDoLegacyBoot (\r
+  IN  BDS_COMMON_OPTION           *Option\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // If no LegacyBios protocol we do not support legacy boot\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Notes: if we separate the int 19, then we don't need to refresh BBS\r
+  //\r
+  BdsRefreshBbsTableForBoot (Option);\r
+\r
+  //\r
+  // Write boot to OS performance data to a file\r
+  //\r
+  PERF_CODE (\r
+    WriteBootToOsPerformanceData ();\r
+  );\r
+\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Legacy Boot: %S\n", Option->Description));\r
+  return LegacyBios->LegacyBoot (\r
+                      LegacyBios,\r
+                      (BBS_BBS_DEVICE_PATH *) Option->DevicePath,\r
+                      Option->LoadOptionsSize,\r
+                      Option->LoadOptions\r
+                      );\r
+}\r
+\r
+\r
+/**\r
+  Process the boot option follow the UEFI specification and\r
+  special treat the legacy boot option with BBS_DEVICE_PATH.\r
+\r
+  @param  Option                 The boot option need to be processed\r
+  @param  DevicePath             The device path which describe where to load the\r
+                                 boot image or the legacy BBS device path to boot\r
+                                 the legacy OS\r
+  @param  ExitDataSize           The size of exit data.\r
+  @param  ExitData               Data returned when Boot image failed.\r
+\r
+  @retval EFI_SUCCESS            Boot from the input boot option successfully.\r
+  @retval EFI_NOT_FOUND          If the Device Path is not found in the system\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBootViaBootOption (\r
+  IN  BDS_COMMON_OPTION             *Option,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath,\r
+  OUT UINTN                         *ExitDataSize,\r
+  OUT CHAR16                        **ExitData OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                Handle;\r
+  EFI_HANDLE                ImageHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *WorkingDevicePath;\r
+  EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
+  LIST_ENTRY                TempBootLists;\r
+\r
+  //\r
+  // Record the performance data for End of BDS\r
+  //\r
+  PERF_END (0, BDS_TOK, NULL, 0);\r
+\r
+  *ExitDataSize = 0;\r
+  *ExitData     = NULL;\r
+\r
+  //\r
+  // Notes: put EFI64 ROM Shadow Solution\r
+  //\r
+  EFI64_SHADOW_ALL_LEGACY_ROM ();\r
+\r
+  //\r
+  // Notes: this code can be remove after the s3 script table\r
+  // hook on the event EVT_SIGNAL_READY_TO_BOOT or\r
+  // EVT_SIGNAL_LEGACY_BOOT\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, (VOID **) &AcpiS3Save);\r
+  if (!EFI_ERROR (Status)) {\r
+    AcpiS3Save->S3Save (AcpiS3Save, NULL);\r
+  }\r
+  //\r
+  // If it's Device Path that starts with a hard drive path, append it with the front part to compose a\r
+  // full device path\r
+  //\r
+  WorkingDevicePath = NULL;\r
+  if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+      (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {\r
+    WorkingDevicePath = BdsExpandPartitionPartialDevicePathToFull (\r
+                          (HARDDRIVE_DEVICE_PATH *)DevicePath\r
+                          );\r
+    if (WorkingDevicePath != NULL) {\r
+      DevicePath = WorkingDevicePath;\r
+    }\r
+  }\r
+  //\r
+  // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
+  //\r
+  EfiSignalEventReadyToBoot();\r
+  \r
+  \r
+  //\r
+  // Set Boot Current\r
+  //\r
+  gRT->SetVariable (\r
+        L"BootCurrent",\r
+        &gEfiGlobalVariableGuid,\r
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+        sizeof (UINT16),\r
+        &Option->BootCurrent\r
+        );\r
+\r
+  ASSERT (Option->DevicePath != NULL);\r
+  if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
+      (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
+    ) {\r
+    //\r
+    // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
+    //\r
+    return BdsLibDoLegacyBoot (Option);\r
+  }\r
+\r
+  //\r
+  // If the boot option point to Internal FV shell, make sure it is valid\r
+  //\r
+  Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);\r
+  if (!EFI_ERROR(Status)) {\r
+    if (Option->DevicePath != NULL) {\r
+      FreePool(Option->DevicePath);\r
+    }\r
+    Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+    ASSERT(Option->DevicePath != NULL);\r
+    CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+    //\r
+    // Update the shell boot option\r
+    //\r
+    InitializeListHead (&TempBootLists);\r
+    BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+    \r
+    //\r
+    // free the temporary device path created by BdsLibUpdateFvFileDevicePath()\r
+    //\r
+    FreePool (DevicePath); \r
+    DevicePath = Option->DevicePath;\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
+\r
+  Status = gBS->LoadImage (\r
+                  TRUE,\r
+                  mBdsImageHandle,\r
+                  DevicePath,\r
+                  NULL,\r
+                  0,\r
+                  &ImageHandle\r
+                  );\r
+\r
+  //\r
+  // If we didn't find an image directly, we need to try as if it is a removable device boot opotion\r
+  // and load the image according to the default boot behavior for removable device.\r
+  //\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // check if there is a bootable removable media could be found in this device path ,\r
+    // and get the bootable media handle\r
+    //\r
+    Handle = BdsLibGetBootableHandle(DevicePath);\r
+    if (Handle == NULL) {\r
+       goto Done;\r
+    }\r
+    //\r
+    // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+    //  machinename is ia32, ia64, x64, ...\r
+    //\r
+    FilePath = FileDevicePath (Handle, (CONST CHAR16*)PcdGetPtr(PcdDefaultBootFileName));\r
+    if (FilePath != NULL) {\r
+      Status = gBS->LoadImage (\r
+                      TRUE,\r
+                      mBdsImageHandle,\r
+                      FilePath,\r
+                      NULL,\r
+                      0,\r
+                      &ImageHandle\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // The DevicePath failed, and it's not a valid\r
+        // removable media device.\r
+        //\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // It there is any error from the Boot attempt exit now.\r
+    //\r
+    goto Done;\r
+  }\r
+  //\r
+  // Provide the image with it's load options\r
+  //\r
+  Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  if (Option->LoadOptionsSize != 0) {\r
+    ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;\r
+    ImageInfo->LoadOptions      = Option->LoadOptions;\r
+  }\r
+  //\r
+  // Before calling the image, enable the Watchdog Timer for\r
+  // the 5 Minute period\r
+  //\r
+  gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+  Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
+\r
+  //\r
+  // Clear the Watchdog Timer after the image returns\r
+  //\r
+  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+\r
+Done:\r
+  //\r
+  // Clear Boot Current\r
+  //\r
+  gRT->SetVariable (\r
+        L"BootCurrent",\r
+        &gEfiGlobalVariableGuid,\r
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+        0,\r
+        &Option->BootCurrent\r
+        );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Expand a device path that starts with a hard drive media device path node to be a\r
+  full device path that includes the full hardware path to the device. We need\r
+  to do this so it can be booted. As an optimization the front match (the part point\r
+  to the partition node. E.g. ACPI() /PCI()/ATA()/Partition() ) is saved in a variable\r
+  so a connect all is not required on every boot. All successful history device path\r
+  which point to partition node (the front part) will be saved.\r
+\r
+  @param  HardDriveDevicePath    EFI Device Path to boot, if it starts with a hard\r
+                                 drive media device path.\r
+  @return A Pointer to the full device path or NULL if a valid Hard Drive devic path\r
+          cannot be found.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsExpandPartitionPartialDevicePathToFull (\r
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     BlockIoHandleCount;\r
+  EFI_HANDLE                *BlockIoBuffer;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FullDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *BlockIoDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     Index;\r
+  UINTN                     InstanceNum;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CachedDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  UINTN                     CachedDevicePathSize;\r
+  BOOLEAN                   DeviceExist;\r
+  BOOLEAN                   NeedAdjust;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  UINTN                     Size;\r
+\r
+  FullDevicePath = NULL;\r
+  //\r
+  // Check if there is prestore 'HDDP' variable.\r
+  // If exist, search the front path which point to partition node in the variable instants.\r
+  // If fail to find or 'HDDP' not exist, reconnect all and search in all system\r
+  //\r
+  CachedDevicePath = BdsLibGetVariableAndSize (\r
+                      L"HDDP",\r
+                      &mHdBootVariablePrivateGuid,\r
+                      &CachedDevicePathSize\r
+                      );\r
+                      \r
+  if (CachedDevicePath != NULL) {\r
+    TempNewDevicePath = CachedDevicePath;\r
+    DeviceExist = FALSE;\r
+    NeedAdjust = FALSE;\r
+    do {\r
+      //\r
+      // Check every instance of the variable\r
+      // First, check whether the instance contain the partition node, which is needed for distinguishing  multi\r
+      // partial partition boot option. Second, check whether the instance could be connected.\r
+      //\r
+      Instance  = GetNextDevicePathInstance (&TempNewDevicePath, &Size);\r
+      if (MatchPartitionDevicePathNode (Instance, HardDriveDevicePath)) {\r
+        //\r
+        // Connect the device path instance, the device path point to hard drive media device path node\r
+        // e.g. ACPI() /PCI()/ATA()/Partition()\r
+        //\r
+        Status = BdsLibConnectDevicePath (Instance);\r
+        if (!EFI_ERROR (Status)) {\r
+          DeviceExist = TRUE;\r
+          break;\r
+        }\r
+      }\r
+      //\r
+      // Come here means the first instance is not matched\r
+      //\r
+      NeedAdjust = TRUE;\r
+      FreePool(Instance);\r
+    } while (TempNewDevicePath != NULL);\r
+\r
+    if (DeviceExist) {\r
+      //\r
+      // Find the matched device path.\r
+      // Append the file path information from the boot option and return the fully expanded device path.\r
+      //\r
+      DevicePath     = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+      FullDevicePath = AppendDevicePath (Instance, DevicePath);\r
+\r
+      //\r
+      // Adjust the 'HDDP' instances sequence if the matched one is not first one.\r
+      //\r
+      if (NeedAdjust) {\r
+        //\r
+        // First delete the matched instance.\r
+        //\r
+        TempNewDevicePath = CachedDevicePath;\r
+        CachedDevicePath  = BdsLibDelPartMatchInstance (CachedDevicePath, Instance );\r
+        FreePool (TempNewDevicePath);\r
+        \r
+        //\r
+        // Second, append the remaining path after the matched instance\r
+        //\r
+        TempNewDevicePath = CachedDevicePath;\r
+        CachedDevicePath = AppendDevicePathInstance (Instance, CachedDevicePath );\r
+        FreePool (TempNewDevicePath);\r
+        //\r
+        // Save the matching Device Path so we don't need to do a connect all next time\r
+        //\r
+        Status = gRT->SetVariable (\r
+                        L"HDDP",\r
+                        &mHdBootVariablePrivateGuid,\r
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                        GetDevicePathSize (CachedDevicePath),\r
+                        CachedDevicePath\r
+                        );\r
+      }\r
+      \r
+      FreePool (Instance);\r
+      FreePool (CachedDevicePath);\r
+      return FullDevicePath;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If we get here we fail to find or 'HDDP' not exist, and now we need\r
+  // to search all devices in the system for a matched partition\r
+  //\r
+  BdsLibConnectAllDriversToAllControllers ();\r
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+  if (EFI_ERROR (Status) || BlockIoHandleCount == 0 || BlockIoBuffer == NULL) {\r
+    //\r
+    // If there was an error or there are no device handles that support\r
+    // the BLOCK_IO Protocol, then return.\r
+    //\r
+    return NULL;\r
+  }\r
+  //\r
+  // Loop through all the device handles that support the BLOCK_IO Protocol\r
+  //\r
+  for (Index = 0; Index < BlockIoHandleCount; Index++) {\r
+\r
+    Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath);\r
+    if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) {\r
+      continue;\r
+    }\r
+\r
+    if (MatchPartitionDevicePathNode (BlockIoDevicePath, HardDriveDevicePath)) {\r
+      //\r
+      // Find the matched partition device path\r
+      //\r
+      DevicePath    = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath);\r
+      FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
+\r
+      //\r
+      // Save the matched partition device path in 'HDDP' variable\r
+      //\r
+      if (CachedDevicePath != NULL) {\r
+        //\r
+        // Save the matched partition device path as first instance of 'HDDP' variable\r
+        //\r
+        if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {\r
+          TempNewDevicePath = CachedDevicePath;\r
+          CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);\r
+          FreePool(TempNewDevicePath);\r
+\r
+          TempNewDevicePath = CachedDevicePath;\r
+          CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+          FreePool(TempNewDevicePath);\r
+        } else {\r
+          TempNewDevicePath = CachedDevicePath;\r
+          CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
+          FreePool(TempNewDevicePath);\r
+        }\r
+        //\r
+        // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
+        // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.\r
+        //\r
+        InstanceNum = 0;\r
+        ASSERT (CachedDevicePath != NULL);\r
+        TempNewDevicePath = CachedDevicePath;\r
+        while (!IsDevicePathEnd (TempNewDevicePath)) {\r
+          TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+          //\r
+          // Parse one instance\r
+          //\r
+          while (!IsDevicePathEndType (TempNewDevicePath)) {\r
+            TempNewDevicePath = NextDevicePathNode (TempNewDevicePath);\r
+          }\r
+          InstanceNum++;\r
+          //\r
+          // If the CachedDevicePath variable contain too much instance, only remain 12 instances.\r
+          //\r
+          if (InstanceNum >= 12) {\r
+            SetDevicePathEndNode (TempNewDevicePath);\r
+            break;\r
+          }\r
+        }\r
+      } else {\r
+        CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
+      }\r
+\r
+      //\r
+      // Save the matching Device Path so we don't need to do a connect all next time\r
+      //\r
+      Status = gRT->SetVariable (\r
+                      L"HDDP",\r
+                      &mHdBootVariablePrivateGuid,\r
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                      GetDevicePathSize (CachedDevicePath),\r
+                      CachedDevicePath\r
+                      );\r
+\r
+      break;\r
+    }\r
+  }\r
+  \r
+  FreePool (CachedDevicePath);\r
+  if (BlockIoBuffer != NULL) {\r
+    FreePool (BlockIoBuffer);\r
+  }\r
+  return FullDevicePath;\r
+}\r
+\r
+/**\r
+  Check whether there is a instance in BlockIoDevicePath, which contain multi device path\r
+  instances, has the same partition node with HardDriveDevicePath device path\r
+\r
+  @param  BlockIoDevicePath      Multi device path instances which need to check\r
+  @param  HardDriveDevicePath    A device path which starts with a hard drive media\r
+                                 device path.\r
+\r
+  @retval TRUE                   There is a matched device path instance.\r
+  @retval FALSE                  There is no matched device path instance.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+MatchPartitionDevicePathNode (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL   *BlockIoDevicePath,\r
+  IN  HARDDRIVE_DEVICE_PATH      *HardDriveDevicePath\r
+  )\r
+{\r
+  HARDDRIVE_DEVICE_PATH     *TmpHdPath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   Match;\r
+  EFI_DEVICE_PATH_PROTOCOL  *BlockIoHdDevicePathNode;\r
+\r
+  if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
+    return FALSE;\r
+  }\r
+  \r
+  //\r
+  // Make PreviousDevicePath == the device path node before the end node\r
+  //\r
+  DevicePath              = BlockIoDevicePath;\r
+  BlockIoHdDevicePathNode = NULL;\r
+\r
+  //\r
+  // find the partition device path node\r
+  //\r
+  while (!IsDevicePathEnd (DevicePath)) {\r
+    if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&\r
+        (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)\r
+        ) {\r
+      BlockIoHdDevicePathNode = DevicePath;\r
+      break;\r
+    }\r
+\r
+    DevicePath = NextDevicePathNode (DevicePath);\r
+  }\r
+\r
+  if (BlockIoHdDevicePathNode == NULL) {\r
+    return FALSE;\r
+  }\r
+  //\r
+  // See if the harddrive device path in blockio matches the orig Hard Drive Node\r
+  //\r
+  TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;\r
+  Match = FALSE;\r
+  \r
+  //\r
+  // Check for the match\r
+  //\r
+  if ((TmpHdPath->MBRType == HardDriveDevicePath->MBRType) &&\r
+      (TmpHdPath->SignatureType == HardDriveDevicePath->SignatureType)) {\r
+    switch (TmpHdPath->SignatureType) {\r
+    case SIGNATURE_TYPE_GUID:\r
+      Match = CompareGuid ((EFI_GUID *)TmpHdPath->Signature, (EFI_GUID *)HardDriveDevicePath->Signature);\r
+      break;\r
+    case SIGNATURE_TYPE_MBR:\r
+      Match = (BOOLEAN)(*((UINT32 *)(&(TmpHdPath->Signature[0]))) == ReadUnaligned32((UINT32 *)(&(HardDriveDevicePath->Signature[0]))));\r
+      break;\r
+    default:\r
+      Match = FALSE;\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Match;\r
+}\r
+\r
+/**\r
+  Delete the boot option associated with the handle passed in.\r
+\r
+  @param  Handle                 The handle which present the device path to create\r
+                                 boot option\r
+\r
+  @retval EFI_SUCCESS            Delete the boot option success\r
+  @retval EFI_NOT_FOUND          If the Device Path is not found in the system\r
+  @retval EFI_OUT_OF_RESOURCES   Lack of memory resource\r
+  @retval Other                  Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsLibDeleteOptionFromHandle (\r
+  IN  EFI_HANDLE                 Handle\r
+  )\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOrderSize;\r
+  UINTN                     BootOptionSize;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  UINT16                    BootOption[BOOT_OPTION_MAX_CHAR];\r
+  UINTN                     DevicePathSize;\r
+  UINTN                     OptionDevicePathSize;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;\r
+  UINT8                     *TempPtr;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  BootOrder     = NULL;\r
+  BootOrderSize = 0;\r
+\r
+  //\r
+  // Check "BootOrder" variable, if no, means there is no any boot order.\r
+  //\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (BootOrder == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Convert device handle to device path protocol instance\r
+  //\r
+  DevicePath = DevicePathFromHandle (Handle);\r
+  if (DevicePath == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  DevicePathSize = GetDevicePathSize (DevicePath);\r
+\r
+  //\r
+  // Loop all boot order variable and find the matching device path\r
+  //\r
+  Index = 0;\r
+  while (Index < BootOrderSize / sizeof (UINT16)) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+                      \r
+    if (BootOptionVar == NULL) {\r
+      FreePool (BootOrder);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TempPtr = BootOptionVar;\r
+    TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+    TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+    OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+    OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);\r
+\r
+    //\r
+    // Check whether the device path match\r
+    //\r
+    if ((OptionDevicePathSize == DevicePathSize) &&\r
+        (CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {\r
+      BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
+      FreePool (BootOptionVar);\r
+      break;\r
+    }\r
+\r
+    FreePool (BootOptionVar);\r
+    Index++;\r
+  }\r
+\r
+  //\r
+  // Adjust number of boot option for "BootOrder" variable.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  BootOrderSize,\r
+                  BootOrder\r
+                  );\r
+\r
+  FreePool (BootOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Delete all invalid EFI boot options. The probable invalid boot option could\r
+  be Removable media or Network boot device.\r
+\r
+  @retval EFI_SUCCESS            Delete all invalid boot option success\r
+  @retval EFI_NOT_FOUND          Variable "BootOrder" is not found\r
+  @retval EFI_OUT_OF_RESOURCES   Lack of memory resource\r
+  @retval Other                  Error return value from SetVariable()\r
+\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidEfiBootOption (\r
+  VOID\r
+  )\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOrderSize;\r
+  UINTN                     BootOptionSize;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINT16                    BootOption[BOOT_OPTION_MAX_CHAR];\r
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;\r
+  UINT8                     *TempPtr;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  BootOrder     = NULL;\r
+  BootOrderSize = 0;\r
+\r
+  //\r
+  // Check "BootOrder" variable firstly, this variable hold the number of boot options\r
+  //\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Index = 0;\r
+  while (Index < BootOrderSize / sizeof (UINT16)) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      FreePool (BootOrder);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TempPtr = BootOptionVar;\r
+    TempPtr += sizeof (UINT32) + sizeof (UINT16);\r
+    TempPtr += StrSize ((CHAR16 *) TempPtr);\r
+    OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+    //\r
+    // Skip legacy boot option (BBS boot device)\r
+    //\r
+    if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&\r
+        (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {\r
+      FreePool (BootOptionVar);\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    if (!BdsLibIsValidEFIBootOptDevicePath (OptionDevicePath, FALSE)) {\r
+      //\r
+      // Delete this invalid boot option "Boot####"\r
+      //\r
+      Status = gRT->SetVariable (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                      0,\r
+                      NULL\r
+                      );\r
+      //\r
+      // Mark this boot option in boot order as deleted\r
+      //\r
+      BootOrder[Index] = 0xffff;\r
+    }\r
+\r
+    FreePool (BootOptionVar);\r
+    Index++;\r
+  }\r
+\r
+  //\r
+  // Adjust boot order array\r
+  //\r
+  Index2 = 0;\r
+  for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+    if (BootOrder[Index] != 0xffff) {\r
+      BootOrder[Index2] = BootOrder[Index];\r
+      Index2 ++;\r
+    }\r
+  }\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  Index2 * sizeof (UINT16),\r
+                  BootOrder\r
+                  );\r
+\r
+  FreePool (BootOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function will enumerate all possible boot device in the system,\r
+  it will only execute once of every boot.\r
+\r
+  @param  BdsBootOptionList      The header of the link list which indexed all\r
+                                 current boot options\r
+\r
+  @retval EFI_SUCCESS            Finished all the boot device enumerate and create\r
+                                 the boot option base on that boot device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibEnumerateAllBootOption (\r
+  IN OUT LIST_ENTRY          *BdsBootOptionList\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINT16                        FloppyNumber;\r
+  UINT16                        CdromNumber;\r
+  UINT16                        UsbNumber;\r
+  UINT16                        MiscNumber;\r
+  UINT16                        NonBlockNumber;\r
+  UINTN                         NumberBlockIoHandles;\r
+  EFI_HANDLE                    *BlockIoHandles;\r
+  EFI_BLOCK_IO_PROTOCOL         *BlkIo;\r
+  UINTN                         Index;\r
+  UINTN                         NumberSimpleNetworkHandles;\r
+  EFI_HANDLE                    *SimpleNetworkHandles;\r
+  UINTN                         FvHandleCount;\r
+  EFI_HANDLE                    *FvHandleBuffer;\r
+  EFI_FV_FILETYPE               Type;\r
+  UINTN                         Size;\r
+  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
+  UINT32                        AuthenticationStatus;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
+  UINTN                         DevicePathType;\r
+  CHAR16                        Buffer[40];\r
+  EFI_HANDLE                    *FileSystemHandles;\r
+  UINTN                         NumberFileSystemHandles;\r
+  BOOLEAN                       NeedDelete;\r
+  EFI_IMAGE_DOS_HEADER          DosHeader;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+\r
+  FloppyNumber  = 0;\r
+  CdromNumber   = 0;\r
+  UsbNumber     = 0;\r
+  MiscNumber    = 0;\r
+  ZeroMem (Buffer, sizeof (Buffer));\r
+  \r
+  //\r
+  // If the boot device enumerate happened, just get the boot\r
+  // device from the boot order variable\r
+  //\r
+  if (mEnumBootDevice) {\r
+    BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // Notes: this dirty code is to get the legacy boot option from the\r
+  // BBS table and create to variable as the EFI boot option, it should\r
+  // be removed after the CSM can provide legacy boot option directly\r
+  //\r
+  REFRESH_LEGACY_BOOT_OPTIONS;\r
+\r
+  //\r
+  // Delete invalid boot option\r
+  //\r
+  BdsDeleteAllInvalidEfiBootOption ();\r
+  \r
+  //\r
+  // Parse removable media\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+        ByProtocol,\r
+        &gEfiBlockIoProtocolGuid,\r
+        NULL,\r
+        &NumberBlockIoHandles,\r
+        &BlockIoHandles\r
+        );\r
+        \r
+  for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    BlockIoHandles[Index],\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    (VOID **) &BlkIo\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      if (!BlkIo->Media->RemovableMedia) {\r
+        //\r
+        // skip the non-removable block devices\r
+        //\r
+        continue;\r
+      }\r
+    }\r
+    DevicePath  = DevicePathFromHandle (BlockIoHandles[Index]);\r
+    DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
+\r
+    switch (DevicePathType) {\r
+    case BDS_EFI_ACPI_FLOPPY_BOOT:\r
+      if (FloppyNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Floppy %d", FloppyNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+      FloppyNumber++;\r
+      break;\r
+\r
+    case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
+      if (CdromNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI DVD/CDROM %d", CdromNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+      CdromNumber++;\r
+      break;\r
+\r
+    case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
+      if (UsbNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI USB Device %d", UsbNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+      UsbNumber++;\r
+      break;\r
+\r
+    case BDS_EFI_MESSAGE_SCSI_BOOT:\r
+      if (UsbNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI SCSI Device %d", UsbNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+      UsbNumber++;\r
+      break;\r
+\r
+    case BDS_EFI_MESSAGE_MISC_BOOT:\r
+      if (MiscNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Misc Device %d", MiscNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
+      MiscNumber++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (NumberBlockIoHandles != 0) {\r
+    FreePool (BlockIoHandles);\r
+  }\r
+\r
+  //\r
+  // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.\r
+  //\r
+  NonBlockNumber = 0;\r
+  gBS->LocateHandleBuffer (\r
+        ByProtocol,\r
+        &gEfiSimpleFileSystemProtocolGuid,\r
+        NULL,\r
+        &NumberFileSystemHandles,\r
+        &FileSystemHandles\r
+        );\r
+  for (Index = 0; Index < NumberFileSystemHandles; Index++) {\r
+    Status = gBS->HandleProtocol (\r
+                    FileSystemHandles[Index],\r
+                    &gEfiBlockIoProtocolGuid,\r
+                    (VOID **) &BlkIo\r
+                    );\r
+     if (!EFI_ERROR (Status)) {\r
+      //\r
+      //  Skip if the file system handle supports a BlkIo protocol,\r
+      //\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
+    //  machinename is ia32, ia64, x64, ...\r
+    //\r
+    Hdr.Union = &HdrData;\r
+    NeedDelete = TRUE;\r
+    Status     = BdsLibGetImageHeader (\r
+                   FileSystemHandles[Index],\r
+                   (CHAR16*)PcdGetPtr (PcdDefaultBootFileName),\r
+                   &DosHeader,\r
+                   Hdr\r
+                   );\r
+    if (!EFI_ERROR (Status) &&\r
+        EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+        Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+      NeedDelete = FALSE;\r
+    }\r
+\r
+    if (NeedDelete) {\r
+      //\r
+      // No such file or the file is not a EFI application, delete this boot option\r
+      //\r
+      BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
+    } else {\r
+      if (NonBlockNumber == 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device");\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);\r
+      }\r
+      BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
+      NonBlockNumber++;\r
+    }\r
+  }\r
+\r
+  if (NumberFileSystemHandles != 0) {\r
+    FreePool (FileSystemHandles);\r
+  }\r
+\r
+  //\r
+  // Parse Network Boot Device\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+        ByProtocol,\r
+        &gEfiSimpleNetworkProtocolGuid,\r
+        NULL,\r
+        &NumberSimpleNetworkHandles,\r
+        &SimpleNetworkHandles\r
+        );\r
+  for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {\r
+    if (Index == 0) {\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network");\r
+    } else {\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Network %d", Index);\r
+    }\r
+    BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);\r
+  }\r
+\r
+  if (NumberSimpleNetworkHandles != 0) {\r
+    FreePool (SimpleNetworkHandles);\r
+  }\r
+\r
+  //\r
+  // Check if we have on flash shell\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+        ByProtocol,\r
+        &gEfiFirmwareVolume2ProtocolGuid,\r
+        NULL,\r
+        &FvHandleCount,\r
+        &FvHandleBuffer\r
+        );\r
+  for (Index = 0; Index < FvHandleCount; Index++) {\r
+    //\r
+    // Only care the dispatched FV. If no dispatch protocol on the FV, it is not dispatched, then skip it.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    FvHandleBuffer[Index],\r
+                    &gEfiFirmwareVolumeDispatchProtocolGuid,\r
+                    (VOID **) &Fv\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+    \r
+    gBS->HandleProtocol (\r
+          FvHandleBuffer[Index],\r
+          &gEfiFirmwareVolume2ProtocolGuid,\r
+          (VOID **) &Fv\r
+          );\r
+\r
+    Status = Fv->ReadFile (\r
+                  Fv,\r
+                  &gEfiShellFileGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  &Type,\r
+                  &Attributes,\r
+                  &AuthenticationStatus\r
+                  );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Skip if no shell file in the FV\r
+      //\r
+      continue;\r
+    }\r
+    //\r
+    // Build the shell boot option\r
+    //\r
+    BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);\r
+  }\r
+\r
+  if (FvHandleCount != 0) {\r
+    FreePool (FvHandleBuffer);\r
+  }\r
+  //\r
+  // Make sure every boot only have one time\r
+  // boot device enumerate\r
+  //\r
+  BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+  mEnumBootDevice = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build the boot option with the handle parsed in\r
+\r
+  @param  Handle                 The handle which present the device path to create\r
+                                 boot option\r
+  @param  BdsBootOptionList      The header of the link list which indexed all\r
+                                 current boot options\r
+  @param  String                 The description of the boot option.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromHandle (\r
+  IN  EFI_HANDLE                 Handle,\r
+  IN  LIST_ENTRY                 *BdsBootOptionList,\r
+  IN  CHAR16                     *String\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  DevicePath  = DevicePathFromHandle (Handle);\r
+\r
+  //\r
+  // Create and register new boot option\r
+  //\r
+  BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, String, L"BootOrder");\r
+}\r
+\r
+\r
+/**\r
+  Build the on flash shell boot option with the handle parsed in.\r
+\r
+  @param  Handle                 The handle which present the device path to create\r
+                                 on flash shell boot option\r
+  @param  BdsBootOptionList      The header of the link list which indexed all\r
+                                 current boot options\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBuildOptionFromShell (\r
+  IN EFI_HANDLE                  Handle,\r
+  IN OUT LIST_ENTRY              *BdsBootOptionList\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode;\r
+\r
+  DevicePath = DevicePathFromHandle (Handle);\r
+\r
+  //\r
+  // Build the shell device path\r
+  //\r
+  EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
+\r
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
+\r
+  //\r
+  // Create and register the shell boot option\r
+  //\r
+  BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
+\r
+}\r
+\r
+/**\r
+  Boot from the UEFI spec defined "BootNext" variable.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibBootNext (\r
+  VOID\r
+  )\r
+{\r
+  UINT16            *BootNext;\r
+  UINTN             BootNextSize;\r
+  CHAR16            Buffer[20];\r
+  BDS_COMMON_OPTION *BootOption;\r
+  LIST_ENTRY        TempList;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+\r
+  //\r
+  // Init the boot option name buffer and temp link list\r
+  //\r
+  InitializeListHead (&TempList);\r
+  ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+  BootNext = BdsLibGetVariableAndSize (\r
+              L"BootNext",\r
+              &gEfiGlobalVariableGuid,\r
+              &BootNextSize\r
+              );\r
+\r
+  //\r
+  // Clear the boot next variable first\r
+  //\r
+  if (BootNext != NULL) {\r
+    gRT->SetVariable (\r
+          L"BootNext",\r
+          &gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+          0,\r
+          BootNext\r
+          );\r
+\r
+    //\r
+    // Start to build the boot option and try to boot\r
+    //\r
+    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext);\r
+    BootOption = BdsLibVariableToOption (&TempList, Buffer);\r
+    ASSERT (BootOption != NULL);\r
+    BdsLibConnectDevicePath (BootOption->DevicePath);\r
+    BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Return the bootable media handle.\r
+  First, check the device is connected\r
+  Second, check whether the device path point to a device which support SimpleFileSystemProtocol,\r
+  Third, detect the the default boot file in the Media, and return the removable Media handle.\r
+\r
+  @param  DevicePath             Device Path to a  bootable device\r
+\r
+  @retval NULL                   The media on the DevicePath is not bootable\r
+\r
+**/\r
+EFI_HANDLE\r
+EFIAPI\r
+BdsLibGetBootableHandle (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_DEVICE_PATH_PROTOCOL        *UpdatedDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;\r
+  EFI_HANDLE                      Handle;\r
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
+  VOID                            *Buffer;\r
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
+  UINTN                           Size;\r
+  UINTN                           TempSize;\r
+  EFI_HANDLE                      ReturnHandle;\r
+  EFI_HANDLE                      *SimpleFileSystemHandles;\r
+\r
+  UINTN                           NumberSimpleFileSystemHandles;\r
+  UINTN                           Index;\r
+  EFI_IMAGE_DOS_HEADER            DosHeader;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+\r
+  UpdatedDevicePath = DevicePath;\r
+  \r
+  //\r
+  // Check whether the device is connected\r
+  //\r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol,\r
+    //\r
+    Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Fail to find the proper BlockIo and simple file protocol, maybe because device not present,  we need to connect it firstly\r
+      //\r
+      UpdatedDevicePath = DevicePath;\r
+      Status            = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+      gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+    }\r
+  } else {\r
+    //\r
+    // Get BlockIo protocol and check removable attribute\r
+    //\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+    //\r
+    // Issue a dummy read to the device to check for media change.\r
+    // When the removable media is changed, any Block IO read/write will\r
+    // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is\r
+    // returned. After the Block IO protocol is reinstalled, subsequent\r
+    // Block IO read/write will success.\r
+    //\r
+    Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
+    if (Buffer != NULL) {\r
+      BlockIo->ReadBlocks (\r
+               BlockIo,\r
+               BlockIo->Media->MediaId,\r
+               0,\r
+               BlockIo->Media->BlockSize,\r
+               Buffer\r
+               );\r
+      FreePool(Buffer);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Detect the the default boot file from removable Media\r
+  //\r
+\r
+  //\r
+  // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus\r
+  // Try to locate the USB node device path first, if fail then use its previous PCI node to search\r
+  //\r
+  DupDevicePath = DuplicateDevicePath (DevicePath);\r
+  ASSERT (DupDevicePath != NULL);\r
+  \r
+  UpdatedDevicePath = DupDevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
+  //\r
+  // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node\r
+  // Acpi()/Pci()/Usb() --> Acpi()/Pci()\r
+  //\r
+  if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) &&\r
+      (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) {\r
+    //\r
+    // Remove the usb node, let the device path only point to PCI node\r
+    //\r
+    SetDevicePathEndNode (UpdatedDevicePath);\r
+    UpdatedDevicePath = DupDevicePath;\r
+  } else {\r
+    UpdatedDevicePath = DevicePath;\r
+  }\r
+\r
+  //\r
+  // Get the device path size of boot option\r
+  //\r
+  Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+  ReturnHandle = NULL;\r
+  gBS->LocateHandleBuffer (\r
+      ByProtocol,\r
+      &gEfiSimpleFileSystemProtocolGuid,\r
+      NULL,\r
+      &NumberSimpleFileSystemHandles,\r
+      &SimpleFileSystemHandles\r
+      );\r
+  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
+    //\r
+    // Get the device path size of SimpleFileSystem handle\r
+    //\r
+    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
+    TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node\r
+    //\r
+    // Check whether the device path of boot option is part of the  SimpleFileSystem handle's device path\r
+    //\r
+    if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) {\r
+      //\r
+      // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+      //  machinename is ia32, ia64, x64, ...\r
+      //\r
+      Hdr.Union = &HdrData;\r
+      Status = BdsLibGetImageHeader (\r
+                 SimpleFileSystemHandles[Index],\r
+                 (CHAR16*)PcdGetPtr(PcdDefaultBootFileName),\r
+                 &DosHeader,\r
+                 Hdr\r
+                 );\r
+      if (!EFI_ERROR (Status) &&\r
+        EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&\r
+        Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+        ReturnHandle = SimpleFileSystemHandles[Index];\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool(DupDevicePath);\r
+\r
+  if (SimpleFileSystemHandles != NULL) {\r
+    FreePool(SimpleFileSystemHandles);\r
+  }\r
+\r
+  return ReturnHandle;\r
+}\r
+\r
+/**\r
+  Check to see if the network cable is plugged in. If the DevicePath is not\r
+  connected it will be connected.\r
+\r
+  @param  DevicePath             Device Path to check\r
+\r
+  @retval TRUE                   DevicePath points to an Network that is connected\r
+  @retval FALSE                  DevicePath does not point to a bootable network\r
+\r
+**/\r
+BOOLEAN\r
+BdsLibNetworkBootWithMediaPresent (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_DEVICE_PATH_PROTOCOL        *UpdatedDevicePath;\r
+  EFI_HANDLE                      Handle;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
+  BOOLEAN                         MediaPresent;\r
+\r
+  MediaPresent = FALSE;\r
+\r
+  UpdatedDevicePath = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Device not present so see if we need to connect it\r
+    //\r
+    Status = BdsLibConnectDevicePath (DevicePath);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // This one should work after we did the connect\r
+      //\r
+      Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (Snp->Mode->MediaPresentSupported) {\r
+        if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
+          //\r
+          // In case some one else is using the SNP check to see if it's connected\r
+          //\r
+          MediaPresent = Snp->Mode->MediaPresent;\r
+        } else {\r
+          //\r
+          // No one is using SNP so we need to Start and Initialize so\r
+          // MediaPresent will be valid.\r
+          //\r
+          Status = Snp->Start (Snp);\r
+          if (!EFI_ERROR (Status)) {\r
+            Status = Snp->Initialize (Snp, 0, 0);\r
+            if (!EFI_ERROR (Status)) {\r
+              MediaPresent = Snp->Mode->MediaPresent;\r
+              Snp->Shutdown (Snp);\r
+            }\r
+            Snp->Stop (Snp);\r
+          }\r
+        }\r
+      } else {\r
+        MediaPresent = TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return MediaPresent;\r
+}\r
+\r
+/**\r
+  For a bootable Device path, return its boot type.\r
+\r
+  @param  DevicePath                      The bootable device Path to check\r
+\r
+  @retval BDS_EFI_MEDIA_HD_BOOT           If the device path contains any media device path node, it is media boot type\r
+                                          For the floppy node, handle it as media node\r
+  @retval BDS_EFI_MEDIA_CDROM_BOOT        If the device path contains any media device path node, it is media boot type\r
+                                          For the floppy node, handle it as media node\r
+  @retval BDS_EFI_ACPI_FLOPPY_BOOT        If the device path contains any media device path node, it is media boot type\r
+                                          For the floppy node, handle it as media node\r
+  @retval BDS_EFI_MESSAGE_ATAPI_BOOT      If the device path not contains any media device path node,  and\r
+                                          its last device path node point to a message device path node, it is\r
+  \r
+  @retval BDS_EFI_MESSAGE_SCSI_BOOT       If the device path not contains any media device path node,  and\r
+                                          its last device path node point to a message device path node, it is\r
+  @retval BDS_EFI_MESSAGE_USB_DEVICE_BOOT If the device path not contains any media device path node,  and\r
+                                          its last device path node point to a message device path node, it is\r
+  @retval BDS_EFI_MESSAGE_MISC_BOOT       If the device path not contains any media device path node,  and\r
+                                          its last device path node point to a message device path node, it is\r
+  @retval BDS_LEGACY_BBS_BOOT             Legacy boot type\r
+  @retval BDS_EFI_UNSUPPORT               An EFI Removable BlockIO device path not point to a media and message device,   \r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+BdsGetBootTypeFromDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  )\r
+{\r
+  ACPI_HID_DEVICE_PATH          *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;\r
+\r
+\r
+  if (NULL == DevicePath) {\r
+    return BDS_EFI_UNSUPPORT;\r
+  }\r
+\r
+  TempDevicePath = DevicePath;\r
+\r
+  while (!IsDevicePathEndType (TempDevicePath)) {\r
+    switch (DevicePathType (TempDevicePath)) {\r
+      case BBS_DEVICE_PATH:\r
+         return BDS_LEGACY_BBS_BOOT;\r
+      case MEDIA_DEVICE_PATH:\r
+        if (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP) {\r
+          return BDS_EFI_MEDIA_HD_BOOT;\r
+        } else if (DevicePathSubType (TempDevicePath) == MEDIA_CDROM_DP) {\r
+          return BDS_EFI_MEDIA_CDROM_BOOT;\r
+        }\r
+        break;\r
+      case ACPI_DEVICE_PATH:\r
+        Acpi = (ACPI_HID_DEVICE_PATH *) TempDevicePath;\r
+        if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {\r
+          return BDS_EFI_ACPI_FLOPPY_BOOT;\r
+        }\r
+        break;\r
+      case MESSAGING_DEVICE_PATH:\r
+        //\r
+        // Get the last device path node\r
+        //\r
+        LastDeviceNode = NextDevicePathNode (TempDevicePath);\r
+        if (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {\r
+          //\r
+          // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),\r
+          // skit it\r
+          //\r
+          LastDeviceNode = NextDevicePathNode (LastDeviceNode);\r
+        }\r
+        //\r
+        // if the device path not only point to driver device, it is not a messaging device path,\r
+        //\r
+        if (!IsDevicePathEndType (LastDeviceNode)) {\r
+          break;        \r
+        }\r
+\r
+        if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {\r
+          return BDS_EFI_MESSAGE_ATAPI_BOOT;\r
+        } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {\r
+          return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
+        } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {\r
+          return BDS_EFI_MESSAGE_SCSI_BOOT;\r
+        }\r
+        return BDS_EFI_MESSAGE_MISC_BOOT;\r
+      default:\r
+        break;\r
+    }\r
+    TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+  }\r
+\r
+  return BDS_EFI_UNSUPPORT;\r
+}\r
+\r
+/**\r
+  Check whether the Device path in a boot option point to a valid bootable device,\r
+  And if CheckMedia is true, check the device is ready to boot now.\r
+\r
+  @param  DevPath     the Device path in a boot option\r
+  @param  CheckMedia  if true, check the device is ready to boot now.\r
+\r
+  @retval TRUE        the Device path  is valid\r
+  @retval FALSE       the Device path  is invalid .\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibIsValidEFIBootOptDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath,\r
+  IN BOOLEAN                      CheckMedia\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HANDLE                Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *LastDeviceNode;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;\r
+\r
+  TempDevicePath = DevPath;\r
+  LastDeviceNode = DevPath;\r
+  \r
+  //\r
+  // Check if it's a valid boot option for network boot device\r
+  // Only check if there is SimpleNetworkProtocol installed. If yes, that means\r
+  // there is the network card there.\r
+  //\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiSimpleNetworkProtocolGuid,\r
+                  &TempDevicePath,\r
+                  &Handle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Device not present so see if we need to connect it\r
+    //\r
+    TempDevicePath = DevPath;\r
+    BdsLibConnectDevicePath (TempDevicePath);\r
+    Status = gBS->LocateDevicePath (\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    &TempDevicePath,\r
+                    &Handle\r
+                    );\r
+  }\r
+  \r
+  if (!EFI_ERROR (Status)) {\r
+    if (CheckMedia) {\r
+      //\r
+      // Test if it is ready to boot now\r
+      //\r
+      if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
+        return TRUE;\r
+      }\r
+    } else {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // If the boot option point to a file, it is a valid EFI boot option,\r
+  // and assume it is ready to boot now\r
+  //\r
+  while (!IsDevicePathEnd (TempDevicePath)) {\r
+     LastDeviceNode = TempDevicePath;\r
+     TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+  }\r
+  if ((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&\r
+    (DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) {\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // Check if it's a valid boot option for internal Shell\r
+  //\r
+  if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {\r
+    //\r
+    // If the boot option point to Internal FV shell, make sure it is valid\r
+    //\r
+    TempDevicePath = DevPath; \r
+    Status = BdsLibUpdateFvFileDevicePath (&TempDevicePath, &gEfiShellFileGuid);\r
+    if (Status == EFI_ALREADY_STARTED) {\r
+      return TRUE;\r
+    } else {\r
+      if (Status == EFI_SUCCESS) {\r
+        FreePool (TempDevicePath); \r
+      }\r
+      return FALSE;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // If the boot option point to a blockIO device, no matter whether or not it is a removeable device, it is a valid EFI boot option\r
+  //\r
+  TempDevicePath = DevPath;\r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Device not present so see if we need to connect it\r
+    //\r
+    Status = BdsLibConnectDevicePath (DevPath);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Try again to get the Block Io protocol after we did the connect\r
+      //\r
+      TempDevicePath = DevPath;\r
+      Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+    }\r
+  }\r
+  \r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (CheckMedia) {\r
+        //\r
+        // Test if it is ready to boot now\r
+        //\r
+        if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+          return TRUE;\r
+        }\r
+      } else {\r
+        return TRUE;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // if the boot option point to a simple file protocol which does not consume block Io protocol, it is also a valid EFI boot option,\r
+    //\r
+    Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
+    if (!EFI_ERROR (Status)) {\r
+      if (CheckMedia) {\r
+        //\r
+        // Test if it is ready to boot now\r
+        //\r
+        if (BdsLibGetBootableHandle (DevPath) != NULL) {\r
+          return TRUE;\r
+        }\r
+      } else {\r
+        return TRUE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  According to a file guild, check a Fv file device path is valid. If it is invalid,\r
+  try to return the valid device path.\r
+  FV address maybe changes for memory layout adjust from time to time, use this function\r
+  could promise the Fv file device path is right.\r
+\r
+  @param  DevicePath             on input, the Fv file device path need to check on\r
+                                 output, the updated valid Fv file device path\r
+  @param  FileGuid               the Fv file guild\r
+\r
+  @retval EFI_INVALID_PARAMETER  the input DevicePath or FileGuid is invalid\r
+                                 parameter\r
+  @retval EFI_UNSUPPORTED        the input DevicePath does not contain Fv file\r
+                                 guild at all\r
+  @retval EFI_ALREADY_STARTED    the input DevicePath has pointed to Fv file, it is\r
+                                 valid\r
+  @retval EFI_SUCCESS            has successfully updated the invalid DevicePath,\r
+                                 and return the updated device path in DevicePath\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateFvFileDevicePath (\r
+  IN  OUT EFI_DEVICE_PATH_PROTOCOL      ** DevicePath,\r
+  IN  EFI_GUID                          *FileGuid\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;\r
+  EFI_STATUS                    Status;\r
+  EFI_GUID                      *GuidPoint;\r
+  UINTN                         Index;\r
+  UINTN                         FvHandleCount;\r
+  EFI_HANDLE                    *FvHandleBuffer;\r
+  EFI_FV_FILETYPE               Type;\r
+  UINTN                         Size;\r
+  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
+  UINT32                        AuthenticationStatus;\r
+  BOOLEAN                       FindFvFile;\r
+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;\r
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
+  EFI_HANDLE                    FoundFvHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;\r
+\r
+  if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  if (FileGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Check whether the device path point to the default the input Fv file\r
+  //\r
+  TempDevicePath = *DevicePath;\r
+  LastDeviceNode = TempDevicePath;\r
+  while (!IsDevicePathEnd (TempDevicePath)) {\r
+     LastDeviceNode = TempDevicePath;\r
+     TempDevicePath = NextDevicePathNode (TempDevicePath);\r
+  }\r
+  GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (\r
+                (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode\r
+                );\r
+  if (GuidPoint == NULL) {\r
+    //\r
+    // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  if (!CompareGuid (GuidPoint, FileGuid)) {\r
+    //\r
+    // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Check whether the input Fv file device path is valid\r
+  //\r
+  TempDevicePath = *DevicePath;\r
+  FoundFvHandle = NULL;\r
+  Status = gBS->LocateDevicePath (\r
+                  &gEfiFirmwareVolume2ProtocolGuid,\r
+                  &TempDevicePath,\r
+                  &FoundFvHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->HandleProtocol (\r
+                    FoundFvHandle,\r
+                    &gEfiFirmwareVolume2ProtocolGuid,\r
+                    (VOID **) &Fv\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
+      //\r
+      Status = Fv->ReadFile (\r
+                    Fv,\r
+                    FileGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    &Type,\r
+                    &Attributes,\r
+                    &AuthenticationStatus\r
+                    );\r
+      if (!EFI_ERROR (Status)) {\r
+        return EFI_ALREADY_STARTED;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Look for the input wanted FV file in current FV\r
+  // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV\r
+  //\r
+  FindFvFile = FALSE;\r
+  FoundFvHandle = NULL;\r
+  Status = gBS->HandleProtocol (\r
+             mBdsImageHandle,\r
+             &gEfiLoadedImageProtocolGuid,\r
+             (VOID **) &LoadedImage\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->HandleProtocol (\r
+                    LoadedImage->DeviceHandle,\r
+                    &gEfiFirmwareVolume2ProtocolGuid,\r
+                    (VOID **) &Fv\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = Fv->ReadFile (\r
+                    Fv,\r
+                    FileGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    &Type,\r
+                    &Attributes,\r
+                    &AuthenticationStatus\r
+                    );\r
+      if (!EFI_ERROR (Status)) {\r
+        FindFvFile = TRUE;\r
+        FoundFvHandle = LoadedImage->DeviceHandle;\r
+      }\r
+    }\r
+  }\r
+  //\r
+  // Second, if fail to find, try to enumerate all FV\r
+  //\r
+  if (!FindFvFile) {\r
+    FvHandleBuffer = NULL;\r
+    gBS->LocateHandleBuffer (\r
+          ByProtocol,\r
+          &gEfiFirmwareVolume2ProtocolGuid,\r
+          NULL,\r
+          &FvHandleCount,\r
+          &FvHandleBuffer\r
+          );\r
+    for (Index = 0; Index < FvHandleCount; Index++) {\r
+      gBS->HandleProtocol (\r
+            FvHandleBuffer[Index],\r
+            &gEfiFirmwareVolume2ProtocolGuid,\r
+            (VOID **) &Fv\r
+            );\r
+\r
+      Status = Fv->ReadFile (\r
+                    Fv,\r
+                    FileGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    &Type,\r
+                    &Attributes,\r
+                    &AuthenticationStatus\r
+                    );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Skip if input Fv file not in the FV\r
+        //\r
+        continue;\r
+      }\r
+      FindFvFile = TRUE;\r
+      FoundFvHandle = FvHandleBuffer[Index];\r
+      break;\r
+    }\r
+\r
+    if (FvHandleBuffer != NULL) {\r
+      FreePool (FvHandleBuffer);  \r
+    }\r
+  }\r
+\r
+  if (FindFvFile) {\r
+    //\r
+    // Build the shell device path\r
+    //\r
+    NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
+    EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
+    NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
+    *DevicePath = NewDevicePath;\r
+    return EFI_SUCCESS;\r
+  }\r
+  return EFI_NOT_FOUND;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConnect.c
new file mode 100644 (file)
index 0000000..7d0254d
--- /dev/null
@@ -0,0 +1,415 @@
+/** @file\r
+  BDS Lib functions which relate with connect the device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+\r
+/**\r
+  This function will connect all the system driver to controller\r
+  first, and then special connect the default console, this make\r
+  sure all the system controller available and the platform default\r
+  console connected.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAll (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Connect the platform console first\r
+  //\r
+  BdsLibConnectAllDefaultConsoles ();\r
+\r
+  //\r
+  // Generic way to connect all the drivers\r
+  //\r
+  BdsLibConnectAllDriversToAllControllers ();\r
+\r
+  //\r
+  // Here we have the assumption that we have already had\r
+  // platform default console\r
+  //\r
+  BdsLibConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+  This function will connect all the system drivers to all controllers\r
+  first, and then connect all the console devices the system current\r
+  have. After this we should get all the device work and console available\r
+  if the system have console device.\r
+\r
+**/\r
+VOID\r
+BdsLibGenericConnectAll (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Most generic way to connect all the drivers\r
+  //\r
+  BdsLibConnectAllDriversToAllControllers ();\r
+  BdsLibConnectAllConsoles ();\r
+}\r
+\r
+\r
+/**\r
+  This function will create all handles associate with every device\r
+  path node. If the handle associate with one device path node can not\r
+  be created success, then still give one chance to do the dispatch,\r
+  which load the missing drivers if possible.\r
+\r
+  @param  DevicePathToConnect   The device path which will be connected, it can be\r
+                                a multi-instance device path\r
+\r
+  @retval EFI_SUCCESS           All handles associate with every device path  node\r
+                                have been created\r
+  @retval EFI_OUT_OF_RESOURCES  There is no resource to create new handles\r
+  @retval EFI_NOT_FOUND         Create the handle associate with one device  path\r
+                                node failed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Next;\r
+  EFI_HANDLE                Handle;\r
+  EFI_HANDLE                PreviousHandle;\r
+  UINTN                     Size;\r
+\r
+  if (DevicePathToConnect == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  DevicePath        = DuplicateDevicePath (DevicePathToConnect);\r
+  if (DevicePath == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  CopyOfDevicePath  = DevicePath;\r
+  \r
+  do {\r
+    //\r
+    // The outer loop handles multi instance device paths.\r
+    // Only console variables contain multiple instance device paths.\r
+    //\r
+    // After this call DevicePath points to the next Instance\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&DevicePath, &Size);\r
+    if (Instance == NULL) {\r
+      FreePool (CopyOfDevicePath);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    Next      = Instance;\r
+    while (!IsDevicePathEndType (Next)) {\r
+      Next = NextDevicePathNode (Next);\r
+    }\r
+\r
+    SetDevicePathEndNode (Next);\r
+\r
+    //\r
+    // Start the real work of connect with RemainingDevicePath\r
+    //\r
+    PreviousHandle = NULL;\r
+    do {\r
+      //\r
+      // Find the handle that best matches the Device Path. If it is only a\r
+      // partial match the remaining part of the device path is returned in\r
+      // RemainingDevicePath.\r
+      //\r
+      RemainingDevicePath = Instance;\r
+      Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        if (Handle == PreviousHandle) {\r
+          //\r
+          // If no forward progress is made try invoking the Dispatcher.\r
+          // A new FV may have been added to the system an new drivers\r
+          // may now be found.\r
+          // Status == EFI_SUCCESS means a driver was dispatched\r
+          // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+          //\r
+          Status = gDS->Dispatch ();\r
+        }\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          PreviousHandle = Handle;\r
+          //\r
+          // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+          // the Recursive flag is FALSE so only one level will be expanded.\r
+          //\r
+          // Do not check the connect status here, if the connect controller fail,\r
+          // then still give the chance to do dispatch, because partial\r
+          // RemainingDevicepath may be in the new FV\r
+          //\r
+          // 1. If the connect fail, RemainingDevicepath and handle will not\r
+          //    change, so next time will do the dispatch, then dispatch's status\r
+          //    will take effect\r
+          // 2. If the connect success, the RemainingDevicepath and handle will\r
+          //    change, then avoid the dispatch, we have chance to continue the\r
+          //    next connection\r
+          //\r
+          gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+        }\r
+      }\r
+      //\r
+      // Loop until RemainingDevicePath is an empty device path\r
+      //\r
+    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  } while (DevicePath != NULL);\r
+\r
+  if (CopyOfDevicePath != NULL) {\r
+    FreePool (CopyOfDevicePath);\r
+  }\r
+  //\r
+  // All handle with DevicePath exists in the handle database\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function will connect all current system handles recursively. The\r
+  connection will finish until every handle's child handle created if it have.\r
+\r
+  @retval EFI_SUCCESS           All handles and it's child handle have been\r
+                                connected\r
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllEfi (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will disconnect all current system handles. The disconnection\r
+  will finish until every handle have been disconnected.\r
+\r
+  @retval EFI_SUCCESS           All handles have been disconnected\r
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibDisconnectAllEfi (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  //\r
+  // Disconnect all\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Connects all drivers to all controllers.\r
+  This function make sure all the current system driver will manage\r
+  the correspoinding controllers if have. And at the same time, make\r
+  sure all the system controllers have driver to manage it if have.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllDriversToAllControllers (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  do {\r
+    //\r
+    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm\r
+    //\r
+    BdsLibConnectAllEfi ();\r
+\r
+    //\r
+    // Check to see if it's possible to dispatch an more DXE drivers.\r
+    // The BdsLibConnectAllEfi () may have made new DXE drivers show up.\r
+    // If anything is Dispatched Status == EFI_SUCCESS and we will try\r
+    // the connect again.\r
+    //\r
+    Status = gDS->Dispatch ();\r
+\r
+  } while (!EFI_ERROR (Status));\r
+\r
+}\r
+\r
+\r
+/**\r
+  Connect the specific Usb device which match the short form device path,\r
+  and whose bus is determined by Host Controller (Uhci or Ehci).\r
+\r
+  @param  HostControllerPI      Uhci (0x00) or Ehci (0x20) or Both uhci and ehci\r
+                                (0xFF)\r
+  @param  RemainingDevicePath   a short-form device path that starts with the first\r
+                                element  being a USB WWID or a USB Class device\r
+                                path\r
+\r
+  @return EFI_INVALID_PARAMETER  RemainingDevicePath is NULL pointer.\r
+                                 RemainingDevicePath is not a USB device path.\r
+                                 Invalid HostControllerPI type.\r
+  @return EFI_SUCCESS            Success to connect USB device\r
+  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectUsbDevByShortFormDP(\r
+  IN UINT8                      HostControllerPI,\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_HANDLE                            *HandleArray;\r
+  UINTN                                 HandleArrayCount;\r
+  UINTN                                 Index;\r
+  EFI_PCI_IO_PROTOCOL                   *PciIo;\r
+  UINT8                                 Class[3];\r
+  BOOLEAN                               AtLeastOneConnected;\r
+\r
+  //\r
+  // Check the passed in parameters\r
+  //\r
+  if (RemainingDevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||\r
+      ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)\r
+      && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)\r
+      )) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HostControllerPI != 0xFF &&\r
+      HostControllerPI != 0x00 &&\r
+      HostControllerPI != 0x20) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find the usb host controller firstly, then connect with the remaining device path\r
+  //\r
+  AtLeastOneConnected = FALSE;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  NULL,\r
+                  &HandleArrayCount,\r
+                  &HandleArray\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < HandleArrayCount; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      HandleArray[Index],\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **)&PciIo\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Check whether the Pci device is the wanted usb host controller\r
+        //\r
+        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+        if (!EFI_ERROR (Status)) {\r
+          if ((PCI_CLASS_SERIAL == Class[2]) &&\r
+              (PCI_CLASS_SERIAL_USB == Class[1])) {\r
+            if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {\r
+              Status = gBS->ConnectController (\r
+                              HandleArray[Index],\r
+                              NULL,\r
+                              RemainingDevicePath,\r
+                              FALSE\r
+                              );\r
+              if (!EFI_ERROR(Status)) {\r
+                AtLeastOneConnected = TRUE;\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (AtLeastOneConnected) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsConsole.c
new file mode 100644 (file)
index 0000000..cb89a8d
--- /dev/null
@@ -0,0 +1,901 @@
+/** @file\r
+  BDS Lib functions which contain all the code to connect console device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+/**\r
+  Check if we need to save the EFI variable with "ConVarName" as name\r
+  as NV type\r
+\r
+  @param ConVarName The name of the EFI variable.\r
+\r
+  @retval TRUE    Set the EFI variable as NV type.\r
+  @retval FALSE   EFI variable as NV type can be set NonNV.\r
+**/\r
+BOOLEAN\r
+IsNvNeed (\r
+  IN CHAR16 *ConVarName\r
+  )\r
+{\r
+  CHAR16 *Ptr;\r
+\r
+  Ptr = ConVarName;\r
+\r
+  //\r
+  // If the variable includes "Dev" at last, we consider\r
+  // it does not support NV attribute.\r
+  //\r
+  while (*Ptr != L'\0') {\r
+    Ptr++;\r
+  }\r
+\r
+  if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) {\r
+    return FALSE;\r
+  } else {\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  This function update console variable based on ConVarName, it can\r
+  add or remove one specific console device path from the variable\r
+\r
+  @param  ConVarName               Console related variable name, ConIn, ConOut,\r
+                                   ErrOut.\r
+  @param  CustomizedConDevicePath  The console device path which will be added to\r
+                                   the console variable ConVarName, this parameter\r
+                                   can not be multi-instance.\r
+  @param  ExclusiveDevicePath      The console device path which will be removed\r
+                                   from the console variable ConVarName, this\r
+                                   parameter can not be multi-instance.\r
+\r
+  @retval EFI_UNSUPPORTED          The added device path is same to the removed one.\r
+  @retval EFI_SUCCESS              Success add or remove the device path from  the\r
+                                   console variable.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateConsoleVariable (\r
+  IN  CHAR16                    *ConVarName,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *CustomizedConDevicePath,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *ExclusiveDevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *VarConsole;\r
+  UINTN                     DevicePathSize;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  UINT32                    Attributes;\r
+\r
+  VarConsole      = NULL;\r
+  DevicePathSize  = 0;\r
+\r
+  //\r
+  // Notes: check the device path point, here should check\r
+  // with compare memory\r
+  //\r
+  if (CustomizedConDevicePath == ExclusiveDevicePath) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Delete the ExclusiveDevicePath from current default console\r
+  //\r
+  VarConsole = BdsLibGetVariableAndSize (\r
+                ConVarName,\r
+                &gEfiGlobalVariableGuid,\r
+                &DevicePathSize\r
+                );\r
+\r
+  //\r
+  // Initialize NewDevicePath\r
+  //\r
+  NewDevicePath  = VarConsole;\r
+\r
+  //\r
+  // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it.\r
+  // In the end, NewDevicePath is the final device path.\r
+  //\r
+  if (ExclusiveDevicePath != NULL && VarConsole != NULL) {\r
+      NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath);\r
+  }\r
+  //\r
+  // Try to append customized device path to NewDevicePath.\r
+  //\r
+  if (CustomizedConDevicePath != NULL) {\r
+    if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) {\r
+      //\r
+      // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it.\r
+      //\r
+      NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath);\r
+      //\r
+      // In the first check, the default console variable will be _ModuleEntryPoint,\r
+      // just append current customized device path\r
+      //\r
+      TempNewDevicePath = NewDevicePath;\r
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath);\r
+      if (TempNewDevicePath != NULL) {\r
+        FreePool(TempNewDevicePath);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV.\r
+  //\r
+  if (IsNvNeed(ConVarName)) {\r
+    //\r
+    // ConVarName has NV attribute.\r
+    //\r
+    Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;\r
+  } else {\r
+    //\r
+    // ConVarName does not have NV attribute.\r
+    //\r
+    Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
+  }\r
+\r
+  //\r
+  // Finally, Update the variable of the default console by NewDevicePath\r
+  //\r
+  gRT->SetVariable (\r
+        ConVarName,\r
+        &gEfiGlobalVariableGuid,\r
+        Attributes,\r
+        GetDevicePathSize (NewDevicePath),\r
+        NewDevicePath\r
+        );\r
+\r
+  if (VarConsole == NewDevicePath) {\r
+    if (VarConsole != NULL) {\r
+      FreePool(VarConsole);\r
+    }\r
+  } else {\r
+    if (VarConsole != NULL) {\r
+      FreePool(VarConsole);\r
+    }\r
+    if (NewDevicePath != NULL) {\r
+      FreePool(NewDevicePath);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Connect the console device base on the variable ConVarName, if\r
+  device path of the ConVarName is multi-instance device path, if\r
+  anyone of the instances is connected success, then this function\r
+  will return success.\r
+\r
+  @param  ConVarName               Console related variable name, ConIn, ConOut,\r
+                                   ErrOut.\r
+\r
+  @retval EFI_NOT_FOUND            There is not any console devices connected\r
+                                   success\r
+  @retval EFI_SUCCESS              Success connect any one instance of the console\r
+                                   device path base on the variable ConVarName.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectConsoleVariable (\r
+  IN  CHAR16                 *ConVarName\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *StartDevicePath;\r
+  UINTN                     VariableSize;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Next;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;\r
+  UINTN                     Size;\r
+  BOOLEAN                   DeviceExist;\r
+\r
+  Status      = EFI_SUCCESS;\r
+  DeviceExist = FALSE;\r
+\r
+  //\r
+  // Check if the console variable exist\r
+  //\r
+  StartDevicePath = BdsLibGetVariableAndSize (\r
+                      ConVarName,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &VariableSize\r
+                      );\r
+  if (StartDevicePath == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  CopyOfDevicePath = StartDevicePath;\r
+  do {\r
+    //\r
+    // Check every instance of the console variable\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&CopyOfDevicePath, &Size);\r
+    if (Instance == NULL) {\r
+      FreePool (StartDevicePath);\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    \r
+    Next      = Instance;\r
+    while (!IsDevicePathEndType (Next)) {\r
+      Next = NextDevicePathNode (Next);\r
+    }\r
+\r
+    SetDevicePathEndNode (Next);\r
+    //\r
+    // Check USB1.1 console\r
+    //\r
+    if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&\r
+       ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)\r
+       || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)\r
+       )) {\r
+      //\r
+      // Check the Usb console in Usb2.0 bus firstly, then Usb1.1 bus\r
+      //\r
+      Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_EHCI, Instance);\r
+      if (!EFI_ERROR (Status)) {\r
+        DeviceExist = TRUE;\r
+      }\r
+\r
+      Status = BdsLibConnectUsbDevByShortFormDP (PCI_CLASSC_PI_UHCI, Instance);\r
+      if (!EFI_ERROR (Status)) {\r
+        DeviceExist = TRUE;\r
+      }\r
+    } else {\r
+      //\r
+      // Connect the instance device path\r
+      //\r
+      Status = BdsLibConnectDevicePath (Instance);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Delete the instance from the console varialbe\r
+        //\r
+        BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance);\r
+      } else {\r
+        DeviceExist = TRUE;\r
+      }\r
+    }\r
+    FreePool(Instance);\r
+  } while (CopyOfDevicePath != NULL);\r
+\r
+  FreePool (StartDevicePath);\r
+\r
+  if (!DeviceExist) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will search every simpletext device in current system,\r
+  and make every simpletext device as pertantial console device.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllConsoles (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                     Index;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
+  UINTN                     HandleCount;\r
+  EFI_HANDLE                *HandleBuffer;\r
+\r
+  Index         = 0;\r
+  HandleCount   = 0;\r
+  HandleBuffer  = NULL;\r
+  ConDevicePath = NULL;\r
+\r
+  //\r
+  // Update all the console variables\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+          ByProtocol,\r
+          &gEfiSimpleTextInProtocolGuid,\r
+          NULL,\r
+          &HandleCount,\r
+          &HandleBuffer\r
+          );\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    gBS->HandleProtocol (\r
+            HandleBuffer[Index],\r
+            &gEfiDevicePathProtocolGuid,\r
+            (VOID **) &ConDevicePath\r
+            );\r
+    BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool(HandleBuffer);\r
+    HandleBuffer = NULL;\r
+  }\r
+\r
+  gBS->LocateHandleBuffer (\r
+          ByProtocol,\r
+          &gEfiSimpleTextOutProtocolGuid,\r
+          NULL,\r
+          &HandleCount,\r
+          &HandleBuffer\r
+          );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    gBS->HandleProtocol (\r
+            HandleBuffer[Index],\r
+            &gEfiDevicePathProtocolGuid,\r
+            (VOID **) &ConDevicePath\r
+            );\r
+    BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL);\r
+    BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL);\r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool(HandleBuffer);\r
+  }\r
+\r
+  //\r
+  // Connect all console variables\r
+  //\r
+  BdsLibConnectAllDefaultConsoles ();\r
+\r
+}\r
+\r
+/**\r
+  This function will connect console device base on the console\r
+  device variable ConIn, ConOut and ErrOut.\r
+\r
+  @retval EFI_SUCCESS              At least one of the ConIn and ConOut device have\r
+                                   been connected success.\r
+  @retval EFI_STATUS               Return the status of BdsLibConnectConsoleVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllDefaultConsoles (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  //\r
+  // Connect all default console variables\r
+  //\r
+\r
+  //\r
+  // It seems impossible not to have any ConOut device on platform,\r
+  // so we check the status here.\r
+  //\r
+  Status = BdsLibConnectConsoleVariable (L"ConOut");\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Insert the performance probe for Console Out\r
+  //\r
+  PERF_START (NULL, "ConOut", "BDS", 1);\r
+  PERF_END (NULL, "ConOut", "BDS", 0);\r
+\r
+  //\r
+  // Because possibly the platform is legacy free, in such case,\r
+  // ConIn devices (Serial Port and PS2 Keyboard ) does not exist,\r
+  // so we need not check the status.\r
+  //\r
+  BdsLibConnectConsoleVariable (L"ConIn");\r
+\r
+  //\r
+  // The _ModuleEntryPoint err out var is legal.\r
+  //\r
+  BdsLibConnectConsoleVariable (L"ErrOut");\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
+  is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
+  buffer is passed in it will be used if it is big enough.\r
+\r
+  @param  BmpImage      Pointer to BMP file\r
+  @param  BmpImageSize  Number of bytes in BmpImage\r
+  @param  GopBlt        Buffer containing GOP version of BmpImage.\r
+  @param  GopBltSize    Size of GopBlt in bytes.\r
+  @param  PixelHeight   Height of GopBlt/BmpImage in pixels\r
+  @param  PixelWidth    Width of GopBlt/BmpImage in pixels\r
+\r
+  @retval EFI_SUCCESS           GopBlt and GopBltSize are returned.\r
+  @retval EFI_UNSUPPORTED       BmpImage is not a valid *.BMP image\r
+  @retval EFI_BUFFER_TOO_SMALL  The passed in GopBlt buffer is not big enough.\r
+                                GopBltSize will contain the required size.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate.\r
+\r
+**/\r
+EFI_STATUS\r
+ConvertBmpToGopBlt (\r
+  IN     VOID      *BmpImage,\r
+  IN     UINTN     BmpImageSize,\r
+  IN OUT VOID      **GopBlt,\r
+  IN OUT UINTN     *GopBltSize,\r
+     OUT UINTN     *PixelHeight,\r
+     OUT UINTN     *PixelWidth\r
+  )\r
+{\r
+  UINT8                         *Image;\r
+  UINT8                         *ImageHeader;\r
+  BMP_IMAGE_HEADER              *BmpHeader;\r
+  BMP_COLOR_MAP                 *BmpColorMap;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+  UINTN                         BltBufferSize;\r
+  UINTN                         Index;\r
+  UINTN                         Height;\r
+  UINTN                         Width;\r
+  UINTN                         ImageIndex;\r
+  BOOLEAN                       IsAllocated;\r
+\r
+  BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
+\r
+  if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Doesn't support compress.\r
+  //\r
+  if (BmpHeader->CompressionType != 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Calculate Color Map offset in the image.\r
+  //\r
+  Image       = BmpImage;\r
+  BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
+\r
+  //\r
+  // Calculate graphics image data address in the image\r
+  //\r
+  Image         = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
+  ImageHeader   = Image;\r
+\r
+  //\r
+  // Calculate the BltBuffer needed size.\r
+  //\r
+  BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+  IsAllocated   = FALSE;\r
+  if (*GopBlt == NULL) {\r
+    //\r
+    // GopBlt is not allocated by caller.\r
+    //\r
+    *GopBltSize = BltBufferSize;\r
+    *GopBlt     = AllocatePool (*GopBltSize);\r
+    IsAllocated = TRUE;\r
+    if (*GopBlt == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  } else {\r
+    //\r
+    // GopBlt has been allocated by caller.\r
+    //\r
+    if (*GopBltSize < BltBufferSize) {\r
+      *GopBltSize = BltBufferSize;\r
+      return EFI_BUFFER_TOO_SMALL;\r
+    }\r
+  }\r
+\r
+  *PixelWidth   = BmpHeader->PixelWidth;\r
+  *PixelHeight  = BmpHeader->PixelHeight;\r
+\r
+  //\r
+  // Convert image from BMP to Blt buffer format\r
+  //\r
+  BltBuffer = *GopBlt;\r
+  for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+    Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+    for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+      switch (BmpHeader->BitPerPixel) {\r
+      case 1:\r
+        //\r
+        // Convert 1-bit (2 colors) BMP to 24-bit color\r
+        //\r
+        for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+          Blt->Red    = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
+          Blt->Green  = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
+          Blt->Blue   = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
+          Blt++;\r
+          Width++;\r
+        }\r
+\r
+        Blt--;\r
+        Width--;\r
+        break;\r
+\r
+      case 4:\r
+        //\r
+        // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
+        //\r
+        Index       = (*Image) >> 4;\r
+        Blt->Red    = BmpColorMap[Index].Red;\r
+        Blt->Green  = BmpColorMap[Index].Green;\r
+        Blt->Blue   = BmpColorMap[Index].Blue;\r
+        if (Width < (BmpHeader->PixelWidth - 1)) {\r
+          Blt++;\r
+          Width++;\r
+          Index       = (*Image) & 0x0f;\r
+          Blt->Red    = BmpColorMap[Index].Red;\r
+          Blt->Green  = BmpColorMap[Index].Green;\r
+          Blt->Blue   = BmpColorMap[Index].Blue;\r
+        }\r
+        break;\r
+\r
+      case 8:\r
+        //\r
+        // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
+        //\r
+        Blt->Red    = BmpColorMap[*Image].Red;\r
+        Blt->Green  = BmpColorMap[*Image].Green;\r
+        Blt->Blue   = BmpColorMap[*Image].Blue;\r
+        break;\r
+\r
+      case 24:\r
+        //\r
+        // It is 24-bit BMP.\r
+        //\r
+        Blt->Blue   = *Image++;\r
+        Blt->Green  = *Image++;\r
+        Blt->Red    = *Image;\r
+        break;\r
+\r
+      default:\r
+        //\r
+        // Other bit format BMP is not supported.\r
+        //\r
+        if (IsAllocated) {\r
+          FreePool (*GopBlt);\r
+          *GopBlt = NULL;\r
+        }\r
+        return EFI_UNSUPPORTED;\r
+        break;\r
+      };\r
+\r
+    }\r
+\r
+    ImageIndex = (UINTN) (Image - ImageHeader);\r
+    if ((ImageIndex % 4) != 0) {\r
+      //\r
+      // Bmp Image starts each row on a 32-bit boundary!\r
+      //\r
+      Image = Image + (4 - (ImageIndex % 4));\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Use Console Control Protocol to lock the Console In Spliter virtual handle.\r
+  This is the ConInHandle and ConIn handle in the EFI system table. All key\r
+  presses will be ignored until the Password is typed in. The only way to\r
+  disable the password is to type it in to a ConIn device.\r
+\r
+  @param  Password        Password used to lock ConIn device.\r
+\r
+  @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.\r
+  @retval EFI_UNSUPPORTED Password not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LockKeyboards (\r
+  IN  CHAR16    *Password\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = ConsoleControl->LockStdIn (ConsoleControl, Password);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Use Console Control to turn off UGA based Simple Text Out consoles from going\r
+  to the UGA device. Put up LogoFile on every UGA device that is a console\r
+\r
+  @param[in]  LogoFile   File name of logo to display on the center of the screen.\r
+\r
+  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.\r
+  @retval EFI_UNSUPPORTED Logo not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnableQuietBoot (\r
+  IN  EFI_GUID  *LogoFile\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+  EFI_OEM_BADGING_PROTOCOL      *Badging;\r
+  UINT32                        SizeOfX;\r
+  UINT32                        SizeOfY;\r
+  INTN                          DestX;\r
+  INTN                          DestY;\r
+  UINT8                         *ImageData;\r
+  UINTN                         ImageSize;\r
+  UINTN                         BltSize;\r
+  UINT32                        Instance;\r
+  EFI_BADGING_FORMAT            Format;\r
+  EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
+  UINTN                         CoordinateX;\r
+  UINTN                         CoordinateY;\r
+  UINTN                         Height;\r
+  UINTN                         Width;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+  EFI_UGA_DRAW_PROTOCOL         *UgaDraw;\r
+  UINT32                        ColorDepth;\r
+  UINT32                        RefreshRate;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  UgaDraw = NULL;\r
+  //\r
+  // Try to open GOP first\r
+  //\r
+  Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);\r
+  if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    GraphicsOutput = NULL;\r
+    //\r
+    // Open GOP failed, try to open UGA\r
+    //\r
+    Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Badging = NULL;\r
+  Status  = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging);\r
+\r
+  //\r
+  // Set console control to graphics mode.\r
+  //\r
+  Status = ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (GraphicsOutput != NULL) {\r
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+\r
+  } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Instance = 0;\r
+  while (1) {\r
+    ImageData = NULL;\r
+    ImageSize = 0;\r
+\r
+    if (Badging != NULL) {\r
+      //\r
+      // Get image from OEMBadging protocol.\r
+      //\r
+      Status = Badging->GetImage (\r
+                          Badging,\r
+                          &Instance,\r
+                          &Format,\r
+                          &ImageData,\r
+                          &ImageSize,\r
+                          &Attribute,\r
+                          &CoordinateX,\r
+                          &CoordinateY\r
+                          );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Currently only support BMP format.\r
+      //\r
+      if (Format != EfiBadgingFormatBMP) {\r
+        if (ImageData != NULL) {\r
+          FreePool (ImageData);\r
+        }\r
+        continue;\r
+      }\r
+    } else {\r
+      //\r
+      // Get the specified image from FV.\r
+      //\r
+      Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
+      CoordinateX = 0;\r
+      CoordinateY = 0;\r
+      Attribute   = EfiBadgingDisplayAttributeCenter;\r
+    }\r
+\r
+    Blt = NULL;\r
+    Status = ConvertBmpToGopBlt (\r
+              ImageData,\r
+              ImageSize,\r
+              (VOID **) &Blt,\r
+              &BltSize,\r
+              &Height,\r
+              &Width\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (ImageData);\r
+\r
+      if (Badging == NULL) {\r
+        return Status;\r
+      } else {\r
+        continue;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Calculate the display position according to Attribute.\r
+    //\r
+    switch (Attribute) {\r
+    case EfiBadgingDisplayAttributeLeftTop:\r
+      DestX = CoordinateX;\r
+      DestY = CoordinateY;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterTop:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = CoordinateY;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeRightTop:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = CoordinateY;;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterRight:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeRightBottom:\r
+      DestX = (SizeOfX - Width - CoordinateX);\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterBottom:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeLeftBottom:\r
+      DestX = CoordinateX;\r
+      DestY = (SizeOfY - Height - CoordinateY);\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenterLeft:\r
+      DestX = CoordinateX;\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    case EfiBadgingDisplayAttributeCenter:\r
+      DestX = (SizeOfX - Width) / 2;\r
+      DestY = (SizeOfY - Height) / 2;\r
+      break;\r
+\r
+    default:\r
+      DestX = CoordinateX;\r
+      DestY = CoordinateY;\r
+      break;\r
+    }\r
+\r
+    if ((DestX >= 0) && (DestY >= 0)) {\r
+      if (GraphicsOutput != NULL) {\r
+        Status = GraphicsOutput->Blt (\r
+                            GraphicsOutput,\r
+                            Blt,\r
+                            EfiBltBufferToVideo,\r
+                            0,\r
+                            0,\r
+                            (UINTN) DestX,\r
+                            (UINTN) DestY,\r
+                            Width,\r
+                            Height,\r
+                            Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                            );\r
+      } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+        Status = UgaDraw->Blt (\r
+                            UgaDraw,\r
+                            (EFI_UGA_PIXEL *) Blt,\r
+                            EfiUgaBltBufferToVideo,\r
+                            0,\r
+                            0,\r
+                            (UINTN) DestX,\r
+                            (UINTN) DestY,\r
+                            Width,\r
+                            Height,\r
+                            Width * sizeof (EFI_UGA_PIXEL)\r
+                            );\r
+      } else {\r
+      Status = EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+\r
+    FreePool (ImageData);\r
+\r
+    if (Blt != NULL) {\r
+      FreePool (Blt);\r
+    }\r
+\r
+    if (Badging == NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Use Console Control to turn on UGA based Simple Text Out consoles. The UGA\r
+  Simple Text Out screens will now be synced up with all non UGA output devices\r
+\r
+  @retval EFI_SUCCESS     UGA devices are back in text mode and synced up.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisableQuietBoot (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Set console control to text mode.\r
+  //\r
+  return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+}\r
+\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c
new file mode 100644 (file)
index 0000000..acf61eb
--- /dev/null
@@ -0,0 +1,1272 @@
+/** @file\r
+  Misc BDS library function\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+\r
+#define MAX_STRING_LEN        200\r
+\r
+BOOLEAN   mFeaturerSwitch = TRUE;\r
+BOOLEAN   mResetRequired  = FALSE;\r
+\r
+extern UINT16 gPlatformBootTimeOutDefault;\r
+\r
+\r
+/**\r
+  Return the default value for system Timeout variable.\r
+\r
+  @return Timeout value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+BdsLibGetTimeout (\r
+  VOID\r
+  )\r
+{\r
+  UINT16      Timeout;\r
+  UINTN       Size;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Return Timeout variable or 0xffff if no valid\r
+  // Timeout variable exists.\r
+  //\r
+  Size    = sizeof (UINT16);\r
+  Status  = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff\r
+    // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.\r
+    // To make the current EFI Automatic-Test activity possible, platform can choose other value\r
+    // for automatic boot when the variable is not present.\r
+    //\r
+    Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);\r
+  }\r
+\r
+  return Timeout;\r
+}\r
+\r
+/**\r
+  The function will go through the driver option link list, load and start\r
+  every driver the driver option device path point to.\r
+\r
+  @param  BdsDriverLists        The header of the current driver option link list\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibLoadDrivers (\r
+  IN LIST_ENTRY                   *BdsDriverLists\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  LIST_ENTRY                *Link;\r
+  BDS_COMMON_OPTION         *Option;\r
+  EFI_HANDLE                ImageHandle;\r
+  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
+  UINTN                     ExitDataSize;\r
+  CHAR16                    *ExitData;\r
+  BOOLEAN                   ReconnectAll;\r
+\r
+  ReconnectAll = FALSE;\r
+\r
+  //\r
+  // Process the driver option\r
+  //\r
+  for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+    \r
+    //\r
+    // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
+    // the boot manager will not automatically load the option.\r
+    //\r
+    if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) {\r
+      continue;\r
+    }\r
+    \r
+    //\r
+    // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
+    // then all of the EFI drivers in the system will be disconnected and\r
+    // reconnected after the last driver load option is processed.\r
+    //\r
+    if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) {\r
+      ReconnectAll = TRUE;\r
+    }\r
+    \r
+    //\r
+    // Make sure the driver path is connected.\r
+    //\r
+    BdsLibConnectDevicePath (Option->DevicePath);\r
+\r
+    //\r
+    // Load and start the image that Driver#### describes\r
+    //\r
+    Status = gBS->LoadImage (\r
+                    FALSE,\r
+                    mBdsImageHandle,\r
+                    Option->DevicePath,\r
+                    NULL,\r
+                    0,\r
+                    &ImageHandle\r
+                    );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
+\r
+      //\r
+      // Verify whether this image is a driver, if not,\r
+      // exit it and continue to parse next load option\r
+      //\r
+      if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
+        gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
+        continue;\r
+      }\r
+\r
+      if (Option->LoadOptionsSize != 0) {\r
+        ImageInfo->LoadOptionsSize  = Option->LoadOptionsSize;\r
+        ImageInfo->LoadOptions      = Option->LoadOptions;\r
+      }\r
+      //\r
+      // Before calling the image, enable the Watchdog Timer for\r
+      // the 5 Minute period\r
+      //\r
+      gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
+\r
+      Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", Status));\r
+\r
+      //\r
+      // Clear the Watchdog Timer after the image returns\r
+      //\r
+      gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
+  //\r
+  if (ReconnectAll) {\r
+    BdsLibDisconnectAllEfi ();\r
+    BdsLibConnectAll ();\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Get the Option Number that does not used.\r
+  Try to locate the specific option variable one by one utile find a free number.\r
+\r
+  @param  VariableName          Indicate if the boot#### or driver#### option\r
+\r
+  @return The Minimal Free Option Number\r
+\r
+**/\r
+UINT16\r
+BdsLibGetFreeOptionNumber (\r
+  IN  CHAR16    *VariableName\r
+  )\r
+{\r
+  UINTN         Index;\r
+  CHAR16        StrTemp[10];\r
+  UINT16        *OptionBuffer;\r
+  UINTN         OptionSize;\r
+\r
+  //\r
+  // Try to find the minimum free number from 0, 1, 2, 3....\r
+  //\r
+  Index = 0;\r
+  do {\r
+    if (*VariableName == 'B') {\r
+      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);\r
+    } else {\r
+      UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Driver%04x", Index);\r
+    }\r
+    //\r
+    // try if the option number is used\r
+    //\r
+    OptionBuffer = BdsLibGetVariableAndSize (\r
+                     StrTemp,\r
+                     &gEfiGlobalVariableGuid,\r
+                     &OptionSize\r
+                     );\r
+    if (OptionBuffer == NULL) {\r
+      break;\r
+    }\r
+    Index++;\r
+  } while (TRUE);\r
+\r
+  return ((UINT16) Index);\r
+}\r
+\r
+\r
+/**\r
+  This function will register the new boot#### or driver#### option base on\r
+  the VariableName. The new registered boot#### or driver#### will be linked\r
+  to BdsOptionList and also update to the VariableName. After the boot#### or\r
+  driver#### updated, the BootOrder or DriverOrder will also be updated.\r
+\r
+  @param  BdsOptionList         The header of the boot#### or driver#### link list\r
+  @param  DevicePath            The device path which the boot#### or driver####\r
+                                option present\r
+  @param  String                The description of the boot#### or driver####\r
+  @param  VariableName          Indicate if the boot#### or driver#### option\r
+\r
+  @retval EFI_SUCCESS           The boot#### or driver#### have been success\r
+                                registered\r
+  @retval EFI_STATUS            Return the status of gRT->SetVariable ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibRegisterNewOption (\r
+  IN  LIST_ENTRY                     *BdsOptionList,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL       *DevicePath,\r
+  IN  CHAR16                         *String,\r
+  IN  CHAR16                         *VariableName\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  UINT16                    RegisterOptionNumber;\r
+  UINT16                    *TempOptionPtr;\r
+  UINTN                     TempOptionSize;\r
+  UINT16                    *OptionOrderPtr;\r
+  VOID                      *OptionPtr;\r
+  UINTN                     OptionSize;\r
+  UINT8                     *TempPtr;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;\r
+  CHAR16                    *Description;\r
+  CHAR16                    OptionName[10];\r
+  BOOLEAN                   UpdateDescription;\r
+  UINT16                    BootOrderEntry;\r
+  UINTN                     OrderItemNum;\r
+\r
+\r
+  OptionPtr             = NULL;\r
+  OptionSize            = 0;\r
+  TempPtr               = NULL;\r
+  OptionDevicePath      = NULL;\r
+  Description           = NULL;\r
+  OptionOrderPtr        = NULL;\r
+  UpdateDescription     = FALSE;\r
+  Status                = EFI_SUCCESS;\r
+  ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+  TempOptionSize = 0;\r
+  TempOptionPtr = BdsLibGetVariableAndSize (\r
+                    VariableName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    &TempOptionSize\r
+                    );\r
+  //\r
+  // Compare with current option variable if the previous option is set in global variable.\r
+  //\r
+  for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) {\r
+    //\r
+    // TempOptionPtr must not be NULL if we have non-zero TempOptionSize.\r
+    //\r
+    ASSERT (TempOptionPtr != NULL);\r
+\r
+    if (*VariableName == 'B') {\r
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]);\r
+    } else {\r
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]);\r
+    }\r
+\r
+    OptionPtr = BdsLibGetVariableAndSize (\r
+                  OptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  &OptionSize\r
+                  );\r
+    if (OptionPtr == NULL) {\r
+      continue;\r
+    }\r
+    TempPtr         =   OptionPtr;\r
+    TempPtr         +=  sizeof (UINT32) + sizeof (UINT16);\r
+    Description     =   (CHAR16 *) TempPtr;\r
+    TempPtr         +=  StrSize ((CHAR16 *) TempPtr);\r
+    OptionDevicePath =  (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+\r
+    //\r
+    // Notes: the description may will change base on the GetStringToken\r
+    //\r
+    if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) {\r
+      if (CompareMem (Description, String, StrSize (Description)) == 0) { \r
+        //\r
+        // Got the option, so just return\r
+        //\r
+        FreePool (OptionPtr);\r
+        FreePool (TempOptionPtr);\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        //\r
+        // Option description changed, need update.\r
+        //\r
+        UpdateDescription = TRUE;\r
+        FreePool (OptionPtr);\r
+        break;\r
+      }\r
+    }\r
+\r
+    FreePool (OptionPtr);\r
+  }\r
+\r
+  OptionSize          = sizeof (UINT32) + sizeof (UINT16) + StrSize (String);\r
+  OptionSize          += GetDevicePathSize (DevicePath);\r
+  OptionPtr           = AllocateZeroPool (OptionSize);\r
+  ASSERT (OptionPtr != NULL);\r
+  \r
+  TempPtr             = OptionPtr;\r
+  *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE;\r
+  TempPtr             += sizeof (UINT32);\r
+  *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath);\r
+  TempPtr             += sizeof (UINT16);\r
+  CopyMem (TempPtr, String, StrSize (String));\r
+  TempPtr             += StrSize (String);\r
+  CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath));\r
+\r
+  if (UpdateDescription) {\r
+    //\r
+    // The number in option#### to be updated. \r
+    // In this case, we must have non-NULL TempOptionPtr.\r
+    //\r
+    ASSERT (TempOptionPtr != NULL);\r
+    RegisterOptionNumber = TempOptionPtr[Index];\r
+  } else {\r
+    //\r
+    // The new option#### number\r
+    //\r
+    RegisterOptionNumber = BdsLibGetFreeOptionNumber(VariableName);\r
+  }\r
+\r
+  if (*VariableName == 'B') {\r
+    UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber);\r
+  } else {\r
+    UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  OptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  OptionSize,\r
+                  OptionPtr\r
+                  );\r
+  //\r
+  // Return if only need to update a changed description or fail to set option.\r
+  //\r
+  if (EFI_ERROR (Status) || UpdateDescription) {\r
+    FreePool (OptionPtr);\r
+    if (TempOptionPtr != NULL) {\r
+      FreePool (TempOptionPtr);\r
+    }\r
+    return Status;\r
+  }\r
+\r
+  FreePool (OptionPtr);\r
+\r
+  //\r
+  // Update the option order variable\r
+  //\r
+\r
+  //\r
+  // If no option order\r
+  //\r
+  if (TempOptionSize == 0) {\r
+    BootOrderEntry = 0;\r
+    Status = gRT->SetVariable (\r
+                    VariableName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    sizeof (UINT16),\r
+                    &BootOrderEntry\r
+                    );\r
+    if (TempOptionPtr != NULL) {\r
+      FreePool (TempOptionPtr);\r
+    }\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // TempOptionPtr must not be NULL if TempOptionSize is not zero.\r
+  //\r
+  ASSERT (TempOptionPtr != NULL);\r
+  //\r
+  // Append the new option number to the original option order\r
+  //\r
+  OrderItemNum = (TempOptionSize / sizeof (UINT16)) + 1 ;\r
+  OptionOrderPtr = AllocateZeroPool ( OrderItemNum * sizeof (UINT16));\r
+  ASSERT (OptionOrderPtr!= NULL);\r
+  CopyMem (OptionOrderPtr, TempOptionPtr, (OrderItemNum - 1) * sizeof (UINT16));\r
+\r
+  OptionOrderPtr[Index] = RegisterOptionNumber;\r
+\r
+  Status = gRT->SetVariable (\r
+                  VariableName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  OrderItemNum * sizeof (UINT16),\r
+                  OptionOrderPtr\r
+                  );\r
+  FreePool (TempOptionPtr);\r
+  FreePool (OptionOrderPtr);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Build the boot#### or driver#### option from the VariableName, the\r
+  build boot#### or driver#### will also be linked to BdsCommonOptionList.\r
+\r
+  @param  BdsCommonOptionList   The header of the boot#### or driver#### option\r
+                                link list\r
+  @param  VariableName          EFI Variable name indicate if it is boot#### or\r
+                                driver####\r
+\r
+  @retval BDS_COMMON_OPTION     Get the option just been created\r
+  @retval NULL                  Failed to get the new option\r
+\r
+**/\r
+BDS_COMMON_OPTION *\r
+EFIAPI\r
+BdsLibVariableToOption (\r
+  IN OUT LIST_ENTRY                   *BdsCommonOptionList,\r
+  IN  CHAR16                          *VariableName\r
+  )\r
+{\r
+  UINT32                    Attribute;\r
+  UINT16                    FilePathSize;\r
+  UINT8                     *Variable;\r
+  UINT8                     *TempPtr;\r
+  UINTN                     VariableSize;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BDS_COMMON_OPTION         *Option;\r
+  VOID                      *LoadOptions;\r
+  UINT32                    LoadOptionsSize;\r
+  CHAR16                    *Description;\r
+  UINT8                     NumOff;\r
+  //\r
+  // Read the variable. We will never free this data.\r
+  //\r
+  Variable = BdsLibGetVariableAndSize (\r
+              VariableName,\r
+              &gEfiGlobalVariableGuid,\r
+              &VariableSize\r
+              );\r
+  if (Variable == NULL) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Notes: careful defined the variable of Boot#### or\r
+  // Driver####, consider use some macro to abstract the code\r
+  //\r
+  //\r
+  // Get the option attribute\r
+  //\r
+  TempPtr   =  Variable;\r
+  Attribute =  *(UINT32 *) Variable;\r
+  TempPtr   += sizeof (UINT32);\r
+\r
+  //\r
+  // Get the option's device path size\r
+  //\r
+  FilePathSize =  *(UINT16 *) TempPtr;\r
+  TempPtr      += sizeof (UINT16);\r
+\r
+  //\r
+  // Get the option's description string\r
+  //\r
+  Description = (CHAR16 *) TempPtr;\r
+\r
+  //\r
+  // Get the option's description string size\r
+  //\r
+  TempPtr     += StrSize ((CHAR16 *) TempPtr);\r
+\r
+  //\r
+  // Get the option's device path\r
+  //\r
+  DevicePath =  (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;\r
+  TempPtr    += FilePathSize;\r
+\r
+  LoadOptions     = TempPtr;\r
+  LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable));\r
+\r
+  //\r
+  // The Console variables may have multiple device paths, so make\r
+  // an Entry for each one.\r
+  //\r
+  Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION));\r
+  if (Option == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Option->Signature   = BDS_LOAD_OPTION_SIGNATURE;\r
+  Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
+  ASSERT(Option->DevicePath != NULL);\r
+  CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
+\r
+  Option->Attribute   = Attribute;\r
+  Option->Description = AllocateZeroPool (StrSize (Description));\r
+  ASSERT(Option->Description != NULL);\r
+  CopyMem (Option->Description, Description, StrSize (Description));\r
+\r
+  Option->LoadOptions = AllocateZeroPool (LoadOptionsSize);\r
+  ASSERT(Option->LoadOptions != NULL);\r
+  CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize);\r
+  Option->LoadOptionsSize = LoadOptionsSize;\r
+\r
+  //\r
+  // Get the value from VariableName Unicode string\r
+  // since the ISO standard assumes ASCII equivalent abbreviations, we can be safe in converting this\r
+  // Unicode stream to ASCII without any loss in meaning.\r
+  //\r
+  if (*VariableName == 'B') {\r
+    NumOff = sizeof (L"Boot")/sizeof(CHAR16) -1 ;\r
+    Option->BootCurrent = (UINT16) ((VariableName[NumOff]  -'0') * 0x1000);\r
+    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+1]-'0') * 0x100));\r
+    Option->BootCurrent = (UINT16) (Option->BootCurrent +  ((VariableName[NumOff+2]-'0') * 0x10));\r
+    Option->BootCurrent = (UINT16) (Option->BootCurrent + ((VariableName[NumOff+3]-'0')));\r
+  }\r
+  //\r
+  // Insert active entry to BdsDeviceList\r
+  //\r
+  if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) {\r
+    InsertTailList (BdsCommonOptionList, &Option->Link);\r
+    FreePool (Variable);\r
+    return Option;\r
+  }\r
+\r
+  FreePool (Variable);\r
+  FreePool (Option);\r
+  return NULL;\r
+\r
+}\r
+\r
+/**\r
+  Process BootOrder, or DriverOrder variables, by calling\r
+  BdsLibVariableToOption () for each UINT16 in the variables.\r
+\r
+  @param  BdsCommonOptionList   The header of the option list base on variable\r
+                                VariableName\r
+  @param  VariableName          EFI Variable name indicate the BootOrder or\r
+                                DriverOrder\r
+\r
+  @retval EFI_SUCCESS           Success create the boot option or driver option\r
+                                list\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to get the boot option or driver option list\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibBuildOptionFromVar (\r
+  IN  LIST_ENTRY                      *BdsCommonOptionList,\r
+  IN  CHAR16                          *VariableName\r
+  )\r
+{\r
+  UINT16            *OptionOrder;\r
+  UINTN             OptionOrderSize;\r
+  UINTN             Index;\r
+  BDS_COMMON_OPTION *Option;\r
+  CHAR16            OptionName[20];\r
+\r
+  //\r
+  // Zero Buffer in order to get all BOOT#### variables\r
+  //\r
+  ZeroMem (OptionName, sizeof (OptionName));\r
+\r
+  //\r
+  // Read the BootOrder, or DriverOrder variable.\r
+  //\r
+  OptionOrder = BdsLibGetVariableAndSize (\r
+                  VariableName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  &OptionOrderSize\r
+                  );\r
+  if (OptionOrder == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) {\r
+    if (*VariableName == 'B') {\r
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]);\r
+    } else {\r
+      UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]);\r
+    }\r
+\r
+    Option              = BdsLibVariableToOption (BdsCommonOptionList, OptionName);\r
+    ASSERT (Option != NULL);\r
+    Option->BootCurrent = OptionOrder[Index];\r
+\r
+  }\r
+\r
+  FreePool (OptionOrder);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get boot mode by looking up configuration table and parsing HOB list\r
+\r
+  @param  BootMode              Boot mode from PEI handoff HOB.\r
+\r
+  @retval EFI_SUCCESS           Successfully get boot mode\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetBootMode (\r
+  OUT EFI_BOOT_MODE       *BootMode\r
+  )\r
+{\r
+  *BootMode = GetBootModeHob ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
+  buffer, and the size of the buffer. If failure return NULL.\r
+\r
+  @param  Name                  String part of EFI variable name\r
+  @param  VendorGuid            GUID part of EFI variable name\r
+  @param  VariableSize          Returns the size of the EFI variable that was read\r
+\r
+  @return                       Dynamically allocated memory that contains a copy of the EFI variable\r
+                                Caller is responsible freeing the buffer.\r
+  @retval NULL                  Variable was not read\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+BdsLibGetVariableAndSize (\r
+  IN  CHAR16              *Name,\r
+  IN  EFI_GUID            *VendorGuid,\r
+  OUT UINTN               *VariableSize\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       BufferSize;\r
+  VOID        *Buffer;\r
+\r
+  Buffer = NULL;\r
+\r
+  //\r
+  // Pass in a zero size buffer to find the required buffer size.\r
+  //\r
+  BufferSize  = 0;\r
+  Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    //\r
+    // Allocate the buffer to return\r
+    //\r
+    Buffer = AllocateZeroPool (BufferSize);\r
+    if (Buffer == NULL) {\r
+      return NULL;\r
+    }\r
+    //\r
+    // Read variable into the allocated buffer.\r
+    //\r
+    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+    if (EFI_ERROR (Status)) {\r
+      BufferSize = 0;\r
+    }\r
+  }\r
+\r
+  *VariableSize = BufferSize;\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Delete the instance in Multi which matches partly with Single instance\r
+\r
+  @param  Multi                 A pointer to a multi-instance device path data\r
+                                structure.\r
+  @param  Single                A pointer to a single-instance device path data\r
+                                structure.\r
+\r
+  @return This function will remove the device path instances in Multi which partly\r
+          match with the Single, and return the result device path. If there is no\r
+          remaining device path as a result, this function will return NULL.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EFIAPI\r
+BdsLibDelPartMatchInstance (\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN     EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TempNewDevicePath;\r
+  UINTN                     InstanceSize;\r
+  UINTN                     SingleDpSize;\r
+  UINTN                     Size;\r
+\r
+  NewDevicePath     = NULL;\r
+  TempNewDevicePath = NULL;\r
+\r
+  if (Multi == NULL || Single == NULL) {\r
+    return Multi;\r
+  }\r
+\r
+  Instance        =  GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+  SingleDpSize    =  GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;\r
+  InstanceSize    -= END_DEVICE_PATH_LENGTH;\r
+\r
+  while (Instance != NULL) {\r
+\r
+    Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize;\r
+\r
+    if ((CompareMem (Instance, Single, Size) != 0)) {\r
+      //\r
+      // Append the device path instance which does not match with Single\r
+      //\r
+      TempNewDevicePath = NewDevicePath;\r
+      NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);\r
+      if (TempNewDevicePath != NULL) {\r
+        FreePool(TempNewDevicePath);\r
+      }\r
+    }\r
+    FreePool(Instance);\r
+    Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);\r
+    InstanceSize  -= END_DEVICE_PATH_LENGTH;\r
+  }\r
+\r
+  return NewDevicePath;\r
+}\r
+\r
+/**\r
+  Function compares a device path data structure to that of all the nodes of a\r
+  second device path instance.\r
+\r
+  @param  Multi                 A pointer to a multi-instance device path data\r
+                                structure.\r
+  @param  Single                A pointer to a single-instance device path data\r
+                                structure.\r
+\r
+  @retval TRUE                  If the Single device path is contained within Multi device path.\r
+  @retval FALSE                 The Single device path is not match within Multi device path.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BdsLibMatchDevicePaths (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Multi,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *Single\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+\r
+  if (Multi == NULL || Single  == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DevicePath      = Multi;\r
+  DevicePathInst  = GetNextDevicePathInstance (&DevicePath, &Size);\r
+\r
+  //\r
+  // Search for the match of 'Single' in 'Multi'\r
+  //\r
+  while (DevicePathInst != NULL) {\r
+    //\r
+    // If the single device path is found in multiple device paths,\r
+    // return success\r
+    //\r
+    if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
+      FreePool (DevicePathInst);\r
+      return TRUE;\r
+    }\r
+\r
+    FreePool (DevicePathInst);\r
+    DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function prints a series of strings.\r
+\r
+  @param  ConOut                Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+  @param  ...                   A variable argument list containing series of\r
+                                strings, the last string must be NULL.\r
+\r
+  @retval EFI_SUCCESS           Success print out the string using ConOut.\r
+  @retval EFI_STATUS            Return the status of the ConOut->OutputString ().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibOutputStrings (\r
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST     Args;\r
+  EFI_STATUS  Status;\r
+  CHAR16      *String;\r
+\r
+  Status = EFI_SUCCESS;\r
+  VA_START (Args, ConOut);\r
+\r
+  while (!EFI_ERROR (Status)) {\r
+    //\r
+    // If String is NULL, then it's the end of the list\r
+    //\r
+    String = VA_ARG (Args, CHAR16 *);\r
+    if (String != NULL) {\r
+      break;\r
+    }\r
+\r
+    Status = ConOut->OutputString (ConOut, String);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+  \r
+  VA_END(Args);\r
+  return Status;\r
+}\r
+\r
+//\r
+//  Following are BDS Lib functions which  contain all the code about setup browser reset reminder feature.\r
+//  Setup Browser reset reminder feature is that an reset reminder will be given before user leaves the setup browser  if\r
+//  user change any option setting which needs a reset to be effective, and  the reset will be applied according to  the user selection.\r
+//\r
+\r
+\r
+/**\r
+  Enable the setup browser reset reminder feature.\r
+  This routine is used in platform tip. If the platform policy need the feature, use the routine to enable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetReminderFeature (\r
+  VOID\r
+  )\r
+{\r
+  mFeaturerSwitch = TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Disable the setup browser reset reminder feature.\r
+  This routine is used in platform tip. If the platform policy do not want the feature, use the routine to disable it.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetReminderFeature (\r
+  VOID\r
+  )\r
+{\r
+  mFeaturerSwitch = FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Record the info that  a reset is required.\r
+  A  module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableResetRequired (\r
+  VOID\r
+  )\r
+{\r
+  mResetRequired = TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Record the info that  no reset is required.\r
+  A  module boolean variable is used to record whether a reset is required.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableResetRequired (\r
+  VOID\r
+  )\r
+{\r
+  mResetRequired = FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Check whether platform policy enable the reset reminder feature. The default is enabled.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetReminderFeatureEnable (\r
+  VOID\r
+  )\r
+{\r
+  return mFeaturerSwitch;\r
+}\r
+\r
+\r
+/**\r
+  Check if  user changed any option setting which needs a system reset to be effective.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsResetRequired (\r
+  VOID\r
+  )\r
+{\r
+  return mResetRequired;\r
+}\r
+\r
+\r
+/**\r
+  Check whether a reset is needed, and finish the reset reminder feature.\r
+  If a reset is needed, Popup a menu to notice user, and finish the feature\r
+  according to the user selection.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupResetReminder (\r
+  VOID\r
+  )\r
+{\r
+  EFI_INPUT_KEY                 Key;\r
+  CHAR16                        *StringBuffer1;\r
+  CHAR16                        *StringBuffer2;\r
+\r
+\r
+  //\r
+  //check any reset required change is applied? if yes, reset system\r
+  //\r
+  if (IsResetReminderFeatureEnable ()) {\r
+    if (IsResetRequired ()) {\r
+\r
+      StringBuffer1 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+      ASSERT (StringBuffer1 != NULL);\r
+      StringBuffer2 = AllocateZeroPool (MAX_STRING_LEN * sizeof (CHAR16));\r
+      ASSERT (StringBuffer2 != NULL);\r
+      StrCpy (StringBuffer1, L"Configuration changed. Reset to apply it Now ? ");\r
+      StrCpy (StringBuffer2, L"Enter (YES)  /   Esc (NO)");\r
+      //\r
+      // Popup a menu to notice user\r
+      //\r
+      do {\r
+        IfrLibCreatePopUp (2, &Key, StringBuffer1, StringBuffer2);\r
+      } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+      FreePool (StringBuffer1);\r
+      FreePool (StringBuffer2);\r
+      //\r
+      // If the user hits the YES Response key, reset\r
+      //\r
+      if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+      }\r
+      gST->ConOut->ClearScreen (gST->ConOut);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get the headers (dos, image, optional header) from an image\r
+\r
+  @param  Device                SimpleFileSystem device handle\r
+  @param  FileName              File name for the image\r
+  @param  DosHeader             Pointer to dos header\r
+  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.\r
+\r
+  @retval EFI_SUCCESS           Successfully get the machine type.\r
+  @retval EFI_NOT_FOUND         The file is not found.\r
+  @retval EFI_LOAD_ERROR        File is not a valid image file.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibGetImageHeader (\r
+  IN  EFI_HANDLE                  Device,\r
+  IN  CHAR16                      *FileName,\r
+  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,\r
+  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Volume;\r
+  EFI_FILE_HANDLE                  Root;\r
+  EFI_FILE_HANDLE                  ThisFile;\r
+  UINTN                            BufferSize;\r
+  UINT64                           FileSize;\r
+  EFI_FILE_INFO                    *Info;\r
+\r
+  Root     = NULL;\r
+  ThisFile = NULL;\r
+  //\r
+  // Handle the file system interface to the device\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Device,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID *) &Volume\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = Volume->OpenVolume (\r
+                     Volume,\r
+                     &Root\r
+                     );\r
+  if (EFI_ERROR (Status)) {\r
+    Root = NULL;\r
+    goto Done;\r
+  }\r
+\r
+  Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Get file size\r
+  //\r
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;\r
+  do {\r
+    Info   = NULL;\r
+    Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    Status = ThisFile->GetInfo (\r
+                         ThisFile,\r
+                         &gEfiFileInfoGuid,\r
+                         &BufferSize,\r
+                         Info\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      FreePool (Info);\r
+      goto Done;\r
+    }\r
+    FreePool (Info);\r
+  } while (TRUE);\r
+\r
+  FileSize = Info->FileSize;\r
+  FreePool (Info);\r
+\r
+  //\r
+  // Read dos header\r
+  //\r
+  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+  Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader);\r
+  if (EFI_ERROR (Status) ||\r
+      BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) ||\r
+      FileSize <= DosHeader->e_lfanew ||\r
+      DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    Status = EFI_LOAD_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Move to PE signature\r
+  //\r
+  Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew);\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_LOAD_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Read and check PE signature\r
+  //\r
+  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+  Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32);\r
+  if (EFI_ERROR (Status) ||\r
+      BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) ||\r
+      Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    Status = EFI_LOAD_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Check PE32 or PE32+ magic\r
+  //\r
+  if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC &&\r
+      Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    Status = EFI_LOAD_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+ Done:\r
+  if (ThisFile != NULL) {\r
+    ThisFile->Close (ThisFile);\r
+  }\r
+  if (Root != NULL) {\r
+    Root->Close (Root);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This routine is a notification function for legayc boot or exit boot\r
+  service event. It will adjust the memory information for different\r
+  memory type and save them into the variables for next boot.\r
+\r
+\r
+  @param Event           The event that triggered this notification function.\r
+  @param Context         Pointer to the notification functions context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsSetMemoryTypeInformationVariable (\r
+  EFI_EVENT  Event,\r
+  VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;\r
+  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;\r
+  UINTN                        VariableSize;\r
+  BOOLEAN                      UpdateRequired;\r
+  UINTN                        Index;\r
+  UINTN                        Index1;\r
+  UINT32                       Previous;\r
+  UINT32                       Current;\r
+  UINT32                       Next;\r
+  EFI_HOB_GUID_TYPE            *GuidHob;\r
+\r
+  UpdateRequired = FALSE;\r
+\r
+  //\r
+  // Retrieve the current memory usage statistics.  If they are not found, then\r
+  // no adjustments can be made to the Memory Type Information variable.\r
+  //\r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEfiMemoryTypeInformationGuid,\r
+             (VOID **) &CurrentMemoryTypeInformation\r
+             );\r
+  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Get the Memory Type Information settings from Hob if they exist,\r
+  // PEI is responsible for getting them from variable and build a Hob to save them.\r
+  // If the previous Memory Type Information is not available, then set defaults\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
+  if (GuidHob == NULL) {\r
+    //\r
+    // If Platform has not built Memory Type Info into the Hob, just return.\r
+    //\r
+    return;\r
+  }\r
+  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
+  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
+\r
+  //\r
+  // Use a heuristic to adjust the Memory Type Information for the next boot\r
+  //\r
+  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
+\r
+    Current = 0;\r
+    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {\r
+      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {\r
+        Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {\r
+      continue;\r
+    }\r
+\r
+    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;\r
+\r
+    //\r
+    // Write next varible to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail\r
+    //\r
+    if (Current > Previous) {\r
+      Next = Current + (Current >> 2);\r
+    } else {\r
+      Next = Previous;\r
+    }\r
+    if (Next > 0 && Next < 4) {\r
+      Next = 4;\r
+    }\r
+\r
+    if (Next != Previous) {\r
+      PreviousMemoryTypeInformation[Index].NumberOfPages = Next;\r
+      UpdateRequired = TRUE;\r
+    }\r
+\r
+  }\r
+\r
+  //\r
+  // If any changes were made to the Memory Type Information settings, then set the new variable value\r
+  //\r
+  if (UpdateRequired) {\r
+    Status = gRT->SetVariable (\r
+          EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+          &gEfiMemoryTypeInformationGuid,\r
+          EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+          VariableSize,\r
+          PreviousMemoryTypeInformation\r
+          );\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+/**\r
+  This routine register a function to adjust the different type memory page number\r
+  just before booting and save the updated info into the variable for next boot to use.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibSaveMemoryTypeInformation (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_EVENT                    ReadyToBootEvent;\r
+\r
+  Status = EfiCreateEventReadyToBootEx (\r
+           TPL_CALLBACK,\r
+           BdsSetMemoryTypeInformationVariable,\r
+           NULL,\r
+           &ReadyToBootEvent\r
+           );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR,"Bds Set Memory Type Informationa Variable Fails\n"));\r
+  }\r
+\r
+}\r
+\r
+\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/DevicePath.c
new file mode 100644 (file)
index 0000000..135fa63
--- /dev/null
@@ -0,0 +1,1485 @@
+/** @file\r
+  BDS internal function define the default device path string, it can be\r
+  replaced by platform device path.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+/**\r
+  Concatenates a formatted unicode string to allocated pool.\r
+  The caller must free the resulting buffer.\r
+\r
+  @param  Str      Tracks the allocated pool, size in use, and amount of pool allocated.\r
+  @param  fmt      The format string\r
+  @param  ...      The data will be printed.\r
+\r
+  @return Allocated buffer with the formatted string printed in it.\r
+          The caller must free the allocated buffer.\r
+          The buffer allocation is not packed.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+CatPrint (\r
+  IN OUT POOL_PRINT   *Str,\r
+  IN CHAR16           *fmt,\r
+  ...\r
+  )\r
+{\r
+  UINT16  *AppendStr;\r
+  VA_LIST Args;\r
+  UINTN   StringSize;\r
+\r
+  AppendStr = AllocateZeroPool (0x1000);\r
+  if (AppendStr == NULL) {\r
+    return Str->str;\r
+  }\r
+\r
+  VA_START (Args, fmt);\r
+  UnicodeVSPrint (AppendStr, 0x1000, fmt, Args);\r
+  VA_END (Args);\r
+  if (NULL == Str->str) {\r
+    StringSize   = StrSize (AppendStr);\r
+    Str->str  = AllocateZeroPool (StringSize);\r
+    ASSERT (Str->str != NULL);\r
+  } else {\r
+    StringSize = StrSize (AppendStr);\r
+    StringSize += (StrSize (Str->str) - sizeof (UINT16));\r
+\r
+    Str->str = ReallocatePool (\r
+                StrSize (Str->str),\r
+                StringSize,\r
+                Str->str\r
+                );\r
+    ASSERT (Str->str != NULL);\r
+  }\r
+\r
+  Str->maxlen = MAX_CHAR * sizeof (UINT16);\r
+  if (StringSize < Str->maxlen) {\r
+    StrCat (Str->str, AppendStr);\r
+    Str->len = StringSize - sizeof (UINT16);\r
+  }\r
+\r
+  FreePool (AppendStr);\r
+  return Str->str;\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPci (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  PCI_DEVICE_PATH *Pci;\r
+\r
+  Pci = DevPath;\r
+  CatPrint (Str, L"Pci(%x|%x)", (UINTN) Pci->Device, (UINTN) Pci->Function);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathPccard (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  PCCARD_DEVICE_PATH  *Pccard;\r
+\r
+  Pccard = DevPath;\r
+  CatPrint (Str, L"Pcmcia(Function%x)", (UINTN) Pccard->FunctionNumber);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMemMap (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEMMAP_DEVICE_PATH  *MemMap;\r
+\r
+  MemMap = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"MemMap(%d:%lx-%lx)",\r
+    MemMap->MemoryType,\r
+    MemMap->StartingAddress,\r
+    MemMap->EndingAddress\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathController (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CONTROLLER_DEVICE_PATH  *Controller;\r
+\r
+  Controller = DevPath;\r
+  CatPrint (Str, L"Ctrl(%d)", (UINTN) Controller->ControllerNumber);\r
+}\r
+\r
+\r
+/**\r
+  Convert Vendor device path to device name.\r
+\r
+  @param  Str      The buffer store device name\r
+  @param  DevPath  Pointer to vendor device path\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DevPathVendor (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  VENDOR_DEVICE_PATH  *Vendor;\r
+  CHAR16              *Type;\r
+  UINTN               DataLength;\r
+  UINTN               Index;\r
+  UINT32              FlowControlMap;\r
+\r
+  UINT16              Info;\r
+\r
+  Vendor  = DevPath;\r
+\r
+  switch (DevicePathType (&Vendor->Header)) {\r
+  case HARDWARE_DEVICE_PATH:\r
+    Type = L"Hw";\r
+    break;\r
+\r
+  case MESSAGING_DEVICE_PATH:\r
+    Type = L"Msg";\r
+    if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {\r
+      CatPrint (Str, L"VenPcAnsi()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {\r
+      CatPrint (Str, L"VenVt100()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {\r
+      CatPrint (Str, L"VenVt100Plus()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {\r
+      CatPrint (Str, L"VenUft8()");\r
+      return ;\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid     )) {\r
+      FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);\r
+      switch (FlowControlMap & 0x00000003) {\r
+      case 0:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"None");\r
+        break;\r
+\r
+      case 1:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");\r
+        break;\r
+\r
+      case 2:\r
+        CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+\r
+      return ;\r
+\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {\r
+      CatPrint (\r
+        Str,\r
+        L"SAS(%lx,%lx,%x,",\r
+        ((SAS_DEVICE_PATH *) Vendor)->SasAddress,\r
+        ((SAS_DEVICE_PATH *) Vendor)->Lun,\r
+        ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort\r
+        );\r
+      Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);\r
+      if ((Info & 0x0f) == 0) {\r
+        CatPrint (Str, L"NoTopology,0,0,0,");\r
+      } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {\r
+        CatPrint (\r
+          Str,\r
+          L"%s,%s,%s,",\r
+          ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",\r
+          ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",\r
+          ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"\r
+          );\r
+        if ((Info & 0x0f) == 1) {\r
+          CatPrint (Str, L"0,");\r
+        } else {\r
+          CatPrint (Str, L"%x,", (UINTN) ((Info >> 8) & 0xff));\r
+        }\r
+      } else {\r
+        CatPrint (Str, L"0,0,0,0,");\r
+      }\r
+\r
+      CatPrint (Str, L"%x)", (UINTN) ((SAS_DEVICE_PATH *) Vendor)->Reserved);\r
+      return ;\r
+\r
+    } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {\r
+      CatPrint (Str, L"DebugPort()");\r
+      return ;\r
+    }\r
+    break;\r
+\r
+  case MEDIA_DEVICE_PATH:\r
+    Type = L"Media";\r
+    break;\r
+\r
+  default:\r
+    Type = L"?";\r
+    break;\r
+  }\r
+\r
+  CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);\r
+  DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);\r
+  if (DataLength > 0) {\r
+    CatPrint (Str, L",");\r
+    for (Index = 0; Index < DataLength; Index++) {\r
+      CatPrint (Str, L"%02x", (UINTN) ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);\r
+    }\r
+  }\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+\r
+  Acpi = DevPath;\r
+  if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+    CatPrint (Str, L"Acpi(PNP%04x,%x)", (UINTN)  EISA_ID_TO_NUM (Acpi->HID), (UINTN) Acpi->UID);\r
+  } else {\r
+    CatPrint (Str, L"Acpi(%08x,%x)", (UINTN) Acpi->HID, (UINTN) Acpi->UID);\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathExtendedAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_EXTENDED_HID_DEVICE_PATH   *ExtendedAcpi;\r
+  \r
+  //\r
+  // Index for HID, UID and CID strings, 0 for non-exist\r
+  //\r
+  UINT16                          HIDSTRIdx;\r
+  UINT16                          UIDSTRIdx;\r
+  UINT16                          CIDSTRIdx;\r
+  UINT16                          Index;\r
+  UINT16                          Length;\r
+  UINT16                          Anchor;\r
+  CHAR8                           *AsChar8Array;\r
+\r
+  ASSERT (Str != NULL);\r
+  ASSERT (DevPath != NULL);\r
+\r
+  HIDSTRIdx    = 0;\r
+  UIDSTRIdx    = 0;\r
+  CIDSTRIdx    = 0;\r
+  ExtendedAcpi = DevPath;\r
+  Length       = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);\r
+\r
+  ASSERT (Length >= 19);\r
+  AsChar8Array = (CHAR8 *) ExtendedAcpi;\r
+\r
+  //\r
+  // find HIDSTR\r
+  //\r
+  Anchor = 16;\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    HIDSTRIdx = Anchor;\r
+  }\r
+  //\r
+  // find UIDSTR\r
+  //\r
+  Anchor = (UINT16) (Index + 1);\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    UIDSTRIdx = Anchor;\r
+  }\r
+  //\r
+  // find CIDSTR\r
+  //\r
+  Anchor = (UINT16) (Index + 1);\r
+  for (Index = Anchor; Index < Length && AsChar8Array[Index] != '\0'; Index++) {\r
+    ;\r
+  }\r
+  if (Index > Anchor) {\r
+    CIDSTRIdx = Anchor;\r
+  }\r
+\r
+  if (HIDSTRIdx == 0 && CIDSTRIdx == 0 && ExtendedAcpi->UID == 0) {\r
+    CatPrint (Str, L"AcpiExp(");\r
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+    }\r
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN)  ExtendedAcpi->CID);\r
+    }\r
+    if (UIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\")");\r
+    }\r
+  } else {\r
+    CatPrint (Str, L"AcpiEx(");\r
+    if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN)  EISA_ID_TO_NUM (ExtendedAcpi->HID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->HID);\r
+    }\r
+    if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {\r
+      CatPrint (Str, L"PNP%04x,", (UINTN) EISA_ID_TO_NUM (ExtendedAcpi->CID));\r
+    } else {\r
+      CatPrint (Str, L"%08x,", (UINTN) ExtendedAcpi->CID);\r
+    }\r
+    CatPrint (Str, L"%x,", (UINTN) ExtendedAcpi->UID);\r
+\r
+    if (HIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\",");\r
+    }\r
+    if (CIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\",");\r
+    }\r
+    if (UIDSTRIdx != 0) {\r
+      CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);\r
+    } else {\r
+      CatPrint (Str, L"\"\")");\r
+    }\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAdrAcpi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ACPI_ADR_DEVICE_PATH    *AcpiAdr;\r
+  UINT16                  Index;\r
+  UINT16                  Length;\r
+  UINT16                  AdditionalAdrCount;\r
+\r
+  AcpiAdr            = DevPath;\r
+  Length             = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);\r
+  AdditionalAdrCount = (UINT16) ((Length - 8) / 4);\r
+\r
+  CatPrint (Str, L"AcpiAdr(%x", (UINTN) AcpiAdr->ADR);\r
+  for (Index = 0; Index < AdditionalAdrCount; Index++) {\r
+    CatPrint (Str, L",%x", (UINTN) *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));\r
+  }\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathAtapi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ATAPI_DEVICE_PATH *Atapi;\r
+\r
+  Atapi = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Ata(%s,%s)",\r
+    Atapi->PrimarySecondary ? L"Secondary" : L"Primary",\r
+    Atapi->SlaveMaster ? L"Slave" : L"Master"\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathScsi (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  SCSI_DEVICE_PATH  *Scsi;\r
+\r
+  Scsi = DevPath;\r
+  CatPrint (Str, L"Scsi(Pun%x,Lun%x)", (UINTN) Scsi->Pun, (UINTN) Scsi->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFibre (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  FIBRECHANNEL_DEVICE_PATH  *Fibre;\r
+\r
+  Fibre = DevPath;\r
+  CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPath1394 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  F1394_DEVICE_PATH *F1394Path;\r
+\r
+  F1394Path = DevPath;\r
+  CatPrint (Str, L"1394(%g)", &F1394Path->Guid);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsb (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_DEVICE_PATH *Usb;\r
+\r
+  Usb = DevPath;\r
+  CatPrint (Str, L"Usb(%x,%x)", (UINTN) Usb->ParentPortNumber, (UINTN) Usb->InterfaceNumber);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbWWID (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_WWID_DEVICE_PATH  *UsbWWId;\r
+\r
+  UsbWWId = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"UsbWwid(%x,%x,%x,\"WWID\")",\r
+    (UINTN) UsbWWId->VendorId,\r
+    (UINTN) UsbWWId->ProductId,\r
+    (UINTN) UsbWWId->InterfaceNumber\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathLogicalUnit (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;\r
+\r
+  LogicalUnit = DevPath;\r
+  CatPrint (Str, L"Unit(%x)", (UINTN) LogicalUnit->Lun);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUsbClass (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  USB_CLASS_DEVICE_PATH *UsbClass;\r
+\r
+  UsbClass = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Usb Class(%x,%x,%x,%x,%x)",\r
+    (UINTN) UsbClass->VendorId,\r
+    (UINTN) UsbClass->ProductId,\r
+    (UINTN) UsbClass->DeviceClass,\r
+    (UINTN) UsbClass->DeviceSubClass,\r
+    (UINTN) UsbClass->DeviceProtocol\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathSata (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  SATA_DEVICE_PATH *Sata;\r
+\r
+  Sata = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Sata(%x,%x,%x)",\r
+    (UINTN) Sata->HBAPortNumber,\r
+    (UINTN) Sata->PortMultiplierPortNumber,\r
+    (UINTN) Sata->Lun\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathI2O (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  I2O_DEVICE_PATH *I2OPath;\r
+\r
+  I2OPath = DevPath;\r
+  CatPrint (Str, L"I2O(%x)", (UINTN) I2OPath->Tid);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMacAddr (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MAC_ADDR_DEVICE_PATH  *MACDevPath;\r
+  UINTN                 HwAddressSize;\r
+  UINTN                 Index;\r
+\r
+  MACDevPath           = DevPath;\r
+\r
+  HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
+  if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) {\r
+    HwAddressSize = 6;\r
+  }\r
+\r
+  CatPrint (Str, L"Mac(");\r
+\r
+  for (Index = 0; Index < HwAddressSize; Index++) {\r
+    CatPrint (Str, L"%02x", (UINTN) MACDevPath->MacAddress.Addr[Index]);\r
+  }\r
+\r
+  CatPrint (Str, L")");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv4 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  IPv4_DEVICE_PATH  *IPDevPath;\r
+\r
+  IPDevPath = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"IPv4(%d.%d.%d.%d:%d)",\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[0],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[1],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[2],\r
+    (UINTN) IPDevPath->RemoteIpAddress.Addr[3],\r
+    (UINTN) IPDevPath->RemotePort\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathIPv6 (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  IPv6_DEVICE_PATH  *IPv6DevPath;\r
+\r
+  IPv6DevPath = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[0],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[1],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[2],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[3],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[4],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[5],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[6],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[7],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[8],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[9],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[10],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[11],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[12],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[13],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[14],\r
+    (UINTN) IPv6DevPath->RemoteIpAddress.Addr[15]\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathInfiniBand (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  INFINIBAND_DEVICE_PATH  *InfiniBand;\r
+\r
+  InfiniBand = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"Infiniband(%x,%g,%lx,%lx,%lx)",\r
+    (UINTN) InfiniBand->ResourceFlags,\r
+    InfiniBand->PortGid,\r
+    InfiniBand->ServiceId,\r
+    InfiniBand->TargetPortId,\r
+    InfiniBand->DeviceId\r
+    );\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathUart (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  UART_DEVICE_PATH  *Uart;\r
+  CHAR8             Parity;\r
+\r
+  Uart = DevPath;\r
+  switch (Uart->Parity) {\r
+  case 0:\r
+    Parity = 'D';\r
+    break;\r
+\r
+  case 1:\r
+    Parity = 'N';\r
+    break;\r
+\r
+  case 2:\r
+    Parity = 'E';\r
+    break;\r
+\r
+  case 3:\r
+    Parity = 'O';\r
+    break;\r
+\r
+  case 4:\r
+    Parity = 'M';\r
+    break;\r
+\r
+  case 5:\r
+    Parity = 'S';\r
+    break;\r
+\r
+  default:\r
+    Parity = 'x';\r
+    break;\r
+  }\r
+\r
+  if (Uart->BaudRate == 0) {\r
+    CatPrint (Str, L"Uart(DEFAULT,%c,", Parity);\r
+  } else {\r
+    CatPrint (Str, L"Uart(%d,%c,", Uart->BaudRate, Parity);\r
+  }\r
+\r
+  if (Uart->DataBits == 0) {\r
+    CatPrint (Str, L"D,");\r
+  } else {\r
+    CatPrint (Str, L"%d,", (UINTN) Uart->DataBits);\r
+  }\r
+\r
+  switch (Uart->StopBits) {\r
+  case 0:\r
+    CatPrint (Str, L"D)");\r
+    break;\r
+\r
+  case 1:\r
+    CatPrint (Str, L"1)");\r
+    break;\r
+\r
+  case 2:\r
+    CatPrint (Str, L"1.5)");\r
+    break;\r
+\r
+  case 3:\r
+    CatPrint (Str, L"2)");\r
+    break;\r
+\r
+  default:\r
+    CatPrint (Str, L"x)");\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathiSCSI (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  ISCSI_DEVICE_PATH_WITH_NAME *IScsi;\r
+  UINT16                      Options;\r
+\r
+  ASSERT (Str != NULL);\r
+  ASSERT (DevPath != NULL);\r
+\r
+  IScsi = DevPath;\r
+  CatPrint (\r
+    Str,\r
+    L"iSCSI(%s,%x,%lx,",\r
+    IScsi->iSCSITargetName,\r
+    IScsi->TargetPortalGroupTag,\r
+    IScsi->Lun\r
+    );\r
+\r
+  Options = IScsi->LoginOption;\r
+  CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+  CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");\r
+  if (((Options >> 11) & 0x0001) != 0) {\r
+    CatPrint (Str, L"%s,", L"None");\r
+  } else if (((Options >> 12) & 0x0001) != 0) {\r
+    CatPrint (Str, L"%s,", L"CHAP_UNI");\r
+  } else {\r
+    CatPrint (Str, L"%s,", L"CHAP_BI");\r
+\r
+  }\r
+\r
+  CatPrint (Str, L"%s)", (IScsi->NetworkProtocol == 0) ? L"TCP" : L"reserved");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathHardDrive (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  HARDDRIVE_DEVICE_PATH *Hd;\r
+\r
+  Hd = DevPath;\r
+  switch (Hd->SignatureType) {\r
+  case SIGNATURE_TYPE_MBR:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,Sig%08x)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (UINTN) *((UINT32 *) (&(Hd->Signature[0])))\r
+      );\r
+    break;\r
+\r
+  case SIGNATURE_TYPE_GUID:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,Sig%g)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (EFI_GUID *) &(Hd->Signature[0])\r
+      );\r
+    break;\r
+\r
+  default:\r
+    CatPrint (\r
+      Str,\r
+      L"HD(Part%d,MBRType=%02x,SigType=%02x)",\r
+      (UINTN) Hd->PartitionNumber,\r
+      (UINTN) Hd->MBRType,\r
+      (UINTN) Hd->SignatureType\r
+      );\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathCDROM (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CDROM_DEVICE_PATH *Cd;\r
+\r
+  Cd = DevPath;\r
+  CatPrint (Str, L"CDROM(Entry%x)", (UINTN) Cd->BootEntry);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFilePath (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  FILEPATH_DEVICE_PATH  *Fp;\r
+\r
+  Fp = DevPath;\r
+  CatPrint (Str, L"%s", Fp->PathName);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathMediaProtocol (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_PROTOCOL_DEVICE_PATH  *MediaProt;\r
+\r
+  MediaProt = DevPath;\r
+  CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathFvFilePath (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+\r
+  FvFilePath = DevPath;\r
+  CatPrint (Str, L"%g", &FvFilePath->FvFileName);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathBssBss (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  BBS_BBS_DEVICE_PATH *Bbs;\r
+  CHAR16              *Type;\r
+\r
+  Bbs = DevPath;\r
+  switch (Bbs->DeviceType) {\r
+  case BBS_TYPE_FLOPPY:\r
+    Type = L"Floppy";\r
+    break;\r
+\r
+  case BBS_TYPE_HARDDRIVE:\r
+    Type = L"Harddrive";\r
+    break;\r
+\r
+  case BBS_TYPE_CDROM:\r
+    Type = L"CDROM";\r
+    break;\r
+\r
+  case BBS_TYPE_PCMCIA:\r
+    Type = L"PCMCIA";\r
+    break;\r
+\r
+  case BBS_TYPE_USB:\r
+    Type = L"Usb";\r
+    break;\r
+\r
+  case BBS_TYPE_EMBEDDED_NETWORK:\r
+    Type = L"Net";\r
+    break;\r
+\r
+  case BBS_TYPE_BEV:\r
+    Type = L"BEV";\r
+    break;\r
+\r
+  default:\r
+    Type = L"?";\r
+    break;\r
+  }\r
+  CatPrint (Str, L"Legacy-%s", Type);\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathEndInstance (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CatPrint (Str, L",");\r
+}\r
+\r
+/**\r
+  Convert Device Path to a Unicode string for printing.\r
+\r
+  @param Str             The buffer holding the output string.\r
+                         This buffer contains the length of the\r
+                         string and the maixmum length reserved\r
+                         for the string buffer.\r
+  @param DevPath         The device path.\r
+\r
+**/\r
+VOID\r
+DevPathNodeUnknown (\r
+  IN OUT POOL_PRINT       *Str,\r
+  IN VOID                 *DevPath\r
+  )\r
+{\r
+  CatPrint (Str, L"?");\r
+}\r
+\r
+DEVICE_PATH_STRING_TABLE  DevPathTable[] = {\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_PCI_DP,\r
+    DevPathPci\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_PCCARD_DP,\r
+    DevPathPccard\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_MEMMAP_DP,\r
+    DevPathMemMap\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    HARDWARE_DEVICE_PATH,\r
+    HW_CONTROLLER_DP,\r
+    DevPathController\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_DP,\r
+    DevPathAcpi\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_EXTENDED_DP,\r
+    DevPathExtendedAcpi\r
+  },\r
+  {\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_ADR_DP,\r
+    DevPathAdrAcpi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_ATAPI_DP,\r
+    DevPathAtapi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_SCSI_DP,\r
+    DevPathScsi\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_FIBRECHANNEL_DP,\r
+    DevPathFibre\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_1394_DP,\r
+    DevPath1394\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_DP,\r
+    DevPathUsb\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_WWID_DP,\r
+    DevPathUsbWWID\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_DEVICE_LOGICAL_UNIT_DP,\r
+    DevPathLogicalUnit\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_USB_CLASS_DP,\r
+    DevPathUsbClass\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_SATA_DP,\r
+    DevPathSata\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_I2O_DP,\r
+    DevPathI2O\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_MAC_ADDR_DP,\r
+    DevPathMacAddr\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_IPv4_DP,\r
+    DevPathIPv4\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_IPv6_DP,\r
+    DevPathIPv6\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_INFINIBAND_DP,\r
+    DevPathInfiniBand\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_UART_DP,\r
+    DevPathUart\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    MESSAGING_DEVICE_PATH,\r
+    MSG_ISCSI_DP,\r
+    DevPathiSCSI\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_HARDDRIVE_DP,\r
+    DevPathHardDrive\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_CDROM_DP,\r
+    DevPathCDROM\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_VENDOR_DP,\r
+    DevPathVendor\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_FILEPATH_DP,\r
+    DevPathFilePath\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_PROTOCOL_DP,\r
+    DevPathMediaProtocol\r
+  },\r
+  {\r
+    MEDIA_DEVICE_PATH,\r
+    MEDIA_PIWG_FW_FILE_DP,\r
+    DevPathFvFilePath\r
+  },\r
+  {\r
+    BBS_DEVICE_PATH,\r
+    BBS_BBS_DP,\r
+    DevPathBssBss\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_INSTANCE_DEVICE_PATH_SUBTYPE,\r
+    DevPathEndInstance\r
+  },\r
+  {\r
+    0,\r
+    0,\r
+    NULL\r
+  }\r
+};\r
+\r
+\r
+/**\r
+  This function converts an input device structure to a Unicode string.\r
+\r
+  @param DevPath                  A pointer to the device path structure.\r
+\r
+  @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+DevicePathToStr (\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  )\r
+{\r
+  POOL_PRINT                Str;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;\r
+  VOID (*DumpNode) (POOL_PRINT *, VOID *);\r
+\r
+  UINTN Index;\r
+  UINTN NewSize;\r
+\r
+  EFI_STATUS                       Status;\r
+  CHAR16                           *ToText;\r
+  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+\r
+  ZeroMem (&Str, sizeof (Str));\r
+\r
+  if (DevPath == NULL) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDevicePathToTextProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &DevPathToText\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    ToText = DevPathToText->ConvertDevicePathToText (\r
+                              DevPath,\r
+                              FALSE,\r
+                              TRUE\r
+                              );\r
+    ASSERT (ToText != NULL);\r
+    return ToText;\r
+  }\r
+\r
+  //\r
+  // Process each device path node\r
+  //\r
+  DevPathNode = DevPath;\r
+  while (!IsDevicePathEnd (DevPathNode)) {\r
+    //\r
+    // Find the handler to dump this device path node\r
+    //\r
+    DumpNode = NULL;\r
+    for (Index = 0; DevPathTable[Index].Function; Index += 1) {\r
+\r
+      if (DevicePathType (DevPathNode) == DevPathTable[Index].Type &&\r
+          DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType\r
+          ) {\r
+        DumpNode = DevPathTable[Index].Function;\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // If not found, use a generic function\r
+    //\r
+    if (!DumpNode) {\r
+      DumpNode = DevPathNodeUnknown;\r
+    }\r
+    //\r
+    //  Put a path seperator in if needed\r
+    //\r
+    if (Str.len && DumpNode != DevPathEndInstance) {\r
+      CatPrint (&Str, L"/");\r
+    }\r
+    //\r
+    // Print this node of the device path\r
+    //\r
+    DumpNode (&Str, DevPathNode);\r
+\r
+    //\r
+    // Next device path node\r
+    //\r
+    DevPathNode = NextDevicePathNode (DevPathNode);\r
+  }\r
+\r
+Done:\r
+  NewSize = (Str.len + 1) * sizeof (CHAR16);\r
+  Str.str = ReallocatePool (NewSize, NewSize, Str.str);\r
+  ASSERT (Str.str != NULL);\r
+  Str.str[Str.len] = 0;\r
+  return Str.str;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf b/IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
new file mode 100644 (file)
index 0000000..fdce5f3
--- /dev/null
@@ -0,0 +1,114 @@
+#/** @file\r
+#  \r
+#  General BDS defines and produce general interfaces for platform BDS driver including:\r
+#  1) BDS boot policy interface;\r
+#  2) BDS boot device connect interface;\r
+#  3) BDS Misc interfaces for mainting boot variable, ouput string, etc.\r
+#  \r
+#  Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+#  All rights reserved. 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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = GenericBdsLib\r
+  FILE_GUID                      = e405ec31-ccaa-4dd4-83e8-0aec01703f7e\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = GenericBdsLib|DXE_DRIVER UEFI_APPLICATION \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  DevicePath.c\r
+  Performance.c\r
+  BdsConnect.c\r
+  BdsMisc.c\r
+  BdsConsole.c\r
+  BdsBoot.c\r
+  InternalBdsLib.h\r
+\r
+[Sources.IPF]\r
+  Ipf/ShadowRom.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  #\r
+  #This dependency is because of gEfiLegacyBiosProtocolGuid. It may be removed if a Library class is created to\r
+  #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols.\r
+  #\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  PeCoffGetEntryPointLib\r
+  BaseLib\r
+  HobLib\r
+  UefiRuntimeServicesTableLib\r
+  DxeServicesTableLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  PcdLib\r
+  PerformanceLib\r
+  TimerLib\r
+  PcdLib\r
+  DxeServicesLib\r
+\r
+[Guids]\r
+  gEfiVT100PlusGuid                             # ALWAYS_CONSUMED\r
+  gEfiMemoryTypeInformationGuid                 # ALWAYS_CONSUMED\r
+  gEfiVTUTF8Guid                                # ALWAYS_CONSUMED\r
+  gEfiShellFileGuid                             # ALWAYS_CONSUMED\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+  gEfiVT100Guid                                 # ALWAYS_CONSUMED\r
+  gEfiFileInfoGuid                              # ALWAYS_CONSUMED\r
+  gEfiPcAnsiGuid                                # ALWAYS_CONSUMED\r
+  gEfiGenericPlatformVariableGuid               # ALWAYS_CONSUMED\r
+  gEfiUartDevicePathGuid                        # ALWAYS_CONSUMED\r
+  gEfiSasDevicePathGuid                         # ALWAYS_CONSUMED\r
+  \r
+[Protocols]\r
+  gEfiSimpleFileSystemProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextOutProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiPciIoProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLoadedImageProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathToTextProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleNetworkProtocolGuid                 # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDebugPortProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextInProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBlockIoProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLegacyBiosProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiCpuArchProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFirmwareVolumeDispatchProtocolGuid        # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiAcpiS3SaveProtocolGuid\r
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUgaDrawProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiConsoleControlProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiOEMBadgingProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiFontProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[FeaturePcd.common]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport\r
+\r
+[Pcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDefaultBootFileName
\ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h
new file mode 100644 (file)
index 0000000..cb11b6e
--- /dev/null
@@ -0,0 +1,106 @@
+/** @file\r
+  BDS library definition, include the file and data structure\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _INTERNAL_BDS_LIB_H_\r
+#define _INTERNAL_BDS_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci22.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/DebugPort.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleNetwork.h>\r
+#include <Protocol/DevicePathToText.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/AcpiS3Save.h>\r
+#include <Protocol/Performance.h>\r
+#include <Protocol/FirmwareVolumeDispatch.h>\r
+#include <Protocol/OEMBadging.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiImage.h>\r
+\r
+\r
+#include <Guid/MemoryTypeInformation.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/PcAnsi.h>\r
+#include <Guid/ShellFile.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/Bmp.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+\r
+#define PERFORMANCE_SIGNATURE   SIGNATURE_32 ('P', 'e', 'r', 'f')\r
+#define PERF_TOKEN_SIZE         28\r
+#define PERF_TOKEN_LENGTH       (PERF_TOKEN_SIZE - 1)\r
+#define PERF_PEI_ENTRY_MAX_NUM  50\r
+\r
+typedef struct {\r
+  CHAR8   Token[PERF_TOKEN_SIZE];\r
+  UINT32  Duration;\r
+} PERF_DATA;\r
+\r
+typedef struct {\r
+  UINT64        BootToOs;\r
+  UINT64        S3Resume;\r
+  UINT32        S3EntryNum;\r
+  PERF_DATA     S3Entry[PERF_PEI_ENTRY_MAX_NUM];\r
+  UINT64        CpuFreq;\r
+  UINT64        BDSRaw;\r
+  UINT32        Count;\r
+  UINT32        Signiture;\r
+} PERF_HEADER;\r
+\r
+/**\r
+\r
+  Allocates a block of memory and writes performance data of booting into it.\r
+  OS can processing these record.\r
+  \r
+**/\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+  VOID\r
+  );\r
+\r
+#endif // _BDS_LIB_H_\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c
new file mode 100644 (file)
index 0000000..10e8f55
--- /dev/null
@@ -0,0 +1,46 @@
+/** @file\r
+  Shadow all option rom\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+UINT8 mShadowRomFlag = 0;\r
+\r
+/**\r
+  Shadow all opton ROM if the it is not done.\r
+**/\r
+VOID\r
+ShadowAllOptionRom(\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  //\r
+  // Rom shadow only do once.\r
+  //\r
+  if (mShadowRomFlag == 0) {\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiLegacyBiosProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &LegacyBios\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL);\r
+    }\r
+\r
+    mShadowRomFlag = 1;\r
+  }\r
+\r
+  return ;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/Performance.c
new file mode 100644 (file)
index 0000000..0e3f793
--- /dev/null
@@ -0,0 +1,316 @@
+/** @file\r
+  This file include the file which can help to get the system\r
+  performance, all the function will only include if the performance\r
+  switch is set.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "InternalBdsLib.h"\r
+\r
+PERF_HEADER               mPerfHeader;\r
+PERF_DATA                 mPerfData;\r
+\r
+/**\r
+  Get the short verion of PDB file name to be\r
+  used in performance data logging.\r
+\r
+  @param PdbFileName     The long PDB file name.\r
+  @param GaugeString     The output string to be logged by performance logger.\r
+\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+  IN  CONST CHAR8  *PdbFileName,\r
+  OUT       CHAR8  *GaugeString\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN Index1;\r
+  UINTN StartIndex;\r
+  UINTN EndIndex;\r
+\r
+  if (PdbFileName == NULL) {\r
+    AsciiStrCpy (GaugeString, " ");\r
+  } else {\r
+    StartIndex = 0;\r
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
+      ;\r
+\r
+    for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
+      if (PdbFileName[Index] == '\\') {\r
+        StartIndex = Index + 1;\r
+      }\r
+\r
+      if (PdbFileName[Index] == '.') {\r
+        EndIndex = Index;\r
+      }\r
+    }\r
+\r
+    Index1 = 0;\r
+    for (Index = StartIndex; Index < EndIndex; Index++) {\r
+      GaugeString[Index1] = PdbFileName[Index];\r
+      Index1++;\r
+      if (Index1 == PERF_TOKEN_LENGTH - 1) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    GaugeString[Index1] = 0;\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Get the name from the Driver handle, which can be a handle with\r
+  EFI_LOADED_IMAGE_PROTOCOL or EFI_DRIVER_BINDING_PROTOCOL installed.\r
+  This name can be used in performance data logging.\r
+\r
+  @param Handle          Driver handle.\r
+  @param GaugeString     The output string to be logged by performance logger.\r
+\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+  IN  EFI_HANDLE     Handle,\r
+  OUT CHAR8          *GaugeString\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_LOADED_IMAGE_PROTOCOL   *Image;\r
+  CHAR8                       *PdbFileName;\r
+  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+\r
+  AsciiStrCpy (GaugeString, " ");\r
+\r
+  //\r
+  // Get handle name from image protocol\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiLoadedImageProtocolGuid,\r
+                  (VOID **) &Image\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                    Handle,\r
+                    &gEfiDriverBindingProtocolGuid,\r
+                    (VOID **) &DriverBinding,\r
+                    NULL,\r
+                    NULL,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return ;\r
+    }\r
+    //\r
+    // Get handle name from image protocol\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    DriverBinding->ImageHandle,\r
+                    &gEfiLoadedImageProtocolGuid,\r
+                    (VOID **) &Image\r
+                    );\r
+  }\r
+\r
+  PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
+\r
+  if (PdbFileName != NULL) {\r
+    GetShortPdbFileName (PdbFileName, GaugeString);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+\r
+  Allocates a block of memory and writes performance data of booting into it.\r
+  OS can processing these record.\r
+  \r
+**/\r
+VOID\r
+WriteBootToOsPerformanceData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_PHYSICAL_ADDRESS      AcpiLowMemoryBase;\r
+  UINT32                    AcpiLowMemoryLength;\r
+  UINT32                    LimitCount;\r
+  EFI_HANDLE                *Handles;\r
+  UINTN                     NoHandles;\r
+  CHAR8                     GaugeString[PERF_TOKEN_LENGTH];\r
+  UINT8                     *Ptr;\r
+  UINT32                    Index;\r
+  UINT64                    Ticker;\r
+  UINT64                    Freq;\r
+  UINT32                    Duration;\r
+  UINTN                     LogEntryKey;\r
+  CONST VOID                *Handle;\r
+  CONST CHAR8               *Token;\r
+  CONST CHAR8               *Module;\r
+  UINT64                    StartTicker;\r
+  UINT64                    EndTicker;\r
+  UINT64                    StartValue;\r
+  UINT64                    EndValue;\r
+  BOOLEAN                   CountUp;\r
+\r
+  //\r
+  // Retrive time stamp count as early as possilbe\r
+  //\r
+  Ticker  = GetPerformanceCounter ();\r
+\r
+  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
+  \r
+  Freq    = DivU64x32 (Freq, 1000);\r
+\r
+  mPerfHeader.CpuFreq = Freq;\r
+\r
+  //\r
+  // Record BDS raw performance data\r
+  //\r
+  if (EndValue >= StartValue) {\r
+    mPerfHeader.BDSRaw = Ticker - StartValue;\r
+    CountUp            = TRUE;\r
+  } else {\r
+    mPerfHeader.BDSRaw = StartValue - Ticker;\r
+    CountUp            = FALSE;\r
+  }\r
+\r
+  AcpiLowMemoryLength   = 0x2000;\r
+\r
+  //\r
+  // Allocate a block of memory that contain performance data to OS\r
+  //\r
+  Status = gBS->AllocatePages (\r
+                  AllocateAnyPages,\r
+                  EfiACPIReclaimMemory,\r
+                  EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),\r
+                  &AcpiLowMemoryBase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+\r
+  Ptr                   = (UINT8 *) ((UINT32) AcpiLowMemoryBase + sizeof (PERF_HEADER));\r
+  LimitCount            = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);\r
+\r
+  //\r
+  // Put Detailed performance data into memory\r
+  //\r
+  Handles = NULL;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePages (AcpiLowMemoryBase, 1);\r
+    return ;\r
+  }\r
+  \r
+  //\r
+  // Get DXE drivers performance\r
+  //\r
+  for (Index = 0; Index < NoHandles; Index++) {\r
+    Ticker = 0;\r
+    LogEntryKey = 0;\r
+    while ((LogEntryKey = GetPerformanceMeasurement (\r
+                            LogEntryKey,\r
+                            &Handle,\r
+                            &Token,\r
+                            &Module,\r
+                            &StartTicker,\r
+                            &EndTicker)) != 0) {\r
+      if ((Handle == Handles[Index]) && (EndTicker != 0)) {\r
+        Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+      }\r
+    }\r
+\r
+    Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+    if (Duration > 0) {\r
+\r
+      GetNameFromHandle (Handles[Index], GaugeString);\r
+\r
+      AsciiStrCpy (mPerfData.Token, GaugeString);\r
+      mPerfData.Duration = Duration;\r
+\r
+      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+      Ptr += sizeof (PERF_DATA);\r
+\r
+      mPerfHeader.Count++;\r
+      if (mPerfHeader.Count == LimitCount) {\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (Handles);\r
+\r
+  //\r
+  // Get inserted performance data\r
+  //\r
+  LogEntryKey = 0;\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Handle,\r
+                          &Token,\r
+                          &Module,\r
+                          &StartTicker,\r
+                          &EndTicker)) != 0) {\r
+    if (Handle == NULL && EndTicker != 0) {\r
+\r
+      ZeroMem (&mPerfData, sizeof (PERF_DATA));\r
+\r
+      AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);\r
+      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+\r
+      mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));\r
+      Ptr += sizeof (PERF_DATA);\r
+\r
+      mPerfHeader.Count++;\r
+      if (mPerfHeader.Count == LimitCount) {\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+Done:\r
+\r
+  mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;\r
+\r
+  //\r
+  // Put performance data to ACPI memory\r
+  //\r
+  CopyMem (\r
+    (UINTN *) (UINTN) AcpiLowMemoryBase,\r
+    &mPerfHeader,\r
+    sizeof (PERF_HEADER)\r
+    );\r
+\r
+  gRT->SetVariable (\r
+        L"PerfDataMemAddr",\r
+        &gEfiGenericPlatformVariableGuid,\r
+        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+        sizeof (EFI_PHYSICAL_ADDRESS),\r
+        &AcpiLowMemoryBase\r
+        );\r
+\r
+  return ;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Bds.h
new file mode 100644 (file)
index 0000000..56b709e
--- /dev/null
@@ -0,0 +1,141 @@
+/** @file\r
+  Head file for BDS Architectural Protocol implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _BDS_MODULE_H_\r
+#define _BDS_MODULE_H_\r
+\r
+#include <PiDxe.h>\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Guid/BootState.h>\r
+#include <Guid/DataHubRecords.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/CpuIo.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/DataHub.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/CapsuleVendor.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/SerialIo.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+#include <Protocol/Performance.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/ExtendedIfrSupportLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CapsuleLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/ExtendedHiiLib.h>\r
+\r
+\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \\r
+  CR ((_this),                                          \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE,                   \\r
+      Bds,                                              \\r
+      EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE          \\r
+      )\r
+\r
+/**\r
+\r
+  Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+  @param TitleForeground Foreground color for Title.\r
+  @param TitleBackground Background color for Title.\r
+  @param Title           Title above progress bar.\r
+  @param ProgressColor   Progress bar color.\r
+  @param Progress        Progress (0-100)\r
+  @param PreviousValue   The previous value of the progress.\r
+\r
+  @retval  EFI_STATUS       Success update the progress bar\r
+\r
+**/\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  IN CHAR16                        *Title,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  IN UINTN                         Progress,\r
+  IN UINTN                         PreviousValue\r
+  );\r
+\r
+//\r
+// Prototypes\r
+//\r
+\r
+/**\r
+\r
+  Install Boot Device Selection Protocol\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval  EFI_SUCEESS  BDS has finished initializing.\r
+                        Return the dispatcher and recall BDS.Entry\r
+  @retval  Other        Return status from AllocatePool() or gBS->InstallProtocolInterface\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                     ImageHandle,\r
+  IN EFI_SYSTEM_TABLE               *SystemTable\r
+  );\r
+\r
+/**\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the\r
+  consoles are initialized, and the boot options are tried.\r
+\r
+  @param This            Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN  EFI_BDS_ARCH_PROTOCOL *This\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf
new file mode 100644 (file)
index 0000000..c8136db
--- /dev/null
@@ -0,0 +1,164 @@
+#/** @file\r
+#\r
+#  BDSDxe module is core driver for BDS phase. \r
+#  When DxeCore dispatching all DXE driver, this module will produce architecture protocol \r
+#  gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry\r
+#  interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.\r
+#\r
+#  Generally, this module take reposiblity to connect all necessary devices for platform boot, \r
+#  these boot device path  are hold in PlatformBdsLib library instance produced by platform.\r
+#  For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select.\r
+#  For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, \r
+#  EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader.\r
+#\r
+#  BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which\r
+#  is used for user to configure boot option or maintain hardware device.\r
+#  \r
+#  Copyright (c) 2008, Intel Corporation. <BR>\r
+#  All rights reserved. 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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BdsDxe\r
+  FILE_GUID                      = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0 \r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+  ENTRY_POINT                    = BdsInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  FrontPage.h\r
+  Language.h\r
+  Bds.h\r
+  Hotkey.h\r
+  BootMaint/BBSsupport.h\r
+  BootMngr/BootManager.h\r
+  BootMaint/BootMaint.h\r
+  String.h\r
+  BootMaint/FormGuid.h\r
+  HwErrRecSupport.c\r
+  HwErrRecSupport.h\r
+\r
+  DeviceMngr/DeviceManager.h\r
+  DeviceMngr/DeviceManagerVfr.Vfr\r
+  DeviceMngr/DeviceManagerStrings.uni\r
+  DeviceMngr/DeviceManager.c\r
+  BootMngr/BootManagerVfr.Vfr\r
+  BootMngr/BootManagerStrings.uni\r
+  BootMngr/BootManager.c\r
+  BootMaint/FE.vfr\r
+  BootMaint/FileExplorer.c\r
+  BootMaint/BootMaint.c\r
+  BootMaint/BBSsupport.c\r
+  BootMaint/UpdatePage.c\r
+  BootMaint/Variable.c\r
+  BootMaint/Data.c\r
+  BootMaint/ConsoleOption.c\r
+  BootMaint/BootOption.c\r
+  BootMaint/BmLib.c\r
+  BootMaint/Bm.vfr\r
+  BootMaint/Bmstring.uni\r
+  Hotkey.c\r
+  MemoryTest.c\r
+  Capsules.c\r
+  Strings.uni\r
+  String.c\r
+  Language.c\r
+  FrontPageVfr.Vfr\r
+  FrontPageStrings.uni\r
+  FrontPage.c\r
+  BdsEntry.c\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  #\r
+  #This dependency is because of gEfiLegacyBiosProtocolGuid and gEfiDataHubProtocolGuid. It may be removed if a Library class is created to\r
+  #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols and Data Hub Protocols.\r
+  #\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  DevicePathLib\r
+  BaseLib\r
+  HobLib\r
+  UefiRuntimeServicesTableLib\r
+  IfrSupportLib\r
+  ExtendedIfrSupportLib\r
+  GenericBdsLib\r
+  ReportStatusCodeLib\r
+  PerformanceLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  PrintLib\r
+  HiiLib\r
+  ExtendedHiiLib\r
+  UefiDriverEntryPoint\r
+  PlatformBdsLib\r
+  CapsuleLib\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+  gEfiBootStateGuid                             # ALWAYS_CONSUMED\r
+  gEfiFileSystemVolumeLabelInfoIdGuid           # ALWAYS_CONSUMED\r
+  gEfiFileInfoGuid                              # ALWAYS_CONSUMED\r
+  gEfiGenericPlatformVariableGuid\r
+  gEfiMiscSubClassGuid\r
+  gEfiMemorySubClassGuid\r
+  gEfiProcessorSubClassGuid\r
+  gEfiCapsuleVendorGuid\r
+\r
+[Protocols]\r
+  gEfiHiiStringProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleFileSystemProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLoadFileProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBdsArchProtocolGuid                       # PROTOCOL ALWAYS_PRODUCED\r
+  gEfiDataHubProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGenericMemTestProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLegacyBiosProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiConsoleControlProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiDatabaseProtocolGuid                   # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUgaDrawProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiBlockIoProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGraphicsOutputProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSimpleTextInputExProtocolGuid             # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigRoutingProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiHiiConfigAccessProtocolGuid               # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiFormBrowser2ProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiSerialIoProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDevicePathProtocolGuid                    # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[FeaturePcd.common]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord\r
+  gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport\r
+\r
+[Pcd.common]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel\r
+\r
+[Depex]\r
+  gEfiHiiDatabaseProtocolGuid\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BdsEntry.c
new file mode 100644 (file)
index 0000000..d8bf26a
--- /dev/null
@@ -0,0 +1,363 @@
+/** @file\r
+  This module produce main entry for BDS phase - BdsEntry. \r
+  When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed\r
+  which contains interface of BdsEntry.\r
+  After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked\r
+  to enter BDS phase.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+#include "Hotkey.h"\r
+#include "HwErrRecSupport.h"\r
+\r
+///\r
+/// BDS arch protocol instance initial value.\r
+///\r
+/// Note: Current BDS not directly get the BootMode, DefaultBoot,\r
+/// TimeoutDefault, MemoryTestLevel value from the BDS arch protocol.\r
+/// Please refer to the library useage of BdsLibGetBootMode, BdsLibGetTimeout \r
+/// and PlatformBdsDiagnostics in BdsPlatform.c\r
+///\r
+EFI_BDS_ARCH_PROTOCOL_INSTANCE  gBdsInstanceTemplate = {\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,\r
+  NULL,\r
+  {BdsEntry},\r
+  0xFFFF,\r
+  TRUE,\r
+  0,\r
+  EXTENSIVE\r
+};\r
+\r
+UINT16                          *mBootNext = NULL;\r
+\r
+EFI_HANDLE                      mBdsImageHandle;\r
+\r
+/**\r
+\r
+  Install Boot Device Selection Protocol\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval  EFI_SUCEESS  BDS has finished initializing.\r
+                        Return the dispatcher and recall BDS.Entry\r
+  @retval  Other        Return status from AllocatePool() or gBS->InstallProtocolInterface\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  mBdsImageHandle = ImageHandle;\r
+\r
+  //\r
+  // Install protocol interface\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gBdsInstanceTemplate.Handle,\r
+                  &gEfiBdsArchProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gBdsInstanceTemplate.Bds\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This function attempts to boot for the boot order specified\r
+  by platform policy.\r
+\r
+**/\r
+VOID\r
+BdsBootDeviceSelect (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  LIST_ENTRY        *Link;\r
+  BDS_COMMON_OPTION *BootOption;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  UINT16            Timeout;\r
+  LIST_ENTRY        BootLists;\r
+  CHAR16            Buffer[20];\r
+  BOOLEAN           BootNextExist;\r
+  LIST_ENTRY        *LinkBootNext;\r
+\r
+  //\r
+  // Got the latest boot option\r
+  //\r
+  BootNextExist = FALSE;\r
+  LinkBootNext  = NULL;\r
+  InitializeListHead (&BootLists);\r
+\r
+  //\r
+  // First check the boot next option\r
+  //\r
+  ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+  if (mBootNext != NULL) {\r
+    //\r
+    // Indicate we have the boot next variable, so this time\r
+    // boot will always have this boot option\r
+    //\r
+    BootNextExist = TRUE;\r
+\r
+    //\r
+    // Clear the this variable so it's only exist in this time boot\r
+    //\r
+    gRT->SetVariable (\r
+          L"BootNext",\r
+          &gEfiGlobalVariableGuid,\r
+          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+          0,\r
+          mBootNext\r
+          );\r
+\r
+    //\r
+    // Add the boot next boot option\r
+    //\r
+    UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);\r
+    BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+    \r
+    //\r
+    // If fail to get boot option from variable, just return and do nothing.\r
+    //\r
+    if (BootOption == NULL) {\r
+      return;\r
+    }\r
+    \r
+    BootOption->BootCurrent = *mBootNext;\r
+  }\r
+  //\r
+  // Parse the boot order to get boot option\r
+  //\r
+  BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+  Link = BootLists.ForwardLink;\r
+\r
+  //\r
+  // Parameter check, make sure the loop will be valid\r
+  //\r
+  if (Link == NULL) {\r
+    return ;\r
+  }\r
+  //\r
+  // Here we make the boot in a loop, every boot success will\r
+  // return to the front page\r
+  //\r
+  for (;;) {\r
+    //\r
+    // Check the boot option list first\r
+    //\r
+    if (Link == &BootLists) {\r
+      //\r
+      // There are two ways to enter here:\r
+      // 1. There is no active boot option, give user chance to\r
+      //    add new boot option\r
+      // 2. All the active boot option processed, and there is no\r
+      //    one is success to boot, then we back here to allow user\r
+      //    add new active boot option\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+      InitializeListHead (&BootLists);\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Get the boot option from the link list\r
+    //\r
+    BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    //\r
+    // According to EFI Specification, if a load option is not marked\r
+    // as LOAD_OPTION_ACTIVE, the boot manager will not automatically\r
+    // load the option.\r
+    //\r
+    if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+      //\r
+      // skip the header of the link list, becuase it has no boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+      continue;\r
+    }\r
+    //\r
+    // Make sure the boot option device path connected,\r
+    // but ignore the BBS device path\r
+    //\r
+    if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+      //\r
+      // Notes: the internal shell can not been connected with device path\r
+      // so we do not check the status here\r
+      //\r
+      BdsLibConnectDevicePath (BootOption->DevicePath);\r
+    }\r
+    //\r
+    // All the driver options should have been processed since\r
+    // now boot will be performed.\r
+    //\r
+    Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Call platform action to indicate the boot fail\r
+      //\r
+      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+      PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+\r
+      //\r
+      // Check the next boot option\r
+      //\r
+      Link = Link->ForwardLink;\r
+\r
+    } else {\r
+      //\r
+      // Call platform action to indicate the boot success\r
+      //\r
+      BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); \r
+      PlatformBdsBootSuccess (BootOption);\r
+\r
+      //\r
+      // Boot success, then stop process the boot order, and\r
+      // present the boot manager menu, front page\r
+      //\r
+      Timeout = 0xffff;\r
+      PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+\r
+      //\r
+      // Rescan the boot option list, avoid pertential risk of the boot\r
+      // option change in front page\r
+      //\r
+      if (BootNextExist) {\r
+        LinkBootNext = BootLists.ForwardLink;\r
+      }\r
+\r
+      InitializeListHead (&BootLists);\r
+      if (LinkBootNext != NULL) {\r
+        //\r
+        // Reserve the boot next option\r
+        //\r
+        InsertTailList (&BootLists, LinkBootNext);\r
+      }\r
+\r
+      BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+      Link = BootLists.ForwardLink;\r
+    }\r
+  }\r
+\r
+}\r
+\r
+/**\r
+\r
+  Service routine for BdsInstance->Entry(). Devices are connected, the\r
+  consoles are initialized, and the boot options are tried.\r
+\r
+  @param This             Protocol Instance structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+  IN EFI_BDS_ARCH_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_BDS_ARCH_PROTOCOL_INSTANCE  *PrivateData;\r
+  LIST_ENTRY                      DriverOptionList;\r
+  LIST_ENTRY                      BootOptionList;\r
+  UINTN                           BootNextSize;\r
+\r
+  //\r
+  // Insert the performance probe\r
+  //\r
+  PERF_END (0, DXE_TOK, NULL, 0);\r
+  PERF_START (0, BDS_TOK, NULL, 0);\r
+\r
+  //\r
+  // Initialize the global system boot option and driver option\r
+  //\r
+  InitializeListHead (&DriverOptionList);\r
+  InitializeListHead (&BootOptionList);\r
+\r
+  //\r
+  // Initialize hotkey service\r
+  //\r
+  InitializeHotkeyService ();\r
+\r
+  //\r
+  // Get the BDS private data\r
+  //\r
+  PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);\r
+\r
+  //\r
+  // Do the platform init, can be customized by OEM/IBV\r
+  //\r
+  PERF_START (0, "PlatformBds", "BDS", 0);\r
+  PlatformBdsInit (PrivateData);\r
+\r
+  if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {\r
+    InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));\r
+  }\r
+  //\r
+  // bugbug: platform specific code\r
+  // Initialize the platform specific string and language\r
+  //\r
+  InitializeStringSupport ();\r
+  InitializeLanguage (TRUE);\r
+  InitializeFrontPage (TRUE);\r
+\r
+  //\r
+  // Set up the device list based on EFI 1.1 variables\r
+  // process Driver#### and Load the driver's in the\r
+  // driver option list\r
+  //\r
+  BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");\r
+  if (!IsListEmpty (&DriverOptionList)) {\r
+    BdsLibLoadDrivers (&DriverOptionList);\r
+  }\r
+  //\r
+  // Check if we have the boot next option\r
+  //\r
+  mBootNext = BdsLibGetVariableAndSize (\r
+                L"BootNext",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootNextSize\r
+                );\r
+\r
+  //\r
+  // Setup some platform policy here\r
+  //\r
+  PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);\r
+  PERF_END (0, "PlatformBds", "BDS", 0);\r
+\r
+  //\r
+  // BDS select the boot device to load OS\r
+  //\r
+  BdsBootDeviceSelect ();\r
+\r
+  //\r
+  // Only assert here since this is the right behavior, we should never\r
+  // return back to DxeCore.\r
+  //\r
+  ASSERT (FALSE);\r
+\r
+  return ;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
new file mode 100644 (file)
index 0000000..94261a0
--- /dev/null
@@ -0,0 +1,1663 @@
+/** @file\r
+  This function deal with the legacy boot option, it create, delete\r
+  and manage the legacy boot option, all legacy boot option is getting from\r
+  the legacy BBS table.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BBSsupport.h"\r
+\r
+/**\r
+\r
+  Translate the first n characters of an Ascii string to\r
+  Unicode characters. The count n is indicated by parameter\r
+  Size. If Size is greater than the length of string, then\r
+  the entire string is translated.\r
+\r
+\r
+  @param AStr               Pointer to input Ascii string.\r
+  @param Size               The number of characters to translate.\r
+  @param UStr               Pointer to output Unicode string buffer.\r
+\r
+**/\r
+VOID\r
+AsciiToUnicodeSize (\r
+  IN UINT8              *AStr,\r
+  IN UINTN              Size,\r
+  OUT UINT16            *UStr\r
+  )\r
+{\r
+  UINTN Idx;\r
+\r
+  Idx = 0;\r
+  while (AStr[Idx] != 0) {\r
+    UStr[Idx] = (CHAR16) AStr[Idx];\r
+    if (Idx == Size) {\r
+      break;\r
+    }\r
+\r
+    Idx++;\r
+  }\r
+  UStr[Idx] = 0;\r
+}\r
+\r
+/**\r
+  Build Legacy Device Name String according.\r
+\r
+  @param CurBBSEntry     BBS Table.\r
+  @param Index           Index.\r
+  @param BufSize         The buffer size.\r
+  @param BootString      The output string.\r
+\r
+**/\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN  BBS_TABLE                 *CurBBSEntry,\r
+  IN  UINTN                     Index,\r
+  IN  UINTN                     BufSize,\r
+  OUT CHAR16                    *BootString\r
+  )\r
+{\r
+  CHAR16  *Fmt;\r
+  CHAR16  *Type;\r
+  UINT8   *StringDesc;\r
+  CHAR16  Temp[80];\r
+\r
+  switch (Index) {\r
+  //\r
+  // Primary Master\r
+  //\r
+  case 1:\r
+    Fmt = L"Primary Master %s";\r
+    break;\r
+\r
+ //\r
+ // Primary Slave\r
+ //\r
+  case 2:\r
+    Fmt = L"Primary Slave %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Master\r
+  //\r
+  case 3:\r
+    Fmt = L"Secondary Master %s";\r
+    break;\r
+\r
+  //\r
+  // Secondary Slave\r
+  //\r
+  case 4:\r
+    Fmt = L"Secondary Slave %s";\r
+    break;\r
+\r
+  default:\r
+    Fmt = L"%s";\r
+    break;\r
+  }\r
+\r
+  switch (CurBBSEntry->DeviceType) {\r
+  case BBS_FLOPPY:\r
+    Type = L"Floppy";\r
+    break;\r
+\r
+  case BBS_HARDDISK:\r
+    Type = L"Harddisk";\r
+    break;\r
+\r
+  case BBS_CDROM:\r
+    Type = L"CDROM";\r
+    break;\r
+\r
+  case BBS_PCMCIA:\r
+    Type = L"PCMCIAe";\r
+    break;\r
+\r
+  case BBS_USB:\r
+    Type = L"USB";\r
+    break;\r
+\r
+  case BBS_EMBED_NETWORK:\r
+    Type = L"Network";\r
+    break;\r
+\r
+  case BBS_BEV_DEVICE:\r
+    Type = L"BEVe";\r
+    break;\r
+\r
+  case BBS_UNKNOWN:\r
+  default:\r
+    Type = L"Unknown";\r
+    break;\r
+  }\r
+  //\r
+  // If current BBS entry has its description then use it.\r
+  //\r
+  StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
+  if (NULL != StringDesc) {\r
+    //\r
+    // Only get fisrt 32 characters, this is suggested by BBS spec\r
+    //\r
+    AsciiToUnicodeSize (StringDesc, 32, Temp);\r
+    Fmt   = L"%s";\r
+    Type  = Temp;\r
+  }\r
+\r
+  //\r
+  // BbsTable 16 entries are for onboard IDE.\r
+  // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
+  //\r
+  if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {\r
+    Fmt = L"%s %d";\r
+    UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
+  } else {\r
+    UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Create a legacy boot option for the specified entry of\r
+  BBS table, save it as variable, and append it to the boot\r
+  order list.\r
+\r
+\r
+  @param CurrentBbsEntry    Pointer to current BBS table.\r
+  @param CurrentBbsDevPath  Pointer to the Device Path Protocol instance of BBS\r
+  @param Index              Index of the specified entry in BBS table.\r
+  @param BootOrderList      On input, the original boot order list.\r
+                            On output, the new boot order list attached with the\r
+                            created node.\r
+  @param BootOrderListSize  On input, the original size of boot order list.\r
+                            On output, the size of new boot order list.\r
+\r
+  @retval  EFI_SUCCESS             Boot Option successfully created.\r
+  @retval  EFI_OUT_OF_RESOURCES    Fail to allocate necessary memory.\r
+  @retval  Other                   Error occurs while setting variable.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateLegacyBootOption (\r
+  IN BBS_TABLE                        *CurrentBbsEntry,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         *CurrentBbsDevPath,\r
+  IN UINTN                            Index,\r
+  IN OUT UINT16                       **BootOrderList,\r
+  IN OUT UINTN                        *BootOrderListSize\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  UINT16               CurrentBootOptionNo;\r
+  UINT16               BootString[10];\r
+  UINT16               BootDesc[100];\r
+  CHAR8                HelpString[100];\r
+  UINT16               *NewBootOrderList;\r
+  UINTN                BufferSize;\r
+  UINTN                StringLen;\r
+  VOID                 *Buffer;\r
+  UINT8                *Ptr;\r
+  UINT16               CurrentBbsDevPathSize;\r
+  UINTN                BootOrderIndex;\r
+  UINTN                BootOrderLastIndex;\r
+  UINTN                ArrayIndex;\r
+  BOOLEAN              IndexNotFound;\r
+  BBS_BBS_DEVICE_PATH  *NewBbsDevPathNode;\r
+\r
+  if ((*BootOrderList) == NULL) {\r
+    CurrentBootOptionNo = 0;\r
+  } else {\r
+    for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
+      IndexNotFound = TRUE;\r
+      for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
+        if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
+          IndexNotFound = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (!IndexNotFound) {\r
+        continue;\r
+      } else {\r
+        break;\r
+      }\r
+    }\r
+\r
+    CurrentBootOptionNo = (UINT16) ArrayIndex;\r
+  }\r
+\r
+  UnicodeSPrint (\r
+    BootString,\r
+    sizeof (BootString),\r
+    L"Boot%04x",\r
+    CurrentBootOptionNo\r
+    );\r
+\r
+  BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
+\r
+  //\r
+  // Create new BBS device path node with description string\r
+  //\r
+  UnicodeStrToAsciiStr ((CONST CHAR16*)&BootDesc, (CHAR8*)&HelpString);\r
+\r
+  StringLen = AsciiStrLen (HelpString);\r
+  NewBbsDevPathNode = AllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+  if (NewBbsDevPathNode == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));\r
+  CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);\r
+  SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+\r
+  //\r
+  // Create entire new CurrentBbsDevPath with end node\r
+  //\r
+  CurrentBbsDevPath = AppendDevicePathNode (\r
+                        EndDevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode\r
+                        );\r
+   if (CurrentBbsDevPath == NULL) {\r
+    FreePool (NewBbsDevPathNode);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
+\r
+  BufferSize = sizeof (UINT32) +\r
+    sizeof (UINT16) +\r
+    StrSize (BootDesc) +\r
+    CurrentBbsDevPathSize +\r
+    sizeof (BBS_TABLE) +\r
+    sizeof (UINT16);\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (Buffer == NULL) {\r
+    FreePool (NewBbsDevPathNode);\r
+    FreePool (CurrentBbsDevPath);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr               = (UINT8 *) Buffer;\r
+\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  Ptr += sizeof (UINT32);\r
+\r
+  *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    BootDesc,\r
+    StrSize (BootDesc)\r
+    );\r
+  Ptr += StrSize (BootDesc);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsDevPath,\r
+    CurrentBbsDevPathSize\r
+    );\r
+  Ptr += CurrentBbsDevPathSize;\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    CurrentBbsEntry,\r
+    sizeof (BBS_TABLE)\r
+    );\r
+\r
+  Ptr += sizeof (BBS_TABLE);\r
+  *((UINT16 *) Ptr) = (UINT16) Index;\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+\r
+  FreePool (Buffer);\r
+  \r
+  Buffer = NULL;\r
+\r
+  NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+  if (NULL == NewBootOrderList) {\r
+    FreePool (NewBbsDevPathNode);\r
+    FreePool (CurrentBbsDevPath);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (*BootOrderList != NULL) {\r
+    CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+    FreePool (*BootOrderList);\r
+  }\r
+\r
+  BootOrderLastIndex                    = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+  NewBootOrderList[BootOrderLastIndex]  = CurrentBootOptionNo;\r
+  *BootOrderListSize += sizeof (UINT16);\r
+  *BootOrderList = NewBootOrderList;\r
+\r
+  FreePool (NewBbsDevPathNode);\r
+  FreePool (CurrentBbsDevPath);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check if the boot option is a legacy one.\r
+\r
+  @param BootOptionVar   The boot option data payload.\r
+  @param BbsEntry        The BBS Table.\r
+  @param BbsIndex        The table index.\r
+\r
+  @retval TRUE           It is a legacy boot option.\r
+  @retval FALSE          It is not a legacy boot option.\r
+\r
+**/\r
+BOOLEAN\r
+BdsIsLegacyBootOption (\r
+  IN UINT8                 *BootOptionVar,\r
+  OUT BBS_TABLE            **BbsEntry,\r
+  OUT UINT16               *BbsIndex\r
+  )\r
+{\r
+  UINT8                     *Ptr;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   Ret;\r
+  UINT16                    DevPathLen;\r
+\r
+  Ptr = BootOptionVar;\r
+  Ptr += sizeof (UINT32);\r
+  DevPathLen = *(UINT16 *) Ptr;\r
+  Ptr += sizeof (UINT16);\r
+  Ptr += StrSize ((UINT16 *) Ptr);\r
+  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+  if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+    Ptr += DevPathLen;\r
+    *BbsEntry = (BBS_TABLE *) Ptr;\r
+    Ptr += sizeof (BBS_TABLE);\r
+    *BbsIndex = *(UINT16 *) Ptr;\r
+    Ret       = TRUE;\r
+  } else {\r
+    *BbsEntry = NULL;\r
+    Ret       = FALSE;\r
+  }\r
+\r
+  return Ret;\r
+}\r
+\r
+/**\r
+  Delete all the invalid legacy boot options.\r
+\r
+  @retval EFI_SUCCESS             All invalide legacy boot options are deleted.\r
+  @retval EFI_OUT_OF_RESOURCES    Fail to allocate necessary memory.\r
+  @retval EFI_NOT_FOUND           Fail to retrive variable of boot order.\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  )\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOrderSize;\r
+  UINTN                     BootOptionSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  BBS_TABLE                 *BbsEntry;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    BootOption[10];\r
+  UINT16                    BootDesc[100];\r
+  BOOLEAN                   DescStringMatch;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  BootOrder     = NULL;\r
+  BootOrderSize = 0;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  BbsEntry      = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Index = 0;\r
+  while (Index < BootOrderSize / sizeof (UINT16)) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      if (BootOrder != NULL) {\r
+        FreePool (BootOrder);\r
+      }\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+  \r
+    //\r
+    // Skip Non-Legacy boot options\r
+    // \r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+      if (BootOptionVar!= NULL) {\r
+        FreePool (BootOptionVar);\r
+      }\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check if BBS Description String is changed\r
+    //\r
+    DescStringMatch = FALSE;\r
+\r
+    BdsBuildLegacyDevNameString (\r
+      &LocalBbsTable[BbsIndex],\r
+      BbsIndex,\r
+      sizeof(BootDesc),\r
+      BootDesc\r
+      );\r
+\r
+    if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
+      DescStringMatch = TRUE;\r
+    }\r
+\r
+    if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
+          (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
+        (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+        DescStringMatch) {\r
+      Index++;\r
+      continue;\r
+    }\r
+\r
+    if (BootOptionVar != NULL) {\r
+      FreePool (BootOptionVar);\r
+    }\r
+    //\r
+    // should delete\r
+    //\r
+    BdsDeleteBootOption (\r
+      BootOrder[Index],\r
+      BootOrder,\r
+      &BootOrderSize\r
+      );\r
+  }\r
+\r
+  //\r
+  // Adjust the number of boot options.\r
+  //\r
+  if (BootOrderSize != 0) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  if (BootOrder != NULL) {\r
+    FreePool (BootOrder);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Find all legacy boot option by device type.\r
+\r
+  @param BootOrder       The boot order array.\r
+  @param BootOptionNum   The number of boot option.\r
+  @param DevType         Device type.\r
+  @param Attribute       The boot option attribute.\r
+  @param BbsIndex        The BBS table index.\r
+  @param OptionNumber    The boot option index.\r
+\r
+  @retval TRUE           The Legacy boot option is found.\r
+  @retval FALSE          The legacy boot option is not found.\r
+\r
+**/\r
+BOOLEAN\r
+BdsFindLegacyBootOptionByDevType (\r
+  IN UINT16                 *BootOrder,\r
+  IN UINTN                  BootOptionNum,\r
+  IN UINT16                 DevType,\r
+  OUT UINT32                *Attribute,\r
+  OUT UINT16                *BbsIndex,\r
+  OUT UINTN                 *OptionNumber\r
+  )\r
+{\r
+  UINTN     Index;\r
+  UINTN     BootOrderIndex;\r
+  UINT16    BootOption[100];\r
+  UINTN     BootOptionSize;\r
+  UINT8     *BootOptionVar;\r
+  BBS_TABLE *BbsEntry;\r
+  BOOLEAN   Found;\r
+\r
+  BbsEntry  = NULL;\r
+  Found     = FALSE;\r
+\r
+  if (NULL == BootOrder) {\r
+    return Found;\r
+  }\r
+\r
+  //\r
+  // Loop all boot option from variable\r
+  //\r
+  for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
+    Index = (UINTN) BootOrder[BootOrderIndex];\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Skip Non-legacy boot option\r
+    //\r
+    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+      FreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    if (BbsEntry->DeviceType != DevType) {\r
+      FreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    *Attribute    = *(UINT32 *) BootOptionVar;\r
+    *OptionNumber = Index;\r
+    Found         = TRUE;\r
+    FreePool (BootOptionVar);\r
+    break;\r
+  }\r
+\r
+  return Found;\r
+}\r
+\r
+/**\r
+  Create a legacy boot option.\r
+\r
+  @param BbsItem         The BBS Table entry.\r
+  @param Index           Index of the specified entry in BBS table.\r
+  @param BootOrderList   The boot order list.\r
+  @param BootOrderListSize The size of boot order list.\r
+\r
+  @retval EFI_OUT_OF_RESOURCE  No enough memory.\r
+  @retval EFI_SUCCESS          The function complete successfully.\r
+  @return Other value if the legacy boot option is not created.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateOneLegacyBootOption (\r
+  IN BBS_TABLE              *BbsItem,\r
+  IN UINTN                  Index,\r
+  IN OUT UINT16             **BootOrderList,\r
+  IN OUT UINTN              *BootOrderListSize\r
+  )\r
+{\r
+  BBS_BBS_DEVICE_PATH       BbsDevPathNode;\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  DevPath                       = NULL;\r
+\r
+  //\r
+  // Create device path node.\r
+  //\r
+  BbsDevPathNode.Header.Type    = BBS_DEVICE_PATH;\r
+  BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
+  SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+  BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
+  CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
+\r
+  DevPath = AppendDevicePathNode (\r
+              EndDevicePath,\r
+              (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
+              );\r
+  if (NULL == DevPath) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = BdsCreateLegacyBootOption (\r
+            BbsItem,\r
+            DevPath,\r
+            Index,\r
+            BootOrderList,\r
+            BootOrderListSize\r
+            );\r
+  BbsItem->BootPriority = 0x00;\r
+\r
+  FreePool (DevPath);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+  @retval EFI_SUCCESS       The boot options are added successfully \r
+                            or they are already in boot options.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  )\r
+{\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT32                    Attribute;\r
+  UINTN                     OptionNumber;\r
+  BOOLEAN                   Ret;\r
+\r
+  BootOrder     = NULL;\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  BootOrder = BdsLibGetVariableAndSize (\r
+                L"BootOrder",\r
+                &gEfiGlobalVariableGuid,\r
+                &BootOrderSize\r
+                );\r
+  if (NULL == BootOrder) {\r
+    BootOrderSize = 0;\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    Ret = BdsFindLegacyBootOptionByDevType (\r
+            BootOrder,\r
+            BootOrderSize / sizeof (UINT16),\r
+            LocalBbsTable[Index].DeviceType,\r
+            &Attribute,\r
+            &BbsIndex,\r
+            &OptionNumber\r
+            );\r
+    if (Ret) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Not found such type of legacy device in boot options or we found but it's disabled\r
+    // so we have to create one and put it to the tail of boot order list\r
+    //\r
+    Status = BdsCreateOneLegacyBootOption (\r
+              &LocalBbsTable[Index],\r
+              Index,\r
+              &BootOrder,\r
+              &BootOrderSize\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrderSize > 0) {\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderSize,\r
+                    BootOrder\r
+                    );\r
+  } else {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  if (BootOrder != NULL) {\r
+    FreePool (BootOrder);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Fill the device order buffer.\r
+\r
+  @param BbsTable        The BBS table.\r
+  @param BbsType         The BBS Type.\r
+  @param BbsCount        The BBS Count.\r
+  @param Buf             device order buffer.\r
+\r
+  @return The device order buffer.\r
+\r
+**/\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+  IN BBS_TABLE                    *BbsTable,\r
+  IN BBS_TYPE                     BbsType,\r
+  IN UINTN                        BbsCount,\r
+  OUT UINT16                       *Buf\r
+  )\r
+{\r
+  UINTN Index;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    if (BbsTable[Index].DeviceType != BbsType) {\r
+      continue;\r
+    }\r
+\r
+    *Buf = (UINT16) (Index & 0xFF);\r
+    Buf++;\r
+  }\r
+\r
+  return Buf;\r
+}\r
+\r
+/**\r
+  Create the device order buffer.\r
+\r
+  @param BbsTable        The BBS table.\r
+  @param BbsCount        The BBS Count.\r
+\r
+  @retval EFI_SUCCES     The buffer is created and the EFI variable named \r
+                         VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrderGuid is\r
+                         set correctly.\r
+  @return Other value if the set of EFI variable fails. Check gRT->SetVariable\r
+          for detailed information.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsCreateDevOrder (\r
+  IN BBS_TABLE                  *BbsTable,\r
+  IN UINT16                     BbsCount\r
+  )\r
+{\r
+  UINTN       Index;\r
+  UINTN       FDCount;\r
+  UINTN       HDCount;\r
+  UINTN       CDCount;\r
+  UINTN       NETCount;\r
+  UINTN       BEVCount;\r
+  UINTN       TotalSize;\r
+  UINTN       HeaderSize;\r
+  UINT8       *DevOrder;\r
+  UINT8       *Ptr;\r
+  EFI_STATUS  Status;\r
+\r
+  FDCount     = 0;\r
+  HDCount     = 0;\r
+  CDCount     = 0;\r
+  NETCount    = 0;\r
+  BEVCount    = 0;\r
+  TotalSize   = 0;\r
+  HeaderSize  = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  DevOrder    = NULL;\r
+  Ptr         = NULL;\r
+  Status      = EFI_SUCCESS;\r
+\r
+  //\r
+  // Count all boot devices\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+      continue;\r
+    }\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
+  TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
+\r
+  //\r
+  // Create buffer to hold all boot device order\r
+  //\r
+  DevOrder = AllocateZeroPool (TotalSize);\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Ptr                 = DevOrder;\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (FDCount != 0) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (HDCount != 0) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (CDCount != 0) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (NETCount != 0) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
+  Ptr += sizeof (BBS_TYPE);\r
+  *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+  if (BEVCount != 0) {\r
+    Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+  }\r
+\r
+  //\r
+  // Save device order for legacy boot device to variable.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  DevOrder\r
+                  );\r
+  FreePool (DevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Add the legacy boot devices from BBS table into \r
+  the legacy device boot order.\r
+\r
+  @retval EFI_SUCCESS       The boot devices are added successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                     *DevOrder;\r
+  UINT8                     *NewDevOrder;\r
+  UINTN                     DevOrderSize;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     *Idx;\r
+  UINTN                     FDCount;\r
+  UINTN                     HDCount;\r
+  UINTN                     CDCount;\r
+  UINTN                     NETCount;\r
+  UINTN                     BEVCount;\r
+  UINTN                     TotalSize;\r
+  UINTN                     HeaderSize;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *NewPtr;\r
+  UINT16                    *NewFDPtr;\r
+  UINT16                    *NewHDPtr;\r
+  UINT16                    *NewCDPtr;\r
+  UINT16                    *NewNETPtr;\r
+  UINT16                    *NewBEVPtr;\r
+  UINT16                    *NewDevPtr;\r
+  UINT16                    Length;\r
+  UINT16                    Tmp;\r
+  UINTN                     FDIndex;\r
+  UINTN                     HDIndex;\r
+  UINTN                     CDIndex;\r
+  UINTN                     NETIndex;\r
+  UINTN                     BEVIndex;\r
+\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  Idx           = NULL;\r
+  FDCount       = 0;\r
+  HDCount       = 0;\r
+  CDCount       = 0;\r
+  NETCount      = 0;\r
+  BEVCount      = 0;\r
+  TotalSize     = 0;\r
+  HeaderSize    = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+  FDIndex       = 0;\r
+  HDIndex       = 0;\r
+  CDIndex       = 0;\r
+  NETIndex      = 0;\r
+  BEVIndex      = 0;\r
+  NewDevPtr     = NULL;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+\r
+  DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VAR_LEGACY_DEV_ORDER,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &DevOrderSize\r
+                        );\r
+  if (NULL == DevOrder) {\r
+    return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
+  }\r
+  //\r
+  // First we figure out how many boot devices with same device type respectively\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      FDCount++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      HDCount++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      CDCount++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      NETCount++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      BEVCount++;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+  }\r
+\r
+  TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
+  TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
+\r
+  NewDevOrder = AllocateZeroPool (TotalSize);\r
+  if (NULL == NewDevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewFDPtr  = (UINT16 *) (NewDevOrder + HeaderSize);\r
+  NewHDPtr  = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
+  NewCDPtr  = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
+  NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
+  NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
+\r
+  //\r
+  // copy FD\r
+  //\r
+  Ptr                     = DevOrder;\r
+  NewPtr                  = NewDevOrder;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
+    FDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy HD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewHDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
+    HDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy CD\r
+  //\r
+  NewPtr                  = (UINT8 *) NewCDPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
+    CDIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy NET\r
+  //\r
+  NewPtr                  = (UINT8 *) NewNETPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
+    NETIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+  //\r
+  // copy BEV\r
+  //\r
+  NewPtr                  = (UINT8 *) NewBEVPtr - HeaderSize;\r
+  *((BBS_TYPE *) NewPtr)  = *((BBS_TYPE *) Ptr);\r
+  Ptr += sizeof (BBS_TYPE);\r
+  NewPtr += sizeof (BBS_TYPE);\r
+  Length                = *((UINT16 *) Ptr);\r
+  *((UINT16 *) NewPtr)  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  Ptr += sizeof (UINT16);\r
+\r
+  for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+    if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+        LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+        LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
+        ) {\r
+      Ptr += sizeof (UINT16);\r
+      continue;\r
+    }\r
+\r
+    NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
+    BEVIndex++;\r
+    Ptr += sizeof (UINT16);\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    switch (LocalBbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      Idx       = &FDIndex;\r
+      NewDevPtr = NewFDPtr;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      Idx       = &HDIndex;\r
+      NewDevPtr = NewHDPtr;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      Idx       = &CDIndex;\r
+      NewDevPtr = NewCDPtr;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      Idx       = &NETIndex;\r
+      NewDevPtr = NewNETPtr;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      Idx       = &BEVIndex;\r
+      NewDevPtr = NewBEVPtr;\r
+      break;\r
+\r
+    default:\r
+      Idx = NULL;\r
+      break;\r
+    }\r
+    //\r
+    // at this point we have copied those valid indexes to new buffer\r
+    // and we should check if there is any new appeared boot device\r
+    //\r
+    if (Idx != 0) {\r
+      for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+        if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Index2 == *Idx) {\r
+        //\r
+        // Index2 == *Idx means we didn't find Index\r
+        // so Index is a new appeared device's index in BBS table\r
+        // save it.\r
+        //\r
+        NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+        (*Idx)++;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (FDCount != 0) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < FDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
+        if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
+          Tmp               = NewFDPtr[Index];\r
+          NewFDPtr[Index]   = NewFDPtr[Index2];\r
+          NewFDPtr[Index2]  = Tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (HDCount != 0) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < HDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
+        if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
+          Tmp               = NewHDPtr[Index];\r
+          NewHDPtr[Index]   = NewHDPtr[Index2];\r
+          NewHDPtr[Index2]  = Tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (CDCount != 0) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < CDIndex - 1; Index++) {\r
+      if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
+        if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
+          Tmp               = NewCDPtr[Index];\r
+          NewCDPtr[Index]   = NewCDPtr[Index2];\r
+          NewCDPtr[Index2]  = Tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (NETCount != 0) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < NETIndex - 1; Index++) {\r
+      if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
+        if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
+          Tmp               = NewNETPtr[Index];\r
+          NewNETPtr[Index]  = NewNETPtr[Index2];\r
+          NewNETPtr[Index2] = Tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (BEVCount!= 0) {\r
+    //\r
+    // Just to make sure that disabled indexes are all at the end of the array\r
+    //\r
+    for (Index = 0; Index < BEVIndex - 1; Index++) {\r
+      if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
+        continue;\r
+      }\r
+\r
+      for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
+        if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
+          Tmp               = NewBEVPtr[Index];\r
+          NewBEVPtr[Index]  = NewBEVPtr[Index2];\r
+          NewBEVPtr[Index2] = Tmp;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (DevOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  TotalSize,\r
+                  NewDevOrder\r
+                  );\r
+  FreePool (NewDevOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set Boot Priority for specified device type.\r
+\r
+  @param DeviceType      The device type.\r
+  @param LocalBbsTable   The BBS table.\r
+  @param Priority        The prority table.\r
+\r
+  @retval EFI_SUCCESS    The function completes successfully.\r
+  @retval EFI_NOT_FOUND  Failed to find device.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsSetBootPriority4SameTypeDev (\r
+  IN UINT16                                              DeviceType,\r
+  IN OUT BBS_TABLE                                       *LocalBbsTable,\r
+  IN OUT UINT16                                          *Priority\r
+  )\r
+{\r
+  UINT8   *DevOrder;\r
+\r
+  UINT8   *OrigBuffer;\r
+  UINT16  *DevIndex;\r
+  UINTN   DevOrderSize;\r
+  UINTN   DevCount;\r
+  UINTN   Index;\r
+\r
+  DevOrder = BdsLibGetVariableAndSize (\r
+              VAR_LEGACY_DEV_ORDER,\r
+              &EfiLegacyDevOrderGuid,\r
+              &DevOrderSize\r
+              );\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrigBuffer = DevOrder;\r
+  while (DevOrder < OrigBuffer + DevOrderSize) {\r
+    if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
+      break;\r
+    }\r
+\r
+    DevOrder += sizeof (BBS_TYPE);\r
+    DevOrder += *(UINT16 *) DevOrder;\r
+  }\r
+\r
+  if (DevOrder >= OrigBuffer + DevOrderSize) {\r
+    FreePool (OrigBuffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  DevOrder += sizeof (BBS_TYPE);\r
+  DevCount  = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
+  DevIndex  = (UINT16 *) (DevOrder + sizeof (UINT16));\r
+  //\r
+  // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+  //\r
+  for (Index = 0; Index < DevCount; Index++) {\r
+    if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
+      //\r
+      // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+      //\r
+    } else {\r
+      LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
+      (*Priority)++;\r
+    }\r
+  }\r
+\r
+  FreePool (OrigBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Print the BBS Table.\r
+\r
+  @param LocalBbsTable   The BBS table.\r
+\r
+**/\r
+VOID\r
+PrintBbsTable (\r
+  IN BBS_TABLE                      *LocalBbsTable\r
+  )\r
+{\r
+  UINT16  Idx;\r
+\r
+  DEBUG ((DEBUG_ERROR, "\n"));\r
+  DEBUG ((DEBUG_ERROR, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+  DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
+  for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {\r
+    if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+        (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG (\r
+      (DEBUG_ERROR,\r
+      " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
+      (UINTN) Idx,\r
+      (UINTN) LocalBbsTable[Idx].BootPriority,\r
+      (UINTN) LocalBbsTable[Idx].Bus,\r
+      (UINTN) LocalBbsTable[Idx].Device,\r
+      (UINTN) LocalBbsTable[Idx].Function,\r
+      (UINTN) LocalBbsTable[Idx].Class,\r
+      (UINTN) LocalBbsTable[Idx].SubClass,\r
+      (UINTN) LocalBbsTable[Idx].DeviceType,\r
+      (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
+      (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
+      (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
+      (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
+      );\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "\n"));\r
+}\r
+\r
+/**\r
+\r
+  Set the boot priority for BBS entries based on boot option entry and boot order.\r
+\r
+  @param  Entry             The boot option is to be checked for refresh BBS table.\r
+  \r
+  @retval EFI_SUCCESS       The boot priority for BBS entries is refreshed successfully.\r
+  @return status of BdsSetBootPriority4SameTypeDev()\r
+**/\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINT16                    HddCount;\r
+  UINT16                    BbsCount;\r
+  HDD_INFO                  *LocalHddInfo;\r
+  BBS_TABLE                 *LocalBbsTable;\r
+  UINT16                    DevType;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINTN                     Index;\r
+  UINT16                    Priority;\r
+  UINT16                    *BootOrder;\r
+  UINTN                     BootOrderSize;\r
+  UINT8                     *BootOptionVar;\r
+  UINTN                     BootOptionSize;\r
+  UINT16                    BootOption[100];\r
+  UINT8                     *Ptr;\r
+  UINT16                    DevPathLen;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
+\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  DevType       = BBS_UNKNOWN;\r
+\r
+  Status        = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  LegacyBios->GetBbsInfo (\r
+                LegacyBios,\r
+                &HddCount,\r
+                &LocalHddInfo,\r
+                &BbsCount,\r
+                &LocalBbsTable\r
+                );\r
+  //\r
+  // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
+  // We will set them according to the settings setup by user\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
+         (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
+      LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+    }\r
+  }\r
+  //\r
+  // boot priority always starts at 0\r
+  //\r
+  Priority = 0;\r
+  if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
+    //\r
+    // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
+    //\r
+    DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              DevType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  //\r
+  // we have to set the boot priority for other BBS entries with different device types\r
+  //\r
+  BootOrder = (UINT16 *) BdsLibGetVariableAndSize (\r
+                          L"BootOrder",\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOrderSize\r
+                          );\r
+  for (Index = 0; ((BootOrder != NULL) && (Index < BootOrderSize / sizeof (UINT16))); Index++) {\r
+    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+    BootOptionVar = BdsLibGetVariableAndSize (\r
+                      BootOption,\r
+                      &gEfiGlobalVariableGuid,\r
+                      &BootOptionSize\r
+                      );\r
+    if (NULL == BootOptionVar) {\r
+      continue;\r
+    }\r
+\r
+    Ptr = BootOptionVar;\r
+\r
+    Ptr += sizeof (UINT32);\r
+    DevPathLen = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+    Ptr += StrSize ((UINT16 *) Ptr);\r
+    DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
+      FreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Ptr += DevPathLen;\r
+    if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
+      //\r
+      // We don't want to process twice for a device type\r
+      //\r
+      FreePool (BootOptionVar);\r
+      continue;\r
+    }\r
+\r
+    Status = BdsSetBootPriority4SameTypeDev (\r
+              ((BBS_TABLE *) Ptr)->DeviceType,\r
+              LocalBbsTable,\r
+              &Priority\r
+              );\r
+    FreePool (BootOptionVar);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (BootOrder != NULL) {\r
+    FreePool (BootOrder);\r
+  }\r
+\r
+  DEBUG_CODE_BEGIN();\r
+    PrintBbsTable (LocalBbsTable);\r
+  DEBUG_CODE_END();\r
+  \r
+  return Status;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
new file mode 100644 (file)
index 0000000..fee8bdb
--- /dev/null
@@ -0,0 +1,94 @@
+/** @file\r
+  declares interface functions\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _EFI_BDS_BBS_SUPPORT_H_\r
+#define _EFI_BDS_BBS_SUPPORT_H_\r
+\r
+#include "BootMaint.h"\r
+\r
+#define MAX_BBS_ENTRIES 0x100\r
+\r
+/**\r
+  Build Legacy Device Name String according.\r
+\r
+  @param CurBBSEntry     BBS Table.\r
+  @param Index           Index.\r
+  @param BufSize         The buffer size.\r
+  @param BootString      The output string.\r
+\r
+  @return VOID           No output.\r
+\r
+**/\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+  IN BBS_TABLE                     *CurBBSEntry,\r
+  IN UINTN                         Index,\r
+  IN UINTN                         BufSize,\r
+  OUT CHAR16                       *BootString\r
+  );\r
+\r
+/**\r
+  Delete all the invalid legacy boot options.\r
+\r
+  \r
+\r
+  @retval EFI_SUCCESS             All invalide legacy boot options are deleted.\r
+  @retval EFI_OUT_OF_RESOURCES    Fail to allocate necessary memory.\r
+  @retval EFI_NOT_FOUND           Fail to retrive variable of boot order.\r
+**/\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  Add the legacy boot options from BBS table if they do not exist.\r
+\r
+  @retval  EFI_SUCCESS        The boot options are added successfully or they are already in boot options.\r
+  @retval  others             An error occurred when creating legacy boot options.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  Add the legacy boot devices from BBS table into \r
+  the legacy device boot order.\r
+\r
+  @retval EFI_SUCCESS       The boot devices are added successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Set the boot priority for BBS entries based on boot option entry and boot order.\r
+\r
+  @param  Entry             The boot option is to be checked for refresh BBS table.\r
+  \r
+  @retval EFI_SUCCESS       The boot priority for BBS entries is refreshed successfully.\r
+  @return status of BdsSetBootPriority4SameTypeDev()\r
+**/\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+  IN BDS_COMMON_OPTION        *Entry\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
new file mode 100644 (file)
index 0000000..4f38a34
--- /dev/null
@@ -0,0 +1,383 @@
+///** @file\r
+//  \r
+//    Boot Maintenance Utility Formset\r
+//  \r
+//  Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+//  All rights reserved. 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
+#include "FormGuid.h"\r
+\r
+#define LABEL_END   0xffff\r
+\r
+formset\r
+  guid = BOOT_MAINT_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FORM_MAIN_TITLE),\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,\r
+  subclass = 0,\r
+\r
+  varstore BMM_FAKE_NV_DATA,\r
+    varid = VARSTORE_ID_BOOT_MAINT,\r
+    name = BmmData,\r
+    guid = BOOT_MAINT_FORMSET_GUID;\r
+\r
+  form formid = FORM_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_MAIN_TITLE);\r
+\r
+    goto FORM_BOOT_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_BOOT_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_DRIVER_SETUP_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_DRIVER_SETUP_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_CON_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_CON_MAIN_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    text\r
+         help   = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),\r
+         text   = STRING_TOKEN(STR_BOOT_FROM_FILE),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_BOOT_FROM_FILE;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+//    label FORM_MAIN_ID;\r
+\r
+    goto FORM_BOOT_NEXT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_BOOT_NEXT_ID;\r
+\r
+    goto FORM_TIME_OUT_ID,\r
+         prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),\r
+         help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),\r
+         flags = INTERACTIVE,\r
+         key = FORM_TIME_OUT_ID;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+    goto FORM_MAIN_ID,\r
+         prompt = STRING_TOKEN(STR_RESET),\r
+         help = STRING_TOKEN(STR_RESET),\r
+         flags = INTERACTIVE,\r
+         key = FORM_RESET;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_BOOT_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_ADD_ID;\r
+\r
+       goto FORM_BOOT_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_DEL_ID;\r
+\r
+       goto FORM_BOOT_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_BOOT_CHG_ID;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+           //\r
+          // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"\r
+          // here dynamically\r
+          //\r
+       label FORM_BOOT_LEGACY_DEVICE_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRIVER_SETUP_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_DRV_ADD_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_ADD_ID;\r
+\r
+       goto FORM_DRV_DEL_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_DEL_ID;\r
+\r
+       goto FORM_DRV_CHG_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_CHG_ID;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_BOOT_ADD_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);\r
+\r
+       label FORM_BOOT_DEL_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);\r
+\r
+       label FORM_BOOT_CHG_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_NEXT_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);\r
+\r
+       label FORM_BOOT_NEXT_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_TIME_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);\r
+\r
+       label FORM_TIME_OUT_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+            help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+            //flags = INTERACTIVE,\r
+            //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_DRV_ADD_FILE_ID,\r
+            prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+            flags = INTERACTIVE,\r
+            key = FORM_DRV_ADD_FILE_ID;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_DEL_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);\r
+\r
+       label FORM_DRV_DEL_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRV_CHG_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);\r
+\r
+       label FORM_DRV_CHG_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_MAIN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);\r
+\r
+       goto FORM_MAIN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+       help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+       //flags = INTERACTIVE,\r
+       //key = FORM_MAIN_ID;\r
+\r
+       goto FORM_CON_IN_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_IN_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_IN_ID;\r
+\r
+       goto FORM_CON_OUT_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_OUT_ID;\r
+\r
+       goto FORM_CON_ERR_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_ERR_ID;\r
+\r
+       goto FORM_CON_MODE_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_MODE_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_MODE_ID;\r
+\r
+       goto FORM_CON_COM_ID,\r
+       prompt = STRING_TOKEN(STR_FORM_COM_TITLE),\r
+       help = STRING_TOKEN(STR_FORM_COM_HELP),\r
+       flags = INTERACTIVE,\r
+       key = FORM_CON_COM_ID;\r
+  endform;\r
+\r
+  form formid = FORM_CON_MODE_ID,\r
+       title = STRING_TOKEN(STR_FORM_MODE_TITLE);\r
+\r
+       label FORM_CON_MODE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_ID,\r
+       title = STRING_TOKEN(STR_FORM_COM_TITLE);\r
+\r
+       label FORM_CON_COM_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_CON_COM_SETUP_ID,\r
+       title = STRING_TOKEN(STR_CON_COM_SETUP);\r
+\r
+       label FORM_CON_COM_SETUP_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_SEEK_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_FILE_NEW_SEEK_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+       label FORM_FILE_NEW_SEEK_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_FILE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);\r
+\r
+       label FORM_DRV_ADD_FILE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_DRV_ADD_HANDLE_DESC_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+       label FORM_DRV_ADD_HANDLE_DESC_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_IN_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);\r
+\r
+       label FORM_CON_IN_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_OUT_ID,\r
+       title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);\r
+\r
+       label FORM_CON_OUT_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_CON_ERR_ID,\r
+       title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);\r
+\r
+       label FORM_CON_ERR_ID;\r
+       label LABEL_END;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_SET_FD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);\r
+\r
+       label FORM_SET_FD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_HD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);\r
+\r
+       label FORM_SET_HD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_CD_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);\r
+\r
+       label FORM_SET_CD_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_NET_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);\r
+\r
+       label FORM_SET_NET_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_SET_BEV_ORDER_ID,\r
+       title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);\r
+\r
+       label FORM_SET_BEV_ORDER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+endformset;\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
new file mode 100644 (file)
index 0000000..aaa64c9
--- /dev/null
@@ -0,0 +1,494 @@
+/** @file\r
+  Utility routines used by boot maintenance modules.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+/**\r
+\r
+  Find the first instance of this Protocol\r
+  in the system and return it's interface.\r
+\r
+\r
+  @param ProtocolGuid    Provides the protocol to search for\r
+  @param Interface       On return, a pointer to the first interface\r
+                         that matches ProtocolGuid\r
+\r
+  @retval  EFI_SUCCESS      A protocol instance matching ProtocolGuid was found\r
+  @retval  EFI_NOT_FOUND    No protocol instances were found that match ProtocolGuid\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID    *ProtocolGuid,\r
+  OUT VOID        **Interface\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  ProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) Interface\r
+                  );\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Function opens and returns a file handle to the root directory of a volume.\r
+\r
+  @param DeviceHandle    A handle for a device\r
+\r
+  @return A valid file handle or NULL is returned\r
+\r
+**/\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE                   DeviceHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+  EFI_FILE_HANDLE                 File;\r
+\r
+  File = NULL;\r
+\r
+  //\r
+  // File the file system interface to the device\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  DeviceHandle,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  (VOID *) &Volume\r
+                  );\r
+\r
+  //\r
+  // Open the root directory of the volume\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = Volume->OpenVolume (\r
+                      Volume,\r
+                      &File\r
+                      );\r
+  }\r
+  //\r
+  // Done\r
+  //\r
+  return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+/**\r
+\r
+  Helper function called as part of the code needed\r
+  to allocate the proper sized buffer for various\r
+  EFI interfaces.\r
+\r
+\r
+  @param Status          Current status\r
+  @param Buffer          Current allocated buffer, or NULL\r
+  @param BufferSize      Current buffer size needed\r
+\r
+  @retval  TRUE  if the buffer was reallocated and the caller\r
+                 should try the API again.\r
+  @retval  FALSE The caller should not call this function again.\r
+\r
+**/\r
+BOOLEAN\r
+EfiGrowBuffer (\r
+  IN OUT EFI_STATUS   *Status,\r
+  IN OUT VOID         **Buffer,\r
+  IN UINTN            BufferSize\r
+  )\r
+{\r
+  BOOLEAN TryAgain;\r
+\r
+  //\r
+  // If this is an initial request, buffer will be null with a new buffer size\r
+  //\r
+  if ((*Buffer == NULL) && (BufferSize != 0)) {\r
+    *Status = EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  //\r
+  // If the status code is "buffer too small", resize the buffer\r
+  //\r
+  TryAgain = FALSE;\r
+  if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+    if (*Buffer != NULL) {\r
+      FreePool (*Buffer);\r
+    }\r
+\r
+    *Buffer = AllocateZeroPool (BufferSize);\r
+\r
+    if (*Buffer != NULL) {\r
+      TryAgain = TRUE;\r
+    } else {\r
+      *Status = EFI_OUT_OF_RESOURCES;\r
+    }\r
+  }\r
+  //\r
+  // If there's an error, free the buffer\r
+  //\r
+  if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {\r
+    FreePool (*Buffer);\r
+    *Buffer = NULL;\r
+  }\r
+\r
+  return TryAgain;\r
+}\r
+\r
+/**\r
+  Function returns the value of the specified variable.\r
+\r
+\r
+  @param Name            A Null-terminated Unicode string that is\r
+                         the name of the vendor's variable.\r
+  @param VendorGuid      A unique identifier for the vendor.\r
+\r
+  @return               The payload of the variable.\r
+  @retval NULL          If the variable can't be read.\r
+\r
+**/\r
+VOID *\r
+EfiLibGetVariable (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid\r
+  )\r
+{\r
+  UINTN VarSize;\r
+\r
+  return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
+}\r
+\r
+/**\r
+  Function deletes the variable specified by VarName and VarGuid.\r
+\r
+  @param VarName           A Null-terminated Unicode string that is\r
+                           the name of the vendor's variable.\r
+                         \r
+  @param VarGuid           A unique identifier for the vendor.\r
+\r
+  @retval  EFI_SUCCESS           The variable was found and removed\r
+  @retval  EFI_UNSUPPORTED       The variable store was inaccessible\r
+  @retval  EFI_OUT_OF_RESOURCES  The temporary buffer was not available\r
+  @retval  EFI_NOT_FOUND         The variable was not found\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  )\r
+{\r
+  VOID        *VarBuf;\r
+  EFI_STATUS  Status;\r
+\r
+  VarBuf  = EfiLibGetVariable (VarName, VarGuid);\r
+  Status  = EFI_NOT_FOUND;\r
+\r
+  if (VarBuf != NULL) {\r
+    //\r
+    // Delete variable from Storage\r
+    //\r
+    Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    FreePool (VarBuf);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Function gets the file system information from an open file descriptor,\r
+  and stores it in a buffer allocated from pool.\r
+\r
+\r
+  @param FHand           The file handle.\r
+\r
+  @return                A pointer to a buffer with file information.\r
+  @retval                NULL is returned if failed to get Vaolume Label Info.\r
+\r
+**/\r
+EFI_FILE_SYSTEM_VOLUME_LABEL *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL      *Buffer;\r
+  UINTN                             BufferSize;\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Duplicate a string.\r
+\r
+  @param Src             The source.\r
+\r
+  @return A new string which is duplicated copy of the source.\r
+  @retval NULL If there is not enough memory.\r
+\r
+**/\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  )\r
+{\r
+  CHAR16  *Dest;\r
+  UINTN   Size;\r
+\r
+  Size  = StrSize (Src);\r
+  Dest  = AllocateZeroPool (Size);\r
+  ASSERT (Dest != NULL);\r
+  if (Dest != NULL) {\r
+    CopyMem (Dest, Src, Size);\r
+  }\r
+\r
+  return Dest;\r
+}\r
+\r
+/**\r
+\r
+  Function gets the file information from an open file descriptor, and stores it\r
+  in a buffer allocated from pool.\r
+\r
+  @param FHand           File Handle.\r
+\r
+  @return                A pointer to a buffer with file information or NULL is returned\r
+\r
+**/\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_FILE_INFO *Buffer;\r
+  UINTN         BufferSize;\r
+\r
+  //\r
+  // Initialize for GrowBuffer loop\r
+  //\r
+  Buffer      = NULL;\r
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+  //\r
+  // Call the real function\r
+  //\r
+  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+    Status = FHand->GetInfo (\r
+                      FHand,\r
+                      &gEfiFileInfoGuid,\r
+                      &BufferSize,\r
+                      Buffer\r
+                      );\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Function is used to determine the number of device path instances\r
+  that exist in a device path.\r
+\r
+\r
+  @param DevicePath      A pointer to a device path data structure.\r
+\r
+  @return This function counts and returns the number of device path instances\r
+          in DevicePath.\r
+\r
+**/\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+{\r
+  UINTN Count;\r
+  UINTN Size;\r
+\r
+  Count = 0;\r
+  while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
+    Count += 1;\r
+  }\r
+\r
+  return Count;\r
+}\r
+\r
+/**\r
+  Adjusts the size of a previously allocated buffer.\r
+\r
+\r
+  @param OldPool         - A pointer to the buffer whose size is being adjusted.\r
+  @param OldSize         - The size of the current buffer.\r
+  @param NewSize         - The size of the new buffer.\r
+\r
+  @return   The newly allocated buffer.\r
+  @retval   NULL  Allocation failed.\r
+\r
+**/\r
+VOID *\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  )\r
+{\r
+  VOID  *NewPool;\r
+\r
+  NewPool = NULL;\r
+  if (NewSize != 0) {\r
+    NewPool = AllocateZeroPool (NewSize);\r
+  }\r
+\r
+  if (OldPool != NULL) {\r
+    if (NewPool != NULL) {\r
+      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+    }\r
+\r
+    FreePool (OldPool);\r
+  }\r
+\r
+  return NewPool;\r
+}\r
+\r
+/**\r
+  Compare two EFI_TIME data.\r
+\r
+\r
+  @param FirstTime       - A pointer to the first EFI_TIME data.\r
+  @param SecondTime      - A pointer to the second EFI_TIME data.\r
+\r
+  @retval  TRUE              The FirstTime is not later than the SecondTime.\r
+  @retval  FALSE             The FirstTime is later than the SecondTime.\r
+\r
+**/\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  )\r
+{\r
+  if (FirstTime->Year != SecondTime->Year) {\r
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+  } else if (FirstTime->Month != SecondTime->Month) {\r
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+  } else if (FirstTime->Day != SecondTime->Day) {\r
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+  } else if (FirstTime->Hour != SecondTime->Hour) {\r
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+  } else if (FirstTime->Minute != SecondTime->Minute) {\r
+    return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+  } else if (FirstTime->Second != SecondTime->Second) {\r
+    return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
+  }\r
+\r
+  return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
+}\r
+\r
+/**\r
+  Get a string from the Data Hub record based on \r
+  a device path.\r
+\r
+  @param DevPath         The device Path.\r
+\r
+  @return A string located from the Data Hub records based on\r
+          the device path.\r
+  @retval NULL  If failed to get the String from Data Hub.\r
+\r
+**/\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  )\r
+{\r
+  EFI_STATUS                                  Status;\r
+  UINT16                                      *Desc;\r
+  EFI_DATA_HUB_PROTOCOL                       *Datahub;\r
+  UINT64                                      Count;\r
+  EFI_DATA_RECORD_HEADER                      *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER                   *DataHdr;\r
+  EFI_GUID                                    MiscGuid;\r
+  EFI_MISC_ONBOARD_DEVICE_DATA                *Ob;\r
+  EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
+  EFI_TIME                                    CurTime;\r
+\r
+  CopyGuid (&MiscGuid, &gEfiMiscSubClassGuid);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &Datahub\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = gRT->GetTime (&CurTime, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Count = 0;\r
+  do {\r
+    Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
+      //\r
+      // This record is what we need\r
+      //\r
+      DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
+        Ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Ob->OnBoardDevicePath, DevPath)) {\r
+          GetProducerString (&Record->ProducerName, Ob->OnBoardDeviceDescription, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+\r
+      if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
+        Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
+        if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
+          GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
+          return Desc;\r
+        }\r
+      }\r
+    }\r
+\r
+  } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
+\r
+  return NULL;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
new file mode 100644 (file)
index 0000000..bd94803
Binary files /dev/null and b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
new file mode 100644 (file)
index 0000000..4598d3d
--- /dev/null
@@ -0,0 +1,1376 @@
+/** @file\r
+  The functions for Boot Maintainence Main menu.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+#include "FormGuid.h"\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL  EndDevicePath[] = {\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    {\r
+      END_DEVICE_PATH_LENGTH,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+\r
+EFI_GUID EfiLegacyDevOrderGuid  = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+EFI_GUID mBootMaintGuid         = BOOT_MAINT_FORMSET_GUID;\r
+EFI_GUID mFileExplorerGuid      = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+CHAR16  mBootMaintStorageName[]     = L"BmData";\r
+CHAR16  mFileExplorerStorageName[]  = L"FeData";\r
+\r
+/**\r
+  Init all memu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+/**\r
+  Free up all Menu Option list.\r
+\r
+**/\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Create string tokens for a menu from its help strings and display strings\r
+\r
+  @param CallbackData       The BMM context data.\r
+  @param HiiHandle          Hii Handle of the package to be updated.\r
+  @param MenuOption         The Menu whose string tokens need to be created\r
+\r
+  @retval  EFI_SUCCESS      String tokens created successfully\r
+  @retval  others           contain some errors\r
+**/\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINTN         Index;\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+\r
+    HiiLibNewString (\r
+      HiiHandle,\r
+      &NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->DisplayString\r
+      );\r
+\r
+    if (NULL == NewMenuEntry->HelpString) {\r
+      NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+    } else {\r
+      HiiLibNewString (\r
+        HiiHandle,\r
+        &NewMenuEntry->HelpStringToken,\r
+        NewMenuEntry->HelpString\r
+        );\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Request         A null-terminated Unicode string in <ConfigRequest> format.\r
+  @param Progress        On return, points to a character in the Request string.\r
+                         Points to the string's null terminator if request was successful.\r
+                         Points to the most recent '&' before the first failing name/value\r
+                         pair (or the beginning of the string if the failure is in the\r
+                         first name/value pair) if the request was not successful.\r
+  @param Results         A null-terminated Unicode string in <ConfigAltResp> format which\r
+                         has all values filled in for the names in the Request string.\r
+                         String to be allocated by the called function.\r
+\r
+  @retval  EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  UINTN              BufferSize;\r
+  BMM_CALLBACK_DATA  *Private;\r
+\r
+  if (Request == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+  //\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = gHiiConfigRouting->BlockToConfig (\r
+                                gHiiConfigRouting,\r
+                                Request,\r
+                                (UINT8 *) &Private->BmmFakeNvData,\r
+                                BufferSize,\r
+                                Results,\r
+                                Progress\r
+                                );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+\r
+  @param This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action             Specifies the type of action taken by the browser.\r
+  @param QuestionId         A unique value which is sent to the original exporting driver\r
+                            so that it can identify the type of data to expect.\r
+  @param Type               The type of value for the question.\r
+  @param Value              A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest      On return, points to the action requested by the callback function.\r
+\r
+  @retval EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.\r
+  @retval EFI_DEVICE_ERROR      The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED       The specified Action is not supported by the callback.\r
+  @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL         *This,\r
+  IN        EFI_BROWSER_ACTION                     Action,\r
+  IN        EFI_QUESTION_ID                        QuestionId,\r
+  IN        UINT8                                  Type,\r
+  IN        EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT       EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  BMM_CALLBACK_DATA *Private;\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  EFI_STATUS        Status;\r
+  UINTN             OldValue;\r
+  UINTN             NewValue;\r
+  UINTN             Number;\r
+  UINTN             Pos;\r
+  UINTN             Bit;\r
+  UINT16            NewValuePos;\r
+  UINT16            Index2;\r
+  UINT16            Index;\r
+  UINT8             *OldLegacyDev;\r
+  UINT8             *NewLegacyDev;\r
+  UINT8             *DisMap;\r
+  EFI_FORM_ID       FormId;\r
+  UINTN             BufferSize;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldValue       = 0;\r
+  NewValue       = 0;\r
+  Number         = 0;\r
+  OldLegacyDev   = NULL;\r
+  NewLegacyDev   = NULL;\r
+  NewValuePos    = 0;\r
+  DisMap         = NULL;\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  Private        = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+  UpdatePageId (Private, QuestionId);\r
+\r
+  //\r
+  // Retrive uncommitted data from Form Browser\r
+  //\r
+  CurrentFakeNVMap = &Private->BmmFakeNvData;\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // need to be subtituded.\r
+  //\r
+  // Update Select FD/HD/CD/NET/BEV Order Form\r
+  //\r
+  if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+      FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+      ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+      (QuestionId >= LEGACY_FD_QUESTION_ID) &&\r
+       (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+      ) {\r
+\r
+    DisMap  = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+    FormId  = Private->BmmPreviousPageId;\r
+    if (FormId == FORM_BOOT_SETUP_ID) {\r
+      FormId = Private->BmmCurrentPageId;\r
+    }\r
+\r
+    switch (FormId) {\r
+    case FORM_SET_FD_ORDER_ID:\r
+      Number        = (UINT16) LegacyFDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyFD;\r
+      break;\r
+\r
+    case FORM_SET_HD_ORDER_ID:\r
+      Number        = (UINT16) LegacyHDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyHD;\r
+      break;\r
+\r
+    case FORM_SET_CD_ORDER_ID:\r
+      Number        = (UINT16) LegacyCDMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyCD;\r
+      break;\r
+\r
+    case FORM_SET_NET_ORDER_ID:\r
+      Number        = (UINT16) LegacyNETMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyNET;\r
+      break;\r
+\r
+    case FORM_SET_BEV_ORDER_ID:\r
+      Number        = (UINT16) LegacyBEVMenu.MenuNumber;\r
+      OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;\r
+      NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+    //\r
+    //  First, find the different position\r
+    //  if there is change, it should be only one\r
+    //\r
+    for (Index = 0; Index < Number; Index++) {\r
+      if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+        OldValue  = OldLegacyDev[Index];\r
+        NewValue  = NewLegacyDev[Index];\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index != Number) {\r
+      //\r
+      // there is change, now process\r
+      //\r
+      if (0xFF == NewValue) {\r
+        //\r
+        // This item will be disable\r
+        // Just move the items behind this forward to overlap it\r
+        //\r
+        Pos = OldValue / 8;\r
+        Bit = 7 - (OldValue % 8);\r
+        DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+        for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+          NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+        }\r
+\r
+        NewLegacyDev[Index2] = 0xFF;\r
+      } else {\r
+        for (Index2 = 0; Index2 < Number; Index2++) {\r
+          if (Index2 == Index) {\r
+            continue;\r
+          }\r
+\r
+          if (OldLegacyDev[Index2] == NewValue) {\r
+            //\r
+            // If NewValue is in OldLegacyDev array\r
+            // remember its old position\r
+            //\r
+            NewValuePos = Index2;\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (Index2 != Number) {\r
+          //\r
+          // We will change current item to an existing item\r
+          // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+          //\r
+          for (Index2 = NewValuePos; Index2 != Index;) {\r
+            if (NewValuePos < Index) {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+              Index2++;\r
+            } else {\r
+              NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+              Index2--;\r
+            }\r
+          }\r
+        } else {\r
+          //\r
+          // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+          // so we should modify DisMap to reflect the change\r
+          //\r
+          Pos = NewValue / 8;\r
+          Bit = 7 - (NewValue % 8);\r
+          DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));\r
+          if (0xFF != OldValue) {\r
+            //\r
+            // Because NewValue is a item that was disabled before\r
+            // so after changing the OldValue should be disabled\r
+            // actually we are doing a swap of enable-disable states of two items\r
+            //\r
+            Pos = OldValue / 8;\r
+            Bit = 7 - (OldValue % 8);\r
+            DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+          }\r
+        }\r
+      }\r
+      //\r
+      // To prevent DISABLE appears in the middle of the list\r
+      // we should perform a re-ordering\r
+      //\r
+      Index = 0;\r
+      while (Index < Number) {\r
+        if (0xFF != NewLegacyDev[Index]) {\r
+          Index++;\r
+          continue;\r
+        }\r
+\r
+        Index2 = Index;\r
+        Index2++;\r
+        while (Index2 < Number) {\r
+          if (0xFF != NewLegacyDev[Index2]) {\r
+            break;\r
+          }\r
+\r
+          Index2++;\r
+        }\r
+\r
+        if (Index2 < Number) {\r
+          NewLegacyDev[Index]   = NewLegacyDev[Index2];\r
+          NewLegacyDev[Index2]  = 0xFF;\r
+        }\r
+\r
+        Index++;\r
+      }\r
+\r
+      CopyMem (\r
+        OldLegacyDev,\r
+        NewLegacyDev,\r
+        Number\r
+        );\r
+    }\r
+  }\r
+\r
+  if (QuestionId < FILE_OPTION_OFFSET) {\r
+    if (QuestionId < CONFIG_OPTION_OFFSET) {\r
+      switch (QuestionId) {\r
+      case KEY_VALUE_BOOT_FROM_FILE:\r
+        Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_BOOT_ADD_ID:\r
+        Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_DRV_ADD_FILE_ID:\r
+        Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+        //\r
+        // Exit Bmm main formset to send File Explorer formset.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+        break;\r
+\r
+      case FORM_DRV_ADD_HANDLE_ID:\r
+        CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+        UpdateDrvAddHandlePage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_DEL_ID:\r
+        CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+        UpdateBootDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_CHG_ID:\r
+      case FORM_DRV_CHG_ID:\r
+        UpdatePageBody (QuestionId, Private);\r
+        break;\r
+\r
+      case FORM_DRV_DEL_ID:\r
+        CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+        UpdateDrvDelPage (Private);\r
+        break;\r
+\r
+      case FORM_BOOT_NEXT_ID:\r
+        CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
+        UpdateBootNextPage (Private);\r
+        break;\r
+\r
+      case FORM_TIME_OUT_ID:\r
+        CleanUpPage (FORM_TIME_OUT_ID, Private);\r
+        UpdateTimeOutPage (Private);\r
+        break;\r
+\r
+      case FORM_RESET:\r
+        gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+        return EFI_UNSUPPORTED;\r
+\r
+      case FORM_CON_IN_ID:\r
+      case FORM_CON_OUT_ID:\r
+      case FORM_CON_ERR_ID:\r
+        UpdatePageBody (QuestionId, Private);\r
+        break;\r
+\r
+      case FORM_CON_MODE_ID:\r
+        CleanUpPage (FORM_CON_MODE_ID, Private);\r
+        UpdateConModePage (Private);\r
+        break;\r
+\r
+      case FORM_CON_COM_ID:\r
+        CleanUpPage (FORM_CON_COM_ID, Private);\r
+        UpdateConCOMPage (Private);\r
+        break;\r
+\r
+      case FORM_SET_FD_ORDER_ID:\r
+      case FORM_SET_HD_ORDER_ID:\r
+      case FORM_SET_CD_ORDER_ID:\r
+      case FORM_SET_NET_ORDER_ID:\r
+      case FORM_SET_BEV_ORDER_ID:\r
+        CleanUpPage (QuestionId, Private);\r
+        UpdateSetLegacyDeviceOrderPage (QuestionId, Private);\r
+        break;\r
+\r
+      case KEY_VALUE_SAVE_AND_EXIT:\r
+      case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+        if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
+          Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+        } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+          DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+        }\r
+\r
+        //\r
+        // Tell browser not to ask for confirmation of changes,\r
+        // since we have already applied or discarded.\r
+        //\r
+        *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
+      Index2                    = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
+      Private->CurrentTerminal  = Index2;\r
+\r
+      CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+      UpdateTerminalPage (Private);\r
+\r
+    } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
+      Index2                  = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
+\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+      ASSERT (NewMenuEntry != NULL);\r
+      Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+      CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+      Private->MenuEntry                  = NewMenuEntry;\r
+      Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;\r
+\r
+      UpdateDriverAddHandleDescPage (Private);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Pass changed uncommitted data back to Form Browser\r
+  //\r
+  BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+  Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Function handling request to apply changes for BMM pages.\r
+\r
+  @param Private            Pointer to callback data buffer.\r
+  @param CurrentFakeNVMap   Pointer to buffer holding data of various values used by BMM\r
+  @param FormId             ID of the form which has sent the request to apply change.\r
+\r
+  @retval  EFI_SUCCESS       Change successfully applied.\r
+  @retval  Other             Error occurs while trying to apply changes.\r
+\r
+**/\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  EFI_FORM_ID                     FormId\r
+  )\r
+{\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  BM_LOAD_CONTEXT     *NewLoadContext;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  EFI_STATUS          Status;\r
+  UINT16              Index;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (FormId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+  case FORM_SET_HD_ORDER_ID:\r
+  case FORM_SET_CD_ORDER_ID:\r
+  case FORM_SET_NET_ORDER_ID:\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    Var_UpdateBBSOption (Private);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (UINT8)));\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+    }\r
+\r
+    Var_DelBootOption ();\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (UINT8)));\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+    }\r
+\r
+    Var_DelDriverOption ();\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    Status = Var_UpdateBootOrder (Private);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    Status = Var_UpdateDriverOrder (Private);\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    Status = gRT->SetVariable (\r
+                    L"Timeout",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    sizeof (UINT16),\r
+                    &(CurrentFakeNVMap->BootTimeOut)\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    Status = Var_UpdateBootNext (Private);\r
+    break;\r
+\r
+  case FORM_CON_MODE_ID:\r
+    Status = Var_UpdateConMode (Private);\r
+    break;\r
+\r
+  case FORM_CON_COM_SETUP_ID:\r
+    NewMenuEntry                      = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+    ASSERT (NewMenuEntry != NULL);\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+    ASSERT (CurrentFakeNVMap->COMBaudRate < (sizeof (BaudRateList) / sizeof (BaudRateList[0])));\r
+    NewTerminalContext->BaudRate      = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+    NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+    ASSERT (CurrentFakeNVMap->COMDataRate < (sizeof (DataBitsList) / sizeof (DataBitsList[0])));\r
+    NewTerminalContext->DataBits      = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+    NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+    ASSERT (CurrentFakeNVMap->COMStopBits < (sizeof (StopBitsList) / sizeof (StopBitsList[0])));\r
+    NewTerminalContext->StopBits      = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+    NewTerminalContext->ParityIndex   = CurrentFakeNVMap->COMParity;\r
+    ASSERT (CurrentFakeNVMap->COMParity < (sizeof (ParityList) / sizeof (ParityList[0])));\r
+    NewTerminalContext->Parity        = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+    NewTerminalContext->TerminalType  = CurrentFakeNVMap->COMTerminalType;\r
+\r
+    ChangeTerminalDevicePath (\r
+      NewTerminalContext->DevicePath,\r
+      FALSE\r
+      );\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    Var_UpdateConsoleOutOption ();\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_IN_ID:\r
+    ASSERT ((ConsoleInpMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+    for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleInpOption ();\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    ASSERT ((ConsoleOutMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+    for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsConOut  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateConsoleOutOption ();\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    ASSERT ((ConsoleErrMenu.MenuNumber + TerminalMenu.MenuNumber) <= (sizeof (CurrentFakeNVMap->ConsoleCheck) / sizeof (UINT8)));\r
+    for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+      NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+    }\r
+\r
+    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+      NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+      NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewTerminalContext->IsStdErr  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+    }\r
+\r
+    Var_UpdateErrorOutOption ();\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+    Status = Var_UpdateDriverOption (\r
+               Private,\r
+               Private->BmmHiiHandle,\r
+               CurrentFakeNVMap->DriverAddHandleDesc,\r
+               CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+               CurrentFakeNVMap->DriverAddForceReconnect\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    BOpt_GetDriverOptions (Private);\r
+    CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+Error:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Discard all changes done to the BMM pages such as Boot Order change,\r
+  Driver order change.\r
+\r
+  @param Private            The BMM context data.\r
+  @param CurrentFakeNVMap   The current Fack NV Map.\r
+\r
+**/\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  )\r
+{\r
+  UINT16  Index;\r
+\r
+  switch (Private->BmmPreviousPageId) {\r
+  case FORM_BOOT_CHG_ID:\r
+  case FORM_DRV_CHG_ID:\r
+    CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+    break;\r
+\r
+  case FORM_BOOT_DEL_ID:\r
+    ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_DRV_DEL_ID:\r
+    ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));\r
+    for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+      CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+    }\r
+    break;\r
+\r
+  case FORM_BOOT_NEXT_ID:\r
+    CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+    break;\r
+\r
+  case FORM_TIME_OUT_ID:\r
+    CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+    break;\r
+\r
+  case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+  case FORM_DRV_ADD_FILE_ID:\r
+  case FORM_DRV_ADD_HANDLE_ID:\r
+    CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;\r
+    CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Initialize the Boot Maintenance Utitliy.\r
+\r
+\r
+  @retval  EFI_SUCCESS      utility ended successfully\r
+  @retval  others           contain some errors\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  )\r
+{\r
+  EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+  BMM_CALLBACK_DATA           *BmmCallbackInfo;\r
+  EFI_STATUS                  Status;\r
+  UINT8                       *Ptr;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // Create CallbackData structures for Driver Callback\r
+  //\r
+  BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+  if (BmmCallbackInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+  //\r
+  Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+  if (Ptr == NULL) {\r
+    FreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Initialize Bmm callback data.\r
+  //\r
+  BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+  BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+  BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+  Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+  BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;\r
+\r
+  BmmCallbackInfo->Signature                     = BMM_CALLBACK_DATA_SIGNATURE;\r
+  BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;\r
+  BmmCallbackInfo->BmmConfigAccess.RouteConfig   = FakeRouteConfig;\r
+  BmmCallbackInfo->BmmConfigAccess.Callback      = BootMaintCallback;\r
+  BmmCallbackInfo->BmmPreviousPageId             = FORM_MAIN_ID;\r
+  BmmCallbackInfo->BmmCurrentPageId              = FORM_MAIN_ID;\r
+  BmmCallbackInfo->FeConfigAccess.ExtractConfig  = FakeExtractConfig;\r
+  BmmCallbackInfo->FeConfigAccess.RouteConfig    = FakeRouteConfig;\r
+  BmmCallbackInfo->FeConfigAccess.Callback       = FileExplorerCallback;\r
+  BmmCallbackInfo->FeCurrentState                = INACTIVE_STATE;\r
+  BmmCallbackInfo->FeDisplayContext              = UNKNOWN_CONTEXT;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &BmmCallbackInfo->BmmDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->BmmConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &BmmCallbackInfo->FeDriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &BmmCallbackInfo->FeConfigAccess\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Post our Boot Maint VFR binnary to the HII database.\r
+  //\r
+  PackageList = HiiLibPreparePackageList (2, &mBootMaintGuid, BmBin, BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           BmmCallbackInfo->BmmDriverHandle,\r
+                           &BmmCallbackInfo->BmmHiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  //\r
+  // Post our File Explorer VFR binary to the HII database.\r
+  //\r
+  PackageList = HiiLibPreparePackageList (2, &mFileExplorerGuid, FEBin, BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           BmmCallbackInfo->FeDriverHandle,\r
+                           &BmmCallbackInfo->FeHiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  //\r
+  // Allocate space for creation of Buffer\r
+  //\r
+  gUpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+  gUpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+  if (gUpdateData.Data == NULL) {\r
+    FreePool (BmmCallbackInfo->LoadContext);\r
+    FreePool (BmmCallbackInfo);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  InitializeStringDepository ();\r
+\r
+  InitAllMenu (BmmCallbackInfo);\r
+\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+  CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+  UpdateBootDelPage (BmmCallbackInfo);\r
+  UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+  if (TerminalMenu.MenuNumber > 0) {\r
+    BmmCallbackInfo->CurrentTerminal = 0;\r
+    UpdateTerminalPage (BmmCallbackInfo);\r
+  }\r
+\r
+  Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+  if (!EFI_ERROR (Status)) {\r
+    RefreshUpdateData ();\r
+\r
+    //\r
+    // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+    // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+    //\r
+    CreateGotoOpCode (\r
+      FORM_SET_FD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_FD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_HD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_HD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_CD_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_CD_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_NET_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_NET_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_SET_BEV_ORDER_ID,\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      FORM_SET_BEV_ORDER_ID,\r
+      &gUpdateData\r
+      );\r
+\r
+    IfrLibUpdateForm (\r
+      BmmCallbackInfo->BmmHiiHandle,\r
+      &mBootMaintGuid,\r
+      FORM_MAIN_ID,\r
+      FORM_BOOT_LEGACY_DEVICE_ID,\r
+      FALSE,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  //\r
+  // Dispatch BMM main formset and File Explorer formset.\r
+  //\r
+  FormSetDispatcher (BmmCallbackInfo);\r
+\r
+  //\r
+  // Remove our IFR data from HII database\r
+  //\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);\r
+\r
+  CleanUpStringDepository ();\r
+\r
+  FreeAllMenu ();\r
+\r
+  FreePool (BmmCallbackInfo->LoadContext);\r
+  FreePool (BmmCallbackInfo);\r
+  FreePool (gUpdateData.Data);\r
+  gUpdateData.Data = NULL;\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Initialized all Menu Option List.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+InitAllMenu (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  BOpt_GetBootOptions (CallbackData);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  BOpt_GetLegacyOptions ();\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+  BOpt_FindDrivers ();\r
+  InitializeListHead (&DirectoryMenu.Head);\r
+  InitializeListHead (&ConsoleInpMenu.Head);\r
+  InitializeListHead (&ConsoleOutMenu.Head);\r
+  InitializeListHead (&ConsoleErrMenu.Head);\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  LocateSerialIo ();\r
+  GetAllConsoles ();\r
+}\r
+\r
+/**\r
+  Free up all Menu Option list.\r
+\r
+**/\r
+VOID\r
+FreeAllMenu (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&DirectoryMenu);\r
+  BOpt_FreeMenu (&FsOptionMenu);\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_FreeMenu (&DriverMenu);\r
+  BOpt_FreeLegacyOptions ();\r
+  FreeAllConsoles ();\r
+}\r
+\r
+/**\r
+  Intialize all the string depositories.\r
+\r
+**/\r
+VOID\r
+InitializeStringDepository (\r
+  VOID\r
+  )\r
+{\r
+  STRING_DEPOSITORY *StringDepository;\r
+  StringDepository              = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+  FileOptionStrDepository       = StringDepository++;\r
+  ConsoleOptionStrDepository    = StringDepository++;\r
+  BootOptionStrDepository       = StringDepository++;\r
+  BootOptionHelpStrDepository   = StringDepository++;\r
+  DriverOptionStrDepository     = StringDepository++;\r
+  DriverOptionHelpStrDepository = StringDepository++;\r
+  TerminalStrDepository         = StringDepository;\r
+}\r
+\r
+/**\r
+  Fetch a usable string node from the string depository and return the string token.\r
+\r
+  @param CallbackData       The BMM context data.\r
+  @param StringDepository   The string repository.\r
+\r
+  @retval  EFI_STRING_ID           String token.\r
+\r
+**/\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  )\r
+{\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+\r
+  CurrentListNode = StringDepository->CurrentNode;\r
+\r
+  if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+    //\r
+    // Fetch one reclaimed node from the list.\r
+    //\r
+    NextListNode = StringDepository->CurrentNode->Next;\r
+  } else {\r
+    //\r
+    // If there is no usable node in the list, update the list.\r
+    //\r
+    NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+    ASSERT (NextListNode != NULL);\r
+    HiiLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");\r
+    ASSERT (NextListNode->StringToken != 0);\r
+\r
+    StringDepository->TotalNodeNumber++;\r
+\r
+    if (NULL == CurrentListNode) {\r
+      StringDepository->ListHead = NextListNode;\r
+    } else {\r
+      CurrentListNode->Next = NextListNode;\r
+    }\r
+  }\r
+\r
+  StringDepository->CurrentNode = NextListNode;\r
+\r
+  return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+/**\r
+  Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+**/\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  )\r
+{\r
+  UINTN             DepositoryIndex;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    StringDepository->CurrentNode = StringDepository->ListHead;\r
+    StringDepository++;\r
+  }\r
+}\r
+\r
+/**\r
+  Release resource for all the string depositories.\r
+\r
+**/\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  )\r
+{\r
+  UINTN             NodeIndex;\r
+  UINTN             DepositoryIndex;\r
+  STRING_LIST_NODE  *CurrentListNode;\r
+  STRING_LIST_NODE  *NextListNode;\r
+  STRING_DEPOSITORY *StringDepository;\r
+\r
+  //\r
+  // Release string list nodes.\r
+  //\r
+  StringDepository = FileOptionStrDepository;\r
+  for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+    CurrentListNode = StringDepository->ListHead;\r
+    for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+      NextListNode = CurrentListNode->Next;\r
+      FreePool (CurrentListNode);\r
+      CurrentListNode = NextListNode;\r
+    }\r
+\r
+    StringDepository++;\r
+  }\r
+  //\r
+  // Release string depository.\r
+  //\r
+  FreePool (FileOptionStrDepository);\r
+}\r
+\r
+/**\r
+  Start boot maintenance manager\r
+\r
+  @retval EFI_SUCCESS If BMM is invoked successfully.\r
+  @return Other value if BMM return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  LIST_ENTRY      BdsBootOptionList;\r
+\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // Have chance to enumerate boot device\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  //\r
+  // Init the BMM\r
+  //\r
+  Status = InitializeBM ();\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Dispatch BMM formset and FileExplorer formset.\r
+\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS If function complete successfully.\r
+  @return Other value if the Setup Browser process BMM's pages and\r
+           return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+  while (TRUE) {\r
+    UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = gFormBrowser2->SendForm (\r
+                             gFormBrowser2,\r
+                             &CallbackData->BmmHiiHandle,\r
+                             1,\r
+                             NULL,\r
+                             0,\r
+                             NULL,\r
+                             &ActionRequest\r
+                             );\r
+    if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    ReclaimStringDepository ();\r
+\r
+    //\r
+    // When this Formset returns, check if we are going to explore files.\r
+    //\r
+    if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+      UpdateFileExplorer (CallbackData, 0);\r
+\r
+      ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+      Status = gFormBrowser2->SendForm (\r
+                               gFormBrowser2,\r
+                               &CallbackData->FeHiiHandle,\r
+                               1,\r
+                               NULL,\r
+                               0,\r
+                               NULL,\r
+                               &ActionRequest\r
+                               );\r
+      if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+        EnableResetRequired ();\r
+      }\r
+\r
+      CallbackData->FeCurrentState    = INACTIVE_STATE;\r
+      CallbackData->FeDisplayContext  = UNKNOWN_CONTEXT;\r
+      ReclaimStringDepository ();\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Deletete the Boot Option from EFI Variable. The Boot Order Arrray\r
+  is also updated.\r
+\r
+  @param OptionNumber    The number of Boot option want to be deleted.\r
+  @param BootOrder       The Boot Order array.\r
+  @param BootOrderSize   The size of the Boot Order Array.\r
+\r
+  @return Other value if the Boot Option specified by OptionNumber is not deleteed succesfully.\r
+  @retval EFI_SUCCESS    If function return successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+  IN UINTN                       OptionNumber,\r
+  IN OUT UINT16                  *BootOrder,\r
+  IN OUT UINTN                   *BootOrderSize\r
+  )\r
+{\r
+  UINT16      BootOption[100];\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index2Del;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  Index2Del = 0;\r
+\r
+  UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+  Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+  \r
+  //\r
+  // adjust boot order array\r
+  //\r
+  for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+    if (BootOrder[Index] == OptionNumber) {\r
+      Index2Del = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+    for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+      if (Index >= Index2Del) {\r
+        BootOrder[Index] = BootOrder[Index + 1];\r
+      }\r
+    }\r
+\r
+    *BootOrderSize -= sizeof (UINT16);\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
new file mode 100644 (file)
index 0000000..2db1337
--- /dev/null
@@ -0,0 +1,1612 @@
+/** @file\r
+  Header file for boot maintenance module.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _BOOT_MAINT_H_\r
+#define _BOOT_MAINT_H_\r
+\r
+#include "Bds.h"\r
+#include "BBSsupport.h"\r
+#include "FormGuid.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder"\r
+\r
+#define VAR_CON_OUT_MODE L"ConOutMode"\r
+\r
+///\r
+/// Guid of a NV Variable which store the information about the\r
+/// FD/HD/CD/NET/BEV order\r
+///\r
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \\r
+  { \\r
+  0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \\r
+  }\r
+\r
+//\r
+// String Contant\r
+//\r
+#define STR_FLOPPY       L"Floppy Drive #%02x"\r
+#define STR_HARDDISK     L"HardDisk Drive #%02x"\r
+#define STR_CDROM        L"ATAPI CDROM Drive #%02x"\r
+#define STR_NET          L"NET Drive #%02x"\r
+#define STR_BEV          L"BEV Drive #%02x"\r
+#define STR_FLOPPY_HELP   L"Select Floppy Drive #%02x"\r
+#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x"\r
+#define STR_CDROM_HELP    L"Select ATAPI CDROM Drive #%02x"\r
+#define STR_NET_HELP      L"NET Drive #%02x"\r
+#define STR_BEV_HELP      L"BEV Drive #%02x"\r
+\r
+//\r
+// Variable created with this flag will be "Efi:...."\r
+//\r
+#define VAR_FLAG  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR      480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+extern EFI_GUID mBootMaintGuid;\r
+extern EFI_GUID mFileExplorerGuid;\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8    BmBin[];\r
+extern UINT8    FEBin[];\r
+\r
+//\r
+// Below are the number of options in Baudrate, Databits,\r
+// Parity and Stopbits selection for serial ports.\r
+//\r
+#define BM_COM_ATTR_BUADRATE  19\r
+#define BM_COM_ATTR_DATABITS  4\r
+#define BM_COM_ATTR_PARITY    5\r
+#define BM_COM_ATTR_STOPBITS  3\r
+\r
+//\r
+// Callback function helper\r
+//\r
+#define BMM_CALLBACK_DATA_SIGNATURE     SIGNATURE_32 ('C', 'b', 'c', 'k')\r
+#define BMM_CALLBACK_DATA_FROM_THIS(a)  CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+#define FE_CALLBACK_DATA_FROM_THIS(a)   CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+//\r
+// Enumeration type definition\r
+//\r
+typedef UINT8 BBS_TYPE;\r
+\r
+typedef enum {\r
+  PC_ANSI                             = 0,\r
+  VT_100,\r
+  VT_100_PLUS,\r
+  VT_UTF8\r
+} TYPE_OF_TERMINAL;\r
+\r
+typedef enum {\r
+  COM1                                = 0,\r
+  COM2,\r
+  UNKNOW_COM\r
+} TYPE_OF_COM;\r
+\r
+typedef enum {\r
+  CONIN                               = 0,\r
+  CONOUT,\r
+  CONERR,\r
+  UNKNOWN_CON\r
+} TYPE_OF_CON;\r
+\r
+typedef enum {\r
+  BAUDRATE                            = 0,\r
+  DATABITS,\r
+  PARITY,\r
+  STOPBITS,\r
+  UNKNOW_ATTR\r
+} TYPE_OF_ATTRIBUTE;\r
+\r
+typedef enum {\r
+  MANNER_GOTO                         = 0,\r
+  MANNER_CHECK,\r
+  MANNER_ONEOF,\r
+  MANNER_USER_DEFINE\r
+} TYPE_OF_UPATE_MANNER;\r
+\r
+typedef enum {\r
+  INACTIVE_STATE                      = 0,\r
+  BOOT_FROM_FILE_STATE,\r
+  ADD_BOOT_OPTION_STATE,\r
+  ADD_DRIVER_OPTION_STATE,\r
+  UNKNOWN_STATE\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef enum {\r
+  FILE_SYSTEM,\r
+  DIRECTORY,\r
+  UNKNOWN_CONTEXT\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+//\r
+// All of the signatures that will be used in list structure\r
+//\r
+#define BM_MENU_OPTION_SIGNATURE      SIGNATURE_32 ('m', 'e', 'n', 'u')\r
+#define BM_LOAD_OPTION_SIGNATURE      SIGNATURE_32 ('l', 'o', 'a', 'd')\r
+#define BM_CONSOLE_OPTION_SIGNATURE   SIGNATURE_32 ('c', 'n', 's', 'l')\r
+#define BM_FILE_OPTION_SIGNATURE      SIGNATURE_32 ('f', 'i', 'l', 'e')\r
+#define BM_HANDLE_OPTION_SIGNATURE    SIGNATURE_32 ('h', 'n', 'd', 'l')\r
+#define BM_TERMINAL_OPTION_SIGNATURE  SIGNATURE_32 ('t', 'r', 'm', 'l')\r
+#define BM_MENU_ENTRY_SIGNATURE       SIGNATURE_32 ('e', 'n', 't', 'r')\r
+\r
+#define BM_LOAD_CONTEXT_SELECT        0x0\r
+#define BM_CONSOLE_CONTEXT_SELECT     0x1\r
+#define BM_FILE_CONTEXT_SELECT        0x2\r
+#define BM_HANDLE_CONTEXT_SELECT      0x3\r
+#define BM_TERMINAL_CONTEXT_SELECT    0x5\r
+\r
+#define BM_CONSOLE_IN_CONTEXT_SELECT  0x6\r
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7\r
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8\r
+#define BM_LEGACY_DEV_CONTEXT_SELECT  0x9\r
+\r
+//\r
+// Buffer size for update data\r
+//\r
+#define UPDATE_DATA_SIZE        0x100000\r
+\r
+//\r
+// Namespace of callback keys used in display and file system navigation\r
+//\r
+#define MAX_BBS_OFFSET          0xE000\r
+#define NET_OPTION_OFFSET       0xD800\r
+#define BEV_OPTION_OFFSET       0xD000\r
+#define FD_OPTION_OFFSET        0xC000\r
+#define HD_OPTION_OFFSET        0xB000\r
+#define CD_OPTION_OFFSET        0xA000\r
+#define FILE_OPTION_OFFSET      0x8000\r
+#define FILE_OPTION_MASK        0x7FFF\r
+#define HANDLE_OPTION_OFFSET    0x7000\r
+#define CONSOLE_OPTION_OFFSET   0x6000\r
+#define TERMINAL_OPTION_OFFSET  0x5000\r
+#define CONFIG_OPTION_OFFSET    0x1200\r
+#define KEY_VALUE_OFFSET        0x1100\r
+#define FORM_ID_OFFSET          0x1000\r
+\r
+//\r
+// VarOffset that will be used to create question\r
+// all these values are computed from the structure\r
+// defined below\r
+//\r
+#define VAR_OFFSET(Field)              ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))\r
+\r
+//\r
+// Question Id of Zero is invalid, so add an offset to it\r
+//\r
+#define QUESTION_ID(Field)             (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)\r
+\r
+#define BOOT_TIME_OUT_VAR_OFFSET        VAR_OFFSET (BootTimeOut)\r
+#define BOOT_NEXT_VAR_OFFSET            VAR_OFFSET (BootNext)\r
+#define COM1_BAUD_RATE_VAR_OFFSET       VAR_OFFSET (COM1BaudRate)\r
+#define COM1_DATA_RATE_VAR_OFFSET       VAR_OFFSET (COM1DataRate)\r
+#define COM1_STOP_BITS_VAR_OFFSET       VAR_OFFSET (COM1StopBits)\r
+#define COM1_PARITY_VAR_OFFSET          VAR_OFFSET (COM1Parity)\r
+#define COM1_TERMINAL_VAR_OFFSET        VAR_OFFSET (COM2TerminalType)\r
+#define COM2_BAUD_RATE_VAR_OFFSET       VAR_OFFSET (COM2BaudRate)\r
+#define COM2_DATA_RATE_VAR_OFFSET       VAR_OFFSET (COM2DataRate)\r
+#define COM2_STOP_BITS_VAR_OFFSET       VAR_OFFSET (COM2StopBits)\r
+#define COM2_PARITY_VAR_OFFSET          VAR_OFFSET (COM2Parity)\r
+#define COM2_TERMINAL_VAR_OFFSET        VAR_OFFSET (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET  VAR_OFFSET (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_VAR_OFFSET       VAR_OFFSET (DriverAddActive)\r
+#define DRV_ADD_RECON_VAR_OFFSET        VAR_OFFSET (DriverAddForceReconnect)\r
+#define CON_IN_COM1_VAR_OFFSET          VAR_OFFSET (ConsoleInputCOM1)\r
+#define CON_IN_COM2_VAR_OFFSET          VAR_OFFSET (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_VAR_OFFSET         VAR_OFFSET (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_VAR_OFFSET         VAR_OFFSET (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_VAR_OFFSET         VAR_OFFSET (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_VAR_OFFSET         VAR_OFFSET (ConsoleErrorCOM2)\r
+#define CON_MODE_VAR_OFFSET             VAR_OFFSET (ConsoleOutMode)\r
+#define CON_DEVICE_VAR_OFFSET           VAR_OFFSET (ConsoleCheck)\r
+#define OPTION_ORDER_VAR_OFFSET         VAR_OFFSET (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_VAR_OFFSET  VAR_OFFSET (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_VAR_OFFSET      VAR_OFFSET (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_VAR_OFFSET    VAR_OFFSET (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_VAR_OFFSET    VAR_OFFSET (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_VAR_OFFSET        VAR_OFFSET (COMBaudRate)\r
+#define COM_DATA_RATE_VAR_OFFSET        VAR_OFFSET (COMDataRate)\r
+#define COM_STOP_BITS_VAR_OFFSET        VAR_OFFSET (COMStopBits)\r
+#define COM_PARITY_VAR_OFFSET           VAR_OFFSET (COMParity)\r
+#define COM_TERMINAL_VAR_OFFSET         VAR_OFFSET (COMTerminalType)\r
+#define LEGACY_FD_VAR_OFFSET            VAR_OFFSET (LegacyFD)\r
+#define LEGACY_HD_VAR_OFFSET            VAR_OFFSET (LegacyHD)\r
+#define LEGACY_CD_VAR_OFFSET            VAR_OFFSET (LegacyCD)\r
+#define LEGACY_NET_VAR_OFFSET           VAR_OFFSET (LegacyNET)\r
+#define LEGACY_BEV_VAR_OFFSET           VAR_OFFSET (LegacyBEV)\r
+\r
+#define BOOT_TIME_OUT_QUESTION_ID       QUESTION_ID (BootTimeOut)\r
+#define BOOT_NEXT_QUESTION_ID           QUESTION_ID (BootNext)\r
+#define COM1_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM1BaudRate)\r
+#define COM1_DATA_RATE_QUESTION_ID      QUESTION_ID (COM1DataRate)\r
+#define COM1_STOP_BITS_QUESTION_ID      QUESTION_ID (COM1StopBits)\r
+#define COM1_PARITY_QUESTION_ID         QUESTION_ID (COM1Parity)\r
+#define COM1_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define COM2_BAUD_RATE_QUESTION_ID      QUESTION_ID (COM2BaudRate)\r
+#define COM2_DATA_RATE_QUESTION_ID      QUESTION_ID (COM2DataRate)\r
+#define COM2_STOP_BITS_QUESTION_ID      QUESTION_ID (COM2StopBits)\r
+#define COM2_PARITY_QUESTION_ID         QUESTION_ID (COM2Parity)\r
+#define COM2_TERMINAL_QUESTION_ID       QUESTION_ID (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_QUESTION_ID      QUESTION_ID (DriverAddActive)\r
+#define DRV_ADD_RECON_QUESTION_ID       QUESTION_ID (DriverAddForceReconnect)\r
+#define CON_IN_COM1_QUESTION_ID         QUESTION_ID (ConsoleInputCOM1)\r
+#define CON_IN_COM2_QUESTION_ID         QUESTION_ID (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_QUESTION_ID        QUESTION_ID (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_QUESTION_ID        QUESTION_ID (ConsoleErrorCOM2)\r
+#define CON_MODE_QUESTION_ID            QUESTION_ID (ConsoleOutMode)\r
+#define CON_DEVICE_QUESTION_ID          QUESTION_ID (ConsoleCheck)\r
+#define OPTION_ORDER_QUESTION_ID        QUESTION_ID (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_QUESTION_ID     QUESTION_ID (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_QUESTION_ID   QUESTION_ID (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_QUESTION_ID   QUESTION_ID (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_QUESTION_ID       QUESTION_ID (COMBaudRate)\r
+#define COM_DATA_RATE_QUESTION_ID       QUESTION_ID (COMDataRate)\r
+#define COM_STOP_BITS_QUESTION_ID       QUESTION_ID (COMStopBits)\r
+#define COM_PARITY_QUESTION_ID          QUESTION_ID (COMParity)\r
+#define COM_TERMINAL_QUESTION_ID        QUESTION_ID (COMTerminalType)\r
+#define LEGACY_FD_QUESTION_ID           QUESTION_ID (LegacyFD)\r
+#define LEGACY_HD_QUESTION_ID           QUESTION_ID (LegacyHD)\r
+#define LEGACY_CD_QUESTION_ID           QUESTION_ID (LegacyCD)\r
+#define LEGACY_NET_QUESTION_ID          QUESTION_ID (LegacyNET)\r
+#define LEGACY_BEV_QUESTION_ID          QUESTION_ID (LegacyBEV)\r
+\r
+#define STRING_DEPOSITORY_NUMBER        8\r
+\r
+///\r
+/// Serial Ports attributes, first one is the value for\r
+/// return from callback function, stringtoken is used to\r
+/// display the value properly\r
+///\r
+typedef struct {\r
+  UINTN   Value;\r
+  UINT16  StringToken;\r
+} COM_ATTR;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  BBS_TYPE  BbsType;\r
+  ///\r
+  /// Length = sizeof (UINT16) + SIZEOF (Data)\r
+  ///\r
+  UINT16    Length;\r
+  UINT16    *Data;\r
+} BM_LEGACY_DEV_ORDER_CONTEXT;\r
+#pragma pack()\r
+\r
+typedef struct {\r
+  UINT64                    BaudRate;\r
+  UINT8                     DataBits;\r
+  UINT8                     Parity;\r
+  UINT8                     StopBits;\r
+\r
+  UINT8                     BaudRateIndex;\r
+  UINT8                     DataBitsIndex;\r
+  UINT8                     ParityIndex;\r
+  UINT8                     StopBitsIndex;\r
+\r
+  UINT8                     IsConIn;\r
+  UINT8                     IsConOut;\r
+  UINT8                     IsStdErr;\r
+  UINT8                     TerminalType;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_TERMINAL_CONTEXT;\r
+\r
+typedef struct {\r
+  BOOLEAN                   IsBootNext;\r
+  BOOLEAN                   LoadOptionModified;\r
+  BOOLEAN                   Deleted;\r
+\r
+  BOOLEAN                   IsLegacy;\r
+  BOOLEAN                   IsActive;\r
+  BOOLEAN                   ForceReconnect;\r
+  UINTN                     OptionalDataSize;\r
+\r
+  UINTN                     LoadOptionSize;\r
+  UINT8                     *LoadOption;\r
+\r
+  UINT32                    Attributes;\r
+  UINT16                    FilePathListLength;\r
+  UINT16                    *Description;\r
+  EFI_DEVICE_PATH_PROTOCOL  *FilePathList;\r
+  UINT8                     *OptionalData;\r
+\r
+  UINT16                    BbsIndex;\r
+} BM_LOAD_CONTEXT;\r
+\r
+typedef struct {\r
+  BBS_TABLE *BbsTable;\r
+  UINTN     Index;\r
+  UINTN     BbsCount;\r
+  UINT16    *Description;\r
+} BM_LEGACY_DEVICE_CONTEXT;\r
+\r
+typedef struct {\r
+\r
+  BOOLEAN                   IsActive;\r
+\r
+  BOOLEAN                   IsTerminal;\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_CONSOLE_CONTEXT;\r
+\r
+typedef struct {\r
+  UINTN   Column;\r
+  UINTN   Row;\r
+} CONSOLE_OUT_MODE;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                        Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;\r
+  EFI_FILE_HANDLE                   FHandle;\r
+  UINT16                            *FileName;\r
+  EFI_FILE_SYSTEM_VOLUME_LABEL      *Info;\r
+\r
+  BOOLEAN                           IsRoot;\r
+  BOOLEAN                           IsDir;\r
+  BOOLEAN                           IsRemovableMedia;\r
+  BOOLEAN                           IsLoadFile;\r
+  BOOLEAN                           IsBootLegacy;\r
+} BM_FILE_CONTEXT;\r
+\r
+typedef struct {\r
+  EFI_HANDLE                Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+} BM_HANDLE_CONTEXT;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Head;\r
+  UINTN           MenuNumber;\r
+} BM_MENU_OPTION;\r
+\r
+typedef struct {\r
+  UINTN           Signature;\r
+  LIST_ENTRY      Link;\r
+  UINTN           OptionNumber;\r
+  UINT16          *DisplayString;\r
+  UINT16          *HelpString;\r
+  EFI_STRING_ID   DisplayStringToken;\r
+  EFI_STRING_ID   HelpStringToken;\r
+  UINTN           ContextSelection;\r
+  VOID            *VariableContext;\r
+} BM_MENU_ENTRY;\r
+\r
+typedef struct {\r
+  //\r
+  // Shared callback data.\r
+  //\r
+  UINTN                          Signature;\r
+\r
+  BM_MENU_ENTRY                  *MenuEntry;\r
+  BM_HANDLE_CONTEXT              *HandleContext;\r
+  BM_FILE_CONTEXT                *FileContext;\r
+  BM_LOAD_CONTEXT                *LoadContext;\r
+  BM_TERMINAL_CONTEXT            *TerminalContext;\r
+  UINTN                          CurrentTerminal;\r
+  BBS_TYPE                       BbsType;\r
+\r
+  //\r
+  // BMM main formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                 BmmHiiHandle;\r
+  EFI_HANDLE                     BmmDriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;\r
+  EFI_FORM_ID                    BmmCurrentPageId;\r
+  EFI_FORM_ID                    BmmPreviousPageId;\r
+  BOOLEAN                        BmmAskSaveOrNot;\r
+  BMM_FAKE_NV_DATA               BmmFakeNvData;\r
+  BMM_FAKE_NV_DATA               BmmOldFakeNVData;\r
+\r
+  //\r
+  // File explorer formset callback data.\r
+  //\r
+  EFI_HII_HANDLE                 FeHiiHandle;\r
+  EFI_HANDLE                     FeDriverHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;\r
+  FILE_EXPLORER_STATE            FeCurrentState;\r
+  FILE_EXPLORER_DISPLAY_CONTEXT  FeDisplayContext;\r
+  FILE_EXPLORER_NV_DATA          FeFakeNvData;\r
+} BMM_CALLBACK_DATA;\r
+\r
+typedef struct _STRING_LIST_NODE {\r
+  EFI_STRING_ID             StringToken;\r
+  struct _STRING_LIST_NODE  *Next;\r
+} STRING_LIST_NODE;\r
+\r
+typedef struct _STRING_DEPOSITORY {\r
+  UINTN             TotalNodeNumber;\r
+  STRING_LIST_NODE  *CurrentNode;\r
+  STRING_LIST_NODE  *ListHead;\r
+} STRING_DEPOSITORY;\r
+\r
+//\r
+// #pragma pack()\r
+//\r
+// For initializing File System menu\r
+//\r
+\r
+/**\r
+  This function build the FsOptionMenu list which records all\r
+  available file system in the system. They includes all instances\r
+  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
+  and all type of legacy boot device.\r
+\r
+  @param CallbackData    BMM context data\r
+\r
+  @retval  EFI_SUCCESS             Success find the file system\r
+  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  );\r
+\r
+/**\r
+  Find files under current directory\r
+  All files and sub-directories in current directory\r
+  will be stored in DirectoryMenu for future use.\r
+\r
+  @param CallbackData  The BMM context data.\r
+  @param MenuEntry     The Menu Entry.\r
+\r
+  @retval EFI_SUCCESS         Get files from current dir successfully.\r
+  @return Other value if can't get files from current dir.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  );\r
+\r
+/**\r
+\r
+  Find drivers that will be added as Driver#### variables from handles\r
+  in current system environment\r
+  All valid handles in the system except those consume SimpleFs, LoadFile\r
+  are stored in DriverMenu for future use.\r
+\r
+  @retval EFI_SUCCESS The function complets successfully.\r
+  @return Other value if failed to build the DriverMenu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  Build the BootOptionMenu according to BootOrder Variable.\r
+  This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
+\r
+  @param CallbackData The BMM context data.\r
+\r
+  @return The number of the Var Boot####.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+/**\r
+\r
+  Build up all DriverOptionMenu\r
+\r
+  @param CallbackData The BMM context data.\r
+\r
+  @return EFI_SUCESS The functin completes successfully.\r
+  @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
+  \r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  );\r
+\r
+\r
+/**\r
+  Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+  @retval EFI_SUCCESS The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Free out resouce allocated from Legacy Boot Options.\r
+\r
+**/\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Free resources allocated in Allocate Rountine.\r
+\r
+  @param FreeMenu        Menu to be freed\r
+\r
+**/\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Append file name to existing file name.\r
+\r
+  @param Str1  The existing file name\r
+  @param Str2  The file name to be appended\r
+\r
+  @return Allocate a new string to hold the appended result.\r
+          Caller is responsible to free the returned string.\r
+\r
+**/\r
+CHAR16*\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  );\r
+\r
+/**\r
+\r
+  Check whether current FileName point to a valid\r
+  Efi Image File.\r
+\r
+  @param FileName  File need to be checked.\r
+\r
+  @retval TRUE  Is Efi Image\r
+  @retval FALSE Not a valid Efi Image\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  );\r
+\r
+/**\r
+\r
+  Check whether current FileName point to a valid Efi Application\r
+\r
+  @param Dir       Pointer to current Directory\r
+  @param FileName  Pointer to current File name.\r
+\r
+  @retval TRUE      Is a valid Efi Application\r
+  @retval FALSE     not a valid Efi Application\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  );\r
+\r
+/**\r
+\r
+  Get the Option Number that has not been allocated for use.\r
+\r
+  @return The available Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  Get the Option Number that is not in use.\r
+\r
+  @return The unused Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Create a menu entry give a Menu type.\r
+\r
+  @param MenuType        The Menu type to be created.\r
+\r
+\r
+  @retval NULL           If failed to create the menu.\r
+  @return                The menu.\r
+\r
+**/\r
+BM_MENU_ENTRY                     *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  );\r
+\r
+/**\r
+  Free up all resource allocated for a BM_MENU_ENTRY.\r
+\r
+  @param MenuEntry   A pointer to BM_MENU_ENTRY.\r
+\r
+**/\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  );\r
+\r
+/**\r
+  Get the Menu Entry from the list in Menu Entry List.\r
+\r
+  If MenuNumber is great or equal to the number of Menu\r
+  Entry in the list, then ASSERT.\r
+\r
+  @param MenuOption      The Menu Entry List to read the menu entry.\r
+  @param MenuNumber      The index of Menu Entry.\r
+\r
+  @return The Menu Entry.\r
+\r
+**/\r
+BM_MENU_ENTRY                     *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  );\r
+\r
+//\r
+// Locate all serial io devices for console\r
+//\r
+/**\r
+  Build a list containing all serial devices.\r
+\r
+  @retval EFI_SUCCESS The function complete successfully.\r
+  @retval EFI_UNSUPPORTED No serial ports present.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateSerialIo (\r
+  VOID\r
+  );\r
+\r
+//\r
+// Initializing Console menu\r
+//\r
+/**\r
+  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+  @retval EFI_SUCCESS    The function always complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAllConsoles(\r
+  VOID\r
+  );\r
+\r
+//\r
+// Get current mode information\r
+//\r
+/**\r
+  Get mode number according to column and row\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+GetConsoleOutMode (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+//\r
+// Cleaning up console menu\r
+//\r
+/**\r
+  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+  @retval EFI_SUCCESS    The function always complete successfully.\r
+**/\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Update the device path that describing a terminal device\r
+  based on the new BaudRate, Data Bits, parity and Stop Bits\r
+  set.\r
+\r
+  @param DevicePath     The devicepath protocol instance wanted to be updated.\r
+\r
+**/\r
+VOID\r
+ChangeVariableDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+/**\r
+  Update the multi-instance device path of Terminal Device based on\r
+  the global TerminalMenu. If ChangeTernimal is TRUE, the terminal \r
+  device path in the Terminal Device in TerminalMenu is also updated.\r
+\r
+  @param DevicePath      The multi-instance device path.\r
+  @param ChangeTerminal  TRUE, then device path in the Terminal Device \r
+                         in TerminalMenu is also updated; FALSE, no update.\r
+\r
+  @return EFI_SUCCESS    The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN BOOLEAN                   ChangeTerminal\r
+  );\r
+\r
+//\r
+// Variable operation by menu selection\r
+//\r
+/**\r
+  This function create a currently loaded Boot Option from \r
+  the BMM. It then appends this Boot Option to the end of \r
+  the "BootOrder" list. It also append this Boot Opotion to the end\r
+  of BootOptionMenu.\r
+\r
+  @param CallbackData           The BMM context data.\r
+  @param NvRamMap               The file explorer formset internal state.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  If not enought memory to complete the operation.\r
+  @retval EFI_SUCCESS           If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  );\r
+\r
+/**\r
+  Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this boot option, call Var_ChangeBootOrder to\r
+  make sure BootOrder is in valid state.\r
+\r
+  @retval EFI_SUCCESS   If all boot load option EFI Variables corresponding to  \r
+                        BM_LOAD_CONTEXT marked for deletion is deleted\r
+  @return Others        If failed to update the "BootOrder" variable after deletion. \r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+  Since some are missing but in BootOrder, while some are present but are\r
+  not reflected by BootOrder. Then a function rebuild BootOrder from\r
+  scratch by content from BootOptionMenu is needed.\r
+\r
+  @retval  EFI_SUCCESS  The boot order is updated successfully.\r
+  @return  other than EFI_SUCCESS if failed to change the "BootOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function create a currently loaded Drive Option from \r
+  the BMM. It then appends this Driver Option to the end of \r
+  the "DriverOrder" list. It append this Driver Opotion to the end\r
+  of DriverOptionMenu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+  @param HiiHandle       The HII handle associated with the BMM formset.\r
+  @param DescriptionData The description of this driver option.\r
+  @param OptionalData    The optional load option.\r
+  @param ForceReconnect  If to force reconnect.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+  @retval EFI_SUCCESS          If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  );\r
+\r
+/**\r
+  Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this Driver option, call Var_ChangeDriverOrder to\r
+  make sure DriverOrder is in valid state.\r
+\r
+  @retval EFI_SUCCESS Load Option is successfully updated.\r
+  @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI\r
+          Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  After any operation on Driver####, there will be a discrepancy in\r
+  DriverOrder. Since some are missing but in DriverOrder, while some\r
+  are present but are not reflected by DriverOrder. Then a function\r
+  rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+  needed.\r
+\r
+  @retval  EFI_SUCCESS  The driver order is updated successfully.\r
+  @return  other than EFI_SUCCESS if failed to set the "DriverOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function delete and build multi-instance device path ConIn\r
+  console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function delete and build multi-instance device path ConOut console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function delete and build multi-instance device path ErrOut console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Update the device path of "ConOut", "ConIn" and "ErrOut" based on the new BaudRate, Data Bits, \r
+  parity and stop Bits set.\r
+\r
+**/\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function update the "BootNext" EFI Variable. If there is no "BootNex" specified in BMM, \r
+  this EFI Variable is deleted.\r
+  It also update the BMM context data specified the "BootNext" value.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+/**\r
+  This function update the "BootOrder" EFI Variable based on BMM Formset's NV map. It then refresh \r
+  BootOptionMenu with the new "BootOrder" list.\r
+\r
+  @param CallbackData           The BMM context data.\r
+\r
+  @retval EFI_SUCCESS           The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory to complete the function.\r
+  @return not The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+/**\r
+  This function update the "DriverOrder" EFI Variable based on\r
+  BMM Formset's NV map. It then refresh DriverOptionMenu\r
+  with the new "DriverOrder" list.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS           The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory to complete the function.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+/**\r
+  Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable\r
+  is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
+  is also updated.\r
+\r
+  @param CallbackData    The context data for BMM.\r
+\r
+  @return EFI_SUCCESS    The function completed successfully.\r
+  @retval EFI_NOT_FOUND  If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+/**\r
+  Update the Text Mode of Console.\r
+\r
+  @param CallbackData  The context data for BMM.\r
+\r
+  @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
+  @return Other value if the Text Mode of Console is not updated.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  );\r
+\r
+//\r
+// Following are page create and refresh functions\r
+//\r
+/**\r
+  Refresh the global UpdateData structure.\r
+\r
+**/\r
+VOID\r
+RefreshUpdateData (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Clean up the dynamic opcode at label and form specified by\r
+  both LabelId. \r
+\r
+  @param LabelId         It is both the Form ID and Label ID for\r
+                         opcode deletion.\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create a lit of boot option from global BootOptionMenu. It\r
+  allow user to delete the boot option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create a lit of driver option from global DriverMenu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create a lit of driver option from global DriverOptionMenu. It\r
+  allow user to delete the driver option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Prepare the page to allow user to add description for a Driver Option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Dispatch the correct update page function to call based on the UpdatePageId.\r
+\r
+  @param UpdatePageId    The form ID.\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create the dynamic page to allow user to set the "BootNext" vaule.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create the dynamic page to allow user to set the "TimeOut" vaule.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,\r
+  Parity, Stop Bits, Terminal Type.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Refresh the text mode page\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateConModePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create a list of Goto Opcode for all terminal devices logged\r
+  by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+/**\r
+  Create a dynamic page so that Legacy Device boot order\r
+  can be set for specified device type.\r
+\r
+  @param UpdatePageId    The form ID. It also spefies the legacy device type.\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  );\r
+\r
+\r
+/**\r
+  Function opens and returns a file handle to the root directory of a volume.\r
+\r
+  @param DeviceHandle    A handle for a device\r
+  @return A valid file handle or NULL is returned\r
+**/\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+  IN EFI_HANDLE       DeviceHandle\r
+  );\r
+\r
+/**\r
+  Function gets the file system information from an open file descriptor,\r
+  and stores it in a buffer allocated from pool.\r
+\r
+  @param FHand           The file handle.\r
+\r
+  @return                A pointer to a buffer with file information.\r
+                         NULL is returned if failed to get Vaolume Label Info.\r
+**/\r
+EFI_FILE_SYSTEM_VOLUME_LABEL *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+/**\r
+\r
+  Function gets the file information from an open file descriptor, and stores it\r
+  in a buffer allocated from pool.\r
+\r
+  @param FHand           File Handle.\r
+\r
+  @return                A pointer to a buffer with file information or NULL is returned\r
+\r
+**/\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+  IN EFI_FILE_HANDLE      FHand\r
+  );\r
+\r
+/**\r
+  This function converts an input device structure to a Unicode string.\r
+\r
+  @param DevPath                  A pointer to the device path structure.\r
+\r
+  @return A new allocated Unicode string that represents the device path.\r
+\r
+**/\r
+CHAR16 *\r
+DevicePathToStr (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevPath\r
+  );\r
+\r
+/**\r
+  Find the first instance of this Protocol in the system and return it's interface.\r
+\r
+  @param ProtocolGuid    Provides the protocol to search for\r
+  @param Interface       On return, a pointer to the first interface\r
+                         that matches ProtocolGuid\r
+\r
+  @retval  EFI_SUCCESS      A protocol instance matching ProtocolGuid was found\r
+  @retval  EFI_NOT_FOUND    No protocol instances were found that match ProtocolGuid\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+  IN  EFI_GUID        *ProtocolGuid,\r
+  OUT VOID            **Interface\r
+  );\r
+\r
+/**\r
+  Adjusts the size of a previously allocated buffer.\r
+\r
+  @param OldPool         A pointer to the buffer whose size is being adjusted.\r
+  @param OldSize         The size of the current buffer.\r
+  @param NewSize         The size of the new buffer.\r
+\r
+  @return   The newly allocated buffer. if NULL, allocation failed.\r
+\r
+**/\r
+VOID*\r
+EfiReallocatePool (\r
+  IN VOID                 *OldPool,\r
+  IN UINTN                OldSize,\r
+  IN UINTN                NewSize\r
+  );\r
+\r
+/**\r
+  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
+  buffer, and the size of the buffer. If failure return NULL.\r
+\r
+  @param  Name                  String part of EFI variable name\r
+  @param  VendorGuid            GUID part of EFI variable name\r
+  @param  VarSize               Returns the size of the EFI variable that was read\r
+\r
+  @return Dynamically allocated memory that contains a copy of the EFI variable.\r
+  @return Caller is responsible freeing the buffer.\r
+  @retval NULL                  Variable was not read\r
+\r
+**/\r
+VOID *\r
+BdsLibGetVariableAndSize (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid,\r
+  OUT UINTN               *VarSize\r
+  );\r
+\r
+/**\r
+  Function deletes the variable specified by VarName and VarGuid.\r
+\r
+\r
+  @param VarName            A Null-terminated Unicode string that is\r
+                            the name of the vendor's variable.\r
+                         \r
+  @param VarGuid            A unique identifier for the vendor.\r
+\r
+  @retval  EFI_SUCCESS           The variable was found and removed\r
+  @retval  EFI_UNSUPPORTED       The variable store was inaccessible\r
+  @retval  EFI_OUT_OF_RESOURCES  The temporary buffer was not available\r
+  @retval  EFI_NOT_FOUND         The variable was not found\r
+\r
+**/\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+  IN CHAR16   *VarName,\r
+  IN EFI_GUID *VarGuid\r
+  );\r
+\r
+/**\r
+  Duplicate a string.\r
+\r
+  @param Src             The source.\r
+\r
+  @return A new string which is duplicated copy of the source.\r
+  @retval NULL If there is not enough memory.\r
+\r
+**/\r
+CHAR16                            *\r
+EfiStrDuplicate (\r
+  IN CHAR16   *Src\r
+  );\r
+\r
+/**\r
+  Function is used to determine the number of device path instances\r
+  that exist in a device path.\r
+\r
+\r
+  @param DevicePath      A pointer to a device path data structure.\r
+\r
+  @return This function counts and returns the number of device path instances\r
+          in DevicePath.\r
+\r
+**/\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  );\r
+\r
+/**\r
+  Create string tokens for a menu from its help strings and display strings\r
+\r
+\r
+  @param CallbackData    The BMM context data.\r
+  @param HiiHandle       Hii Handle of the package to be updated.\r
+  @param MenuOption      The Menu whose string tokens need to be created\r
+\r
+  @retval  EFI_SUCCESS      string tokens created successfully\r
+  @retval  others           contain some errors\r
+\r
+**/\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+  IN BMM_CALLBACK_DATA                *CallbackData,\r
+  IN EFI_HII_HANDLE                   HiiHandle,\r
+  IN BM_MENU_OPTION                   *MenuOption\r
+  );\r
+\r
+/**\r
+  Get a string from the Data Hub record based on \r
+  a device path.\r
+\r
+  @param DevPath         The device Path.\r
+\r
+  @return A string located from the Data Hub records based on\r
+          the device path.\r
+  @retval NULL  If failed to get the String from Data Hub.\r
+\r
+**/\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath\r
+  );\r
+\r
+/**\r
+  Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type\r
+  specified by DeviceType.\r
+\r
+  @param DeviceType      The legacy device type. It can be floppy, network, harddisk, cdrom,\r
+                         etc.\r
+  @param OptionIndex     Returns the index number (#### in Boot####).\r
+  @param OptionSize      Return the size of the Boot### variable.\r
+\r
+**/\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+  );\r
+\r
+/**\r
+  Initialize the Boot Maintenance Utitliy.\r
+\r
+  @retval  EFI_SUCCESS      utility ended successfully.\r
+  @retval  others           contain some errors.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBM (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Start boot maintenance manager\r
+\r
+  @retval EFI_SUCCESS If BMM is invoked successfully.\r
+  @return Other value if BMM return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Intialize all the string depositories.\r
+\r
+**/\r
+VOID\r
+InitializeStringDepository (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Fetch a usable string node from the string depository and return the string token.\r
+\r
+\r
+  @param CallbackData       The BMM context data.\r
+  @param StringDepository   Pointer of the string depository.\r
+\r
+  @retval  EFI_STRING_ID    String token.\r
+\r
+**/\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+  IN   BMM_CALLBACK_DATA     *CallbackData,\r
+  IN   STRING_DEPOSITORY     *StringDepository\r
+  );\r
+\r
+/**\r
+  Reclaim string depositories by moving the current node pointer to list head..\r
+**/\r
+VOID\r
+ReclaimStringDepository (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Release resource for all the string depositories.\r
+\r
+**/\r
+VOID\r
+CleanUpStringDepository (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Function handling request to apply changes for BMM pages.\r
+\r
+  @param Private            Pointer to callback data buffer.\r
+  @param CurrentFakeNVMap   Pointer to buffer holding data of various values used by BMM\r
+  @param FormId             ID of the form which has sent the request to apply change.\r
+\r
+  @retval  EFI_SUCCESS      Change successfully applied.\r
+  @retval  Other            Error occurs while trying to apply changes.\r
+\r
+**/\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
+  IN  EFI_FORM_ID                     FormId\r
+  );\r
+\r
+/**\r
+  Discard all changes done to the BMM pages such as Boot Order change,\r
+  Driver order change.\r
+\r
+  @param Private         The BMM context data.\r
+  @param CurrentFakeNVMap The current Fack NV Map.\r
+\r
+**/\r
+VOID\r
+DiscardChangeHandler (\r
+  IN  BMM_CALLBACK_DATA               *Private,\r
+  IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
+  );\r
+\r
+/**\r
+  Dispatch the display to the next page based on NewPageId.\r
+\r
+  @param Private         The BMM context data.\r
+  @param NewPageId       The original page ID.\r
+\r
+**/\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  );\r
+\r
+/**\r
+  Boot a file selected by user at File Expoloer of BMM.\r
+\r
+  @param FileContext     The file context data, which contains the device path\r
+                         of the file to be boot from.\r
+\r
+  @retval EFI_SUCCESS    The function completed successfull.\r
+  @return                 Other value if the boot from the file fails.\r
+\r
+**/\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  );\r
+\r
+/**\r
+  Update the file explower page with the refershed file system.\r
+\r
+\r
+  @param CallbackData    BMM context data\r
+  @param KeyValue        Key value to identify the type of data to expect.\r
+\r
+  @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.\r
+  @retval  FALSE          Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  );\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+  When user select a interactive opcode, this callback will be triggered.\r
+  Based on the Question(QuestionId) that triggers the callback, the corresponding\r
+  actions is performed. It handles:\r
+\r
+  1) the addition of boot option.\r
+  2) the addition of driver option.\r
+  3) exit from file browser\r
+  4) update of file content if a dir is selected.\r
+  5) boot the file if a file is selected in "boot from file"\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.\r
+  @retval  EFI_DEVICE_ERROR      The variable could not be saved.\r
+  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+/**\r
+  Dispatch BMM formset and FileExplorer formset.\r
+\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS If function complete successfully.\r
+  @return Other value if the Setup Browser process BMM's pages and\r
+           return unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  );\r
+\r
+/**\r
+  Function returns the value of the specified variable.\r
+\r
+  @param Name            A Null-terminated Unicode string that is\r
+                         the name of the vendor's variable.\r
+  @param VendorGuid      A unique identifier for the vendor.\r
+\r
+  @return               The payload of the variable.\r
+  @retval NULL          If the variable can't be read.\r
+\r
+**/\r
+VOID *\r
+EfiLibGetVariable (\r
+  IN CHAR16               *Name,\r
+  IN EFI_GUID             *VendorGuid\r
+  );\r
+\r
+//\r
+// Global variable in this program (defined in data.c)\r
+//\r
+extern BM_MENU_OPTION             BootOptionMenu;\r
+extern BM_MENU_OPTION             DriverOptionMenu;\r
+extern BM_MENU_OPTION             FsOptionMenu;\r
+extern BM_MENU_OPTION             ConsoleInpMenu;\r
+extern BM_MENU_OPTION             ConsoleOutMenu;\r
+extern BM_MENU_OPTION             ConsoleErrMenu;\r
+extern BM_MENU_OPTION             DirectoryMenu;\r
+extern BM_MENU_OPTION             DriverMenu;\r
+extern BM_MENU_OPTION             TerminalMenu;\r
+extern BM_MENU_OPTION             LegacyFDMenu;\r
+extern BM_MENU_OPTION             LegacyHDMenu;\r
+extern BM_MENU_OPTION             LegacyCDMenu;\r
+extern BM_MENU_OPTION             LegacyNETMenu;\r
+extern BM_MENU_OPTION             LegacyBEVMenu;\r
+extern UINT16                     TerminalType[];\r
+extern COM_ATTR                   BaudRateList[19];\r
+extern COM_ATTR                   DataBitsList[4];\r
+extern COM_ATTR                   ParityList[5];\r
+extern COM_ATTR                   StopBitsList[3];\r
+extern EFI_GUID                   TerminalTypeGuid[4];\r
+extern EFI_HII_UPDATE_DATA        gUpdateData;\r
+extern STRING_DEPOSITORY          *FileOptionStrDepository;\r
+extern STRING_DEPOSITORY          *ConsoleOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionStrDepository;\r
+extern STRING_DEPOSITORY          *BootOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionStrDepository;\r
+extern STRING_DEPOSITORY          *DriverOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY          *TerminalStrDepository;\r
+extern EFI_DEVICE_PATH_PROTOCOL   EndDevicePath[];\r
+extern EFI_GUID                   EfiLegacyDevOrderGuid;\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
new file mode 100644 (file)
index 0000000..e9caf59
--- /dev/null
@@ -0,0 +1,1661 @@
+/** @file\r
+  Provide boot option support for Application "BootMaint"\r
+\r
+  Include file system navigation, system handle selection\r
+\r
+  Boot option manipulation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+#include "BBSsupport.h"\r
+\r
+/**\r
+  Create a menu entry by given menu type.\r
+\r
+  @param MenuType        The Menu type to be created.\r
+\r
+  @retval NULL           If failed to create the menu.\r
+  @return the new menu entry.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+  UINTN           MenuType\r
+  )\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  UINTN         ContextSize;\r
+\r
+  //\r
+  // Get context size according to menu type\r
+  //\r
+  switch (MenuType) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LOAD_CONTEXT);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_FILE_CONTEXT);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
+    break;\r
+\r
+  default:\r
+    ContextSize = 0;\r
+    break;\r
+  }\r
+\r
+  if (ContextSize == 0) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create new menu entry\r
+  //\r
+  MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
+  if (MenuEntry == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  MenuEntry->VariableContext = AllocateZeroPool (ContextSize);\r
+  if (MenuEntry->VariableContext == NULL) {\r
+    FreePool (MenuEntry);\r
+    return NULL;\r
+  }\r
+\r
+  MenuEntry->Signature        = BM_MENU_ENTRY_SIGNATURE;\r
+  MenuEntry->ContextSelection = MenuType;\r
+  return MenuEntry;\r
+}\r
+\r
+/**\r
+  Free up all resource allocated for a BM_MENU_ENTRY.\r
+\r
+  @param MenuEntry   A pointer to BM_MENU_ENTRY.\r
+\r
+**/\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+  BM_MENU_ENTRY         *MenuEntry\r
+  )\r
+{\r
+  BM_LOAD_CONTEXT           *LoadContext;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  BM_CONSOLE_CONTEXT        *ConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *TerminalContext;\r
+  BM_HANDLE_CONTEXT         *HandleContext;\r
+  BM_LEGACY_DEVICE_CONTEXT  *LegacyDevContext;\r
+\r
+  //\r
+  //  Select by the type in Menu entry for current context type\r
+  //\r
+  switch (MenuEntry->ContextSelection) {\r
+  case BM_LOAD_CONTEXT_SELECT:\r
+    LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
+    FreePool (LoadContext->FilePathList);\r
+    FreePool (LoadContext->LoadOption);\r
+    if (LoadContext->OptionalData != NULL) {\r
+      FreePool (LoadContext->OptionalData);\r
+    }\r
+    FreePool (LoadContext);\r
+    break;\r
+\r
+  case BM_FILE_CONTEXT_SELECT:\r
+    FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+    if (!FileContext->IsRoot) {\r
+      FreePool (FileContext->DevicePath);\r
+    } else {\r
+      if (FileContext->FHandle != NULL) {\r
+        FileContext->FHandle->Close (FileContext->FHandle);\r
+      }\r
+    }\r
+\r
+    if (FileContext->FileName != NULL) {\r
+      FreePool (FileContext->FileName);\r
+    }\r
+    if (FileContext->Info != NULL) {\r
+      FreePool (FileContext->Info);\r
+    }\r
+    FreePool (FileContext);\r
+    break;\r
+\r
+  case BM_CONSOLE_CONTEXT_SELECT:\r
+    ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
+    FreePool (ConsoleContext->DevicePath);\r
+    FreePool (ConsoleContext);\r
+    break;\r
+\r
+  case BM_TERMINAL_CONTEXT_SELECT:\r
+    TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
+    FreePool (TerminalContext->DevicePath);\r
+    FreePool (TerminalContext);\r
+    break;\r
+\r
+  case BM_HANDLE_CONTEXT_SELECT:\r
+    HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
+    FreePool (HandleContext);\r
+    break;\r
+\r
+  case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+    LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
+    FreePool (LegacyDevContext);\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  FreePool (MenuEntry->DisplayString);\r
+  if (MenuEntry->HelpString != NULL) {\r
+    FreePool (MenuEntry->HelpString);\r
+  }\r
+\r
+  FreePool (MenuEntry);\r
+}\r
+\r
+/**\r
+  Get the Menu Entry from the list in Menu Entry List.\r
+\r
+  If MenuNumber is great or equal to the number of Menu\r
+  Entry in the list, then ASSERT.\r
+\r
+  @param MenuOption      The Menu Entry List to read the menu entry.\r
+  @param MenuNumber      The index of Menu Entry.\r
+\r
+  @return The Menu Entry.\r
+\r
+**/\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+  BM_MENU_OPTION      *MenuOption,\r
+  UINTN               MenuNumber\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  UINTN           Index;\r
+  LIST_ENTRY      *List;\r
+\r
+  ASSERT (MenuNumber < MenuOption->MenuNumber);\r
+\r
+  List = MenuOption->Head.ForwardLink;\r
+  for (Index = 0; Index < MenuNumber; Index++) {\r
+    List = List->ForwardLink;\r
+  }\r
+\r
+  NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
+\r
+  return NewMenuEntry;\r
+}\r
+\r
+/**\r
+  This function build the FsOptionMenu list which records all\r
+  available file system in the system. They includes all instances\r
+  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
+  and all type of legacy boot device.\r
+\r
+  @param CallbackData    BMM context data\r
+\r
+  @retval  EFI_SUCCESS             Success find the file system\r
+  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+  IN BMM_CALLBACK_DATA          *CallbackData\r
+  )\r
+{\r
+  UINTN                     NoBlkIoHandles;\r
+  UINTN                     NoSimpleFsHandles;\r
+  UINTN                     NoLoadFileHandles;\r
+  EFI_HANDLE                *BlkIoHandle;\r
+  EFI_HANDLE                *SimpleFsHandle;\r
+  EFI_HANDLE                *LoadFileHandle;\r
+  UINT16                    *VolumeLabel;\r
+  EFI_BLOCK_IO_PROTOCOL     *BlkIo;\r
+  UINTN                     Index;\r
+  EFI_STATUS                Status;\r
+  BM_MENU_ENTRY             *MenuEntry;\r
+  BM_FILE_CONTEXT           *FileContext;\r
+  UINT16                    *TempStr;\r
+  UINTN                     OptionNumber;\r
+  VOID                      *Buffer;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    DeviceType;\r
+  BBS_BBS_DEVICE_PATH       BbsDevicePathNode;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  BOOLEAN                   RemovableMedia;\r
+\r
+\r
+  NoSimpleFsHandles = 0;\r
+  NoLoadFileHandles = 0;\r
+  OptionNumber      = 0;\r
+  InitializeListHead (&FsOptionMenu.Head);\r
+\r
+  //\r
+  // Locate Handles that support BlockIo protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  NULL,\r
+                  &NoBlkIoHandles,\r
+                  &BlkIoHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      BlkIoHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
+      //\r
+      if (BlkIo->Media->RemovableMedia) {\r
+        Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);\r
+        if (NULL == Buffer) {\r
+          FreePool (BlkIoHandle);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        BlkIo->ReadBlocks (\r
+                BlkIo,\r
+                BlkIo->Media->MediaId,\r
+                0,\r
+                BlkIo->Media->BlockSize,\r
+                Buffer\r
+                );\r
+        FreePool (Buffer);\r
+      }\r
+    }\r
+    FreePool (BlkIoHandle);\r
+  }\r
+\r
+  //\r
+  // Locate Handles that support Simple File System protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSimpleFileSystemProtocolGuid,\r
+                  NULL,\r
+                  &NoSimpleFsHandles,\r
+                  &SimpleFsHandle\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Find all the instances of the File System prototocol\r
+    //\r
+    for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      SimpleFsHandle[Index],\r
+                      &gEfiBlockIoProtocolGuid,\r
+                      (VOID **) &BlkIo\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If no block IO exists assume it's NOT a removable media\r
+        //\r
+        RemovableMedia = FALSE;\r
+      } else {\r
+        //\r
+        // If block IO exists check to see if it's remobable media\r
+        //\r
+        RemovableMedia = BlkIo->Media->RemovableMedia;\r
+      }\r
+\r
+      //\r
+      // Allocate pool for this load option\r
+      //\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        FreePool (SimpleFsHandle);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+      FileContext->Handle     = SimpleFsHandle[Index];\r
+      MenuEntry->OptionNumber = Index;\r
+      FileContext->FHandle    = EfiLibOpenRoot (FileContext->Handle);\r
+      if (FileContext->FHandle == NULL) {\r
+        BOpt_DestroyMenuEntry (MenuEntry);\r
+        continue;\r
+      }\r
+\r
+      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+      FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
+      FileContext->FileName = EfiStrDuplicate (L"\\");\r
+      FileContext->DevicePath = FileDevicePath (\r
+                                  FileContext->Handle,\r
+                                  FileContext->FileName\r
+                                  );\r
+      FileContext->IsDir            = TRUE;\r
+      FileContext->IsRoot           = TRUE;\r
+      FileContext->IsRemovableMedia = RemovableMedia;\r
+      FileContext->IsLoadFile       = FALSE;\r
+\r
+      //\r
+      // Get current file system's Volume Label\r
+      //\r
+      if (FileContext->Info == NULL) {\r
+        VolumeLabel = L"NO FILE SYSTEM INFO";\r
+      } else {\r
+        if (FileContext->Info->VolumeLabel == NULL) {\r
+          VolumeLabel = L"NULL VOLUME LABEL";\r
+        } else {\r
+          VolumeLabel = FileContext->Info->VolumeLabel;\r
+          if (*VolumeLabel == 0x0000) {\r
+            VolumeLabel = L"NO VOLUME LABEL";\r
+          }\r
+        }\r
+      }\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"%s, [%s]",\r
+        VolumeLabel,\r
+        TempStr\r
+        );\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoSimpleFsHandles != 0) {\r
+    FreePool (SimpleFsHandle);\r
+  }\r
+  //\r
+  // Searching for handles that support Load File protocol\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  NULL,\r
+                  &NoLoadFileHandles,\r
+                  &LoadFileHandle\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        FreePool (LoadFileHandle);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+      FileContext->IsRemovableMedia = FALSE;\r
+      FileContext->IsLoadFile       = TRUE;\r
+      FileContext->Handle           = LoadFileHandle[Index];\r
+      FileContext->IsRoot           = TRUE;\r
+\r
+      FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
+\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Load File [%s]",\r
+        TempStr\r
+        );\r
+\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  if (NoLoadFileHandles != 0) {\r
+    FreePool (LoadFileHandle);\r
+  }\r
+\r
+  //\r
+  // Add Legacy Boot Option Support Here\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
+      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == MenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FileContext                       = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+      FileContext->IsRemovableMedia     = FALSE;\r
+      FileContext->IsLoadFile           = TRUE;\r
+      FileContext->IsBootLegacy         = TRUE;\r
+      DeviceType                        = (UINT16) Index;\r
+      BbsDevicePathNode.Header.Type     = BBS_DEVICE_PATH;\r
+      BbsDevicePathNode.Header.SubType  = BBS_BBS_DP;\r
+      SetDevicePathNodeLength (\r
+        &BbsDevicePathNode.Header,\r
+        sizeof (BBS_BBS_DEVICE_PATH)\r
+        );\r
+      BbsDevicePathNode.DeviceType  = DeviceType;\r
+      BbsDevicePathNode.StatusFlag  = 0;\r
+      BbsDevicePathNode.String[0]   = 0;\r
+      DevicePath = AppendDevicePathNode (\r
+                    EndDevicePath,\r
+                    (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
+                    );\r
+\r
+      FileContext->DevicePath   = DevicePath;\r
+      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);\r
+\r
+      TempStr                   = MenuEntry->HelpString;\r
+      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);\r
+      ASSERT (MenuEntry->DisplayString != NULL);\r
+      UnicodeSPrint (\r
+        MenuEntry->DisplayString,\r
+        MAX_CHAR,\r
+        L"Boot Legacy [%s]",\r
+        TempStr\r
+        );\r
+      MenuEntry->OptionNumber = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+    }\r
+  }\r
+  //\r
+  // Remember how many file system options are here\r
+  //\r
+  FsOptionMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Free resources allocated in Allocate Rountine.\r
+\r
+  @param FreeMenu        Menu to be freed\r
+**/\r
+VOID\r
+BOpt_FreeMenu (\r
+  BM_MENU_OPTION        *FreeMenu\r
+  )\r
+{\r
+  BM_MENU_ENTRY *MenuEntry;\r
+  while (!IsListEmpty (&FreeMenu->Head)) {\r
+    MenuEntry = CR (\r
+                  FreeMenu->Head.ForwardLink,\r
+                  BM_MENU_ENTRY,\r
+                  Link,\r
+                  BM_MENU_ENTRY_SIGNATURE\r
+                  );\r
+    RemoveEntryList (&MenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (MenuEntry);\r
+  }\r
+}\r
+\r
+/**\r
+  Find files under current directory\r
+  All files and sub-directories in current directory\r
+  will be stored in DirectoryMenu for future use.\r
+\r
+  @param CallbackData  The BMM context data.\r
+  @param MenuEntry     The Menu Entry.\r
+\r
+  @retval EFI_SUCCESS         Get files from current dir successfully.\r
+  @return Other value if can't get files from current dir.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+  IN BMM_CALLBACK_DATA          *CallbackData,\r
+  IN BM_MENU_ENTRY              *MenuEntry\r
+  )\r
+{\r
+  EFI_FILE_HANDLE NewDir;\r
+  EFI_FILE_HANDLE Dir;\r
+  EFI_FILE_INFO   *DirInfo;\r
+  UINTN           BufferSize;\r
+  UINTN           DirBufferSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *FileContext;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  UINTN           Pass;\r
+  EFI_STATUS      Status;\r
+  UINTN           OptionNumber;\r
+\r
+  FileContext   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+  Dir           = FileContext->FHandle;\r
+  OptionNumber  = 0;\r
+  //\r
+  // Open current directory to get files from it\r
+  //\r
+  Status = Dir->Open (\r
+                  Dir,\r
+                  &NewDir,\r
+                  FileContext->FileName,\r
+                  EFI_FILE_READ_ONLY,\r
+                  0\r
+                  );\r
+  if (!FileContext->IsRoot) {\r
+    Dir->Close (Dir);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DirInfo = EfiLibFileInfo (NewDir);\r
+  if (DirInfo == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FileContext->DevicePath = FileDevicePath (\r
+                              FileContext->Handle,\r
+                              FileContext->FileName\r
+                              );\r
+\r
+  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+  DirInfo       = AllocateZeroPool (DirBufferSize);\r
+  if (DirInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Get all files in current directory\r
+  // Pass 1 to get Directories\r
+  // Pass 2 to get files that are EFI images\r
+  //\r
+  for (Pass = 1; Pass <= 2; Pass++) {\r
+    NewDir->SetPosition (NewDir, 0);\r
+    for (;;) {\r
+      BufferSize  = DirBufferSize;\r
+      Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+      if (EFI_ERROR (Status) || BufferSize == 0) {\r
+        break;\r
+      }\r
+\r
+      if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||\r
+          (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)\r
+          ) {\r
+        //\r
+        // Pass 1 is for Directories\r
+        // Pass 2 is for file names\r
+        //\r
+        continue;\r
+      }\r
+\r
+      if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+        //\r
+        // Slip file unless it is a directory entry or a .EFI file\r
+        //\r
+        continue;\r
+      }\r
+\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+      if (NULL == NewMenuEntry) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewFileContext          = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+      NewFileContext->Handle  = FileContext->Handle;\r
+      NewFileContext->FileName = BOpt_AppendFileName (\r
+                                  FileContext->FileName,\r
+                                  DirInfo->FileName\r
+                                  );\r
+      NewFileContext->FHandle = NewDir;\r
+      NewFileContext->DevicePath = FileDevicePath (\r
+                                    NewFileContext->Handle,\r
+                                    NewFileContext->FileName\r
+                                    );\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        FileOptionStrDepository\r
+                                        );\r
+\r
+      NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+\r
+      if (NewFileContext->IsDir) {\r
+        BufferSize                  = StrLen (DirInfo->FileName) * 2 + 6;\r
+        NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
+\r
+        UnicodeSPrint (\r
+          NewMenuEntry->DisplayString,\r
+          BufferSize,\r
+          L"<%s>",\r
+          DirInfo->FileName\r
+          );\r
+\r
+      } else {\r
+        NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
+      }\r
+\r
+      NewFileContext->IsRoot            = FALSE;\r
+      NewFileContext->IsLoadFile        = FALSE;\r
+      NewFileContext->IsRemovableMedia  = FALSE;\r
+\r
+      NewMenuEntry->OptionNumber        = OptionNumber;\r
+      OptionNumber++;\r
+      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  DirectoryMenu.MenuNumber = OptionNumber;\r
+  FreePool (DirInfo);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+  @retval EFI_SUCCESS The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+  VOID\r
+  )\r
+{\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LEGACY_DEVICE_CONTEXT  *NewLegacyDevContext;\r
+  EFI_STATUS                Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
+  UINT16                    HddCount;\r
+  HDD_INFO                  *HddInfo;\r
+  UINT16                    BbsCount;\r
+  BBS_TABLE                 *BbsTable;\r
+  UINTN                     Index;\r
+  CHAR16                    DescString[100];\r
+  UINTN                     FDNum;\r
+  UINTN                     HDNum;\r
+  UINTN                     CDNum;\r
+  UINTN                     NETNum;\r
+  UINTN                     BEVNum;\r
+\r
+  NewMenuEntry  = NULL;\r
+  HddInfo       = NULL;\r
+  BbsTable      = NULL;\r
+  BbsCount      = 0;\r
+\r
+  //\r
+  // Initialize Bbs Table Context from BBS info data\r
+  //\r
+  InitializeListHead (&LegacyFDMenu.Head);\r
+  InitializeListHead (&LegacyHDMenu.Head);\r
+  InitializeListHead (&LegacyCDMenu.Head);\r
+  InitializeListHead (&LegacyNETMenu.Head);\r
+  InitializeListHead (&LegacyBEVMenu.Head);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiLegacyBiosProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &LegacyBios\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = LegacyBios->GetBbsInfo (\r
+                          LegacyBios,\r
+                          &HddCount,\r
+                          &HddInfo,\r
+                          &BbsCount,\r
+                          &BbsTable\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  FDNum   = 0;\r
+  HDNum   = 0;\r
+  CDNum   = 0;\r
+  NETNum  = 0;\r
+  BEVNum  = 0;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
+        (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      break;\r
+    }\r
+\r
+    NewLegacyDevContext           = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLegacyDevContext->BbsTable = &BbsTable[Index];\r
+    NewLegacyDevContext->Index    = Index;\r
+    NewLegacyDevContext->BbsCount = BbsCount;\r
+    BdsBuildLegacyDevNameString (\r
+      &BbsTable[Index],\r
+      Index,\r
+      sizeof (DescString),\r
+      DescString\r
+      );\r
+    NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString));\r
+    if (NULL == NewLegacyDevContext->Description) {\r
+      break;\r
+    }\r
+\r
+    CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));\r
+    NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
+    NewMenuEntry->HelpString    = NULL;\r
+\r
+    switch (BbsTable[Index].DeviceType) {\r
+    case BBS_FLOPPY:\r
+      InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
+      FDNum++;\r
+      break;\r
+\r
+    case BBS_HARDDISK:\r
+      InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
+      HDNum++;\r
+      break;\r
+\r
+    case BBS_CDROM:\r
+      InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
+      CDNum++;\r
+      break;\r
+\r
+    case BBS_EMBED_NETWORK:\r
+      InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
+      NETNum++;\r
+      break;\r
+\r
+    case BBS_BEV_DEVICE:\r
+      InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
+      BEVNum++;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != BbsCount) {\r
+    BOpt_FreeLegacyOptions ();\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  LegacyFDMenu.MenuNumber   = FDNum;\r
+  LegacyHDMenu.MenuNumber   = HDNum;\r
+  LegacyCDMenu.MenuNumber   = CDNum;\r
+  LegacyNETMenu.MenuNumber  = NETNum;\r
+  LegacyBEVMenu.MenuNumber  = BEVNum;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Free out resouce allocated from Legacy Boot Options.\r
+\r
+**/\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&LegacyFDMenu);\r
+  BOpt_FreeMenu (&LegacyHDMenu);\r
+  BOpt_FreeMenu (&LegacyCDMenu);\r
+  BOpt_FreeMenu (&LegacyNETMenu);\r
+  BOpt_FreeMenu (&LegacyBEVMenu);\r
+}\r
+\r
+/**\r
+\r
+  Build the BootOptionMenu according to BootOrder Variable.\r
+  This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
+\r
+  @param CallbackData The BMM context data.\r
+\r
+  @return EFI_NOT_FOUND Fail to find "BootOrder" variable.\r
+  @return EFI_SUCESS    Success build boot option menu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+{\r
+  UINTN                     Index;\r
+  UINT16                    BootString[10];\r
+  UINT8                     *LoadOptionFromVar;\r
+  UINT8                     *LoadOption;\r
+  UINTN                     BootOptionSize;\r
+  BOOLEAN                   BootNextFlag;\r
+  UINT16                    *BootOrderList;\r
+  UINTN                     BootOrderListSize;\r
+  UINT16                    *BootNext;\r
+  UINTN                     BootNextSize;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_LOAD_CONTEXT           *NewLoadContext;\r
+  UINT8                     *LoadOptionPtr;\r
+  UINTN                     StringSize;\r
+  UINTN                     OptionalDataSize;\r
+  UINT8                     *LoadOptionEnd;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     MenuCount;\r
+  UINT8                     *Ptr;\r
+\r
+  MenuCount         = 0;\r
+  BootOrderListSize = 0;\r
+  BootNextSize      = 0;\r
+  BootOrderList     = NULL;\r
+  BootNext          = NULL;\r
+  LoadOptionFromVar = NULL;\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  InitializeListHead (&BootOptionMenu.Head);\r
+\r
+  //\r
+  // Get the BootOrder from the Var\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+  if (BootOrderList == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  //\r
+  // Get the BootNext from the Var\r
+  //\r
+  BootNext = BdsLibGetVariableAndSize (\r
+              L"BootNext",\r
+              &gEfiGlobalVariableGuid,\r
+              &BootNextSize\r
+              );\r
+\r
+  if (BootNext != NULL) {\r
+    if (BootNextSize != sizeof (UINT16)) {\r
+      FreePool (BootNext);\r
+      BootNext = NULL;\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          BootString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &BootOptionSize\r
+                          );\r
+    if (LoadOptionFromVar == NULL) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = AllocateZeroPool (BootOptionSize);\r
+    if (LoadOption == NULL) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
+    FreePool (LoadOptionFromVar);\r
+\r
+    if (BootNext != NULL) {\r
+      BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
+    } else {\r
+      BootNextFlag = FALSE;\r
+    }\r
+\r
+    if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
+      FreePool (LoadOption);\r
+      continue;\r
+    }\r
+    //\r
+    // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
+    // the buffer allocated already should be freed before returning.\r
+    //\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + BootOptionSize;\r
+\r
+    NewMenuEntry->OptionNumber          = BootOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsBootNext          = BootNextFlag;\r
+\r
+    //\r
+    // Is a Legacy Device?\r
+    //\r
+    Ptr = (UINT8 *) LoadOption;\r
+\r
+    //\r
+    // Attribute = *(UINT32 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT32);\r
+\r
+    //\r
+    // FilePathSize = *(UINT16 *)Ptr;\r
+    //\r
+    Ptr += sizeof (UINT16);\r
+\r
+    //\r
+    // Description = (CHAR16 *)Ptr;\r
+    //\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+      NewLoadContext->IsLegacy = TRUE;\r
+    } else {\r
+      NewLoadContext->IsLegacy = FALSE;\r
+    }\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = BootOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        BootOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = BootOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+    MenuCount++;\r
+  }\r
+\r
+  if (BootNext != NULL) {\r
+    FreePool (BootNext);\r
+  }\r
+  if (BootOrderList != NULL) {\r
+    FreePool (BootOrderList);\r
+  }\r
+  BootOptionMenu.MenuNumber = MenuCount;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Append file name to existing file name.\r
+\r
+  @param Str1  The existing file name\r
+  @param Str2  The file name to be appended\r
+\r
+  @return Allocate a new string to hold the appended result.\r
+          Caller is responsible to free the returned string.\r
+\r
+**/\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+  IN  CHAR16  *Str1,\r
+  IN  CHAR16  *Str2\r
+  )\r
+{\r
+  UINTN   Size1;\r
+  UINTN   Size2;\r
+  CHAR16  *Str;\r
+  CHAR16  *TmpStr;\r
+  CHAR16  *Ptr;\r
+  CHAR16  *LastSlash;\r
+\r
+  Size1 = StrSize (Str1);\r
+  Size2 = StrSize (Str2);\r
+  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+  ASSERT (Str != NULL);\r
+\r
+  TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); \r
+  ASSERT (TmpStr != NULL);\r
+\r
+  StrCat (Str, Str1);\r
+  if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+    StrCat (Str, L"\\");\r
+  }\r
+\r
+  StrCat (Str, Str2);\r
+\r
+  Ptr       = Str;\r
+  LastSlash = Str;\r
+  while (*Ptr != 0) {\r
+    if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
+      //\r
+      // Convert "\Name\..\" to "\"\r
+      // DO NOT convert the .. if it is at the end of the string. This will\r
+      // break the .. behavior in changing directories.\r
+      //\r
+\r
+      //\r
+      // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+      // that overlap.\r
+      //\r
+      StrCpy (TmpStr, Ptr + 3);\r
+      StrCpy (LastSlash, TmpStr);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+      //\r
+      // Convert a "\.\" to a "\"\r
+      //\r
+\r
+      //\r
+      // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings \r
+      // that overlap.\r
+      //\r
+      StrCpy (TmpStr, Ptr + 2);\r
+      StrCpy (Ptr, TmpStr);\r
+      Ptr = LastSlash;\r
+    } else if (*Ptr == '\\') {\r
+      LastSlash = Ptr;\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  FreePool (TmpStr);\r
+  \r
+  return Str;\r
+}\r
+\r
+/**\r
+\r
+  Check whether current FileName point to a valid\r
+  Efi Image File.\r
+\r
+  @param FileName  File need to be checked.\r
+\r
+  @retval TRUE  Is Efi Image\r
+  @retval FALSE Not a valid Efi Image\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+  IN UINT16  *FileName\r
+  )\r
+{\r
+  //\r
+  // Search for ".efi" extension\r
+  //\r
+  while (*FileName != L'\0') {\r
+    if (FileName[0] == '.') {\r
+      if (FileName[1] == 'e' || FileName[1] == 'E') {\r
+        if (FileName[2] == 'f' || FileName[2] == 'F') {\r
+          if (FileName[3] == 'i' || FileName[3] == 'I') {\r
+            return TRUE;\r
+          } else if (FileName[3] == 0x0000) {\r
+            return FALSE;\r
+          }\r
+        } else if (FileName[2] == 0x0000) {\r
+          return FALSE;\r
+        }\r
+      } else if (FileName[1] == 0x0000) {\r
+        return FALSE;\r
+      }\r
+    }\r
+\r
+    FileName += 1;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+\r
+  Check whether current FileName point to a valid Efi Application\r
+\r
+  @param Dir       Pointer to current Directory\r
+  @param FileName  Pointer to current File name.\r
+\r
+  @retval TRUE      Is a valid Efi Application\r
+  @retval FALSE     not a valid Efi Application\r
+\r
+**/\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+  IN EFI_FILE_HANDLE Dir,\r
+  IN UINT16          *FileName\r
+  )\r
+{\r
+  UINTN                       BufferSize;\r
+  EFI_IMAGE_DOS_HEADER        DosHdr;\r
+  UINT16                      Subsystem;\r
+  EFI_FILE_HANDLE             File;\r
+  EFI_STATUS                  Status;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;\r
+\r
+  Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+  File->Read (File, &BufferSize, &DosHdr);\r
+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+\r
+  File->SetPosition (File, DosHdr.e_lfanew);\r
+  BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
+  File->Read (File, &BufferSize, &PeHdr);\r
+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Determine PE type and read subsytem\r
+  //\r
+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    Subsystem = PeHdr.Pe32.OptionalHeader.Subsystem;\r
+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    Subsystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+    File->Close (File);\r
+    return TRUE;\r
+  } else {\r
+    File->Close (File);\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  Find drivers that will be added as Driver#### variables from handles\r
+  in current system environment\r
+  All valid handles in the system except those consume SimpleFs, LoadFile\r
+  are stored in DriverMenu for future use.\r
+\r
+  @retval EFI_SUCCESS The function complets successfully.\r
+  @return Other value if failed to build the DriverMenu.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                           NoDevicePathHandles;\r
+  EFI_HANDLE                      *DevicePathHandle;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  BM_MENU_ENTRY                   *NewMenuEntry;\r
+  BM_HANDLE_CONTEXT               *NewHandleContext;\r
+  EFI_HANDLE                      CurHandle;\r
+  UINTN                           OptionNumber;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
+  EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
+\r
+  SimpleFs  = NULL;\r
+  LoadFile  = NULL;\r
+\r
+  InitializeListHead (&DriverMenu.Head);\r
+\r
+  //\r
+  // At first, get all handles that support Device Path\r
+  // protocol which is the basic requirement for\r
+  // Driver####\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  NULL,\r
+                  &NoDevicePathHandles,\r
+                  &DevicePathHandle\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OptionNumber = 0;\r
+  for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
+    CurHandle = DevicePathHandle[Index];\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiSimpleFileSystemProtocolGuid,\r
+                    (VOID **) &SimpleFs\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    CurHandle,\r
+                    &gEfiLoadFileProtocolGuid,\r
+                    (VOID **) &LoadFile\r
+                    );\r
+    if (Status == EFI_SUCCESS) {\r
+      continue;\r
+    }\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      FreePool (DevicePathHandle);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewHandleContext              = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewHandleContext->Handle      = CurHandle;\r
+    NewHandleContext->DevicePath  = DevicePathFromHandle (CurHandle);\r
+    NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
+    NewMenuEntry->HelpString    = NULL;\r
+    NewMenuEntry->OptionNumber  = OptionNumber;\r
+    OptionNumber++;\r
+    InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+\r
+  if (DevicePathHandle != NULL) {\r
+    FreePool (DevicePathHandle);\r
+  }\r
+\r
+  DriverMenu.MenuNumber = OptionNumber;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Get the Option Number that has not been allocated for use.\r
+\r
+  @return The available Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+  VOID\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINTN         BootOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+  CHAR16        StrTemp[100];\r
+  UINT16        *OptionBuffer;\r
+  UINTN         OptionSize;\r
+\r
+  BootOrderListSize = 0;\r
+  BootOrderList     = NULL;\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+  if (BootOrderList != NULL) {\r
+    //\r
+    // already have Boot####\r
+    //\r
+    // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);\r
+        DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));\r
+        OptionBuffer = BdsLibGetVariableAndSize (\r
+                          StrTemp,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &OptionSize\r
+                          );\r
+        if (NULL == OptionBuffer) {\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Boot####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+/**\r
+\r
+  Get the Option Number that is not in use.\r
+\r
+  @return The unused Option Number.\r
+\r
+**/\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+  VOID\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINTN         DriverOrderListSize;\r
+  UINT16        Number;\r
+  UINTN         Index;\r
+  UINTN         Index2;\r
+  BOOLEAN       Found;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  if (DriverOrderList != NULL) {\r
+    //\r
+    // already have Driver####\r
+    //\r
+    // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+      Found = TRUE;\r
+      for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {\r
+        NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);\r
+        if (Index == NewMenuEntry->OptionNumber) {\r
+          Found = FALSE;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Found) {\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // end for Index\r
+    //\r
+    Number = (UINT16) Index;\r
+  } else {\r
+    //\r
+    // No Driver####\r
+    //\r
+    Number = 0;\r
+  }\r
+\r
+  return Number;\r
+}\r
+\r
+/**\r
+\r
+  Build up all DriverOptionMenu\r
+\r
+  @param CallbackData The BMM context data.\r
+\r
+  @retval EFI_SUCESS           The functin completes successfully.\r
+  @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
+  @retval EFI_NOT_FOUND        Fail to get "DriverOrder" variable.\r
+\r
+**/\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData\r
+  )\r
+{\r
+  UINTN           Index;\r
+  UINT16          DriverString[12];\r
+  UINT8           *LoadOptionFromVar;\r
+  UINT8           *LoadOption;\r
+  UINTN           DriverOptionSize;\r
+\r
+  UINT16          *DriverOrderList;\r
+  UINTN           DriverOrderListSize;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT8           *LoadOptionPtr;\r
+  UINTN           StringSize;\r
+  UINTN           OptionalDataSize;\r
+  UINT8           *LoadOptionEnd;\r
+\r
+  DriverOrderListSize = 0;\r
+  DriverOrderList     = NULL;\r
+  DriverOptionSize    = 0;\r
+  LoadOptionFromVar   = NULL;\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  InitializeListHead (&DriverOptionMenu.Head);\r
+  //\r
+  // Get the DriverOrder from the Var\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  if (DriverOrderList == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      DriverOrderList[Index]\r
+      );\r
+    //\r
+    //  Get all loadoptions from the VAR\r
+    //\r
+    LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+                          DriverString,\r
+                          &gEfiGlobalVariableGuid,\r
+                          &DriverOptionSize\r
+                          );\r
+    if (LoadOptionFromVar == NULL) {\r
+      continue;\r
+    }\r
+\r
+    LoadOption = AllocateZeroPool (DriverOptionSize);\r
+    if (LoadOption == NULL) {\r
+      continue;\r
+    }\r
+\r
+    CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
+    FreePool (LoadOptionFromVar);\r
+\r
+    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    LoadOptionPtr                       = LoadOption;\r
+    LoadOptionEnd                       = LoadOption + DriverOptionSize;\r
+    NewMenuEntry->OptionNumber          = DriverOrderList[Index];\r
+    NewLoadContext->LoadOptionModified  = FALSE;\r
+    NewLoadContext->Deleted             = FALSE;\r
+    NewLoadContext->IsLegacy            = FALSE;\r
+\r
+    //\r
+    // LoadOption is a pointer type of UINT8\r
+    // for easy use with following LOAD_OPTION\r
+    // embedded in this struct\r
+    //\r
+    NewLoadContext->LoadOption      = LoadOption;\r
+    NewLoadContext->LoadOptionSize  = DriverOptionSize;\r
+\r
+    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;\r
+    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+    LoadOptionPtr += sizeof (UINT32);\r
+\r
+    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+    LoadOptionPtr += sizeof (UINT16);\r
+\r
+    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);\r
+    NewLoadContext->Description = AllocateZeroPool (StringSize);\r
+    ASSERT (NewLoadContext->Description != NULL);\r
+    CopyMem (\r
+      NewLoadContext->Description,\r
+      (UINT16 *) LoadOptionPtr,\r
+      StringSize\r
+      );\r
+    NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+    LoadOptionPtr += StringSize;\r
+\r
+    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
+    ASSERT (NewLoadContext->FilePathList != NULL);\r
+    CopyMem (\r
+      NewLoadContext->FilePathList,\r
+      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+      NewLoadContext->FilePathListLength\r
+      );\r
+\r
+    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                        CallbackData,\r
+                                        DriverOptionStrDepository\r
+                                        );\r
+    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionHelpStrDepository\r
+                                      );\r
+    LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+    if (LoadOptionPtr < LoadOptionEnd) {\r
+      OptionalDataSize = DriverOptionSize -\r
+        sizeof (UINT32) -\r
+        sizeof (UINT16) -\r
+        StringSize -\r
+        NewLoadContext->FilePathListLength;\r
+\r
+      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
+      ASSERT (NewLoadContext->OptionalData != NULL);\r
+      CopyMem (\r
+        NewLoadContext->OptionalData,\r
+        LoadOptionPtr,\r
+        OptionalDataSize\r
+        );\r
+\r
+      NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+    }\r
+\r
+    InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+\r
+  }\r
+\r
+  if (DriverOrderList != NULL) {\r
+    FreePool (DriverOrderList);\r
+  }\r
+  DriverOptionMenu.MenuNumber = Index;\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
new file mode 100644 (file)
index 0000000..da0a838
--- /dev/null
@@ -0,0 +1,942 @@
+/** @file\r
+  handles console redirection from boot manager\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+/**\r
+  Update Com Ports attributes from DevicePath\r
+\r
+  @param DevicePath      DevicePath that contains Com ports\r
+\r
+  @retval EFI_SUCCESS   The update is successful.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  );\r
+\r
+/**\r
+  Update the multi-instance device path of Terminal Device based on\r
+  the global TerminalMenu. If ChangeTernimal is TRUE, the terminal \r
+  device path in the Terminal Device in TerminalMenu is also updated.\r
+\r
+  @param DevicePath      The multi-instance device path.\r
+  @param ChangeTerminal  TRUE, then device path in the Terminal Device \r
+                         in TerminalMenu is also updated; FALSE, no update.\r
+\r
+  @return EFI_SUCCESS    The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+  IN OUT    EFI_DEVICE_PATH_PROTOCOL  *DevicePath,\r
+  IN        BOOLEAN                   ChangeTerminal\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node1;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      Uart = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      //\r
+      // Change the device path in the ComPort\r
+      //\r
+      if (ChangeTerminal) {\r
+        Node1 = NewTerminalContext->DevicePath;\r
+        Node1 = NextDevicePathNode (Node1);\r
+        while (!IsDevicePathEnd (Node1)) {\r
+          if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+            Uart1 = (UART_DEVICE_PATH *) Node1;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+            break;\r
+          }\r
+          //\r
+          // end if\r
+          //\r
+          Node1 = NextDevicePathNode (Node1);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+        break;\r
+      }\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  Update the device path that describing a terminal device\r
+  based on the new BaudRate, Data Bits, parity and Stop Bits\r
+  set.\r
+\r
+  @param DevicePath terminal device's path\r
+\r
+**/\r
+VOID\r
+ChangeVariableDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UINTN                     Com;\r
+  UINT32                    Match;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+\r
+  Match = EISA_PNP_ID (0x0501);\r
+  Node  = DevicePath;\r
+  Node  = NextDevicePathNode (Node);\r
+  Com   = 0;\r
+  while (!IsDevicePathEnd (Node)) {\r
+    if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+      Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+      if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+        CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+      }\r
+    }\r
+\r
+    if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (\r
+                      &TerminalMenu,\r
+                      Com\r
+                      );\r
+      ASSERT (NewMenuEntry != NULL);\r
+      NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      Uart                = (UART_DEVICE_PATH *) Node;\r
+      CopyMem (\r
+        &Uart->BaudRate,\r
+        &NewTerminalContext->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->DataBits,\r
+        &NewTerminalContext->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->Parity,\r
+        &NewTerminalContext->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &Uart->StopBits,\r
+        &NewTerminalContext->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+    }\r
+\r
+    Node = NextDevicePathNode (Node);\r
+  }\r
+}\r
+\r
+/**\r
+  Retrieve ACPI UID of UART from device path\r
+\r
+  @param Handle          The handle for the UART device.\r
+  @param AcpiUid         The ACPI UID on output.\r
+\r
+  @retval  TRUE   Find valid UID from device path\r
+  @retval  FALSE  Can't find\r
+\r
+**/\r
+BOOLEAN\r
+RetrieveUartUid (\r
+  IN EFI_HANDLE   Handle,\r
+  IN OUT UINT32   *AcpiUid\r
+  )\r
+{\r
+  UINT32                    Match;\r
+  UINT8                     *Ptr;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  gBS->HandleProtocol (\r
+        Handle,\r
+        &gEfiDevicePathProtocolGuid,\r
+        (VOID **) &DevicePath\r
+        );\r
+  Ptr = (UINT8 *) DevicePath;\r
+\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    if (AcpiUid != NULL) {\r
+      *AcpiUid = Acpi->UID;\r
+    }\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Sort Uart handles array with Acpi->UID from low to high.\r
+\r
+  @param Handles         EFI_SERIAL_IO_PROTOCOL handle buffer\r
+  @param NoHandles       EFI_SERIAL_IO_PROTOCOL handle count\r
+**/\r
+VOID\r
+SortedUartHandle (\r
+  IN  EFI_HANDLE *Handles,\r
+  IN  UINTN      NoHandles\r
+  )\r
+{\r
+  UINTN       Index1;\r
+  UINTN       Index2;\r
+  UINTN       Position;\r
+  UINT32      AcpiUid1;\r
+  UINT32      AcpiUid2;\r
+  UINT32      TempAcpiUid;\r
+  EFI_HANDLE  TempHandle;\r
+\r
+  for (Index1 = 0; Index1 < NoHandles-1; Index1++) {\r
+    if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {\r
+      continue;\r
+    }\r
+    TempHandle  = Handles[Index1];\r
+    Position    = Index1;\r
+    TempAcpiUid = AcpiUid1;\r
+\r
+    for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {\r
+      if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {\r
+        continue;\r
+      }\r
+      if (AcpiUid2 < TempAcpiUid) {\r
+        TempAcpiUid = AcpiUid2;\r
+        TempHandle  = Handles[Index2];\r
+        Position    = Index2;\r
+      }\r
+    }\r
+    Handles[Position] = Handles[Index1];\r
+    Handles[Index1]   = TempHandle;\r
+  }\r
+}\r
+\r
+/**\r
+  Test whether DevicePath is a valid Terminal\r
+\r
+\r
+  @param DevicePath      DevicePath to be checked\r
+  @param Termi           If DevicePath is valid Terminal, terminal type is returned.\r
+  @param Com             If DevicePath is valid Terminal, Com Port type is returned.\r
+\r
+  @retval  TRUE         If DevicePath point to a Terminal.\r
+  @retval  FALSE        If DevicePath does not point to a Terminal.\r
+\r
+**/\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  );\r
+\r
+/**\r
+  Build a list containing all serial devices.\r
+\r
+\r
+  @retval EFI_SUCCESS The function complete successfully.\r
+  @retval EFI_UNSUPPORTED No serial ports present.\r
+\r
+**/\r
+EFI_STATUS\r
+LocateSerialIo (\r
+  VOID\r
+  )\r
+{\r
+  UINT8                     *Ptr;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     NoHandles;\r
+  EFI_HANDLE                *Handles;\r
+  EFI_STATUS                Status;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINT32                    Match;\r
+  EFI_SERIAL_IO_PROTOCOL    *SerialIo;\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  //\r
+  // Get all handles that have SerialIo protocol installed\r
+  //\r
+  InitializeListHead (&TerminalMenu.Head);\r
+  TerminalMenu.MenuNumber = 0;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiSerialIoProtocolGuid,\r
+                  NULL,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // No serial ports present\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Sort Uart handles array with Acpi->UID from low to high\r
+  // then Terminal menu can be built from low Acpi->UID to high Acpi->UID\r
+  //\r
+  SortedUartHandle (Handles, NoHandles);\r
+\r
+  for (Index = 0; Index < NoHandles; Index++) {\r
+    //\r
+    // Check to see whether the handle has DevicePath Protocol installed\r
+    //\r
+    gBS->HandleProtocol (\r
+          Handles[Index],\r
+          &gEfiDevicePathProtocolGuid,\r
+          (VOID **) &DevicePath\r
+          );\r
+    Ptr = (UINT8 *) DevicePath;\r
+    while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+      Ptr++;\r
+    }\r
+\r
+    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+    Match = EISA_PNP_ID (0x0501);\r
+\r
+    if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+      NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+      if (NewMenuEntry == NULL) {\r
+        FreePool (Handles);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+      CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+      NewTerminalContext->DevicePath = DuplicateDevicePath (DevicePath);\r
+      //\r
+      // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+      // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+      // datahub which is not completed, so a searching for end of device path will enter a\r
+      // dead-loop.\r
+      //\r
+      NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+      if (NULL == NewMenuEntry->DisplayString) {\r
+        NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+      }\r
+\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      gBS->HandleProtocol (\r
+            Handles[Index],\r
+            &gEfiSerialIoProtocolGuid,\r
+            (VOID **) &SerialIo\r
+            );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->BaudRate,\r
+        &SerialIo->Mode->BaudRate,\r
+        sizeof (UINT64)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->DataBits,\r
+        &SerialIo->Mode->DataBits,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->Parity,\r
+        &SerialIo->Mode->Parity,\r
+        sizeof (UINT8)\r
+        );\r
+\r
+      CopyMem (\r
+        &NewTerminalContext->StopBits,\r
+        &SerialIo->Mode->StopBits,\r
+        sizeof (UINT8)\r
+        );\r
+      InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+      TerminalMenu.MenuNumber++;\r
+    }\r
+  }\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  //\r
+  // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+  //\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath != NULL) {\r
+    UpdateComAttributeFromVariable (OutDevicePath);\r
+  }\r
+\r
+  if (InpDevicePath != NULL) {\r
+    UpdateComAttributeFromVariable (InpDevicePath);\r
+  }\r
+\r
+  if (ErrDevicePath != NULL) {\r
+    UpdateComAttributeFromVariable (ErrDevicePath);\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    NewTerminalContext->TerminalType  = 0;\r
+    NewTerminalContext->IsConIn       = FALSE;\r
+    NewTerminalContext->IsConOut      = FALSE;\r
+    NewTerminalContext->IsStdErr      = FALSE;\r
+\r
+    Vendor.Header.Type                = MESSAGING_DEVICE_PATH;\r
+    Vendor.Header.SubType             = MSG_VENDOR_DP;\r
+\r
+    for (Index2 = 0; Index2 < 4; Index2++) {\r
+      CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID));\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      NewDevicePath = AppendDevicePathNode (\r
+                        NewTerminalContext->DevicePath,\r
+                        (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                        );\r
+      if (NewMenuEntry->HelpString != NULL) {\r
+        FreePool (NewMenuEntry->HelpString);\r
+      }\r
+      //\r
+      // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+      // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+      //\r
+      NewMenuEntry->HelpString = NULL;\r
+\r
+      if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConOut      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsConIn       = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+\r
+      if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+        NewTerminalContext->IsStdErr      = TRUE;\r
+        NewTerminalContext->TerminalType  = (UINT8) Index2;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update Com Ports attributes from DevicePath\r
+\r
+  @param DevicePath      DevicePath that contains Com ports\r
+\r
+  @retval EFI_SUCCESS   The update is successful.\r
+  @retval EFI_NOT_FOUND Can not find specific menu entry\r
+**/\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL  *SerialNode;\r
+  ACPI_HID_DEVICE_PATH      *Acpi;\r
+  UART_DEVICE_PATH          *Uart;\r
+  UART_DEVICE_PATH          *Uart1;\r
+  UINT32                    Match;\r
+  UINTN                     TerminalNumber;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  UINTN                     Index;\r
+\r
+  Match           = EISA_PNP_ID (0x0501);\r
+  Node            = DevicePath;\r
+  Node            = NextDevicePathNode (Node);\r
+  TerminalNumber  = 0;\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    while (!IsDevicePathEnd (Node)) {\r
+      if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+        Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+        if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+          CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+        }\r
+      }\r
+\r
+      if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+        Uart          = (UART_DEVICE_PATH *) Node;\r
+        NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+        if (NULL == NewMenuEntry) {\r
+          return EFI_NOT_FOUND;\r
+        }\r
+\r
+        NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+        CopyMem (\r
+          &NewTerminalContext->BaudRate,\r
+          &Uart->BaudRate,\r
+          sizeof (UINT64)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->DataBits,\r
+          &Uart->DataBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->Parity,\r
+          &Uart->Parity,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        CopyMem (\r
+          &NewTerminalContext->StopBits,\r
+          &Uart->StopBits,\r
+          sizeof (UINT8)\r
+          );\r
+\r
+        SerialNode  = NewTerminalContext->DevicePath;\r
+        SerialNode  = NextDevicePathNode (SerialNode);\r
+        while (!IsDevicePathEnd (SerialNode)) {\r
+          if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+            //\r
+            // Update following device paths according to\r
+            // previous acquired uart attributes\r
+            //\r
+            Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+            CopyMem (\r
+              &Uart1->BaudRate,\r
+              &NewTerminalContext->BaudRate,\r
+              sizeof (UINT64)\r
+              );\r
+\r
+            CopyMem (\r
+              &Uart1->DataBits,\r
+              &NewTerminalContext->DataBits,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->Parity,\r
+              &NewTerminalContext->Parity,\r
+              sizeof (UINT8)\r
+              );\r
+            CopyMem (\r
+              &Uart1->StopBits,\r
+              &NewTerminalContext->StopBits,\r
+              sizeof (UINT8)\r
+              );\r
+\r
+            break;\r
+          }\r
+\r
+          SerialNode = NextDevicePathNode (SerialNode);\r
+        }\r
+        //\r
+        // end while\r
+        //\r
+      }\r
+\r
+      Node = NextDevicePathNode (Node);\r
+    }\r
+    //\r
+    // end while\r
+    //\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build up Console Menu based on types passed in. The type can\r
+  be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT\r
+  and BM_CONSOLE_ERR_CONTEXT_SELECT.\r
+\r
+  @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT\r
+                         and BM_CONSOLE_ERR_CONTEXT_SELECT.\r
+\r
+  @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined.\r
+  @retval EFI_NOT_FOUND   If the EFI Variable defined in UEFI spec with name "ConOutDev", \r
+                          "ConInDev" or "ConErrDev" doesn't exists.\r
+  @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations.\r
+  @retval EFI_SUCCESS          Function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+  IN UINTN              ConsoleMenuType\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *AllDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *MultiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathInst;\r
+  UINTN                     Size;\r
+  UINTN                     AllCount;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  TYPE_OF_TERMINAL          Terminal;\r
+  UINTN                     Com;\r
+  BM_MENU_OPTION            *ConsoleMenu;\r
+\r
+  DevicePath    = NULL;\r
+  AllDevicePath = NULL;\r
+  AllCount      = 0;\r
+  switch (ConsoleMenuType) {\r
+  case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleInpMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConIn",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConInDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleOutMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ConOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ConOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+    ConsoleMenu = &ConsoleErrMenu;\r
+    DevicePath = EfiLibGetVariable (\r
+                  L"ErrOut",\r
+                  &gEfiGlobalVariableGuid\r
+                  );\r
+\r
+    AllDevicePath = EfiLibGetVariable (\r
+                      L"ErrOutDev",\r
+                      &gEfiGlobalVariableGuid\r
+                      );\r
+    break;\r
+\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (NULL == AllDevicePath) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InitializeListHead (&ConsoleMenu->Head);\r
+\r
+  AllCount                = EfiDevicePathInstanceCount (AllDevicePath);\r
+  ConsoleMenu->MenuNumber = 0;\r
+  //\r
+  // Following is menu building up for Console Devices selected.\r
+  //\r
+  MultiDevicePath = AllDevicePath;\r
+  Index2          = 0;\r
+  for (Index = 0; Index < AllCount; Index++) {\r
+    DevicePathInst  = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+    NewMenuEntry    = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    NewConsoleContext             = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewMenuEntry->OptionNumber    = Index2;\r
+\r
+    NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst);\r
+    NewMenuEntry->DisplayString   = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+    if (NULL == NewMenuEntry->DisplayString) {\r
+      NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+    }\r
+\r
+    NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+                                      NewConsoleContext->DevicePath,\r
+                                      &Terminal,\r
+                                      &Com\r
+                                      );\r
+\r
+    NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+                                    DevicePath,\r
+                                    NewConsoleContext->DevicePath\r
+                                    );\r
+\r
+    if (NewConsoleContext->IsTerminal) {\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    } else {\r
+      Index2++;\r
+      ConsoleMenu->MenuNumber++;\r
+      InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+  @retval EFI_SUCCESS    The function always complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAllConsoles (\r
+  VOID\r
+  )\r
+{\r
+  GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+  GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+  @retval EFI_SUCCESS    The function always complete successfully.\r
+**/\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+  VOID\r
+  )\r
+{\r
+  BOpt_FreeMenu (&ConsoleOutMenu);\r
+  BOpt_FreeMenu (&ConsoleInpMenu);\r
+  BOpt_FreeMenu (&ConsoleErrMenu);\r
+  BOpt_FreeMenu (&TerminalMenu);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Test whether DevicePath is a valid Terminal\r
+\r
+\r
+  @param DevicePath      DevicePath to be checked\r
+  @param Termi           If DevicePath is valid Terminal, terminal type is returned.\r
+  @param Com             If DevicePath is valid Terminal, Com Port type is returned.\r
+\r
+  @retval  TRUE         If DevicePath point to a Terminal.\r
+  @retval  FALSE        If DevicePath does not point to a Terminal.\r
+\r
+**/\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+  OUT TYPE_OF_TERMINAL         *Termi,\r
+  OUT UINTN                    *Com\r
+  )\r
+{\r
+  UINT8                 *Ptr;\r
+  BOOLEAN               IsTerminal;\r
+  VENDOR_DEVICE_PATH    *Vendor;\r
+  ACPI_HID_DEVICE_PATH  *Acpi;\r
+  UINT32                Match;\r
+  EFI_GUID              TempGuid;\r
+\r
+  IsTerminal = FALSE;\r
+\r
+  //\r
+  // Parse the Device Path, should be change later!!!\r
+  //\r
+  Ptr = (UINT8 *) DevicePath;\r
+  while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+    Ptr++;\r
+  }\r
+\r
+  Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+  Vendor  = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+  //\r
+  // There are four kinds of Terminal types\r
+  // check to see whether this devicepath\r
+  // is one of that type\r
+  //\r
+  CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+  if (CompareGuid (&TempGuid, &TerminalTypeGuid[0])) {\r
+    *Termi      = PC_ANSI;\r
+    IsTerminal  = TRUE;\r
+  } else {\r
+    if (CompareGuid (&TempGuid, &TerminalTypeGuid[1])) {\r
+      *Termi      = VT_100;\r
+      IsTerminal  = TRUE;\r
+    } else {\r
+      if (CompareGuid (&TempGuid, &TerminalTypeGuid[2])) {\r
+        *Termi      = VT_100_PLUS;\r
+        IsTerminal  = TRUE;\r
+      } else {\r
+        if (CompareGuid (&TempGuid, &TerminalTypeGuid[3])) {\r
+          *Termi      = VT_UTF8;\r
+          IsTerminal  = TRUE;\r
+        } else {\r
+          IsTerminal = FALSE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (!IsTerminal) {\r
+    return FALSE;\r
+  }\r
+\r
+  Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+  Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+  Match = EISA_PNP_ID (0x0501);\r
+  if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+    CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+  } else {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get mode number according to column and row\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+GetConsoleOutMode (\r
+  IN  BMM_CALLBACK_DATA    *CallbackData\r
+  )\r
+{\r
+  UINTN                         Col;\r
+  UINTN                         Row;\r
+  UINTN                         CurrentCol;\r
+  UINTN                         CurrentRow;\r
+  UINTN                         Mode;\r
+  UINTN                         MaxMode;\r
+  EFI_STATUS                    Status;\r
+  CONSOLE_OUT_MODE              *ModeInfo;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;\r
+\r
+  ConOut   = gST->ConOut;\r
+  MaxMode  = (UINTN) (ConOut->Mode->MaxMode);\r
+  ModeInfo = EfiLibGetVariable (VAR_CON_OUT_MODE, &gEfiGenericPlatformVariableGuid);\r
+\r
+  if (ModeInfo != NULL) {\r
+    CurrentCol = ModeInfo->Column;\r
+    CurrentRow = ModeInfo->Row;\r
+    for (Mode = 0; Mode < MaxMode; Mode++) {\r
+      Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+      if (!EFI_ERROR(Status)) {\r
+        if (CurrentCol == Col && CurrentRow == Row) {\r
+          CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    FreePool (ModeInfo);\r
+  }\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Data.c
new file mode 100644 (file)
index 0000000..5a22e77
--- /dev/null
@@ -0,0 +1,315 @@
+/** @file\r
+  Define some data used for Boot Maint\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+EFI_HII_UPDATE_DATA gUpdateData;\r
+STRING_DEPOSITORY   *FileOptionStrDepository;\r
+STRING_DEPOSITORY   *ConsoleOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionStrDepository;\r
+STRING_DEPOSITORY   *BootOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionStrDepository;\r
+STRING_DEPOSITORY   *DriverOptionHelpStrDepository;\r
+STRING_DEPOSITORY   *TerminalStrDepository;\r
+\r
+///\r
+/// Terminal type string token storage\r
+///\r
+UINT16              TerminalType[] = {\r
+  STRING_TOKEN(STR_COM_TYPE_0),\r
+  STRING_TOKEN(STR_COM_TYPE_1),\r
+  STRING_TOKEN(STR_COM_TYPE_2),\r
+  STRING_TOKEN(STR_COM_TYPE_3),\r
+};\r
+\r
+///\r
+/// File system selection menu\r
+///\r
+BM_MENU_OPTION      FsOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Console Input Device Selection Menu\r
+///\r
+BM_MENU_OPTION      ConsoleInpMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Console Output Device Selection Menu\r
+///\r
+BM_MENU_OPTION      ConsoleOutMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Error Output Device Selection Menu\r
+///\r
+BM_MENU_OPTION      ConsoleErrMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Boot Option from variable Menu\r
+///\r
+BM_MENU_OPTION      BootOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Driver Option from variable menu\r
+///\r
+BM_MENU_OPTION      DriverOptionMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Legacy FD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION      LegacyFDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Legacy HD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION      LegacyHDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Legacy CD Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION      LegacyCDMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION      LegacyNETMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+///\r
+BM_MENU_OPTION      LegacyBEVMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Files and sub-directories in current directory menu\r
+///\r
+BM_MENU_OPTION      DirectoryMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Handles in current system selection menu\r
+///\r
+BM_MENU_OPTION      DriverMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+BM_MENU_OPTION      TerminalMenu = {\r
+  BM_MENU_OPTION_SIGNATURE,\r
+  {NULL},\r
+  0\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for BaudRate\r
+///\r
+COM_ATTR            BaudRateList[19] = {\r
+  {\r
+    115200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_0)\r
+  },\r
+  {\r
+    57600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_1)\r
+  },\r
+  {\r
+    38400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_2)\r
+  },\r
+  {\r
+    19200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_3)\r
+  },\r
+  {\r
+    9600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_4)\r
+  },\r
+  {\r
+    7200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_5)\r
+  },\r
+  {\r
+    4800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_6)\r
+  },\r
+  {\r
+    3600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_7)\r
+  },\r
+  {\r
+    2400,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_8)\r
+  },\r
+  {\r
+    2000,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_9)\r
+  },\r
+  {\r
+    1800,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_10)\r
+  },\r
+  {\r
+    1200,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_11)\r
+  },\r
+  {\r
+    600,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_12)\r
+  },\r
+  {\r
+    300,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_13)\r
+  },\r
+  {\r
+    150,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_14)\r
+  },\r
+  {\r
+    134,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_15)\r
+  },\r
+  {\r
+    110,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_16)\r
+  },\r
+  {\r
+    75,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_17)\r
+  },\r
+  {\r
+    50,\r
+    STRING_TOKEN(STR_COM_BAUD_RATE_18)\r
+  }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for DataBits\r
+///\r
+COM_ATTR            DataBitsList[4] = {\r
+  {\r
+    5,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_0)\r
+  },\r
+  {\r
+    6,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_1)\r
+  },\r
+  {\r
+    7,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_2)\r
+  },\r
+  {\r
+    8,\r
+    STRING_TOKEN(STR_COM_DATA_BITS_3)\r
+  }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for Parity\r
+///\r
+COM_ATTR            ParityList[5] = {\r
+  {\r
+    NoParity,\r
+    STRING_TOKEN(STR_COM_PAR_0)\r
+  },\r
+  {\r
+    EvenParity,\r
+    STRING_TOKEN(STR_COM_PAR_1)\r
+  },\r
+  {\r
+    OddParity,\r
+    STRING_TOKEN(STR_COM_PAR_2)\r
+  },\r
+  {\r
+    MarkParity,\r
+    STRING_TOKEN(STR_COM_PAR_3)\r
+  },\r
+  {\r
+    SpaceParity,\r
+    STRING_TOKEN(STR_COM_PAR_4)\r
+  }\r
+};\r
+\r
+///\r
+/// Value and string token correspondency for Baudreate\r
+///\r
+COM_ATTR            StopBitsList[3] = {\r
+  {\r
+    OneStopBit,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_0)\r
+  },\r
+  {\r
+    OneFiveStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_1)\r
+  },\r
+  {\r
+    TwoStopBits,\r
+    STRING_TOKEN(STR_COM_STOP_BITS_2)\r
+  }\r
+};\r
+\r
+///\r
+/// Guid for messaging path, used in Serial port setting.\r
+///\r
+EFI_GUID            TerminalTypeGuid[4] = {\r
+  DEVICE_PATH_MESSAGING_PC_ANSI,\r
+  DEVICE_PATH_MESSAGING_VT_100,\r
+  DEVICE_PATH_MESSAGING_VT_100_PLUS,\r
+  DEVICE_PATH_MESSAGING_VT_UTF8\r
+};\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
new file mode 100644 (file)
index 0000000..b89cf11
--- /dev/null
@@ -0,0 +1,126 @@
+///** @file\r
+//  \r
+//    File Explorer Formset\r
+//  \r
+//  Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+//  All rights reserved. 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
+#include "FormGuid.h"\r
+\r
+#define LABEL_END   0xffff\r
+\r
+formset\r
+  guid = FILE_EXPLORE_FORMSET_GUID,\r
+  title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),\r
+  help = STRING_TOKEN(STR_NULL_STRING),\r
+  class = 0,\r
+  subclass = 0,\r
+\r
+  varstore FILE_EXPLORER_NV_DATA,\r
+    varid = VARSTORE_ID_BOOT_MAINT,\r
+    name = FeData,\r
+    guid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+  form formid = FORM_FILE_EXPLORER_ID,\r
+       title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+       label FORM_FILE_EXPLORER_ID;\r
+       label LABEL_END;\r
+  endform;\r
+\r
+  form formid = FORM_BOOT_ADD_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);\r
+\r
+       label FORM_BOOT_ADD_DESCRIPTION_ID;\r
+       label LABEL_END;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       string    varid    = FeData.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FeData.OptionalData,\r
+                       prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                       help     = STRING_TOKEN(STR_NULL_STRING),\r
+                       minsize  = 0,\r
+                       maxsize  = 120,\r
+       endstring;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_BOOT;\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;\r
+\r
+  endform;\r
+\r
+  form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,\r
+       title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+       label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+       label LABEL_END;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       string    varid    = FeData.DescriptionData,\r
+                 prompt   = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 6,\r
+                 maxsize  = 75,\r
+       endstring;\r
+\r
+       string    varid    = FeData.OptionalData,\r
+                 prompt   = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+                 help     = STRING_TOKEN(STR_NULL_STRING),\r
+                 minsize  = 0,\r
+                 maxsize  = 120,\r
+       endstring;\r
+\r
+       checkbox varid    = FeData.ForceReconnect,\r
+               prompt   = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+               help     = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+               flags    = CHECKBOX_DEFAULT,\r
+               key      = 0,\r
+       endcheckbox;\r
+\r
+       subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_SAVE_AND_EXIT_DRIVER;  //BUGBUB: allow duplicate key in one formset???\r
+\r
+       text\r
+         help   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+         text   = STRING_TOKEN(STR_NULL_STRING),\r
+         flags  = INTERACTIVE,\r
+         key    = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;\r
+\r
+  endform;\r
+\r
+endformset;
\ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
new file mode 100644 (file)
index 0000000..8253ded
--- /dev/null
@@ -0,0 +1,319 @@
+/** @file\r
+  File explorer related functions.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+/**\r
+  Update the File Explore page.\r
+\r
+  @param CallbackData    The BMM context data.\r
+  @param MenuOption      Pointer to menu options to display.\r
+\r
+**/\r
+VOID\r
+UpdateFileExplorePage (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  BM_MENU_OPTION                  *MenuOption\r
+  )\r
+{\r
+  UINTN           Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  EFI_FORM_ID     FormId;\r
+\r
+  NewMenuEntry    = NULL;\r
+  NewFileContext  = NULL;\r
+  FormId          = 0;\r
+\r
+  RefreshUpdateData ();\r
+\r
+  for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (MenuOption, Index);\r
+    NewFileContext  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsBootLegacy) {\r
+      continue;\r
+    }\r
+\r
+    if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {\r
+      //\r
+      // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.\r
+      //\r
+      CreateActionOpCode (\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        0,\r
+        &gUpdateData\r
+        );\r
+    } else {\r
+      //\r
+      // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.\r
+      //\r
+      if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+      } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {\r
+        FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+      }\r
+\r
+      CreateGotoOpCode (\r
+        FormId,\r
+        NewMenuEntry->DisplayStringToken,\r
+        STRING_TOKEN (STR_NULL_STRING),\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        (UINT16) (FILE_OPTION_OFFSET + Index),\r
+        &gUpdateData\r
+        );\r
+    }\r
+  }\r
+\r
+  IfrLibUpdateForm (\r
+    CallbackData->FeHiiHandle,\r
+    &mFileExplorerGuid,\r
+    FORM_FILE_EXPLORER_ID,\r
+    FORM_FILE_EXPLORER_ID,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+/**\r
+  Update the file explower page with the refershed file system.\r
+\r
+\r
+  @param CallbackData    BMM context data\r
+  @param KeyValue        Key value to identify the type of data to expect.\r
+\r
+  @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.\r
+  @retval  FALSE          Indicate that there is no need to exit file explorer.\r
+\r
+**/\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+  IN BMM_CALLBACK_DATA            *CallbackData,\r
+  IN UINT16                       KeyValue\r
+  )\r
+{\r
+  UINT16          FileOptionMask;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_FILE_CONTEXT *NewFileContext;\r
+  EFI_FORM_ID     FormId;\r
+  BOOLEAN         ExitFileExplorer;\r
+  EFI_STATUS      Status;\r
+\r
+  NewMenuEntry      = NULL;\r
+  NewFileContext    = NULL;\r
+  ExitFileExplorer  = FALSE;\r
+\r
+  FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+  if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {\r
+    //\r
+    // First in, display file system.\r
+    //\r
+    BOpt_FreeMenu (&FsOptionMenu);\r
+    BOpt_FindFileSystem (CallbackData);\r
+    CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);\r
+\r
+    UpdateFileExplorePage (CallbackData, &FsOptionMenu);\r
+\r
+    CallbackData->FeDisplayContext = FILE_SYSTEM;\r
+  } else {\r
+    if (FILE_SYSTEM == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+    } else if (DIRECTORY == CallbackData->FeDisplayContext) {\r
+      NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+    }\r
+\r
+    CallbackData->FeDisplayContext  = DIRECTORY;\r
+\r
+    NewFileContext                  = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (NewFileContext->IsDir ) {\r
+      RemoveEntryList (&NewMenuEntry->Link);\r
+      BOpt_FreeMenu (&DirectoryMenu);\r
+      Status = BOpt_FindFiles (CallbackData, NewMenuEntry);\r
+       if (EFI_ERROR (Status)) {\r
+         ExitFileExplorer = TRUE;\r
+         goto exit;\r
+       }\r
+      CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);\r
+      BOpt_DestroyMenuEntry (NewMenuEntry);\r
+\r
+      UpdateFileExplorePage (CallbackData, &DirectoryMenu);\r
+\r
+    } else {\r
+      switch (CallbackData->FeCurrentState) {\r
+      case BOOT_FROM_FILE_STATE:\r
+        //\r
+        // Here boot from file\r
+        //\r
+        BootThisFile (NewFileContext);\r
+        ExitFileExplorer = TRUE;\r
+        break;\r
+\r
+      case ADD_BOOT_OPTION_STATE:\r
+      case ADD_DRIVER_OPTION_STATE:\r
+        if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+          FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+        } else {\r
+          FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+        }\r
+\r
+        CallbackData->MenuEntry = NewMenuEntry;\r
+        CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;\r
+\r
+        //\r
+        // Create Subtitle op-code for the display string of the option.\r
+        //\r
+        RefreshUpdateData ();\r
+\r
+        CreateSubTitleOpCode (\r
+          NewMenuEntry->DisplayStringToken,\r
+          0,\r
+          0,\r
+          0,\r
+          &gUpdateData\r
+          );\r
+\r
+        IfrLibUpdateForm (\r
+          CallbackData->FeHiiHandle,\r
+          &mFileExplorerGuid,\r
+          FormId,\r
+          FormId,\r
+          FALSE,\r
+          &gUpdateData\r
+          );\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  exit:\r
+  return ExitFileExplorer;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+  When user select a interactive opcode, this callback will be triggered.\r
+  Based on the Question(QuestionId) that triggers the callback, the corresponding\r
+  actions is performed. It handles:\r
+\r
+  1) the addition of boot option.\r
+  2) the addition of driver option.\r
+  3) exit from file browser\r
+  4) update of file content if a dir is selected.\r
+  5) boot the file if a file is selected in "boot from file"\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.\r
+  @retval  EFI_DEVICE_ERROR      The variable could not be saved.\r
+  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.\r
+  @retval  EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  BMM_CALLBACK_DATA     *Private;\r
+  FILE_EXPLORER_NV_DATA *NvRamMap;\r
+  EFI_STATUS            Status;\r
+  UINTN                 BufferSize;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status         = EFI_SUCCESS;\r
+  Private        = FE_CALLBACK_DATA_FROM_THIS (This);\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+  //\r
+  // Retrieve uncommitted data from Form Browser\r
+  //\r
+  NvRamMap = &Private->FeFakeNvData;\r
+  BufferSize = sizeof (FILE_EXPLORER_NV_DATA);\r
+  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
+    //\r
+    // Apply changes and exit formset\r
+    //\r
+    if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateBootOption (Private, NvRamMap);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetBootOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);\r
+    } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {\r
+      Status = Var_UpdateDriverOption (\r
+                Private,\r
+                Private->FeHiiHandle,\r
+                NvRamMap->DescriptionData,\r
+                NvRamMap->OptionalData,\r
+                NvRamMap->ForceReconnect\r
+                );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      BOpt_GetDriverOptions (Private);\r
+      CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);\r
+    }\r
+\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
+    //\r
+    // Discard changes and exit formset\r
+    //\r
+    NvRamMap->OptionalData[0]     = 0x0000;\r
+    NvRamMap->DescriptionData[0]  = 0x0000;\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else if (QuestionId < FILE_OPTION_OFFSET) {\r
+    //\r
+    // Exit File Explorer formset\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+  } else {\r
+    if (UpdateFileExplorer (Private, QuestionId)) {\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
new file mode 100644 (file)
index 0000000..2523d64
--- /dev/null
@@ -0,0 +1,209 @@
+/** @file\r
+  Formset guids, form id and VarStore data structure for Boot Maintenance Manager.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#ifndef _FORM_GUID_H_\r
+#define _FORM_GUID_H_\r
+\r
+#define BOOT_MAINT_FORMSET_GUID \\r
+  { \\r
+  0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \\r
+  }\r
+\r
+#define FILE_EXPLORE_FORMSET_GUID \\r
+  { \\r
+  0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \\r
+  }\r
+\r
+#define FORM_MAIN_ID                         0x1001\r
+#define FORM_BOOT_ADD_ID                     0x1002\r
+#define FORM_BOOT_DEL_ID                     0x1003\r
+#define FORM_BOOT_CHG_ID                     0x1004\r
+#define FORM_DRV_ADD_ID                      0x1005\r
+#define FORM_DRV_DEL_ID                      0x1006\r
+#define FORM_DRV_CHG_ID                      0x1007\r
+#define FORM_CON_MAIN_ID                     0x1008\r
+#define FORM_CON_IN_ID                       0x1009\r
+#define FORM_CON_OUT_ID                      0x100A\r
+#define FORM_CON_ERR_ID                      0x100B\r
+#define FORM_FILE_SEEK_ID                    0x100C\r
+#define FORM_FILE_NEW_SEEK_ID                0x100D\r
+#define FORM_DRV_ADD_FILE_ID                 0x100E\r
+#define FORM_DRV_ADD_HANDLE_ID               0x100F\r
+#define FORM_DRV_ADD_HANDLE_DESC_ID          0x1010\r
+#define FORM_BOOT_NEXT_ID                    0x1011\r
+#define FORM_TIME_OUT_ID                     0x1012\r
+#define FORM_RESET                           0x1013\r
+#define FORM_BOOT_SETUP_ID                   0x1014\r
+#define FORM_DRIVER_SETUP_ID                 0x1015\r
+#define FORM_BOOT_LEGACY_DEVICE_ID           0x1016\r
+#define FORM_CON_COM_ID                      0x1017\r
+#define FORM_CON_COM_SETUP_ID                0x1018\r
+#define FORM_SET_FD_ORDER_ID                 0x1019\r
+#define FORM_SET_HD_ORDER_ID                 0x101A\r
+#define FORM_SET_CD_ORDER_ID                 0x101B\r
+#define FORM_SET_NET_ORDER_ID                0x101C\r
+#define FORM_SET_BEV_ORDER_ID                0x101D\r
+#define FORM_FILE_EXPLORER_ID                0x101E\r
+#define FORM_BOOT_ADD_DESCRIPTION_ID         0x101F\r
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID  0x1020\r
+#define FORM_CON_MODE_ID                     0x1021\r
+\r
+#define MAXIMUM_FORM_ID                      0x10FF\r
+\r
+#define KEY_VALUE_COM_SET_BAUD_RATE          0x1101\r
+#define KEY_VALUE_COM_SET_DATA_BITS          0x1102\r
+#define KEY_VALUE_COM_SET_STOP_BITS          0x1103\r
+#define KEY_VALUE_COM_SET_PARITY             0x1104\r
+#define KEY_VALUE_COM_SET_TERMI_TYPE         0x1105\r
+#define KEY_VALUE_MAIN_BOOT_NEXT             0x1106\r
+#define KEY_VALUE_BOOT_ADD_DESC_DATA         0x1107\r
+#define KEY_VALUE_BOOT_ADD_OPT_DATA          0x1108\r
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA       0x1109\r
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA        0x110A\r
+#define KEY_VALUE_SAVE_AND_EXIT              0x110B\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT           0x110C\r
+#define KEY_VALUE_BOOT_FROM_FILE             0x110D\r
+\r
+#define MAXIMUM_NORMAL_KEY_VALUE             0x11FF\r
+\r
+//\r
+// Varstore ID defined for Buffer Stoarge\r
+//\r
+#define VARSTORE_ID_BOOT_MAINT               0x1000\r
+#define VARSTORE_ID_FILE_EXPLORER            0x1001\r
+\r
+///\r
+/// This is the structure that will be used to store the\r
+/// question's current value. Use it at initialize time to\r
+/// set default value for each question. When using at run\r
+/// time, this map is returned by the callback function,\r
+/// so dynamically changing the question's value will be\r
+/// possible through this mechanism\r
+///\r
+typedef struct {\r
+  //\r
+  // Three questions displayed at the main page\r
+  // for Timeout, BootNext Variables respectively\r
+  //\r
+  UINT16  BootTimeOut;\r
+  UINT16  BootNext;\r
+\r
+  //\r
+  // This is the COM1 Attributes value storage\r
+  //\r
+  UINT8   COM1BaudRate;\r
+  UINT8   COM1DataRate;\r
+  UINT8   COM1StopBits;\r
+  UINT8   COM1Parity;\r
+  UINT8   COM1TerminalType;\r
+\r
+  //\r
+  // This is the COM2 Attributes value storage\r
+  //\r
+  UINT8   COM2BaudRate;\r
+  UINT8   COM2DataRate;\r
+  UINT8   COM2StopBits;\r
+  UINT8   COM2Parity;\r
+  UINT8   COM2TerminalType;\r
+\r
+  //\r
+  // Driver Option Add Handle page storage\r
+  //\r
+  UINT16  DriverAddHandleDesc[100];\r
+  UINT16  DriverAddHandleOptionalData[100];\r
+  UINT8   DriverAddActive;\r
+  UINT8   DriverAddForceReconnect;\r
+\r
+  //\r
+  // Console Input/Output/Errorout using COM port check storage\r
+  //\r
+  UINT8   ConsoleInputCOM1;\r
+  UINT8   ConsoleInputCOM2;\r
+  UINT8   ConsoleOutputCOM1;\r
+  UINT8   ConsoleOutputCOM2;\r
+  UINT8   ConsoleErrorCOM1;\r
+  UINT8   ConsoleErrorCOM2;\r
+\r
+  //\r
+  // At most 100 input/output/errorout device for console storage\r
+  //\r
+  UINT8   ConsoleCheck[100];\r
+\r
+  //\r
+  // Boot or Driver Option Order storage\r
+  //\r
+  UINT8   OptionOrder[100];\r
+  UINT8   DriverOptionToBeDeleted[100];\r
+\r
+  //\r
+  // Boot Option Delete storage\r
+  //\r
+  UINT8   BootOptionDel[100];\r
+  UINT8   DriverOptionDel[100];\r
+\r
+  //\r
+  // This is the Terminal Attributes value storage\r
+  //\r
+  UINT8   COMBaudRate;\r
+  UINT8   COMDataRate;\r
+  UINT8   COMStopBits;\r
+  UINT8   COMParity;\r
+  UINT8   COMTerminalType;\r
+\r
+  //\r
+  // Legacy Device Order Selection Storage\r
+  //\r
+  UINT8   LegacyFD[100];\r
+  UINT8   LegacyHD[100];\r
+  UINT8   LegacyCD[100];\r
+  UINT8   LegacyNET[100];\r
+  UINT8   LegacyBEV[100];\r
+\r
+  //\r
+  // We use DisableMap array to record the enable/disable state of each boot device\r
+  // It should be taken as a bit array, from left to right there are totally 256 bits\r
+  // the most left one stands for BBS table item 0, and the most right one stands for item 256\r
+  // If the bit is 1, it means the boot device has been disabled.\r
+  //\r
+  UINT8   DisableMap[32];\r
+\r
+  //\r
+  // Console Output Text Mode\r
+  //\r
+  UINT16  ConsoleOutMode;\r
+\r
+  //\r
+  //  UINT16                    PadArea[10];\r
+  //\r
+} BMM_FAKE_NV_DATA;\r
+\r
+//\r
+// Key used by File Explorer forms\r
+//\r
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT           0x1000\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT        0x1001\r
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER         0x1002\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER      0x1003\r
+\r
+///\r
+/// This is the data structure used by File Explorer formset\r
+///\r
+typedef struct {\r
+  UINT16  DescriptionData[75];\r
+  UINT16  OptionalData[127];\r
+  UINT8   Active;\r
+  UINT8   ForceReconnect;\r
+} FILE_EXPLORER_NV_DATA;\r
+\r
+#endif\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
new file mode 100644 (file)
index 0000000..9fa2556
--- /dev/null
@@ -0,0 +1,1323 @@
+/** @file\r
+Dynamically update the pages.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+/**\r
+  Refresh the global UpdateData structure.\r
+\r
+**/\r
+VOID\r
+RefreshUpdateData (\r
+  VOID\r
+  )\r
+{\r
+  gUpdateData.Offset = 0;\r
+}\r
+\r
+/**\r
+  Add a "Go back to main page" tag in front of the form when there are no\r
+  "Apply changes" and "Discard changes" tags in the end of the form.\r
\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageStart (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  RefreshUpdateData ();\r
+\r
+  if (!(CallbackData->BmmAskSaveOrNot)) {\r
+    //\r
+    // Add a "Go back to main page" tag in front of the form when there are no\r
+    // "Apply changes" and "Discard changes" tags in the end of the form.\r
+    //\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+      0,\r
+      FORM_MAIN_ID,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Create the "Apply changes" and "Discard changes" tags. And\r
+  ensure user can return to the main page.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageEnd (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  //\r
+  // Create the "Apply changes" and "Discard changes" tags.\r
+  //\r
+  if (CallbackData->BmmAskSaveOrNot) {\r
+    CreateSubTitleOpCode (\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      0,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+\r
+    CreateGotoOpCode (\r
+      FORM_MAIN_ID,\r
+      STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      KEY_VALUE_SAVE_AND_EXIT,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  //\r
+  // Ensure user can return to the main page.\r
+  //\r
+  CreateGotoOpCode (\r
+    FORM_MAIN_ID,\r
+    STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    KEY_VALUE_NO_SAVE_AND_EXIT,\r
+    &gUpdateData\r
+    );\r
+\r
+  IfrLibUpdateForm (\r
+    CallbackData->BmmHiiHandle,\r
+    &mBootMaintGuid,\r
+    CallbackData->BmmCurrentPageId,\r
+    CallbackData->BmmCurrentPageId,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+/**\r
+  Clean up the dynamic opcode at label and form specified by both LabelId. \r
+\r
+  @param LabelId         It is both the Form ID and Label ID for opcode deletion.\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+CleanUpPage (\r
+  IN UINT16                           LabelId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  RefreshUpdateData ();\r
+\r
+  //\r
+  // Remove all op-codes from dynamic page\r
+  //\r
+  IfrLibUpdateForm (\r
+    CallbackData->BmmHiiHandle,\r
+    &mBootMaintGuid,\r
+    LabelId,\r
+    LabelId,\r
+    FALSE,\r
+    &gUpdateData\r
+    );\r
+}\r
+\r
+/**\r
+  Boot a file selected by user at File Expoloer of BMM.\r
+\r
+  @param FileContext     The file context data, which contains the device path\r
+                         of the file to be boot from.\r
+\r
+  @retval EFI_SUCCESS    The function completed successfull.\r
+  @return Other value if the boot from the file fails.\r
+\r
+**/\r
+EFI_STATUS\r
+BootThisFile (\r
+  IN BM_FILE_CONTEXT                   *FileContext\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             ExitDataSize;\r
+  CHAR16            *ExitData;\r
+  BDS_COMMON_OPTION *Option;\r
+\r
+  Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION));\r
+  ASSERT (Option != NULL);\r
+  Option->Description     = FileContext->FileName;\r
+  Option->DevicePath      = FileContext->DevicePath;\r
+  Option->LoadOptionsSize = 0;\r
+  Option->LoadOptions     = NULL;\r
+\r
+  //\r
+  // Since current no boot from removable media directly is allowed */\r
+  //\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+  ExitDataSize  = 0;\r
+\r
+  Status        = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Create a list of Goto Opcode for all terminal devices logged\r
+  by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.\r
+\r
+  @param CallbackData    The BMM context data.\r
+**/\r
+VOID\r
+UpdateConCOMPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+    CreateGotoOpCode (\r
+      FORM_CON_COM_SETUP_ID,\r
+      NewMenuEntry->DisplayStringToken,\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      (UINT16) (TERMINAL_OPTION_OFFSET + Index),\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Create a lit of boot option from global BootOptionMenu. It\r
+  allow user to delete the boot option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewLoadContext->IsLegacy) {\r
+      continue;\r
+    }\r
+\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Create a lit of driver option from global DriverMenu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
+\r
+    CreateGotoOpCode (\r
+      FORM_DRV_ADD_HANDLE_DESC_ID,\r
+      NewMenuEntry->DisplayStringToken,\r
+      STRING_TOKEN (STR_NULL_STRING),\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      (UINT16) (HANDLE_OPTION_OFFSET + Index),\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Create a lit of driver option from global DriverOptionMenu. It\r
+  allow user to delete the driver option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDrvDelPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          Index;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);\r
+  \r
+  ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+\r
+    NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->Deleted = FALSE;\r
+    CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      0,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Prepare the page to allow user to add description for \r
+  a Driver Option.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+  CallbackData->BmmFakeNvData.DriverAddActive          = 0x01;\r
+  CallbackData->BmmFakeNvData.DriverAddForceReconnect  = 0x00;\r
+  CallbackData->BmmAskSaveOrNot                        = TRUE;\r
+  NewMenuEntry = CallbackData->MenuEntry;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateSubTitleOpCode (\r
+    NewMenuEntry->DisplayStringToken,\r
+    0,\r
+    0,\r
+    0,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateStringOpCode (\r
+    (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRV_ADD_HANDLE_DESC_VAR_OFFSET,\r
+    STRING_TOKEN (STR_LOAD_OPTION_DESC),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    0,\r
+    0,\r
+    6,\r
+    75,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateCheckBoxOpCode (\r
+    (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRV_ADD_RECON_VAR_OFFSET,\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+    0,\r
+    0,\r
+    &gUpdateData\r
+    );\r
+\r
+  CreateStringOpCode (\r
+    (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    DRIVER_ADD_OPTION_VAR_OFFSET,\r
+    STRING_TOKEN (STR_OPTIONAL_DATA),\r
+    STRING_TOKEN (STR_NULL_STRING),\r
+    0,\r
+    0,\r
+    6,\r
+    75,\r
+    &gUpdateData\r
+    );\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Update console page.\r
+\r
+  @param UpdatePageId    The form ID to be updated.\r
+  @param ConsoleMenu     The console menu list.\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateConsolePage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *ConsoleMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+  UINT16              Index;\r
+  UINT16              Index2;\r
+  UINT8               CheckFlags;\r
\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  ASSERT (ConsoleMenu->MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.ConsoleCheck) / sizeof (CallbackData->BmmFakeNvData.ConsoleCheck[0])));\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry      = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    CheckFlags        = 0;\r
+    if (NewConsoleContext->IsActive) {\r
+      CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+    } else {\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+    }\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      CheckFlags,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {\r
+    CheckFlags          = 0;\r
+    NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, Index2);\r
+    NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+    if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+        ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+        ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))\r
+        ) {\r
+      CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+    } else {\r
+      CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+    }\r
+\r
+    CreateCheckBoxOpCode (\r
+      (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+      NewMenuEntry->DisplayStringToken,\r
+      NewMenuEntry->HelpStringToken,\r
+      0,\r
+      CheckFlags,\r
+      &gUpdateData\r
+      );\r
+\r
+    Index++;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Update the page's NV Map if user has changed the order\r
+  a list. This list can be Boot Order or Driver Order.\r
+\r
+  @param UpdatePageId    The form ID to be updated.\r
+  @param OptionMenu      The new list.\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BM_MENU_OPTION                   *OptionMenu,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        Index;\r
+  IFR_OPTION    *IfrOptionList;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);\r
+  if (IfrOptionList == NULL) {\r
+    return ;\r
+  }\r
+  \r
+  ASSERT (OptionMenu->MenuNumber <= (sizeof (IfrOptionList) / sizeof (IfrOptionList[0])));\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);\r
+    IfrOptionList[Index].Flags = 0;\r
+    CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;\r
+  }\r
+\r
+  if (OptionMenu->MenuNumber > 0) {\r
+    CreateOrderedListOpCode (\r
+      (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      OPTION_ORDER_VAR_OFFSET,\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      STRING_TOKEN (STR_CHANGE_ORDER),\r
+      0,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      100,\r
+      IfrOptionList,\r
+      OptionMenu->MenuNumber,\r
+      &gUpdateData\r
+      );\r
+  }\r
+\r
+  FreePool (IfrOptionList);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+\r
+  CopyMem (\r
+    CallbackData->BmmOldFakeNVData.OptionOrder,\r
+    CallbackData->BmmFakeNvData.OptionOrder,\r
+    100\r
+    );\r
+}\r
+\r
+/**\r
+  Create the dynamic page to allow user to set\r
+  the "BootNext" value.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateBootNextPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  IFR_OPTION      *IfrOptionList;\r
+  UINTN           NumberOfOptions;\r
+  UINT16          Index;\r
+\r
+  IfrOptionList                 = NULL;\r
+  NumberOfOptions               = BootOptionMenu.MenuNumber;\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+  if (NumberOfOptions > 0) {\r
+    IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));\r
+\r
+    ASSERT (IfrOptionList);\r
+\r
+    CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);\r
+\r
+    for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+      if (NewLoadContext->IsBootNext) {\r
+        IfrOptionList[Index].Flags            = EFI_IFR_OPTION_DEFAULT;\r
+        CallbackData->BmmFakeNvData.BootNext = Index;\r
+      } else {\r
+        IfrOptionList[Index].Flags = 0;\r
+      }\r
+\r
+      IfrOptionList[Index].Value.u16    = Index;\r
+      IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+    }\r
+\r
+    IfrOptionList[Index].Value.u16        = Index;\r
+    IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_NONE);\r
+    IfrOptionList[Index].Flags        = 0;\r
+    if (CallbackData->BmmFakeNvData.BootNext == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    CreateOneOfOpCode (\r
+      (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,\r
+      VARSTORE_ID_BOOT_MAINT,\r
+      BOOT_NEXT_VAR_OFFSET,\r
+      STRING_TOKEN (STR_BOOT_NEXT),\r
+      STRING_TOKEN (STR_BOOT_NEXT_HELP),\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_2,\r
+      IfrOptionList,\r
+      (UINTN) (NumberOfOptions + 1),\r
+      &gUpdateData\r
+      );\r
+\r
+    FreePool (IfrOptionList);\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Create the dynamic page to allow user to set the "TimeOut" value.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateTimeOutPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT16  BootTimeOut;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  BootTimeOut = BdsLibGetTimeout ();\r
+\r
+  CreateNumericOpCode (\r
+    (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    BOOT_TIME_OUT_VAR_OFFSET,\r
+    STRING_TOKEN (STR_NUM_AUTO_BOOT),\r
+    STRING_TOKEN (STR_HLP_AUTO_BOOT),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,\r
+    0,\r
+    65535,\r
+    0,\r
+    BootTimeOut,\r
+    &gUpdateData\r
+    );\r
+\r
+  CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Refresh the text mode page.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateConModePage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINTN                         Mode;\r
+  UINTN                         Index;\r
+  UINTN                         Col;\r
+  UINTN                         Row;\r
+  CHAR16                        RowString[50];\r
+  CHAR16                        ModeString[50];\r
+  UINTN                         MaxMode;\r
+  UINTN                         ValidMode;\r
+  EFI_STRING_ID                 *ModeToken;\r
+  IFR_OPTION                    *IfrOptionList;\r
+  EFI_STATUS                    Status;\r
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;\r
+\r
+  ConOut    = gST->ConOut;\r
+  Index     = 0;\r
+  ValidMode = 0;\r
+  MaxMode   = (UINTN) (ConOut->Mode->MaxMode);\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  //\r
+  // Check valid mode\r
+  //\r
+  for (Mode = 0; Mode < MaxMode; Mode++) {\r
+    Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+    ValidMode++;\r
+  }\r
+\r
+  if (ValidMode == 0) {\r
+    return;\r
+  }\r
+\r
+  IfrOptionList       = AllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);\r
+  ASSERT(IfrOptionList != NULL);\r
+\r
+  ModeToken           = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);\r
+  ASSERT(ModeToken != NULL);\r
+\r
+  //\r
+  // Determin which mode should be the first entry in menu\r
+  //\r
+  GetConsoleOutMode (CallbackData);\r
+\r
+  //\r
+  // Build text mode options\r
+  //\r
+  for (Mode = 0; Mode < MaxMode; Mode++) {\r
+    Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+    \r
+    //\r
+    // Build mode string Column x Row\r
+    //\r
+    UnicodeValueToString (ModeString, 0, Col, 0);\r
+    ASSERT ((StrLen (ModeString)  + 1) < (sizeof (ModeString) / sizeof (ModeString[0])));\r
+    StrCat (ModeString, L" x ");\r
+    UnicodeValueToString (RowString, 0, Row, 0);\r
+    ASSERT ((StrLen (ModeString)  + StrLen(RowString)) < (sizeof (ModeString) / sizeof (ModeString[0])));\r
+    StrCat (ModeString, RowString);\r
+\r
+    HiiLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);\r
+\r
+    IfrOptionList[Index].StringToken  = ModeToken[Index];\r
+    IfrOptionList[Index].Value.u16    = (UINT16) Mode;\r
+    if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {\r
+      IfrOptionList[Index].Flags      = EFI_IFR_OPTION_DEFAULT;\r
+    } else {\r
+      IfrOptionList[Index].Flags      = 0;\r
+    }\r
+    Index++;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    CON_MODE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_CON_MODE_SETUP),\r
+    STRING_TOKEN (STR_CON_MODE_SETUP),\r
+    EFI_IFR_FLAG_RESET_REQUIRED,\r
+    EFI_IFR_NUMERIC_SIZE_2,\r
+    IfrOptionList,\r
+    ValidMode,\r
+    &gUpdateData\r
+    );\r
+  FreePool (IfrOptionList);\r
+  FreePool (ModeToken);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,\r
+  Parity, Stop Bits, Terminal Type.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdateTerminalPage (\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  UINT8               Index;\r
+  UINT8               CheckFlags;\r
+  IFR_OPTION          *IfrOptionList;\r
+  BM_MENU_ENTRY       *NewMenuEntry;\r
+  BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+  UpdatePageStart (CallbackData);\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &TerminalMenu,\r
+                  CallbackData->CurrentTerminal\r
+                  );\r
+\r
+  if (NewMenuEntry == NULL) {\r
+    return ;\r
+  }\r
+\r
+  NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+  IfrOptionList       = AllocateZeroPool (sizeof (IFR_OPTION) * 19);\r
+  if (IfrOptionList == NULL) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->BaudRateIndex         = Index;\r
+      CallbackData->BmmFakeNvData.COMBaudRate  = NewTerminalContext->BaudRateIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = BaudRateList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_BAUD_RATE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    STRING_TOKEN (STR_COM_BAUD_RATE),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    19,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < sizeof (DataBitsList) / sizeof (DataBitsList[0]); Index++) {\r
+    CheckFlags = 0;\r
+\r
+    if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {\r
+      NewTerminalContext->DataBitsIndex         = Index;\r
+      CallbackData->BmmFakeNvData.COMDataRate  = NewTerminalContext->DataBitsIndex;\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = DataBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_DATA_RATE_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    STRING_TOKEN (STR_COM_DATA_BITS),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    4,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < sizeof (ParityList) / sizeof (ParityList[0]); Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->Parity == ParityList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->ParityIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData.COMParity  = NewTerminalContext->ParityIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = ParityList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_PARITY_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    STRING_TOKEN (STR_COM_PARITY),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    5,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < sizeof (StopBitsList) / sizeof (StopBitsList[0]); Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      NewTerminalContext->StopBitsIndex         = (UINT8) Index;\r
+      CallbackData->BmmFakeNvData.COMStopBits  = NewTerminalContext->StopBitsIndex;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = StopBitsList[Index].StringToken;\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_STOP_BITS_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    STRING_TOKEN (STR_COM_STOP_BITS),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    3,\r
+    &gUpdateData\r
+    );\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    CheckFlags = 0;\r
+    if (NewTerminalContext->TerminalType == Index) {\r
+      CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+      CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;\r
+    }\r
+\r
+    IfrOptionList[Index].Flags        = CheckFlags;\r
+    IfrOptionList[Index].StringToken  = (EFI_STRING_ID) TerminalType[Index];\r
+    IfrOptionList[Index].Value.u8     = Index;\r
+  }\r
+\r
+  CreateOneOfOpCode (\r
+    (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,\r
+    VARSTORE_ID_BOOT_MAINT,\r
+    COM_TERMINAL_VAR_OFFSET,\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+    0,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    4,\r
+    &gUpdateData\r
+    );\r
+\r
+  FreePool (IfrOptionList);\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Dispatch the correct update page function to call based on\r
+  the UpdatePageId.\r
+\r
+  @param UpdatePageId    The form ID.\r
+  @param CallbackData    The BMM context data.\r
+\r
+**/\r
+VOID\r
+UpdatePageBody (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  CleanUpPage (UpdatePageId, CallbackData);\r
+  switch (UpdatePageId) {\r
+  case FORM_CON_IN_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_OUT_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_CON_ERR_ID:\r
+    UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_BOOT_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);\r
+    break;\r
+\r
+  case FORM_DRV_CHG_ID:\r
+    UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);\r
+    break;\r
+\r
+  default:\r
+    break;\r
+  }\r
+}\r
+\r
+/**\r
+  Get the index number (#### in Boot####) for the boot option pointed to a BBS legacy device type\r
+  specified by DeviceType.\r
+\r
+  @param DeviceType      The legacy device type. It can be floppy, network, harddisk, cdrom,\r
+                         etc.\r
+  @param OptionIndex     Returns the index number (#### in Boot####).\r
+  @param OptionSize      Return the size of the Boot### variable.\r
+\r
+**/\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+  IN  UINTN                            DeviceType,\r
+  OUT UINTN                            *OptionIndex,\r
+  OUT UINTN                            *OptionSize\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  VOID                      *OptionBuffer;\r
+  UINTN                     OrderSize;\r
+  UINTN                     Index;\r
+  UINT16                    *OrderBuffer;\r
+  CHAR16                    StrTemp[100];\r
+  UINT16                    FilePathSize;\r
+  UINT8                     *Ptr;\r
+  UINT8                     *OptionalData;\r
+\r
+  //\r
+  // Get Boot Option number from the size of BootOrder\r
+  //\r
+  OrderBuffer = BdsLibGetVariableAndSize (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  &OrderSize\r
+                  );\r
+                  \r
+  if (OrderBuffer == NULL) {\r
+    return NULL;\r
+  }\r
+  \r
+  for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {\r
+    UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);\r
+    OptionBuffer = BdsLibGetVariableAndSize (\r
+                    StrTemp,\r
+                    &gEfiGlobalVariableGuid,\r
+                    OptionSize\r
+                    );\r
+    if (NULL == OptionBuffer) {\r
+      continue;\r
+    }\r
+\r
+    Ptr       = (UINT8 *) OptionBuffer;\r
+    Ptr += sizeof (UINT32);\r
+\r
+    FilePathSize = *(UINT16 *) Ptr;\r
+    Ptr += sizeof (UINT16);\r
+\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    //\r
+    // Now Ptr point to Device Path\r
+    //\r
+    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+    Ptr += FilePathSize;\r
+\r
+    //\r
+    // Now Ptr point to Optional Data\r
+    //\r
+    OptionalData = Ptr;\r
+\r
+    if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&\r
+        (BBS_DEVICE_PATH == DevicePath->Type) &&\r
+        (BBS_BBS_DP == DevicePath->SubType)\r
+        ) {\r
+      *OptionIndex = OrderBuffer[Index];\r
+      FreePool (OrderBuffer);\r
+      return OptionBuffer;\r
+    } else {\r
+      FreePool (OptionBuffer);\r
+    }\r
+  }\r
+\r
+  FreePool (OrderBuffer);\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Create a dynamic page so that Legacy Device boot order\r
+  can be set for specified device type.\r
+\r
+  @param UpdatePageId    The form ID. It also spefies the legacy device type.\r
+  @param CallbackData    The BMM context data.\r
+\r
+\r
+**/\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+  IN UINT16                           UpdatePageId,\r
+  IN BMM_CALLBACK_DATA                *CallbackData\r
+  )\r
+{\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  IFR_OPTION                  *IfrOptionList;\r
+  EFI_STRING_ID               StrRef;\r
+  EFI_STRING_ID               StrRefHelp;\r
+  BBS_TYPE                    BbsType;\r
+  UINTN                       VarSize;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      Index;\r
+  UINT16                      Key;\r
+  CHAR16                      String[100];\r
+  CHAR16                      *TypeStr;\r
+  CHAR16                      *TypeStrHelp;\r
+  UINT16                      VarDevOrder;\r
+  UINT8                       *VarData;\r
+  UINT8                       *LegacyOrder;\r
+  UINT8                       *OldData;\r
+  UINT8                       *DisMap;\r
+\r
+  OptionMenu = NULL;\r
+  Key = 0;\r
+  StrRef = 0;\r
+  StrRefHelp = 0;\r
+  TypeStr = NULL;\r
+  TypeStrHelp = NULL;\r
+  BbsType = BBS_FLOPPY;\r
+  LegacyOrder = NULL;\r
+  OldData = NULL;\r
+  DisMap = NULL;\r
+\r
+  CallbackData->BmmAskSaveOrNot = TRUE;\r
+  UpdatePageStart (CallbackData);\r
+\r
+  DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+\r
+  SetMem (DisMap, 32, 0);\r
+  //\r
+  // Create oneof option list\r
+  //\r
+  switch (UpdatePageId) {\r
+  case FORM_SET_FD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    Key         = (UINT16) LEGACY_FD_QUESTION_ID;\r
+    TypeStr     = STR_FLOPPY;\r
+    TypeStrHelp = STR_FLOPPY_HELP;\r
+    BbsType     = BBS_FLOPPY;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyFD;\r
+    break;\r
+\r
+  case FORM_SET_HD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+    Key         = (UINT16) LEGACY_HD_QUESTION_ID;\r
+    TypeStr     = STR_HARDDISK;\r
+    TypeStrHelp = STR_HARDDISK_HELP;\r
+    BbsType     = BBS_HARDDISK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyHD;\r
+    break;\r
+\r
+  case FORM_SET_CD_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+    Key         = (UINT16) LEGACY_CD_QUESTION_ID;\r
+    TypeStr     = STR_CDROM;\r
+    TypeStrHelp = STR_CDROM_HELP;\r
+    BbsType     = BBS_CDROM;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyCD;\r
+    break;\r
+\r
+  case FORM_SET_NET_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+    Key         = (UINT16) LEGACY_NET_QUESTION_ID;\r
+    TypeStr     = STR_NET;\r
+    TypeStrHelp = STR_NET_HELP;\r
+    BbsType     = BBS_EMBED_NETWORK;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyNET;\r
+    break;\r
+\r
+  case FORM_SET_BEV_ORDER_ID:\r
+    OptionMenu  = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+    Key         = (UINT16) LEGACY_BEV_QUESTION_ID;\r
+    TypeStr     = STR_BEV;\r
+    TypeStrHelp = STR_BEV_HELP;\r
+    BbsType     = BBS_BEV_DEVICE;\r
+    LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
+    OldData     = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
+    break;\r
+\r
+  default:\r
+    DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));\r
+    return;\r
+  }\r
+\r
+  CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+  IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));\r
+  if (NULL == IfrOptionList) {\r
+    return ;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry                = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    IfrOptionList[Index].Flags  = 0;\r
+    if (0 == Index) {\r
+      IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+    }\r
+\r
+    IfrOptionList[Index].StringToken  = NewMenuEntry->DisplayStringToken;\r
+    IfrOptionList[Index].Value.u8     = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;\r
+  }\r
+  //\r
+  // for item "Disabled"\r
+  //\r
+  IfrOptionList[Index].Flags        = 0;\r
+  IfrOptionList[Index].StringToken  = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);\r
+  IfrOptionList[Index].Value.u8     = 0xFF;\r
+\r
+  //\r
+  // Get Device Order from variable\r
+  //\r
+  VarData = BdsLibGetVariableAndSize (\r
+              VAR_LEGACY_DEV_ORDER,\r
+              &EfiLegacyDevOrderGuid,\r
+              &VarSize\r
+              );\r
+\r
+  if (NULL != VarData) {\r
+    DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    while (VarData < VarData + VarSize) {\r
+      if (DevOrder->BbsType == BbsType) {\r
+        break;\r
+      }\r
+\r
+      VarData += sizeof (BBS_TYPE);\r
+      VarData += *(UINT16 *) VarData;\r
+      DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+    }\r
+    //\r
+    // Create oneof tag here for FD/HD/CD #1 #2\r
+    //\r
+    for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+      //\r
+      // Create the string for oneof tag\r
+      //\r
+      UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
+      StrRef = 0;\r
+      HiiLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);\r
+\r
+      UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
+      StrRefHelp = 0;\r
+      HiiLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);\r
+\r
+      CreateOneOfOpCode (\r
+        (EFI_QUESTION_ID) (Key + Index),\r
+        VARSTORE_ID_BOOT_MAINT,\r
+        (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),\r
+        StrRef,\r
+        StrRefHelp,\r
+        EFI_IFR_FLAG_CALLBACK,\r
+        EFI_IFR_NUMERIC_SIZE_1,\r
+        IfrOptionList,\r
+        OptionMenu->MenuNumber + 1,\r
+        &gUpdateData\r
+        );\r
+\r
+      VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));\r
+\r
+      if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
+        LegacyOrder[Index]  = 0xFF;\r
+        Pos                 = (VarDevOrder & 0xFF) / 8;\r
+        Bit                 = 7 - ((VarDevOrder & 0xFF) % 8);\r
+        DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+      } else {\r
+        LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);\r
+      }\r
+    }\r
+  }\r
+\r
+  CopyMem (OldData, LegacyOrder, 100);\r
+\r
+  if (IfrOptionList != NULL) {\r
+    FreePool (IfrOptionList);\r
+    IfrOptionList = NULL;\r
+  }\r
+\r
+  UpdatePageEnd (CallbackData);\r
+}\r
+\r
+/**\r
+  Dispatch the display to the next page based on NewPageId.\r
+\r
+  @param Private         The BMM context data.\r
+  @param NewPageId       The original page ID.\r
+\r
+**/\r
+VOID\r
+UpdatePageId (\r
+  BMM_CALLBACK_DATA              *Private,\r
+  UINT16                         NewPageId\r
+  )\r
+{\r
+  if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {\r
+    //\r
+    // If we select a handle to add driver option, advance to the add handle description page.\r
+    //\r
+    NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;\r
+  } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {\r
+    //\r
+    // Return to main page after "Save Changes" or "Discard Changes".\r
+    //\r
+    NewPageId = FORM_MAIN_ID;\r
+  } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {\r
+    NewPageId = FORM_CON_COM_SETUP_ID;\r
+  }\r
+\r
+  if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {\r
+    Private->BmmPreviousPageId  = Private->BmmCurrentPageId;\r
+    Private->BmmCurrentPageId   = NewPageId;\r
+  }\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/Variable.c
new file mode 100644 (file)
index 0000000..5cc7abc
--- /dev/null
@@ -0,0 +1,1417 @@
+/** @file\r
+  Variable operation that will be used by bootmaint\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootMaint.h"\r
+\r
+/**\r
+  Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this boot option, call Var_ChangeBootOrder to\r
+  make sure BootOrder is in valid state.\r
+\r
+  @retval EFI_SUCCESS   If all boot load option EFI Variables corresponding to  \r
+                        BM_LOAD_CONTEXT marked for deletion is deleted.\r
+  @retval EFI_NOT_FOUND If can not find the boot option want to be deleted.\r
+  @return Others        If failed to update the "BootOrder" variable after deletion. \r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+  VOID\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          BootString[10];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      BootString,\r
+      sizeof (BootString),\r
+      L"Boot%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+    //\r
+    // If current Load Option is the same as BootNext,\r
+    // must delete BootNext in order to make sure\r
+    // there will be no panic on next boot\r
+    //\r
+    if (NewLoadContext->IsBootNext) {\r
+      EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    }\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  BootOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeBootOrder ();\r
+  return Status;\r
+}\r
+\r
+/**\r
+  After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+  Since some are missing but in BootOrder, while some are present but are\r
+  not reflected by BootOrder. Then a function rebuild BootOrder from\r
+  scratch by content from BootOptionMenu is needed.\r
+\r
+\r
+  \r
+\r
+  @retval  EFI_SUCCESS  The boot order is updated successfully.\r
+  @return               EFI_STATUS other than EFI_SUCCESS if failed to\r
+                        Set the "BootOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+  VOID\r
+  )\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *BootOrderList;\r
+  UINT16        *BootOrderListPtr;\r
+  UINTN         BootOrderListSize;\r
+  UINTN         Index;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+    FreePool (BootOrderList);\r
+    BootOrderList = NULL;\r
+  }\r
+  //\r
+  // Maybe here should be some check method to ensure that\r
+  // no new added boot options will be added\r
+  // but the setup engine now will give only one callback\r
+  // that is to say, user are granted only one chance to\r
+  // decide whether the boot option will be added or not\r
+  // there should be no indictor to show whether this\r
+  // is a "new" boot option\r
+  //\r
+  BootOrderListSize = BootOptionMenu.MenuNumber;\r
+\r
+  if (BootOrderListSize > 0) {\r
+    BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
+    ASSERT (BootOrderList != NULL);\r
+    BootOrderListPtr = BootOrderList;\r
+\r
+    //\r
+    // Get all current used Boot#### from BootOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < BootOrderListSize; Index++) {\r
+      NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+      *BootOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      BootOrderList++;\r
+    }\r
+\r
+    BootOrderList = BootOrderListPtr;\r
+\r
+    //\r
+    // After building the BootOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    BootOrderListSize * sizeof (UINT16),\r
+                    BootOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+  After deleting this Driver option, call Var_ChangeDriverOrder to\r
+  make sure DriverOrder is in valid state.\r
+\r
+  @retval EFI_SUCCESS       Load Option is successfully updated.\r
+  @retval EFI_NOT_FOUND     Fail to find the driver option want to be deleted.\r
+  @return Other value than EFI_SUCCESS if failed to update "Driver Order" EFI\r
+          Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+  VOID\r
+  )\r
+{\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  UINT16          DriverString[12];\r
+  EFI_STATUS      Status;\r
+  UINTN           Index;\r
+  UINTN           Index2;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  Index2  = 0;\r
+  for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
+    if (NULL == NewMenuEntry) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (!NewLoadContext->Deleted) {\r
+      continue;\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      DriverString,\r
+      sizeof (DriverString),\r
+      L"Driver%04x",\r
+      NewMenuEntry->OptionNumber\r
+      );\r
+\r
+    EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
+    Index2++;\r
+\r
+    RemoveEntryList (&NewMenuEntry->Link);\r
+    BOpt_DestroyMenuEntry (NewMenuEntry);\r
+    NewMenuEntry = NULL;\r
+  }\r
+\r
+  DriverOptionMenu.MenuNumber -= Index2;\r
+\r
+  Status = Var_ChangeDriverOrder ();\r
+  return Status;\r
+}\r
+\r
+/**\r
+  After any operation on Driver####, there will be a discrepancy in\r
+  DriverOrder. Since some are missing but in DriverOrder, while some\r
+  are present but are not reflected by DriverOrder. Then a function\r
+  rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+  needed.\r
+\r
+  @retval  EFI_SUCCESS  The driver order is updated successfully.\r
+  @return               EFI_STATUS other than EFI_SUCCESS if failed to\r
+                                 Set the "DriverOrder" EFI Variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  BM_MENU_ENTRY *NewMenuEntry;\r
+  UINT16        *DriverOrderList;\r
+  UINT16        *DriverOrderListPtr;\r
+  UINTN         DriverOrderListSize;\r
+  UINTN         Index;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+    FreePool (DriverOrderList);\r
+    DriverOrderList = NULL;\r
+  }\r
+\r
+  DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
+\r
+  if (DriverOrderListSize > 0) {\r
+    DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
+    ASSERT (DriverOrderList != NULL);\r
+    DriverOrderListPtr = DriverOrderList;\r
+\r
+    //\r
+    // Get all current used Driver#### from DriverOptionMenu.\r
+    // OptionNumber in each BM_LOAD_OPTION is really its\r
+    // #### value.\r
+    //\r
+    for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+      NewMenuEntry      = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+      *DriverOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
+      DriverOrderList++;\r
+    }\r
+\r
+    DriverOrderList = DriverOrderListPtr;\r
+\r
+    //\r
+    // After building the DriverOrderList, write it back\r
+    //\r
+    Status = gRT->SetVariable (\r
+                    L"DriverOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    DriverOrderListSize * sizeof (UINT16),\r
+                    DriverOrderList\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update the device path of "ConOut", "ConIn" and "ErrOut" \r
+  based on the new BaudRate, Data Bits, parity and Stop Bits\r
+  set.\r
+\r
+**/\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+  VOID\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
+  EFI_STATUS                Status;\r
+\r
+  OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+  InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+  ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+  if (OutDevicePath != NULL) {\r
+    ChangeVariableDevicePath (OutDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (OutDevicePath),\r
+                    OutDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (InpDevicePath != NULL) {\r
+    ChangeVariableDevicePath (InpDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ConIn",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (InpDevicePath),\r
+                    InpDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+\r
+  if (ErrDevicePath != NULL) {\r
+    ChangeVariableDevicePath (ErrDevicePath);\r
+    Status = gRT->SetVariable (\r
+                    L"ErrOut",\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ErrDevicePath),\r
+                    ErrDevicePath\r
+                    );\r
+    ASSERT (!EFI_ERROR (Status));\r
+  }\r
+}\r
+\r
+/**\r
+  This function delete and build multi-instance device path for\r
+  specified type of console device.\r
+\r
+  This function clear the EFI variable defined by ConsoleName and\r
+  gEfiGlobalVariableGuid. It then build the multi-instance device\r
+  path by appending the device path of the Console (In/Out/Err) instance \r
+  in ConsoleMenu. Then it scan all corresponding console device by\r
+  scanning Terminal (built from device supporting Serial I/O instances)\r
+  devices in TerminalMenu. At last, it save a EFI variable specifed\r
+  by ConsoleName and gEfiGlobalVariableGuid.\r
+\r
+  @param ConsoleName     The name for the console device type. They are\r
+                         usually "ConIn", "ConOut" and "ErrOut".\r
+  @param ConsoleMenu     The console memu which is a list of console devices.\r
+  @param UpdatePageId    The flag specifying which type of console device\r
+                         to be processed.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOption (\r
+  IN UINT16                     *ConsoleName,\r
+  IN BM_MENU_OPTION             *ConsoleMenu,\r
+  IN UINT16                     UpdatePageId\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
+  BM_MENU_ENTRY             *NewMenuEntry;\r
+  BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
+  BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
+  EFI_STATUS                Status;\r
+  VENDOR_DEVICE_PATH        Vendor;\r
+  EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath;\r
+  UINTN                     Index;\r
+\r
+  ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+  if (ConDevicePath != NULL) {\r
+    EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+    FreePool (ConDevicePath);\r
+    ConDevicePath = NULL;\r
+  };\r
+\r
+  //\r
+  // First add all console input device from console input menu\r
+  //\r
+  for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+\r
+    NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (NewConsoleContext->IsActive) {\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        NewConsoleContext->DevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+    NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+        ((NewTerminalContext->IsConOut != 0)  && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+        ((NewTerminalContext->IsStdErr  != 0) && (UpdatePageId == FORM_CON_ERR_ID))\r
+        ) {\r
+      Vendor.Header.Type    = MESSAGING_DEVICE_PATH;\r
+      Vendor.Header.SubType = MSG_VENDOR_DP;\r
+      \r
+      ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0])));\r
+      CopyMem (\r
+        &Vendor.Guid,\r
+        &TerminalTypeGuid[NewTerminalContext->TerminalType],\r
+        sizeof (EFI_GUID)\r
+        );\r
+      SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+      TerminalDevicePath = AppendDevicePathNode (\r
+                            NewTerminalContext->DevicePath,\r
+                            (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+                            );\r
+      ASSERT (TerminalDevicePath != NULL);\r
+      ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
+      ConDevicePath = AppendDevicePathInstance (\r
+                        ConDevicePath,\r
+                        TerminalDevicePath\r
+                        );\r
+    }\r
+  }\r
+\r
+  if (ConDevicePath != NULL) {\r
+    Status = gRT->SetVariable (\r
+                    ConsoleName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    GetDevicePathSize (ConDevicePath),\r
+                    ConDevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  This function delete and build multi-instance device path ConIn\r
+  console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
+}\r
+\r
+/**\r
+  This function delete and build multi-instance device path ConOut\r
+  console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
+}\r
+\r
+/**\r
+  This function delete and build multi-instance device path ErrOut\r
+  console device.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.  \r
+**/\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+  VOID\r
+  )\r
+{\r
+  return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
+}\r
+\r
+/**\r
+  This function create a currently loaded Drive Option from \r
+  the BMM. It then appends this Driver Option to the end of \r
+  the "DriverOrder" list. It append this Driver Opotion to the end\r
+  of DriverOptionMenu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+  @param HiiHandle       The HII handle associated with the BMM formset.\r
+  @param DescriptionData The description of this driver option.\r
+  @param OptionalData    The optional load option.\r
+  @param ForceReconnect  If to force reconnect.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+  @retval EFI_SUCCESS          If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+  IN  BMM_CALLBACK_DATA         *CallbackData,\r
+  IN  EFI_HII_HANDLE            HiiHandle,\r
+  IN  UINT16                    *DescriptionData,\r
+  IN  UINT16                    *OptionalData,\r
+  IN  UINT8                     ForceReconnect\r
+  )\r
+{\r
+  UINT16          Index;\r
+  UINT16          *DriverOrderList;\r
+  UINT16          *NewDriverOrderList;\r
+  UINT16          DriverString[12];\r
+  UINTN           DriverOrderListSize;\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index             = BOpt_GetDriverOptionNumber ();\r
+  UnicodeSPrint (\r
+    DriverString,\r
+    sizeof (DriverString),\r
+    L"Driver%04x",\r
+    Index\r
+    );\r
+\r
+  if (*DescriptionData == 0x0000) {\r
+    StrCpy (DescriptionData, DriverString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
+  BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (*OptionalData != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (OptionalData);\r
+  }\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    FreePool (Buffer);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+\r
+  Ptr += sizeof (UINT16);\r
+  CopyMem (\r
+    Ptr,\r
+    DescriptionData,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      DriverOptionStrDepository\r
+                                      );\r
+  HiiLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    DriverOptionHelpStrDepository\r
+                                    );\r
+  HiiLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (\r
+      Ptr,\r
+      OptionalData,\r
+      StrSize (OptionalData)\r
+      );\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  DriverString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+  NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewDriverOrderList != NULL);\r
+  CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
+  NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
+  if (DriverOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize + sizeof (UINT16),\r
+                  NewDriverOrderList\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (DriverOrderList != NULL) {\r
+    FreePool (DriverOrderList);\r
+  }\r
+  DriverOrderList = NULL;\r
+  FreePool (NewDriverOrderList);\r
+  InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+  DriverOptionMenu.MenuNumber++;\r
+\r
+  *DescriptionData  = 0x0000;\r
+  *OptionalData     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function create a currently loaded Boot Option from \r
+  the BMM. It then appends this Boot Option to the end of \r
+  the "BootOrder" list. It also append this Boot Opotion to the end\r
+  of BootOptionMenu.\r
+\r
+  @param CallbackData    The BMM context data.\r
+  @param NvRamMap        The file explorer formset internal state.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation.\r
+  @retval EFI_SUCCESS          If function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+  IN  BMM_CALLBACK_DATA                   *CallbackData,\r
+  IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
+  )\r
+{\r
+  UINT16          *BootOrderList;\r
+  UINT16          *NewBootOrderList;\r
+  UINTN           BootOrderListSize;\r
+  UINT16          BootString[10];\r
+  VOID            *Buffer;\r
+  UINTN           BufferSize;\r
+  UINT8           *Ptr;\r
+  UINT16          Index;\r
+  BM_MENU_ENTRY   *NewMenuEntry;\r
+  BM_LOAD_CONTEXT *NewLoadContext;\r
+  BOOLEAN         OptionalDataExist;\r
+  EFI_STATUS      Status;\r
+\r
+  OptionalDataExist = FALSE;\r
+\r
+  Index = BOpt_GetBootOptionNumber () ;\r
+  UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
+\r
+  if (NvRamMap->DescriptionData[0] == 0x0000) {\r
+    StrCpy (NvRamMap->DescriptionData, BootString);\r
+  }\r
+\r
+  BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
+  BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+  if (NvRamMap->OptionalData[0] != 0x0000) {\r
+    OptionalDataExist = TRUE;\r
+    BufferSize += StrSize (NvRamMap->OptionalData);\r
+  }\r
+\r
+  Buffer = AllocateZeroPool (BufferSize);\r
+  if (NULL == Buffer) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+  if (NULL == NewMenuEntry) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  NewLoadContext->Deleted         = FALSE;\r
+  NewLoadContext->LoadOptionSize  = BufferSize;\r
+  Ptr = (UINT8 *) Buffer;\r
+  NewLoadContext->LoadOption = Ptr;\r
+  *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+  NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+  NewLoadContext->IsActive = TRUE;\r
+  NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+  Ptr += sizeof (UINT32);\r
+  *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+  NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+  Ptr += sizeof (UINT16);\r
+\r
+  CopyMem (\r
+    Ptr,\r
+    NvRamMap->DescriptionData,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
+  ASSERT (NewLoadContext->Description != NULL);\r
+\r
+  NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+  CopyMem (\r
+    NewLoadContext->Description,\r
+    (VOID *) Ptr,\r
+    StrSize (NvRamMap->DescriptionData)\r
+    );\r
+\r
+  Ptr += StrSize (NvRamMap->DescriptionData);\r
+  CopyMem (\r
+    Ptr,\r
+    CallbackData->LoadContext->FilePathList,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+  ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+  CopyMem (\r
+    NewLoadContext->FilePathList,\r
+    (VOID *) Ptr,\r
+    GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+    );\r
+\r
+  NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
+  NewMenuEntry->OptionNumber  = Index;\r
+  NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+                                      CallbackData,\r
+                                      BootOptionStrDepository\r
+                                      );\r
+  HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+  NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+                                    CallbackData,\r
+                                    BootOptionHelpStrDepository\r
+                                    );\r
+  HiiLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+  if (OptionalDataExist) {\r
+    Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+    CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  BootString,\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BufferSize,\r
+                  Buffer\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
+  ASSERT (NewBootOrderList != NULL);\r
+  CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
+  NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
+\r
+  if (BootOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+    FreePool (BootOrderList);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize + sizeof (UINT16),\r
+                  NewBootOrderList\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  FreePool (NewBootOrderList);\r
+  NewBootOrderList = NULL;\r
+  InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+  BootOptionMenu.MenuNumber++;\r
+\r
+  NvRamMap->DescriptionData[0]  = 0x0000;\r
+  NvRamMap->OptionalData[0]     = 0x0000;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function update the "BootNext" EFI Variable. If there is \r
+  no "BootNex" specified in BMM, this EFI Variable is deleted.\r
+  It also update the BMM context data specified the "BootNext"\r
+  vaule.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS    The function complete successfully.\r
+  @return                The EFI variable can be saved. See gRT->SetVariable \r
+                         for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  BM_MENU_ENTRY     *NewMenuEntry;\r
+  BM_LOAD_CONTEXT   *NewLoadContext;\r
+  BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
+  UINT16            Index;\r
+  EFI_STATUS        Status;\r
+\r
+  Status            = EFI_SUCCESS;\r
+  CurrentFakeNVMap  = &CallbackData->BmmFakeNvData;\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+    ASSERT (NULL != NewMenuEntry);\r
+\r
+    NewLoadContext              = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+    NewLoadContext->IsBootNext  = FALSE;\r
+  }\r
+\r
+  if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
+    EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  NewMenuEntry = BOpt_GetMenuEntry (\r
+                  &BootOptionMenu,\r
+                  CurrentFakeNVMap->BootNext\r
+                  );\r
+  ASSERT (NewMenuEntry != NULL);\r
+\r
+  NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+  Status = gRT->SetVariable (\r
+                  L"BootNext",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  sizeof (UINT16),\r
+                  &NewMenuEntry->OptionNumber\r
+                  );\r
+  NewLoadContext->IsBootNext              = TRUE;\r
+  CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function update the "BootOrder" EFI Variable based on\r
+  BMM Formset's NV map. It then refresh BootOptionMenu\r
+  with the new "BootOrder" list.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS             The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to complete the function.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *BootOrderList;\r
+  UINT16      *NewBootOrderList;\r
+  UINTN       BootOrderListSize;\r
+\r
+  BootOrderList     = NULL;\r
+  BootOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether BootOrder is present in current configuration\r
+  //\r
+  BootOrderList = BdsLibGetVariableAndSize (\r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOrderListSize\r
+                    );\r
+\r
+  NewBootOrderList = AllocateZeroPool (BootOrderListSize);\r
+  if (NewBootOrderList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // If exists, delete it to hold new BootOrder\r
+  //\r
+  if (BootOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+    FreePool (BootOrderList);\r
+  }\r
+\r
+  ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));\r
+  for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+    NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  BootOrderListSize,\r
+                  NewBootOrderList\r
+                  );\r
+  FreePool (NewBootOrderList);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BOpt_FreeMenu (&BootOptionMenu);\r
+  BOpt_GetBootOptions (CallbackData);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+  This function update the "DriverOrder" EFI Variable based on\r
+  BMM Formset's NV map. It then refresh DriverOptionMenu\r
+  with the new "DriverOrder" list.\r
+\r
+  @param CallbackData    The BMM context data.\r
+\r
+  @retval EFI_SUCCESS           The function complete successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Not enough memory to complete the function.\r
+  @return The EFI variable can not be saved. See gRT->SetVariable for detail return information.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT16      Index;\r
+  UINT16      *DriverOrderList;\r
+  UINT16      *NewDriverOrderList;\r
+  UINTN       DriverOrderListSize;\r
+\r
+  DriverOrderList     = NULL;\r
+  DriverOrderListSize = 0;\r
+\r
+  //\r
+  // First check whether DriverOrder is present in current configuration\r
+  //\r
+  DriverOrderList = BdsLibGetVariableAndSize (\r
+                      L"DriverOrder",\r
+                      &gEfiGlobalVariableGuid,\r
+                      &DriverOrderListSize\r
+                      );\r
+\r
+  NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
+\r
+  if (NewDriverOrderList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // If exists, delete it to hold new DriverOrder\r
+  //\r
+  if (DriverOrderList != NULL) {\r
+    EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+    FreePool (DriverOrderList);\r
+  }\r
+\r
+  ASSERT (DriverOrderListSize <= (sizeof (CallbackData->BmmFakeNvData.OptionOrder) / sizeof (CallbackData->BmmFakeNvData.OptionOrder[0])));\r
+  for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+    NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"DriverOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  VAR_FLAG,\r
+                  DriverOrderListSize,\r
+                  NewDriverOrderList\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  BOpt_FreeMenu (&DriverOptionMenu);\r
+  BOpt_GetDriverOptions (CallbackData);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update the legacy BBS boot option. L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable\r
+  is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid\r
+  is also updated.\r
+\r
+  @param CallbackData    The context data for BMM.\r
+\r
+  @return EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_NOT_FOUND         If L"LegacyDevOrder" and EfiLegacyDevOrderGuid EFI Variable can be found.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate memory resource\r
+**/\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  UINTN                       Index;\r
+  UINTN                       Index2;\r
+  VOID                        *BootOptionVar;\r
+  CHAR16                      VarName[100];\r
+  UINTN                       OptionSize;\r
+  UINT8                       *Ptr;\r
+  EFI_STATUS                  Status;\r
+  CHAR16                      DescString[100];\r
+  CHAR8                       DescAsciiString[100];\r
+  UINTN                       NewOptionSize;\r
+  UINT8                       *NewOptionPtr;\r
+  UINT8                       *TempPtr;\r
+  UINT32                      *Attribute;\r
+  BM_MENU_OPTION              *OptionMenu;\r
+  BM_LEGACY_DEVICE_CONTEXT    *LegacyDeviceContext;\r
+  UINT8                       *LegacyDev;\r
+  UINT8                       *VarData;\r
+  UINTN                       VarSize;\r
+  BM_MENU_ENTRY               *NewMenuEntry;\r
+  BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+  UINT8                       *OriginalPtr;\r
+  UINT8                       *DisMap;\r
+  UINTN                       Pos;\r
+  UINTN                       Bit;\r
+  UINT16                      *NewOrder;\r
+  UINT16                      Tmp;\r
+\r
+  LegacyDeviceContext = NULL;\r
+  DisMap              = NULL;\r
+  NewOrder            = NULL;\r
+\r
+  if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+    OptionMenu            = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+    LegacyDev             = CallbackData->BmmFakeNvData.LegacyFD;\r
+    CallbackData->BbsType = BBS_FLOPPY;\r
+  } else {\r
+    if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+      OptionMenu            = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+      LegacyDev             = CallbackData->BmmFakeNvData.LegacyHD;\r
+      CallbackData->BbsType = BBS_HARDDISK;\r
+    } else {\r
+      if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+        OptionMenu            = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+        LegacyDev             = CallbackData->BmmFakeNvData.LegacyCD;\r
+        CallbackData->BbsType = BBS_CDROM;\r
+      } else {\r
+        if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData.LegacyNET;\r
+          CallbackData->BbsType = BBS_EMBED_NETWORK;\r
+        } else {\r
+          OptionMenu            = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+          LegacyDev             = CallbackData->BmmFakeNvData.LegacyBEV;\r
+          CallbackData->BbsType = BBS_BEV_DEVICE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  DisMap  = CallbackData->BmmOldFakeNVData.DisableMap;\r
+  Status  = EFI_SUCCESS;\r
+\r
+  //\r
+  // Find the first device's context\r
+  // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
+  // because we just use it to fill the desc string, and user can not see the string in UI\r
+  //\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    NewMenuEntry        = BOpt_GetMenuEntry (OptionMenu, Index);\r
+    LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+    if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
+      DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Update the Variable "LegacyDevOrder"\r
+  //\r
+  VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
+                        VAR_LEGACY_DEV_ORDER,\r
+                        &EfiLegacyDevOrderGuid,\r
+                        &VarSize\r
+                        );\r
+\r
+  if (VarData == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  OriginalPtr = VarData;\r
+  DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+\r
+  while (VarData < VarData + VarSize) {\r
+    if (DevOrder->BbsType == CallbackData->BbsType) {\r
+      break;\r
+    }\r
+\r
+    VarData += sizeof (BBS_TYPE);\r
+    VarData += *(UINT16 *) VarData;\r
+    DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+  }\r
+\r
+  if (VarData >= VarData + VarSize) {\r
+    FreePool (OriginalPtr);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
+  if (NewOrder == NULL) {\r
+    FreePool (VarData);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+    if (0xFF == LegacyDev[Index]) {\r
+      break;\r
+    }\r
+\r
+    NewOrder[Index] = LegacyDev[Index];\r
+  }\r
+  //\r
+  // Only the enable/disable state of each boot device with same device type can be changed,\r
+  // so we can count on the index information in DevOrder.\r
+  // DisMap bit array is the only reliable source to check a device's en/dis state,\r
+  // so we use DisMap to set en/dis state of each item in NewOrder array\r
+  //\r
+  for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
+    Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
+    Tmp &= 0xFF;\r
+    Pos = Tmp / 8;\r
+    Bit = 7 - (Tmp % 8);\r
+    if ((DisMap[Pos] & (1 << Bit)) != 0) {\r
+      NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
+      Index++;\r
+    }\r
+  }\r
+\r
+  CopyMem (\r
+    (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
+    NewOrder,\r
+    DevOrder->Length - sizeof (UINT16)\r
+    );\r
+  FreePool (NewOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &EfiLegacyDevOrderGuid,\r
+                  VAR_FLAG,\r
+                  VarSize,\r
+                  OriginalPtr\r
+                  );\r
+\r
+  FreePool (OriginalPtr);\r
+\r
+  //\r
+  // Update Optional Data of Boot####\r
+  //\r
+  BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
+\r
+  if (BootOptionVar != NULL) {\r
+    CopyMem (\r
+      DescString,\r
+      LegacyDeviceContext->Description,\r
+      StrSize (LegacyDeviceContext->Description)\r
+      );\r
+\r
+       UnicodeStrToAsciiStr((CONST CHAR16*)&DescString, (CHAR8 *)&DescAsciiString);\r
+\r
+    NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +\r
+                    sizeof (BBS_BBS_DEVICE_PATH);\r
+    NewOptionSize += AsciiStrLen (DescAsciiString) +\r
+                    END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);\r
+\r
+    UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
+\r
+    Ptr       = BootOptionVar;\r
+\r
+    Attribute = (UINT32 *) Ptr;\r
+    *Attribute |= LOAD_OPTION_ACTIVE;\r
+    if (LegacyDev[0] == 0xFF) {\r
+      //\r
+      // Disable this legacy boot option\r
+      //\r
+      *Attribute &= ~LOAD_OPTION_ACTIVE;\r
+    }\r
+\r
+    Ptr += sizeof (UINT32);\r
+\r
+    Ptr += sizeof (UINT16);\r
+    Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+    NewOptionPtr = AllocateZeroPool (NewOptionSize);\r
+    if (NewOptionPtr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    TempPtr = NewOptionPtr;\r
+\r
+    //\r
+    // Attribute\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      BootOptionVar,\r
+      sizeof (UINT32)\r
+      );\r
+\r
+    TempPtr += sizeof (UINT32);\r
+\r
+    //\r
+    // BBS device path Length\r
+    //\r
+    *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +\r
+                         AsciiStrLen (DescAsciiString) +\r
+                         END_DEVICE_PATH_LENGTH);\r
+\r
+    TempPtr += sizeof (UINT16);\r
+\r
+    //\r
+    // Description string\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      DescString,\r
+      StrSize (DescString)\r
+      );\r
+\r
+    TempPtr += StrSize (DescString);\r
+\r
+    //\r
+    // BBS device path\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      Ptr,\r
+      sizeof (BBS_BBS_DEVICE_PATH)\r
+      );\r
+\r
+    CopyMem (\r
+      ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,\r
+      DescAsciiString,\r
+      AsciiStrSize (DescAsciiString)\r
+      );\r
+\r
+    SetDevicePathNodeLength (\r
+          (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,\r
+          sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)\r
+          );\r
+\r
+    TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);\r
+\r
+    //\r
+    // End node\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      EndDevicePath,\r
+      END_DEVICE_PATH_LENGTH\r
+      );\r
+    TempPtr += END_DEVICE_PATH_LENGTH;\r
+\r
+    //\r
+    // Now TempPtr point to optional data, i.e. Bbs Table\r
+    //\r
+    CopyMem (\r
+      TempPtr,\r
+      LegacyDeviceContext->BbsTable,\r
+      sizeof (BBS_TABLE)\r
+      );\r
+\r
+    //\r
+    // Now TempPtr point to BBS index\r
+    //\r
+    TempPtr += sizeof (BBS_TABLE);\r
+    *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
+\r
+    Status = gRT->SetVariable (\r
+                    VarName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    VAR_FLAG,\r
+                    NewOptionSize,\r
+                    NewOptionPtr\r
+                    );\r
+\r
+    FreePool (NewOptionPtr);\r
+    FreePool (BootOptionVar);\r
+  }\r
+\r
+  BOpt_GetBootOptions (CallbackData);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update the Text Mode of Console.\r
+\r
+  @param CallbackData  The context data for BMM.\r
+\r
+  @retval EFI_SUCCSS If the Text Mode of Console is updated.\r
+  @return Other value if the Text Mode of Console is not updated.\r
+\r
+**/\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+  IN BMM_CALLBACK_DATA            *CallbackData\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             Mode;\r
+  CONSOLE_OUT_MODE  ModeInfo;\r
+\r
+  Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
+\r
+  Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
+  if (EFI_ERROR(Status)) {\r
+    ModeInfo.Column = 80;\r
+    ModeInfo.Row = 25;\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_CON_OUT_MODE,\r
+                  &gEfiGenericPlatformVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  sizeof (CONSOLE_OUT_MODE),\r
+                  &ModeInfo\r
+                  );\r
+\r
+  return Status;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
new file mode 100644 (file)
index 0000000..a1612cd
--- /dev/null
@@ -0,0 +1,299 @@
+/** @file\r
+  The platform boot manager reference implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "BootManager.h"\r
+\r
+UINT16             mKeyInput;\r
+EFI_GUID           mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
+LIST_ENTRY         *mBootOptionsList;\r
+BDS_COMMON_OPTION  *gOption;\r
+\r
+BOOT_MANAGER_CALLBACK_DATA  gBootManagerPrivate = {\r
+  BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    BootManagerCallback\r
+  }\r
+};\r
+\r
+/**\r
+  This call back funtion is registered with Boot Manager formset.\r
+  When user selects a boot option, this call back function will\r
+  be triggered. The boot option is saved for later processing.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  BDS_COMMON_OPTION       *Option;\r
+  LIST_ENTRY              *Link;\r
+  UINT16                  KeyCount;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Initialize the key count\r
+  //\r
+  KeyCount = 0;\r
+\r
+  for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    KeyCount++;\r
+\r
+    gOption = Option;\r
+\r
+    //\r
+    // Is this device the one chosen?\r
+    //\r
+    if (KeyCount == QuestionId) {\r
+      //\r
+      // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+      //\r
+      mKeyInput = QuestionId;\r
+\r
+      //\r
+      // Request to exit SendForm(), so that we could boot the selected option\r
+      //\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+      break;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Registers HII packages for the Boot Manger to HII Database.\r
+  It also registers the browser call back function.\r
+\r
+  @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeBootManager (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gBootManagerPrivate.DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gBootManagerPrivate.ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  PackageList = HiiLibPreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gBootManagerPrivate.DriverHandle,\r
+                           &gBootManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This funtion invokees Boot Manager. If all devices have not a chance to be connected,\r
+  the connect all will be triggered. It then enumerate all boot options. If \r
+  a boot option from the Boot Manager page is selected, Boot Manager will boot\r
+  from this boot option.\r
+  \r
+**/\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  BDS_COMMON_OPTION           *Option;\r
+  LIST_ENTRY                  *Link;\r
+  EFI_HII_UPDATE_DATA         UpdateData;\r
+  CHAR16                      *ExitData;\r
+  UINTN                       ExitDataSize;\r
+  EFI_STRING_ID               Token;\r
+  EFI_INPUT_KEY               Key;\r
+  LIST_ENTRY                  BdsBootOptionList;\r
+  CHAR16                      *HelpString;\r
+  EFI_STRING_ID               HelpToken;\r
+  UINT16                      *TempStr;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+  UINTN                       TempSize;\r
+\r
+  gOption = NULL;\r
+  InitializeListHead (&BdsBootOptionList);\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+  //\r
+  // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+  // get the boot order every time from "BootOrder" variable.\r
+  // Recreate the boot option list base on the BootOrder variable\r
+  //\r
+  BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+  mBootOptionsList  = &BdsBootOptionList;\r
+\r
+  HiiHandle = gBootManagerPrivate.HiiHandle;\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData.BufferSize = 0x1000;\r
+  UpdateData.Offset = 0;\r
+  UpdateData.Data = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData.Data != NULL);\r
+\r
+  mKeyInput = 0;\r
+\r
+  for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+    Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+    //\r
+    // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+    //\r
+    mKeyInput++;\r
+\r
+    //\r
+    // Don't display the boot option marked as LOAD_OPTION_HIDDEN\r
+    //\r
+    if (Option->Attribute & LOAD_OPTION_HIDDEN) {\r
+      continue;\r
+    }\r
+\r
+    HiiLibNewString (HiiHandle, &Token, Option->Description);\r
+\r
+    TempStr = DevicePathToStr (Option->DevicePath);\r
+    TempSize = StrSize (TempStr);\r
+    HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
+    ASSERT (HelpString != NULL);\r
+    StrCat (HelpString, L"Device Path : ");\r
+    StrCat (HelpString, TempStr);\r
+\r
+    HiiLibNewString (HiiHandle, &HelpToken, HelpString);\r
+\r
+    CreateActionOpCode (\r
+      mKeyInput,\r
+      Token,\r
+      HelpToken,\r
+      EFI_IFR_FLAG_CALLBACK,\r
+      0,\r
+      &UpdateData\r
+      );\r
+  }\r
+\r
+  IfrLibUpdateForm (\r
+    HiiHandle,\r
+    &mBootManagerGuid,\r
+    BOOT_MANAGER_FORM_ID,\r
+    LABEL_BOOT_OPTION,\r
+    FALSE,\r
+    &UpdateData\r
+    );\r
+  FreePool (UpdateData.Data);\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                           gFormBrowser2,\r
+                           &HiiHandle,\r
+                           1,\r
+                           NULL,\r
+                           0,\r
+                           NULL,\r
+                           &ActionRequest\r
+                           );\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  if (gOption == NULL) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  SetupResetReminder ();\r
+\r
+  //\r
+  // parse the selected option\r
+  //\r
+  Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+    PlatformBdsBootSuccess (gOption);\r
+  } else {\r
+    gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+    PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+    gST->ConOut->OutputString (\r
+                  gST->ConOut,\r
+                  GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+                  );\r
+    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  }\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
new file mode 100644 (file)
index 0000000..4e46078
--- /dev/null
@@ -0,0 +1,108 @@
+/** @file\r
+  The platform boot manager reference implement\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _EFI_BOOT_MANAGER_H_\r
+#define _EFI_BOOT_MANAGER_H_\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define BOOT_MANAGER_FORMSET_GUID \\r
+  { \\r
+  0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \\r
+  }\r
+\r
+#define BOOT_MANAGER_FORM_ID     0x1000\r
+\r
+#define LABEL_BOOT_OPTION        0x00\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BootManagerVfrBin[];\r
+\r
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE  SIGNATURE_32 ('B', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  //\r
+  // HII relative handles\r
+  //\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+\r
+  //\r
+  // Produced protocols\r
+  //\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL   ConfigAccess;\r
+} BOOT_MANAGER_CALLBACK_DATA;\r
+\r
+/**\r
+  This call back funtion is registered with Boot Manager formset.\r
+  When user selects a boot option, this call back function will\r
+  be triggered. The boot option is saved for later processing.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+/**\r
+\r
+  Registers HII packages for the Boot Manger to HII Database.\r
+  It also registers the browser call back function.\r
+\r
+  @return Status of HiiLibCreateHiiDriverHandle() and gHiiDatabase->NewPackageList()\r
+**/\r
+EFI_STATUS\r
+InitializeBootManager (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This funtion invokees Boot Manager. If all devices have not a chance to be connected,\r
+  the connect all will be triggered. It then enumerate all boot options. If \r
+  a boot option from the Boot Manager page is selected, Boot Manager will boot\r
+  from this boot option.\r
+  \r
+**/\r
+VOID\r
+CallBootManager (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
new file mode 100644 (file)
index 0000000..5a29d53
Binary files /dev/null and b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..a70966c
--- /dev/null
@@ -0,0 +1,51 @@
+///** @file\r
+//  \r
+//    Browser formset.\r
+//  \r
+//  Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+//  All rights reserved. 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
+#define FORMSET_GUID  { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }\r
+\r
+#define BOOT_MANAGER_FORM_ID     0x1000\r
+\r
+#define LABEL_BOOT_OPTION        0x00\r
+#define LABEL_BOOT_OPTION_END    0x01\r
+\r
+#define BOOT_MANAGER_CLASS       0x00\r
+#define BOOT_MANAGER_SUBCLASS    0x00\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_BM_BANNER),\r
+  help     = STRING_TOKEN(STR_LAST_STRING),\r
+  class    = BOOT_MANAGER_CLASS,\r
+  subclass = BOOT_MANAGER_SUBCLASS,\r
+\r
+  form formid = BOOT_MANAGER_FORM_ID,\r
+       title  = STRING_TOKEN(STR_BM_BANNER);\r
+\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+    subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+\r
+    //\r
+    // This is where we will dynamically add choices for the Boot Manager\r
+    //\r
+    label LABEL_BOOT_OPTION;\r
+    label LABEL_BOOT_OPTION_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+    subtitle text = STRING_TOKEN(STR_HELP_FOOTER);\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Capsules.c
new file mode 100644 (file)
index 0000000..904a775
--- /dev/null
@@ -0,0 +1,257 @@
+/** @file\r
+  BDS routines to handle capsules.\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Bds.h"\r
+\r
+/**\r
+  This function locks the block \r
+\r
+  @param CpuIo           A instance of EFI_CPU_IO_PROTOCOL. \r
+  @param Base            The base address flash region to be locked.\r
+\r
+**/\r
+VOID\r
+BdsLockFv (\r
+  IN EFI_CPU_IO_PROTOCOL          *CpuIo,\r
+  IN EFI_PHYSICAL_ADDRESS         Base\r
+  )\r
+{\r
+  EFI_FV_BLOCK_MAP_ENTRY      *BlockMap;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  EFI_PHYSICAL_ADDRESS        BaseAddress;\r
+  UINT8                       Data;\r
+  UINT32                      BlockLength;\r
+  UINTN                       Index;\r
+\r
+  BaseAddress = Base - 0x400000 + 2;\r
+  FvHeader    = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));\r
+  BlockMap    = &(FvHeader->BlockMap[0]);\r
+\r
+  while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {\r
+    BlockLength = BlockMap->Length;\r
+    for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+      CpuIo->Mem.Read (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      Data = (UINT8) (Data | 0x3);\r
+      CpuIo->Mem.Write (\r
+                  CpuIo,\r
+                  EfiCpuIoWidthUint8,\r
+                  BaseAddress,\r
+                  1,\r
+                  &Data\r
+                  );\r
+      BaseAddress += BlockLength;\r
+    }\r
+\r
+    BlockMap++;\r
+  }\r
+}\r
+\r
+/**\r
+\r
+  This routine is called to see if there are any capsules we need to process.\r
+  If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
+  capsule HOBS and produce firmware volumes for them via the DXE service.\r
+  Then call the dispatcher to dispatch drivers from them. Finally, check\r
+  the status of the updates.\r
+\r
+  This function should be called by BDS in case we need to do some\r
+  sort of processing even if there is no capsule to process. We\r
+  need to do this if an earlier update went away and we need to\r
+  clear the capsule variable so on the next reset PEI does not see it and\r
+  think there is a capsule available.\r
+\r
+  @param BootMode                 the current boot mode\r
+\r
+  @retval EFI_INVALID_PARAMETER   boot mode is not correct for an update\r
+  @retval EFI_SUCCESS             There is no error when processing capsule\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessCapsules (\r
+  EFI_BOOT_MODE BootMode\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_PEI_HOB_POINTERS        HobPointer;\r
+  EFI_CAPSULE_HEADER          *CapsuleHeader;\r
+  UINT32                      Size;\r
+  UINT32                      CapsuleNumber;\r
+  UINT32                      CapsuleTotalNumber;\r
+  EFI_CAPSULE_TABLE           *CapsuleTable;\r
+  UINT32                      Index;\r
+  UINT32                      CacheIndex;\r
+  UINT32                      CacheNumber;\r
+  VOID                        **CapsulePtr;\r
+  VOID                        **CapsulePtrCache;\r
+  EFI_GUID                    *CapsuleGuidCache; \r
+  CAPSULE_HOB_INFO            *CapsuleHobInfo;\r
+\r
+  CapsuleNumber = 0;\r
+  CapsuleTotalNumber = 0;\r
+  CacheIndex   = 0;\r
+  CacheNumber  = 0;\r
+  CapsulePtr        = NULL;\r
+  CapsulePtrCache   = NULL;\r
+  CapsuleGuidCache  = NULL;\r
+\r
+  //\r
+  // We don't do anything else if the boot mode is not flash-update\r
+  //\r
+  if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  Status = EFI_SUCCESS;\r
+  //\r
+  // Find all capsule images from hob\r
+  //\r
+  HobPointer.Raw = GetHobList ();\r
+  while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+    CapsuleTotalNumber ++;\r
+\r
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+  }\r
+  \r
+  if (CapsuleTotalNumber == 0) {\r
+    //\r
+    // We didn't find a hob, so had no errors.\r
+    //\r
+    PlatformBdsLockNonUpdatableFlash ();\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // Init temp Capsule Data table.\r
+  //\r
+  CapsulePtr       = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+  ASSERT (CapsulePtr != NULL);\r
+  CapsulePtrCache  = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+  ASSERT (CapsulePtrCache != NULL);\r
+  CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
+  ASSERT (CapsuleGuidCache != NULL);\r
+  \r
+  //\r
+  // Find all capsule images from hob\r
+  //\r
+  HobPointer.Raw = GetHobList ();\r
+  while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+    CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);\r
+    CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);\r
+\r
+    HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+  }\r
+\r
+  //\r
+  //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
+  //capsuleTable to configure table with EFI_CAPSULE_GUID\r
+  //\r
+\r
+  //\r
+  // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
+  // System to have information persist across a system reset. EFI System Table must \r
+  // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
+  // searching for this type capsule will look in EFI System Table and search for the \r
+  // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
+  // how to sorting the capsules by the unique guid and install the array to EFI System Table. \r
+  // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an \r
+  // array for later sorting capsules by CapsuleGuid.\r
+  //\r
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+      //\r
+      // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
+      // If already has the Guid, skip it. Whereas, record it in the CacheArray as \r
+      // an additional one.\r
+      //\r
+      CacheIndex = 0;\r
+      while (CacheIndex < CacheNumber) {\r
+        if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
+          break;\r
+        }\r
+        CacheIndex++;\r
+      }\r
+      if (CacheIndex == CacheNumber) {\r
+        CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
+  // whose guid is the same as it, and malloc memory for an array which preceding\r
+  // with UINT32. The array fills with entry point of capsules that have the same\r
+  // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
+  // this array into EFI System Table, so that agents searching for this type capsule\r
+  // will look in EFI System Table and search for the capsule's Guid and associated\r
+  // pointer to retrieve the data.\r
+  //\r
+  CacheIndex = 0;\r
+  while (CacheIndex < CacheNumber) {\r
+    CapsuleNumber = 0;  \r
+    for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+      CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+      if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+        if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
+          //\r
+          // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
+          //\r
+          CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
+        }\r
+      }\r
+    }\r
+    if (CapsuleNumber != 0) {\r
+      Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);  \r
+      CapsuleTable = AllocateRuntimePool (Size);\r
+      ASSERT (CapsuleTable != NULL);\r
+      CapsuleTable->CapsuleArrayNumber =  CapsuleNumber;\r
+      CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
+      Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    CacheIndex++;\r
+  }\r
+\r
+  //\r
+  // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are\r
+  // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash \r
+  // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional\r
+  // type capsule transaction could be extended. It depends on platform policy.\r
+  //\r
+  for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+    CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+      //\r
+      // Call capsule library to process capsule image.\r
+      //\r
+      ProcessCapsuleImage (CapsuleHeader);\r
+    }\r
+  }\r
+\r
+  PlatformBdsLockNonUpdatableFlash ();\r
+  \r
+  //\r
+  // Free the allocated temp memory space.\r
+  //\r
+  FreePool (CapsuleGuidCache);\r
+  FreePool (CapsulePtrCache);\r
+  FreePool (CapsulePtr);\r
+\r
+  return Status;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
new file mode 100644 (file)
index 0000000..715e101
--- /dev/null
@@ -0,0 +1,409 @@
+/** @file\r
+  The platform device manager reference implementation\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "DeviceManager.h"\r
+\r
+DEVICE_MANAGER_CALLBACK_DATA  gDeviceManagerPrivate = {\r
+  DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    DeviceManagerCallback\r
+  }\r
+};\r
+\r
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
+\r
+DEVICE_MANAGER_MENU_ITEM  mDeviceManagerMenuItemTable[] = {\r
+  { STRING_TOKEN (STR_DISK_DEVICE),     EFI_DISK_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_VIDEO_DEVICE),    EFI_VIDEO_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_NETWORK_DEVICE),  EFI_NETWORK_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_INPUT_DEVICE),    EFI_INPUT_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
+  { STRING_TOKEN (STR_OTHER_DEVICE),    EFI_OTHER_DEVICE_CLASS }\r
+};\r
+\r
+#define MENU_ITEM_NUM  \\r
+  (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))\r
+\r
+/**\r
+  This function is invoked if user selected a iteractive opcode from Device Manager's\r
+  Formset. The decision by user is saved to gCallbackKey for later processing. If\r
+  user set VBIOS, the new value is saved to EFI variable.\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  DEVICE_MANAGER_CALLBACK_DATA *PrivateData;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+  switch (QuestionId) {\r
+  case DEVICE_MANAGER_KEY_VBIOS:\r
+    PrivateData->VideoBios = Value->u8;\r
+    gRT->SetVariable (\r
+           L"VBIOS",\r
+           &gEfiGenericPlatformVariableGuid,\r
+           EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+           sizeof (UINT8),\r
+           &PrivateData->VideoBios\r
+           );\r
+\r
+    //\r
+    // Tell browser not to ask for confirmation of changes,\r
+    // since we have already applied.\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+    break;\r
+\r
+  default:\r
+    //\r
+    // The key corresponds the Handle Index which was requested to be displayed\r
+    //\r
+    gCallbackKey = QuestionId;\r
+\r
+    //\r
+    // Request to exit SendForm(), so as to switch to selected form\r
+    //\r
+    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  This function registers HII packages to HII database.\r
+\r
+  @retval EFI_SUCCESS This function complete successfully.\r
+  @return Other value if failed to register HII packages.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install Config Access protocol to driver handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &gDeviceManagerPrivate.DriverHandle,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &gDeviceManagerPrivate.ConfigAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gDeviceManagerPrivate.DriverHandle,\r
+                           &gDeviceManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Call the browser and display the device manager to allow user\r
+  to configure the platform.\r
+\r
+  This function create the dynamic content for device manager. It includes\r
+  section header for all class of devices, one-of opcode to set VBIOS.\r
+  \r
+  @retval  EFI_SUCCESS             Operation is successful.\r
+  @return  Other values if failed to clean up the dynamic content from HII\r
+           database.\r
+\r
+**/\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       Count;\r
+  UINTN                       Index;\r
+  CHAR16                      *String;\r
+  UINTN                       StringLength;\r
+  EFI_HII_UPDATE_DATA         UpdateData[MENU_ITEM_NUM];\r
+  EFI_STRING_ID               Token;\r
+  EFI_STRING_ID               TokenHelp;\r
+  IFR_OPTION                  *IfrOptionList;\r
+  UINT8                       *VideoOption;\r
+  UINTN                       VideoOptionSize;\r
+  EFI_HII_HANDLE              *HiiHandles;\r
+  UINTN                       HandleBufferLength;\r
+  UINTN                       NumberOfHiiHandles;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+  UINT16                      FormSetClass;\r
+  EFI_STRING_ID               FormSetTitle;\r
+  EFI_STRING_ID               FormSetHelp;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+  IfrOptionList       = NULL;\r
+  VideoOption         = NULL;\r
+  HiiHandles          = NULL;\r
+  HandleBufferLength  = 0;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  gCallbackKey  = 0;\r
+\r
+  //\r
+  // Connect all prior to entering the platform setup menu.\r
+  //\r
+  if (!gConnectAllHappened) {\r
+    BdsLibConnectAllDriversToAllControllers ();\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+\r
+  //\r
+  // Create Subtitle OpCodes\r
+  //\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    //\r
+    // Allocate space for creation of UpdateData Buffer\r
+    //\r
+    UpdateData[Index].BufferSize = 0x1000;\r
+    UpdateData[Index].Offset = 0;\r
+    UpdateData[Index].Data = AllocatePool (0x1000);\r
+    ASSERT (UpdateData[Index].Data != NULL);\r
+\r
+    CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1,  &UpdateData[Index]);\r
+  }\r
+\r
+  //\r
+  // Get all the Hii handles\r
+  //\r
+  Status = HiiLibGetHiiHandles (&HandleBufferLength, &HiiHandles);\r
+  ASSERT_EFI_ERROR (Status && (HiiHandles != NULL));\r
+\r
+  HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
+\r
+  StringLength  = 0x1000;\r
+  String        = AllocateZeroPool (StringLength);\r
+  ASSERT (String != NULL);\r
+\r
+  //\r
+  // Search for formset of each class type\r
+  //\r
+  NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+  for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+    IfrLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);\r
+\r
+    if (FormSetClass == EFI_NON_DEVICE_CLASS) {\r
+      continue;\r
+    }\r
+\r
+    Token = 0;\r
+    *String = 0;\r
+    StringLength = 0x1000;\r
+    HiiLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);\r
+    HiiLibNewString (HiiHandle, &Token, String);\r
+\r
+    TokenHelp = 0;\r
+    *String = 0;\r
+    StringLength = 0x1000;\r
+    HiiLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);\r
+    HiiLibNewString (HiiHandle, &TokenHelp, String);\r
+\r
+    for (Count = 0; Count < MENU_ITEM_NUM; Count++) {\r
+      if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {\r
+        CreateActionOpCode (\r
+          (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),\r
+          Token,\r
+          TokenHelp,\r
+          EFI_IFR_FLAG_CALLBACK,\r
+          0,\r
+          &UpdateData[Count]\r
+          );\r
+      }\r
+    }\r
+  }\r
+  FreePool (String);\r
+\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    //\r
+    // Add End Opcode for Subtitle\r
+    //\r
+    CreateEndOpCode (&UpdateData[Index]);\r
+\r
+    IfrLibUpdateForm (\r
+      HiiHandle,\r
+      &mDeviceManagerGuid,\r
+      DEVICE_MANAGER_FORM_ID,\r
+      mDeviceManagerMenuItemTable[Index].Class,\r
+      FALSE,\r
+      &UpdateData[Index]\r
+      );\r
+  }\r
+\r
+  //\r
+  // Add oneof for video BIOS selection\r
+  //\r
+  VideoOption = BdsLibGetVariableAndSize (\r
+                  L"VBIOS",\r
+                  &gEfiGenericPlatformVariableGuid,\r
+                  &VideoOptionSize\r
+                  );\r
+  if (VideoOption == NULL) {\r
+    gDeviceManagerPrivate.VideoBios = 0;\r
+  } else {\r
+    gDeviceManagerPrivate.VideoBios = VideoOption[0];\r
+    FreePool (VideoOption);\r
+  }\r
+\r
+  ASSERT (gDeviceManagerPrivate.VideoBios <= 1);\r
+\r
+  IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+  ASSERT (IfrOptionList != NULL);\r
+  IfrOptionList[0].Flags        = 0;\r
+  IfrOptionList[0].StringToken  = STRING_TOKEN (STR_ONE_OF_PCI);\r
+  IfrOptionList[0].Value.u8     = 0;\r
+  IfrOptionList[1].Flags        = 0;\r
+  IfrOptionList[1].StringToken  = STRING_TOKEN (STR_ONE_OF_AGP);\r
+  IfrOptionList[1].Value.u8     = 1;\r
+  IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+\r
+  UpdateData[0].Offset = 0;\r
+  CreateOneOfOpCode (\r
+    DEVICE_MANAGER_KEY_VBIOS,\r
+    0,\r
+    0,\r
+    STRING_TOKEN (STR_ONE_OF_VBIOS),\r
+    STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    IfrOptionList,\r
+    2,\r
+    &UpdateData[0]\r
+    );\r
+\r
+  IfrLibUpdateForm (\r
+    HiiHandle,\r
+    &mDeviceManagerGuid,\r
+    DEVICE_MANAGER_FORM_ID,\r
+    LABEL_VBIOS,\r
+    FALSE,\r
+    &UpdateData[0]\r
+    );\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                           gFormBrowser2,\r
+                           &HiiHandle,\r
+                           1,\r
+                           NULL,\r
+                           0,\r
+                           NULL,\r
+                           &ActionRequest\r
+                           );\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  //\r
+  // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+  // a target to display\r
+  //\r
+  if (gCallbackKey != 0) {\r
+    ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+    Status = gFormBrowser2->SendForm (\r
+                             gFormBrowser2,\r
+                             &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
+                             1,\r
+                             NULL,\r
+                             0,\r
+                             NULL,\r
+                             &ActionRequest\r
+                             );\r
+\r
+    if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+      EnableResetRequired ();\r
+    }\r
+\r
+    //\r
+    // Force return to Device Manager\r
+    //\r
+    gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+  }\r
+\r
+  //\r
+  // Cleanup dynamic created strings in HII database by reinstall the packagelist\r
+  //\r
+  gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+  PackageList = HiiLibPreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           gDeviceManagerPrivate.DriverHandle,\r
+                           &gDeviceManagerPrivate.HiiHandle\r
+                           );\r
+  FreePool (PackageList);\r
+\r
+  for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+    FreePool (UpdateData[Index].Data);\r
+  }\r
+  FreePool (HiiHandles);\r
+\r
+  return Status;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
new file mode 100644 (file)
index 0000000..23809dd
--- /dev/null
@@ -0,0 +1,134 @@
+/** @file\r
+  The platform device manager reference implement\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _DEVICE_MANAGER_H_\r
+#define _DEVICE_MANAGER_H_\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define DEVICE_MANAGER_FORMSET_GUID  \\r
+  { \\r
+  0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \\r
+  }\r
+\r
+#define LABEL_VBIOS                          0x0040\r
+\r
+#define DEVICE_MANAGER_FORM_ID               0x1000\r
+\r
+#define DEVICE_KEY_OFFSET                    0x1000\r
+#define DEVICE_MANAGER_KEY_VBIOS             0x2000\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8  DeviceManagerVfrBin[];\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE  SIGNATURE_32 ('D', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  ///\r
+  /// HII relative handles\r
+  ///\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+\r
+  ///\r
+  /// Produced protocols\r
+  ///\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;\r
+\r
+  ///\r
+  /// Configuration data\r
+  ///\r
+  UINT8                           VideoBios;\r
+} DEVICE_MANAGER_CALLBACK_DATA;\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      DEVICE_MANAGER_CALLBACK_DATA, \\r
+      ConfigAccess, \\r
+      DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \\r
+      )\r
+typedef struct {\r
+  EFI_STRING_ID  StringId;\r
+  UINT16         Class;\r
+} DEVICE_MANAGER_MENU_ITEM;\r
+\r
+/**\r
+  This function is invoked if user selected a iteractive opcode from Device Manager's\r
+  Formset. The decision by user is saved to gCallbackKey for later processing. If\r
+  user set VBIOS, the new value is saved to EFI variable.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+/**\r
+\r
+  This function registers HII packages to HII database.\r
+\r
+  @retval EFI_SUCCESS This function complete successfully.\r
+  @return Other value if failed to register HII packages.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  Call the browser and display the device manager to allow user\r
+  to configure the platform.\r
+\r
+  This function create the dynamic content for device manager. It includes\r
+  section header for all class of devices, one-of opcode to set VBIOS.\r
+  \r
+  @retval  EFI_SUCCESS             Operation is successful.\r
+  @retval  Other values if failed to clean up the dynamic content from HII\r
+           database.\r
+\r
+**/\r
+EFI_STATUS\r
+CallDeviceManager (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
new file mode 100644 (file)
index 0000000..8cc4db2
Binary files /dev/null and b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
new file mode 100644 (file)
index 0000000..14cafd4
--- /dev/null
@@ -0,0 +1,74 @@
+///** @file\r
+//  \r
+//    Device Manager formset.\r
+//  \r
+//  Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+//  All rights reserved. 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
+#define FORMSET_GUID  { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }\r
+\r
+#define EFI_DISK_DEVICE_CLASS              0x0001\r
+#define EFI_VIDEO_DEVICE_CLASS             0x0002\r
+#define EFI_NETWORK_DEVICE_CLASS           0x0004\r
+#define EFI_INPUT_DEVICE_CLASS             0x0008\r
+#define EFI_ON_BOARD_DEVICE_CLASS          0x0010\r
+#define EFI_OTHER_DEVICE_CLASS             0x0020\r
+#define LABEL_VBIOS                        0x0040\r
+\r
+#define LABEL_END                          0xffff\r
+\r
+#define DEVICE_MANAGER_CLASS               0x0000\r
+#define FRONT_PAGE_SUBCLASS                       0x0003\r
+\r
+#define DEVICE_MANAGER_FORM_ID             0x1000\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),\r
+  help     = STRING_TOKEN(STR_EMPTY_STRING),\r
+  class    = DEVICE_MANAGER_CLASS,\r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = DEVICE_MANAGER_FORM_ID,\r
+       title  = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);\r
+\r
+    //\r
+    // This is where devices get added to the device manager hierarchy\r
+    //\r
+    label EFI_DISK_DEVICE_CLASS;\r
+//    label LABEL_END;  // Since next opcode is a label, so this one could be omitted to save code size\r
+\r
+    label EFI_VIDEO_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_NETWORK_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_INPUT_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_ON_BOARD_DEVICE_CLASS;\r
+//    label LABEL_END;\r
+\r
+    label EFI_OTHER_DEVICE_CLASS;\r
+    label LABEL_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+\r
+    label LABEL_VBIOS;\r
+    label LABEL_END;\r
+\r
+    subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+    subtitle text = STRING_TOKEN(STR_EXIT_STRING);\r
+\r
+  endform;\r
+endformset;\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.c
new file mode 100644 (file)
index 0000000..44a1e08
--- /dev/null
@@ -0,0 +1,976 @@
+/** @file\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID  mFrontPageGuid      = FRONT_PAGE_FORMSET_GUID;\r
+\r
+BOOLEAN   gConnectAllHappened = FALSE;\r
+UINTN     gCallbackKey;\r
+\r
+EFI_HII_DATABASE_PROTOCOL       *gHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL         *gHiiString;\r
+EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+FRONT_PAGE_CALLBACK_DATA  gFrontPagePrivate = {\r
+  FRONT_PAGE_CALLBACK_DATA_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    FakeExtractConfig,\r
+    FakeRouteConfig,\r
+    FrontPageCallback\r
+  }\r
+};\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Request         A null-terminated Unicode string in <ConfigRequest> format.\r
+  @param Progress        On return, points to a character in the Request string.\r
+                         Points to the string's null terminator if request was successful.\r
+                         Points to the most recent '&' before the first failing name/value\r
+                         pair (or the beginning of the string if the failure is in the\r
+                         first name/value pair) if the request was not successful.\r
+  @param Results         A null-terminated Unicode string in <ConfigAltResp> format which\r
+                         has all values filled in for the names in the Request string.\r
+                         String to be allocated by the called function.\r
+\r
+  @retval  EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Configuration   A null-terminated Unicode string in <ConfigResp> format.\r
+  @param Progress        A pointer to a string filled in with the offset of the most\r
+                         recent '&' before the first failing name/value pair (or the\r
+                         beginning of the string if the failure is in the first\r
+                         name/value pair) or the terminating NULL if all was successful.\r
+\r
+  @retval  EFI_SUCCESS            The Results is processed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+\r
+  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          Specifies the type of action taken by the browser.\r
+  @param QuestionId      A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            The type of value for the question.\r
+  @param Value           A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.\r
+  @retval  EFI_DEVICE_ERROR      The variable could not be saved.\r
+  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  CHAR8                         *LanguageString;\r
+  CHAR8                         *LangCode;\r
+  CHAR8                         Lang[RFC_3066_ENTRY_SIZE];\r
+  CHAR8                         OldLang[ISO_639_2_ENTRY_SIZE];\r
+  UINTN                         Index;\r
+  EFI_STATUS                    Status;\r
+\r
+  if ((Value == NULL) || (ActionRequest == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  gCallbackKey = QuestionId;\r
+\r
+  //\r
+  // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+  // describe to their customers in documentation how to find their setup information (namely\r
+  // under the device manager and specific buckets)\r
+  //\r
+  switch (QuestionId) {\r
+  case FRONT_PAGE_KEY_CONTINUE:\r
+    //\r
+    // This is the continue - clear the screen and return an error to get out of FrontPage loop\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_LANGUAGE:\r
+    //\r
+    // Collect the languages from what our current Language support is based on our VFR\r
+    //\r
+    LanguageString = HiiLibGetSupportedLanguages (gFrontPagePrivate.HiiHandle);\r
+    ASSERT (LanguageString != NULL);\r
+\r
+    Index = 0;\r
+    LangCode = LanguageString;\r
+    while (*LangCode != 0) {\r
+      HiiLibGetNextLanguage (&LangCode, Lang);\r
+\r
+      if (Index == Value->u8) {\r
+        break;\r
+      }\r
+\r
+      Index++;\r
+    }\r
+\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (Lang),\r
+                    Lang\r
+                    );\r
+\r
+    if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+      //\r
+      // Set UEFI deprecated variable "Lang" for backwards compatibility\r
+      //\r
+      Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = gRT->SetVariable (\r
+                        L"Lang",\r
+                        &gEfiGlobalVariableGuid,\r
+                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                        ISO_639_2_ENTRY_SIZE,\r
+                        OldLang\r
+                        );\r
+      }\r
+    }\r
+\r
+    FreePool (LanguageString);\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+    //\r
+    // Boot Manager\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+    //\r
+    // Device Manager\r
+    //\r
+    break;\r
+\r
+  case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+    //\r
+    // Boot Maintenance Manager\r
+    //\r
+    break;\r
+\r
+  default:\r
+    gCallbackKey = 0;\r
+    break;\r
+  }\r
+\r
+  *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize HII information for the FrontPage\r
+\r
+\r
+  @param InitializeHiiData    TRUE if HII elements need to be initialized.\r
+\r
+  @retval  EFI_SUCCESS        The operation is successful.\r
+  @retval  EFI_DEVICE_ERROR   If the dynamic opcode creation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  IN BOOLEAN                         InitializeHiiData\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+  EFI_HII_UPDATE_DATA         UpdateData;\r
+  IFR_OPTION                  *OptionList;\r
+  CHAR8                       *LanguageString;\r
+  CHAR8                       *LangCode;\r
+  CHAR8                       Lang[RFC_3066_ENTRY_SIZE];\r
+  CHAR8                       CurrentLang[RFC_3066_ENTRY_SIZE];\r
+  UINTN                       OptionCount;\r
+  EFI_STRING_ID               Token;\r
+  CHAR16                      *StringBuffer;\r
+  UINTN                       BufferSize;\r
+  UINTN                       Index;\r
+  EFI_HII_HANDLE              HiiHandle;\r
+\r
+  if (InitializeHiiData) {\r
+    //\r
+    // Initialize the Device Manager\r
+    //\r
+    InitializeDeviceManager ();\r
+\r
+    //\r
+    // Initialize the Device Manager\r
+    //\r
+    InitializeBootManager ();\r
+\r
+    gCallbackKey  = 0;\r
+\r
+    //\r
+    // Locate Hii relative protocols\r
+    //\r
+    Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Create driver handle used by HII database\r
+    //\r
+    Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Install Config Access protocol to driver handle\r
+    //\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &gFrontPagePrivate.DriverHandle,\r
+                    &gEfiHiiConfigAccessProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    &gFrontPagePrivate.ConfigAccess\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Publish our HII data\r
+    //\r
+    PackageList = HiiLibPreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsDxeStrings);\r
+    ASSERT (PackageList != NULL);\r
+\r
+    Status = gHiiDatabase->NewPackageList (\r
+                             gHiiDatabase,\r
+                             PackageList,\r
+                             gFrontPagePrivate.DriverHandle,\r
+                             &gFrontPagePrivate.HiiHandle\r
+                             );\r
+    FreePool (PackageList);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Get current language setting\r
+  //\r
+  GetCurrentLanguage (CurrentLang);\r
+\r
+  //\r
+  // Allocate space for creation of UpdateData Buffer\r
+  //\r
+  UpdateData.BufferSize = 0x1000;\r
+  UpdateData.Data = AllocateZeroPool (0x1000);\r
+  ASSERT (UpdateData.Data != NULL);\r
+\r
+  OptionList = AllocateZeroPool (0x1000);\r
+  ASSERT (OptionList != NULL);\r
+\r
+  //\r
+  // Collect the languages from what our current Language support is based on our VFR\r
+  //\r
+  HiiHandle = gFrontPagePrivate.HiiHandle;\r
+  LanguageString = HiiLibGetSupportedLanguages (HiiHandle);\r
+  ASSERT (LanguageString != NULL);\r
+\r
+  OptionCount = 0;\r
+  LangCode = LanguageString;\r
+  while (*LangCode != 0) {\r
+    HiiLibGetNextLanguage (&LangCode, Lang);\r
+\r
+    if (gFrontPagePrivate.LanguageToken == NULL) {\r
+      //\r
+      // Get Language Name from String Package. The StringId of Printable Language\r
+      // Name is always 1 which is generated by StringGather Tool.\r
+      //\r
+      BufferSize = 0x100;\r
+      StringBuffer = AllocatePool (BufferSize);\r
+      Status = gHiiString->GetString (\r
+                           gHiiString,\r
+                           Lang,\r
+                           HiiHandle,\r
+                           PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+                           StringBuffer,\r
+                           &BufferSize,\r
+                           NULL\r
+                           );\r
+      if (Status == EFI_BUFFER_TOO_SMALL) {\r
+        FreePool (StringBuffer);\r
+        StringBuffer = AllocatePool (BufferSize);\r
+        Status = gHiiString->GetString (\r
+                             gHiiString,\r
+                             Lang,\r
+                             HiiHandle,\r
+                             PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+                             StringBuffer,\r
+                             &BufferSize,\r
+                             NULL\r
+                             );\r
+      }\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Token = 0;\r
+      Status = HiiLibNewString (HiiHandle, &Token, StringBuffer);\r
+      FreePool (StringBuffer);\r
+    } else {\r
+      Token = gFrontPagePrivate.LanguageToken[OptionCount];\r
+    }\r
+\r
+    if (AsciiStrCmp (Lang, CurrentLang) == 0) {\r
+      OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;\r
+    } else {\r
+      OptionList[OptionCount].Flags = 0;\r
+    }\r
+    OptionList[OptionCount].StringToken = Token;\r
+    OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;\r
+\r
+    OptionCount++;\r
+  }\r
+\r
+  FreePool (LanguageString);\r
+\r
+  UpdateData.Offset = 0;\r
+  CreateOneOfOpCode (\r
+    FRONT_PAGE_KEY_LANGUAGE,\r
+    0,\r
+    0,\r
+    STRING_TOKEN (STR_LANGUAGE_SELECT),\r
+    STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),\r
+    EFI_IFR_FLAG_CALLBACK,\r
+    EFI_IFR_NUMERIC_SIZE_1,\r
+    OptionList,\r
+    OptionCount,\r
+    &UpdateData\r
+    );\r
+\r
+  Status = IfrLibUpdateForm (\r
+             HiiHandle,\r
+             &mFrontPageGuid,\r
+             FRONT_PAGE_FORM_ID,\r
+             LABEL_SELECT_LANGUAGE,\r
+             FALSE,\r
+             &UpdateData\r
+             );\r
+\r
+  //\r
+  // Save the string Id for each language\r
+  //\r
+  gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));\r
+  ASSERT (gFrontPagePrivate.LanguageToken != NULL);\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;\r
+  }\r
+\r
+  FreePool (UpdateData.Data);\r
+  FreePool (OptionList);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Call the browser and display the front page\r
+\r
+  @return   Status code that will be returned by\r
+            EFI_FORM_BROWSER2_PROTOCOL.SendForm ().\r
+\r
+**/\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+\r
+  //\r
+  // Begin waiting for USER INPUT\r
+  //\r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)\r
+    );\r
+\r
+  ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+  Status = gFormBrowser2->SendForm (\r
+                            gFormBrowser2,\r
+                            &gFrontPagePrivate.HiiHandle,\r
+                            1,\r
+                            NULL,\r
+                            0,\r
+                            NULL,\r
+                            &ActionRequest\r
+                            );\r
+  //\r
+  // Check whether user  change any option setting which needs a reset to be effective\r
+  //\r
+  if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+    EnableResetRequired ();\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Acquire the string associated with the ProducerGuid and return it.\r
+\r
+\r
+  @param ProducerGuid    The Guid to search the HII database for\r
+  @param Token           The token value of the string to extract\r
+  @param String          The string that is extracted\r
+\r
+  @retval  EFI_SUCCESS  The function returns EFI_SUCCESS always.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProducerString (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      EFI_STRING_ID             Token,\r
+  OUT     CHAR16                    **String\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+\r
+  Status = HiiLibGetStringFromToken (ProducerGuid, Token, String);\r
+  if (EFI_ERROR (Status)) {\r
+    *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert Processor Frequency Data to a string\r
+\r
+  @param ProcessorFrequency The frequency data to process\r
+  @param String             The string that is created\r
+\r
+**/\r
+VOID\r
+ConvertProcessorToString (\r
+  IN  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,\r
+  OUT CHAR16                            **String\r
+  )\r
+{\r
+  CHAR16  *StringBuffer;\r
+  UINTN   Index;\r
+  UINT32  FreqMhz;\r
+\r
+  if (ProcessorFrequency->Exponent >= 6) {\r
+    FreqMhz = ProcessorFrequency->Value;\r
+    for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {\r
+      FreqMhz *= 10;\r
+    }\r
+  } else {\r
+    FreqMhz = 0;\r
+  }\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);\r
+  StrCat (StringBuffer, L".");\r
+  UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);\r
+  StrCat (StringBuffer, L" GHz");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Convert Memory Size to a string.\r
+\r
+  @param MemorySize      The size of the memory to process\r
+  @param String          The string that is created\r
+\r
+**/\r
+VOID\r
+ConvertMemorySizeToString (\r
+  IN  UINT32          MemorySize,\r
+  OUT CHAR16          **String\r
+  )\r
+{\r
+  CHAR16  *StringBuffer;\r
+\r
+  StringBuffer = AllocateZeroPool (0x20);\r
+  ASSERT (StringBuffer != NULL);\r
+  UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);\r
+  StrCat (StringBuffer, L" MB RAM");\r
+\r
+  *String = (CHAR16 *) StringBuffer;\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Update the banner information for the Front Page based on DataHub information.\r
+\r
+**/\r
+VOID\r
+UpdateFrontPageStrings (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_STRING_ID                     TokenToUpdate;\r
+  CHAR16                            *NewString;\r
+  UINT64                            MonotonicCount;\r
+  EFI_DATA_HUB_PROTOCOL             *DataHub;\r
+  EFI_DATA_RECORD_HEADER            *Record;\r
+  EFI_SUBCLASS_TYPE1_HEADER         *DataHeader;\r
+  EFI_MISC_BIOS_VENDOR_DATA         *BiosVendor;\r
+  EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;\r
+  EFI_PROCESSOR_VERSION_DATA        *ProcessorVersion;\r
+  EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;\r
+  EFI_MEMORY_ARRAY_START_ADDRESS_DATA    *MemoryArray;\r
+  BOOLEAN                           Find[5];\r
+\r
+  ZeroMem (Find, sizeof (Find));\r
+\r
+  //\r
+  // Update Front Page strings\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiDataHubProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &DataHub\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  MonotonicCount  = 0;\r
+  Record          = NULL;\r
+  do {\r
+    Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
+    if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+      DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)\r
+          ) {\r
+        BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);\r
+        HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[0] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)\r
+          ) {\r
+        SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);\r
+        HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[1] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+          (DataHeader->RecordType == ProcessorVersionRecordType)\r
+          ) {\r
+        ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);\r
+        GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);\r
+        HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[2] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+          (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
+          ) {\r
+        ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);\r
+        ConvertProcessorToString (ProcessorFrequency, &NewString);\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);\r
+        HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[3] = TRUE;\r
+      }\r
+\r
+      if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&\r
+          (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
+          ) {\r
+        MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);\r
+        ConvertMemorySizeToString (\r
+          (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),\r
+          &NewString\r
+          );\r
+        TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);\r
+        HiiLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+        FreePool (NewString);\r
+        Find[4] = TRUE;\r
+      }\r
+    }\r
+  } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+  @param Event              The event to wait for\r
+  @param Timeout            An optional timeout value in 100 ns units.\r
+\r
+  @retval  EFI_SUCCESS      Event fired before Timeout expired.\r
+  @retval  EFI_TIME_OUT     Timout expired before Event fired..\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForSingleEvent (\r
+  IN EFI_EVENT                  Event,\r
+  IN UINT64                     Timeout OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  EFI_EVENT   TimerEvent;\r
+  EFI_EVENT   WaitList[2];\r
+\r
+  if (Timeout != 0) {\r
+    //\r
+    // Create a timer event\r
+    //\r
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Set the timer event\r
+      //\r
+      gBS->SetTimer (\r
+            TimerEvent,\r
+            TimerRelative,\r
+            Timeout\r
+            );\r
+\r
+      //\r
+      // Wait for the original event or the timer\r
+      //\r
+      WaitList[0] = Event;\r
+      WaitList[1] = TimerEvent;\r
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);\r
+      gBS->CloseEvent (TimerEvent);\r
+\r
+      //\r
+      // If the timer expired, change the return to timed out\r
+      //\r
+      if (!EFI_ERROR (Status) && Index == 1) {\r
+        Status = EFI_TIMEOUT;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // No timeout... just wait on the event\r
+    //\r
+    Status = gBS->WaitForEvent (1, &Event, &Index);\r
+    ASSERT (!EFI_ERROR (Status));\r
+    ASSERT (Index == 0);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Function show progress bar to wait for user input.\r
+\r
+\r
+  @param TimeoutDefault  The fault time out value before the system continue to boot.\r
+\r
+  @retval  EFI_SUCCESS       User pressed some key except "Enter"\r
+  @retval  EFI_TIME_OUT      Timout expired or user press "Enter"\r
+\r
+**/\r
+EFI_STATUS\r
+ShowProgress (\r
+  IN UINT16                       TimeoutDefault\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  CHAR16                        *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+  EFI_INPUT_KEY                 Key;\r
+  UINT16                        TimeoutRemain;\r
+\r
+  if (TimeoutDefault == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));\r
+  \r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  //\r
+  // Clear the progress status bar first\r
+  //\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+  if (TmpStr != NULL) {\r
+    PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);\r
+  }\r
+\r
+  TimeoutRemain = TimeoutDefault;\r
+  while (TimeoutRemain != 0) {\r
+    DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));\r
+    \r
+    Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);\r
+    if (Status != EFI_TIMEOUT) {\r
+      break;\r
+    }\r
+    TimeoutRemain--;\r
+\r
+    //\r
+    // Show progress\r
+    //\r
+    if (TmpStr != NULL) {\r
+      PlatformBdsShowProgress (\r
+        Foreground,\r
+        Background,\r
+        TmpStr,\r
+        Color,\r
+        ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),\r
+        0\r
+        );\r
+    }\r
+  }\r
+  gBS->FreePool (TmpStr);\r
+\r
+  //\r
+  // Timeout expired\r
+  //\r
+  if (TimeoutRemain == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  //\r
+  // User pressed some key\r
+  //\r
+  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+    //\r
+    // User pressed enter, equivalent to select "continue"\r
+    //\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is the main entry of the platform setup entry.\r
+  The function will present the main menu of the system setup,\r
+  this is the platform reference part and can be customize.\r
+\r
+\r
+  @param TimeoutDefault     The fault time out value before the system\r
+                            continue to boot.\r
+  @param ConnectAllHappened The indicater to check if the connect all have\r
+                            already happended.\r
+\r
+**/\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                       TimeoutDefault,\r
+  IN BOOLEAN                      ConnectAllHappened\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_CONSOLE_CONTROL_PROTOCOL  *ConsoleControl;\r
+\r
+  PERF_START (0, "BdsTimeOut", "BDS", 0);\r
+  //\r
+  // Indicate if we need connect all in the platform setup\r
+  //\r
+  if (ConnectAllHappened) {\r
+    gConnectAllHappened = TRUE;\r
+  }\r
+\r
+  if (TimeoutDefault != 0xffff) {\r
+    Status = ShowProgress (TimeoutDefault);\r
+\r
+    //\r
+    // Ensure screen is clear when switch Console from Graphics mode to Text mode\r
+    //\r
+    gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+    gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Timeout or user press enter to continue\r
+      //\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  do {\r
+\r
+    InitializeFrontPage (FALSE);\r
+\r
+    //\r
+    // Update Front Page strings\r
+    //\r
+    UpdateFrontPageStrings ();\r
+\r
+    gCallbackKey = 0;\r
+    Status = CallFrontPage ();\r
+\r
+    //\r
+    // If gCallbackKey is greater than 1 and less or equal to 5,\r
+    // it will lauch configuration utilities.\r
+    // 2 = set language\r
+    // 3 = boot manager\r
+    // 4 = device manager\r
+    // 5 = boot maintainenance manager\r
+    //\r
+    if (gCallbackKey != 0) {\r
+      REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)\r
+        );\r
+    }\r
+    //\r
+    // Based on the key that was set, we can determine what to do\r
+    //\r
+    switch (gCallbackKey) {\r
+    //\r
+    // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+    // describe to their customers in documentation how to find their setup information (namely\r
+    // under the device manager and specific buckets)\r
+    //\r
+    // These entries consist of the Continue, Select language, Boot Manager, and Device Manager\r
+    //\r
+    case FRONT_PAGE_KEY_CONTINUE:\r
+      //\r
+      // User hit continue\r
+      //\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_LANGUAGE:\r
+      //\r
+      // User made a language setting change - display front page again\r
+      //\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+      //\r
+      // User chose to run the Boot Manager\r
+      //\r
+      CallBootManager ();\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+      //\r
+      // Display the Device Manager\r
+      //\r
+      do {\r
+        CallDeviceManager();\r
+      } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);\r
+      break;\r
+\r
+    case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+      //\r
+      // Display the Boot Maintenance Manager\r
+      //\r
+      BdsStartBootMaint ();\r
+      break;\r
+    }\r
+\r
+  } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));\r
+\r
+  //\r
+  //Will leave browser, check any reset required change is applied? if yes, reset system\r
+  //\r
+  SetupResetReminder ();\r
+\r
+Exit:\r
+  //\r
+  // Automatically load current entry\r
+  // Note: The following lines of code only execute when Auto boot\r
+  // takes affect\r
+  //\r
+  PERF_END (0, "BdsTimeOut", "BDS", 0);\r
+  Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+  ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPage.h
new file mode 100644 (file)
index 0000000..d8e3bb4
--- /dev/null
@@ -0,0 +1,240 @@
+/** @file\r
+  FrontPage routines to handle the callbacks and browser calls\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _FRONT_PAGE_H_\r
+#define _FRONT_PAGE_H_\r
+\r
+#include "DeviceMngr/DeviceManager.h"\r
+#include "BootMaint/BootMaint.h"\r
+#include "BootMngr/BootManager.h"\r
+#include "String.h"\r
+\r
+#define ONE_SECOND  10000000\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID     0x0001\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define FRONT_PAGE_FORM_ID             0x1000\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE        0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE        0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER    0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER  0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN   0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE          0x1000\r
+\r
+#define FRONT_PAGE_FORMSET_GUID \\r
+  { \\r
+    0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe} \\r
+  }\r
+\r
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE  SIGNATURE_32 ('F', 'P', 'C', 'B')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+\r
+  //\r
+  // HII relative handles\r
+  //\r
+  EFI_HII_HANDLE                  HiiHandle;\r
+  EFI_HANDLE                      DriverHandle;\r
+  EFI_STRING_ID                   *LanguageToken;\r
+\r
+  //\r
+  // Produced protocols\r
+  //\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;\r
+} FRONT_PAGE_CALLBACK_DATA;\r
+\r
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      FRONT_PAGE_CALLBACK_DATA, \\r
+      ConfigAccess, \\r
+      FRONT_PAGE_CALLBACK_DATA_SIGNATURE \\r
+      )\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8  FrontPageVfrBin[];\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL       *gHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL         *gHiiString;\r
+extern EFI_FORM_BROWSER2_PROTOCOL      *gFormBrowser2;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+extern UINTN    gCallbackKey;\r
+extern BOOLEAN  gConnectAllHappened;\r
+\r
+/**\r
+  This function allows a caller to extract the current configuration for one\r
+  or more named elements from the target driver.\r
+\r
+\r
+  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Request         - A null-terminated Unicode string in <ConfigRequest> format.\r
+  @param Progress        - On return, points to a character in the Request string.\r
+                         Points to the string's null terminator if request was successful.\r
+                         Points to the most recent '&' before the first failing name/value\r
+                         pair (or the beginning of the string if the failure is in the\r
+                         first name/value pair) if the request was not successful.\r
+  @param Results         - A null-terminated Unicode string in <ConfigAltResp> format which\r
+                         has all values filled in for the names in the Request string.\r
+                         String to be allocated by the called function.\r
+\r
+  @retval  EFI_SUCCESS            The Results is filled with the requested values.\r
+  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.\r
+  @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.\r
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  );\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+\r
+  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Configuration   - A null-terminated Unicode string in <ConfigResp> format.\r
+  @param Progress        - A pointer to a string filled in with the offset of the most\r
+                         recent '&' before the first failing name/value pair (or the\r
+                         beginning of the string if the failure is in the first\r
+                         name/value pair) or the terminating NULL if all was successful.\r
+\r
+  @retval  EFI_SUCCESS            The Results is processed successfully.\r
+  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.\r
+  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  );\r
+\r
+/**\r
+  This function processes the results of changes in configuration.\r
+\r
+\r
+  @param This            - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param Action          - Specifies the type of action taken by the browser.\r
+  @param QuestionId      - A unique value which is sent to the original exporting driver\r
+                         so that it can identify the type of data to expect.\r
+  @param Type            - The type of value for the question.\r
+  @param Value           - A pointer to the data being sent to the original exporting driver.\r
+  @param ActionRequest   - On return, points to the action requested by the callback function.\r
+\r
+  @retval  EFI_SUCCESS           The callback successfully handled the action.\r
+  @retval  EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.\r
+  @retval  EFI_DEVICE_ERROR      The variable could not be saved.\r
+  @retval  EFI_UNSUPPORTED       The specified Action is not supported by the callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  );\r
+\r
+/**\r
+  Initialize HII information for the FrontPage\r
+\r
+\r
+  @param InitializeHiiData    TRUE if HII elements need to be initialized.\r
+\r
+  @retval  EFI_SUCCESS        The operation is successful.\r
+  @retval  EFI_DEVICE_ERROR   If the dynamic opcode creation failed.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+  IN BOOLEAN    InitializeHiiData\r
+  );\r
+\r
+/**\r
+  Acquire the string associated with the ProducerGuid and return it.\r
+\r
+\r
+  @param ProducerGuid    - The Guid to search the HII database for\r
+  @param Token           - The token value of the string to extract\r
+  @param String          - The string that is extracted\r
+\r
+  @retval  EFI_SUCCESS  The function returns EFI_SUCCESS always.\r
+\r
+**/\r
+EFI_STATUS\r
+GetProducerString (\r
+  IN      EFI_GUID                  *ProducerGuid,\r
+  IN      EFI_STRING_ID             Token,\r
+  OUT     CHAR16                    **String\r
+  );\r
+\r
+/**\r
+  Compare two EFI_TIME data.\r
+\r
+\r
+  @param FirstTime       - A pointer to the first EFI_TIME data.\r
+  @param SecondTime      - A pointer to the second EFI_TIME data.\r
+\r
+  @retval  TRUE              The FirstTime is not later than the SecondTime.\r
+  @retval  FALSE             The FirstTime is later than the SecondTime.\r
+\r
+**/\r
+BOOLEAN\r
+TimeCompare (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  );\r
+\r
+/**\r
+  This function is the main entry of the platform setup entry.\r
+  The function will present the main menu of the system setup,\r
+  this is the platform reference part and can be customize.\r
+\r
+\r
+  @param TimeoutDefault  - The fault time out value before the system\r
+                         continue to boot.\r
+  @param ConnectAllHappened - The indicater to check if the connect all have\r
+                         already happended.\r
+\r
+**/\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+  IN UINT16                 TimeoutDefault,\r
+  IN BOOLEAN                ConnectAllHappened\r
+  );\r
+\r
+#endif // _FRONT_PAGE_H_\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni
new file mode 100644 (file)
index 0000000..4d55b2b
Binary files /dev/null and b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageStrings.uni differ
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/IntelFrameworkModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
new file mode 100644 (file)
index 0000000..4bf657d
--- /dev/null
@@ -0,0 +1,137 @@
+///** @file\r
+//  \r
+//    Browser formset.\r
+//  \r
+//  Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+//  All rights reserved. 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
+#define FORMSET_GUID  { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }\r
+\r
+#define FRONT_PAGE_CLASS               0x0000\r
+#define FRONT_PAGE_SUBCLASS            0x0002\r
+\r
+#define FRONT_PAGE_FORM_ID             0x1000\r
+\r
+#define FRONT_PAGE_ITEM_ONE            0x0001\r
+#define FRONT_PAGE_ITEM_TWO            0x0002\r
+#define FRONT_PAGE_ITEM_THREE          0x0003\r
+#define FRONT_PAGE_ITEM_FOUR           0x0004\r
+#define FRONT_PAGE_ITEM_FIVE           0x0005\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE        0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE        0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER    0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER  0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN   0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE          0x1000\r
+#define LABEL_TIMEOUT                  0x2000\r
+#define LABEL_END                      0xffff\r
+\r
+formset\r
+  guid     = FORMSET_GUID,\r
+  title    = STRING_TOKEN(STR_FRONT_PAGE_TITLE),\r
+  help     = STRING_TOKEN(STR_NULL_STRING),\r
+  class    = FRONT_PAGE_CLASS,\r
+  subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+  form formid = FRONT_PAGE_FORM_ID,\r
+       title  = STRING_TOKEN(STR_FRONT_PAGE_TITLE);\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),\r
+      line  0,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),\r
+      line  1,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),\r
+      line  1,\r
+      align right;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),\r
+      line  2,\r
+      align left;\r
+\r
+    banner\r
+      title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),\r
+      line  2,\r
+      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),\r
+//      line  0,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),\r
+//      line  0,\r
+//      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),\r
+//      line  1,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),\r
+//      line  1,\r
+//      align right;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),\r
+//      line  2,\r
+//      align left;\r
+\r
+//    banner\r
+//      title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),\r
+//      line  3,\r
+//      align left;\r
+\r
+    goto FRONT_PAGE_ITEM_ONE,\r
+      prompt  = STRING_TOKEN(STR_CONTINUE_PROMPT),\r
+      help    = STRING_TOKEN(STR_CONTINUE_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_CONTINUE;\r
+\r
+    label LABEL_SELECT_LANGUAGE;\r
+    //\r
+    // This is where we will dynamically add a OneOf type op-code to select\r
+    // Languages from the currently available choices\r
+    //\r
+    label LABEL_END;\r
+\r
+    goto FRONT_PAGE_ITEM_THREE,\r
+      prompt  = STRING_TOKEN(STR_BOOT_MANAGER),\r
+      help    = STRING_TOKEN(STR_BOOT_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_BOOT_MANAGER;\r
+\r
+    goto FRONT_PAGE_ITEM_FOUR,\r
+      prompt  = STRING_TOKEN(STR_DEVICE_MANAGER),\r
+      help    = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+\r
+    goto FRONT_PAGE_ITEM_FIVE,\r
+      prompt  = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),\r
+      help    = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),\r
+      flags   = INTERACTIVE,\r
+      key     = FRONT_PAGE_KEY_BOOT_MAINTAIN;\r
+\r
+  endform;\r
+\r
+endformset;\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
new file mode 100644 (file)
index 0000000..bfad7ce
--- /dev/null
@@ -0,0 +1,701 @@
+/** @file\r
+  Provides a way for 3rd party applications to register themselves for launch by the\r
+  Boot Manager based on hot key\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Hotkey.h"\r
+\r
+\r
+LIST_ENTRY      mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
+BOOLEAN         mHotkeyCallbackPending = FALSE;\r
+EFI_EVENT       mHotkeyEvent;\r
+VOID            *mHotkeyRegistration;\r
+\r
+\r
+/**\r
+  Check if the Key Option is valid or not.\r
+\r
+  @param KeyOption       The Hot Key Option to be checked.\r
+\r
+  @retval  TRUE          The Hot Key Option is valid.\r
+  @retval  FALSE         The Hot Key Option is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+IsKeyOptionValid (\r
+  IN EFI_KEY_OPTION     *KeyOption\r
+)\r
+{\r
+  UINT16   BootOptionName[10];\r
+  UINT8    *BootOptionVar;\r
+  UINTN    BootOptionSize;\r
+  UINT32   Crc;\r
+\r
+  //\r
+  // Check whether corresponding Boot Option exist\r
+  //\r
+  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);\r
+  BootOptionVar = BdsLibGetVariableAndSize (\r
+                    BootOptionName,\r
+                    &gEfiGlobalVariableGuid,\r
+                    &BootOptionSize\r
+                    );\r
+\r
+  if (BootOptionVar == NULL || BootOptionSize == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check CRC for Boot Option\r
+  //\r
+  gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);\r
+  FreePool (BootOptionVar);\r
+\r
+  return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);\r
+}\r
+\r
+/**\r
+  Create Key#### for the given hotkey.\r
+\r
+  @param KeyOption       The Hot Key Option to be added.\r
+  @param KeyOptionNumber The key option number for Key#### (optional).\r
+\r
+  @retval  EFI_SUCCESS            Register hotkey successfully.\r
+  @retval  EFI_INVALID_PARAMETER  The hotkey option is invalid.\r
+  @retval  EFI_OUT_OF_RESOURCES   Fail to allocate memory resource.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterHotkey (\r
+  IN EFI_KEY_OPTION     *KeyOption,\r
+  OUT UINT16            *KeyOptionNumber\r
+)\r
+{\r
+  UINT16          KeyOptionName[10];\r
+  UINT16          *KeyOrder;\r
+  UINTN           KeyOrderSize;\r
+  UINT16          *NewKeyOrder;\r
+  UINTN           Index;\r
+  UINT16          MaxOptionNumber;\r
+  UINT16          RegisterOptionNumber;\r
+  EFI_KEY_OPTION  *TempOption;\r
+  UINTN           TempOptionSize;\r
+  EFI_STATUS      Status;\r
+  UINTN           KeyOptionSize;\r
+  BOOLEAN         UpdateBootOption;\r
+\r
+  //\r
+  // Validate the given key option\r
+  //\r
+  if (!IsKeyOptionValid (KeyOption)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) * sizeof (EFI_INPUT_KEY);\r
+  UpdateBootOption = FALSE;\r
+\r
+  //\r
+  // check whether HotKey conflict with keys used by Setup Browser\r
+  //\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VAR_KEY_ORDER,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+  if (KeyOrder == NULL) {\r
+    KeyOrderSize = 0;\r
+  }\r
+\r
+  //\r
+  // Find free key option number\r
+  //\r
+  MaxOptionNumber = 0;\r
+  TempOption = NULL;\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+    if (MaxOptionNumber < KeyOrder[Index]) {\r
+      MaxOptionNumber = KeyOrder[Index];\r
+    }\r
+\r
+    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+    TempOption = BdsLibGetVariableAndSize (\r
+                   KeyOptionName,\r
+                   &gEfiGlobalVariableGuid,\r
+                   &TempOptionSize\r
+                   );\r
+\r
+    if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
+      //\r
+      // Got the option, so just return\r
+      //\r
+      FreePool (TempOption);\r
+      FreePool (KeyOrder);\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
+      if (GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) == 0 ||\r
+          CompareMem (\r
+            ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
+            ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
+            KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
+            ) == 0) {\r
+          //\r
+          // Hotkey is the same but BootOption changed, need update\r
+          //\r
+          UpdateBootOption = TRUE;\r
+          break;\r
+      }\r
+    }\r
+\r
+    FreePool (TempOption);\r
+  }\r
+\r
+  if (UpdateBootOption) {\r
+    RegisterOptionNumber = KeyOrder[Index];\r
+    FreePool (TempOption);\r
+  } else {\r
+    RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
+  }\r
+\r
+  if (KeyOptionNumber != NULL) {\r
+    *KeyOptionNumber = RegisterOptionNumber;\r
+  }\r
+\r
+  //\r
+  // Create variable Key####\r
+  //\r
+  UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
+  Status = gRT->SetVariable (\r
+                  KeyOptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOptionSize,\r
+                  KeyOption\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (KeyOrder);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Update the key order variable - "KeyOrder"\r
+  //\r
+  if (!UpdateBootOption) {\r
+    Index = KeyOrderSize / sizeof (UINT16);\r
+    KeyOrderSize += sizeof (UINT16);\r
+  }\r
+\r
+  NewKeyOrder = AllocatePool (KeyOrderSize);\r
+  if (NewKeyOrder == NULL) {\r
+    FreePool (KeyOrder);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (KeyOrder != NULL) {\r
+    CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
+  }\r
+\r
+  NewKeyOrder[Index] = RegisterOptionNumber;\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_KEY_ORDER,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOrderSize,\r
+                  NewKeyOrder\r
+                  );\r
+\r
+  FreePool (KeyOrder);\r
+  FreePool (NewKeyOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Delete Key#### for the given Key Option number.\r
+\r
+  @param KeyOptionNumber Key option number for Key####\r
+\r
+  @retval  EFI_SUCCESS            Unregister hotkey successfully.\r
+  @retval  EFI_NOT_FOUND          No Key#### is found for the given Key Option number.\r
+\r
+**/\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+  IN UINT16     KeyOptionNumber\r
+)\r
+{\r
+  UINT16      KeyOption[10];\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+  UINTN       Index2Del;\r
+  UINT16      *KeyOrder;\r
+  UINTN       KeyOrderSize;\r
+\r
+  //\r
+  // Delete variable Key####\r
+  //\r
+  UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
+  gRT->SetVariable (\r
+         KeyOption,\r
+         &gEfiGlobalVariableGuid,\r
+         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+         0,\r
+         NULL\r
+         );\r
+\r
+  //\r
+  // Adjust key order array\r
+  //\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VAR_KEY_ORDER,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+  if (KeyOrder == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Index2Del = 0;\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+    if (KeyOrder[Index] == KeyOptionNumber) {\r
+      Index2Del = Index;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index != KeyOrderSize / sizeof (UINT16)) {\r
+    //\r
+    // KeyOptionNumber found in "KeyOrder", delete it\r
+    //\r
+    for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
+      KeyOrder[Index] = KeyOrder[Index + 1];\r
+    }\r
+\r
+    KeyOrderSize -= sizeof (UINT16);\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_KEY_ORDER,\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  KeyOrderSize,\r
+                  KeyOrder\r
+                  );\r
+\r
+  FreePool (KeyOrder);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This is the common notification function for HotKeys, it will be registered\r
+  with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
+\r
+  @param KeyData         A pointer to a buffer that is filled in with the keystroke\r
+                         information for the key that was pressed.\r
+\r
+  @retval  EFI_SUCCESS   KeyData is successfully processed.\r
+  @return  EFI_NOT_FOUND Fail to find boot option variable.\r
+**/\r
+EFI_STATUS\r
+HotkeyCallback (\r
+  IN EFI_KEY_DATA     *KeyData\r
+)\r
+{\r
+  BOOLEAN            HotkeyCatched;\r
+  LIST_ENTRY         BootLists;\r
+  LIST_ENTRY         *Link;\r
+  BDS_HOTKEY_OPTION  *Hotkey;\r
+  UINT16             Buffer[10];\r
+  BDS_COMMON_OPTION  *BootOption;\r
+  UINTN              ExitDataSize;\r
+  CHAR16             *ExitData;\r
+  EFI_STATUS         Status;\r
+  EFI_KEY_DATA       *HotkeyData;\r
+\r
+  if (mHotkeyCallbackPending) {\r
+    //\r
+    // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
+    // the current Boot#### load option returned\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  Link = GetFirstNode (&mHotkeyList);\r
+\r
+  while (!IsNull (&mHotkeyList, Link)) {\r
+    HotkeyCatched = FALSE;\r
+    Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+    //\r
+    // Is this Key Stroke we are waiting for?\r
+    //\r
+    ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
+    HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
+    if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
+       (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
+       ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
+      //\r
+      // Receive an expecting key stroke\r
+      //\r
+      if (Hotkey->CodeCount > 1) {\r
+        //\r
+        // For hotkey of key combination, transit to next waiting state\r
+        //\r
+        Hotkey->WaitingKey++;\r
+\r
+        if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
+          //\r
+          // Received the whole key stroke sequence\r
+          //\r
+          HotkeyCatched = TRUE;\r
+        }\r
+      } else {\r
+        //\r
+        // For hotkey of single key stroke\r
+        //\r
+        HotkeyCatched = TRUE;\r
+      }\r
+    } else {\r
+      //\r
+      // Receive an unexpected key stroke, reset to initial waiting state\r
+      //\r
+      Hotkey->WaitingKey = 0;\r
+    }\r
+\r
+    if (HotkeyCatched) {\r
+      //\r
+      // Reset to initial waiting state\r
+      //\r
+      Hotkey->WaitingKey = 0;\r
+\r
+      //\r
+      // Launch its BootOption\r
+      //\r
+      InitializeListHead (&BootLists);\r
+\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
+      BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+      if (BootOption == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+      BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
+      BdsLibConnectDevicePath (BootOption->DevicePath);\r
+\r
+      //\r
+      // Clear the screen before launch this BootOption\r
+      //\r
+      gST->ConOut->Reset (gST->ConOut, FALSE);\r
+\r
+      mHotkeyCallbackPending = TRUE;\r
+      Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+      mHotkeyCallbackPending = FALSE;\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Call platform action to indicate the boot fail\r
+        //\r
+        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+        PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+      } else {\r
+        //\r
+        // Call platform action to indicate the boot success\r
+        //\r
+        BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+        PlatformBdsBootSuccess (BootOption);\r
+      }\r
+    }\r
+\r
+    Link = GetNextNode (&mHotkeyList, Link);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
+\r
+  @param SimpleTextInEx  Simple Text Input Ex protocol instance\r
+\r
+  @retval  EFI_SUCCESS            Register hotkey notification function successfully.\r
+  @retval  EFI_OUT_OF_RESOURCES   Unable to allocate necessary data structures.\r
+\r
+**/\r
+EFI_STATUS\r
+HotkeyRegisterNotify (\r
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *SimpleTextInEx\r
+)\r
+{\r
+  UINTN              Index;\r
+  EFI_STATUS         Status;\r
+  LIST_ENTRY         *Link;\r
+  BDS_HOTKEY_OPTION  *Hotkey;\r
+\r
+  //\r
+  // Register notification function for each hotkey\r
+  //\r
+  Link = GetFirstNode (&mHotkeyList);\r
+\r
+  while (!IsNull (&mHotkeyList, Link)) {\r
+    Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+    Index = 0;\r
+    do {\r
+      Status = SimpleTextInEx->RegisterKeyNotify (\r
+                                 SimpleTextInEx,\r
+                                 &Hotkey->KeyData[Index],\r
+                                 HotkeyCallback,\r
+                                 &Hotkey->NotifyHandle\r
+                                 );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // some of the hotkey registry failed\r
+        //\r
+        return Status;\r
+      }\r
+      Index ++;\r
+    } while (Index < Hotkey->CodeCount);\r
+\r
+    Link = GetNextNode (&mHotkeyList, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Callback function for SimpleTextInEx protocol install events\r
+\r
+  @param Event           the event that is signaled.\r
+  @param Context         not used here.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HotkeyEvent (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+  UINTN                              BufferSize;\r
+  EFI_HANDLE                         Handle;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *SimpleTextInEx;\r
+\r
+  while (TRUE) {\r
+    BufferSize = sizeof (EFI_HANDLE);\r
+    Status = gBS->LocateHandle (\r
+                    ByRegisterNotify,\r
+                    NULL,\r
+                    mHotkeyRegistration,\r
+                    &BufferSize,\r
+                    &Handle\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // If no more notification events exist\r
+      //\r
+      return ;\r
+    }\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    Handle,\r
+                    &gEfiSimpleTextInputExProtocolGuid,\r
+                    (VOID **) &SimpleTextInEx\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    HotkeyRegisterNotify (SimpleTextInEx);\r
+  }\r
+}\r
+\r
+/**\r
+  Insert Key Option to hotkey list.\r
+\r
+  @param KeyOption       The Hot Key Option to be added to hotkey list.\r
+\r
+  @retval EFI_SUCCESS           Add to hotkey list success.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate memory resource.\r
+**/\r
+EFI_STATUS\r
+HotkeyInsertList (\r
+  IN EFI_KEY_OPTION     *KeyOption\r
+)\r
+{\r
+  BDS_HOTKEY_OPTION  *HotkeyLeft;\r
+  BDS_HOTKEY_OPTION  *HotkeyRight;\r
+  UINTN              Index;\r
+  UINT32             KeyOptions;\r
+  UINT32             KeyShiftStateLeft;\r
+  UINT32             KeyShiftStateRight;\r
+  EFI_INPUT_KEY      *InputKey;\r
+  EFI_KEY_DATA       *KeyData;\r
+\r
+  HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
+  if (HotkeyLeft == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
+  HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
+\r
+  KeyOptions = KeyOption->KeyData.PackedValue;\r
+\r
+  HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
+\r
+  //\r
+  // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
+  //\r
+  KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
+                       ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
+                       ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
+                       EFI_SHIFT_STATE_VALID;\r
+\r
+  KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
+\r
+  InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
+\r
+  Index = 0;\r
+  KeyData = &HotkeyLeft->KeyData[0];\r
+  do {\r
+    //\r
+    // If Key CodeCount is 0, then only KeyData[0] is used;\r
+    // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
+    //\r
+    KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
+    KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
+    KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
+\r
+    Index++;\r
+    KeyData++;\r
+  } while (Index < HotkeyLeft->CodeCount);\r
+  InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
+\r
+  if (KeyShiftStateLeft != KeyShiftStateRight) {\r
+    //\r
+    // Need an extra hotkey for shift key on right\r
+    //\r
+    HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
+    if (HotkeyRight == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Index = 0;\r
+    KeyData = &HotkeyRight->KeyData[0];\r
+    do {\r
+      //\r
+      // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
+      // only need to update KeyState.KeyShiftState\r
+      //\r
+      KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
+\r
+      Index++;\r
+      KeyData++;\r
+    } while (Index < HotkeyRight->CodeCount);\r
+    InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+  @retval  EFI_SUCCESS    Hotkey services successfully initialized.\r
+  @retval  EFI_NOT_FOUND  Can not find the "KeyOrder" variable\r
+**/\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT32          BootOptionSupport;\r
+  UINT16          *KeyOrder;\r
+  UINTN           KeyOrderSize;\r
+  UINTN           Index;\r
+  UINT16          KeyOptionName[8];\r
+  UINTN           KeyOptionSize;\r
+  EFI_KEY_OPTION  *KeyOption;\r
+\r
+  //\r
+  // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
+  //\r
+  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
+  Status = gRT->SetVariable (\r
+                  L"BootOptionSupport",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  sizeof (UINT32),\r
+                  &BootOptionSupport\r
+                  );\r
+\r
+  //\r
+  // Get valid Key Option List from private EFI variable "KeyOrder"\r
+  //\r
+  KeyOrder = BdsLibGetVariableAndSize (\r
+               VAR_KEY_ORDER,\r
+               &gEfiGlobalVariableGuid,\r
+               &KeyOrderSize\r
+               );\r
+\r
+  if (KeyOrder == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
+    UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+    KeyOption = BdsLibGetVariableAndSize (\r
+                  KeyOptionName,\r
+                  &gEfiGlobalVariableGuid,\r
+                  &KeyOptionSize\r
+                  );\r
+\r
+    if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
+      UnregisterHotkey (KeyOrder[Index]);\r
+    } else {\r
+      HotkeyInsertList (KeyOption);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Register Protocol notify for Hotkey service\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  HotkeyEvent,\r
+                  NULL,\r
+                  &mHotkeyEvent\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Register for protocol notifications on this event\r
+  //\r
+  Status = gBS->RegisterProtocolNotify (\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  mHotkeyEvent,\r
+                  &mHotkeyRegistration\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.h
new file mode 100644 (file)
index 0000000..f2d1c60
--- /dev/null
@@ -0,0 +1,90 @@
+/** @file\r
+  Provides a way for 3rd party applications to register themselves for launch by the\r
+  Boot Manager based on hot key\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _HOTKEY_H_\r
+#define _HOTKEY_H_\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+#define GET_KEY_CODE_COUNT(KeyOptions)      (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)\r
+\r
+#define BDS_HOTKEY_OPTION_SIGNATURE SIGNATURE_32 ('B', 'd', 'K', 'O')\r
+typedef struct {\r
+  UINTN                     Signature;\r
+  LIST_ENTRY                Link;\r
+\r
+  EFI_HANDLE                NotifyHandle;\r
+  UINT16                    BootOptionNumber;\r
+  UINT8                     CodeCount;\r
+  UINT8                     WaitingKey;\r
+  EFI_KEY_DATA              KeyData[3];\r
+} BDS_HOTKEY_OPTION;\r
+\r
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)\r
+\r
+#define VAR_KEY_ORDER       L"KeyOrder"\r
+\r
+/**\r
+\r
+  Create Key#### for the given hotkey.\r
+\r
+\r
+  @param KeyOption       - The Hot Key Option to be added.\r
+  @param KeyOptionNumber - The key option number for Key#### (optional).\r
+\r
+  @retval  EFI_SUCCESS            Register hotkey successfully.\r
+  @retval  EFI_INVALID_PARAMETER  The hotkey option is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterHotkey (\r
+  IN EFI_KEY_OPTION     *KeyOption,\r
+  OUT UINT16            *KeyOptionNumber\r
+  );\r
+\r
+/**\r
+\r
+  Delete Key#### for the given Key Option number.\r
+\r
+\r
+  @param KeyOptionNumber - Key option number for Key####\r
+\r
+  @retval  EFI_SUCCESS            Unregister hotkey successfully.\r
+  @retval  EFI_NOT_FOUND          No Key#### is found for the given Key Option number.\r
+\r
+**/\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+  IN UINT16             KeyOptionNumber\r
+  );\r
+\r
+\r
+/**\r
+\r
+  Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+\r
+  @param VOID\r
+\r
+  @retval  EFI_SUCCESS    Hotkey services successfully initialized.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+  VOID\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.c
new file mode 100644 (file)
index 0000000..3b48c37
--- /dev/null
@@ -0,0 +1,49 @@
+/** @file\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "HwErrRecSupport.h"\r
+\r
+/**\r
+  Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+  level of support for Hardware Error Record Persistence that is implemented\r
+  by the platform.\r
+\r
+\r
+  @param HwErrRecSupportLevel\r
+                         zero value:      Indicates that the platform implements no support for\r
+                                          Hardware Error Record Persistence.\r
+                         non-zero value:  Indicates that the platform implements Hardware Error\r
+                                          Record Persistence.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  IN UINT16       HwErrRecSupportLevel\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gRT->SetVariable (\r
+                  L"HwErrRecSupport",\r
+                  &gEfiGlobalVariableGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                  sizeof (UINT16),\r
+                  &HwErrRecSupportLevel\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));\r
+  }\r
+\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/IntelFrameworkModulePkg/Universal/BdsDxe/HwErrRecSupport.h
new file mode 100644 (file)
index 0000000..1926839
--- /dev/null
@@ -0,0 +1,39 @@
+/** @file\r
+  Set the level of support for Hardware Error Record Persistence that is\r
+  implemented by the platform.\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _HW_ERR_REC_SUPPORT_H_\r
+#define _HW_ERR_REC_SUPPORT_H_\r
+\r
+#include "Bds.h"\r
+\r
+/**\r
+  Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+  level of support for Hardware Error Record Persistence that is implemented\r
+  by the platform.\r
+\r
+\r
+  @param HwErrRecSupportLevel\r
+                         zero value      - Indicates that the platform implements no support for\r
+                         Hardware Error Record Persistence.\r
+                         non-zero value  - Indicates that the platform implements Hardware Error\r
+                         Record Persistence.\r
+\r
+**/\r
+VOID\r
+InitializeHwErrRecSupport (\r
+  IN UINT16       HwErrRecSupportLevel\r
+  );\r
+\r
+#endif\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.c
new file mode 100644 (file)
index 0000000..4e7537c
--- /dev/null
@@ -0,0 +1,399 @@
+/** @file\r
+  Language settings\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+#define NARROW_GLYPH_NUMBER 8\r
+#define WIDE_GLYPH_NUMBER   75\r
+\r
+EFI_GUID  mFontPackageGuid = {\r
+  0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}\r
+};\r
+\r
+typedef struct {\r
+  ///\r
+  /// This 4-bytes total array length is required by HiiLibPreparePackageList()\r
+  ///\r
+  UINT32                 Length;\r
+\r
+  //\r
+  // This is the Font package definition\r
+  //\r
+  EFI_HII_PACKAGE_HEADER Header;\r
+  UINT16                 NumberOfNarrowGlyphs;\r
+  UINT16                 NumberOfWideGlyphs;\r
+  EFI_NARROW_GLYPH       NarrowArray[NARROW_GLYPH_NUMBER];\r
+  EFI_WIDE_GLYPH         WideArray[WIDE_GLYPH_NUMBER];\r
+} FONT_PACK_BIN;\r
+\r
+FONT_PACK_BIN mFontBin = {\r
+  sizeof (FONT_PACK_BIN),\r
+  {\r
+    sizeof (FONT_PACK_BIN) - sizeof (UINT32),\r
+    EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+  },\r
+  NARROW_GLYPH_NUMBER,\r
+  0,\r
+  {     // Narrow Glyphs\r
+    {\r
+      0x05d0,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x4E,\r
+        0x6E,\r
+        0x62,\r
+        0x32,\r
+        0x32,\r
+        0x3C,\r
+        0x68,\r
+        0x4C,\r
+        0x4C,\r
+        0x46,\r
+        0x76,\r
+        0x72,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d1,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x7E,\r
+        0x7E,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d2,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x78,\r
+        0x7C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x1C,\r
+        0x3E,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d3,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7E,\r
+        0x7E,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d4,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x7C,\r
+        0x7E,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x06,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x66,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d5,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x3C,\r
+        0x3C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x0C,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x05d6,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x38,\r
+        0x38,\r
+        0x1E,\r
+        0x1E,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x18,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    },\r
+    {\r
+      0x0000,\r
+      0x00,\r
+      {\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00,\r
+        0x00\r
+      }\r
+    }\r
+  }\r
+};\r
+\r
+/**\r
+  Routine to export glyphs to the HII database.  This is in addition to whatever is defined in the Graphics Console driver.\r
+\r
+**/\r
+VOID\r
+ExportFonts (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HANDLE                   DriverHandle;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  PackageList = HiiLibPreparePackageList (1, &mFontPackageGuid, &mFontBin);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);\r
+  FreePool (PackageList);\r
+}\r
+\r
+/**\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables.\r
+\r
+  @param LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Size;\r
+  CHAR8       *Lang;\r
+  CHAR8       LangCode[ISO_639_2_ENTRY_SIZE];\r
+  CHAR8       *LangCodes;\r
+  CHAR8       *PlatformLang;\r
+  CHAR8       *PlatformLangCodes;\r
+  UINTN       Index;\r
+  BOOLEAN     Invalid;\r
+\r
+  ExportFonts ();\r
+\r
+  LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);\r
+  if (LangCodesSettingRequired) {\r
+    if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+      //\r
+      // UEFI 2.1 depricated this variable so we support turning it off\r
+      //\r
+      Status = gRT->SetVariable (\r
+                      L"LangCodes",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      AsciiStrLen (LangCodes),\r
+                      LangCodes\r
+                      );\r
+    }\r
+\r
+\r
+    PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLangCodes",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (PlatformLangCodes),\r
+                    PlatformLangCodes\r
+                    );\r
+  }\r
+\r
+  if (!FeaturePcdGet (PcdUefiVariableDefaultLangDeprecate)) {\r
+    //\r
+    // UEFI 2.1 depricated this variable so we support turning it off\r
+    //\r
+\r
+    //\r
+    // Find current LangCode from Lang NV Variable\r
+    //\r
+    Size = ISO_639_2_ENTRY_SIZE;\r
+    Status = gRT->GetVariable (\r
+                    L"Lang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    &LangCode\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = EFI_NOT_FOUND;\r
+      for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {\r
+        if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    //\r
+    // If we cannot get language code from Lang variable,\r
+    // or LangCode cannot be found from language table,\r
+    // set the mDefaultLangCode to Lang variable.\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);\r
+      Status = gRT->SetVariable (\r
+                      L"Lang",\r
+                      &gEfiGlobalVariableGuid,\r
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                      ISO_639_2_ENTRY_SIZE,\r
+                      Lang\r
+                      );\r
+    }\r
+  }\r
+\r
+  Invalid = FALSE;\r
+  PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);\r
+  if (PlatformLang != NULL) {\r
+    //\r
+    // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD\r
+    // Set Invalid based on state of PlatformLang.\r
+    //\r
+\r
+    FreePool (PlatformLang);\r
+  } else {\r
+    // No valid variable is set\r
+    Invalid = TRUE;\r
+  }\r
+\r
+  if (Invalid) {\r
+    PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);\r
+    Status = gRT->SetVariable (\r
+                    L"PlatformLang",\r
+                    &gEfiGlobalVariableGuid,\r
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+                    AsciiStrSize (PlatformLang),\r
+                    PlatformLang\r
+                    );\r
+  }\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h b/IntelFrameworkModulePkg/Universal/BdsDxe/Language.h
new file mode 100644 (file)
index 0000000..39dd1ec
--- /dev/null
@@ -0,0 +1,32 @@
+/** @file\r
+  Language setting\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _LANGUAGE_H_\r
+#define _LANGUAGE_H_\r
+\r
+#include "String.h"\r
+\r
+/**\r
+  Determine the current language that will be used\r
+  based on language related EFI Variables.\r
+\r
+  @param LangCodesSettingRequired If required to set LangCode variable\r
+\r
+**/\r
+VOID\r
+InitializeLanguage (\r
+  BOOLEAN LangCodesSettingRequired\r
+  );\r
+\r
+#endif // _LANGUAGE_H_\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c b/IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c
new file mode 100644 (file)
index 0000000..fabdf24
--- /dev/null
@@ -0,0 +1,425 @@
+/** @file\r
+  Perform the platform memory test\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+/**\r
+\r
+  Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+\r
+  @param TitleForeground Foreground color for Title.\r
+  @param TitleBackground Background color for Title.\r
+  @param Title           Title above progress bar.\r
+  @param ProgressColor   Progress bar color.\r
+  @param Progress        Progress (0-100)\r
+  @param PreviousValue   The previous value of the progress.\r
+\r
+  @retval  EFI_STATUS       Success update the progress bar\r
+\r
+**/\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+  IN CHAR16                        *Title,\r
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+  IN UINTN                         Progress,\r
+  IN UINTN                         PreviousValue\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_GRAPHICS_OUTPUT_PROTOCOL   *GraphicsOutput;\r
+  EFI_UGA_DRAW_PROTOCOL          *UgaDraw;\r
+  UINT32                         SizeOfX;\r
+  UINT32                         SizeOfY;\r
+  UINT32                         ColorDepth;\r
+  UINT32                         RefreshRate;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Color;\r
+  UINTN                          BlockHeight;\r
+  UINTN                          BlockWidth;\r
+  UINTN                          BlockNum;\r
+  UINTN                          PosX;\r
+  UINTN                          PosY;\r
+  UINTN                          Index;\r
+\r
+  if (Progress > 100) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  UgaDraw = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  gST->ConsoleOutHandle,\r
+                  &gEfiGraphicsOutputProtocolGuid,\r
+                  (VOID **) &GraphicsOutput\r
+                  );\r
+  if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+    GraphicsOutput = NULL;\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    gST->ConsoleOutHandle,\r
+                    &gEfiUgaDrawProtocolGuid,\r
+                    (VOID **) &UgaDraw\r
+                    );\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  SizeOfX = 0;\r
+  SizeOfY = 0;\r
+  if (GraphicsOutput != NULL) {\r
+    SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+    SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+  } else if (UgaDraw != NULL) {\r
+    Status = UgaDraw->GetMode (\r
+                        UgaDraw,\r
+                        &SizeOfX,\r
+                        &SizeOfY,\r
+                        &ColorDepth,\r
+                        &RefreshRate\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  BlockWidth  = SizeOfX / 100;\r
+  BlockHeight = SizeOfY / 50;\r
+\r
+  BlockNum    = Progress;\r
+\r
+  PosX        = 0;\r
+  PosY        = SizeOfY * 48 / 50;\r
+\r
+  if (BlockNum == 0) {\r
+    //\r
+    // Clear progress area\r
+    //\r
+    SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &Color,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - EFI_GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &Color,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          0,\r
+                          PosY - EFI_GLYPH_HEIGHT - 1,\r
+                          SizeOfX,\r
+                          SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
+                          SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    } else {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+  //\r
+  // Show progress by drawing blocks\r
+  //\r
+  for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+    PosX = Index * BlockWidth;\r
+    if (GraphicsOutput != NULL) {\r
+      Status = GraphicsOutput->Blt (\r
+                          GraphicsOutput,\r
+                          &ProgressColor,\r
+                          EfiBltVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+                          );\r
+    } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+      Status = UgaDraw->Blt (\r
+                          UgaDraw,\r
+                          (EFI_UGA_PIXEL *) &ProgressColor,\r
+                          EfiUgaVideoFill,\r
+                          0,\r
+                          0,\r
+                          PosX,\r
+                          PosY,\r
+                          BlockWidth - 1,\r
+                          BlockHeight,\r
+                          (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+                          );\r
+    } else {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  PrintXY (\r
+    (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
+    PosY - EFI_GLYPH_HEIGHT - 1,\r
+    &TitleForeground,\r
+    &TitleBackground,\r
+    Title\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Perform the memory test base on the memory test intensive level,\r
+  and update the memory resource.\r
+\r
+\r
+  @param Level           The memory test intensive level.\r
+\r
+  @retval  EFI_STATUS       Success test all the system memory and update\r
+                            the memory resource\r
+\r
+**/\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+  IN EXTENDMEM_COVERAGE_LEVEL Level\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_STATUS                        KeyStatus;\r
+  EFI_STATUS                        InitStatus;\r
+  EFI_STATUS                        ReturnStatus;\r
+  BOOLEAN                           RequireSoftECCInit;\r
+  EFI_GENERIC_MEMORY_TEST_PROTOCOL  *GenMemoryTest;\r
+  UINT64                            TestedMemorySize;\r
+  UINT64                            TotalMemorySize;\r
+  UINTN                             TestPercent;\r
+  UINT64                            PreviousValue;\r
+  BOOLEAN                           ErrorOut;\r
+  BOOLEAN                           TestAbort;\r
+  EFI_INPUT_KEY                     Key;\r
+  CHAR16                            StrPercent[16];\r
+  CHAR16                            *StrTotalMemory;\r
+  CHAR16                            *Pos;\r
+  CHAR16                            *TmpStr;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Foreground;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Background;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Color;\r
+  UINT8                             Value;\r
+  UINTN                             DataSize;\r
+  UINT32                            Attributes;\r
+  UINT32                            TempData;\r
+\r
+  ReturnStatus = EFI_SUCCESS;\r
+  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+  Pos = AllocatePool (128);\r
+\r
+  if (Pos == NULL) {\r
+    return ReturnStatus;\r
+  }\r
+\r
+  StrTotalMemory    = Pos;\r
+\r
+  TestedMemorySize  = 0;\r
+  TotalMemorySize   = 0;\r
+  PreviousValue     = 0;\r
+  ErrorOut          = FALSE;\r
+  TestAbort         = FALSE;\r
+\r
+  SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+  SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+  SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+  RequireSoftECCInit = FALSE;\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiGenericMemTestProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &GenMemoryTest\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  InitStatus = GenMemoryTest->MemoryTestInit (\r
+                                GenMemoryTest,\r
+                                Level,\r
+                                &RequireSoftECCInit\r
+                                );\r
+  if (InitStatus == EFI_NO_MEDIA) {\r
+    //\r
+    // The PEI codes also have the relevant memory test code to check the memory,\r
+    // it can select to test some range of the memory or all of them. If PEI code\r
+    // checks all the memory, this BDS memory test will has no not-test memory to\r
+    // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+    // "MemoryTestInit". So it does not need to test memory again, just return.\r
+    //\r
+    FreePool (Pos);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+  if (TmpStr != NULL) {\r
+    gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+    FreePool (TmpStr);\r
+  }\r
+\r
+  do {\r
+    Status = GenMemoryTest->PerformMemoryTest (\r
+                              GenMemoryTest,\r
+                              &TestedMemorySize,\r
+                              &TotalMemorySize,\r
+                              &ErrorOut,\r
+                              TestAbort\r
+                              );\r
+    if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+      if (TmpStr != NULL) {\r
+        PrintXY (10, 10, NULL, NULL, TmpStr);\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+        gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+        FreePool (TmpStr);\r
+      }\r
+\r
+      ASSERT (0);\r
+    }\r
+\r
+    TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
+    TestPercent = (UINTN) DivU64x32 (\r
+                            DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+                            TempData\r
+                            );\r
+    if (TestPercent != PreviousValue) {\r
+      UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+      if (TmpStr != NULL) {\r
+        BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+        FreePool (TmpStr);\r
+      }\r
+\r
+      TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+      if (TmpStr != NULL) {\r
+        PlatformBdsShowProgress (\r
+          Foreground,\r
+          Background,\r
+          TmpStr,\r
+          Color,\r
+          TestPercent,\r
+          (UINTN) PreviousValue\r
+          );\r
+        FreePool (TmpStr);\r
+      }\r
+    }\r
+\r
+    PreviousValue = TestPercent;\r
+\r
+    KeyStatus     = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+    if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {\r
+      if (!RequireSoftECCInit) {\r
+        TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+        if (TmpStr != NULL) {\r
+          PlatformBdsShowProgress (\r
+            Foreground,\r
+            Background,\r
+            TmpStr,\r
+            Color,\r
+            100,\r
+            (UINTN) PreviousValue\r
+            );\r
+          FreePool (TmpStr);\r
+        }\r
+\r
+        gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+        gST->ConOut->OutputString (gST->ConOut, L"100");\r
+        Status = GenMemoryTest->Finished (GenMemoryTest);\r
+        goto Done;\r
+      }\r
+\r
+      TestAbort = TRUE;\r
+    }\r
+  } while (Status != EFI_NOT_FOUND);\r
+\r
+  Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+  UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
+  if (StrTotalMemory[0] == L',') {\r
+    StrTotalMemory++;\r
+  }\r
+\r
+  TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+  if (TmpStr != NULL) {\r
+    StrCat (StrTotalMemory, TmpStr);\r
+    FreePool (TmpStr);\r
+  }\r
+\r
+  gST->ConOut->ClearScreen (gST->ConOut);\r
+  gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+  gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+  gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+  PlatformBdsShowProgress (\r
+    Foreground,\r
+    Background,\r
+    StrTotalMemory,\r
+    Color,\r
+    100,\r
+    (UINTN) PreviousValue\r
+    );\r
+\r
+  FreePool (Pos);\r
+\r
+  DataSize = sizeof (Value);\r
+  Status = gRT->GetVariable (\r
+                  L"BootState",\r
+                  &gEfiBootStateGuid,\r
+                  &Attributes,\r
+                  &DataSize,\r
+                  &Value\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Value = 1;\r
+    gRT->SetVariable (\r
+          L"BootState",\r
+          &gEfiBootStateGuid,\r
+          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+          sizeof (Value),\r
+          &Value\r
+          );\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.c b/IntelFrameworkModulePkg/Universal/BdsDxe/String.c
new file mode 100644 (file)
index 0000000..d1c6651
--- /dev/null
@@ -0,0 +1,88 @@
+/** @file\r
+  String support\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_HII_HANDLE gStringPackHandle;\r
+\r
+EFI_GUID mBdsStringPackGuid = {\r
+  0x7bac95d3, 0xddf, 0x42f3, {0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a}\r
+};\r
+\r
+/**\r
+  Initialize HII global accessor for string support\r
+\r
+  @retval  EFI_SUCCESS  String support initialize success.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_HANDLE                   DriverHandle;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Create driver handle used by HII database\r
+  //\r
+  Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  PackageList = HiiLibPreparePackageList (1, &mBdsStringPackGuid, &BdsDxeStrings);\r
+  ASSERT (PackageList != NULL);\r
+\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase,\r
+                           PackageList,\r
+                           DriverHandle,\r
+                           &gStringPackHandle\r
+                           );\r
+\r
+  FreePool (PackageList);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get string by string id from HII Interface\r
+\r
+\r
+  @param Id              String ID.\r
+\r
+  @retval  CHAR16 *  String from ID.\r
+  @retval  NULL      If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+GetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  )\r
+{\r
+  CHAR16 *String;\r
+\r
+  String = NULL;\r
+  HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);\r
+\r
+  return String;\r
+}\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/String.h b/IntelFrameworkModulePkg/Universal/BdsDxe/String.h
new file mode 100644 (file)
index 0000000..81a7a60
--- /dev/null
@@ -0,0 +1,75 @@
+/** @file\r
+  String support\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. 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 _STRING_H_\r
+#define _STRING_H_\r
+\r
+#include "Bds.h"\r
+\r
+extern EFI_HII_HANDLE gStringPackHandle;\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+\r
+extern UINT8  BdsDxeStrings[];\r
+\r
+//\r
+// String Definition Guid for BDS Platform\r
+//\r
+#define EFI_BDS_PLATFORM_GUID \\r
+  { \\r
+    0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \\r
+  }\r
+\r
+/**\r
+  Get string by string id from HII Interface\r
+\r
+\r
+  @param Id              String ID.\r
+\r
+  @retval  CHAR16 *  String from ID.\r
+  @retval  NULL      If error occurs.\r
+\r
+**/\r
+CHAR16 *\r
+GetStringById (\r
+  IN  EFI_STRING_ID   Id\r
+  );\r
+\r
+/**\r
+  Initialize HII global accessor for string support\r
+\r
+  @retval  EFI_SUCCESS  String support initialize success.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Call the browser and display the front page\r
+\r
+  @return   Status code that will be returned by\r
+            EFI_FORM_BROWSER2_PROTOCOL.SendForm ().\r
+\r
+**/\r
+EFI_STATUS\r
+CallFrontPage (\r
+  VOID\r
+  );\r
+\r
+#endif // _STRING_H_\r
diff --git a/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni b/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni
new file mode 100644 (file)
index 0000000..0d4274a
Binary files /dev/null and b/IntelFrameworkModulePkg/Universal/BdsDxe/Strings.uni differ