Patch is good to me. Reviewed-by: Fu Siyuan <siyuan...@intel.com> > -----Original Message----- > From: Ni, Ruiyu > Sent: Friday, March 4, 2016 6:15 PM > To: edk2-devel@lists.01.org > Cc: Ni, Ruiyu <ruiyu...@intel.com>; Tian, Feng <feng.t...@intel.com>; Fu, > Siyuan <siyuan...@intel.com> > Subject: [Patch 1/2] MdeModulePkg/UefiBootManagerLib: Separate boot > description functions. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ruiyu Ni <ruiyu...@intel.com> > Cc: Feng Tian <feng.t...@intel.com> > Cc: Siyuan Fu <siyuan...@intel.com> > --- > MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 576 ------------------- > - > .../Library/UefiBootManagerLib/BmBootDescription.c | 586 > +++++++++++++++++++++ > .../Library/UefiBootManagerLib/InternalBm.h | 69 +-- > .../UefiBootManagerLib/UefiBootManagerLib.inf | 3 +- > 4 files changed, 613 insertions(+), 621 deletions(-) > create mode 100644 > MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c > > diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c > b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c > index 18f835a..0b86cb9 100644 > --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c > +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c > @@ -15,19 +15,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY > KIND, EITHER EXPRESS OR IMPLIED. > > #include "InternalBm.h" > > -#define VENDOR_IDENTIFICATION_OFFSET 3 > -#define VENDOR_IDENTIFICATION_LENGTH 8 > -#define PRODUCT_IDENTIFICATION_OFFSET 11 > -#define PRODUCT_IDENTIFICATION_LENGTH 16 > - > -CONST UINT16 mBmUsbLangId = 0x0409; // English > -CHAR16 mBmUefiPrefix[] = L"UEFI "; > - > EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION > mBmRefreshLegacyBootOption = NULL; > EFI_BOOT_MANAGER_LEGACY_BOOT mBmLegacyBoot = > NULL; > > -LIST_ENTRY mPlatformBootDescriptionHandlers = > INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers); > - > /// > /// This GUID is used for an EFI Variable that stores the front device pathes > /// for a partial device path that starts with the HD node. > @@ -75,107 +65,6 @@ BmIsAutoCreateBootOption ( > } > > /** > - For a bootable Device path, return its boot type. > - > - @param DevicePath The bootable device Path to check > - > - @retval AcpiFloppyBoot If given device path contains > ACPI_DEVICE_PATH type device path node > - which HID is floppy device. > - @retval MessageAtapiBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is MSG_ATAPI_DP. > - @retval MessageSataBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is MSG_SATA_DP. > - @retval MessageScsiBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is MSG_SCSI_DP. > - @retval MessageUsbBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is MSG_USB_DP. > - @retval MessageNetworkBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is > MSG_MAC_ADDR_DP, MSG_VLAN_DP, > - MSG_IPv4_DP or MSG_IPv6_DP. > - @retval MessageHttpBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > - and its last device path node's > subtype is MSG_URI_DP. > - @retval UnsupportedBoot If tiven device path doesn't match the > above condition, it's not supported. > - > -**/ > -BM_BOOT_TYPE > -BmDevicePathType ( > - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath > - ) > -{ > - EFI_DEVICE_PATH_PROTOCOL *Node; > - EFI_DEVICE_PATH_PROTOCOL *NextNode; > - > - ASSERT (DevicePath != NULL); > - > - for (Node = DevicePath; !IsDevicePathEndType (Node); Node = > NextDevicePathNode (Node)) { > - switch (DevicePathType (Node)) { > - > - case ACPI_DEVICE_PATH: > - if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == > 0x0604) { > - return BmAcpiFloppyBoot; > - } > - break; > - > - case HARDWARE_DEVICE_PATH: > - if (DevicePathSubType (Node) == HW_CONTROLLER_DP) { > - return BmHardwareDeviceBoot; > - } > - break; > - > - case MESSAGING_DEVICE_PATH: > - // > - // Skip LUN device node > - // > - NextNode = Node; > - do { > - NextNode = NextDevicePathNode (NextNode); > - } while ( > - (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) && > - (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP) > - ); > - > - // > - // If the device path not only point to driver device, it is not a > messaging > device path, > - // > - if (!IsDevicePathEndType (NextNode)) { > - continue; > - } > - > - switch (DevicePathSubType (Node)) { > - case MSG_ATAPI_DP: > - return BmMessageAtapiBoot; > - break; > - > - case MSG_SATA_DP: > - return BmMessageSataBoot; > - break; > - > - case MSG_USB_DP: > - return BmMessageUsbBoot; > - break; > - > - case MSG_SCSI_DP: > - return BmMessageScsiBoot; > - break; > - > - case MSG_MAC_ADDR_DP: > - case MSG_VLAN_DP: > - case MSG_IPv4_DP: > - case MSG_IPv6_DP: > - return BmMessageNetworkBoot; > - break; > - > - case MSG_URI_DP: > - return BmMessageHttpBoot; > - break; > - } > - } > - } > - > - return BmMiscBoot; > -} > - > -/** > Find the boot option in the NV storage and return the option number. > > @param OptionToFind Boot option to be checked. > @@ -455,411 +344,6 @@ BmMatchUsbClass ( > } > > /** > - Eliminate the extra spaces in the Str to one space. > - > - @param Str Input string info. > -**/ > -VOID > -BmEliminateExtraSpaces ( > - IN CHAR16 *Str > - ) > -{ > - UINTN Index; > - UINTN ActualIndex; > - > - for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) { > - if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] > != L' '))) { > - Str[ActualIndex++] = Str[Index]; > - } > - } > - Str[ActualIndex] = L'\0'; > -} > - > -/** > - Try to get the controller's ATA/ATAPI description. > - > - @param Handle Controller handle. > - > - @return The description string. > -**/ > -CHAR16 * > -BmGetDescriptionFromDiskInfo ( > - IN EFI_HANDLE Handle > - ) > -{ > - UINTN Index; > - EFI_STATUS Status; > - EFI_DISK_INFO_PROTOCOL *DiskInfo; > - UINT32 BufferSize; > - EFI_ATAPI_IDENTIFY_DATA IdentifyData; > - EFI_SCSI_INQUIRY_DATA InquiryData; > - CHAR16 *Description; > - UINTN Length; > - CONST UINTN ModelNameLength = 40; > - CONST UINTN SerialNumberLength = 20; > - CHAR8 *StrPtr; > - UINT8 Temp; > - > - Description = NULL; > - > - Status = gBS->HandleProtocol ( > - Handle, > - &gEfiDiskInfoProtocolGuid, > - (VOID **) &DiskInfo > - ); > - if (EFI_ERROR (Status)) { > - return NULL; > - } > - > - if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || > - CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) { > - BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA); > - Status = DiskInfo->Identify ( > - DiskInfo, > - &IdentifyData, > - &BufferSize > - ); > - if (!EFI_ERROR (Status)) { > - Description = AllocateZeroPool ((ModelNameLength + > SerialNumberLength + 2) * sizeof (CHAR16)); > - ASSERT (Description != NULL); > - for (Index = 0; Index + 1 < ModelNameLength; Index += 2) { > - Description[Index] = (CHAR16) IdentifyData.ModelName[Index + 1]; > - Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index]; > - } > - > - Length = Index; > - Description[Length++] = L' '; > - > - for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { > - Description[Length + Index] = (CHAR16) > IdentifyData.SerialNo[Index + > 1]; > - Description[Length + Index + 1] = (CHAR16) > IdentifyData.SerialNo[Index]; > - } > - Length += Index; > - Description[Length++] = L'\0'; > - ASSERT (Length == ModelNameLength + SerialNumberLength + 2); > - > - BmEliminateExtraSpaces (Description); > - } > - } else if (CompareGuid (&DiskInfo->Interface, > &gEfiDiskInfoScsiInterfaceGuid)) { > - BufferSize = sizeof (EFI_SCSI_INQUIRY_DATA); > - Status = DiskInfo->Inquiry ( > - DiskInfo, > - &InquiryData, > - &BufferSize > - ); > - if (!EFI_ERROR (Status)) { > - Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + > PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16)); > - ASSERT (Description != NULL); > - > - // > - // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the > Verdor identification > - // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product > identification, > - // Here combine the vendor identification and product identification to > the description. > - // > - StrPtr = (CHAR8 *) > (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]); > - Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH]; > - StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0'; > - AsciiStrToUnicodeStr (StrPtr, Description); > - StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp; > - > - // > - // Add one space at the middle of vendor information and product > information. > - // > - Description[VENDOR_IDENTIFICATION_LENGTH] = L' '; > - > - StrPtr = (CHAR8 *) > (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]); > - StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0'; > - AsciiStrToUnicodeStr (StrPtr, Description + > VENDOR_IDENTIFICATION_LENGTH + 1); > - > - BmEliminateExtraSpaces (Description); > - } > - } > - > - return Description; > -} > - > -/** > - Try to get the controller's USB description. > - > - @param Handle Controller handle. > - > - @return The description string. > -**/ > -CHAR16 * > -BmGetUsbDescription ( > - IN EFI_HANDLE Handle > - ) > -{ > - EFI_STATUS Status; > - EFI_USB_IO_PROTOCOL *UsbIo; > - CHAR16 NullChar; > - CHAR16 *Manufacturer; > - CHAR16 *Product; > - CHAR16 *SerialNumber; > - CHAR16 *Description; > - EFI_USB_DEVICE_DESCRIPTOR DevDesc; > - UINTN DescMaxSize; > - > - Status = gBS->HandleProtocol ( > - Handle, > - &gEfiUsbIoProtocolGuid, > - (VOID **) &UsbIo > - ); > - if (EFI_ERROR (Status)) { > - return NULL; > - } > - > - NullChar = L'\0'; > - > - Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); > - if (EFI_ERROR (Status)) { > - return NULL; > - } > - > - Status = UsbIo->UsbGetStringDescriptor ( > - UsbIo, > - mBmUsbLangId, > - DevDesc.StrManufacturer, > - &Manufacturer > - ); > - if (EFI_ERROR (Status)) { > - Manufacturer = &NullChar; > - } > - > - Status = UsbIo->UsbGetStringDescriptor ( > - UsbIo, > - mBmUsbLangId, > - DevDesc.StrProduct, > - &Product > - ); > - if (EFI_ERROR (Status)) { > - Product = &NullChar; > - } > - > - Status = UsbIo->UsbGetStringDescriptor ( > - UsbIo, > - mBmUsbLangId, > - DevDesc.StrSerialNumber, > - &SerialNumber > - ); > - if (EFI_ERROR (Status)) { > - SerialNumber = &NullChar; > - } > - > - if ((Manufacturer == &NullChar) && > - (Product == &NullChar) && > - (SerialNumber == &NullChar) > - ) { > - return NULL; > - } > - > - DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize > (SerialNumber); > - Description = AllocateZeroPool (DescMaxSize); > - ASSERT (Description != NULL); > - StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer); > - StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" "); > - > - StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product); > - StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" "); > - > - StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber); > - > - if (Manufacturer != &NullChar) { > - FreePool (Manufacturer); > - } > - if (Product != &NullChar) { > - FreePool (Product); > - } > - if (SerialNumber != &NullChar) { > - FreePool (SerialNumber); > - } > - > - BmEliminateExtraSpaces (Description); > - > - return Description; > -} > - > -/** > - Return the boot description for the controller based on the type. > - > - @param Handle Controller handle. > - > - @return The description string. > -**/ > -CHAR16 * > -BmGetMiscDescription ( > - IN EFI_HANDLE Handle > - ) > -{ > - EFI_STATUS Status; > - CHAR16 *Description; > - EFI_BLOCK_IO_PROTOCOL *BlockIo; > - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > - > - switch (BmDevicePathType (DevicePathFromHandle (Handle))) { > - case BmAcpiFloppyBoot: > - Description = L"Floppy"; > - break; > - > - case BmMessageAtapiBoot: > - case BmMessageSataBoot: > - Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) > &BlockIo); > - ASSERT_EFI_ERROR (Status); > - // > - // Assume a removable SATA device should be the DVD/CD device > - // > - Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : > L"Hard Drive"; > - break; > - > - case BmMessageUsbBoot: > - Description = L"USB Device"; > - break; > - > - case BmMessageScsiBoot: > - Description = L"SCSI Device"; > - break; > - > - case BmHardwareDeviceBoot: > - Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) > &BlockIo); > - if (!EFI_ERROR (Status)) { > - Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : > L"Hard Drive"; > - } else { > - Description = L"Misc Device"; > - } > - break; > - > - case BmMessageNetworkBoot: > - Description = L"Network"; > - break; > - > - case BmMessageHttpBoot: > - Description = L"Http"; > - break; > - > - default: > - Status = gBS->HandleProtocol (Handle, > &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs); > - if (!EFI_ERROR (Status)) { > - Description = L"Non-Block Boot Device"; > - } else { > - Description = L"Misc Device"; > - } > - break; > - } > - > - return AllocateCopyPool (StrSize (Description), Description); > -} > - > -/** > - Register the platform provided boot description handler. > - > - @param Handler The platform provided boot description handler > - > - @retval EFI_SUCCESS The handler was registered successfully. > - @retval EFI_ALREADY_STARTED The handler was already registered. > - @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform > the registration. > -**/ > -EFI_STATUS > -EFIAPI > -EfiBootManagerRegisterBootDescriptionHandler ( > - IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler > - ) > -{ > - LIST_ENTRY *Link; > - BM_BOOT_DESCRIPTION_ENTRY *Entry; > - > - for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers) > - ; !IsNull (&mPlatformBootDescriptionHandlers, Link) > - ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link) > - ) { > - Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, > BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE); > - if (Entry->Handler == Handler) { > - return EFI_ALREADY_STARTED; > - } > - } > - > - Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY)); > - if (Entry == NULL) { > - return EFI_OUT_OF_RESOURCES; > - } > - > - Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE; > - Entry->Handler = Handler; > - InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link); > - return EFI_SUCCESS; > -} > - > -BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = { > - BmGetUsbDescription, > - BmGetDescriptionFromDiskInfo, > - BmGetMiscDescription > -}; > - > -/** > - Return the boot description for the controller. > - > - @param Handle Controller handle. > - > - @return The description string. > -**/ > -CHAR16 * > -BmGetBootDescription ( > - IN EFI_HANDLE Handle > - ) > -{ > - LIST_ENTRY *Link; > - BM_BOOT_DESCRIPTION_ENTRY *Entry; > - CHAR16 *Description; > - CHAR16 *DefaultDescription; > - CHAR16 *Temp; > - UINTN Index; > - > - // > - // Firstly get the default boot description > - // > - DefaultDescription = NULL; > - for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof > (mBmBootDescriptionHandlers[0]); Index++) { > - DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle); > - if (DefaultDescription != NULL) { > - // > - // Avoid description confusion between UEFI & Legacy boot option by > adding "UEFI " prefix > - // ONLY for core provided boot description handler. > - // > - Temp = AllocatePool (StrSize (DefaultDescription) + sizeof > (mBmUefiPrefix)); > - ASSERT (Temp != NULL); > - StrCpyS ( Temp, > - (StrSize (DefaultDescription) + sizeof > (mBmUefiPrefix))/sizeof(CHAR16), > - mBmUefiPrefix > - ); > - StrCatS ( Temp, > - (StrSize (DefaultDescription) + sizeof > (mBmUefiPrefix))/sizeof(CHAR16), > - DefaultDescription > - ); > - FreePool (DefaultDescription); > - DefaultDescription = Temp; > - break; > - } > - } > - ASSERT (DefaultDescription != NULL); > - > - // > - // Secondly query platform for the better boot description > - // > - for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers) > - ; !IsNull (&mPlatformBootDescriptionHandlers, Link) > - ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link) > - ) { > - Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, > BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE); > - Description = Entry->Handler (Handle, DefaultDescription); > - if (Description != NULL) { > - FreePool (DefaultDescription); > - return Description; > - } > - } > - > - return DefaultDescription; > -} > - > -/** > Check whether a USB device match the specified USB WWID device path. > This > function follows "Load Option Processing" behavior in UEFI specification. > > @@ -2252,66 +1736,6 @@ BmMatchPartitionDevicePathNode ( > } > > /** > - Enumerate all boot option descriptions and append " 2"/" 3"/... to make > - unique description. > - > - @param BootOptions Array of boot options. > - @param BootOptionCount Count of boot options. > -**/ > -VOID > -BmMakeBootOptionDescriptionUnique ( > - EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, > - UINTN BootOptionCount > - ) > -{ > - UINTN Base; > - UINTN Index; > - UINTN DescriptionSize; > - UINTN MaxSuffixSize; > - BOOLEAN *Visited; > - UINTN MatchCount; > - > - if (BootOptionCount == 0) { > - return; > - } > - > - // > - // Calculate the maximum buffer size for the number suffix. > - // The initial sizeof (CHAR16) is for the blank space before the number. > - // > - MaxSuffixSize = sizeof (CHAR16); > - for (Index = BootOptionCount; Index != 0; Index = Index / 10) { > - MaxSuffixSize += sizeof (CHAR16); > - } > - > - Visited = AllocateZeroPool (sizeof (BOOLEAN) * BootOptionCount); > - ASSERT (Visited != NULL); > - > - for (Base = 0; Base < BootOptionCount; Base++) { > - if (!Visited[Base]) { > - MatchCount = 1; > - Visited[Base] = TRUE; > - DescriptionSize = StrSize (BootOptions[Base].Description); > - for (Index = Base + 1; Index < BootOptionCount; Index++) { > - if (!Visited[Index] && StrCmp (BootOptions[Base].Description, > BootOptions[Index].Description) == 0) { > - Visited[Index] = TRUE; > - MatchCount++; > - FreePool (BootOptions[Index].Description); > - BootOptions[Index].Description = AllocatePool (DescriptionSize + > MaxSuffixSize); > - UnicodeSPrint ( > - BootOptions[Index].Description, DescriptionSize + MaxSuffixSize, > - L"%s %d", > - BootOptions[Base].Description, MatchCount > - ); > - } > - } > - } > - } > - > - FreePool (Visited); > -} > - > -/** > Emuerate all possible bootable medias in the following order: > 1. Removable BlockIo - The boot option only points to the > removable > media > device, like USB key, DVD, Floppy etc. > diff --git > a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c > b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c > new file mode 100644 > index 0000000..5c77e86 > --- /dev/null > +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c > @@ -0,0 +1,586 @@ > +/** @file > + Library functions which relate with boot option description. > + > +Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR> > +(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> > +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BSD > License > +which accompanies this distribution. The full text of the license may be > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include "InternalBm.h" > + > +#define VENDOR_IDENTIFICATION_OFFSET 3 > +#define VENDOR_IDENTIFICATION_LENGTH 8 > +#define PRODUCT_IDENTIFICATION_OFFSET 11 > +#define PRODUCT_IDENTIFICATION_LENGTH 16 > + > +CONST UINT16 mBmUsbLangId = 0x0409; // English > +CHAR16 mBmUefiPrefix[] = L"UEFI "; > + > +LIST_ENTRY mPlatformBootDescriptionHandlers = > INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers); > + > +/** > + For a bootable Device path, return its boot type. > + > + @param DevicePath The bootable device Path to check > + > + @retval AcpiFloppyBoot If given device path contains > ACPI_DEVICE_PATH type device path node > + which HID is floppy device. > + @retval MessageAtapiBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is > MSG_ATAPI_DP. > + @retval MessageSataBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is MSG_SATA_DP. > + @retval MessageScsiBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is MSG_SCSI_DP. > + @retval MessageUsbBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is MSG_USB_DP. > + @retval MessageNetworkBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is > MSG_MAC_ADDR_DP, MSG_VLAN_DP, > + MSG_IPv4_DP or MSG_IPv6_DP. > + @retval MessageHttpBoot If given device path contains > MESSAGING_DEVICE_PATH type device path node > + and its last device path node's > subtype is MSG_URI_DP. > + @retval UnsupportedBoot If tiven device path doesn't match the > above condition, it's not supported. > + > +**/ > +BM_BOOT_TYPE > +BmDevicePathType ( > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath > + ) > +{ > + EFI_DEVICE_PATH_PROTOCOL *Node; > + EFI_DEVICE_PATH_PROTOCOL *NextNode; > + > + ASSERT (DevicePath != NULL); > + > + for (Node = DevicePath; !IsDevicePathEndType (Node); Node = > NextDevicePathNode (Node)) { > + switch (DevicePathType (Node)) { > + > + case ACPI_DEVICE_PATH: > + if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == > 0x0604) { > + return BmAcpiFloppyBoot; > + } > + break; > + > + case HARDWARE_DEVICE_PATH: > + if (DevicePathSubType (Node) == HW_CONTROLLER_DP) { > + return BmHardwareDeviceBoot; > + } > + break; > + > + case MESSAGING_DEVICE_PATH: > + // > + // Skip LUN device node > + // > + NextNode = Node; > + do { > + NextNode = NextDevicePathNode (NextNode); > + } while ( > + (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) && > + (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP) > + ); > + > + // > + // If the device path not only point to driver device, it is not a > messaging > device path, > + // > + if (!IsDevicePathEndType (NextNode)) { > + continue; > + } > + > + switch (DevicePathSubType (Node)) { > + case MSG_ATAPI_DP: > + return BmMessageAtapiBoot; > + break; > + > + case MSG_SATA_DP: > + return BmMessageSataBoot; > + break; > + > + case MSG_USB_DP: > + return BmMessageUsbBoot; > + break; > + > + case MSG_SCSI_DP: > + return BmMessageScsiBoot; > + break; > + > + case MSG_MAC_ADDR_DP: > + case MSG_VLAN_DP: > + case MSG_IPv4_DP: > + case MSG_IPv6_DP: > + return BmMessageNetworkBoot; > + break; > + > + case MSG_URI_DP: > + return BmMessageHttpBoot; > + break; > + } > + } > + } > + > + return BmMiscBoot; > +} > + > +/** > + Eliminate the extra spaces in the Str to one space. > + > + @param Str Input string info. > +**/ > +VOID > +BmEliminateExtraSpaces ( > + IN CHAR16 *Str > + ) > +{ > + UINTN Index; > + UINTN ActualIndex; > + > + for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) { > + if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] > != L' '))) { > + Str[ActualIndex++] = Str[Index]; > + } > + } > + Str[ActualIndex] = L'\0'; > +} > + > +/** > + Try to get the controller's ATA/ATAPI description. > + > + @param Handle Controller handle. > + > + @return The description string. > +**/ > +CHAR16 * > +BmGetDescriptionFromDiskInfo ( > + IN EFI_HANDLE Handle > + ) > +{ > + UINTN Index; > + EFI_STATUS Status; > + EFI_DISK_INFO_PROTOCOL *DiskInfo; > + UINT32 BufferSize; > + EFI_ATAPI_IDENTIFY_DATA IdentifyData; > + EFI_SCSI_INQUIRY_DATA InquiryData; > + CHAR16 *Description; > + UINTN Length; > + CONST UINTN ModelNameLength = 40; > + CONST UINTN SerialNumberLength = 20; > + CHAR8 *StrPtr; > + UINT8 Temp; > + > + Description = NULL; > + > + Status = gBS->HandleProtocol ( > + Handle, > + &gEfiDiskInfoProtocolGuid, > + (VOID **) &DiskInfo > + ); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || > + CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) { > + BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA); > + Status = DiskInfo->Identify ( > + DiskInfo, > + &IdentifyData, > + &BufferSize > + ); > + if (!EFI_ERROR (Status)) { > + Description = AllocateZeroPool ((ModelNameLength + > SerialNumberLength + 2) * sizeof (CHAR16)); > + ASSERT (Description != NULL); > + for (Index = 0; Index + 1 < ModelNameLength; Index += 2) { > + Description[Index] = (CHAR16) IdentifyData.ModelName[Index + 1]; > + Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index]; > + } > + > + Length = Index; > + Description[Length++] = L' '; > + > + for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { > + Description[Length + Index] = (CHAR16) > IdentifyData.SerialNo[Index + > 1]; > + Description[Length + Index + 1] = (CHAR16) > IdentifyData.SerialNo[Index]; > + } > + Length += Index; > + Description[Length++] = L'\0'; > + ASSERT (Length == ModelNameLength + SerialNumberLength + 2); > + > + BmEliminateExtraSpaces (Description); > + } > + } else if (CompareGuid (&DiskInfo->Interface, > &gEfiDiskInfoScsiInterfaceGuid)) { > + BufferSize = sizeof (EFI_SCSI_INQUIRY_DATA); > + Status = DiskInfo->Inquiry ( > + DiskInfo, > + &InquiryData, > + &BufferSize > + ); > + if (!EFI_ERROR (Status)) { > + Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + > PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16)); > + ASSERT (Description != NULL); > + > + // > + // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the > Verdor identification > + // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product > identification, > + // Here combine the vendor identification and product identification to > the description. > + // > + StrPtr = (CHAR8 *) > (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]); > + Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH]; > + StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0'; > + AsciiStrToUnicodeStr (StrPtr, Description); > + StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp; > + > + // > + // Add one space at the middle of vendor information and product > information. > + // > + Description[VENDOR_IDENTIFICATION_LENGTH] = L' '; > + > + StrPtr = (CHAR8 *) > (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]); > + StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0'; > + AsciiStrToUnicodeStr (StrPtr, Description + > VENDOR_IDENTIFICATION_LENGTH + 1); > + > + BmEliminateExtraSpaces (Description); > + } > + } > + > + return Description; > +} > + > +/** > + Try to get the controller's USB description. > + > + @param Handle Controller handle. > + > + @return The description string. > +**/ > +CHAR16 * > +BmGetUsbDescription ( > + IN EFI_HANDLE Handle > + ) > +{ > + EFI_STATUS Status; > + EFI_USB_IO_PROTOCOL *UsbIo; > + CHAR16 NullChar; > + CHAR16 *Manufacturer; > + CHAR16 *Product; > + CHAR16 *SerialNumber; > + CHAR16 *Description; > + EFI_USB_DEVICE_DESCRIPTOR DevDesc; > + UINTN DescMaxSize; > + > + Status = gBS->HandleProtocol ( > + Handle, > + &gEfiUsbIoProtocolGuid, > + (VOID **) &UsbIo > + ); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + NullChar = L'\0'; > + > + Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + Status = UsbIo->UsbGetStringDescriptor ( > + UsbIo, > + mBmUsbLangId, > + DevDesc.StrManufacturer, > + &Manufacturer > + ); > + if (EFI_ERROR (Status)) { > + Manufacturer = &NullChar; > + } > + > + Status = UsbIo->UsbGetStringDescriptor ( > + UsbIo, > + mBmUsbLangId, > + DevDesc.StrProduct, > + &Product > + ); > + if (EFI_ERROR (Status)) { > + Product = &NullChar; > + } > + > + Status = UsbIo->UsbGetStringDescriptor ( > + UsbIo, > + mBmUsbLangId, > + DevDesc.StrSerialNumber, > + &SerialNumber > + ); > + if (EFI_ERROR (Status)) { > + SerialNumber = &NullChar; > + } > + > + if ((Manufacturer == &NullChar) && > + (Product == &NullChar) && > + (SerialNumber == &NullChar) > + ) { > + return NULL; > + } > + > + DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize > (SerialNumber); > + Description = AllocateZeroPool (DescMaxSize); > + ASSERT (Description != NULL); > + StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer); > + StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" "); > + > + StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product); > + StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" "); > + > + StrCatS (Description, DescMaxSize/sizeof(CHAR16), SerialNumber); > + > + if (Manufacturer != &NullChar) { > + FreePool (Manufacturer); > + } > + if (Product != &NullChar) { > + FreePool (Product); > + } > + if (SerialNumber != &NullChar) { > + FreePool (SerialNumber); > + } > + > + BmEliminateExtraSpaces (Description); > + > + return Description; > +} > + > +/** > + Return the boot description for the controller based on the type. > + > + @param Handle Controller handle. > + > + @return The description string. > +**/ > +CHAR16 * > +BmGetMiscDescription ( > + IN EFI_HANDLE Handle > + ) > +{ > + EFI_STATUS Status; > + CHAR16 *Description; > + EFI_BLOCK_IO_PROTOCOL *BlockIo; > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; > + > + switch (BmDevicePathType (DevicePathFromHandle (Handle))) { > + case BmAcpiFloppyBoot: > + Description = L"Floppy"; > + break; > + > + case BmMessageAtapiBoot: > + case BmMessageSataBoot: > + Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID > **) &BlockIo); > + ASSERT_EFI_ERROR (Status); > + // > + // Assume a removable SATA device should be the DVD/CD device > + // > + Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : > L"Hard Drive"; > + break; > + > + case BmMessageUsbBoot: > + Description = L"USB Device"; > + break; > + > + case BmMessageScsiBoot: > + Description = L"SCSI Device"; > + break; > + > + case BmHardwareDeviceBoot: > + Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID > **) &BlockIo); > + if (!EFI_ERROR (Status)) { > + Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : > L"Hard Drive"; > + } else { > + Description = L"Misc Device"; > + } > + break; > + > + case BmMessageNetworkBoot: > + Description = L"Network"; > + break; > + > + case BmMessageHttpBoot: > + Description = L"Http"; > + break; > + > + default: > + Status = gBS->HandleProtocol (Handle, > &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Fs); > + if (!EFI_ERROR (Status)) { > + Description = L"Non-Block Boot Device"; > + } else { > + Description = L"Misc Device"; > + } > + break; > + } > + > + return AllocateCopyPool (StrSize (Description), Description); > +} > + > +/** > + Register the platform provided boot description handler. > + > + @param Handler The platform provided boot description handler > + > + @retval EFI_SUCCESS The handler was registered successfully. > + @retval EFI_ALREADY_STARTED The handler was already registered. > + @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform > the registration. > +**/ > +EFI_STATUS > +EFIAPI > +EfiBootManagerRegisterBootDescriptionHandler ( > + IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler > + ) > +{ > + LIST_ENTRY *Link; > + BM_BOOT_DESCRIPTION_ENTRY *Entry; > + > + for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers) > + ; !IsNull (&mPlatformBootDescriptionHandlers, Link) > + ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link) > + ) { > + Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, > BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE); > + if (Entry->Handler == Handler) { > + return EFI_ALREADY_STARTED; > + } > + } > + > + Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY)); > + if (Entry == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE; > + Entry->Handler = Handler; > + InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link); > + return EFI_SUCCESS; > +} > + > +BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = { > + BmGetUsbDescription, > + BmGetDescriptionFromDiskInfo, > + BmGetMiscDescription > +}; > + > +/** > + Return the boot description for the controller. > + > + @param Handle Controller handle. > + > + @return The description string. > +**/ > +CHAR16 * > +BmGetBootDescription ( > + IN EFI_HANDLE Handle > + ) > +{ > + LIST_ENTRY *Link; > + BM_BOOT_DESCRIPTION_ENTRY *Entry; > + CHAR16 *Description; > + CHAR16 *DefaultDescription; > + CHAR16 *Temp; > + UINTN Index; > + > + // > + // Firstly get the default boot description > + // > + DefaultDescription = NULL; > + for (Index = 0; Index < sizeof (mBmBootDescriptionHandlers) / sizeof > (mBmBootDescriptionHandlers[0]); Index++) { > + DefaultDescription = mBmBootDescriptionHandlers[Index] (Handle); > + if (DefaultDescription != NULL) { > + // > + // Avoid description confusion between UEFI & Legacy boot option by > adding "UEFI " prefix > + // ONLY for core provided boot description handler. > + // > + Temp = AllocatePool (StrSize (DefaultDescription) + sizeof > (mBmUefiPrefix)); > + ASSERT (Temp != NULL); > + StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) > / > sizeof (CHAR16), mBmUefiPrefix); > + StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) > / > sizeof (CHAR16), DefaultDescription); > + FreePool (DefaultDescription); > + DefaultDescription = Temp; > + break; > + } > + } > + ASSERT (DefaultDescription != NULL); > + > + // > + // Secondly query platform for the better boot description > + // > + for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers) > + ; !IsNull (&mPlatformBootDescriptionHandlers, Link) > + ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link) > + ) { > + Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, > BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE); > + Description = Entry->Handler (Handle, DefaultDescription); > + if (Description != NULL) { > + FreePool (DefaultDescription); > + return Description; > + } > + } > + > + return DefaultDescription; > +} > + > +/** > + Enumerate all boot option descriptions and append " 2"/" 3"/... to make > + unique description. > + > + @param BootOptions Array of boot options. > + @param BootOptionCount Count of boot options. > +**/ > +VOID > +BmMakeBootOptionDescriptionUnique ( > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, > + UINTN BootOptionCount > + ) > +{ > + UINTN Base; > + UINTN Index; > + UINTN DescriptionSize; > + UINTN MaxSuffixSize; > + BOOLEAN *Visited; > + UINTN MatchCount; > + > + if (BootOptionCount == 0) { > + return; > + } > + > + // > + // Calculate the maximum buffer size for the number suffix. > + // The initial sizeof (CHAR16) is for the blank space before the number. > + // > + MaxSuffixSize = sizeof (CHAR16); > + for (Index = BootOptionCount; Index != 0; Index = Index / 10) { > + MaxSuffixSize += sizeof (CHAR16); > + } > + > + Visited = AllocateZeroPool (sizeof (BOOLEAN) * BootOptionCount); > + ASSERT (Visited != NULL); > + > + for (Base = 0; Base < BootOptionCount; Base++) { > + if (!Visited[Base]) { > + MatchCount = 1; > + Visited[Base] = TRUE; > + DescriptionSize = StrSize (BootOptions[Base].Description); > + for (Index = Base + 1; Index < BootOptionCount; Index++) { > + if (!Visited[Index] && StrCmp (BootOptions[Base].Description, > BootOptions[Index].Description) == 0) { > + Visited[Index] = TRUE; > + MatchCount++; > + FreePool (BootOptions[Index].Description); > + BootOptions[Index].Description = AllocatePool (DescriptionSize + > MaxSuffixSize); > + UnicodeSPrint ( > + BootOptions[Index].Description, DescriptionSize + MaxSuffixSize, > + L"%s %d", > + BootOptions[Base].Description, MatchCount > + ); > + } > + } > + } > + } > + > + FreePool (Visited); > +} > diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h > b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h > index cfaeefe..c1514c3 100644 > --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h > +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h > @@ -167,28 +167,6 @@ typedef struct { > #define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, > BM_HOTKEY_SIGNATURE) > > /** > - Get the image file buffer data and buffer size by its device path. > - > - @param FilePath On input, a pointer to an allocated buffer containing the > device > - path of the file. > - On output the pointer could be NULL when the function > fails to > - load the boot option, or could point to an allocated > buffer > containing > - the device path of the file. > - It could be updated by either short-form device path > expanding, > - or default boot file path appending. > - Caller is responsible to free it when it's non-NULL. > - @param FileSize A pointer to the size of the file buffer. > - > - @retval NULL File is NULL, or FileSize is NULL. Or, the file can't be > found. > - @retval other The file buffer. The caller is responsible to free the > memory. > -**/ > -VOID * > -BmLoadEfiBootOption ( > - IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, > - OUT UINTN *FileSize > - ); > - > -/** > Get the Option Number that wasn't used. > > @param LoadOptionType Load option type. > @@ -221,28 +199,6 @@ BmWriteBootToOsPerformanceData ( > IN VOID *Context > ); > > - > -/** > - Get the headers (dos, image, optional header) from an image > - > - @param Device SimpleFileSystem device handle > - @param FileName File name for the image > - @param DosHeader Pointer to dos header > - @param Hdr The buffer in which to return the PE32, > PE32+, or TE > header. > - > - @retval EFI_SUCCESS Successfully get the machine type. > - @retval EFI_NOT_FOUND The file is not found. > - @retval EFI_LOAD_ERROR File is not a valid image file. > - > -**/ > -EFI_STATUS > -BmGetImageHeader ( > - IN EFI_HANDLE Device, > - IN CHAR16 *FileName, > - OUT EFI_IMAGE_DOS_HEADER *DosHeader, > - OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr > - ); > - > /** > This routine adjust the memory information for different memory type and > save them into the variables for next boot. It resets the system when > @@ -472,4 +428,29 @@ BmGetFileBufferFromLoadFileFileSystem ( > OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, > OUT UINTN *FileSize > ); > + > +/** > + Return the boot description for the controller. > + > + @param Handle Controller handle. > + > + @return The description string. > +**/ > +CHAR16 * > +BmGetBootDescription ( > + IN EFI_HANDLE Handle > + ); > + > +/** > + Enumerate all boot option descriptions and append " 2"/" 3"/... to make > + unique description. > + > + @param BootOptions Array of boot options. > + @param BootOptionCount Count of boot options. > +**/ > +VOID > +BmMakeBootOptionDescriptionUnique ( > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, > + UINTN BootOptionCount > + ); > #endif // _INTERNAL_BM_H_ > diff --git > a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf > b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf > index f1f6246..e9e74b1 100644 > --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf > +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf > @@ -5,7 +5,7 @@ > # manipulation, hotkey registration, UEFI boot, connect/disconnect, console > # manipulation, driver health checking and etc. > # > -# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> > # This program and the accompanying materials > # are licensed and made available under the terms and conditions of the > BSD License > # which accompanies this distribution. The full text of the license may be > found at > @@ -37,6 +37,7 @@ > BmMisc.c > BmConsole.c > BmBoot.c > + BmBootDescription.c > BmLoadOption.c > BmHotkey.c > BmDriverHealth.c > -- > 2.7.0.windows.1
_______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel