]> git.proxmox.com Git - mirror_edk2.git/commitdiff
IntelFrameworkModulePkg: Add LegacyBootManagerLib.
authorRuiyu Ni <ruiyu.ni@intel.com>
Wed, 6 May 2015 04:50:23 +0000 (04:50 +0000)
committerniruiyu <niruiyu@Edk2>
Wed, 6 May 2015 04:50:23 +0000 (04:50 +0000)
LegacyBootManagerLib is a NULL class library to work with UefiBootManagerLib
providing legacy boot support.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17330 6f19259b-4bc3-4df7-8a09-765794883524

IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h [new file with mode: 0644]
IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c [new file with mode: 0644]
IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf [new file with mode: 0644]

index 7505301232410bf02db9b31b6e9bc948a096085b..20e016d363d5797dda902605ef75e59f3e461928 100644 (file)
@@ -3,7 +3,7 @@
 #\r
 # This file is used to build all modules in IntelFrameworkModulePkg.\r
 #\r
-#Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+#Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 #This program and the accompanying materials are licensed and made available under \r
 #the terms and conditions of the BSD License that accompanies this distribution.  \r
 #The full text of the license may be found at\r
   IntelFrameworkModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
   IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
   IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.inf\r
+  IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf\r
 \r
   IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/InternalLegacyBm.h
new file mode 100644 (file)
index 0000000..e7bdde9
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _INTERNAL_LEGACY_BM_H_\r
+#define _INTERNAL_LEGACY_BM_H_\r
+\r
+#include <PiDxe.h>\r
+#include <Guid/LegacyDevOrder.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/UefiBootManagerLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/PerformanceLib.h>\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+  UINT16     BbsIndex;\r
+} LEGACY_BM_BOOT_OPTION_BBS_DATA;\r
+#pragma pack()\r
+\r
+/**\r
+  Boot the legacy system with the boot option.\r
+\r
+  @param  BootOption The legacy boot option which have BBS device path\r
+                     On return, BootOption->Status contains the boot status.\r
+                     EFI_UNSUPPORTED    There is no legacybios protocol, do not support\r
+                                        legacy boot.\r
+                     EFI_STATUS         The status of LegacyBios->LegacyBoot ().\r
+**/\r
+VOID\r
+EFIAPI\r
+LegacyBmBoot (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION           *BootOption\r
+  );\r
+\r
+/**\r
+  Refresh all legacy boot options.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+LegacyBmRefreshAllBootOption (\r
+  VOID\r
+  );\r
+\r
+#endif // _INTERNAL_LEGACY_BM_H_
\ No newline at end of file
diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBm.c
new file mode 100644 (file)
index 0000000..1ed42d5
--- /dev/null
@@ -0,0 +1,1536 @@
+/** @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) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalLegacyBm.h"\r
+\r
+#define  LEGACY_BM_BOOT_DESCRIPTION_LENGTH  32\r
+\r
+/**\r
+  Initialize legacy boot manager library by call EfiBootManagerRegisterLegacyBootSupport\r
+  function to export two function pointer.\r
+\r
+  @param ImageHandle     The image handle.\r
+  @param SystemTable     The system table.\r
+\r
+  @retval EFI_SUCCESS    The legacy boot manager library is initialized correctly.\r
+  @return Other value if failed to initialize the legacy boot manager library.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+LegacyBootManagerLibConstructor (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+)\r
+{\r
+  EfiBootManagerRegisterLegacyBootSupport (\r
+    LegacyBmRefreshAllBootOption,\r
+    LegacyBmBoot\r
+    );\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get the device type from the input legacy device path.\r
+\r
+  @param DevicePath     The legacy device path.\r
+\r
+  @retval               The legacy device type.\r
+**/\r
+UINT16\r
+LegacyBmDeviceType (\r
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+  )\r
+{\r
+  ASSERT ((DevicePathType (DevicePath) == BBS_DEVICE_PATH) &&\r
+          (DevicePathSubType (DevicePath) == BBS_BBS_DP));\r
+  return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType;\r
+}\r
+\r
+/**\r
+  Validate the BbsEntry base on the Boot Priority info in the BbsEntry.\r
+\r
+  @param BbsEntry       The input bbs entry info.\r
+\r
+  @retval TRUE          The BbsEntry is valid.\r
+  @retval FALSE         The BbsEntry is invalid.\r
+**/\r
+BOOLEAN\r
+LegacyBmValidBbsEntry (\r
+  IN BBS_TABLE   *BbsEntry\r
+  )\r
+{\r
+  switch (BbsEntry->BootPriority) {\r
+    case BBS_IGNORE_ENTRY:\r
+    case BBS_DO_NOT_BOOT_FROM:\r
+    case BBS_LOWEST_PRIORITY:\r
+      return FALSE;\r
+    default:\r
+      return TRUE;\r
+  }\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
+LegacyBmBuildLegacyDevNameString (\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
+  CHAR8   *StringDesc;\r
+  CHAR8   StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
+  CHAR16  StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\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 = (CHAR8 *) (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
+    CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH);\r
+    StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] = 0;\r
+    AsciiStrToUnicodeStr (StringBufferA, StringBufferU);\r
+    Fmt   = L"%s";\r
+    Type  = StringBufferU;\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 || CurBBSEntry->DeviceType == BBS_CDROM)) {\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
+  Get the Bbs index for the input boot option.\r
+\r
+  @param BootOption     The input boot option info.\r
+  @param BbsTable       The input Bbs table.\r
+  @param BbsCount       The input total bbs entry number.\r
+  @param BbsIndexUsed   The array shows how many BBS table indexs have been used.\r
+\r
+  @retval The index for the input boot option.\r
+**/\r
+UINT16\r
+LegacyBmFuzzyMatch (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION   *BootOption,\r
+  BBS_TABLE                      *BbsTable,\r
+  UINT16                         BbsCount,\r
+  BOOLEAN                        *BbsIndexUsed\r
+  )\r
+{\r
+  UINT16                         Index;\r
+  LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData;\r
+  CHAR16                         Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
+\r
+  BbsData = (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData;\r
+\r
+  //\r
+  // Directly check the BBS index stored in BootOption\r
+  //\r
+  if ((BbsData->BbsIndex < BbsCount) &&\r
+      (LegacyBmDeviceType (BootOption->FilePath) == BbsTable[BbsData->BbsIndex].DeviceType)) {\r
+    LegacyBmBuildLegacyDevNameString (\r
+      &BbsTable[BbsData->BbsIndex],\r
+      BbsData->BbsIndex,\r
+      sizeof (Description),\r
+      Description\r
+      );\r
+    if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[BbsData->BbsIndex]) {\r
+      //\r
+      // If devices with the same description string are connected, \r
+      // the BbsIndex of the first device is returned for the other device also.\r
+      // So, check if the BbsIndex is already being used, before assigning the BbsIndex.\r
+      //\r
+      BbsIndexUsed[BbsData->BbsIndex] = TRUE;\r
+      return BbsData->BbsIndex;\r
+    }\r
+  }\r
+\r
+  //\r
+  // BBS table could be changed (entry removed/moved)\r
+  // find the correct BBS index\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&BbsTable[Index]) ||\r
+        (BbsTable[Index].DeviceType != LegacyBmDeviceType (BootOption->FilePath))) {\r
+      continue;\r
+    }\r
+\r
+    LegacyBmBuildLegacyDevNameString (\r
+      &BbsTable[Index],\r
+      Index,\r
+      sizeof (Description),\r
+      Description\r
+      );\r
+    if ((StrCmp (Description, BootOption->Description) == 0) && !BbsIndexUsed[Index]) {\r
+      //\r
+      // If devices with the same description string are connected, \r
+      // the BbsIndex of the first device is assigned for the other device also.\r
+      // So, check if the BbsIndex is already being used, before assigning the corrected BbsIndex.\r
+      //\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Add the corrected BbsIndex in the UsedBbsIndex Buffer\r
+  //\r
+  if (Index != BbsCount) {\r
+    BbsIndexUsed[Index] = TRUE;\r
+  }\r
+\r
+  return Index;\r
+}\r
+\r
+/**\r
+\r
+  Update legacy device order base on the input info.\r
+\r
+  @param   LegacyDevOrder     Legacy device order data buffer.\r
+  @param   LegacyDevOrderSize Legacy device order data buffer size.\r
+  @param   DeviceType         Device type which need to check.\r
+  @param   OldBbsIndex        Old Bds Index.\r
+  @param   NewBbsIndex        New Bds Index, if it is -1,means remove this option.\r
+\r
+**/\r
+VOID\r
+LegacyBmUpdateBbsIndex (\r
+  LEGACY_DEV_ORDER_ENTRY   *LegacyDevOrder,\r
+  UINTN                    *LegacyDevOrderSize,\r
+  UINT16                   DeviceType,\r
+  UINT16                   OldBbsIndex,\r
+  UINT16                   NewBbsIndex // Delete entry if -1\r
+  )\r
+{\r
+  LEGACY_DEV_ORDER_ENTRY   *Entry;\r
+  UINTN                    Index;\r
+\r
+  ASSERT (((LegacyDevOrder == NULL) && (*LegacyDevOrderSize == 0)) ||\r
+          ((LegacyDevOrder != NULL) && (*LegacyDevOrderSize != 0))\r
+         );\r
+\r
+  for (Entry = LegacyDevOrder; \r
+       Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *LegacyDevOrderSize);\r
+       Entry = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_TYPE) + Entry->Length)\r
+       ) {\r
+    if (Entry->BbsType == DeviceType) {\r
+      for (Index = 0; Index < Entry->Length / sizeof (UINT16) - 1; Index++) {\r
+        if (Entry->Data[Index] == OldBbsIndex) {\r
+          if (NewBbsIndex == (UINT16) -1) {\r
+            //\r
+            // Delete the old entry\r
+            //\r
+            CopyMem (\r
+              &Entry->Data[Index], \r
+              &Entry->Data[Index + 1], \r
+              (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &Entry->Data[Index + 1]\r
+              );\r
+            Entry->Length       -= sizeof (UINT16);\r
+            *LegacyDevOrderSize -= sizeof(UINT16);\r
+          } else {\r
+            Entry->Data[Index]   = NewBbsIndex;\r
+          }\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Delete all the legacy boot options.\r
+\r
+  @retval EFI_SUCCESS            All legacy boot options are deleted.\r
+**/\r
+EFI_STATUS\r
+LegacyBmDeleteAllBootOptions (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;\r
+  UINTN                         BootOptionCount;\r
+\r
+  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    if ((DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) &&\r
+        (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP)) {\r
+      Status = EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
+      //\r
+      // Deleting variable with current variable implementation shouldn't fail.\r
+      //\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &gEfiLegacyDevOrderVariableGuid,\r
+                  0,\r
+                  0,\r
+                  NULL\r
+                  );\r
+  //\r
+  // Deleting variable with current variable implementation shouldn't fail.\r
+  //\r
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
+\r
+  return EFI_SUCCESS;\r
+}\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
+LegacyBmDeleteAllInvalidBootOptions (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINT16                        HddCount;\r
+  UINT16                        BbsCount;\r
+  HDD_INFO                      *HddInfo;\r
+  BBS_TABLE                     *BbsTable;\r
+  UINT16                        BbsIndex;\r
+  EFI_LEGACY_BIOS_PROTOCOL      *LegacyBios;\r
+  UINTN                         Index;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption;\r
+  UINTN                         BootOptionCount;\r
+  LEGACY_DEV_ORDER_ENTRY        *LegacyDevOrder;\r
+  UINTN                         LegacyDevOrderSize;\r
+  BOOLEAN                       *BbsIndexUsed;\r
+\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  HddInfo       = NULL;\r
+  BbsTable      = NULL;\r
+\r
+  Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\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
+  GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &LegacyDevOrder, &LegacyDevOrderSize);\r
+\r
+  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
+\r
+  BbsIndexUsed = AllocateZeroPool (BbsCount * sizeof (BOOLEAN));\r
+  ASSERT (BbsIndexUsed != NULL);\r
+\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    //\r
+    // Skip non legacy boot option\r
+    //\r
+    if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) ||\r
+        (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP)) {\r
+      continue;\r
+    }\r
+\r
+    BbsIndex = LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCount, BbsIndexUsed);\r
+    if (BbsIndex == BbsCount) {\r
+      DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description));\r
+      //\r
+      // Delete entry from LegacyDevOrder\r
+      //\r
+      LegacyBmUpdateBbsIndex (\r
+        LegacyDevOrder,\r
+        &LegacyDevOrderSize,\r
+        LegacyBmDeviceType (BootOption[Index].FilePath),\r
+        ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
+        (UINT16) -1\r
+        );\r
+      EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumber, BootOption[Index].OptionType);\r
+    } else {\r
+      if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex != BbsIndex) {\r
+        DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s Bbs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description,\r
+                (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex, (UINTN) BbsIndex));\r
+        //\r
+        // Update the BBS index in LegacyDevOrder\r
+        //\r
+        LegacyBmUpdateBbsIndex (\r
+          LegacyDevOrder,\r
+          &LegacyDevOrderSize,\r
+          LegacyBmDeviceType (BootOption[Index].FilePath),\r
+          ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex,\r
+          BbsIndex\r
+          );\r
+\r
+        //\r
+        // Update the OptionalData in the Boot#### variable\r
+        //\r
+        ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex = BbsIndex;\r
+        EfiBootManagerLoadOptionToVariable (&BootOption[Index]);\r
+      }\r
+    }\r
+  }\r
+  EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);\r
+\r
+  if (LegacyDevOrder != NULL) {\r
+    Status = gRT->SetVariable (\r
+                    VAR_LEGACY_DEV_ORDER,\r
+                    &gEfiLegacyDevOrderVariableGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    LegacyDevOrderSize,\r
+                    LegacyDevOrder\r
+                    );\r
+    //\r
+    // Shrink variable with current variable implementation shouldn't fail.\r
+    //\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    FreePool (LegacyDevOrder);\r
+  }\r
+  FreePool(BbsIndexUsed);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Create legacy boot option.\r
+\r
+  @param BootOption        Ponter to the boot option which will be crated.\r
+  @param BbsEntry          The input bbs entry info.\r
+  @param BbsIndex          The BBS index.\r
+\r
+  @retval EFI_SUCCESS            Create legacy boot option successfully.\r
+  @retval EFI_INVALID_PARAMETER  Invalid input parameter.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBmCreateLegacyBootOption (\r
+  IN OUT EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption,\r
+  IN BBS_TABLE                         *BbsEntry,\r
+  IN UINT16                            BbsIndex\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
+  CHAR16                       Description[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
+  CHAR8                        HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1];\r
+  UINTN                        StringLen;\r
+  LEGACY_BM_BOOT_OPTION_BBS_DATA  *OptionalData;\r
+  BBS_BBS_DEVICE_PATH          *BbsNode;\r
+\r
+  if ((BootOption == NULL) || (BbsEntry == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Description), Description);\r
+\r
+  //\r
+  // Create the BBS device path with description string\r
+  //\r
+  UnicodeStrToAsciiStr (Description, HelpString);\r
+  StringLen = AsciiStrLen (HelpString);\r
+  DevicePath = AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + END_DEVICE_PATH_LENGTH);\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  BbsNode = (BBS_BBS_DEVICE_PATH *) DevicePath;\r
+  SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+  BbsNode->Header.Type    = BBS_DEVICE_PATH;\r
+  BbsNode->Header.SubType = BBS_BBS_DP;\r
+  BbsNode->DeviceType     = BbsEntry->DeviceType;\r
+  CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATUS_FLAGS));\r
+  CopyMem (BbsNode->String, HelpString, StringLen + 1);\r
+\r
+  SetDevicePathEndNode (NextDevicePathNode (BbsNode));\r
+\r
+  //\r
+  // Create the OptionalData\r
+  //\r
+  OptionalData = AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA));\r
+  ASSERT (OptionalData != NULL);\r
+  OptionalData->BbsIndex = BbsIndex;\r
+\r
+  //\r
+  // Create the BootOption\r
+  //\r
+  Status = EfiBootManagerInitializeLoadOption (\r
+             BootOption,\r
+             LoadOptionNumberUnassigned,\r
+             LoadOptionTypeBoot,\r
+             LOAD_OPTION_ACTIVE,\r
+             Description,\r
+             DevicePath,\r
+             (UINT8 *) OptionalData,\r
+             sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)\r
+             );\r
+  FreePool (DevicePath);\r
+  FreePool (OptionalData);\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
+LegacyBmFillDevOrderBuf (\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 (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\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
+  @retval EFI_OUT_OF_RESOURCES   Memmory or storage is not enough.\r
+  @retval EFI_DEVICE_ERROR       Fail to add the device order into EFI variable fail\r
+                                 because of hardware error.\r
+**/\r
+EFI_STATUS\r
+LegacyBmCreateDevOrder (\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
+  LEGACY_DEV_ORDER_ENTRY      *DevOrder;\r
+  LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;\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
+  Status      = EFI_SUCCESS;\r
+\r
+  //\r
+  // Count all boot devices\r
+  //\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\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
+  DevOrderPtr          = DevOrder;\r
+\r
+  DevOrderPtr->BbsType = BBS_FLOPPY;\r
+  DevOrderPtr->Length  = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));\r
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data);\r
+\r
+  DevOrderPtr->BbsType = BBS_HARDDISK;\r
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data);\r
+  \r
+  DevOrderPtr->BbsType = BBS_CDROM;\r
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data);\r
+  \r
+  DevOrderPtr->BbsType = BBS_EMBED_NETWORK;\r
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data);\r
+\r
+  DevOrderPtr->BbsType = BBS_BEV_DEVICE;\r
+  DevOrderPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);\r
+\r
+  ASSERT (TotalSize == (UINTN) ((UINT8 *) DevOrderPtr - (UINT8 *) DevOrder));\r
+\r
+  //\r
+  // Save device order for legacy boot device to variable.\r
+  //\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &gEfiLegacyDevOrderVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                  TotalSize,\r
+                  DevOrder\r
+                  );\r
+  FreePool (DevOrder);\r
+\r
+  return Status;\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
+  @retval EFI_NOT_FOUND         The legacy boot devices are not found.\r
+  @retval EFI_OUT_OF_RESOURCES  Memmory or storage is not enough.\r
+  @retval EFI_DEVICE_ERROR      Fail to add the legacy device boot order into EFI variable\r
+                                because of hardware error.\r
+**/\r
+EFI_STATUS\r
+LegacyBmUpdateDevOrder (\r
+  VOID\r
+  )\r
+{\r
+  LEGACY_DEV_ORDER_ENTRY      *DevOrder;\r
+  LEGACY_DEV_ORDER_ENTRY      *NewDevOrder;\r
+  LEGACY_DEV_ORDER_ENTRY      *Ptr;\r
+  LEGACY_DEV_ORDER_ENTRY      *NewPtr;\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
+  UINT16                      *NewFDPtr;\r
+  UINT16                      *NewHDPtr;\r
+  UINT16                      *NewCDPtr;\r
+  UINT16                      *NewNETPtr;\r
+  UINT16                      *NewBEVPtr;\r
+  UINT16                      *NewDevPtr;\r
+  UINTN                       FDIndex;\r
+  UINTN                       HDIndex;\r
+  UINTN                       CDIndex;\r
+  UINTN                       NETIndex;\r
+  UINTN                       BEVIndex;\r
+\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        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = LegacyBios->GetBbsInfo (\r
+                         LegacyBios,\r
+                         &HddCount,\r
+                         &LocalHddInfo,\r
+                         &BbsCount,\r
+                         &LocalBbsTable\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, NULL);\r
+  if (NULL == DevOrder) {\r
+    return LegacyBmCreateDevOrder (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 (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\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
+  //\r
+  // copy FD\r
+  //\r
+  Ptr             = DevOrder;\r
+  NewPtr          = NewDevOrder;\r
+  NewPtr->BbsType = Ptr->BbsType;\r
+  NewPtr->Length  = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+  for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
+        LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_FLOPPY\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewPtr->Data[FDIndex] = Ptr->Data[Index];\r
+    FDIndex++;\r
+  }\r
+  NewFDPtr = NewPtr->Data;\r
+\r
+  //\r
+  // copy HD\r
+  //\r
+  Ptr             = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
+  NewPtr          = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
+  NewPtr->BbsType = Ptr->BbsType;\r
+  NewPtr->Length  = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+  for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
+        LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_HARDDISK\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewPtr->Data[HDIndex] = Ptr->Data[Index];\r
+    HDIndex++;\r
+  }\r
+  NewHDPtr = NewPtr->Data;\r
+\r
+  //\r
+  // copy CD\r
+  //\r
+  Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
+  NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
+  NewPtr->BbsType = Ptr->BbsType;\r
+  NewPtr->Length  = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+  for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
+        LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_CDROM\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewPtr->Data[CDIndex] = Ptr->Data[Index];\r
+    CDIndex++;\r
+  }\r
+  NewCDPtr = NewPtr->Data;\r
+\r
+  //\r
+  // copy NET\r
+  //\r
+  Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
+  NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
+  NewPtr->BbsType = Ptr->BbsType;\r
+  NewPtr->Length  = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+  for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
+        LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_EMBED_NETWORK\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewPtr->Data[NETIndex] = Ptr->Data[Index];\r
+    NETIndex++;\r
+  }\r
+  NewNETPtr = NewPtr->Data;\r
+  \r
+  //\r
+  // copy BEV\r
+  //\r
+  Ptr    = (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (UINT16) - 1]);\r
+  NewPtr = (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / sizeof (UINT16) -1]);\r
+  NewPtr->BbsType = Ptr->BbsType;\r
+  NewPtr->Length  = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+  for (Index = 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) ||\r
+        LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType != BBS_BEV_DEVICE\r
+        ) {\r
+      continue;\r
+    }\r
+\r
+    NewPtr->Data[BEVIndex] = Ptr->Data[Index];\r
+    BEVIndex++;\r
+  }\r
+  NewBEVPtr = NewPtr->Data;\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\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 != NULL) {\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
+        // insert it before disabled indexes.\r
+        //\r
+        for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+          if ((NewDevPtr[Index2] & 0xFF00) == 0xFF00) {\r
+            break;\r
+          }\r
+        }\r
+        CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index2) * sizeof (UINT16));\r
+        NewDevPtr[Index2] = (UINT16) (Index & 0xFF);\r
+        (*Idx)++;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (DevOrder);\r
+\r
+  Status = gRT->SetVariable (\r
+                  VAR_LEGACY_DEV_ORDER,\r
+                  &gEfiLegacyDevOrderVariableGuid,\r
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\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 BbsIndex        The BBS index to set the highest priority. Ignore when -1.\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
+  @retval EFI_OUT_OF_RESOURCES  Failed to get the efi variable of device order.\r
+\r
+**/\r
+EFI_STATUS\r
+LegacyBmSetPriorityForSameTypeDev (\r
+  IN UINT16                                              DeviceType,\r
+  IN UINTN                                               BbsIndex,\r
+  IN OUT BBS_TABLE                                       *LocalBbsTable,\r
+  IN OUT UINT16                                          *Priority\r
+  )\r
+{\r
+  LEGACY_DEV_ORDER_ENTRY      *DevOrder;\r
+  LEGACY_DEV_ORDER_ENTRY      *DevOrderPtr;\r
+  UINTN                       DevOrderSize;\r
+  UINTN                       Index;\r
+\r
+  GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VOID **) &DevOrder, &DevOrderSize);\r
+  if (NULL == DevOrder) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  DevOrderPtr = DevOrder;\r
+  while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) {\r
+    if (DevOrderPtr->BbsType == DeviceType) {\r
+      break;\r
+    }\r
+\r
+    DevOrderPtr = (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) DevOrderPtr + sizeof (BBS_TYPE) + DevOrderPtr->Length);\r
+  }\r
+\r
+  if ((UINT8 *) DevOrderPtr >= (UINT8 *) DevOrder + DevOrderSize) {\r
+    FreePool (DevOrder);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (BbsIndex != (UINTN) -1) {\r
+    //\r
+    // In case the BBS entry isn't valid because devices were plugged or removed.\r
+    //\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTable[BbsIndex].DeviceType != DeviceType)) {\r
+      FreePool (DevOrder);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+    LocalBbsTable[BbsIndex].BootPriority = *Priority;\r
+    (*Priority)++;\r
+  }\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 < DevOrderPtr->Length / sizeof (UINT16) - 1; Index++) {\r
+    if ((DevOrderPtr->Data[Index] & 0xFF00) == 0xFF00) {\r
+      //\r
+      // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+      //\r
+    } else if (DevOrderPtr->Data[Index] != BbsIndex) {\r
+      LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority = *Priority;\r
+      (*Priority)++;\r
+    }\r
+  }\r
+\r
+  FreePool (DevOrder);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Print the BBS Table.\r
+\r
+  @param LocalBbsTable   The BBS table.\r
+  @param BbsCount        The count of entry in BBS table.\r
+**/\r
+VOID\r
+LegacyBmPrintBbsTable (\r
+  IN BBS_TABLE  *LocalBbsTable,\r
+  IN UINT16     BbsCount\r
+  )\r
+{\r
+  UINT16  Index;\r
+\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+  DEBUG ((DEBUG_INFO, " NO  Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+  DEBUG ((DEBUG_INFO, "=============================================\n"));\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
+      continue;\r
+    }\r
+\r
+    DEBUG (\r
+      (DEBUG_INFO,\r
+      " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",\r
+      (UINTN) Index,\r
+      (UINTN) LocalBbsTable[Index].BootPriority,\r
+      (UINTN) LocalBbsTable[Index].Bus,\r
+      (UINTN) LocalBbsTable[Index].Device,\r
+      (UINTN) LocalBbsTable[Index].Function,\r
+      (UINTN) LocalBbsTable[Index].Class,\r
+      (UINTN) LocalBbsTable[Index].SubClass,\r
+      (UINTN) LocalBbsTable[Index].DeviceType,\r
+      (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags,\r
+      (UINTN) LocalBbsTable[Index].BootHandlerSegment,\r
+      (UINTN) LocalBbsTable[Index].BootHandlerOffset,\r
+      (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),\r
+      (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))\r
+      );\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/**\r
+  Set the boot priority for BBS entries based on boot option entry and boot order.\r
+\r
+  @param  BootOption            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
+  @retval EFI_NOT_FOUND         BBS entries can't be found.\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to get the legacy device boot order.\r
+**/\r
+EFI_STATUS\r
+LegacyBmRefreshBbsTableForBoot (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION        *BootOption\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINT16                        BbsIndex;\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                        *DeviceType;\r
+  UINTN                         DeviceTypeCount;\r
+  UINTN                         DeviceTypeIndex;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *Option;\r
+  UINTN                         OptionCount;\r
+\r
+  HddCount      = 0;\r
+  BbsCount      = 0;\r
+  LocalHddInfo  = NULL;\r
+  LocalBbsTable = NULL;\r
+  DevType       = BBS_UNKNOWN;\r
+\r
+  Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = LegacyBios->GetBbsInfo (\r
+                         LegacyBios,\r
+                         &HddCount,\r
+                         &LocalHddInfo,\r
+                         &BbsCount,\r
+                         &LocalBbsTable\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\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 (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {\r
+      LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+    }\r
+  }\r
+  //\r
+  // boot priority always starts at 0\r
+  //\r
+  Priority = 0;  \r
+  if ((DevicePathType (BootOption->FilePath) == BBS_DEVICE_PATH) &&\r
+      (DevicePathSubType (BootOption->FilePath) == BBS_BBS_DP)) {\r
+    //\r
+    // If BootOption stands for a legacy boot option, we prioritize the devices with the same type first.\r
+    //\r
+    DevType  = LegacyBmDeviceType (BootOption->FilePath);\r
+    BbsIndex = ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData)->BbsIndex;\r
+    Status = LegacyBmSetPriorityForSameTypeDev (\r
+               DevType,\r
+               BbsIndex,\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
+  Option          = EfiBootManagerGetLoadOptions (&OptionCount, LoadOptionTypeBoot);\r
+  DeviceType      = AllocatePool (sizeof (UINT16) * OptionCount);\r
+  ASSERT (DeviceType != NULL);\r
+  DeviceType[0]   = DevType;\r
+  DeviceTypeCount = 1;\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    if ((DevicePathType (Option[Index].FilePath) != BBS_DEVICE_PATH) ||\r
+        (DevicePathSubType (Option[Index].FilePath) != BBS_BBS_DP)) {\r
+      continue;\r
+    }\r
+    \r
+    DevType = LegacyBmDeviceType (Option[Index].FilePath);\r
+    for (DeviceTypeIndex = 0; DeviceTypeIndex < DeviceTypeCount; DeviceTypeIndex++) {\r
+      if (DeviceType[DeviceTypeIndex] == DevType) {\r
+        break;\r
+      }\r
+    }\r
+    if (DeviceTypeIndex < DeviceTypeCount) {\r
+      //\r
+      // We don't want to process twice for a device type\r
+      //\r
+      continue;\r
+    }\r
+\r
+    DeviceType[DeviceTypeCount] = DevType;\r
+    DeviceTypeCount++;\r
+\r
+    Status = LegacyBmSetPriorityForSameTypeDev (\r
+               DevType,\r
+               (UINTN) -1,\r
+               LocalBbsTable,\r
+               &Priority\r
+               );\r
+  }\r
+  EfiBootManagerFreeLoadOptions (Option, OptionCount);\r
+\r
+  DEBUG_CODE_BEGIN();\r
+    LegacyBmPrintBbsTable (LocalBbsTable, BbsCount);\r
+  DEBUG_CODE_END();\r
+  \r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Boot the legacy system with the boot option.\r
+\r
+  @param  BootOption The legacy boot option which have BBS device path\r
+                     On return, BootOption->Status contains the boot status.\r
+                     EFI_UNSUPPORTED    There is no legacybios protocol, do not support\r
+                                        legacy boot.\r
+                     EFI_STATUS         The status of LegacyBios->LegacyBoot ().\r
+**/\r
+VOID\r
+EFIAPI\r
+LegacyBmBoot (\r
+  IN  EFI_BOOT_MANAGER_LOAD_OPTION           *BootOption\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
+    BootOption->Status = EFI_UNSUPPORTED;\r
+    return;\r
+  }\r
+  //\r
+  // Notes: if we separate the int 19, then we don't need to refresh BBS\r
+  //\r
+  Status = LegacyBmRefreshBbsTableForBoot (BootOption);\r
+  if (EFI_ERROR (Status)) {\r
+    BootOption->Status = Status;\r
+    return;\r
+  }\r
+\r
+  BootOption->Status = LegacyBios->LegacyBoot (\r
+                                     LegacyBios,\r
+                                     (BBS_BBS_DEVICE_PATH *) BootOption->FilePath,\r
+                                     BootOption->OptionalDataSize,\r
+                                     BootOption->OptionalData\r
+                                     );\r
+}\r
+\r
+/**\r
+  This function enumerates all the legacy boot options.\r
+\r
+  @param BootOptionCount   Return the legacy boot option count.\r
+\r
+  @retval    Pointer to the legacy boot option buffer.\r
+**/\r
+EFI_BOOT_MANAGER_LOAD_OPTION *\r
+LegacyBmEnumerateAllBootOptions (\r
+  UINTN                         *BootOptionCount\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  UINT16                        HddCount;\r
+  UINT16                        BbsCount;\r
+  HDD_INFO                      *HddInfo;\r
+  BBS_TABLE                     *BbsTable;\r
+  EFI_LEGACY_BIOS_PROTOCOL      *LegacyBios;\r
+  UINT16                        Index;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;\r
+\r
+  ASSERT (BootOptionCount != NULL);\r
+\r
+  BootOptions      = NULL;\r
+  *BootOptionCount = 0;\r
+  BbsCount         = 0;\r
+\r
+  Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = LegacyBios->GetBbsInfo (\r
+                         LegacyBios,\r
+                         &HddCount,\r
+                         &HddInfo,\r
+                         &BbsCount,\r
+                         &BbsTable\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  for (Index = 0; Index < BbsCount; Index++) {\r
+    if (!LegacyBmValidBbsEntry (&BbsTable[Index])) {\r
+      continue;\r
+    }\r
+\r
+    BootOptions = ReallocatePool (\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
+                    sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
+                    BootOptions\r
+                    );\r
+    ASSERT (BootOptions != NULL);\r
+\r
+    Status = LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCount)++], &BbsTable[Index], Index);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  return BootOptions;\r
+}\r
+\r
+/**\r
+  Return the index of the boot option in the boot option array.\r
+\r
+  The function compares the Description, FilePath, OptionalData.\r
+\r
+  @param Key         The input boot option which is compared with.\r
+  @param Array       The input boot option array.\r
+  @param Count       The count of the input boot options.\r
+\r
+  @retval  The index of the input boot option in the array.\r
+\r
+**/\r
+INTN\r
+LegacyBmFindBootOption (\r
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
+  IN UINTN                              Count\r
+  )\r
+{\r
+  UINTN                             Index;\r
+\r
+  for (Index = 0; Index < Count; Index++) {\r
+    if ((StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
+        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
+        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
+        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {\r
+      return (INTN) Index;\r
+    }\r
+  }\r
+\r
+  return -1;\r
+}\r
+\r
+/**\r
+  Refresh all legacy boot options.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+LegacyBmRefreshAllBootOption (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  EFI_LEGACY_BIOS_PROTOCOL                   *LegacyBios;\r
+  UINTN                                      RootBridgeHandleCount;\r
+  EFI_HANDLE                                 *RootBridgeHandleBuffer;\r
+  UINTN                                      HandleCount;\r
+  EFI_HANDLE                                 *HandleBuffer;\r
+  UINTN                                      RootBridgeIndex;\r
+  UINTN                                      Index;\r
+  UINTN                                      Flags;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION               *BootOptions;\r
+  UINTN                                      BootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION               *ExistingBootOptions;\r
+  UINTN                                      ExistingBootOptionCount;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
+  if (EFI_ERROR (Status)) {\r
+    LegacyBmDeleteAllBootOptions ();\r
+    return;\r
+  }\r
+  PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
+\r
+  //\r
+  // Before enumerating the legacy boot option, we need to dispatch all the legacy option roms \r
+  // to ensure the GetBbsInfo() counts all the legacy devices.\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiPciRootBridgeIoProtocolGuid,\r
+         NULL,\r
+         &RootBridgeHandleCount,\r
+         &RootBridgeHandleBuffer\r
+         );\r
+  for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {\r
+    gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);\r
+    gBS->LocateHandleBuffer (\r
+           ByProtocol,\r
+           &gEfiPciIoProtocolGuid,\r
+           NULL,\r
+           &HandleCount,\r
+           &HandleBuffer\r
+           );\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      //\r
+      // Start the thunk driver so that the legacy option rom gets dispatched.\r
+      // Note: We don't directly call InstallPciRom because some thunk drivers \r
+      // (e.g. BlockIo thunk driver) depend on the immediate result after dispatching\r
+      //\r
+      Status = LegacyBios->CheckPciRom (\r
+                             LegacyBios,\r
+                             HandleBuffer[Index],\r
+                             NULL,\r
+                             NULL,\r
+                             &Flags\r
+                             );\r
+      if (!EFI_ERROR (Status)) {\r
+        gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption\r
+  // Firstly delete the invalid legacy boot options,\r
+  // then enumreate and save the newly appeared legacy boot options\r
+  // the last step is legacy boot option special action to refresh the LegacyDevOrder variable\r
+  //\r
+  LegacyBmDeleteAllInvalidBootOptions ();\r
+\r
+  ExistingBootOptions = EfiBootManagerGetLoadOptions (&ExistingBootOptionCount, LoadOptionTypeBoot);\r
+  BootOptions         = LegacyBmEnumerateAllBootOptions   (&BootOptionCount);\r
+\r
+  for (Index = 0; Index < BootOptionCount; Index++) {\r
+    if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, ExistingBootOptionCount) == -1) {\r
+      Status = EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
+      DEBUG ((\r
+        EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r\n",\r
+        (UINTN) BootOptions[Index].OptionNumber,\r
+        (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].OptionalData)->BbsIndex,\r
+        BootOptions[Index].Description,\r
+        Status\r
+        ));\r
+      //\r
+      // Continue upon failure to add boot option.\r
+      //\r
+    }\r
+  }\r
+\r
+  EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCount);\r
+  EfiBootManagerFreeLoadOptions (BootOptions,         BootOptionCount);\r
+\r
+  //\r
+  // Failure to create LegacyDevOrder variable only impacts the boot order.\r
+  //\r
+  LegacyBmUpdateDevOrder ();\r
+\r
+  PERF_END   (NULL, "LegacyBootOptionEnum", "BDS", 0);\r
+}\r
diff --git a/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf b/IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBootManagerLib.inf
new file mode 100644 (file)
index 0000000..2dc03a8
--- /dev/null
@@ -0,0 +1,65 @@
+## @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) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#  \r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = LegacyBootManagerLib\r
+  FILE_GUID                      = F1B87BE4-0ACC-409A-A52B-7BFFABCC96A0\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL|DXE_DRIVER UEFI_APPLICATION\r
+  CONSTRUCTOR                    = LegacyBootManagerLibConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+  LegacyBm.c\r
+  InternalLegacyBm.h\r
+  \r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  DevicePathLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  DebugLib\r
+  PrintLib\r
+  PerformanceLib\r
+  UefiBootManagerLib\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        ## SOMETIMES_PRODUCES ## Variable:L"Boot####" (Boot option variable)\r
+                                                ## SOMETIMES_CONSUMES ## Variable:L"BootOrder" (The boot option array)\r
+  gEfiLegacyDevOrderVariableGuid\r
+\r
+[Protocols]\r
+  gEfiLegacyBiosProtocolGuid                    ## SOMETIMES_CONSUMES\r
+\r
+[FeaturePcd]\r
+\r
+[Pcd]\r