]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/UefiBootManagerLib: Separate boot description functions.
authorRuiyu Ni <ruiyu.ni@intel.com>
Fri, 4 Mar 2016 08:34:43 +0000 (16:34 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Mon, 7 Mar 2016 05:35:43 +0000 (13:35 +0800)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c [new file with mode: 0644]
MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf

index 4225e80f42a45032316a606fe8896a6b468e365b..f6c68458abb11f3de8fcd34917167962fdf750d6 100644 (file)
@@ -15,19 +15,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "InternalBm.h"\r
 \r
 \r
 #include "InternalBm.h"\r
 \r
-#define VENDOR_IDENTIFICATION_OFFSET     3\r
-#define VENDOR_IDENTIFICATION_LENGTH     8\r
-#define PRODUCT_IDENTIFICATION_OFFSET    11\r
-#define PRODUCT_IDENTIFICATION_LENGTH    16\r
-\r
-CONST UINT16 mBmUsbLangId    = 0x0409; // English\r
-CHAR16       mBmUefiPrefix[] = L"UEFI ";\r
-\r
 EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION  mBmRefreshLegacyBootOption = NULL;\r
 EFI_BOOT_MANAGER_LEGACY_BOOT                 mBmLegacyBoot              = NULL;\r
 \r
 EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION  mBmRefreshLegacyBootOption = NULL;\r
 EFI_BOOT_MANAGER_LEGACY_BOOT                 mBmLegacyBoot              = NULL;\r
 \r
-LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);\r
-\r
 ///\r
 /// This GUID is used for an EFI Variable that stores the front device pathes\r
 /// for a partial device path that starts with the HD node.\r
 ///\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
@@ -74,107 +64,6 @@ BmIsAutoCreateBootOption (
   }\r
 }\r
 \r
   }\r
 }\r
 \r
-/**\r
-  For a bootable Device path, return its boot type.\r
-\r
-  @param  DevicePath                   The bootable device Path to check\r
-\r
-  @retval AcpiFloppyBoot               If given device path contains ACPI_DEVICE_PATH type device path node\r
-                                       which HID is floppy device.\r
-  @retval MessageAtapiBoot             If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_ATAPI_DP.\r
-  @retval MessageSataBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_SATA_DP.\r
-  @retval MessageScsiBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_SCSI_DP.\r
-  @retval MessageUsbBoot               If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_USB_DP.\r
-  @retval MessageNetworkBoot           If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,\r
-                                       MSG_IPv4_DP or MSG_IPv6_DP.\r
-  @retval MessageHttpBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
-                                       and its last device path node's subtype is MSG_URI_DP.\r
-  @retval UnsupportedBoot              If tiven device path doesn't match the above condition, it's not supported.\r
-\r
-**/\r
-BM_BOOT_TYPE\r
-BmDevicePathType (\r
-  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
-  )\r
-{\r
-  EFI_DEVICE_PATH_PROTOCOL      *Node;\r
-  EFI_DEVICE_PATH_PROTOCOL      *NextNode;\r
-\r
-  ASSERT (DevicePath != NULL);\r
-\r
-  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {\r
-    switch (DevicePathType (Node)) {\r
-\r
-      case ACPI_DEVICE_PATH:\r
-        if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {\r
-          return BmAcpiFloppyBoot;\r
-        }\r
-        break;\r
-\r
-      case HARDWARE_DEVICE_PATH:\r
-        if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {\r
-          return BmHardwareDeviceBoot;\r
-        }\r
-        break;\r
-\r
-      case MESSAGING_DEVICE_PATH:\r
-        //\r
-        // Skip LUN device node\r
-        //\r
-        NextNode = Node;\r
-        do {\r
-          NextNode = NextDevicePathNode (NextNode);\r
-        } while (\r
-            (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&\r
-            (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)\r
-            );\r
-\r
-        //\r
-        // If the device path not only point to driver device, it is not a messaging device path,\r
-        //\r
-        if (!IsDevicePathEndType (NextNode)) {\r
-          continue;\r
-        }\r
-\r
-        switch (DevicePathSubType (Node)) {\r
-        case MSG_ATAPI_DP:\r
-          return BmMessageAtapiBoot;\r
-          break;\r
-\r
-        case MSG_SATA_DP:\r
-          return BmMessageSataBoot;\r
-          break;\r
-\r
-        case MSG_USB_DP:\r
-          return BmMessageUsbBoot;\r
-          break;\r
-\r
-        case MSG_SCSI_DP:\r
-          return BmMessageScsiBoot;\r
-          break;\r
-\r
-        case MSG_MAC_ADDR_DP:\r
-        case MSG_VLAN_DP:\r
-        case MSG_IPv4_DP:\r
-        case MSG_IPv6_DP:\r
-          return BmMessageNetworkBoot;\r
-          break;\r
-\r
-        case MSG_URI_DP:\r
-          return BmMessageHttpBoot;\r
-          break;\r
-        }\r
-    }\r
-  }\r
-\r
-  return BmMiscBoot;\r
-}\r
-\r
 /**\r
   Find the boot option in the NV storage and return the option number.\r
 \r
 /**\r
   Find the boot option in the NV storage and return the option number.\r
 \r
@@ -454,411 +343,6 @@ BmMatchUsbClass (
   return TRUE;\r
 }\r
 \r
   return TRUE;\r
 }\r
 \r
-/**\r
-  Eliminate the extra spaces in the Str to one space.\r
-\r
-  @param    Str     Input string info.\r
-**/\r
-VOID\r
-BmEliminateExtraSpaces (\r
-  IN CHAR16                    *Str\r
-  )\r
-{\r
-  UINTN                        Index;\r
-  UINTN                        ActualIndex;\r
-\r
-  for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {\r
-    if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {\r
-      Str[ActualIndex++] = Str[Index];\r
-    }\r
-  }\r
-  Str[ActualIndex] = L'\0';\r
-}\r
-\r
-/**\r
-  Try to get the controller's ATA/ATAPI description.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetDescriptionFromDiskInfo (\r
-  IN EFI_HANDLE                Handle\r
-  )\r
-{\r
-  UINTN                        Index;\r
-  EFI_STATUS                   Status;\r
-  EFI_DISK_INFO_PROTOCOL       *DiskInfo;\r
-  UINT32                       BufferSize;\r
-  EFI_ATAPI_IDENTIFY_DATA      IdentifyData;\r
-  EFI_SCSI_INQUIRY_DATA        InquiryData;\r
-  CHAR16                       *Description;\r
-  UINTN                        Length;\r
-  CONST UINTN                  ModelNameLength    = 40;\r
-  CONST UINTN                  SerialNumberLength = 20;\r
-  CHAR8                        *StrPtr;\r
-  UINT8                        Temp;\r
-\r
-  Description  = NULL;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiDiskInfoProtocolGuid,\r
-                  (VOID **) &DiskInfo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || \r
-      CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
-    BufferSize   = sizeof (EFI_ATAPI_IDENTIFY_DATA);\r
-    Status = DiskInfo->Identify (\r
-                         DiskInfo,\r
-                         &IdentifyData,\r
-                         &BufferSize\r
-                         );\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));\r
-      ASSERT (Description != NULL);\r
-      for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {\r
-        Description[Index]     = (CHAR16) IdentifyData.ModelName[Index + 1];\r
-        Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];\r
-      }\r
-\r
-      Length = Index;\r
-      Description[Length++] = L' ';\r
-\r
-      for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {\r
-        Description[Length + Index]     = (CHAR16) IdentifyData.SerialNo[Index + 1];\r
-        Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];\r
-      }\r
-      Length += Index;\r
-      Description[Length++] = L'\0';\r
-      ASSERT (Length == ModelNameLength + SerialNumberLength + 2);\r
-\r
-      BmEliminateExtraSpaces (Description);\r
-    }\r
-  } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
-    BufferSize   = sizeof (EFI_SCSI_INQUIRY_DATA);\r
-    Status = DiskInfo->Inquiry (\r
-                         DiskInfo,\r
-                         &InquiryData,\r
-                         &BufferSize\r
-                         );\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));\r
-      ASSERT (Description != NULL);\r
-\r
-      //\r
-      // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification\r
-      // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, \r
-      // Here combine the vendor identification and product identification to the description.\r
-      //\r
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);\r
-      Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];\r
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';\r
-      AsciiStrToUnicodeStr (StrPtr, Description);\r
-      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;\r
-\r
-      //\r
-      // Add one space at the middle of vendor information and product information.\r
-      //\r
-      Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';\r
-\r
-      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);\r
-      StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';\r
-      AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);\r
-\r
-      BmEliminateExtraSpaces (Description);\r
-    }\r
-  }\r
-\r
-  return Description;\r
-}\r
-\r
-/**\r
-  Try to get the controller's USB description.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetUsbDescription (\r
-  IN EFI_HANDLE                Handle\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  EFI_USB_IO_PROTOCOL          *UsbIo;\r
-  CHAR16                       NullChar;\r
-  CHAR16                       *Manufacturer;\r
-  CHAR16                       *Product;\r
-  CHAR16                       *SerialNumber;\r
-  CHAR16                       *Description;\r
-  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
-  UINTN                        DescMaxSize;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiUsbIoProtocolGuid,\r
-                  (VOID **) &UsbIo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  NullChar = L'\0';\r
-\r
-  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrManufacturer,\r
-                    &Manufacturer\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    Manufacturer = &NullChar;\r
-  }\r
-  \r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrProduct,\r
-                    &Product\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    Product = &NullChar;\r
-  }\r
-  \r
-  Status = UsbIo->UsbGetStringDescriptor (\r
-                    UsbIo,\r
-                    mBmUsbLangId,\r
-                    DevDesc.StrSerialNumber,\r
-                    &SerialNumber\r
-                    );\r
-  if (EFI_ERROR (Status)) {\r
-    SerialNumber = &NullChar;\r
-  }\r
-\r
-  if ((Manufacturer == &NullChar) &&\r
-      (Product == &NullChar) &&\r
-      (SerialNumber == &NullChar)\r
-      ) {\r
-    return NULL;\r
-  }\r
-\r
-  DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);\r
-  Description = AllocateZeroPool (DescMaxSize);\r
-  ASSERT (Description != NULL);\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product);  \r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
-\r
-  StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber);\r
-\r
-  if (Manufacturer != &NullChar) {\r
-    FreePool (Manufacturer);\r
-  }\r
-  if (Product != &NullChar) {\r
-    FreePool (Product);\r
-  }\r
-  if (SerialNumber != &NullChar) {\r
-    FreePool (SerialNumber);\r
-  }\r
-\r
-  BmEliminateExtraSpaces (Description);\r
-\r
-  return Description;\r
-}\r
-\r
-/**\r
-  Return the boot description for the controller based on the type.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetMiscDescription (\r
-  IN EFI_HANDLE                  Handle\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  CHAR16                          *Description;\r
-  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
-\r
-  switch (BmDevicePathType (DevicePathFromHandle (Handle))) {\r
-  case BmAcpiFloppyBoot:\r
-    Description = L"Floppy";\r
-    break;\r
-\r
-  case BmMessageAtapiBoot:\r
-  case BmMessageSataBoot:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
-    ASSERT_EFI_ERROR (Status);\r
-    //\r
-    // Assume a removable SATA device should be the DVD/CD device\r
-    //\r
-    Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";\r
-    break;\r
-\r
-  case BmMessageUsbBoot:\r
-    Description = L"USB Device";\r
-    break;\r
-\r
-  case BmMessageScsiBoot:\r
-    Description = L"SCSI Device";\r
-    break;\r
-\r
-  case BmHardwareDeviceBoot:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";\r
-    } else {\r
-      Description = L"Misc Device";\r
-    }\r
-    break;\r
-\r
-  case BmMessageNetworkBoot:\r
-    Description = L"Network";\r
-    break;\r
-\r
-  case BmMessageHttpBoot:\r
-    Description = L"Http";\r
-    break;\r
-\r
-  default:\r
-    Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs);\r
-    if (!EFI_ERROR (Status)) {\r
-      Description = L"Non-Block Boot Device";\r
-    } else {\r
-      Description = L"Misc Device";\r
-    }\r
-    break;\r
-  }\r
-\r
-  return AllocateCopyPool (StrSize (Description), Description);\r
-}\r
-\r
-/**\r
-  Register the platform provided boot description handler.\r
-\r
-  @param Handler  The platform provided boot description handler\r
-\r
-  @retval EFI_SUCCESS          The handler was registered successfully.\r
-  @retval EFI_ALREADY_STARTED  The handler was already registered.\r
-  @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiBootManagerRegisterBootDescriptionHandler (\r
-  IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER  Handler\r
-  )\r
-{\r
-  LIST_ENTRY                                    *Link;\r
-  BM_BOOT_DESCRIPTION_ENTRY                    *Entry;\r
-\r
-  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
-      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
-      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
-      ) {\r
-    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
-    if (Entry->Handler == Handler) {\r
-      return EFI_ALREADY_STARTED;\r
-    }\r
-  }\r
-\r
-  Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));\r
-  if (Entry == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;\r
-  Entry->Handler   = Handler;\r
-  InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {\r
-  BmGetUsbDescription,\r
-  BmGetDescriptionFromDiskInfo,\r
-  BmGetMiscDescription\r
-};\r
-\r
-/**\r
-  Return the boot description for the controller.\r
-\r
-  @param Handle                Controller handle.\r
-\r
-  @return  The description string.\r
-**/\r
-CHAR16 *\r
-BmGetBootDescription (\r
-  IN EFI_HANDLE                  Handle\r
-  )\r
-{\r
-  LIST_ENTRY                     *Link;\r
-  BM_BOOT_DESCRIPTION_ENTRY      *Entry;\r
-  CHAR16                         *Description;\r
-  CHAR16                         *DefaultDescription;\r
-  CHAR16                         *Temp;\r
-  UINTN                          Index;\r
-\r
-  //\r
-  // Firstly get the default boot description\r
-  //\r
-  DefaultDescription = NULL;\r
-  for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof (mBmBootDescriptionHandlers[0]); Index++) {\r
-    DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle);\r
-    if (DefaultDescription != NULL) {\r
-      //\r
-      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
-      // ONLY for core provided boot description handler.\r
-      //\r
-      Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); \r
-      ASSERT (Temp != NULL);\r
-      StrCpyS ( Temp, \r
-                (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
-                mBmUefiPrefix\r
-                );\r
-      StrCatS ( Temp, \r
-                (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix))/sizeof(CHAR16), \r
-                DefaultDescription\r
-                );\r
-      FreePool (DefaultDescription);\r
-      DefaultDescription = Temp;\r
-      break;\r
-    }\r
-  }\r
-  ASSERT (DefaultDescription != NULL);\r
-\r
-  //\r
-  // Secondly query platform for the better boot description\r
-  //\r
-  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
-      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
-      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
-      ) {\r
-    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
-    Description = Entry->Handler (Handle, DefaultDescription);\r
-    if (Description != NULL) {\r
-      FreePool (DefaultDescription);\r
-      return Description;\r
-    }\r
-  }\r
-\r
-  return DefaultDescription;\r
-}\r
-\r
 /**\r
   Check whether a USB device match the specified USB WWID device path. This\r
   function follows "Load Option Processing" behavior in UEFI specification.\r
 /**\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
@@ -2253,66 +1737,6 @@ BmMatchPartitionDevicePathNode (
     );\r
 }\r
 \r
     );\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
 /**\r
   Emuerate all possible bootable medias in the following order:\r
   1. Removable BlockIo            - The boot option only points to the removable media\r
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
new file mode 100644 (file)
index 0000000..5c77e86
--- /dev/null
@@ -0,0 +1,586 @@
+/** @file\r
+  Library functions which relate with boot option description.\r
+\r
+Copyright (c) 2011 - 2016, 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBm.h"\r
+\r
+#define VENDOR_IDENTIFICATION_OFFSET     3\r
+#define VENDOR_IDENTIFICATION_LENGTH     8\r
+#define PRODUCT_IDENTIFICATION_OFFSET    11\r
+#define PRODUCT_IDENTIFICATION_LENGTH    16\r
+\r
+CONST UINT16 mBmUsbLangId    = 0x0409; // English\r
+CHAR16       mBmUefiPrefix[] = L"UEFI ";\r
+\r
+LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);\r
+\r
+/**\r
+  For a bootable Device path, return its boot type.\r
+\r
+  @param  DevicePath                   The bootable device Path to check\r
+\r
+  @retval AcpiFloppyBoot               If given device path contains ACPI_DEVICE_PATH type device path node\r
+                                       which HID is floppy device.\r
+  @retval MessageAtapiBoot             If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_ATAPI_DP.\r
+  @retval MessageSataBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_SATA_DP.\r
+  @retval MessageScsiBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_SCSI_DP.\r
+  @retval MessageUsbBoot               If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_USB_DP.\r
+  @retval MessageNetworkBoot           If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_MAC_ADDR_DP, MSG_VLAN_DP,\r
+                                       MSG_IPv4_DP or MSG_IPv6_DP.\r
+  @retval MessageHttpBoot              If given device path contains MESSAGING_DEVICE_PATH type device path node\r
+                                       and its last device path node's subtype is MSG_URI_DP.\r
+  @retval UnsupportedBoot              If tiven device path doesn't match the above condition, it's not supported.\r
+\r
+**/\r
+BM_BOOT_TYPE\r
+BmDevicePathType (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+  )\r
+{\r
+  EFI_DEVICE_PATH_PROTOCOL      *Node;\r
+  EFI_DEVICE_PATH_PROTOCOL      *NextNode;\r
+\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {\r
+    switch (DevicePathType (Node)) {\r
+\r
+      case ACPI_DEVICE_PATH:\r
+        if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) {\r
+          return BmAcpiFloppyBoot;\r
+        }\r
+        break;\r
+\r
+      case HARDWARE_DEVICE_PATH:\r
+        if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {\r
+          return BmHardwareDeviceBoot;\r
+        }\r
+        break;\r
+\r
+      case MESSAGING_DEVICE_PATH:\r
+        //\r
+        // Skip LUN device node\r
+        //\r
+        NextNode = Node;\r
+        do {\r
+          NextNode = NextDevicePathNode (NextNode);\r
+        } while (\r
+            (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&\r
+            (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)\r
+            );\r
+\r
+        //\r
+        // If the device path not only point to driver device, it is not a messaging device path,\r
+        //\r
+        if (!IsDevicePathEndType (NextNode)) {\r
+          continue;\r
+        }\r
+\r
+        switch (DevicePathSubType (Node)) {\r
+        case MSG_ATAPI_DP:\r
+          return BmMessageAtapiBoot;\r
+          break;\r
+\r
+        case MSG_SATA_DP:\r
+          return BmMessageSataBoot;\r
+          break;\r
+\r
+        case MSG_USB_DP:\r
+          return BmMessageUsbBoot;\r
+          break;\r
+\r
+        case MSG_SCSI_DP:\r
+          return BmMessageScsiBoot;\r
+          break;\r
+\r
+        case MSG_MAC_ADDR_DP:\r
+        case MSG_VLAN_DP:\r
+        case MSG_IPv4_DP:\r
+        case MSG_IPv6_DP:\r
+          return BmMessageNetworkBoot;\r
+          break;\r
+\r
+        case MSG_URI_DP:\r
+          return BmMessageHttpBoot;\r
+          break;\r
+        }\r
+    }\r
+  }\r
+\r
+  return BmMiscBoot;\r
+}\r
+\r
+/**\r
+  Eliminate the extra spaces in the Str to one space.\r
+\r
+  @param    Str     Input string info.\r
+**/\r
+VOID\r
+BmEliminateExtraSpaces (\r
+  IN CHAR16                    *Str\r
+  )\r
+{\r
+  UINTN                        Index;\r
+  UINTN                        ActualIndex;\r
+\r
+  for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {\r
+    if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {\r
+      Str[ActualIndex++] = Str[Index];\r
+    }\r
+  }\r
+  Str[ActualIndex] = L'\0';\r
+}\r
+\r
+/**\r
+  Try to get the controller's ATA/ATAPI description.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetDescriptionFromDiskInfo (\r
+  IN EFI_HANDLE                Handle\r
+  )\r
+{\r
+  UINTN                        Index;\r
+  EFI_STATUS                   Status;\r
+  EFI_DISK_INFO_PROTOCOL       *DiskInfo;\r
+  UINT32                       BufferSize;\r
+  EFI_ATAPI_IDENTIFY_DATA      IdentifyData;\r
+  EFI_SCSI_INQUIRY_DATA        InquiryData;\r
+  CHAR16                       *Description;\r
+  UINTN                        Length;\r
+  CONST UINTN                  ModelNameLength    = 40;\r
+  CONST UINTN                  SerialNumberLength = 20;\r
+  CHAR8                        *StrPtr;\r
+  UINT8                        Temp;\r
+\r
+  Description  = NULL;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiDiskInfoProtocolGuid,\r
+                  (VOID **) &DiskInfo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) ||\r
+      CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {\r
+    BufferSize   = sizeof (EFI_ATAPI_IDENTIFY_DATA);\r
+    Status = DiskInfo->Identify (\r
+                         DiskInfo,\r
+                         &IdentifyData,\r
+                         &BufferSize\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));\r
+      ASSERT (Description != NULL);\r
+      for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {\r
+        Description[Index]     = (CHAR16) IdentifyData.ModelName[Index + 1];\r
+        Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index];\r
+      }\r
+\r
+      Length = Index;\r
+      Description[Length++] = L' ';\r
+\r
+      for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {\r
+        Description[Length + Index]     = (CHAR16) IdentifyData.SerialNo[Index + 1];\r
+        Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index];\r
+      }\r
+      Length += Index;\r
+      Description[Length++] = L'\0';\r
+      ASSERT (Length == ModelNameLength + SerialNumberLength + 2);\r
+\r
+      BmEliminateExtraSpaces (Description);\r
+    }\r
+  } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) {\r
+    BufferSize   = sizeof (EFI_SCSI_INQUIRY_DATA);\r
+    Status = DiskInfo->Inquiry (\r
+                         DiskInfo,\r
+                         &InquiryData,\r
+                         &BufferSize\r
+                         );\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));\r
+      ASSERT (Description != NULL);\r
+\r
+      //\r
+      // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification\r
+      // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification,\r
+      // Here combine the vendor identification and product identification to the description.\r
+      //\r
+      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);\r
+      Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];\r
+      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';\r
+      AsciiStrToUnicodeStr (StrPtr, Description);\r
+      StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;\r
+\r
+      //\r
+      // Add one space at the middle of vendor information and product information.\r
+      //\r
+      Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';\r
+\r
+      StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);\r
+      StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';\r
+      AsciiStrToUnicodeStr (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1);\r
+\r
+      BmEliminateExtraSpaces (Description);\r
+    }\r
+  }\r
+\r
+  return Description;\r
+}\r
+\r
+/**\r
+  Try to get the controller's USB description.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetUsbDescription (\r
+  IN EFI_HANDLE                Handle\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_USB_IO_PROTOCOL          *UsbIo;\r
+  CHAR16                       NullChar;\r
+  CHAR16                       *Manufacturer;\r
+  CHAR16                       *Product;\r
+  CHAR16                       *SerialNumber;\r
+  CHAR16                       *Description;\r
+  EFI_USB_DEVICE_DESCRIPTOR    DevDesc;\r
+  UINTN                        DescMaxSize;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiUsbIoProtocolGuid,\r
+                  (VOID **) &UsbIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  NullChar = L'\0';\r
+\r
+  Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrManufacturer,\r
+                    &Manufacturer\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Manufacturer = &NullChar;\r
+  }\r
+\r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrProduct,\r
+                    &Product\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Product = &NullChar;\r
+  }\r
+\r
+  Status = UsbIo->UsbGetStringDescriptor (\r
+                    UsbIo,\r
+                    mBmUsbLangId,\r
+                    DevDesc.StrSerialNumber,\r
+                    &SerialNumber\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    SerialNumber = &NullChar;\r
+  }\r
+\r
+  if ((Manufacturer == &NullChar) &&\r
+      (Product == &NullChar) &&\r
+      (SerialNumber == &NullChar)\r
+      ) {\r
+    return NULL;\r
+  }\r
+\r
+  DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);\r
+  Description = AllocateZeroPool (DescMaxSize);\r
+  ASSERT (Description != NULL);\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
+\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product);\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");\r
+\r
+  StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber);\r
+\r
+  if (Manufacturer != &NullChar) {\r
+    FreePool (Manufacturer);\r
+  }\r
+  if (Product != &NullChar) {\r
+    FreePool (Product);\r
+  }\r
+  if (SerialNumber != &NullChar) {\r
+    FreePool (SerialNumber);\r
+  }\r
+\r
+  BmEliminateExtraSpaces (Description);\r
+\r
+  return Description;\r
+}\r
+\r
+/**\r
+  Return the boot description for the controller based on the type.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetMiscDescription (\r
+  IN EFI_HANDLE                  Handle\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  CHAR16                          *Description;\r
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
+\r
+  switch (BmDevicePathType (DevicePathFromHandle (Handle))) {\r
+  case BmAcpiFloppyBoot:\r
+    Description = L"Floppy";\r
+    break;\r
+\r
+  case BmMessageAtapiBoot:\r
+  case BmMessageSataBoot:\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+    ASSERT_EFI_ERROR (Status);\r
+    //\r
+    // Assume a removable SATA device should be the DVD/CD device\r
+    //\r
+    Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";\r
+    break;\r
+\r
+  case BmMessageUsbBoot:\r
+    Description = L"USB Device";\r
+    break;\r
+\r
+  case BmMessageScsiBoot:\r
+    Description = L"SCSI Device";\r
+    break;\r
+\r
+  case BmHardwareDeviceBoot:\r
+    Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";\r
+    } else {\r
+      Description = L"Misc Device";\r
+    }\r
+    break;\r
+\r
+  case BmMessageNetworkBoot:\r
+    Description = L"Network";\r
+    break;\r
+\r
+  case BmMessageHttpBoot:\r
+    Description = L"Http";\r
+    break;\r
+\r
+  default:\r
+    Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs);\r
+    if (!EFI_ERROR (Status)) {\r
+      Description = L"Non-Block Boot Device";\r
+    } else {\r
+      Description = L"Misc Device";\r
+    }\r
+    break;\r
+  }\r
+\r
+  return AllocateCopyPool (StrSize (Description), Description);\r
+}\r
+\r
+/**\r
+  Register the platform provided boot description handler.\r
+\r
+  @param Handler  The platform provided boot description handler\r
+\r
+  @retval EFI_SUCCESS          The handler was registered successfully.\r
+  @retval EFI_ALREADY_STARTED  The handler was already registered.\r
+  @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiBootManagerRegisterBootDescriptionHandler (\r
+  IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER  Handler\r
+  )\r
+{\r
+  LIST_ENTRY                                    *Link;\r
+  BM_BOOT_DESCRIPTION_ENTRY                    *Entry;\r
+\r
+  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)\r
+      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)\r
+      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)\r
+      ) {\r
+    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);\r
+    if (Entry->Handler == Handler) {\r
+      return EFI_ALREADY_STARTED;\r
+    }\r
+  }\r
+\r
+  Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));\r
+  if (Entry == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;\r
+  Entry->Handler   = Handler;\r
+  InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {\r
+  BmGetUsbDescription,\r
+  BmGetDescriptionFromDiskInfo,\r
+  BmGetMiscDescription\r
+};\r
+\r
+/**\r
+  Return the boot description for the controller.\r
+\r
+  @param Handle                Controller handle.\r
+\r
+  @return  The description string.\r
+**/\r
+CHAR16 *\r
+BmGetBootDescription (\r
+  IN EFI_HANDLE                  Handle\r
+  )\r
+{\r
+  LIST_ENTRY                     *Link;\r
+  BM_BOOT_DESCRIPTION_ENTRY      *Entry;\r
+  CHAR16                         *Description;\r
+  CHAR16                         *DefaultDescription;\r
+  CHAR16                         *Temp;\r
+  UINTN                          Index;\r
+\r
+  //\r
+  // Firstly get the default boot description\r
+  //\r
+  DefaultDescription = NULL;\r
+  for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof (mBmBootDescriptionHandlers[0]); Index++) {\r
+    DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle);\r
+    if (DefaultDescription != NULL) {\r
+      //\r
+      // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix\r
+      // ONLY for core provided boot description handler.\r
+      //\r
+      Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix));\r
+      ASSERT (Temp != NULL);\r
+      StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), mBmUefiPrefix);\r
+      StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), DefaultDescription);\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
+  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
index cfaeefe181955eb7642305f4422e69f3132d5a36..c1514c3ee48171f19858b39224753e2dd2d5a892 100644 (file)
@@ -166,28 +166,6 @@ typedef struct {
 \r
 #define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)\r
 \r
 \r
 #define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)\r
 \r
-/**\r
-  Get the image file buffer data and buffer size by its device path. \r
-\r
-  @param FilePath  On input, a pointer to an allocated buffer containing the device\r
-                   path of the file.\r
-                   On output the pointer could be NULL when the function fails to\r
-                   load the boot option, or could point to an allocated buffer containing\r
-                   the device path of the file.\r
-                   It could be updated by either short-form device path expanding,\r
-                   or default boot file path appending.\r
-                   Caller is responsible to free it when it's non-NULL.\r
-  @param FileSize  A pointer to the size of the file buffer.\r
-\r
-  @retval NULL   File is NULL, or FileSize is NULL. Or, the file can't be found.\r
-  @retval other  The file buffer. The caller is responsible to free the memory.\r
-**/\r
-VOID *\r
-BmLoadEfiBootOption (\r
-  IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
-  OUT    UINTN                    *FileSize\r
-  );\r
-\r
 /**\r
   Get the Option Number that wasn't used.\r
 \r
 /**\r
   Get the Option Number that wasn't used.\r
 \r
@@ -221,28 +199,6 @@ BmWriteBootToOsPerformanceData (
   IN VOID       *Context\r
   );\r
 \r
   IN VOID       *Context\r
   );\r
 \r
-\r
-/**\r
-  Get the headers (dos, image, optional header) from an image\r
-\r
-  @param  Device                SimpleFileSystem device handle\r
-  @param  FileName              File name for the image\r
-  @param  DosHeader             Pointer to dos header\r
-  @param  Hdr                   The buffer in which to return the PE32, PE32+, or TE header.\r
-\r
-  @retval EFI_SUCCESS           Successfully get the machine type.\r
-  @retval EFI_NOT_FOUND         The file is not found.\r
-  @retval EFI_LOAD_ERROR        File is not a valid image file.\r
-\r
-**/\r
-EFI_STATUS\r
-BmGetImageHeader (\r
-  IN  EFI_HANDLE                  Device,\r
-  IN  CHAR16                      *FileName,\r
-  OUT EFI_IMAGE_DOS_HEADER        *DosHeader,\r
-  OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr\r
-  );\r
-\r
 /**\r
   This routine adjust the memory information for different memory type and \r
   save them into the variables for next boot. It resets the system when\r
 /**\r
   This routine adjust the memory information for different memory type and \r
   save them into the variables for next boot. It resets the system when\r
@@ -472,4 +428,29 @@ BmGetFileBufferFromLoadFileFileSystem (
   OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
   OUT UINTN                           *FileSize\r
   );\r
   OUT EFI_DEVICE_PATH_PROTOCOL        **FullPath,\r
   OUT UINTN                           *FileSize\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
+/**\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
 #endif // _INTERNAL_BM_H_\r
 #endif // _INTERNAL_BM_H_\r
index f1f6246b110779ca7dbdfc840f71447fab17f26b..e9e74b15877481d215cb4ebead5892633ae6fb7b 100644 (file)
@@ -5,7 +5,7 @@
 #  manipulation, hotkey registration, UEFI boot, connect/disconnect, console\r
 #  manipulation, driver health checking and etc.\r
 #\r
 #  manipulation, hotkey registration, UEFI boot, connect/disconnect, console\r
 #  manipulation, driver health checking and etc.\r
 #\r
-#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2016, 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
 #  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
@@ -37,6 +37,7 @@
   BmMisc.c\r
   BmConsole.c\r
   BmBoot.c\r
   BmMisc.c\r
   BmConsole.c\r
   BmBoot.c\r
+  BmBootDescription.c\r
   BmLoadOption.c\r
   BmHotkey.c\r
   BmDriverHealth.c\r
   BmLoadOption.c\r
   BmHotkey.c\r
   BmDriverHealth.c\r