硬盘是一种块设备,所以每个硬盘设备控制器都安装有一个BlockIo实例、一个BlockIo2实例,然后还安装了一个DiskIo实例、一个DiskIo2实例,这两者的区别就是BlockIo只能按块读写设备,而DiskIo可以从任意便宜出读写磁盘,并且可以读取任意字节数,BlockIo是EFI_BLOCK_IO_PROTOCOL的缩写,DiskIo是EFI_DISK_IO_PROTOCOL的缩写。
虽然BlockIo和DiskIo极大的方便了我们操作磁盘,但是其功能十分有限,通过BlockIo和DiskIo,我们只能对硬盘设备进行读、写、flush操作,如果相对硬盘进行更多的操作,则需要通过PassThrough向硬盘发送命令。
以获取NVME硬盘信息为例:
# define TEMP_POOL_SIZE 300
VOID
UpdateNvmePortInfo ()
{
EFI_STATUS Status;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
EFI_DISK_INFO_PROTOCOL *DiskInfo;
UINTN Index;
CHAR16 *UnicodeStr;
EFI_IDENTIFY_DATA *IdentifyDriveInfo;
NVME_ADMIN_CONTROLLER_DATA NvmeIdentifyControllerData;
//找出所有支持BlockIo的设备
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
//遍历所有支持BlockIo设备,获取他们全部的信息
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (HandleBuffer [Index], &gEfiDiskInfoProtocolGuid, (VOID **)&DiskInfo);
if (!EFI_ERROR (Status)) {
// if Nvme HDD devices
UnicodeStr = (CHAR16*)AllocateZeroPool (TEMP_POOL_SIZE);
IdentifyDriveInfo = (EFI_IDENTIFY_DATA*)AllocatePool (sizeof (EFI_IDENTIFY_DATA));
//通过compareGuid,定位NVME硬盘设备
if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoNvmeInterfaceGuid)) {
//获取NVME硬盘设备全部信息
Status = NvmeIdentifyController (HandleBuffer[Index], &NvmeIdentifyControllerData);
if (EFI_ERROR (Status)) {
continue;
}
//从信息中筛选出设备ModelName,显示在setup界面
NvmeIdentifyControllerData.Mn[40] = 0;
UnicodeSPrintAsciiFormat (UnicodeStr, TEMP_POOL_SIZE, "%a",(CHAR8 *)&NvmeIdentifyControllerData.Mn);
HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN(STR_NVME_DISK_INFO), UnicodeStr, NULL) ;
}
}
}
}
待写。。。。