GenericBdsLib: add BmBootDescription from UefiBootManagerLib
Copy BmBootDescription from MdeModulePkg/UefiBootManagerLib, removing appending of serial # since it makes descriptions unweildy. Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
This commit is contained in:
@@ -0,0 +1,870 @@
|
|||||||
|
/** @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>
|
||||||
|
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"";
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 + 1) * 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'\0';
|
||||||
|
ASSERT (Length == ModelNameLength + 1);
|
||||||
|
|
||||||
|
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';
|
||||||
|
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);
|
||||||
|
Description = AllocateZeroPool (DescMaxSize);
|
||||||
|
ASSERT (Description != NULL);
|
||||||
|
StrCatS (Description, DescMaxSize/sizeof(CHAR16), Manufacturer);
|
||||||
|
StrCatS (Description, DescMaxSize/sizeof(CHAR16), L" ");
|
||||||
|
|
||||||
|
StrCatS (Description, DescMaxSize/sizeof(CHAR16), Product);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
@@ -39,7 +39,9 @@
|
|||||||
BdsMisc.c
|
BdsMisc.c
|
||||||
BdsConsole.c
|
BdsConsole.c
|
||||||
BdsBoot.c
|
BdsBoot.c
|
||||||
|
BmBootDescription.c
|
||||||
InternalBdsLib.h
|
InternalBdsLib.h
|
||||||
|
InternalBm.h
|
||||||
String.h
|
String.h
|
||||||
String.c
|
String.c
|
||||||
GenericBdsStrings.uni
|
GenericBdsStrings.uni
|
||||||
@@ -103,6 +105,10 @@
|
|||||||
## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder"
|
## SOMETIMES_CONSUMES ## Variable:L"LegacyDevOrder"
|
||||||
gEfiLegacyDevOrderVariableGuid
|
gEfiLegacyDevOrderVariableGuid
|
||||||
gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID
|
gEdkiiStatusCodeDataTypeVariableGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoAhciInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoScsiInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiDiskInfoSdMmcInterfaceGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
@@ -125,6 +131,8 @@
|
|||||||
gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES
|
gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiNvmExpressPassThruProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
[FeaturePcd]
|
[FeaturePcd]
|
||||||
gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES
|
gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES
|
||||||
|
471
IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBm.h
Normal file
471
IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBm.h
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
/** @file
|
||||||
|
BDS library definition, include the file and data structure
|
||||||
|
|
||||||
|
Copyright (c) 2004 - 2018, 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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _INTERNAL_BM_H_
|
||||||
|
#define _INTERNAL_BM_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <IndustryStandard/Pci.h>
|
||||||
|
#include <IndustryStandard/PeImage.h>
|
||||||
|
#include <IndustryStandard/Atapi.h>
|
||||||
|
#include <IndustryStandard/Scsi.h>
|
||||||
|
#include <IndustryStandard/Nvme.h>
|
||||||
|
|
||||||
|
#include <Protocol/PciRootBridgeIo.h>
|
||||||
|
#include <Protocol/BlockIo.h>
|
||||||
|
#include <Protocol/LoadedImage.h>
|
||||||
|
#include <Protocol/SimpleFileSystem.h>
|
||||||
|
#include <Protocol/LoadFile.h>
|
||||||
|
#include <Protocol/DevicePath.h>
|
||||||
|
#include <Protocol/SimpleTextIn.h>
|
||||||
|
#include <Protocol/SimpleTextInEx.h>
|
||||||
|
#include <Protocol/SimpleTextOut.h>
|
||||||
|
#include <Protocol/SimpleNetwork.h>
|
||||||
|
#include <Protocol/FirmwareVolume2.h>
|
||||||
|
#include <Protocol/PciIo.h>
|
||||||
|
#include <Protocol/GraphicsOutput.h>
|
||||||
|
#include <Protocol/UsbIo.h>
|
||||||
|
#include <Protocol/DiskInfo.h>
|
||||||
|
#include <Protocol/NvmExpressPassthru.h>
|
||||||
|
#include <Protocol/IdeControllerInit.h>
|
||||||
|
#include <Protocol/BootLogo.h>
|
||||||
|
#include <Protocol/DriverHealth.h>
|
||||||
|
#include <Protocol/FormBrowser2.h>
|
||||||
|
#include <Protocol/VariableLock.h>
|
||||||
|
#include <Protocol/RamDisk.h>
|
||||||
|
#include <Protocol/DeferredImageLoad.h>
|
||||||
|
|
||||||
|
#include <Guid/MemoryTypeInformation.h>
|
||||||
|
#include <Guid/FileInfo.h>
|
||||||
|
#include <Guid/GlobalVariable.h>
|
||||||
|
#include <Guid/StatusCodeDataTypeVariable.h>
|
||||||
|
|
||||||
|
#include <Library/PrintLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/DevicePathLib.h>
|
||||||
|
#include <Library/PerformanceLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/PeCoffGetEntryPointLib.h>
|
||||||
|
#include <Library/UefiBootManagerLib.h>
|
||||||
|
#include <Library/DxeServicesLib.h>
|
||||||
|
#include <Library/ReportStatusCodeLib.h>
|
||||||
|
#include <Library/CapsuleLib.h>
|
||||||
|
#include <Library/PerformanceLib.h>
|
||||||
|
#include <Library/HiiLib.h>
|
||||||
|
|
||||||
|
#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
|
||||||
|
#if defined (MDE_CPU_EBC)
|
||||||
|
//
|
||||||
|
// Uefi specification only defines the default boot file name for IA32, X64
|
||||||
|
// and IPF processor, so need define boot file name for EBC architecture here.
|
||||||
|
//
|
||||||
|
#define EFI_REMOVABLE_MEDIA_FILE_NAME L"\\EFI\\BOOT\\BOOTEBC.EFI"
|
||||||
|
#else
|
||||||
|
#error "Can not determine the default boot file name for unknown processor type!"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BmAcpiFloppyBoot,
|
||||||
|
BmHardwareDeviceBoot,
|
||||||
|
BmMessageAtapiBoot,
|
||||||
|
BmMessageSataBoot,
|
||||||
|
BmMessageUsbBoot,
|
||||||
|
BmMessageScsiBoot,
|
||||||
|
BmMiscBoot
|
||||||
|
} BM_BOOT_TYPE;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
CHAR16 *
|
||||||
|
(* BM_GET_BOOT_DESCRIPTION) (
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// PlatformRecovery#### is the load option with the longest name
|
||||||
|
//
|
||||||
|
#define BM_OPTION_NAME_LEN sizeof ("PlatformRecovery####")
|
||||||
|
extern CHAR16 *mBmLoadOptionName[];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Maximum number of reconnect retry to repair controller; it is to limit the
|
||||||
|
// number of recursive call of BmRepairAllControllers.
|
||||||
|
//
|
||||||
|
#define MAX_RECONNECT_REPAIR 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
Visitor function to be called by BmForEachVariable for each variable
|
||||||
|
in variable storage.
|
||||||
|
|
||||||
|
@param Name Variable name.
|
||||||
|
@param Guid Variable GUID.
|
||||||
|
@param Context The same context passed to BmForEachVariable.
|
||||||
|
**/
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(*BM_VARIABLE_VISITOR) (
|
||||||
|
CHAR16 *Name,
|
||||||
|
EFI_GUID *Guid,
|
||||||
|
VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call Visitor function for each variable in variable storage.
|
||||||
|
|
||||||
|
@param Visitor Visitor function.
|
||||||
|
@param Context The context passed to Visitor function.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmForEachVariable (
|
||||||
|
BM_VARIABLE_VISITOR Visitor,
|
||||||
|
VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
#define BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE SIGNATURE_32 ('b', 'm', 'd', 'h')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler;
|
||||||
|
} BM_BOOT_DESCRIPTION_ENTRY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Repair all the controllers according to the Driver Health status queried.
|
||||||
|
|
||||||
|
@param ReconnectRepairCount To record the number of recursive call of
|
||||||
|
this function itself.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmRepairAllControllers (
|
||||||
|
UINTN ReconnectRepairCount
|
||||||
|
);
|
||||||
|
|
||||||
|
#define BM_HOTKEY_SIGNATURE SIGNATURE_32 ('b', 'm', 'h', 'k')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
|
||||||
|
BOOLEAN IsContinue;
|
||||||
|
UINT16 BootOption;
|
||||||
|
UINT8 CodeCount;
|
||||||
|
UINT8 WaitingKey;
|
||||||
|
EFI_KEY_DATA KeyData[3];
|
||||||
|
} BM_HOTKEY;
|
||||||
|
|
||||||
|
#define BM_HOTKEY_FROM_LINK(a) CR (a, BM_HOTKEY, Link, BM_HOTKEY_SIGNATURE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the Option Number that wasn't used.
|
||||||
|
|
||||||
|
@param LoadOptionType Load option type.
|
||||||
|
@param FreeOptionNumber To receive the minimal free option number.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The option number is found
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no free option number that can be used.
|
||||||
|
@retval EFI_INVALID_PARAMETER FreeOptionNumber is NULL
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmGetFreeOptionNumber (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType,
|
||||||
|
OUT UINT16 *FreeOptionNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This routine adjust the memory information for different memory type and
|
||||||
|
save them into the variables for next boot. It resets the system when
|
||||||
|
memory information is updated and the current boot option belongs to
|
||||||
|
boot category instead of application category. It doesn't count the
|
||||||
|
reserved memory occupied by RAM Disk.
|
||||||
|
|
||||||
|
@param Boot TRUE if current boot option belongs to boot
|
||||||
|
category instead of application category.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmSetMemoryTypeInformationVariable (
|
||||||
|
IN BOOLEAN Boot
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check whether there is a instance in BlockIoDevicePath, which contain multi device path
|
||||||
|
instances, has the same partition node with HardDriveDevicePath device path
|
||||||
|
|
||||||
|
@param BlockIoDevicePath Multi device path instances which need to check
|
||||||
|
@param HardDriveDevicePath A device path which starts with a hard drive media
|
||||||
|
device path.
|
||||||
|
|
||||||
|
@retval TRUE There is a matched device path instance.
|
||||||
|
@retval FALSE There is no matched device path instance.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmMatchPartitionDevicePathNode (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
|
||||||
|
IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Connect the specific Usb device which match the short form device path.
|
||||||
|
|
||||||
|
@param DevicePath A short-form device path that starts with the first
|
||||||
|
element being a USB WWID or a USB Class device
|
||||||
|
path
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER DevicePath is NULL pointer.
|
||||||
|
DevicePath is not a USB device path.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS Success to connect USB device
|
||||||
|
@return EFI_NOT_FOUND Fail to find handle for USB controller to connect.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmConnectUsbShortFormDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stop the hotkey processing.
|
||||||
|
|
||||||
|
@param Event Event pointer related to hotkey service.
|
||||||
|
@param Context Context pass to this function.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
BmStopHotkeyService (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the variable and report the error through status code upon failure.
|
||||||
|
|
||||||
|
@param VariableName A Null-terminated string that is the name of the vendor's variable.
|
||||||
|
Each VariableName is unique for each VendorGuid. VariableName must
|
||||||
|
contain 1 or more characters. If VariableName is an empty string,
|
||||||
|
then EFI_INVALID_PARAMETER is returned.
|
||||||
|
@param VendorGuid A unique identifier for the vendor.
|
||||||
|
@param Attributes Attributes bitmask to set for the variable.
|
||||||
|
@param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
|
||||||
|
or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
|
||||||
|
causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
|
||||||
|
set, then a SetVariable() call with a DataSize of zero will not cause any change to
|
||||||
|
the variable value (the timestamp associated with the variable may be updated however
|
||||||
|
even if no new data value is provided,see the description of the
|
||||||
|
EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
|
||||||
|
be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
|
||||||
|
@param Data The contents for the variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
|
||||||
|
defined by the Attributes.
|
||||||
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
|
||||||
|
DataSize exceeds the maximum allowed.
|
||||||
|
@retval EFI_INVALID_PARAMETER VariableName is an empty string.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
|
||||||
|
@retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question is read-only.
|
||||||
|
@retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
|
||||||
|
@retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS
|
||||||
|
being set, but the AuthInfo does NOT pass the validation check carried out by the firmware.
|
||||||
|
|
||||||
|
@retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
BmSetVariableAndReportStatusCodeOnError (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN VOID *Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function compares a device path data structure to that of all the nodes of a
|
||||||
|
second device path instance.
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@retval TRUE If the Single device path is contained within Multi device path.
|
||||||
|
@retval FALSE The Single device path is not match within Multi device path.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
BmMatchDevicePaths (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete the instance in Multi which matches partly with Single instance
|
||||||
|
|
||||||
|
@param Multi A pointer to a multi-instance device path data
|
||||||
|
structure.
|
||||||
|
@param Single A pointer to a single-instance device path data
|
||||||
|
structure.
|
||||||
|
|
||||||
|
@return This function will remove the device path instances in Multi which partly
|
||||||
|
match with the Single, and return the result device path. If there is no
|
||||||
|
remaining device path as a result, this function will return NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmDelPartMatchInstance (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Multi,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *Single
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Print the device path info.
|
||||||
|
|
||||||
|
@param DevicePath The device path need to print.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmPrintDp (
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert a single character to number.
|
||||||
|
It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
|
||||||
|
|
||||||
|
@param Char The input char which need to convert to int.
|
||||||
|
|
||||||
|
@return The converted 8-bit number or (UINTN) -1 if conversion failed.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
BmCharToUint (
|
||||||
|
IN CHAR16 Char
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the file buffer from the specified Load File instance.
|
||||||
|
|
||||||
|
@param LoadFileHandle The specified Load File instance.
|
||||||
|
@param FilePath The file path which will pass to LoadFile().
|
||||||
|
|
||||||
|
@return The full device path pointing to the load option buffer.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmExpandLoadFile (
|
||||||
|
IN EFI_HANDLE LoadFileHandle,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the RAM Disk device path created by LoadFile.
|
||||||
|
|
||||||
|
@param FilePath The source file path.
|
||||||
|
|
||||||
|
@return Callee-to-free RAM Disk device path
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmGetRamDiskDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroy the RAM Disk.
|
||||||
|
|
||||||
|
The destroy operation includes to call RamDisk.Unregister to
|
||||||
|
unregister the RAM DISK from RAM DISK driver, free the memory
|
||||||
|
allocated for the RAM Disk.
|
||||||
|
|
||||||
|
@param RamDiskDevicePath RAM Disk device path.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmDestroyRamDisk (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the next possible full path pointing to the load option.
|
||||||
|
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath The full path returned by the routine in last call.
|
||||||
|
Set to NULL in first call.
|
||||||
|
|
||||||
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmGetNextLoadOptionDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the next matched load option buffer.
|
||||||
|
The routine keeps calling BmGetNextLoadOptionDevicePath() until a valid
|
||||||
|
load option is read.
|
||||||
|
|
||||||
|
@param Type The load option type.
|
||||||
|
It's used to check whether the load option is valid.
|
||||||
|
When it's LoadOptionTypeMax, the routine only guarantees
|
||||||
|
the load option is a valid PE image but doesn't guarantee
|
||||||
|
the PE's subsystem type is valid.
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath Return the next full device path of the load option after
|
||||||
|
short-form device path expanding.
|
||||||
|
Caller is responsible to free it.
|
||||||
|
NULL to return the first matched full device path.
|
||||||
|
@param FileSize Return the load option size.
|
||||||
|
|
||||||
|
@return The load option buffer. Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
BmGetNextLoadOptionBuffer (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
|
OUT UINTN *FileSize
|
||||||
|
);
|
||||||
|
#endif // _INTERNAL_BM_H_
|
Reference in New Issue
Block a user