]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c
Remove IntelFrameworkModulePkg
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsBoot.c
diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c
deleted file mode 100644 (file)
index 3b22736..0000000
+++ /dev/null
@@ -1,4373 +0,0 @@
-/** @file\r
-  BDS Lib functions which relate with create or process the boot option.\r
-\r
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "InternalBdsLib.h"\r
-#include "String.h"\r
-\r
-BOOLEAN mEnumBootDevice = FALSE;\r
-EFI_HII_HANDLE gBdsLibStringPackHandle = NULL;\r
-\r
-/**\r
-\r
-  End Perf entry of BDS\r
-\r
-  @param  Event                 The triggered event.\r
-  @param  Context               Context for this event.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-BmEndOfBdsPerfCode (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  //\r
-  // Record the performance data for End of BDS\r
-  //\r
-  PERF_END(NULL, "BDS", NULL, 0);\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  The constructor function register UNI strings into imageHandle.\r
-\r
-  It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.\r
-\r
-  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
-  @param  SystemTable   A pointer to the EFI System Table.\r
-\r
-  @retval EFI_SUCCESS   The constructor successfully added string package.\r
-  @retval Other value   The constructor can't add string package.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GenericBdsLibConstructor (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
-\r
-  gBdsLibStringPackHandle = HiiAddPackages (\r
-                              &gBdsLibStringPackageGuid,\r
-                              ImageHandle,\r
-                              GenericBdsLibStrings,\r
-                              NULL\r
-                              );\r
-\r
-  ASSERT (gBdsLibStringPackHandle != NULL);\r
-\r
-  return EFI_SUCCESS;\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
-  @retval  EFI_SUCCESS           The Boot Option Variable was found and removed\r
-  @retval  EFI_UNSUPPORTED       The Boot Option Variable store was inaccessible\r
-  @retval  EFI_NOT_FOUND         The Boot Option Variable was not found\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsDeleteBootOption (\r
-  IN UINTN                       OptionNumber,\r
-  IN OUT UINT16                  *BootOrder,\r
-  IN OUT UINTN                   *BootOrderSize\r
-  )\r
-{\r
-  CHAR16      BootOption[9];\r
-  UINTN       Index;\r
-  EFI_STATUS  Status;\r
-\r
-  UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
-  Status = gRT->SetVariable (\r
-                  BootOption,\r
-                  &gEfiGlobalVariableGuid,\r
-                  0,\r
-                  0,\r
-                  NULL\r
-                  );\r
-  //\r
-  // Deleting variable with existing variable implementation shouldn't fail.\r
-  //\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // adjust boot order array\r
-  //\r
-  for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
-    if (BootOrder[Index] == OptionNumber) {\r
-      CopyMem (&BootOrder[Index], &BootOrder[Index+1], *BootOrderSize - (Index+1) * sizeof (UINT16));\r
-      *BootOrderSize -= sizeof (UINT16);\r
-      break;\r
-    }\r
-  }\r
-\r
-  return Status;\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 || 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
-\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
-  CHAR16               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
-  UnicodeStrToAsciiStrS (BootDesc, HelpString, sizeof (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
-                        NULL,\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
-                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\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
-EFIAPI\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        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  BootOrder = BdsLibGetVariableAndSize (\r
-                L"BootOrder",\r
-                &gEfiGlobalVariableGuid,\r
-                &BootOrderSize\r
-                );\r
-  if (BootOrder == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  LegacyBios->GetBbsInfo (\r
-                LegacyBios,\r
-                &HddCount,\r
-                &LocalHddInfo,\r
-                &BbsCount,\r
-                &LocalBbsTable\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
-      BootOptionSize = 0;\r
-      Status = gRT->GetVariable (\r
-                      BootOption,\r
-                      &gEfiGlobalVariableGuid,\r
-                      NULL,\r
-                      &BootOptionSize,\r
-                      BootOptionVar\r
-                      );\r
-      if (Status == EFI_NOT_FOUND) {\r
-        //\r
-        // Update BootOrder\r
-        //\r
-        BdsDeleteBootOption (\r
-          BootOrder[Index],\r
-          BootOrder,\r
-          &BootOrderSize\r
-          );\r
-        continue;\r
-      } else {\r
-        FreePool (BootOrder);\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Skip Non-Legacy boot option\r
-    //\r
-    if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
-      if (BootOptionVar!= NULL) {\r
-        FreePool (BootOptionVar);\r
-      }\r
-      Index++;\r
-      continue;\r
-    }\r
-\r
-    if (BbsIndex < BbsCount) {\r
-      //\r
-      // Check if BBS Description String is changed\r
-      //\r
-      DescStringMatch = FALSE;\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
-\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
-  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
-  // Shrinking variable with existing variable implementation shouldn't fail.\r
-  //\r
-  ASSERT_EFI_ERROR (Status);\r
-  FreePool (BootOrder);\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 DevName         Device name.\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
-BdsFindLegacyBootOptionByDevTypeAndName (\r
-  IN UINT16                 *BootOrder,\r
-  IN UINTN                  BootOptionNum,\r
-  IN UINT16                 DevType,\r
-  IN CHAR16                 *DevName,\r
-  OUT UINT32                *Attribute,\r
-  OUT UINT16                *BbsIndex,\r
-  OUT UINT16                *OptionNumber\r
-  )\r
-{\r
-  UINTN     Index;\r
-  CHAR16    BootOption[9];\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 (Index = 0; Index < BootOptionNum; Index++) {\r
-    UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", (UINTN) BootOrder[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 (\r
-        (BbsEntry->DeviceType != DevType) ||\r
-        (StrCmp (DevName, (CHAR16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) != 0)\r
-       ) {\r
-      FreePool (BootOptionVar);\r
-      continue;\r
-    }\r
-\r
-    *Attribute    = *(UINT32 *) BootOptionVar;\r
-    *OptionNumber = BootOrder[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
-              NULL,\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
-  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
-  @retval EFI_NOT_FOUND        No legacy boot options is found.\r
-  @retval EFI_OUT_OF_RESOURCE  No enough memory.\r
-  @return Other value          LegacyBoot options are not added.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-BdsAddNonExistingLegacyBootOptions (\r
-  VOID\r
-  )\r
-{\r
-  UINT16                    *BootOrder;\r
-  UINTN                     BootOrderSize;\r
-  EFI_STATUS                Status;\r
-  CHAR16                    Desc[100];\r
-  UINT16                    HddCount;\r
-  UINT16                    BbsCount;\r
-  HDD_INFO                  *LocalHddInfo;\r
-  BBS_TABLE                 *LocalBbsTable;\r
-  UINT16                    BbsIndex;\r
-  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
-  UINT16                    Index;\r
-  UINT32                    Attribute;\r
-  UINT16                    OptionNumber;\r
-  BOOLEAN                   Exist;\r
-\r
-  HddCount      = 0;\r
-  BbsCount      = 0;\r
-  LocalHddInfo  = NULL;\r
-  LocalBbsTable = NULL;\r
-\r
-  Status        = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (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 (BootOrder == NULL) {\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
-    BdsBuildLegacyDevNameString (&LocalBbsTable[Index], Index, sizeof (Desc), Desc);\r
-\r
-    Exist = BdsFindLegacyBootOptionByDevTypeAndName (\r
-              BootOrder,\r
-              BootOrderSize / sizeof (UINT16),\r
-              LocalBbsTable[Index].DeviceType,\r
-              Desc,\r
-              &Attribute,\r
-              &BbsIndex,\r
-              &OptionNumber\r
-              );\r
-    if (!Exist) {\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
-        ASSERT (BootOrder != NULL);\r
-        BbsIndex     = Index;\r
-        OptionNumber = BootOrder[BootOrderSize / sizeof (UINT16) - 1];\r
-      }\r
-    }\r
-\r
-    ASSERT (BbsIndex == Index);\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
-                  BootOrderSize,\r
-                  BootOrder\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 gEfiLegacyDevOrderVariableGuid 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
-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
-  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 (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
-  DevOrderPtr          = DevOrder;\r
-\r
-  DevOrderPtr->BbsType = BBS_FLOPPY;\r
-  DevOrderPtr->Length  = (UINT16) (sizeof (DevOrderPtr->Length) + FDCount * sizeof (UINT16));\r
-  DevOrderPtr          = (LEGACY_DEV_ORDER_ENTRY *) BdsFillDevOrderBuf (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 *) BdsFillDevOrderBuf (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 *) BdsFillDevOrderBuf (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 *) BdsFillDevOrderBuf (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 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data);\r
-\r
-  ASSERT (TotalSize == ((UINTN) DevOrderPtr - (UINTN) 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
-EFIAPI\r
-BdsUpdateLegacyDevOrder (\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
-  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
-  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
-  DevOrder = BdsLibGetVariableAndSize (\r
-               VAR_LEGACY_DEV_ORDER,\r
-               &gEfiLegacyDevOrderVariableGuid,\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
-\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 (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\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 (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\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 (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\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 (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\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 (LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_IGNORE_ENTRY ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
-        LocalBbsTable[Ptr->Data[Index] & 0xFF].BootPriority == BBS_LOWEST_PRIORITY ||\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 ((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 != 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
-BdsSetBootPriority4SameTypeDev (\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
-  DevOrder = BdsLibGetVariableAndSize (\r
-               VAR_LEGACY_DEV_ORDER,\r
-               &gEfiLegacyDevOrderVariableGuid,\r
-               &DevOrderSize\r
-               );\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
-    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
-PrintBbsTable (\r
-  IN BBS_TABLE  *LocalBbsTable,\r
-  IN UINT16     BbsCount\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 < BbsCount; 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
-  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
-  @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
-EFIAPI\r
-BdsRefreshBbsTableForBoot (\r
-  IN BDS_COMMON_OPTION        *Entry\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                    *BootOrder;\r
-  UINTN                     BootOrderSize;\r
-  UINT8                     *BootOptionVar;\r
-  UINTN                     BootOptionSize;\r
-  CHAR16                    BootOption[9];\r
-  UINT8                     *Ptr;\r
-  UINT16                    DevPathLen;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
-  UINT16                    *DeviceType;\r
-  UINTN                     DeviceTypeCount;\r
-  UINTN                     DeviceTypeIndex;\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
-  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
-    BbsIndex = *(UINT16 *) ((BBS_TABLE *) Entry->LoadOptions + 1);\r
-    Status = BdsSetBootPriority4SameTypeDev (\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
-  BootOrder = BdsLibGetVariableAndSize (\r
-                L"BootOrder",\r
-                &gEfiGlobalVariableGuid,\r
-                &BootOrderSize\r
-                );\r
-  DeviceType = AllocatePool (BootOrderSize + sizeof (UINT16));\r
-  ASSERT (DeviceType != NULL);\r
-\r
-  DeviceType[0]   = DevType;\r
-  DeviceTypeCount = 1;\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
-    DevType = ((BBS_TABLE *) Ptr)->DeviceType;\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
-      FreePool (BootOptionVar);\r
-      continue;\r
-    }\r
-\r
-    DeviceType[DeviceTypeCount] = DevType;\r
-    DeviceTypeCount++;\r
-\r
-    Status = BdsSetBootPriority4SameTypeDev (\r
-              DevType,\r
-              (UINTN) -1,\r
-              LocalBbsTable,\r
-              &Priority\r
-              );\r
-    FreePool (BootOptionVar);\r
-    if (EFI_ERROR (Status)) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  FreePool (DeviceType);\r
-\r
-  if (BootOrder != NULL) {\r
-    FreePool (BootOrder);\r
-  }\r
-\r
-  DEBUG_CODE_BEGIN();\r
-    PrintBbsTable (LocalBbsTable, BbsCount);\r
-  DEBUG_CODE_END();\r
-\r
-  return Status;\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
-  EFI_EVENT                 LegacyBootEvent;\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 for legacy boot.\r
-  //\r
-  PERF_CODE (\r
-    //\r
-    // Create an event to be signalled when Legacy Boot occurs to write performance data.\r
-    //\r
-    Status = EfiCreateEventLegacyBootEx(\r
-               TPL_NOTIFY,\r
-               BmEndOfBdsPerfCode,\r
-               NULL,\r
-               &LegacyBootEvent\r
-               );\r
-    ASSERT_EFI_ERROR (Status);\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
-  Internal function to check if the input boot option is a valid EFI NV Boot####.\r
-\r
-  @param OptionToCheck  Boot option to be checked.\r
-\r
-  @retval TRUE      This boot option matches a valid EFI NV Boot####.\r
-  @retval FALSE     If not.\r
-\r
-**/\r
-BOOLEAN\r
-IsBootOptionValidNVVarialbe (\r
-  IN  BDS_COMMON_OPTION             *OptionToCheck\r
-  )\r
-{\r
-  LIST_ENTRY        TempList;\r
-  BDS_COMMON_OPTION *BootOption;\r
-  BOOLEAN           Valid;\r
-  CHAR16            OptionName[20];\r
-\r
-  Valid = FALSE;\r
-\r
-  InitializeListHead (&TempList);\r
-  UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionToCheck->BootCurrent);\r
-\r
-  BootOption = BdsLibVariableToOption (&TempList, OptionName);\r
-  if (BootOption == NULL) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // If the Boot Option Number and Device Path matches, OptionToCheck matches a\r
-  // valid EFI NV Boot####.\r
-  //\r
-  if ((OptionToCheck->BootCurrent == BootOption->BootCurrent) &&\r
-      (CompareMem (OptionToCheck->DevicePath, BootOption->DevicePath, GetDevicePathSize (OptionToCheck->DevicePath)) == 0))\r
-      {\r
-    Valid = TRUE;\r
-  }\r
-\r
-  FreePool (BootOption);\r
-\r
-  return Valid;\r
-}\r
-\r
-/**\r
-  Check whether a USB device match the specified USB Class device path. This\r
-  function follows "Load Option Processing" behavior in UEFI specification.\r
-\r
-  @param UsbIo       USB I/O protocol associated with the USB device.\r
-  @param UsbClass    The USB Class device path to match.\r
-\r
-  @retval TRUE       The USB device match the USB Class device path.\r
-  @retval FALSE      The USB device does not match the USB Class device path.\r
-\r
-**/\r
-BOOLEAN\r
-BdsMatchUsbClass (\r
-  IN EFI_USB_IO_PROTOCOL        *UsbIo,\r
-  IN USB_CLASS_DEVICE_PATH      *UsbClass\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  EFI_USB_DEVICE_DESCRIPTOR     DevDesc;\r
-  EFI_USB_INTERFACE_DESCRIPTOR  IfDesc;\r
-  UINT8                         DeviceClass;\r
-  UINT8                         DeviceSubClass;\r
-  UINT8                         DeviceProtocol;\r
-\r
-  if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||\r
-      (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP)){\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Check Vendor Id and Product Id.\r
-  //\r
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
-\r
-  if ((UsbClass->VendorId != 0xffff) &&\r
-      (UsbClass->VendorId != DevDesc.IdVendor)) {\r
-    return FALSE;\r
-  }\r
-\r
-  if ((UsbClass->ProductId != 0xffff) &&\r
-      (UsbClass->ProductId != DevDesc.IdProduct)) {\r
-    return FALSE;\r
-  }\r
-\r
-  DeviceClass    = DevDesc.DeviceClass;\r
-  DeviceSubClass = DevDesc.DeviceSubClass;\r
-  DeviceProtocol = DevDesc.DeviceProtocol;\r
-  if (DeviceClass == 0) {\r
-    //\r
-    // If Class in Device Descriptor is set to 0, use the Class, SubClass and\r
-    // Protocol in Interface Descriptor instead.\r
-    //\r
-    Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
-    if (EFI_ERROR (Status)) {\r
-      return FALSE;\r
-    }\r
-\r
-    DeviceClass    = IfDesc.InterfaceClass;\r
-    DeviceSubClass = IfDesc.InterfaceSubClass;\r
-    DeviceProtocol = IfDesc.InterfaceProtocol;\r
-  }\r
-\r
-  //\r
-  // Check Class, SubClass and Protocol.\r
-  //\r
-  if ((UsbClass->DeviceClass != 0xff) &&\r
-      (UsbClass->DeviceClass != DeviceClass)) {\r
-    return FALSE;\r
-  }\r
-\r
-  if ((UsbClass->DeviceSubClass != 0xff) &&\r
-      (UsbClass->DeviceSubClass != DeviceSubClass)) {\r
-    return FALSE;\r
-  }\r
-\r
-  if ((UsbClass->DeviceProtocol != 0xff) &&\r
-      (UsbClass->DeviceProtocol != DeviceProtocol)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-/**\r
-  Check whether a USB device match the specified USB WWID device path. This\r
-  function follows "Load Option Processing" behavior in UEFI specification.\r
-\r
-  @param UsbIo       USB I/O protocol associated with the USB device.\r
-  @param UsbWwid     The USB WWID device path to match.\r
-\r
-  @retval TRUE       The USB device match the USB WWID device path.\r
-  @retval FALSE      The USB device does not match the USB WWID device path.\r
-\r
-**/\r
-BOOLEAN\r
-BdsMatchUsbWwid (\r
-  IN EFI_USB_IO_PROTOCOL        *UsbIo,\r
-  IN USB_WWID_DEVICE_PATH       *UsbWwid\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
-  EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
-  UINT16                       *LangIdTable;\r
-  UINT16                       TableSize;\r
-  UINT16                       Index;\r
-  CHAR16                       *CompareStr;\r
-  UINTN                        CompareLen;\r
-  CHAR16                       *SerialNumberStr;\r
-  UINTN                        Length;\r
-\r
-  if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||\r
-      (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP )){\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Check Vendor Id and Product Id.\r
-  //\r
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
-  if ((DevDesc.IdVendor != UsbWwid->VendorId) ||\r
-      (DevDesc.IdProduct != UsbWwid->ProductId)) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Check Interface Number.\r
-  //\r
-  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
-  if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Check Serial Number.\r
-  //\r
-  if (DevDesc.StrSerialNumber == 0) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Get all supported languages.\r
-  //\r
-  TableSize = 0;\r
-  LangIdTable = NULL;\r
-  Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);\r
-  if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
-  //\r
-  CompareStr = (CHAR16 *) (UINTN) (UsbWwid + 1);\r
-  CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
-  if (CompareStr[CompareLen - 1] == L'\0') {\r
-    CompareLen--;\r
-  }\r
-\r
-  //\r
-  // Compare serial number in each supported language.\r
-  //\r
-  for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {\r
-    SerialNumberStr = NULL;\r
-    Status = UsbIo->UsbGetStringDescriptor (\r
-                      UsbIo,\r
-                      LangIdTable[Index],\r
-                      DevDesc.StrSerialNumber,\r
-                      &SerialNumberStr\r
-                      );\r
-    if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {\r
-      continue;\r
-    }\r
-\r
-    Length = StrLen (SerialNumberStr);\r
-    if ((Length >= CompareLen) &&\r
-        (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {\r
-      FreePool (SerialNumberStr);\r
-      return TRUE;\r
-    }\r
-\r
-    FreePool (SerialNumberStr);\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Find a USB device path which match the specified short-form device path start\r
-  with USB Class or USB WWID device path and load the boot file then return the\r
-  image handle. If ParentDevicePath is NULL, this function will search in all USB\r
-  devices of the platform. If ParentDevicePath is not NULL,this function will only\r
-  search in its child devices.\r
-\r
-  @param ParentDevicePath      The device path of the parent.\r
-  @param ShortFormDevicePath   The USB Class or USB WWID device path to match.\r
-\r
-  @return  The image Handle if find load file from specified short-form device path\r
-           or NULL if not found.\r
-\r
-**/\r
-EFI_HANDLE *\r
-BdsFindUsbDevice (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *ParentDevicePath,\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *ShortFormDevicePath\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  UINTN                     UsbIoHandleCount;\r
-  EFI_HANDLE                *UsbIoHandleBuffer;\r
-  EFI_DEVICE_PATH_PROTOCOL  *UsbIoDevicePath;\r
-  EFI_USB_IO_PROTOCOL       *UsbIo;\r
-  UINTN                     Index;\r
-  UINTN                     ParentSize;\r
-  UINTN                     Size;\r
-  EFI_HANDLE                ImageHandle;\r
-  EFI_HANDLE                Handle;\r
-  EFI_DEVICE_PATH_PROTOCOL  *FullDevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *NextDevicePath;\r
-\r
-  FullDevicePath = NULL;\r
-  ImageHandle    = NULL;\r
-\r
-  //\r
-  // Get all UsbIo Handles.\r
-  //\r
-  UsbIoHandleCount = 0;\r
-  UsbIoHandleBuffer = NULL;\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiUsbIoProtocolGuid,\r
-                  NULL,\r
-                  &UsbIoHandleCount,\r
-                  &UsbIoHandleBuffer\r
-                  );\r
-  if (EFI_ERROR (Status) || (UsbIoHandleCount == 0) || (UsbIoHandleBuffer == NULL)) {\r
-    return NULL;\r
-  }\r
-\r
-  ParentSize = (ParentDevicePath == NULL) ? 0 : GetDevicePathSize (ParentDevicePath);\r
-  for (Index = 0; Index < UsbIoHandleCount; Index++) {\r
-    //\r
-    // Get the Usb IO interface.\r
-    //\r
-    Status = gBS->HandleProtocol(\r
-                    UsbIoHandleBuffer[Index],\r
-                    &gEfiUsbIoProtocolGuid,\r
-                    (VOID **) &UsbIo\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    UsbIoDevicePath = DevicePathFromHandle (UsbIoHandleBuffer[Index]);\r
-    if (UsbIoDevicePath == NULL) {\r
-      continue;\r
-    }\r
-\r
-    if (ParentDevicePath != NULL) {\r
-      //\r
-      // Compare starting part of UsbIoHandle's device path with ParentDevicePath.\r
-      //\r
-      Size = GetDevicePathSize (UsbIoDevicePath);\r
-      if ((Size < ParentSize) ||\r
-          (CompareMem (UsbIoDevicePath, ParentDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0)) {\r
-        continue;\r
-      }\r
-    }\r
-\r
-    if (BdsMatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *) ShortFormDevicePath) ||\r
-        BdsMatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *) ShortFormDevicePath)) {\r
-      //\r
-      // Try to find if there is the boot file in this DevicePath\r
-      //\r
-      NextDevicePath = NextDevicePathNode (ShortFormDevicePath);\r
-      if (!IsDevicePathEnd (NextDevicePath)) {\r
-        FullDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePath);\r
-        //\r
-        // Connect the full device path, so that Simple File System protocol\r
-        // could be installed for this USB device.\r
-        //\r
-        BdsLibConnectDevicePath (FullDevicePath);\r
-        REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
-        Status = gBS->LoadImage (\r
-                       TRUE,\r
-                       gImageHandle,\r
-                       FullDevicePath,\r
-                       NULL,\r
-                       0,\r
-                       &ImageHandle\r
-                       );\r
-        FreePool (FullDevicePath);\r
-      } else {\r
-        FullDevicePath = UsbIoDevicePath;\r
-        Status = EFI_NOT_FOUND;\r
-      }\r
-\r
-      //\r
-      // If we didn't find an image directly, we need to try as if it is a removable device boot option\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(UsbIoDevicePath);\r
-        if (Handle == NULL) {\r
-          continue;\r
-        }\r
-        //\r
-        // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
-        //  machinename is ia32, ia64, x64, ...\r
-        //\r
-        FullDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
-        if (FullDevicePath != NULL) {\r
-          REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
-          Status = gBS->LoadImage (\r
-                          TRUE,\r
-                          gImageHandle,\r
-                          FullDevicePath,\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
-            continue;\r
-          }\r
-        } else {\r
-          continue;\r
-        }\r
-      }\r
-      break;\r
-    }\r
-  }\r
-\r
-  FreePool (UsbIoHandleBuffer);\r
-  return ImageHandle;\r
-}\r
-\r
-/**\r
-  Expand USB Class or USB WWID device path node to be full device path of a USB\r
-  device in platform then load the boot file on this full device path and return the\r
-  image handle.\r
-\r
-  This function support following 4 cases:\r
-  1) Boot Option device path starts with a USB Class or USB WWID device path,\r
-     and there is no Media FilePath device path in the end.\r
-     In this case, it will follow Removable Media Boot Behavior.\r
-  2) Boot Option device path starts with a USB Class or USB WWID device path,\r
-     and ended with Media FilePath device path.\r
-  3) Boot Option device path starts with a full device path to a USB Host Controller,\r
-     contains a USB Class or USB WWID device path node, while not ended with Media\r
-     FilePath device path. In this case, it will follow Removable Media Boot Behavior.\r
-  4) Boot Option device path starts with a full device path to a USB Host Controller,\r
-     contains a USB Class or USB WWID device path node, and ended with Media\r
-     FilePath device path.\r
-\r
-  @param  DevicePath    The Boot Option device path.\r
-\r
-  @return  The image handle of boot file, or NULL if there is no boot file found in\r
-           the specified USB Class or USB WWID device path.\r
-\r
-**/\r
-EFI_HANDLE *\r
-BdsExpandUsbShortFormDevicePath (\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *DevicePath\r
-  )\r
-{\r
-  EFI_HANDLE                *ImageHandle;\r
-  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *ShortFormDevicePath;\r
-\r
-  //\r
-  // Search for USB Class or USB WWID device path node.\r
-  //\r
-  ShortFormDevicePath = NULL;\r
-  ImageHandle         = NULL;\r
-  TempDevicePath      = DevicePath;\r
-  while (!IsDevicePathEnd (TempDevicePath)) {\r
-    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
-        ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) ||\r
-         (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) {\r
-      ShortFormDevicePath = TempDevicePath;\r
-      break;\r
-    }\r
-    TempDevicePath = NextDevicePathNode (TempDevicePath);\r
-  }\r
-\r
-  if (ShortFormDevicePath == NULL) {\r
-    //\r
-    // No USB Class or USB WWID device path node found, do nothing.\r
-    //\r
-    return NULL;\r
-  }\r
-\r
-  if (ShortFormDevicePath == DevicePath) {\r
-    //\r
-    // Boot Option device path starts with USB Class or USB WWID device path.\r
-    //\r
-    ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath);\r
-    if (ImageHandle == NULL) {\r
-      //\r
-      // Failed to find a match in existing devices, connect the short form USB\r
-      // device path and try again.\r
-      //\r
-      BdsLibConnectUsbDevByShortFormDP (0xff, ShortFormDevicePath);\r
-      ImageHandle = BdsFindUsbDevice (NULL, ShortFormDevicePath);\r
-    }\r
-  } else {\r
-    //\r
-    // Boot Option device path contains USB Class or USB WWID device path node.\r
-    //\r
-\r
-    //\r
-    // Prepare the parent device path for search.\r
-    //\r
-    TempDevicePath = DuplicateDevicePath (DevicePath);\r
-    ASSERT (TempDevicePath != NULL);\r
-    SetDevicePathEndNode (((UINT8 *) TempDevicePath) + ((UINTN) ShortFormDevicePath - (UINTN) DevicePath));\r
-\r
-    //\r
-    // The USB Host Controller device path is already in Boot Option device path\r
-    // and USB Bus driver already support RemainingDevicePath starts with USB\r
-    // Class or USB WWID device path, so just search in existing USB devices and\r
-    // doesn't perform ConnectController here.\r
-    //\r
-    ImageHandle = BdsFindUsbDevice (TempDevicePath, ShortFormDevicePath);\r
-    FreePool (TempDevicePath);\r
-  }\r
-\r
-  return ImageHandle;\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_STATUS                StatusLogo;\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
-  LIST_ENTRY                TempBootLists;\r
-  EFI_BOOT_LOGO_PROTOCOL    *BootLogo;\r
-\r
-  Status        = EFI_SUCCESS;\r
-  *ExitDataSize = 0;\r
-  *ExitData     = 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
-  //\r
-  // Set Boot Current\r
-  //\r
-  if (IsBootOptionValidNVVarialbe (Option)) {\r
-    //\r
-    // For a temporary boot (i.e. a boot by selected a EFI Shell using "Boot From File"), Boot Current is actually not valid.\r
-    // In this case, "BootCurrent" is not created.\r
-    // Only create the BootCurrent variable when it points to a valid Boot#### variable.\r
-    //\r
-    SetVariableAndReportStatusCodeOnError (\r
-          L"BootCurrent",\r
-          &gEfiGlobalVariableGuid,\r
-          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-          sizeof (UINT16),\r
-          &Option->BootCurrent\r
-          );\r
-  }\r
-\r
-  //\r
-  // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
-  //\r
-  EfiSignalEventReadyToBoot();\r
-\r
-  //\r
-  // Report Status Code to indicate ReadyToBoot event was signalled\r
-  //\r
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT));\r
-\r
-  //\r
-  // Expand USB Class or USB WWID device path node to be full device path of a USB\r
-  // device in platform then load the boot file on this full device path and get the\r
-  // image handle.\r
-  //\r
-  ImageHandle = BdsExpandUsbShortFormDevicePath (DevicePath);\r
-\r
-  //\r
-  // Adjust the different type memory page number just before booting\r
-  // and save the updated info into the variable for next boot to use\r
-  //\r
-  BdsSetMemoryTypeInformationVariable ();\r
-\r
-  //\r
-  // By expanding the USB Class or WWID device path, the ImageHandle has returnned.\r
-  // Here get the ImageHandle for the non USB class or WWID device path.\r
-  //\r
-  if (ImageHandle == NULL) {\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, PcdGetPtr(PcdShellFile));\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_CODE_BEGIN();\r
-\r
-    if (Option->Description == NULL) {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting from unknown device path\n"));\r
-    } else {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
-    }\r
-\r
-    DEBUG_CODE_END();\r
-\r
-    //\r
-    // Report status code for OS Loader LoadImage.\r
-    //\r
-    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
-    Status = gBS->LoadImage (\r
-                    TRUE,\r
-                    gImageHandle,\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 option\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
-        //\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, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
-        if (FilePath != NULL) {\r
-          REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));\r
-          Status = gBS->LoadImage (\r
-                          TRUE,\r
-                          gImageHandle,\r
-                          FilePath,\r
-                          NULL,\r
-                          0,\r
-                          &ImageHandle\r
-                          );\r
-        }\r
-      }\r
-    }\r
-  }\r
-  //\r
-  // Provide the image with it's load options\r
-  //\r
-  if ((ImageHandle == NULL) || (EFI_ERROR(Status))) {\r
-    //\r
-    // Report Status Code to indicate that the failure to load boot option\r
-    //\r
-    REPORT_STATUS_CODE (\r
-      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
-      );\r
-    goto Done;\r
-  }\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
-  //\r
-  // Clean to NULL because the image is loaded directly from the firmwares boot manager.\r
-  //\r
-  ImageInfo->ParentHandle = NULL;\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
-  //\r
-  // Write boot to OS performance data for UEFI boot\r
-  //\r
-  PERF_CODE (\r
-    BmEndOfBdsPerfCode (NULL, NULL);\r
-  );\r
-\r
-  //\r
-  // Report status code for OS Loader StartImage.\r
-  //\r
-  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderStart));\r
-\r
-  Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);\r
-  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Report Status Code to indicate that boot failure\r
-    //\r
-    REPORT_STATUS_CODE (\r
-      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-      (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)\r
-      );\r
-  }\r
-\r
-  //\r
-  // Clear the Watchdog Timer after the image returns\r
-  //\r
-  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
-\r
-Done:\r
-  //\r
-  // Set Logo status invalid after trying one boot option\r
-  //\r
-  BootLogo = NULL;\r
-  StatusLogo = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);\r
-  if (!EFI_ERROR (StatusLogo) && (BootLogo != NULL)) {\r
-    BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);\r
-  }\r
-\r
-  //\r
-  // Clear Boot Current\r
-  // Deleting variable with current implementation shouldn't fail.\r
-  //\r
-  gRT->SetVariable (\r
-        L"BootCurrent",\r
-        &gEfiGlobalVariableGuid,\r
-        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
-        0,\r
-        NULL\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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable.\r
-  // If exist, search the front path which point to partition node in the variable instants.\r
-  // If fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, reconnect all and search in all system\r
-  //\r
-  GetVariable2 (\r
-    HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
-    &gHdBootDevicePathVariablGuid,\r
-    (VOID **) &CachedDevicePath,\r
-    &CachedDevicePathSize\r
-    );\r
-\r
-  //\r
-  // Delete the invalid HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable.\r
-  //\r
-  if ((CachedDevicePath != NULL) && !IsDevicePathValid (CachedDevicePath, CachedDevicePathSize)) {\r
-    FreePool (CachedDevicePath);\r
-    CachedDevicePath = NULL;\r
-    Status = gRT->SetVariable (\r
-                    HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
-                    &gHdBootDevicePathVariablGuid,\r
-                    0,\r
-                    0,\r
-                    NULL\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME 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
-        // Failure to set the variable only impacts the performance when next time expanding the short-form device path.\r
-        //\r
-        Status = gRT->SetVariable (\r
-                        HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
-                        &gHdBootDevicePathVariablGuid,\r
-                        EFI_VARIABLE_BOOTSERVICE_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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME 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 HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable\r
-      //\r
-      if (CachedDevicePath != NULL) {\r
-        //\r
-        // Save the matched partition device path as first instance of HD_BOOT_DEVICE_PATH_VARIABLE_NAME variable\r
-        //\r
-        if (BdsLibMatchDevicePaths (CachedDevicePath, BlockIoDevicePath)) {\r
-          TempNewDevicePath = CachedDevicePath;\r
-          CachedDevicePath = BdsLibDelPartMatchInstance (CachedDevicePath, BlockIoDevicePath);\r
-          FreePool(TempNewDevicePath);\r
-        }\r
-\r
-        if (CachedDevicePath != NULL) {\r
-          TempNewDevicePath = CachedDevicePath;\r
-          CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
-          FreePool(TempNewDevicePath);\r
-        } else {\r
-          CachedDevicePath = DuplicateDevicePath (BlockIoDevicePath);\r
-        }\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,\r
-        // the HD_BOOT_DEVICE_PATH_VARIABLE_NAME 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
-      // Failure to set the variable only impacts the performance when next time expanding the short-form device path.\r
-      //\r
-      Status = gRT->SetVariable (\r
-                      HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
-                      &gHdBootDevicePathVariablGuid,\r
-                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-                      GetDevicePathSize (CachedDevicePath),\r
-                      CachedDevicePath\r
-                      );\r
-\r
-      break;\r
-    }\r
-  }\r
-\r
-  if (CachedDevicePath != NULL) {\r
-    FreePool (CachedDevicePath);\r
-  }\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
-    if (!ValidateOption(BootOptionVar, BootOptionSize)) {\r
-      BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);\r
-      FreePool (BootOptionVar);\r
-      Index++;\r
-      continue;\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
-  // Shrinking variable with existing variable implementation shouldn't fail.\r
-  //\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  FreePool (BootOrder);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Delete all invalid EFI boot options.\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
-  CHAR16                    *Description;\r
-  BOOLEAN                   Corrupted;\r
-\r
-  Status           = EFI_SUCCESS;\r
-  BootOrder        = NULL;\r
-  Description      = NULL;\r
-  OptionDevicePath = NULL;\r
-  BootOrderSize    = 0;\r
-  Corrupted        = FALSE;\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
-    if (!ValidateOption(BootOptionVar, BootOptionSize)) {\r
-      Corrupted = TRUE;\r
-    } else {\r
-      TempPtr = BootOptionVar;\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
-      // 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
-\r
-    if (Corrupted || !BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) {\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
-      // Deleting variable with current variable implementation shouldn't fail.\r
-      //\r
-      ASSERT_EFI_ERROR (Status);\r
-      //\r
-      // Mark this boot option in boot order as deleted\r
-      //\r
-      BootOrder[Index] = 0xffff;\r
-      Corrupted        = FALSE;\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
-  // Shrinking variable with current variable implementation shouldn't fail.\r
-  //\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  FreePool (BootOrder);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  For EFI boot option, BDS separate them as six types:\r
-  1. Network - The boot option points to the SimpleNetworkProtocol device.\r
-               Bds will try to automatically create this type boot option when enumerate.\r
-  2. Shell   - The boot option points to internal flash shell.\r
-               Bds will try to automatically create this type boot option when enumerate.\r
-  3. Removable BlockIo      - The boot option only points to the removable media\r
-                              device, like USB flash disk, DVD, Floppy etc.\r
-                              These device should contain a *removable* blockIo\r
-                              protocol in their device handle.\r
-                              Bds will try to automatically create this type boot option\r
-                              when enumerate.\r
-  4. Fixed BlockIo          - The boot option only points to a Fixed blockIo device,\r
-                              like HardDisk.\r
-                              These device should contain a *fixed* blockIo\r
-                              protocol in their device handle.\r
-                              BDS will skip fixed blockIo devices, and NOT\r
-                              automatically create boot option for them. But BDS\r
-                              will help to delete those fixed blockIo boot option,\r
-                              whose description rule conflict with other auto-created\r
-                              boot options.\r
-  5. Non-BlockIo Simplefile - The boot option points to a device whose handle\r
-                              has SimpleFileSystem Protocol, but has no blockio\r
-                              protocol. These devices do not offer blockIo\r
-                              protocol, but BDS still can get the\r
-                              \EFI\BOOT\boot{machinename}.EFI by SimpleFileSystem\r
-                              Protocol.\r
-  6. File    - The boot option points to a file. These boot options are usually\r
-               created by user manually or OS loader. BDS will not delete or modify\r
-               these boot options.\r
-\r
-  This function will enumerate all possible boot device in the system, and\r
-  automatically create boot options for Network, Shell, Removable BlockIo,\r
-  and Non-BlockIo Simplefile devices.\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
-  @retval EFI_OUT_OF_RESOURCES   Failed to enumerate the boot device and create the boot option list\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                        HarddriveNumber;\r
-  UINT16                        CdromNumber;\r
-  UINT16                        UsbNumber;\r
-  UINT16                        MiscNumber;\r
-  UINT16                        ScsiNumber;\r
-  UINT16                        NonBlockNumber;\r
-  UINTN                         NumberBlockIoHandles;\r
-  EFI_HANDLE                    *BlockIoHandles;\r
-  EFI_BLOCK_IO_PROTOCOL         *BlkIo;\r
-  BOOLEAN                       Removable[2];\r
-  UINTN                         RemovableIndex;\r
-  UINTN                         Index;\r
-  UINTN                         NumOfLoadFileHandles;\r
-  EFI_HANDLE                    *LoadFileHandles;\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
-  CHAR8                         *PlatLang;\r
-  CHAR8                         *LastLang;\r
-  EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;\r
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
-\r
-  FloppyNumber    = 0;\r
-  HarddriveNumber = 0;\r
-  CdromNumber     = 0;\r
-  UsbNumber       = 0;\r
-  MiscNumber      = 0;\r
-  ScsiNumber      = 0;\r
-  PlatLang        = NULL;\r
-  LastLang        = NULL;\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
-    GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, (VOID**)&LastLang, NULL);\r
-    GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatLang, NULL);\r
-    ASSERT (PlatLang != NULL);\r
-    if ((LastLang != NULL) && (AsciiStrCmp (LastLang, PlatLang) == 0)) {\r
-      Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
-      FreePool (LastLang);\r
-      FreePool (PlatLang);\r
-      return Status;\r
-    } else {\r
-      Status = gRT->SetVariable (\r
-        LAST_ENUM_LANGUAGE_VARIABLE_NAME,\r
-        &gLastEnumLangGuid,\r
-        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-        AsciiStrSize (PlatLang),\r
-        PlatLang\r
-        );\r
-      //\r
-      // Failure to set the variable only impacts the performance next time enumerating the boot options.\r
-      //\r
-\r
-      if (LastLang != NULL) {\r
-        FreePool (LastLang);\r
-      }\r
-      FreePool (PlatLang);\r
-    }\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 followed by fixed media.\r
-  // The Removable[] array is used by the for-loop below to create removable media boot options\r
-  // at first, and then to create fixed media boot options.\r
-  //\r
-  Removable[0]  = FALSE;\r
-  Removable[1]  = TRUE;\r
-\r
-  gBS->LocateHandleBuffer (\r
-        ByProtocol,\r
-        &gEfiBlockIoProtocolGuid,\r
-        NULL,\r
-        &NumberBlockIoHandles,\r
-        &BlockIoHandles\r
-        );\r
-\r
-  for (RemovableIndex = 0; RemovableIndex < 2; RemovableIndex++) {\r
-    for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
-      Status = gBS->HandleProtocol (\r
-                      BlockIoHandles[Index],\r
-                      &gEfiBlockIoProtocolGuid,\r
-                      (VOID **) &BlkIo\r
-                      );\r
-      //\r
-      // skip the logical partition\r
-      //\r
-      if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) {\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // firstly fixed block io then the removable block io\r
-      //\r
-      if (BlkIo->Media->RemovableMedia == Removable[RemovableIndex]) {\r
-        continue;\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"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);\r
-        } else {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));\r
-        }\r
-        BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-        FloppyNumber++;\r
-        break;\r
-\r
-      //\r
-      // Assume a removable SATA device should be the DVD/CD device, a fixed SATA device should be the Hard Drive device.\r
-      //\r
-      case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
-      case BDS_EFI_MESSAGE_SATA_BOOT:\r
-        if (BlkIo->Media->RemovableMedia) {\r
-          if (CdromNumber != 0) {\r
-            UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);\r
-          } else {\r
-            UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));\r
-          }\r
-          CdromNumber++;\r
-        } else {\r
-          if (HarddriveNumber != 0) {\r
-            UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)), HarddriveNumber);\r
-          } else {\r
-            UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)));\r
-          }\r
-          HarddriveNumber++;\r
-        }\r
-        DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));\r
-        BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-        break;\r
-\r
-      case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
-        if (UsbNumber != 0) {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);\r
-        } else {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));\r
-        }\r
-        BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-        UsbNumber++;\r
-        break;\r
-\r
-      case BDS_EFI_MESSAGE_SCSI_BOOT:\r
-        if (ScsiNumber != 0) {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);\r
-        } else {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));\r
-        }\r
-        BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-        ScsiNumber++;\r
-        break;\r
-\r
-      case BDS_EFI_MESSAGE_MISC_BOOT:\r
-      default:\r
-        if (MiscNumber != 0) {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);\r
-        } else {\r
-          UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));\r
-        }\r
-        BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-        MiscNumber++;\r
-        break;\r
-      }\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
-                   EFI_REMOVABLE_MEDIA_FILE_NAME,\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"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);\r
-      } else {\r
-        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));\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
-  NumOfLoadFileHandles = 0;\r
-  //\r
-  // Search Load File protocol for PXE boot option.\r
-  //\r
-  gBS->LocateHandleBuffer (\r
-        ByProtocol,\r
-        &gEfiLoadFileProtocolGuid,\r
-        NULL,\r
-        &NumOfLoadFileHandles,\r
-        &LoadFileHandles\r
-        );\r
-\r
-  for (Index = 0; Index < NumOfLoadFileHandles; Index++) {\r
-    if (Index != 0) {\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), Index);\r
-    } else {\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)));\r
-    }\r
-    BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);\r
-  }\r
-\r
-  if (NumOfLoadFileHandles != 0) {\r
-    FreePool (LoadFileHandles);\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
-    gBS->HandleProtocol (\r
-          FvHandleBuffer[Index],\r
-          &gEfiFirmwareVolume2ProtocolGuid,\r
-          (VOID **) &Fv\r
-          );\r
-\r
-    Status = Fv->ReadFile (\r
-                  Fv,\r
-                  PcdGetPtr(PcdShellFile),\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
-  Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
-  mEnumBootDevice = TRUE;\r
-\r
-  return Status;\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, PcdGetPtr(PcdShellFile));\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
-  EFI_STATUS        Status;\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
-    Status = gRT->SetVariable (\r
-                    L"BootNext",\r
-                    &gEfiGlobalVariableGuid,\r
-                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-                    0,\r
-                    NULL\r
-                    );\r
-    //\r
-    // Deleting variable with current variable implementation shouldn't fail.\r
-    //\r
-    ASSERT_EFI_ERROR (Status);\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
-    FreePool(BootOption);\r
-    FreePool(BootNext);\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
-  @return  The bootable media handle. If the media on the DevicePath is not bootable, NULL will return.\r
-\r
-**/\r
-EFI_HANDLE\r
-EFIAPI\r
-BdsLibGetBootableHandle (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  EFI_TPL                         OldTpl;\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
-  // Enter to critical section to protect the acquired BlockIo instance\r
-  // from getting released due to the USB mass storage hotplug event\r
-  //\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\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
-    // For removable device boot option, its contained device path only point to the removable device handle,\r
-    // should make sure all its children handles (its child partion or media handles) are created and connected.\r
-    //\r
-    gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
-    //\r
-    // Get BlockIo protocol and check removable attribute\r
-    //\r
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
-    ASSERT_EFI_ERROR (Status);\r
-\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
-                 EFI_REMOVABLE_MEDIA_FILE_NAME,\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
-  gBS->RestoreTPL (OldTpl);\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
-  UINT32                          InterruptStatus;\r
-\r
-  MediaPresent = FALSE;\r
-\r
-  UpdatedDevicePath = DevicePath;\r
-  //\r
-  // Locate Load File Protocol for PXE boot option first\r
-  //\r
-  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &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 (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
-    }\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
-    if (EFI_ERROR (Status)) {\r
-      //\r
-      // Failed to open SNP from this handle, try to get SNP from parent handle\r
-      //\r
-      UpdatedDevicePath = DevicePathFromHandle (Handle);\r
-      if (UpdatedDevicePath != NULL) {\r
-        Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
-        if (!EFI_ERROR (Status)) {\r
-          //\r
-          // SNP handle found, get SNP from it\r
-          //\r
-          Status = gBS->HandleProtocol (Handle, &gEfiSimpleNetworkProtocolGuid, (VOID **) &Snp);\r
-        }\r
-      }\r
-    }\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      if (Snp->Mode->MediaPresentSupported) {\r
-        if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
-          //\r
-          // Invoke Snp->GetStatus() to refresh the media status\r
-          //\r
-          Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
-\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 given device path contains MEDIA_DEVICE_PATH type device path node\r
-                                          which subtype is MEDIA_HARDDRIVE_DP\r
-  @retval BDS_EFI_MEDIA_CDROM_BOOT        If given device path contains MEDIA_DEVICE_PATH type device path node\r
-                                          which subtype is MEDIA_CDROM_DP\r
-  @retval BDS_EFI_ACPI_FLOPPY_BOOT        If given device path contains ACPI_DEVICE_PATH type device path node\r
-                                          which HID is floppy device.\r
-  @retval BDS_EFI_MESSAGE_ATAPI_BOOT      If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                          and its last device path node's subtype is MSG_ATAPI_DP.\r
-  @retval BDS_EFI_MESSAGE_SCSI_BOOT       If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                          and its last device path node's subtype is MSG_SCSI_DP.\r
-  @retval BDS_EFI_MESSAGE_USB_DEVICE_BOOT If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                          and its last device path node's subtype is MSG_USB_DP.\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.\r
-  @retval BDS_LEGACY_BBS_BOOT             If given device path contains BBS_DEVICE_PATH type device path node.\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
-  UINT32                        BootType;\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
-          // skip 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
-        switch (DevicePathSubType (TempDevicePath)) {\r
-        case MSG_ATAPI_DP:\r
-          BootType = BDS_EFI_MESSAGE_ATAPI_BOOT;\r
-          break;\r
-\r
-        case MSG_USB_DP:\r
-          BootType = BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
-          break;\r
-\r
-        case MSG_SCSI_DP:\r
-          BootType = BDS_EFI_MESSAGE_SCSI_BOOT;\r
-          break;\r
-\r
-        case MSG_SATA_DP:\r
-          BootType = BDS_EFI_MESSAGE_SATA_BOOT;\r
-          break;\r
-\r
-        case MSG_MAC_ADDR_DP:\r
-        case MSG_VLAN_DP:\r
-        case MSG_IPv4_DP:\r
-        case MSG_IPv6_DP:\r
-          BootType = BDS_EFI_MESSAGE_MAC_BOOT;\r
-          break;\r
-\r
-        default:\r
-          BootType = BDS_EFI_MESSAGE_MISC_BOOT;\r
-          break;\r
-        }\r
-        return BootType;\r
-\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
-  return BdsLibIsValidEFIBootOptDevicePathExt (DevPath, CheckMedia, NULL);\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
-  If Description is not NULL and the device path point to a fixed BlockIo\r
-  device, check the description whether conflict with other auto-created\r
-  boot options.\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
-  @param  Description the description in a boot option\r
-\r
-  @retval TRUE        the Device path  is valid\r
-  @retval FALSE       the Device path  is invalid .\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-BdsLibIsValidEFIBootOptDevicePathExt (\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath,\r
-  IN BOOLEAN                      CheckMedia,\r
-  IN CHAR16                       *Description\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
-  // Check if there is EfiLoadFileProtocol installed.\r
-  // If yes, that means there is a boot option for network.\r
-  //\r
-  Status = gBS->LocateDevicePath (\r
-                  &gEfiLoadFileProtocolGuid,\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
-                    &gEfiLoadFileProtocolGuid,\r
-                    &TempDevicePath,\r
-                    &Handle\r
-                    );\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    if (!IsDevicePathEnd (TempDevicePath)) {\r
-      //\r
-      // LoadFile protocol is not installed on handle with exactly the same DevPath\r
-      //\r
-      return FALSE;\r
-    }\r
-\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
-    //\r
-    // If there is USB Class or USB WWID device path node, treat it as valid EFI\r
-    // Boot Option. BdsExpandUsbShortFormDevicePath () will be used to expand it\r
-    // to full device path.\r
-    //\r
-    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
-        ((DevicePathSubType (TempDevicePath) == MSG_USB_CLASS_DP) ||\r
-         (DevicePathSubType (TempDevicePath) == MSG_USB_WWID_DP))) {\r
-      return TRUE;\r
-    }\r
-\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 FV application\r
-  //\r
-  if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL) {\r
-    //\r
-    // If the boot option point to internal FV application, make sure it is valid\r
-    //\r
-    TempDevicePath = DevPath;\r
-    Status = BdsLibUpdateFvFileDevicePath (\r
-               &TempDevicePath,\r
-               EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode)\r
-               );\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:\r
-  //    if it is a removable blockIo device, it is valid.\r
-  //    if it is a fixed blockIo device, check its description confliction.\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
-             gImageHandle,\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
-    ASSERT (NewDevicePath != NULL);\r
-    *DevicePath = NewDevicePath;\r
-    return EFI_SUCCESS;\r
-  }\r
-  return EFI_NOT_FOUND;\r
-}\r