EFI SCSI Driver Stack
UEFI下的SCSI的协议栈大致如下图所示:
最下面一层涉及到具体的硬件设备的访问,最上面一层之上就是其它驱动或者应用,它们可以直接调用Block/Disk IO Protocol等完成对硬盘等设备的访问。
主要涉及三个驱动(节选自《UEFI Spec》):
下面是一些说明:
1. SCSI Pass Thru Driver用来控制SCSI Host Controller,这个SCSI Host Controller包含一个或多个SCSI总线。
2. SCSI Pass Thru Driver会为每个SCSI总线创建Handle(称为SCSI Bus Controller Handle),这个Handle上还有Device Path Protocol,SCSI Pass Thru Protocol和Extended SCSI Pass Thre Protocol。
3. SCSI Bus Driver会处理SCSI Pass Thru Driver创建的SCSI Bus Controller Handle,并创建新的Handle(SCSI Device Handle),这个Handle用来表示SCSI总线扫描(扫描的动作也在这个SCSI Bus Driver中)时被扫到的硬盘,其上还有SCIS I/O Protocol和Device Path Protocol。
4. SCSI Device Driver用来处理某类SCSI Device Handle,并为这个Handle增加对应的某类SCSI Dvice实例(UEFI代码中就时SCSI_DISK_DEV),这个实例是对这类SCIS Device的I/O抽象,结构体如下:
typedef struct {
UINT32 Signature;
EFI_HANDLE Handle;
EFI_BLOCK_IO_PROTOCOL BlkIo;
EFI_BLOCK_IO2_PROTOCOL BlkIo2;
EFI_BLOCK_IO_MEDIA BlkIoMedia;
EFI_ERASE_BLOCK_PROTOCOL EraseBlock;
EFI_SCSI_IO_PROTOCOL *ScsiIo;
UINT8 DeviceType;
BOOLEAN FixedDevice;
UINT16 Reserved;
EFI_SCSI_SENSE_DATA *SenseData;
UINTN SenseDataNumber;
EFI_SCSI_INQUIRY_DATA InquiryData;
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
EFI_DISK_INFO_PROTOCOL DiskInfo;
//
// The following fields are only valid for ATAPI/SATA device
//
UINT32 Channel;
UINT32 Device;
ATAPI_IDENTIFY_DATA IdentifyData;
//
// Scsi UNMAP command parameters information
//
SCSI_UNMAP_PARAM_INFO UnmapInfo;
BOOLEAN BlockLimitsVpdSupported;
//
// The flag indicates if 16-byte command can be used
//
BOOLEAN Cdb16Byte;
//
// The queue for asynchronous task requests
//
LIST_ENTRY AsyncTaskQueue;
} SCSI_DISK_DEV;
5. 在上述Protocol之上的时Block IO (2) Protocol和Disk IO (2) Protocol,是普通的驱动或者应用会调用的接口;BIockIo和DiskIo都有两个版本,一个是普通版本另一个是扩展版本,这里以普通版本举例,下面是它们的接口:
Block IO Protocol:
///
/// This protocol provides control over block devices.
///
struct _EFI_BLOCK_IO_PROTOCOL {
///
/// The revision to which the block IO interface adheres. All future
/// revisions must be backwards compatible. If a future version is not
/// back wards compatible, it is not the same GUID.
///
UINT64 Revision;
///
/// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
///
EFI_BLOCK_IO_MEDIA *Media;
EFI_BLOCK_RESET Reset;
EFI_BLOCK_READ ReadBlocks;
EFI_BLOCK_WRITE WriteBlocks;
EFI_BLOCK_FLUSH FlushBlocks;
};
Disk IO Protocol:
///
/// This protocol is used to abstract Block I/O interfaces.
///
struct _EFI_DISK_IO_PROTOCOL {
///
/// The revision to which the disk I/O interface adheres. All future
/// revisions must be backwards compatible. If a future version is not
/// backwards compatible, it is not the same GUID.
///
UINT64 Revision;
EFI_DISK_READ ReadDisk;
EFI_DISK_WRITE WriteDisk;
};
两者的差异在《UEFI Spec》中有说明:
Block IO Protocol:
This protocol is used to abstract mass storage devices to allow code running in the EFI boot services environment to access them without specific knowledge of the type of device or controller that manages the device. Functions are defined to read and write data at a block level from mass storage devices as well as to manage such devices in the EFI boot services environment.
Disk IO Protocol:
This protocol is used to abstract the block accesses of the Block I/O protocol to a more general offset-length protocol. The firmware is responsible for adding this protocol to any Block I/O interface that appears in the system that does not already have a Disk I/O protocol. File systems and other disk access code utilize the Disk I/O protocol.
简单的来说,Block IO Protocol更底层,Disk IO Protocol是Block IO Protocol的进一步抽象,我们要访问磁盘类存储设备的话应该使用Disk IO Protocol。