这次介绍一下用来取得系统上硬盘信息的 Protocol: EFI_DISK_INFO_PROTOCOL。
在\MdePkg\Include\Protocol\DiskInfo.h 有他的原型:
///
/// Forward declaration for EFI_DISK_INFO_PROTOCOL
///
typedef struct _EFI_DISK_INFO_PROTOCOL EFI_DISK_INFO_PROTOCOL;
///
/// The EFI_DISK_INFO_PROTOCOL provides controller specific information.
///
struct _EFI_DISK_INFO_PROTOCOL {
///
/// A GUID that defines the format of buffers for the other member functions
/// of this protocol.
///
EFI_GUID Interface;
///
/// Return the results of the Inquiry command to a drive in InquiryData. Data
/// format of Inquiry data is defined by the Interface GUID.
///
EFI_DISK_INFO_INQUIRY Inquiry;
///
/// Return the results of the Identify command to a drive in IdentifyData. Data
/// format of Identify data is defined by the Interface GUID.
///
EFI_DISK_INFO_IDENTIFY Identify;
///
/// Return the results of the Request Sense command to a drive in SenseData. Data
/// format of Sense data is defined by the Interface GUID.
///
EFI_DISK_INFO_SENSE_DATA SenseData;
///
/// Specific controller.
///
EFI_DISK_INFO_WHICH_IDE WhichIde;
};
更详细的介绍可以在 PI Specification 1.4 上找到。
对于不同类型的设备,比如 IDE 和 USB ,返回的数据格式是不同的。枚举到这个 PROTOCOL 之后需要检查EFI_GUID Interface 通过不同的GUID得知当前设备的类型。
下面先编写一个简单的 Demo,检查 GUID ,判断当前设备的类型:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/DiskInfo.h>
#include <Library/BaseMemoryLib.h>
extern EFI_BOOT_SERVICES *gBS;
extern EFI_HANDLE gImageHandle;
EFI_GUID gEfiDiskInfoProtocolGuid = { 0xD432A67F, 0x14DC, 0x484B,
{ 0xB3, 0xBB, 0x3F, 0x02, 0x91, 0x84, 0x93, 0x27 }};
EFI_GUID gEfiDiskInfoIdeInterfaceGuid = { 0x5E948FE3, 0x26D3, 0x42B5,
{ 0xAF, 0x17, 0x61, 0x02, 0x87, 0x18, 0x8D, 0xEC }};
EFI_GUID gEfiDiskInfoScsiInterfaceGuid = { 0x08F74BAA, 0xEA36, 0x41D9,
{ 0x95, 0x21, 0x21, 0xA7, 0x0F, 0x87, 0x80, 0xBC }};
EFI_GUID gEfiDiskInfoUsbInterfaceGuid = { 0xCB871572, 0xC11A, 0x47B5,
{ 0xB4, 0x92, 0x67, 0x5E, 0xAF, 0xA7, 0x77, 0x27 }};
EFI_GUID gEfiDiskInfoAhciInterfaceGuid = { 0x9e498932, 0x4abc, 0x45af,
{ 0xa3, 0x4d, 0x02, 0x47, 0x78, 0x7b, 0xe7, 0xc6 }};
EFI_GUID gEfiDiskInfoNvmeInterfaceGuid = { 0x3ab14680, 0x5d3f, 0x4a4d,
{ 0xbc, 0xdc, 0xcc, 0x38, 0x0, 0x18, 0xc7, 0xf7 }};
EFI_GUID gEfiDiskInfoUfsInterfaceGuid = { 0x4b3029cc, 0x6b98, 0x47fb,
{ 0xbc, 0x96, 0x76, 0xdc, 0xb8, 0x4, 0x41, 0xf0 }};
int
EFIAPI
main (
IN int Argc,
IN CHAR16 **Argv
)
{
EFI_STATUS Status;
UINTN HandleIndex, NumHandles;
EFI_HANDLE *ControllerHandle = NULL;
EFI_DISK_INFO_PROTOCOL *DiskInfoProtocol;
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiDiskInfoProtocolGuid,
NULL,
&NumHandles,
&ControllerHandle);
for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {
Status = gBS->OpenProtocol(
ControllerHandle[HandleIndex],
&gEfiDiskInfoProtocolGuid,
(VOID**)&DiskInfoProtocol,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR(Status)) {
continue;
}
Print(L"Device[%d] GUID: %g",
HandleIndex,
DiskInfoProtocol->Interface);
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoIdeInterfaceGuid)) {
Print(L" IDE HDD\n");
}
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoScsiInterfaceGuid)) {
Print(L" Scsi HDD\n");
}
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoUsbInterfaceGuid)) {
Print(L" USB HDD\n");
}
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoAhciInterfaceGuid)) {
Print(L" AHCI HDD\n");
}
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoNvmeInterfaceGuid)) {
Print(L" NVME HDD\n");
}
if (CompareGuid (
&DiskInfoProtocol->Interface,
&gEfiDiskInfoUfsInterfaceGuid)) {
Print(L" Ufs HDD\n");
}
}
return EFI_SUCCESS;
}
上述代码在UDK2014中编译通过,但是无法在 NT32环境下运行。于是在实体机KabyLake HDK 上实验, 板子上挂载了一个 SATA HDD 一个eMMC和两个USB Disk。运行结果如下:
可以看出,当前的SATA 是AHCI 模式。此外, eMMC 设备是无法被识别出来的,也许后面会扩展到这种设备吧。
完整的代码下载:
diskinfotest