]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg: Add new API HttpUrlGetPath() to HttpLib.h
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmBoot.c
index efac6d5bea65fdbf2a82556ef1fc71ea39a959ba..7297a1ddda2f7e7159b9a3ce29ddffaafdd05caf 100644 (file)
@@ -2,6 +2,7 @@
   Library functions which relates with booting.\r
 \r
 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 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
@@ -25,6 +26,8 @@ CHAR16       mBmUefiPrefix[] = L"UEFI ";
 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
@@ -49,6 +52,28 @@ EfiBootManagerRegisterLegacyBootSupport (
   mBmLegacyBoot              = LegacyBoot;\r
 }\r
 \r
+/**\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
+BOOLEAN\r
+BmIsAutoCreateBootOption (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption\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
+\r
 /**\r
   For a bootable Device path, return its boot type.\r
 \r
@@ -67,6 +92,8 @@ EfiBootManagerRegisterLegacyBootSupport (
   @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
 \r
 **/\r
@@ -111,7 +138,7 @@ BmDevicePathType (
         // If the device path not only point to driver device, it is not a messaging device path,\r
         //\r
         if (!IsDevicePathEndType (NextNode)) {\r
-          break;\r
+          continue;\r
         }\r
 \r
         switch (DevicePathSubType (Node)) {\r
@@ -137,6 +164,10 @@ BmDevicePathType (
         case MSG_IPv6_DP:\r
           return BmMessageNetworkBoot;\r
           break;\r
+\r
+        case MSG_URI_DP:\r
+          return BmMessageHttpBoot;\r
+          break;\r
         }\r
     }\r
   }\r
@@ -197,7 +228,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
@@ -550,6 +581,7 @@ BmGetUsbDescription (
   CHAR16                       *SerialNumber;\r
   CHAR16                       *Description;\r
   EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
+  UINTN                        DescMaxSize;\r
 \r
   Status = gBS->HandleProtocol (\r
                   Handle,\r
@@ -604,15 +636,16 @@ BmGetUsbDescription (
     return NULL;\r
   }\r
 \r
-  Description = AllocateZeroPool (StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber));\r
+  DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);\r
+  Description = AllocateZeroPool (DescMaxSize);\r
   ASSERT (Description != NULL);\r
-  StrCat (Description, Manufacturer);\r
-  StrCat (Description, L" ");\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
 \r
-  StrCat (Description, Product);  \r
-  StrCat (Description, L" ");\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product);  \r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
 \r
-  StrCat (Description, SerialNumber);\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber);\r
 \r
   if (Manufacturer != &NullChar) {\r
     FreePool (Manufacturer);\r
@@ -641,9 +674,10 @@ BmGetMiscDescription (
   IN EFI_HANDLE                  Handle\r
   )\r
 {\r
-  EFI_STATUS                     Status;\r
-  CHAR16                         *Description;\r
-  EFI_BLOCK_IO_PROTOCOL          *BlockIo;\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
@@ -677,20 +711,137 @@ BmGetMiscDescription (
     }\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
-    Description = L"Misc Device";\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
-BM_GET_BOOT_DESCRIPTION mBmGetBootDescription[] = {\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
@@ -828,7 +979,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
@@ -860,7 +1010,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
@@ -945,6 +1094,76 @@ BmExpandUsbDevicePath (
   return FileBuffer;\r
 }\r
 \r
+/**\r
+  Expand File-path 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
+BmExpandFileDevicePath (\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
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
+  UINTN                           MediaType;\r
+  EFI_DEVICE_PATH_PROTOCOL        *FullDevicePath;\r
+  VOID                            *FileBuffer;\r
+  UINT32                          AuthenticationStatus;\r
+  \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
+  //\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
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+\r
+  *FullPath = NULL;\r
+  return NULL;\r
+}\r
+\r
 /**\r
   Save the partition DevicePath to the CachedDevicePath as the first instance.\r
 \r
@@ -1346,6 +1565,12 @@ 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 {\r
     for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {\r
       if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&\r
@@ -1383,9 +1608,18 @@ BmGetLoadOptionBuffer (
   // 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
   //\r
+  Node   = FilePath;\r
+  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
   FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);\r
   if (FileBuffer != NULL) {\r
-    *FullPath = DuplicateDevicePath (FilePath);\r
+    if (EFI_ERROR (Status)) {\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
   }\r
 \r
   return FileBuffer;\r
@@ -1553,11 +1787,9 @@ EfiBootManagerBoot (
   // 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
+  BmSetMemoryTypeInformationVariable (\r
+    (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
+    );\r
 \r
   DEBUG_CODE_BEGIN();\r
     if (BootOption->Description == NULL) {\r
@@ -1604,8 +1836,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
@@ -1731,6 +1965,66 @@ BmMatchPartitionDevicePathNode (
     );\r
 }\r
 \r
+/**\r
+  Enumerate all boot option descriptions and append " 2"/" 3"/... to make\r
+  unique description.\r
+\r
+  @param BootOptions            Array of boot options.\r
+  @param BootOptionCount        Count of boot options.\r
+**/\r
+VOID\r
+BmMakeBootOptionDescriptionUnique (\r
+  EFI_BOOT_MANAGER_LOAD_OPTION         *BootOptions,\r
+  UINTN                                BootOptionCount\r
+  )\r
+{\r
+  UINTN                                Base;\r
+  UINTN                                Index;\r
+  UINTN                                DescriptionSize;\r
+  UINTN                                MaxSuffixSize;\r
+  BOOLEAN                              *Visited;\r
+  UINTN                                MatchCount;\r
+\r
+  if (BootOptionCount == 0) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Calculate the maximum buffer size for the number suffix.\r
+  // The initial sizeof (CHAR16) is for the blank space before the number.\r
+  //\r
+  MaxSuffixSize = sizeof (CHAR16);\r
+  for (Index = BootOptionCount; Index != 0; Index = Index / 10) {\r
+    MaxSuffixSize += sizeof (CHAR16);\r
+  }\r
+\r
+  Visited = AllocateZeroPool (sizeof (BOOLEAN) * BootOptionCount);\r
+  ASSERT (Visited != NULL);\r
+\r
+  for (Base = 0; Base < BootOptionCount; Base++) {\r
+    if (!Visited[Base]) {\r
+      MatchCount      = 1;\r
+      Visited[Base]   = TRUE;\r
+      DescriptionSize = StrSize (BootOptions[Base].Description);\r
+      for (Index = Base + 1; Index < BootOptionCount; Index++) {\r
+        if (!Visited[Index] && StrCmp (BootOptions[Base].Description, BootOptions[Index].Description) == 0) {\r
+          Visited[Index] = TRUE;\r
+          MatchCount++;\r
+          FreePool (BootOptions[Index].Description);\r
+          BootOptions[Index].Description = AllocatePool (DescriptionSize + MaxSuffixSize);\r
+          UnicodeSPrint (\r
+            BootOptions[Index].Description, DescriptionSize + MaxSuffixSize,\r
+            L"%s %d",\r
+            BootOptions[Base].Description, MatchCount\r
+            );\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (Visited);\r
+}\r
+\r
 /**\r
   Emuerate all possible bootable medias in the following order:\r
   1. Removable BlockIo            - The boot option only points to the removable media\r
@@ -1755,16 +2049,12 @@ BmEnumerateBootOptions (
 {\r
   EFI_STATUS                            Status;\r
   EFI_BOOT_MANAGER_LOAD_OPTION          *BootOptions;\r
-  UINT16                                NonBlockNumber;\r
   UINTN                                 HandleCount;\r
   EFI_HANDLE                            *Handles;\r
   EFI_BLOCK_IO_PROTOCOL                 *BlkIo;\r
   UINTN                                 Removable;\r
   UINTN                                 Index;\r
-  UINTN                                 FunctionIndex;\r
-  CHAR16                                *Temp;\r
-  CHAR16                                *DescriptionPtr;\r
-  CHAR16                                Description[30];\r
+  CHAR16                                *Description;\r
 \r
   ASSERT (BootOptionCount != NULL);\r
 \r
@@ -1807,28 +2097,7 @@ BmEnumerateBootOptions (
         continue;\r
       }\r
 \r
-      DescriptionPtr = NULL;\r
-      for (FunctionIndex = 0; FunctionIndex < sizeof (mBmGetBootDescription) / sizeof (mBmGetBootDescription[0]); FunctionIndex++) {\r
-        DescriptionPtr = mBmGetBootDescription[FunctionIndex] (Handles[Index]);\r
-        if (DescriptionPtr != NULL) {\r
-          break;\r
-        }\r
-      }\r
-\r
-      if (DescriptionPtr == NULL) {\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
-      //\r
-      Temp = AllocatePool (StrSize (DescriptionPtr) + sizeof (mBmUefiPrefix)); \r
-      ASSERT (Temp != NULL);\r
-      StrCpy (Temp, mBmUefiPrefix);\r
-      StrCat (Temp, DescriptionPtr);\r
-      FreePool (DescriptionPtr);\r
-      DescriptionPtr = Temp;\r
-\r
+      Description = BmGetBootDescription (Handles[Index]);\r
       BootOptions = ReallocatePool (\r
                       sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
                       sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
@@ -1841,14 +2110,14 @@ BmEnumerateBootOptions (
                  LoadOptionNumberUnassigned,\r
                  LoadOptionTypeBoot,\r
                  LOAD_OPTION_ACTIVE,\r
-                 DescriptionPtr,\r
+                 Description,\r
                  DevicePathFromHandle (Handles[Index]),\r
                  NULL,\r
                  0\r
                  );\r
       ASSERT_EFI_ERROR (Status);\r
 \r
-      FreePool (DescriptionPtr);\r
+      FreePool (Description);\r
     }\r
   }\r
 \r
@@ -1859,7 +2128,6 @@ BmEnumerateBootOptions (
   //\r
   // Parse simple file system not based on block io\r
   //\r
-  NonBlockNumber = 0;\r
   gBS->LocateHandleBuffer (\r
          ByProtocol,\r
          &gEfiSimpleFileSystemProtocolGuid,\r
@@ -1879,8 +2147,7 @@ BmEnumerateBootOptions (
       //\r
       continue;\r
     }\r
-    UnicodeSPrint (Description, sizeof (Description), NonBlockNumber > 0 ? L"%s %d" : L"%s", L"UEFI Non-Block Boot Device", NonBlockNumber);\r
-    \r
+    Description = BmGetBootDescription (Handles[Index]);\r
     BootOptions = ReallocatePool (\r
                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
@@ -1899,6 +2166,7 @@ BmEnumerateBootOptions (
                0\r
                );\r
     ASSERT_EFI_ERROR (Status);\r
+    FreePool (Description);\r
   }\r
 \r
   if (HandleCount != 0) {\r
@@ -1917,8 +2185,7 @@ BmEnumerateBootOptions (
          );\r
   for (Index = 0; Index < HandleCount; Index++) {\r
 \r
-    UnicodeSPrint (Description, sizeof (Description), Index > 0 ? L"%s %d" : L"%s", L"UEFI Network", Index);\r
-\r
+    Description = BmGetBootDescription (Handles[Index]);\r
     BootOptions = ReallocatePool (\r
                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount),\r
                     sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1),\r
@@ -1937,12 +2204,14 @@ BmEnumerateBootOptions (
                0\r
                );\r
     ASSERT_EFI_ERROR (Status);\r
+    FreePool (Description);\r
   }\r
 \r
   if (HandleCount != 0) {\r
     FreePool (Handles);\r
   }\r
 \r
+  BmMakeBootOptionDescriptionUnique (BootOptions, *BootOptionCount);\r
   return BootOptions;\r
 }\r
 \r
@@ -1986,15 +2255,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) == (UINTN) -1) {\r
         Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
         //\r
         // Deleting variable with current variable implementation shouldn't fail.\r
@@ -2008,7 +2275,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) == (UINTN) -1) {\r
       EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
       //\r
       // Try best to add the boot options so continue upon failure.\r
@@ -2089,7 +2356,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