]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg/UefiBootManagerLib: Generate boot description for NVME
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmBoot.c
index 2c38aa827529f0da06be24f26fa82a320c8d25da..8a3a4027eec0139d8203eee14a080eaf95cec3df 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Library functions which relates with booting.\r
 \r
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -14,19 +15,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "InternalBm.h"\r
 \r
-#define VENDOR_IDENTIFICATION_OFFSET     3\r
-#define VENDOR_IDENTIFICATION_LENGTH     8\r
-#define PRODUCT_IDENTIFICATION_OFFSET    11\r
-#define PRODUCT_IDENTIFICATION_LENGTH    16\r
-\r
-CONST UINT16 mBmUsbLangId    = 0x0409; // English\r
-CHAR16       mBmUefiPrefix[] = L"UEFI ";\r
+EFI_RAM_DISK_PROTOCOL                        *mRamDisk                  = NULL;\r
 \r
 EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION  mBmRefreshLegacyBootOption = NULL;\r
 EFI_BOOT_MANAGER_LEGACY_BOOT                 mBmLegacyBoot              = NULL;\r
 \r
-LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);\r
-\r
 ///\r
 /// This GUID is used for an EFI Variable that stores the front device pathes\r
 /// for a partial device path that starts with the HD node.\r
@@ -52,104 +45,25 @@ EfiBootManagerRegisterLegacyBootSupport (
 }\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 AcpiFloppyBoot               If given device path contains ACPI_DEVICE_PATH type device path node\r
-                                       which HID is floppy device.\r
-  @retval MessageAtapiBoot             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 MessageSataBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_SATA_DP.\r
-  @retval MessageScsiBoot              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 MessageUsbBoot               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 MessageNetworkBoot           If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,\r
-                                       MSG_IPv4_DP or MSG_IPv6_DP.\r
-  @retval MessageHttpBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_URI_DP.\r
-  @retval UnsupportedBoot              If tiven device path doesn't match the above condition, it's not supported.\r
+  Return TRUE when the boot option is auto-created instead of manually added.\r
 \r
+  @param BootOption Pointer to the boot option to check.\r
+\r
+  @retval TRUE  The boot option is auto-created.\r
+  @retval FALSE The boot option is manually added.\r
 **/\r
-BM_BOOT_TYPE\r
-BmDevicePathType (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+BOOLEAN\r
+BmIsAutoCreateBootOption (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL      *Node;\r
-  EFI_DEVICE_PATH_PROTOCOL      *NextNode;\r
-\r
-  ASSERT (DevicePath != NULL);\r
-\r
-  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {\r
-    switch (DevicePathType (Node)) {\r
-\r
-      case ACPI_DEVICE_PATH:\r
-        if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {\r
-          return BmAcpiFloppyBoot;\r
-        }\r
-        break;\r
-\r
-      case HARDWARE_DEVICE_PATH:\r
-        if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {\r
-          return BmHardwareDeviceBoot;\r
-        }\r
-        break;\r
-\r
-      case MESSAGING_DEVICE_PATH:\r
-        //\r
-        // Skip LUN device node\r
-        //\r
-        NextNode = Node;\r
-        do {\r
-          NextNode = NextDevicePathNode (NextNode);\r
-        } while (\r
-            (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&\r
-            (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)\r
-            );\r
-\r
-        //\r
-        // If the device path not only point to driver device, it is not a messaging device path,\r
-        //\r
-        if (!IsDevicePathEndType (NextNode)) {\r
-          continue;\r
-        }\r
-\r
-        switch (DevicePathSubType (Node)) {\r
-        case MSG_ATAPI_DP:\r
-          return BmMessageAtapiBoot;\r
-          break;\r
-\r
-        case MSG_SATA_DP:\r
-          return BmMessageSataBoot;\r
-          break;\r
-\r
-        case MSG_USB_DP:\r
-          return BmMessageUsbBoot;\r
-          break;\r
-\r
-        case MSG_SCSI_DP:\r
-          return BmMessageScsiBoot;\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
-          return BmMessageNetworkBoot;\r
-          break;\r
-\r
-        case MSG_URI_DP:\r
-          return BmMessageHttpBoot;\r
-          break;\r
-        }\r
-    }\r
+  if ((BootOption->OptionalDataSize == sizeof (EFI_GUID)) &&\r
+      CompareGuid ((EFI_GUID *) BootOption->OptionalData, &mBmAutoCreateBootOptionGuid)\r
+      ) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
   }\r
-\r
-  return BmMiscBoot;\r
 }\r
 \r
 /**\r
@@ -205,7 +119,7 @@ BmFindBootOptionInVariable (
   if (OptionNumber == LoadOptionNumberUnassigned) {\r
     BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
 \r
-    Index = BmFindLoadOption (OptionToFind, BootOptions, BootOptionCount);\r
+    Index = EfiBootManagerFindLoadOption (OptionToFind, BootOptions, BootOptionCount);\r
     if (Index != -1) {\r
       OptionNumber = BootOptions[Index].OptionNumber;\r
     }\r
@@ -221,15 +135,15 @@ BmFindBootOptionInVariable (
 \r
   FV address may change across reboot. This routine promises the FV file device path is right.\r
 \r
-  @param  DevicePath   The Memory Mapped Device Path to get the file buffer.\r
+  @param  FilePath     The Memory Mapped Device Path to get the file buffer.\r
   @param  FullPath     Receive the updated FV Device Path pointint to the file.\r
   @param  FileSize     Receive the file buffer size.\r
 \r
   @return  The file buffer.\r
 **/\r
 VOID *\r
-BmGetFileBufferByMemmapFv (\r
-  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath,\r
+BmGetFileBufferByFvFilePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *FilePath,\r
   OUT EFI_DEVICE_PATH_PROTOCOL     **FullPath,\r
   OUT UINTN                        *FileSize\r
   )\r
@@ -244,18 +158,28 @@ BmGetFileBufferByMemmapFv (
   EFI_HANDLE                    *FvHandles;\r
   EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;\r
   VOID                          *FileBuffer;\r
-  \r
-  FvFileNode = DevicePath;\r
+\r
+  //\r
+  // Get the file buffer by using the exactly FilePath.\r
+  //\r
+  FvFileNode = FilePath;\r
   Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);\r
   if (!EFI_ERROR (Status)) {\r
-    FileBuffer = GetFileBufferByFilePath (TRUE, DevicePath, FileSize, &AuthenticationStatus);\r
+    FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
     if (FileBuffer != NULL) {\r
-      *FullPath = DuplicateDevicePath (DevicePath);\r
+      *FullPath = DuplicateDevicePath (FilePath);\r
     }\r
     return FileBuffer;\r
   }\r
 \r
-  FvFileNode = NextDevicePathNode (DevicePath);\r
+  //\r
+  // Only wide match other FVs if it's a memory mapped FV file path.\r
+  //\r
+  if ((DevicePathType (FilePath) != HARDWARE_DEVICE_PATH) || (DevicePathSubType (FilePath) != HW_MEMMAP_DP)) {\r
+    return NULL;\r
+  }\r
+\r
+  FvFileNode = NextDevicePathNode (FilePath);\r
 \r
   //\r
   // Firstly find the FV file in current FV\r
@@ -266,7 +190,7 @@ BmGetFileBufferByMemmapFv (
          (VOID **) &LoadedImage\r
          );\r
   NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);\r
-  FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+  FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
   FreePool (NewDevicePath);\r
 \r
   if (FileBuffer != NULL) {\r
@@ -291,7 +215,7 @@ BmGetFileBufferByMemmapFv (
       continue;\r
     }\r
     NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);\r
-    FileBuffer = BmGetFileBufferByMemmapFv (NewDevicePath, FullPath, FileSize);\r
+    FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);\r
     FreePool (NewDevicePath);\r
   }\r
   \r
@@ -302,29 +226,36 @@ BmGetFileBufferByMemmapFv (
 }\r
 \r
 /**\r
-  Check if it's a Memory Mapped FV Device Path.\r
+  Check if it's a Device Path pointing to FV file.\r
   \r
   The function doesn't garentee the device path points to existing FV file.\r
 \r
   @param  DevicePath     Input device path.\r
 \r
-  @retval TRUE   The device path is a Memory Mapped FV Device Path.\r
-  @retval FALSE  The device path is NOT a Memory Mapped FV Device Path.\r
+  @retval TRUE   The device path is a FV File Device Path.\r
+  @retval FALSE  The device path is NOT a FV File Device Path.\r
 **/\r
 BOOLEAN\r
-BmIsMemmapFvFilePath (\r
+BmIsFvFilePath (\r
   IN EFI_DEVICE_PATH_PROTOCOL    *DevicePath\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL   *FileNode;\r
+  EFI_STATUS                     Status;\r
+  EFI_HANDLE                     Handle;\r
+  EFI_DEVICE_PATH_PROTOCOL       *Node;\r
+\r
+  Node = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &Handle);\r
+  if (!EFI_ERROR (Status)) {\r
+    return TRUE;\r
+  }\r
 \r
   if ((DevicePathType (DevicePath) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (DevicePath) == HW_MEMMAP_DP)) {\r
-    FileNode = NextDevicePathNode (DevicePath);\r
-    if ((DevicePathType (FileNode) == MEDIA_DEVICE_PATH) && (DevicePathSubType (FileNode) == MEDIA_PIWG_FW_FILE_DP)) {\r
-      return IsDevicePathEnd (NextDevicePathNode (FileNode));\r
+    DevicePath = NextDevicePathNode (DevicePath);\r
+    if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MEDIA_PIWG_FW_FILE_DP)) {\r
+      return IsDevicePathEnd (NextDevicePathNode (DevicePath));\r
     }\r
   }\r
-\r
   return FALSE;\r
 }\r
 \r
@@ -414,411 +345,6 @@ BmMatchUsbClass (
   return TRUE;\r
 }\r
 \r
-/**\r
-  Eliminate the extra spaces in the Str to one space.\r
-\r
-  @param    Str     Input string info.\r
-**/\r
-VOID\r
-BmEliminateExtraSpaces (\r
-  IN CHAR16                    *Str\r
-  )\r
-{\r
-  UINTN                        Index;\r
-  UINTN                        ActualIndex;\r
-\r
-  for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {\r
-    if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {\r
-      Str[ActualIndex++] = Str[Index];\r
-    }\r
-  }\r
-  Str[ActualIndex] = L'\0';\r
-}\r
-\r
-/**\r
-  Try to get the controller's ATA/ATAPI description.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetDescriptionFromDiskInfo (\r
-  IN EFI_HANDLE                Handle\r
-  )\r
-{\r
-  UINTN                        Index;\r
-  EFI_STATUS                   Status;\r
-  EFI_DISK_INFO_PROTOCOL       *DiskInfo;\r
-  UINT32                       BufferSize;\r
-  EFI_ATAPI_IDENTIFY_DATA      IdentifyData;\r
-  EFI_SCSI_INQUIRY_DATA        InquiryData;\r
-  CHAR16                       *Description;\r
-  UINTN                        Length;\r
-  CONST UINTN                  ModelNameLength    = 40;\r
-  CONST UINTN                  SerialNumberLength = 20;\r
-  CHAR8                        *StrPtr;\r
-  UINT8                        Temp;\r
-\r
-  Description  = NULL;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiDiskInfoProtocolGuid,\r
-                  (VOID **) &DiskInfo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || \r
-      CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
-    BufferSize   = sizeof (EFI_ATAPI_IDENTIFY_DATA);\r
-    Status = DiskInfo->Identify (\r
-                         DiskInfo,\r
-                         &IdentifyData,\r
-                         &BufferSize\r
-                         );\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));\r
-      ASSERT (Description != NULL);\r
-      for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {\r
-        Description[Index]     = (CHAR16) IdentifyData.ModelName[Index + 1];\r
-        Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];\r
-      }\r
-\r
-      Length = Index;\r
-      Description[Length++] = L' ';\r
-\r
-      for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {\r
-        Description[Length + Index]     = (CHAR16) IdentifyData.SerialNo[Index + 1];\r
-        Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];\r
-      }\r
-      Length += Index;\r
-      Description[Length++] = L'\0';\r
-      ASSERT (Length == ModelNameLength + SerialNumberLength + 2);\r
-\r
-      BmEliminateExtraSpaces (Description);\r
-    }\r
-  } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
-    BufferSize   = sizeof (EFI_SCSI_INQUIRY_DATA);\r
-    Status = DiskInfo->Inquiry (\r
-                         DiskInfo,\r
-                         &InquiryData,\r
-                         &BufferSize\r
-                         );\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));\r
-      ASSERT (Description != NULL);\r
-\r
-      //\r
-      // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification\r
-      // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, \r
-      // Here combine the vendor identification and product identification to the description.\r
-      //\r
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);\r
-      Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];\r
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';\r
-      AsciiStrToUnicodeStr (StrPtr, Description);\r
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;\r
-\r
-      //\r
-      // Add one space at the middle of vendor information and product information.\r
-      //\r
-      Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';\r
-\r
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);\r
-      StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';\r
-      AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);\r
-\r
-      BmEliminateExtraSpaces (Description);\r
-    }\r
-  }\r
-\r
-  return Description;\r
-}\r
-\r
-/**\r
-  Try to get the controller's USB description.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetUsbDescription (\r
-  IN EFI_HANDLE                Handle\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  EFI_USB_IO_PROTOCOL          *UsbIo;\r
-  CHAR16                       NullChar;\r
-  CHAR16                       *Manufacturer;\r
-  CHAR16                       *Product;\r
-  CHAR16                       *SerialNumber;\r
-  CHAR16                       *Description;\r
-  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
-  UINTN                        DescMaxSize;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiUsbIoProtocolGuid,\r
-                  (VOID **) &UsbIo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  NullChar = L'\0';\r
-\r
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrManufacturer,\r
-                    &Manufacturer\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    Manufacturer = &NullChar;\r
-  }\r
-  \r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrProduct,\r
-                    &Product\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    Product = &NullChar;\r
-  }\r
-  \r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrSerialNumber,\r
-                    &SerialNumber\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    SerialNumber = &NullChar;\r
-  }\r
-\r
-  if ((Manufacturer == &NullChar) &&\r
-      (Product == &NullChar) &&\r
-      (SerialNumber == &NullChar)\r
-      ) {\r
-    return NULL;\r
-  }\r
-\r
-  DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);\r
-  Description = AllocateZeroPool (DescMaxSize);\r
-  ASSERT (Description != NULL);\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product);  \r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber);\r
-\r
-  if (Manufacturer != &NullChar) {\r
-    FreePool (Manufacturer);\r
-  }\r
-  if (Product != &NullChar) {\r
-    FreePool (Product);\r
-  }\r
-  if (SerialNumber != &NullChar) {\r
-    FreePool (SerialNumber);\r
-  }\r
-\r
-  BmEliminateExtraSpaces (Description);\r
-\r
-  return Description;\r
-}\r
-\r
-/**\r
-  Return the boot description for the controller based on the type.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetMiscDescription (\r
-  IN EFI_HANDLE                  Handle\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  CHAR16                          *Description;\r
-  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
-\r
-  switch (BmDevicePathType (DevicePathFromHandle (Handle))) {\r
-  case BmAcpiFloppyBoot:\r
-    Description = L"Floppy";\r
-    break;\r
-\r
-  case BmMessageAtapiBoot:\r
-  case BmMessageSataBoot:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
-    ASSERT_EFI_ERROR (Status);\r
-    //\r
-    // Assume a removable SATA device should be the DVD/CD device\r
-    //\r
-    Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";\r
-    break;\r
-\r
-  case BmMessageUsbBoot:\r
-    Description = L"USB Device";\r
-    break;\r
-\r
-  case BmMessageScsiBoot:\r
-    Description = L"SCSI Device";\r
-    break;\r
-\r
-  case BmHardwareDeviceBoot:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";\r
-    } else {\r
-      Description = L"Misc Device";\r
-    }\r
-    break;\r
-\r
-  case BmMessageNetworkBoot:\r
-    Description = L"Network";\r
-    break;\r
-\r
-  case BmMessageHttpBoot:\r
-    Description = L"Http";\r
-    break;\r
-\r
-  default:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs);\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = L"Non-Block Boot Device";\r
-    } else {\r
-      Description = L"Misc Device";\r
-    }\r
-    break;\r
-  }\r
-\r
-  return AllocateCopyPool (StrSize (Description), Description);\r
-}\r
-\r
-/**\r
-  Register the platform provided boot description handler.\r
-\r
-  @param Handler  The platform provided boot description handler\r
-\r
-  @retval EFI_SUCCESS          The handler was registered successfully.\r
-  @retval EFI_ALREADY_STARTED  The handler was already registered.\r
-  @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiBootManagerRegisterBootDescriptionHandler (\r
-  IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER  Handler\r
-  )\r
-{\r
-  LIST_ENTRY                                    *Link;\r
-  BM_BOOT_DESCRIPTION_ENTRY                    *Entry;\r
-\r
-  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
-      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
-      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
-      ) {\r
-    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
-    if (Entry->Handler == Handler) {\r
-      return EFI_ALREADY_STARTED;\r
-    }\r
-  }\r
-\r
-  Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));\r
-  if (Entry == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;\r
-  Entry->Handler   = Handler;\r
-  InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {\r
-  BmGetUsbDescription,\r
-  BmGetDescriptionFromDiskInfo,\r
-  BmGetMiscDescription\r
-};\r
-\r
-/**\r
-  Return the boot description for the controller.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetBootDescription (\r
-  IN EFI_HANDLE                  Handle\r
-  )\r
-{\r
-  LIST_ENTRY                     *Link;\r
-  BM_BOOT_DESCRIPTION_ENTRY      *Entry;\r
-  CHAR16                         *Description;\r
-  CHAR16                         *DefaultDescription;\r
-  CHAR16                         *Temp;\r
-  UINTN                          Index;\r
-\r
-  //\r
-  // Firstly get the default boot description\r
-  //\r
-  DefaultDescription = NULL;\r
-  for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof (mBmBootDescriptionHandlers[0]); Index++) {\r
-    DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle);\r
-    if (DefaultDescription != NULL) {\r
-      //\r
-      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
-      // ONLY for core provided boot description handler.\r
-      //\r
-      Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); \r
-      ASSERT (Temp != NULL);\r
-      StrCpyS ( Temp, \r
-                (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
-                mBmUefiPrefix\r
-                );\r
-      StrCatS ( Temp, \r
-                (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
-                DefaultDescription\r
-                );\r
-      FreePool (DefaultDescription);\r
-      DefaultDescription = Temp;\r
-      break;\r
-    }\r
-  }\r
-  ASSERT (DefaultDescription != NULL);\r
-\r
-  //\r
-  // Secondly query platform for the better boot description\r
-  //\r
-  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
-      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
-      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
-      ) {\r
-    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
-    Description = Entry->Handler (Handle, DefaultDescription);\r
-    if (Description != NULL) {\r
-      FreePool (DefaultDescription);\r
-      return Description;\r
-    }\r
-  }\r
-\r
-  return DefaultDescription;\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
@@ -956,7 +482,6 @@ BmFindUsbDevice (
   EFI_DEVICE_PATH_PROTOCOL  *UsbIoDevicePath;\r
   EFI_USB_IO_PROTOCOL       *UsbIo;\r
   UINTN                     Index;\r
-  UINTN                     UsbIoDevicePathSize;\r
   BOOLEAN                   Matched;\r
 \r
   ASSERT (UsbIoHandleCount != NULL);  \r
@@ -988,7 +513,6 @@ BmFindUsbDevice (
     UsbIoDevicePath = DevicePathFromHandle (UsbIoHandles[Index]);\r
     Matched         = FALSE;\r
     if (!EFI_ERROR (Status) && (UsbIoDevicePath != NULL)) {\r
-      UsbIoDevicePathSize = GetDevicePathSize (UsbIoDevicePath) - END_DEVICE_PATH_LENGTH;\r
 \r
       //\r
       // Compare starting part of UsbIoHandle's device path with ParentDevicePath.\r
@@ -1062,7 +586,7 @@ BmExpandUsbDevicePath (
 \r
   for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {\r
     FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);\r
-    FileBuffer = BmGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
+    FileBuffer = EfiBootManagerGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
     FreePool (FullDevicePath);\r
   }\r
 \r
@@ -1074,41 +598,158 @@ BmExpandUsbDevicePath (
 }\r
 \r
 /**\r
-  Save the partition DevicePath to the CachedDevicePath as the first instance.\r
+  Expand File-path device path node to be full device path in platform.\r
 \r
-  @param CachedDevicePath  The device path cache.\r
-  @param DevicePath        The partition device path to be cached.\r
+  @param FilePath      The device path pointing to a load option.\r
+                       It could be a short-form device path.\r
+  @param FullPath      Return the full device path of the load option after\r
+                       short-form device path expanding.\r
+                       Caller is responsible to free it.\r
+  @param FileSize      Return the load option size.\r
+\r
+  @return The load option buffer. Caller is responsible to free the memory.\r
 **/\r
-VOID\r
-BmCachePartitionDevicePath (\r
-  IN OUT EFI_DEVICE_PATH_PROTOCOL **CachedDevicePath,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+VOID *\r
+BmExpandFileDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL    **FullPath,\r
+  OUT UINTN                       *FileSize\r
   )\r
 {\r
-  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
-  UINTN                           Count;\r
+  EFI_STATUS                      Status;\r
+  UINTN                           Index;\r
+  UINTN                           HandleCount;\r
+  EFI_HANDLE                      *Handles;\r
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
+  UINTN                           MediaType;\r
+  EFI_DEVICE_PATH_PROTOCOL        *FullDevicePath;\r
+  VOID                            *FileBuffer;\r
+  UINT32                          AuthenticationStatus;\r
   \r
-  if (BmMatchDevicePaths (*CachedDevicePath, DevicePath)) {\r
-    TempDevicePath = *CachedDevicePath;\r
-    *CachedDevicePath = BmDelPartMatchInstance (*CachedDevicePath, DevicePath);\r
-    FreePool (TempDevicePath);\r
+  EfiBootManagerConnectAll ();\r
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);\r
+  if (EFI_ERROR (Status)) {\r
+    HandleCount = 0;\r
+    Handles = NULL;\r
   }\r
 \r
-  if (*CachedDevicePath == NULL) {\r
-    *CachedDevicePath = DuplicateDevicePath (DevicePath);\r
-    return;\r
+  //\r
+  // Enumerate all removable media devices followed by all fixed media devices,\r
+  //   followed by media devices which don't layer on block io.\r
+  //\r
+  for (MediaType = 0; MediaType < 3; MediaType++) {\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      Status = gBS->HandleProtocol (Handles[Index], &gEfiBlockIoProtocolGuid, (VOID *) &BlockIo);\r
+      if (EFI_ERROR (Status)) {\r
+        BlockIo = NULL;\r
+      }\r
+      if ((MediaType == 0 && BlockIo != NULL && BlockIo->Media->RemovableMedia) ||\r
+          (MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||\r
+          (MediaType == 2 && BlockIo == NULL)\r
+          ) {\r
+        FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);\r
+        FileBuffer = GetFileBufferByFilePath (TRUE, FullDevicePath, FileSize, &AuthenticationStatus);\r
+        if (FileBuffer != NULL) {\r
+          *FullPath = FullDevicePath;\r
+          FreePool (Handles);\r
+          return FileBuffer;\r
+        }\r
+        FreePool (FullDevicePath);\r
+      }\r
+    }\r
   }\r
 \r
-  TempDevicePath = *CachedDevicePath;\r
-  *CachedDevicePath = AppendDevicePathInstance (DevicePath, *CachedDevicePath);\r
-  if (TempDevicePath != NULL) {\r
-    FreePool (TempDevicePath);\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  *FullPath = NULL;\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Expand URI device path node to be full device path in platform.\r
+\r
+  @param FilePath      The device path pointing to a load option.\r
+                       It could be a short-form device path.\r
+  @param FullPath      Return the full device path of the load option after\r
+                       short-form device path expanding.\r
+                       Caller is responsible to free it.\r
+  @param FileSize      Return the load option size.\r
+\r
+  @return The load option buffer. Caller is responsible to free the memory.\r
+**/\r
+VOID *\r
+BmExpandUriDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL    **FullPath,\r
+  OUT UINTN                       *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  UINTN                           Index;\r
+  UINTN                           HandleCount;\r
+  EFI_HANDLE                      *Handles;\r
+  VOID                            *FileBuffer;\r
+\r
+  EfiBootManagerConnectAll ();\r
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles);\r
+  if (EFI_ERROR (Status)) {\r
+    HandleCount = 0;\r
+    Handles = NULL;\r
+  }\r
+\r
+  FileBuffer = NULL;\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    FileBuffer = BmGetFileBufferFromLoadFile (Handles[Index], FilePath, FullPath, FileSize);\r
+    if (FileBuffer != NULL) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Save the partition DevicePath to the CachedDevicePath as the first instance.\r
+\r
+  @param CachedDevicePath  The device path cache.\r
+  @param DevicePath        The partition device path to be cached.\r
+**/\r
+VOID\r
+BmCachePartitionDevicePath (\r
+  IN OUT EFI_DEVICE_PATH_PROTOCOL **CachedDevicePath,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
+  UINTN                           Count;\r
+  \r
+  if (BmMatchDevicePaths (*CachedDevicePath, DevicePath)) {\r
+    TempDevicePath = *CachedDevicePath;\r
+    *CachedDevicePath = BmDelPartMatchInstance (*CachedDevicePath, DevicePath);\r
+    FreePool (TempDevicePath);\r
+  }\r
+\r
+  if (*CachedDevicePath == NULL) {\r
+    *CachedDevicePath = DuplicateDevicePath (DevicePath);\r
+    return;\r
+  }\r
+\r
+  TempDevicePath = *CachedDevicePath;\r
+  *CachedDevicePath = AppendDevicePathInstance (DevicePath, *CachedDevicePath);\r
+  if (TempDevicePath != NULL) {\r
+    FreePool (TempDevicePath);\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, the 'HDDP' variable maybe become larger and larger.\r
-  //\r
+  // Here limit the device path instance number to 12, which is max number for a system support 3 IDE controller\r
+  // If the user try to boot many OS in different HDs or partitions, in theory, the 'HDDP' variable maybe become larger and larger.\r
+  //\r
   Count = 0;\r
   TempDevicePath = *CachedDevicePath;\r
   while (!IsDevicePathEnd (TempDevicePath)) {\r
@@ -1210,7 +851,7 @@ BmExpandPartitionDevicePath (
         Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
         if (!EFI_ERROR (Status)) {\r
           TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));\r
-          FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+          FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
           FreePool (TempDevicePath);\r
 \r
           if (FileBuffer != NULL) {\r
@@ -1246,177 +887,531 @@ BmExpandPartitionDevicePath (
     } while (TempNewDevicePath != NULL);\r
   }\r
 \r
-  //\r
-  // If we get here we fail to find or 'HDDP' not exist, and now we need\r
-  // to search all devices in the system for a matched partition\r
-  //\r
-  EfiBootManagerConnectAll ();\r
-  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+  //\r
+  // If we get here we fail to find or 'HDDP' not exist, and now we need\r
+  // to search all devices in the system for a matched partition\r
+  //\r
+  EfiBootManagerConnectAll ();\r
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    BlockIoHandleCount = 0;\r
+    BlockIoBuffer      = 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
+    BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);\r
+    if (BlockIoDevicePath == NULL) {\r
+      continue;\r
+    }\r
+\r
+    if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) FilePath)) {\r
+      //\r
+      // Find the matched partition device path\r
+      //\r
+      TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));\r
+      FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+      FreePool (TempDevicePath);\r
+\r
+      if (FileBuffer != NULL) {\r
+        BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);\r
+\r
+        //\r
+        // Save the matching Device Path so we don't need to do a connect all next time\r
+        // Failing to save only impacts performance next time expanding the short-form device path\r
+        //\r
+        Status = gRT->SetVariable (\r
+                        L"HDDP",\r
+                        &mBmHardDriveBootVariableGuid,\r
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                        GetDevicePathSize (CachedDevicePath),\r
+                        CachedDevicePath\r
+                        );\r
+\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (CachedDevicePath != NULL) {\r
+    FreePool (CachedDevicePath);\r
+  }\r
+  if (BlockIoBuffer != NULL) {\r
+    FreePool (BlockIoBuffer);\r
+  }\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Expand the media device path which points to a BlockIo or SimpleFileSystem instance\r
+  by appending EFI_REMOVABLE_MEDIA_FILE_NAME.\r
+\r
+  @param DevicePath  The media device path pointing to a BlockIo or SimpleFileSystem instance.\r
+  @param FullPath    Return the full device path pointing to the load option.\r
+  @param FileSize    Return the size of the load option.\r
+\r
+  @return  The load option buffer.\r
+**/\r
+VOID *\r
+BmExpandMediaDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
+  OUT UINTN                           *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\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                          *SimpleFileSystemHandles;\r
+  UINTN                               NumberSimpleFileSystemHandles;\r
+  UINTN                               Index;\r
+  VOID                                *FileBuffer;\r
+  UINT32                              AuthenticationStatus;\r
+\r
+  //\r
+  // Check whether the device is connected\r
+  //\r
+  TempDevicePath = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
+  if (!EFI_ERROR (Status)) {\r
+    ASSERT (IsDevicePathEnd (TempDevicePath));\r
+\r
+    TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+    FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
+    if (FileBuffer == NULL) {\r
+      FreePool (TempDevicePath);\r
+      TempDevicePath = NULL;\r
+    }\r
+    *FullPath = TempDevicePath;\r
+    return FileBuffer;\r
+  }\r
+\r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // For device boot option only pointing to the removable device handle,\r
+  // should make sure all its children handles (its child partion or media handles)\r
+  // are created and connected.\r
+  //\r
+  gBS->ConnectController (Handle, NULL, NULL, TRUE);\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
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+  ASSERT_EFI_ERROR (Status);\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
+  // Detect the the default boot file from removable Media\r
+  //\r
+  FileBuffer = NULL;\r
+  *FullPath = NULL;\r
+  Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;\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) - END_DEVICE_PATH_LENGTH;\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, DevicePath, Size) == 0)) {\r
+      TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
+      FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
+      if (FileBuffer != NULL) {\r
+        *FullPath = TempDevicePath;\r
+        break;\r
+      }\r
+      FreePool (TempDevicePath);\r
+    }\r
+  }\r
+\r
+  if (SimpleFileSystemHandles != NULL) {\r
+    FreePool (SimpleFileSystemHandles);\r
+  }\r
+\r
+  return FileBuffer;\r
+}\r
+\r
+/**\r
+  Check whether Left and Right are the same without matching the specific\r
+  device path data in IP device path and URI device path node.\r
+\r
+  @retval TRUE  Left and Right are the same.\r
+  @retval FALSE Left and Right are the different.\r
+**/\r
+BOOLEAN\r
+BmMatchHttpBootDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *Left,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *Right\r
+  )\r
+{\r
+  for (;  !IsDevicePathEnd (Left) && !IsDevicePathEnd (Right)\r
+       ;  Left = NextDevicePathNode (Left), Right = NextDevicePathNode (Right)\r
+       ) {\r
+    if (CompareMem (Left, Right, DevicePathNodeLength (Left)) != 0) {\r
+      if ((DevicePathType (Left) != MESSAGING_DEVICE_PATH) || (DevicePathType (Right) != MESSAGING_DEVICE_PATH)) {\r
+        return FALSE;\r
+      }\r
+\r
+      if (((DevicePathSubType (Left) != MSG_IPv4_DP) || (DevicePathSubType (Right) != MSG_IPv4_DP)) &&\r
+          ((DevicePathSubType (Left) != MSG_IPv6_DP) || (DevicePathSubType (Right) != MSG_IPv6_DP)) &&\r
+          ((DevicePathSubType (Left) != MSG_URI_DP)  || (DevicePathSubType (Right) != MSG_URI_DP))\r
+          ) {\r
+        return FALSE;\r
+      }\r
+    }\r
+  }\r
+  return (BOOLEAN) (IsDevicePathEnd (Left) && IsDevicePathEnd (Right));\r
+}\r
+\r
+/**\r
+  Get the file buffer from the file system produced by Load File instance.\r
+\r
+  @param LoadFileHandle The handle of LoadFile instance.\r
+  @param FullPath       Return the full device path pointing to the load option.\r
+  @param FileSize       Return the size of the load option.\r
+  @param RamDiskHandle  Return the RAM Disk handle.\r
+\r
+  @return  The load option buffer.\r
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFileSystem (\r
+  IN  EFI_HANDLE                      LoadFileHandle,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
+  OUT UINTN                           *FileSize,\r
+  OUT EFI_HANDLE                      *RamDiskHandle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_HANDLE                      Handle;\r
+  EFI_HANDLE                      *Handles;\r
+  UINTN                           HandleCount;\r
+  UINTN                           Index;\r
+  EFI_DEVICE_PATH_PROTOCOL        *Node;\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiBlockIoProtocolGuid,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Handles = NULL;\r
+    HandleCount = 0;\r
+  }\r
+\r
+  Handle = NULL;\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Node = DevicePathFromHandle (Handles[Index]);\r
+    Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+    if (!EFI_ERROR (Status) &&\r
+        (Handle == LoadFileHandle) &&\r
+        (DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)) {\r
+      Handle = Handles[Index];\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  if (Index == HandleCount) {\r
+    Handle = NULL;\r
+  }\r
+\r
+  *RamDiskHandle = Handle;\r
+\r
+  if (Handle != NULL) {\r
+    return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize);\r
+  } else {\r
+    return NULL;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Return the RAM Disk device path created by LoadFile.\r
+\r
+  @param FilePath  The source file path.\r
+\r
+  @return Callee-to-free RAM Disk device path\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmGetRamDiskDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_DEVICE_PATH_PROTOCOL    *RamDiskDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL    *Node;\r
+  EFI_HANDLE                  Handle;\r
+\r
+  Node = FilePath;\r
+  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+  if (!EFI_ERROR (Status) &&\r
+      (DevicePathType (Node) == MEDIA_DEVICE_PATH) &&\r
+      (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)\r
+      ) {\r
+\r
+    //\r
+    // Construct the device path pointing to RAM Disk\r
+    //\r
+    Node = NextDevicePathNode (Node);\r
+    RamDiskDevicePath = DuplicateDevicePath (FilePath);\r
+    ASSERT (RamDiskDevicePath != NULL);\r
+    SetDevicePathEndNode ((VOID *) ((UINTN) RamDiskDevicePath + ((UINTN) Node - (UINTN) FilePath)));\r
+    return RamDiskDevicePath;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Return the buffer and buffer size occupied by the RAM Disk.\r
+\r
+  @param RamDiskDevicePath  RAM Disk device path.\r
+  @param RamDiskSizeInPages Return RAM Disk size in pages.\r
+\r
+  @retval RAM Disk buffer.\r
+**/\r
+VOID *\r
+BmGetRamDiskMemoryInfo (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath,\r
+  OUT UINTN                   *RamDiskSizeInPages\r
+  )\r
+{\r
+\r
+  EFI_STATUS                  Status;\r
+  EFI_HANDLE                  Handle;\r
+  UINT64                      StartingAddr;\r
+  UINT64                      EndingAddr;\r
+\r
+  ASSERT (RamDiskDevicePath != NULL);\r
+\r
+  *RamDiskSizeInPages = 0;\r
+\r
+  //\r
+  // Get the buffer occupied by RAM Disk.\r
+  //\r
+  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &RamDiskDevicePath, &Handle);\r
+  ASSERT_EFI_ERROR (Status);\r
+  ASSERT ((DevicePathType (RamDiskDevicePath) == MEDIA_DEVICE_PATH) &&\r
+          (DevicePathSubType (RamDiskDevicePath) == MEDIA_RAM_DISK_DP));\r
+  StartingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->StartingAddr);\r
+  EndingAddr   = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->EndingAddr);\r
+  *RamDiskSizeInPages = EFI_SIZE_TO_PAGES ((UINTN) (EndingAddr - StartingAddr + 1));\r
+  return (VOID *) (UINTN) StartingAddr;\r
+}\r
+\r
+/**\r
+  Destroy the RAM Disk.\r
+\r
+  The destroy operation includes to call RamDisk.Unregister to\r
+  unregister the RAM DISK from RAM DISK driver, free the memory\r
+  allocated for the RAM Disk.\r
+\r
+  @param RamDiskDevicePath    RAM Disk device path.\r
+**/\r
+VOID\r
+BmDestroyRamDisk (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  VOID                        *RamDiskBuffer;\r
+  UINTN                       RamDiskSizeInPages;\r
+\r
+  ASSERT (RamDiskDevicePath != NULL);\r
+\r
+  RamDiskBuffer = BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
+\r
+  //\r
+  // Destroy RAM Disk.\r
+  //\r
+  if (mRamDisk == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID *) &mRamDisk);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  Status = mRamDisk->Unregister (RamDiskDevicePath);\r
+  ASSERT_EFI_ERROR (Status);\r
+  FreePages (RamDiskBuffer, RamDiskSizeInPages);\r
+}\r
+\r
+/**\r
+  Get the file buffer from the specified Load File instance.\r
+\r
+  @param LoadFileHandle The specified Load File instance.\r
+  @param FilePath       The file path which will pass to LoadFile().\r
+  @param FullPath       Return the full device path pointing to the load option.\r
+  @param FileSize       Return the size of the load option.\r
+\r
+  @return  The load option buffer or NULL if fails.\r
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFile (\r
+  IN  EFI_HANDLE                      LoadFileHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *FilePath,\r
+  OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
+  OUT UINTN                           *FileSize\r
+  )\r
+{\r
+  EFI_STATUS                          Status;\r
+  EFI_LOAD_FILE_PROTOCOL              *LoadFile;\r
+  VOID                                *FileBuffer;\r
+  BOOLEAN                             LoadFileSystem;\r
+  EFI_HANDLE                          RamDiskHandle;\r
+  UINTN                               BufferSize;\r
+\r
+  *FileSize = 0;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  LoadFileHandle,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  (VOID **) &LoadFile,\r
+                  gImageHandle,\r
+                  NULL,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  FileBuffer = NULL;\r
+  BufferSize = 0;\r
+  Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+  if ((Status != EFI_WARN_FILE_SYSTEM) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+    return NULL;\r
+  }\r
+\r
+  LoadFileSystem = (BOOLEAN) (Status == EFI_WARN_FILE_SYSTEM);\r
+  FileBuffer = LoadFileSystem ? AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize)) : AllocatePool (BufferSize);\r
+  if (FileBuffer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
   if (EFI_ERROR (Status)) {\r
-    BlockIoHandleCount = 0;\r
-    BlockIoBuffer      = 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
-    BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[Index]);\r
-    if (BlockIoDevicePath == NULL) {\r
-      continue;\r
+    if (LoadFileSystem) {\r
+      FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+    } else {\r
+      FreePool (FileBuffer);\r
     }\r
+    return NULL;\r
+  }\r
 \r
-    if (BmMatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) FilePath)) {\r
+  if (LoadFileSystem) {\r
+    FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize, &RamDiskHandle);\r
+    if (FileBuffer == NULL) {\r
       //\r
-      // Find the matched partition device path\r
+      // If there is no bootable executable in the populated\r
       //\r
-      TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));\r
-      FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
-      FreePool (TempDevicePath);\r
-\r
-      if (FileBuffer != NULL) {\r
-        BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);\r
-\r
-        //\r
-        // Save the matching Device Path so we don't need to do a connect all next time\r
-        // Failing to save only impacts performance next time expanding the short-form device path\r
-        //\r
-        Status = gRT->SetVariable (\r
-                        L"HDDP",\r
-                        &mBmHardDriveBootVariableGuid,\r
-                        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-                        GetDevicePathSize (CachedDevicePath),\r
-                        CachedDevicePath\r
-                        );\r
-\r
-        break;\r
-      }\r
+      BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));\r
     }\r
+  } else {\r
+    *FileSize = BufferSize;\r
+    *FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));\r
   }\r
 \r
-  if (CachedDevicePath != NULL) {\r
-    FreePool (CachedDevicePath);\r
-  }\r
-  if (BlockIoBuffer != NULL) {\r
-    FreePool (BlockIoBuffer);\r
-  }\r
   return FileBuffer;\r
 }\r
 \r
 /**\r
-  Expand the media device path which points to a BlockIo or SimpleFileSystem instance\r
-  by appending EFI_REMOVABLE_MEDIA_FILE_NAME.\r
+  Get the file buffer from all the Load File instances.\r
 \r
-  @param DevicePath  The media device path pointing to a BlockIo or SimpleFileSystem instance.\r
+  @param FilePath    The media device path pointing to a LoadFile instance.\r
   @param FullPath    Return the full device path pointing to the load option.\r
   @param FileSize    Return the size of the load option.\r
 \r
   @return  The load option buffer.\r
 **/\r
 VOID *\r
-BmExpandMediaDevicePath (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,\r
+BmGetFileBufferFromLoadFiles (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL        *FilePath,\r
   OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
   OUT UINTN                           *FileSize\r
   )\r
 {\r
-  EFI_STATUS                          Status;\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                          *SimpleFileSystemHandles;\r
-  UINTN                               NumberSimpleFileSystemHandles;\r
-  UINTN                               Index;\r
-  VOID                                *FileBuffer;\r
-  UINT32                              AuthenticationStatus;\r
-\r
-  //\r
-  // Check whether the device is connected\r
-  //\r
-  TempDevicePath = DevicePath;\r
-  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &Handle);\r
-  if (!EFI_ERROR (Status)) {\r
-    ASSERT (IsDevicePathEnd (TempDevicePath));\r
-\r
-    TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
-    FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
-    if (FileBuffer == NULL) {\r
-      FreePool (TempDevicePath);\r
-      TempDevicePath = NULL;\r
-    }\r
-    *FullPath = TempDevicePath;\r
-    return FileBuffer;\r
-  }\r
-\r
-  //\r
-  // For device boot option only pointing 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
-  //\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
-  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
-  ASSERT_EFI_ERROR (Status);\r
-  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
-  ASSERT_EFI_ERROR (Status);\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
+  EFI_STATUS                      Status;\r
+  EFI_HANDLE                      Handle;\r
+  EFI_HANDLE                      *Handles;\r
+  UINTN                           HandleCount;\r
+  UINTN                           Index;\r
+  EFI_DEVICE_PATH_PROTOCOL        *Node;\r
 \r
   //\r
-  // Detect the the default boot file from removable Media\r
+  // Get file buffer from load file instance.\r
   //\r
-  FileBuffer = NULL;\r
-  *FullPath = NULL;\r
-  Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;\r
-  gBS->LocateHandleBuffer (\r
-         ByProtocol,\r
-         &gEfiSimpleFileSystemProtocolGuid,\r
-         NULL,\r
-         &NumberSimpleFileSystemHandles,\r
-         &SimpleFileSystemHandles\r
-         );\r
-  for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {\r
+  Node = FilePath;\r
+  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+  if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {\r
     //\r
-    // Get the device path size of SimpleFileSystem handle\r
+    // When wide match happens, pass full device path to LoadFile (),\r
+    // otherwise, pass remaining device path to LoadFile ().\r
     //\r
-    TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);\r
-    TempSize = GetDevicePathSize (TempDevicePath) - END_DEVICE_PATH_LENGTH;\r
+    FilePath = Node;\r
+  } else {\r
+    Handle = NULL;\r
     //\r
-    // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path\r
+    // Use wide match algorithm to find one when\r
+    //  cannot find a LoadFile instance to exactly match the FilePath\r
     //\r
-    if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {\r
-      TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);\r
-      FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);\r
-      if (FileBuffer != NULL) {\r
-        *FullPath = TempDevicePath;\r
+    Status = gBS->LocateHandleBuffer (\r
+                    ByProtocol,\r
+                    &gEfiLoadFileProtocolGuid,\r
+                    NULL,\r
+                    &HandleCount,\r
+                    &Handles\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      Handles = NULL;\r
+      HandleCount = 0;\r
+    }\r
+    for (Index = 0; Index < HandleCount; Index++) {\r
+      if (BmMatchHttpBootDevicePath (DevicePathFromHandle (Handles[Index]), FilePath)) {\r
+        Handle = Handles[Index];\r
         break;\r
       }\r
-      FreePool (TempDevicePath);\r
+    }\r
+    if (Handles != NULL) {\r
+      FreePool (Handles);\r
     }\r
   }\r
 \r
-  if (SimpleFileSystemHandles != NULL) {\r
-    FreePool (SimpleFileSystemHandles);\r
+  if (Handle == NULL) {\r
+    return NULL;\r
   }\r
 \r
-  return FileBuffer;\r
+  return BmGetFileBufferFromLoadFile (Handle, FilePath, FullPath, FileSize);\r
 }\r
 \r
 /**\r
@@ -1432,7 +1427,8 @@ BmExpandMediaDevicePath (
   @return The load option buffer. Caller is responsible to free the memory.\r
 **/\r
 VOID *\r
-BmGetLoadOptionBuffer (\r
+EFIAPI\r
+EfiBootManagerGetLoadOptionBuffer (\r
   IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,\r
   OUT EFI_DEVICE_PATH_PROTOCOL          **FullPath,\r
   OUT UINTN                             *FileSize\r
@@ -1474,6 +1470,18 @@ BmGetLoadOptionBuffer (
     // Expand the Harddrive device path\r
     //\r
     return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize);\r
+  } else if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&\r
+             (DevicePathSubType (FilePath) == MEDIA_FILEPATH_DP)) {\r
+    //\r
+    // Expand the File-path device path\r
+    //\r
+    return BmExpandFileDevicePath (FilePath, FullPath, FileSize);\r
+  } else if ((DevicePathType (FilePath) == MESSAGING_DEVICE_PATH) &&\r
+             (DevicePathSubType (FilePath) == MSG_URI_DP)) {\r
+    //\r
+    // Expand the URI device path\r
+    //\r
+    return BmExpandUriDevicePath (FilePath, FullPath, FileSize);\r
   } else {\r
     for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
       if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
@@ -1501,31 +1509,54 @@ BmGetLoadOptionBuffer (
   }\r
 \r
   //\r
-  // Fix up the boot option path if it points to a FV in memory map style of device path\r
+  // Get file buffer from FV file path.\r
   //\r
-  if (BmIsMemmapFvFilePath (FilePath)) {\r
-    return BmGetFileBufferByMemmapFv (FilePath, FullPath, FileSize);\r
+  if (BmIsFvFilePath (FilePath)) {\r
+    return BmGetFileBufferByFvFilePath (FilePath, FullPath, FileSize);\r
   }\r
 \r
   //\r
-  // Directly reads the load option when it doesn't reside in simple file system instance (LoadFile/LoadFile2),\r
-  //   or it directly points to a file in simple file system instance.\r
+  // Get file buffer from simple file system.\r
   //\r
   Node   = FilePath;\r
-  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
-  FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
-  if (FileBuffer != NULL) {\r
-    if (EFI_ERROR (Status)) {\r
+  Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);\r
+  if (!EFI_ERROR (Status)) {\r
+    FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
+    if (FileBuffer != NULL) {\r
       *FullPath = DuplicateDevicePath (FilePath);\r
-    } else {\r
-      //\r
-      // LoadFile () may cause the device path of the Handle be updated.\r
-      //\r
-      *FullPath = AppendDevicePath (DevicePathFromHandle (Handle), Node);\r
     }\r
+    return FileBuffer;\r
   }\r
 \r
-  return FileBuffer;\r
+  return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);\r
+}\r
+\r
+/**\r
+  Check if it's a Device Path pointing to BootManagerMenu.\r
+\r
+  @param  DevicePath     Input device path.\r
+\r
+  @retval TRUE   The device path is BootManagerMenu File Device Path.\r
+  @retval FALSE  The device path is NOT BootManagerMenu File Device Path.\r
+**/\r
+BOOLEAN\r
+BmIsBootManagerMenuFilePath (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+)\r
+{\r
+  EFI_HANDLE                      FvHandle;\r
+  VOID                            *NameGuid;\r
+  EFI_STATUS                      Status;\r
+\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);\r
+  if (!EFI_ERROR (Status)) {\r
+    NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);\r
+    if (NameGuid != NULL) {\r
+      return CompareGuid (NameGuid, PcdGetPtr (PcdBootManagerMenuFile));\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -1561,8 +1592,7 @@ EfiBootManagerBoot (
   UINTN                     OptionNumber;\r
   UINTN                     OriginalOptionNumber;\r
   EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
-  EFI_HANDLE                FvHandle;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RamDiskDevicePath;\r
   VOID                      *FileBuffer;\r
   UINTN                     FileSize;\r
   EFI_BOOT_LOGO_PROTOCOL    *BootLogo;\r
@@ -1617,12 +1647,7 @@ EfiBootManagerBoot (
   // 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute\r
   //    the boot option.\r
   //\r
-  Node   = BootOption->FilePath;\r
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
-  if (!EFI_ERROR (Status) && CompareGuid (\r
-        EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
-        PcdGetPtr (PcdBootManagerMenuFile)\r
-        )) {\r
+  if (BmIsBootManagerMenuFilePath (BootOption->FilePath)) {\r
     DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));\r
     BmStopHotkeyService (NULL, NULL);\r
   } else {\r
@@ -1640,12 +1665,32 @@ EfiBootManagerBoot (
   PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
 \r
   //\r
-  // 5. Load EFI boot option to ImageHandle\r
+  // 5. 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
+  BmSetMemoryTypeInformationVariable (\r
+    (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
+  );\r
+\r
+  //\r
+  // 6. Load EFI boot option to ImageHandle\r
   //\r
-  ImageHandle = NULL;\r
+  DEBUG_CODE_BEGIN ();\r
+  if (BootOption->Description == NULL) {\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
+  } else {\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
+  }\r
+  DEBUG_CODE_END ();\r
+\r
+  ImageHandle       = NULL;\r
+  RamDiskDevicePath = NULL;\r
   if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {\r
     Status     = EFI_NOT_FOUND;\r
-    FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
+    FileBuffer = EfiBootManagerGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
+    if (FileBuffer != NULL) {\r
+      RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);\r
+    }\r
     DEBUG_CODE (\r
       if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {\r
         DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));\r
@@ -1682,28 +1727,17 @@ EfiBootManagerBoot (
         (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
         );\r
       BootOption->Status = Status;\r
+      //\r
+      // Destroy the RAM disk\r
+      //\r
+      if (RamDiskDevicePath != NULL) {\r
+        BmDestroyRamDisk (RamDiskDevicePath);\r
+        FreePool (RamDiskDevicePath);\r
+      }\r
       return;\r
     }\r
   }\r
 \r
-  //\r
-  // 6. 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
-  if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT) {\r
-    if (PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {\r
-      BmSetMemoryTypeInformationVariable ();\r
-    }\r
-  }\r
-\r
-  DEBUG_CODE_BEGIN();\r
-    if (BootOption->Description == NULL) {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
-    } else {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
-    }\r
-  DEBUG_CODE_END();\r
-\r
   //\r
   // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
   // Write boot to OS performance data for Legacy boot\r
@@ -1741,8 +1775,10 @@ EfiBootManagerBoot (
   Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  ImageInfo->LoadOptionsSize  = BootOption->OptionalDataSize;\r
-  ImageInfo->LoadOptions      = BootOption->OptionalData;\r
+  if (!BmIsAutoCreateBootOption (BootOption)) {\r
+    ImageInfo->LoadOptionsSize = BootOption->OptionalDataSize;\r
+    ImageInfo->LoadOptions     = BootOption->OptionalData;\r
+  }\r
 \r
   //\r
   // Clean to NULL because the image is loaded directly from the firmwares boot manager.\r
@@ -1777,6 +1813,14 @@ EfiBootManagerBoot (
   }\r
   PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
 \r
+  //\r
+  // Destroy the RAM disk\r
+  //\r
+  if (RamDiskDevicePath != NULL) {\r
+    BmDestroyRamDisk (RamDiskDevicePath);\r
+    FreePool (RamDiskDevicePath);\r
+  }\r
+\r
   //\r
   // Clear the Watchdog Timer after the image returns\r
   //\r
@@ -2017,7 +2061,7 @@ BmEnumerateBootOptions (
   }\r
 \r
   //\r
-  // Parse load file, assuming UEFI Network boot option\r
+  // Parse load file protocol\r
   //\r
   gBS->LocateHandleBuffer (\r
          ByProtocol,\r
@@ -2027,6 +2071,12 @@ BmEnumerateBootOptions (
          &Handles\r
          );\r
   for (Index = 0; Index < HandleCount; Index++) {\r
+    //\r
+    // Ignore BootManagerMenu. its boot option will be created by EfiBootManagerGetBootManagerMenu().\r
+    //\r
+    if (BmIsBootManagerMenuFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+      continue;\r
+    }\r
 \r
     Description = BmGetBootDescription (Handles[Index]);\r
     BootOptions = ReallocatePool (\r
@@ -2054,6 +2104,7 @@ BmEnumerateBootOptions (
     FreePool (Handles);\r
   }\r
 \r
+  BmMakeBootOptionDescriptionUnique (BootOptions, *BootOptionCount);\r
   return BootOptions;\r
 }\r
 \r
@@ -2097,15 +2148,13 @@ EfiBootManagerRefreshAllBootOption (
   for (Index = 0; Index < NvBootOptionCount; Index++) {\r
     if (((DevicePathType (NvBootOptions[Index].FilePath) != BBS_DEVICE_PATH) || \r
          (DevicePathSubType (NvBootOptions[Index].FilePath) != BBS_BBS_DP)\r
-        ) &&\r
-        (NvBootOptions[Index].OptionalDataSize == sizeof (EFI_GUID)) &&\r
-        CompareGuid ((EFI_GUID *) NvBootOptions[Index].OptionalData, &mBmAutoCreateBootOptionGuid)\r
+        ) && BmIsAutoCreateBootOption (&NvBootOptions[Index])\r
        ) {\r
       //\r
       // Only check those added by BDS\r
       // so that the boot options added by end-user or OS installer won't be deleted\r
       //\r
-      if (BmFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {\r
+      if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == -1) {\r
         Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
         //\r
         // Deleting variable with current variable implementation shouldn't fail.\r
@@ -2119,7 +2168,7 @@ EfiBootManagerRefreshAllBootOption (
   // Add new EFI boot options to NV\r
   //\r
   for (Index = 0; Index < BootOptionCount; Index++) {\r
-    if (BmFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {\r
+    if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == -1) {\r
       EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
       //\r
       // Try best to add the boot options so continue upon failure.\r
@@ -2132,7 +2181,7 @@ EfiBootManagerRefreshAllBootOption (
 }\r
 \r
 /**\r
-  This function is called to create the boot option for the Boot Manager Menu.\r
+  This function is called to get or create the boot option for the Boot Manager Menu.\r
 \r
   The Boot Manager Menu is shown after successfully booting a boot option.\r
   Assume the BootManagerMenuFile is in the same FV as the module links to this library.\r
@@ -2140,8 +2189,10 @@ EfiBootManagerRefreshAllBootOption (
   @param  BootOption    Return the boot option of the Boot Manager Menu\r
 \r
   @retval EFI_SUCCESS   Successfully register the Boot Manager Menu.\r
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+  @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+  @retval others        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+                        and EFI_NOT_FOUND.\r
 **/\r
 EFI_STATUS\r
 BmRegisterBootManagerMenu (\r
@@ -2154,30 +2205,79 @@ BmRegisterBootManagerMenu (
   EFI_DEVICE_PATH_PROTOCOL           *DevicePath;\r
   EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;\r
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;\r
+  UINTN                              HandleCount;\r
+  EFI_HANDLE                         *Handles;\r
+  UINTN                              Index;\r
+  VOID                               *Data;\r
+  UINTN                              DataSize;\r
 \r
-  Status = GetSectionFromFv (\r
-             PcdGetPtr (PcdBootManagerMenuFile),\r
-             EFI_SECTION_USER_INTERFACE,\r
-             0,\r
-             (VOID **) &Description,\r
-             &DescriptionLength\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    Description = NULL;\r
+  DevicePath = NULL;\r
+  Description = NULL;\r
+  //\r
+  // Try to find BootManagerMenu from LoadFile protocol\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiLoadFileProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    if (BmIsBootManagerMenuFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+      DevicePath  = DuplicateDevicePath (DevicePathFromHandle (Handles[Index]));\r
+      Description = BmGetBootDescription (Handles[Index]);\r
+      break;\r
+    }\r
+  }\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\r
   }\r
 \r
-  EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
-  Status = gBS->HandleProtocol (\r
-                  gImageHandle,\r
-                  &gEfiLoadedImageProtocolGuid,\r
-                  (VOID **) &LoadedImage\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-  DevicePath = AppendDevicePathNode (\r
-                 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
-                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
-                 );\r
-  ASSERT (DevicePath != NULL);\r
+  if (DevicePath == NULL) {\r
+    Data = NULL;\r
+    Status = GetSectionFromFv (\r
+               PcdGetPtr (PcdBootManagerMenuFile),\r
+               EFI_SECTION_PE32,\r
+               0,\r
+               (VOID **) &Data,\r
+               &DataSize\r
+               );\r
+    if (Data != NULL) {\r
+      FreePool (Data);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_WARN, "[Bds]BootManagerMenu FFS section can not be found, skip its boot option registration\n"));\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Get BootManagerMenu application's description from EFI User Interface Section.\r
+    //\r
+    Status = GetSectionFromFv (\r
+               PcdGetPtr (PcdBootManagerMenuFile),\r
+               EFI_SECTION_USER_INTERFACE,\r
+               0,\r
+               (VOID **) &Description,\r
+               &DescriptionLength\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      Description = NULL;\r
+    }\r
+\r
+    EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
+    Status = gBS->HandleProtocol (\r
+                    gImageHandle,\r
+                    &gEfiLoadedImageProtocolGuid,\r
+                    (VOID **) &LoadedImage\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+    DevicePath = AppendDevicePathNode (\r
+                   DevicePathFromHandle (LoadedImage->DeviceHandle),\r
+                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
+                   );\r
+    ASSERT (DevicePath != NULL);\r
+  }\r
 \r
   Status = EfiBootManagerInitializeLoadOption (\r
              BootOption,\r
@@ -2200,7 +2300,7 @@ BmRegisterBootManagerMenu (
     UINTN                           BootOptionCount;\r
 \r
     BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
-    ASSERT (BmFindLoadOption (BootOption, BootOptions, BootOptionCount) == -1);\r
+    ASSERT (EfiBootManagerFindLoadOption (BootOption, BootOptions, BootOptionCount) == -1);\r
     EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
     );\r
 \r
@@ -2210,12 +2310,14 @@ BmRegisterBootManagerMenu (
 /**\r
   Return the boot option corresponding to the Boot Manager Menu.\r
   It may automatically create one if the boot option hasn't been created yet.\r
-  \r
+\r
   @param BootOption    Return the Boot Manager Menu.\r
 \r
   @retval EFI_SUCCESS   The Boot Manager Menu is successfully returned.\r
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+  @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+  @retval others        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+                        and EFI_NOT_FOUND.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2227,20 +2329,11 @@ EfiBootManagerGetBootManagerMenu (
   UINTN                        BootOptionCount;\r
   EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
   UINTN                        Index;\r
-  EFI_DEVICE_PATH_PROTOCOL     *Node;\r
-  EFI_HANDLE                   FvHandle;\r
   \r
   BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
 \r
   for (Index = 0; Index < BootOptionCount; Index++) {\r
-    Node   = BootOptions[Index].FilePath;\r
-    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
-    if (!EFI_ERROR (Status)) {\r
-      if (CompareGuid (\r
-            EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
-            PcdGetPtr (PcdBootManagerMenuFile)\r
-            )\r
-          ) {        \r
+    if (BmIsBootManagerMenuFilePath (BootOptions[Index].FilePath)) {\r
         Status = EfiBootManagerInitializeLoadOption (\r
                    BootOption,\r
                    BootOptions[Index].OptionNumber,\r
@@ -2253,7 +2346,6 @@ EfiBootManagerGetBootManagerMenu (
                    );\r
         ASSERT_EFI_ERROR (Status);\r
         break;\r
-      }\r
     }\r
   }\r
 \r