123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- /** @file
- Library functions which relate with boot option description.
- Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #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 BmMiscBoot If tiven device path doesn't match the above condition.
- **/
- 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;
- }
- }
- }
- 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;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- 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) ||
- CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoUfsInterfaceGuid))
- {
- 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';
- AsciiStrToUnicodeStrS (StrPtr, Description, VENDOR_IDENTIFICATION_LENGTH + 1);
- 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';
- AsciiStrToUnicodeStrS (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1, PRODUCT_IDENTIFICATION_LENGTH + 1);
- BmEliminateExtraSpaces (Description);
- }
- } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoSdMmcInterfaceGuid)) {
- DevicePath = DevicePathFromHandle (Handle);
- if (DevicePath == NULL) {
- return NULL;
- }
- while (!IsDevicePathEnd (DevicePath) && (DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH)) {
- DevicePath = NextDevicePathNode (DevicePath);
- }
- if (IsDevicePathEnd (DevicePath)) {
- return NULL;
- }
- if (DevicePathSubType (DevicePath) == MSG_SD_DP) {
- Description = L"SD Device";
- } else if (DevicePathSubType (DevicePath) == MSG_EMMC_DP) {
- Description = L"eMMC Device";
- } else {
- return NULL;
- }
- Description = AllocateCopyPool (StrSize (Description), 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 description for network boot device.
- @param Handle Controller handle.
- @return The description string.
- **/
- CHAR16 *
- BmGetNetworkDescription (
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- MAC_ADDR_DEVICE_PATH *Mac;
- VLAN_DEVICE_PATH *Vlan;
- EFI_DEVICE_PATH_PROTOCOL *Ip;
- EFI_DEVICE_PATH_PROTOCOL *Uri;
- CHAR16 *Description;
- UINTN DescriptionSize;
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiLoadFileProtocolGuid,
- NULL,
- gImageHandle,
- Handle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&DevicePath,
- gImageHandle,
- Handle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status) || (DevicePath == NULL)) {
- return NULL;
- }
- //
- // The PXE device path is like:
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)
- //
- // The HTTP device path is like:
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
- //
- while (!IsDevicePathEnd (DevicePath) &&
- ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
- (DevicePathSubType (DevicePath) != MSG_MAC_ADDR_DP))
- )
- {
- DevicePath = NextDevicePathNode (DevicePath);
- }
- if (IsDevicePathEnd (DevicePath)) {
- return NULL;
- }
- Mac = (MAC_ADDR_DEVICE_PATH *)DevicePath;
- DevicePath = NextDevicePathNode (DevicePath);
- //
- // Locate the optional Vlan node
- //
- if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == MSG_VLAN_DP)
- )
- {
- Vlan = (VLAN_DEVICE_PATH *)DevicePath;
- DevicePath = NextDevicePathNode (DevicePath);
- } else {
- Vlan = NULL;
- }
- //
- // Skip the optional Wi-Fi node
- //
- if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == MSG_WIFI_DP)
- )
- {
- DevicePath = NextDevicePathNode (DevicePath);
- }
- //
- // Locate the IP node
- //
- if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
- ((DevicePathSubType (DevicePath) == MSG_IPv4_DP) ||
- (DevicePathSubType (DevicePath) == MSG_IPv6_DP))
- )
- {
- Ip = DevicePath;
- DevicePath = NextDevicePathNode (DevicePath);
- } else {
- Ip = NULL;
- }
- //
- // Skip the optional DNS node
- //
- if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == MSG_DNS_DP)
- )
- {
- DevicePath = NextDevicePathNode (DevicePath);
- }
- //
- // Locate the URI node
- //
- if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (DevicePath) == MSG_URI_DP)
- )
- {
- Uri = DevicePath;
- DevicePath = NextDevicePathNode (DevicePath);
- } else {
- Uri = NULL;
- }
- //
- // Build description like below:
- // "PXEv6 (MAC:112233445566 VLAN1)"
- // "HTTPv4 (MAC:112233445566)"
- //
- DescriptionSize = sizeof (L"HTTPv6 (MAC:112233445566 VLAN65535)");
- Description = AllocatePool (DescriptionSize);
- ASSERT (Description != NULL);
- UnicodeSPrint (
- Description,
- DescriptionSize,
- (Vlan == NULL) ?
- L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x)" :
- L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x VLAN%d)",
- (Uri == NULL) ? L"PXE" : L"HTTP",
- ((Ip == NULL) || (DevicePathSubType (Ip) == MSG_IPv4_DP)) ? 4 : 6,
- Mac->MacAddress.Addr[0],
- Mac->MacAddress.Addr[1],
- Mac->MacAddress.Addr[2],
- Mac->MacAddress.Addr[3],
- Mac->MacAddress.Addr[4],
- Mac->MacAddress.Addr[5],
- (Vlan == NULL) ? 0 : Vlan->VlanId
- );
- return Description;
- }
- /**
- Return the boot description for LoadFile
- @param Handle Controller handle.
- @return The description string.
- **/
- CHAR16 *
- BmGetLoadFileDescription (
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *FilePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
- CHAR16 *Description;
- EFI_LOAD_FILE_PROTOCOL *LoadFile;
- Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFile);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
- //
- // Get the file name
- //
- Description = NULL;
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&FilePath);
- if (!EFI_ERROR (Status)) {
- DevicePathNode = FilePath;
- while (!IsDevicePathEnd (DevicePathNode)) {
- if ((DevicePathNode->Type == MEDIA_DEVICE_PATH) && (DevicePathNode->SubType == MEDIA_FILEPATH_DP)) {
- Description = (CHAR16 *)(DevicePathNode + 1);
- break;
- }
- DevicePathNode = NextDevicePathNode (DevicePathNode);
- }
- }
- if (Description != NULL) {
- return AllocateCopyPool (StrSize (Description), Description);
- }
- return NULL;
- }
- /**
- Return the boot description for NVME boot device.
- @param Handle Controller handle.
- @return The description string.
- **/
- CHAR16 *
- BmGetNvmeDescription (
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmePassthru;
- EFI_DEV_PATH_PTR DevicePath;
- EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
- EFI_NVM_EXPRESS_COMMAND Command;
- EFI_NVM_EXPRESS_COMPLETION Completion;
- NVME_ADMIN_CONTROLLER_DATA ControllerData;
- CHAR16 *Description;
- CHAR16 *Char;
- UINTN Index;
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath.DevPath);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
- Status = gBS->LocateDevicePath (&gEfiNvmExpressPassThruProtocolGuid, &DevicePath.DevPath, &Handle);
- if (EFI_ERROR (Status) ||
- (DevicePathType (DevicePath.DevPath) != MESSAGING_DEVICE_PATH) ||
- (DevicePathSubType (DevicePath.DevPath) != MSG_NVME_NAMESPACE_DP))
- {
- //
- // Do not return description when the Handle is not a child of NVME controller.
- //
- return NULL;
- }
- //
- // Send ADMIN_IDENTIFY command to NVME controller to get the model and serial number.
- //
- Status = gBS->HandleProtocol (Handle, &gEfiNvmExpressPassThruProtocolGuid, (VOID **)&NvmePassthru);
- ASSERT_EFI_ERROR (Status);
- ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
- ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
- ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
- Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
- //
- // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
- // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
- //
- Command.Nsid = 0;
- CommandPacket.NvmeCmd = &Command;
- CommandPacket.NvmeCompletion = &Completion;
- CommandPacket.TransferBuffer = &ControllerData;
- CommandPacket.TransferLength = sizeof (ControllerData);
- CommandPacket.CommandTimeout = EFI_TIMER_PERIOD_SECONDS (5);
- CommandPacket.QueueType = NVME_ADMIN_QUEUE;
- //
- // Set bit 0 (Cns bit) to 1 to identify a controller
- //
- Command.Cdw10 = 1;
- Command.Flags = CDW10_VALID;
- Status = NvmePassthru->PassThru (
- NvmePassthru,
- 0,
- &CommandPacket,
- NULL
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
- Description = AllocateZeroPool (
- (ARRAY_SIZE (ControllerData.Mn) + 1
- + ARRAY_SIZE (ControllerData.Sn) + 1
- + MAXIMUM_VALUE_CHARACTERS + 1
- ) * sizeof (CHAR16)
- );
- if (Description != NULL) {
- Char = Description;
- for (Index = 0; Index < ARRAY_SIZE (ControllerData.Mn); Index++) {
- *(Char++) = (CHAR16)ControllerData.Mn[Index];
- }
- *(Char++) = L' ';
- for (Index = 0; Index < ARRAY_SIZE (ControllerData.Sn); Index++) {
- *(Char++) = (CHAR16)ControllerData.Sn[Index];
- }
- *(Char++) = L' ';
- UnicodeValueToStringS (
- Char,
- sizeof (CHAR16) * (MAXIMUM_VALUE_CHARACTERS + 1),
- 0,
- DevicePath.NvmeNamespace->NamespaceId,
- 0
- );
- 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;
- 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,
- BmGetNetworkDescription,
- BmGetLoadFileDescription,
- BmGetNvmeDescription,
- 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 < ARRAY_SIZE (mBmBootDescriptionHandlers); 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);
- }
|