]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c
Add new interface GetVariable2 and GetEfiGlobalVariable2 to return more info. Also...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsBoot.c
index d0ce36e9870a9c73fe601592498641fb60596a0f..91dc6def4e7b233f44f2809498f1f3d483d0bff3 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   BDS Lib functions which relate with create or process the boot option.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -13,14 +13,42 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "InternalBdsLib.h"\r
+#include "String.h"\r
 \r
 BOOLEAN mEnumBootDevice = FALSE;\r
+EFI_HII_HANDLE gBdsLibStringPackHandle = NULL;\r
 \r
-///\r
-/// This GUID is used for an EFI Variable that stores the front device pathes\r
-/// for a partial device path that starts with the HD node.\r
-///\r
-EFI_GUID  mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
+/**\r
+  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
 \r
@@ -55,7 +83,7 @@ BdsLibDoLegacyBoot (
   BdsRefreshBbsTableForBoot (Option);\r
 \r
   //\r
-  // Write boot to OS performance data to a file\r
+  // Write boot to OS performance data for legacy boot.\r
   //\r
   PERF_CODE (\r
     WriteBootToOsPerformanceData ();\r
@@ -77,7 +105,7 @@ BdsLibDoLegacyBoot (
 \r
   @retval TRUE      This boot option matches a valid EFI NV Boot####.\r
   @retval FALSE     If not.\r
-  \r
+\r
 **/\r
 BOOLEAN\r
 IsBootOptionValidNVVarialbe (\r
@@ -100,7 +128,7 @@ IsBootOptionValidNVVarialbe (
   }\r
 \r
   //\r
-  // If the Boot Option Number and Device Path matches, OptionToCheck matches a \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
@@ -110,9 +138,457 @@ IsBootOptionValidNVVarialbe (
   }\r
 \r
   FreePool (BootOption);\r
-    \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
@@ -138,6 +614,7 @@ BdsLibBootViaBootOption (
   )\r
 {\r
   EFI_STATUS                Status;\r
+  EFI_STATUS                StatusLogo;\r
   EFI_HANDLE                Handle;\r
   EFI_HANDLE                ImageHandle;\r
   EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
@@ -145,21 +622,16 @@ BdsLibBootViaBootOption (
   EFI_DEVICE_PATH_PROTOCOL  *WorkingDevicePath;\r
   EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;\r
   LIST_ENTRY                TempBootLists;\r
-  EFI_SECURITY_ARCH_PROTOCOL *SecurityProtocol;\r
+  EFI_BOOT_LOGO_PROTOCOL    *BootLogo;\r
 \r
   //\r
   // Record the performance data for End of BDS\r
   //\r
-  PERF_END (0, "BDS", NULL, 0);\r
+  PERF_END(NULL, "BDS", NULL, 0);\r
 \r
   *ExitDataSize = 0;\r
   *ExitData     = NULL;\r
 \r
-  //\r
-  // Notes: put EFI64 ROM Shadow Solution\r
-  //\r
-  EFI64_SHADOW_ALL_LEGACY_ROM ();\r
-\r
   //\r
   // Notes: this code can be remove after the s3 script table\r
   // hook on the event EVT_SIGNAL_READY_TO_BOOT or\r
@@ -183,12 +655,7 @@ BdsLibBootViaBootOption (
       DevicePath = WorkingDevicePath;\r
     }\r
   }\r
-  //\r
-  // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
-  //\r
-  EfiSignalEventReadyToBoot();\r
-  \r
-  \r
+\r
   //\r
   // Set Boot Current\r
   //\r
@@ -207,109 +674,137 @@ BdsLibBootViaBootOption (
           );\r
   }\r
 \r
-  ASSERT (Option->DevicePath != NULL);\r
-  if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) &&\r
-      (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP)\r
-    ) {\r
-    //\r
-    // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
-    //\r
-    return BdsLibDoLegacyBoot (Option);\r
-  }\r
+  //\r
+  // Signal the EVT_SIGNAL_READY_TO_BOOT event\r
+  //\r
+  EfiSignalEventReadyToBoot();\r
 \r
   //\r
-  // If the boot option point to Internal FV shell, make sure it is valid\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
-  Status = BdsLibUpdateFvFileDevicePath (&DevicePath, &gEfiShellFileGuid);\r
-  if (!EFI_ERROR(Status)) {\r
-    if (Option->DevicePath != NULL) {\r
-      FreePool(Option->DevicePath);\r
-    }\r
-    Option->DevicePath  = AllocateZeroPool (GetDevicePathSize (DevicePath));\r
-    ASSERT(Option->DevicePath != NULL);\r
-    CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath));\r
-    //\r
-    // Update the shell boot option\r
-    //\r
-    InitializeListHead (&TempBootLists);\r
-    BdsLibRegisterNewOption (&TempBootLists, DevicePath, L"EFI Internal Shell", L"BootOrder");\r
-    \r
-    //\r
-    // free the temporary device path created by BdsLibUpdateFvFileDevicePath()\r
-    //\r
-    FreePool (DevicePath); \r
-    DevicePath = Option->DevicePath;\r
-  }\r
+  ImageHandle = BdsExpandUsbShortFormDevicePath (DevicePath);\r
 \r
   //\r
-  // Measure GPT Table by SAP protocol.\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
-  Status = gBS->LocateProtocol (\r
-                  &gEfiSecurityArchProtocolGuid,\r
-                  NULL,\r
-                  (VOID**) &SecurityProtocol\r
-                  );\r
-  if (!EFI_ERROR (Status)) {\r
-    Status = SecurityProtocol->FileAuthenticationState (SecurityProtocol, 0, DevicePath);\r
-  }\r
+  BdsSetMemoryTypeInformationVariable ();\r
 \r
-  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\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
-  Status = gBS->LoadImage (\r
-                  TRUE,\r
-                  mBdsImageHandle,\r
-                  DevicePath,\r
-                  NULL,\r
-                  0,\r
-                  &ImageHandle\r
-                  );\r
+    DEBUG_CODE_BEGIN();\r
 \r
-  //\r
-  // If we didn't find an image directly, we need to try as if it is a removable device boot opotion\r
-  // and load the image according to the default boot behavior for removable device.\r
-  //\r
-  if (EFI_ERROR (Status)) {\r
+    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
-    // check if there is a bootable removable media could be found in this device path ,\r
-    // and get the bootable media handle\r
+    // Report status code for OS Loader LoadImage.\r
     //\r
-    Handle = BdsLibGetBootableHandle(DevicePath);\r
-    if (Handle == NULL) {\r
-       goto Done;\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
-    // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
-    //  machinename is ia32, ia64, x64, ...\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
-    FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
-    if (FilePath != NULL) {\r
-      Status = gBS->LoadImage (\r
-                      TRUE,\r
-                      mBdsImageHandle,\r
-                      FilePath,\r
-                      NULL,\r
-                      0,\r
-                      &ImageHandle\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        //\r
-        // The DevicePath failed, and it's not a valid\r
-        // removable media device.\r
-        //\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // check if there is a bootable removable media could be found in this device path ,\r
+      // and get the bootable media handle\r
+      //\r
+      Handle = BdsLibGetBootableHandle(DevicePath);\r
+      if (Handle == NULL) {\r
         goto Done;\r
       }\r
+      //\r
+      // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media\r
+      //  machinename is ia32, ia64, x64, ...\r
+      //\r
+      FilePath = FileDevicePath (Handle, 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
+       if (EFI_ERROR (Status)) {\r
+          //\r
+          // The DevicePath failed, and it's not a valid\r
+          // removable media device.\r
+          //\r
+          goto Done;\r
+        }\r
+      }\r
     }\r
-  }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // It there is any error from the Boot attempt exit now.\r
-    //\r
-    goto Done;\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // It there is any error from the Boot attempt exit now.\r
+      //\r
+      goto Done;\r
+    }\r
   }\r
   //\r
   // Provide the image with it's load options\r
   //\r
+  if (ImageHandle == NULL) {\r
+    goto Done;\r
+  }\r
   Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -317,12 +812,30 @@ BdsLibBootViaBootOption (
     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
+    WriteBootToOsPerformanceData ();\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
 \r
@@ -332,6 +845,15 @@ BdsLibBootViaBootOption (
   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
   //\r
@@ -385,16 +907,16 @@ BdsExpandPartitionPartialDevicePathToFull (
 \r
   FullDevicePath = NULL;\r
   //\r
-  // Check if there is prestore 'HDDP' variable.\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 'HDDP' not exist, reconnect all and search in all system\r
+  // If fail to find or HD_BOOT_DEVICE_PATH_VARIABLE_NAME not exist, reconnect all and search in all system\r
   //\r
   CachedDevicePath = BdsLibGetVariableAndSize (\r
-                      L"HDDP",\r
-                      &mHdBootVariablePrivateGuid,\r
+                      HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
+                      &gHdBootDevicePathVariablGuid,\r
                       &CachedDevicePathSize\r
                       );\r
-                      \r
+\r
   if (CachedDevicePath != NULL) {\r
     TempNewDevicePath = CachedDevicePath;\r
     DeviceExist = FALSE;\r
@@ -433,7 +955,7 @@ BdsExpandPartitionPartialDevicePathToFull (
       FullDevicePath = AppendDevicePath (Instance, DevicePath);\r
 \r
       //\r
-      // Adjust the 'HDDP' instances sequence if the matched one is not first one.\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
@@ -442,7 +964,7 @@ BdsExpandPartitionPartialDevicePathToFull (
         TempNewDevicePath = CachedDevicePath;\r
         CachedDevicePath  = BdsLibDelPartMatchInstance (CachedDevicePath, Instance );\r
         FreePool (TempNewDevicePath);\r
-        \r
+\r
         //\r
         // Second, append the remaining path after the matched instance\r
         //\r
@@ -453,14 +975,14 @@ BdsExpandPartitionPartialDevicePathToFull (
         // Save the matching Device Path so we don't need to do a connect all next time\r
         //\r
         Status = gRT->SetVariable (\r
-                        L"HDDP",\r
-                        &mHdBootVariablePrivateGuid,\r
+                        HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
+                        &gHdBootDevicePathVariablGuid,\r
                         EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
                         GetDevicePathSize (CachedDevicePath),\r
                         CachedDevicePath\r
                         );\r
       }\r
-      \r
+\r
       FreePool (Instance);\r
       FreePool (CachedDevicePath);\r
       return FullDevicePath;\r
@@ -468,7 +990,7 @@ BdsExpandPartitionPartialDevicePathToFull (
   }\r
 \r
   //\r
-  // If we get here we fail to find or 'HDDP' not exist, and now we need\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
@@ -498,11 +1020,11 @@ BdsExpandPartitionPartialDevicePathToFull (
       FullDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath);\r
 \r
       //\r
-      // Save the matched partition device path in 'HDDP' variable\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 'HDDP' variable\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
@@ -511,7 +1033,9 @@ BdsExpandPartitionPartialDevicePathToFull (
 \r
           TempNewDevicePath = CachedDevicePath;\r
           CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
-          FreePool(TempNewDevicePath);\r
+          if (TempNewDevicePath != NULL) {\r
+            FreePool(TempNewDevicePath);\r
+          }\r
         } else {\r
           TempNewDevicePath = CachedDevicePath;\r
           CachedDevicePath = AppendDevicePathInstance (BlockIoDevicePath, CachedDevicePath);\r
@@ -519,7 +1043,8 @@ BdsExpandPartitionPartialDevicePathToFull (
         }\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
+        // 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
@@ -549,8 +1074,8 @@ BdsExpandPartitionPartialDevicePathToFull (
       // Save the matching Device Path so we don't need to do a connect all next time\r
       //\r
       Status = gRT->SetVariable (\r
-                      L"HDDP",\r
-                      &mHdBootVariablePrivateGuid,\r
+                      HD_BOOT_DEVICE_PATH_VARIABLE_NAME,\r
+                      &gHdBootDevicePathVariablGuid,\r
                       EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
                       GetDevicePathSize (CachedDevicePath),\r
                       CachedDevicePath\r
@@ -559,8 +1084,10 @@ BdsExpandPartitionPartialDevicePathToFull (
       break;\r
     }\r
   }\r
-  \r
-  FreePool (CachedDevicePath);\r
+\r
+  if (CachedDevicePath != NULL) {\r
+    FreePool (CachedDevicePath);\r
+  }\r
   if (BlockIoBuffer != NULL) {\r
     FreePool (BlockIoBuffer);\r
   }\r
@@ -594,7 +1121,7 @@ MatchPartitionDevicePathNode (
   if ((BlockIoDevicePath == NULL) || (HardDriveDevicePath == NULL)) {\r
     return FALSE;\r
   }\r
-  \r
+\r
   //\r
   // Make PreviousDevicePath == the device path node before the end node\r
   //\r
@@ -623,7 +1150,7 @@ MatchPartitionDevicePathNode (
   //\r
   TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePathNode;\r
   Match = FALSE;\r
-  \r
+\r
   //\r
   // Check for the match\r
   //\r
@@ -711,12 +1238,19 @@ BdsLibDeleteOptionFromHandle (
                       &gEfiGlobalVariableGuid,\r
                       &BootOptionSize\r
                       );\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
@@ -779,10 +1313,14 @@ BdsDeleteAllInvalidEfiBootOption (
   EFI_DEVICE_PATH_PROTOCOL  *OptionDevicePath;\r
   UINT8                     *TempPtr;\r
   CHAR16                    *Description;\r
+  BOOLEAN                   Corrupted;\r
 \r
-  Status        = EFI_SUCCESS;\r
-  BootOrder     = NULL;\r
-  BootOrderSize = 0;\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
@@ -809,23 +1347,27 @@ BdsDeleteAllInvalidEfiBootOption (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \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
+    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
+      // 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 (!BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) {\r
+    if (Corrupted || !BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) {\r
       //\r
       // Delete this invalid boot option "Boot####"\r
       //\r
@@ -840,6 +1382,7 @@ BdsDeleteAllInvalidEfiBootOption (
       // Mark this boot option in boot order as deleted\r
       //\r
       BootOrder[Index] = 0xffff;\r
+      Corrupted        = FALSE;\r
     }\r
 \r
     FreePool (BootOptionVar);\r
@@ -872,46 +1415,47 @@ BdsDeleteAllInvalidEfiBootOption (
 \r
 /**\r
   For EFI boot option, BDS separate them as six types:\r
-  1. Network - The boot option points to the SimpleNetworkProtocol device. \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
+  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
+                              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
+  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
+                              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
+  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
+                              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
+  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
+               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
+  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
+\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
@@ -921,6 +1465,7 @@ BdsLibEnumerateAllBootOption (
 {\r
   EFI_STATUS                    Status;\r
   UINT16                        FloppyNumber;\r
+  UINT16                        HarddriveNumber;\r
   UINT16                        CdromNumber;\r
   UINT16                        UsbNumber;\r
   UINT16                        MiscNumber;\r
@@ -929,9 +1474,11 @@ BdsLibEnumerateAllBootOption (
   UINTN                         NumberBlockIoHandles;\r
   EFI_HANDLE                    *BlockIoHandles;\r
   EFI_BLOCK_IO_PROTOCOL         *BlkIo;\r
+  BOOLEAN                       Removable[2];\r
+  UINTN                         RemovableIndex;\r
   UINTN                         Index;\r
-  UINTN                         NumberSimpleNetworkHandles;\r
-  EFI_HANDLE                    *SimpleNetworkHandles;\r
+  UINTN                         NumOfLoadFileHandles;\r
+  EFI_HANDLE                    *LoadFileHandles;\r
   UINTN                         FvHandleCount;\r
   EFI_HANDLE                    *FvHandleBuffer;\r
   EFI_FV_FILETYPE               Type;\r
@@ -946,25 +1493,51 @@ BdsLibEnumerateAllBootOption (
   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
-  CdromNumber   = 0;\r
-  UsbNumber     = 0;\r
-  MiscNumber    = 0;\r
-  ScsiNumber    = 0;\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
   //\r
   // If the boot device enumerate happened, just get the boot\r
   // device from the boot order variable\r
   //\r
   if (mEnumBootDevice) {\r
-    BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
-    return EFI_SUCCESS;\r
+    GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, &LastLang, NULL);\r
+    GetEfiGlobalVariable2 (L"PlatformLang", &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
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      if (LastLang != NULL) {\r
+        FreePool (LastLang);\r
+      }\r
+      FreePool (PlatLang);\r
+    }\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
@@ -976,10 +1549,15 @@ BdsLibEnumerateAllBootOption (
   // Delete invalid boot option\r
   //\r
   BdsDeleteAllInvalidEfiBootOption ();\r
-  \r
+\r
   //\r
-  // Parse removable media\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
@@ -987,61 +1565,91 @@ BdsLibEnumerateAllBootOption (
         &NumberBlockIoHandles,\r
         &BlockIoHandles\r
         );\r
-        \r
-  for (Index = 0; Index < NumberBlockIoHandles; Index++) {\r
-    Status = gBS->HandleProtocol (\r
-                    BlockIoHandles[Index],\r
-                    &gEfiBlockIoProtocolGuid,\r
-                    (VOID **) &BlkIo\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      if (!BlkIo->Media->RemovableMedia) {\r
-        //\r
-        // skip the non-removable block devices\r
-        //\r
+\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 fixed block io then the removable block io\r
+      //\r
+      if (EFI_ERROR (Status) || (BlkIo->Media->RemovableMedia == Removable[RemovableIndex])) {\r
         continue;\r
       }\r
-    }\r
-    DevicePath  = DevicePathFromHandle (BlockIoHandles[Index]);\r
-    DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
-\r
-    switch (DevicePathType) {\r
-    case BDS_EFI_ACPI_FLOPPY_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_FLOPPY_NUM, FloppyNumber); \r
-      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-      FloppyNumber++;\r
-      break;\r
-    \r
-    //\r
-    // Assume a removable SATA device should be the DVD/CD device\r
-    //\r
-    case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
-    case BDS_EFI_MESSAGE_SATA_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_DVD_NUM, CdromNumber);\r
-      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-      CdromNumber++;\r
-      break;\r
+      DevicePath  = DevicePathFromHandle (BlockIoHandles[Index]);\r
+      DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);\r
 \r
-    case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_USB_NUM, UsbNumber);\r
-      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
-      UsbNumber++;\r
-      break;\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
-    case BDS_EFI_MESSAGE_SCSI_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_SCSI_NUM, ScsiNumber);\r
-      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);      \r
-      ScsiNumber++;\r
-      break;\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_MISC_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_MISC_NUM, MiscNumber);\r
-      BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);      \r
-      MiscNumber++;\r
-      break;\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
-    default:\r
-      break;\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
+        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
+      default:\r
+        break;\r
+      }\r
     }\r
   }\r
 \r
@@ -1077,7 +1685,7 @@ BdsLibEnumerateAllBootOption (
     // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI\r
     //  machinename is ia32, ia64, x64, ...\r
     //\r
-    Hdr.Union = &HdrData;\r
+    Hdr.Union  = &HdrData;\r
     NeedDelete = TRUE;\r
     Status     = BdsLibGetImageHeader (\r
                    FileSystemHandles[Index],\r
@@ -1097,7 +1705,11 @@ BdsLibEnumerateAllBootOption (
       //\r
       BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
     } else {\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_NON_BLOCK_NUM, NonBlockNumber);\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
@@ -1110,21 +1722,29 @@ BdsLibEnumerateAllBootOption (
   //\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
-        &gEfiSimpleNetworkProtocolGuid,\r
+        &gEfiLoadFileProtocolGuid,\r
         NULL,\r
-        &NumberSimpleNetworkHandles,\r
-        &SimpleNetworkHandles\r
+        &NumOfLoadFileHandles,\r
+        &LoadFileHandles\r
         );\r
 \r
-  for (Index = 0; Index < NumberSimpleNetworkHandles; Index++) {\r
-    UnicodeSPrint (Buffer, sizeof (Buffer), DESCRIPTION_NETWORK_NUM, Index);\r
-    BdsLibBuildOptionFromHandle (SimpleNetworkHandles[Index], BdsBootOptionList, Buffer);\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 (NumberSimpleNetworkHandles != 0) {\r
-    FreePool (SimpleNetworkHandles);\r
+  if (NumOfLoadFileHandles != 0) {\r
+    FreePool (LoadFileHandles);\r
   }\r
 \r
   //\r
@@ -1146,7 +1766,7 @@ BdsLibEnumerateAllBootOption (
 \r
     Status = Fv->ReadFile (\r
                   Fv,\r
-                  &gEfiShellFileGuid,\r
+                  PcdGetPtr(PcdShellFile),\r
                   NULL,\r
                   &Size,\r
                   &Type,\r
@@ -1172,10 +1792,10 @@ BdsLibEnumerateAllBootOption (
   // Make sure every boot only have one time\r
   // boot device enumerate\r
   //\r
-  BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+  Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
   mEnumBootDevice = TRUE;\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1231,7 +1851,7 @@ BdsLibBuildOptionFromShell (
   //\r
   // Build the shell device path\r
   //\r
-  EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid);\r
+  EfiInitializeFwVolDevicepathNode (&ShellNode, PcdGetPtr(PcdShellFile));\r
 \r
   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode);\r
 \r
@@ -1302,9 +1922,9 @@ BdsLibBootNext (
   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
+  @param  DevicePath  Device Path to a  bootable device\r
 \r
-  @retval NULL                   The media on the DevicePath is not bootable\r
+  @return  The bootable media handle. If the media on the DevicePath is not bootable, NULL will return.\r
 \r
 **/\r
 EFI_HANDLE\r
@@ -1314,6 +1934,7 @@ BdsLibGetBootableHandle (
   )\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
@@ -1332,7 +1953,13 @@ BdsLibGetBootableHandle (
   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
 \r
   UpdatedDevicePath = DevicePath;\r
-  \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
@@ -1351,10 +1978,17 @@ BdsLibGetBootableHandle (
       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
@@ -1385,7 +2019,7 @@ BdsLibGetBootableHandle (
   //\r
   DupDevicePath = DuplicateDevicePath (DevicePath);\r
   ASSERT (DupDevicePath != NULL);\r
-  \r
+\r
   UpdatedDevicePath = DupDevicePath;\r
   Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle);\r
   //\r
@@ -1451,6 +2085,8 @@ BdsLibGetBootableHandle (
     FreePool(SimpleFileSystemHandles);\r
   }\r
 \r
+  gBS->RestoreTPL (OldTpl);\r
+\r
   return ReturnHandle;\r
 }\r
 \r
@@ -1474,11 +2110,15 @@ BdsLibNetworkBootWithMediaPresent (
   EFI_HANDLE                      Handle;\r
   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
   BOOLEAN                         MediaPresent;\r
+  UINT32                          InterruptStatus;\r
 \r
   MediaPresent = FALSE;\r
 \r
   UpdatedDevicePath = DevicePath;\r
-  Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\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
@@ -1488,15 +2128,36 @@ BdsLibNetworkBootWithMediaPresent (
       //\r
       // This one should work after we did the connect\r
       //\r
-      Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\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
@@ -1530,23 +2191,22 @@ BdsLibNetworkBootWithMediaPresent (
 \r
   @param  DevicePath                      The bootable device Path to check\r
 \r
-  @retval BDS_EFI_MEDIA_HD_BOOT           If the device path contains any media device path node, it is media boot type\r
-                                          For the floppy node, handle it as media node\r
-  @retval BDS_EFI_MEDIA_CDROM_BOOT        If the device path contains any media device path node, it is media boot type\r
-                                          For the floppy node, handle it as media node\r
-  @retval BDS_EFI_ACPI_FLOPPY_BOOT        If the device path contains any media device path node, it is media boot type\r
-                                          For the floppy node, handle it as media node\r
-  @retval BDS_EFI_MESSAGE_ATAPI_BOOT      If the device path not contains any media device path node,  and\r
-                                          its last device path node point to a message device path node, it is\r
-  \r
-  @retval BDS_EFI_MESSAGE_SCSI_BOOT       If the device path not contains any media device path node,  and\r
-                                          its last device path node point to a message device path node, it is\r
-  @retval BDS_EFI_MESSAGE_USB_DEVICE_BOOT If the device path not contains any media device path node,  and\r
-                                          its last device path node point to a message device path node, it is\r
+  @retval BDS_EFI_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, it is\r
-  @retval BDS_LEGACY_BBS_BOOT             Legacy boot type\r
-  @retval BDS_EFI_UNSUPPORT               An EFI Removable BlockIO device path not point to a media and message device,   \r
+                                          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
@@ -1558,7 +2218,7 @@ BdsGetBootTypeFromDevicePath (
   ACPI_HID_DEVICE_PATH          *Acpi;\r
   EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;\r
   EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;\r
-\r
+  UINT32                        BootType;\r
 \r
   if (NULL == DevicePath) {\r
     return BDS_EFI_UNSUPPORT;\r
@@ -1591,7 +2251,7 @@ BdsGetBootTypeFromDevicePath (
         if (DevicePathSubType(LastDeviceNode) == MSG_DEVICE_LOGICAL_UNIT_DP) {\r
           //\r
           // if the next node type is Device Logical Unit, which specify the Logical Unit Number (LUN),\r
-          // skit it\r
+          // skip it\r
           //\r
           LastDeviceNode = NextDevicePathNode (LastDeviceNode);\r
         }\r
@@ -1599,19 +2259,39 @@ BdsGetBootTypeFromDevicePath (
         // 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
+          break;\r
         }\r
 \r
-        if (DevicePathSubType(TempDevicePath) == MSG_ATAPI_DP) {\r
-          return BDS_EFI_MESSAGE_ATAPI_BOOT;\r
-        } else if (DevicePathSubType(TempDevicePath) == MSG_USB_DP) {\r
-          return BDS_EFI_MESSAGE_USB_DEVICE_BOOT;\r
-        } else if (DevicePathSubType(TempDevicePath) == MSG_SCSI_DP) {\r
-          return BDS_EFI_MESSAGE_SCSI_BOOT;\r
-        } else if (DevicePathSubType(TempDevicePath) == MSG_SATA_DP) {\r
-          return BDS_EFI_MESSAGE_SATA_BOOT;\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 BDS_EFI_MESSAGE_MISC_BOOT;\r
+        return BootType;\r
+\r
       default:\r
         break;\r
     }\r
@@ -1621,41 +2301,6 @@ BdsGetBootTypeFromDevicePath (
   return BDS_EFI_UNSUPPORT;\r
 }\r
 \r
-\r
-/** \r
-  Check whether the descriptionis is conflict with the description reserved for\r
-  auto-created boot options.\r
-\r
-  @param  Description  The Description in a boot option\r
-  \r
-  @retval TRUE    The description is conflict with the description reserved for\r
-                  auto-created boot options.\r
-  @retval FALSE   The description is not conflict with the description reserved.\r
-  \r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-CheckDescritptionConflict (\r
-  IN CHAR16                       *Description\r
-  )\r
-{\r
-  if (Description == NULL) {\r
-    return FALSE;  \r
-  }\r
-  if ((CompareMem (Description, DESCRIPTION_FLOPPY, StrLen (DESCRIPTION_FLOPPY) * sizeof (CHAR16)) == 0)  ||\r
-      (CompareMem (Description, DESCRIPTION_DVD, StrLen (DESCRIPTION_DVD) * sizeof (CHAR16)) == 0)        ||\r
-      (CompareMem (Description, DESCRIPTION_USB, StrLen (DESCRIPTION_USB) * sizeof (CHAR16)) == 0)        ||\r
-      (CompareMem (Description, DESCRIPTION_SCSI, StrLen (DESCRIPTION_SCSI) * sizeof (CHAR16)) == 0)      ||\r
-      (CompareMem (Description, DESCRIPTION_MISC, StrLen (DESCRIPTION_MISC) * sizeof (CHAR16)) == 0)      ||\r
-      (CompareMem (Description, DESCRIPTION_NETWORK, StrLen (DESCRIPTION_NETWORK) * sizeof (CHAR16)) == 0)||\r
-      (CompareMem (Description, DESCRIPTION_NON_BLOCK, StrLen (DESCRIPTION_NON_BLOCK) * sizeof (CHAR16)) == 0)) { \r
-     return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\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
@@ -1708,14 +2353,14 @@ BdsLibIsValidEFIBootOptDevicePathExt (
 \r
   TempDevicePath = DevPath;\r
   LastDeviceNode = DevPath;\r
-  \r
+\r
   //\r
-  // Check if it's a valid boot option for network boot device\r
-  // Only check if there is SimpleNetworkProtocol installed. If yes, that means\r
-  // there is the network card there.\r
+  // 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
-                  &gEfiSimpleNetworkProtocolGuid,\r
+                  &gEfiLoadFileProtocolGuid,\r
                   &TempDevicePath,\r
                   &Handle\r
                   );\r
@@ -1726,13 +2371,20 @@ BdsLibIsValidEFIBootOptDevicePathExt (
     TempDevicePath = DevPath;\r
     BdsLibConnectDevicePath (TempDevicePath);\r
     Status = gBS->LocateDevicePath (\r
-                    &gEfiSimpleNetworkProtocolGuid,\r
+                    &gEfiLoadFileProtocolGuid,\r
                     &TempDevicePath,\r
                     &Handle\r
                     );\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
@@ -1742,7 +2394,7 @@ BdsLibIsValidEFIBootOptDevicePathExt (
       }\r
     } else {\r
       return TRUE;\r
-    }\r
+    }    \r
   }\r
 \r
   //\r
@@ -1750,8 +2402,19 @@ BdsLibIsValidEFIBootOptDevicePathExt (
   // and assume it is ready to boot now\r
   //\r
   while (!IsDevicePathEnd (TempDevicePath)) {\r
-     LastDeviceNode = TempDevicePath;\r
-     TempDevicePath = NextDevicePathNode (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
@@ -1759,28 +2422,31 @@ BdsLibIsValidEFIBootOptDevicePathExt (
   }\r
 \r
   //\r
-  // Check if it's a valid boot option for internal Shell\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 shell, make sure it is valid\r
+    // If the boot option point to internal FV application, make sure it is valid\r
     //\r
-    TempDevicePath = DevPath; \r
-    Status = BdsLibUpdateFvFileDevicePath (&TempDevicePath, &gEfiShellFileGuid);\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
+        FreePool (TempDevicePath);\r
       }\r
       return FALSE;\r
     }\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
+  //    if it is a fixed blockIo device, check its description confliction.\r
   //\r
   TempDevicePath = DevPath;\r
   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
@@ -1797,24 +2463,10 @@ BdsLibIsValidEFIBootOptDevicePathExt (
       Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
     }\r
   }\r
-  \r
+\r
   if (!EFI_ERROR (Status)) {\r
     Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
     if (!EFI_ERROR (Status)) {\r
-      if (!BlockIo->Media->RemovableMedia) {\r
-        //\r
-        // For the Fixed block devices, check its description whether conflict\r
-        // with other auto-created boot options. BDS permit a boot option point to \r
-        // Fixed block device, but not permit it use the description reserved for\r
-        // auto-created boot options.\r
-        // The check is to cover the bug, that replace a removable BlockIo device\r
-        // with a fixed BlockIo device at the same port, but the removable device's\r
-        // boot option can not be automatically deleted.\r
-        //\r
-        if (CheckDescritptionConflict (Description)) {\r
-           return FALSE; \r
-        }\r
-      }      \r
       if (CheckMedia) {\r
         //\r
         // Test if it is ready to boot now\r
@@ -1900,7 +2552,7 @@ BdsLibUpdateFvFileDevicePath (
   if (FileGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   //\r
   // Check whether the device path point to the default the input Fv file\r
   //\r
@@ -1968,7 +2620,7 @@ BdsLibUpdateFvFileDevicePath (
   FindFvFile = FALSE;\r
   FoundFvHandle = NULL;\r
   Status = gBS->HandleProtocol (\r
-             mBdsImageHandle,\r
+             gImageHandle,\r
              &gEfiLoadedImageProtocolGuid,\r
              (VOID **) &LoadedImage\r
              );\r
@@ -2034,7 +2686,7 @@ BdsLibUpdateFvFileDevicePath (
     }\r
 \r
     if (FvHandleBuffer != NULL) {\r
-      FreePool (FvHandleBuffer);  \r
+      FreePool (FvHandleBuffer);\r
     }\r
   }\r
 \r