基于UEFI的BIOS怎么识别不同设备(SataHdd、SataCdrom、USB、BMC)
参考:UEFI_SPEC
第一种方法:
SATA设备根据EFI_ATA_DEVICE_TYPE类型来细分
ATAPI接口是SCSI和IDE总线的结合产物。该接口使用IDE接口和协议机型ATA和SCSI总线命令传输,允许使用ATAPI控制所连接的SCSI设备。
1、EFI_ATA_PASS_THRU_PROTOCOL
提供允许将ATA命令发送到附加到ATA控制器上的ATA设备的服务。基于包的命令只能通过扩展SCSI协议发送到ATAPI设备。当ATA_PASS_THRU向ATA公开一个接口,EXT_SCSI_PASS_THRU负责为同一ATA控制器上的ATAPI设备公开基于数据包的命令接口。
Status =gBS->LocateHandleBuffer (ByProtocol,&gEfiAtaPassThruProtocolGuid,NULL,&NumberHandles,&AtaPassHandles);
用LocateHandleBuffer 定位支持gEfiAtaPassThruProtocolGuid的句柄。
2、循环遍历获得的句柄,获得支持gEfiAtaPassThruProtocolGuid的接口AtaPassProtocol
for (Index = 0; Index < NumberHandles; Index++) {Status = gBS->HandleProtocol (AtaPassHandles[Index],&gEfiAtaPassThruProtocolGuid,(VOID **) &AtaPassProtocol);if (Status == EFI_SUCCESS) {Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (AtaPassProtocol);Node = GetFirstNode (&Instance->DeviceList);while (!IsNull (&Instance->DeviceList, Node)) {ATADeviceInfo = ATA_ATAPI_DEVICE_INFO_FROM_THIS (Node);Node = GetNextNode (&Instance->DeviceList, Node);}
}
3、判断条件:区分SataHdd和SataCdrom:
SataHdd:ATADeviceInfo->Type == EfiIdeHarddisk
SataCdrom:ATADeviceInfo->Type == EfiIdeCdrom;
typedef enum {
EfiIdeCdrom, /* ATAPI CDROM /
EfiIdeHarddisk, / Hard Disk /
EfiPortMultiplier, / Port Multiplier */
EfiIdeUnknown
} EFI_ATA_DEVICE_TYPE;
EFI_ATA_DEVICE_TYPE对SATA的设备类型进行细分,Cdrom,和Harddisk都接的SATA口,使用ATA类型可以进一步划分。
第二种方法:分析设备路径类型
设备路径的区分通过EFI_DEVICE_PATH_PROTOCOL的Type和SubType的值进行区分
1、EFI_DEVICE_PATH_PROTOCOL.
设备路径用于定义指向设备的编程路径。设备路径的主要目的是允许一个应用程序,例如操作系统加载程序,来确定接口正在抽象的物理设备。
可用于任何设备句柄,以获取有关物理设备或逻辑设备的通用路径/位置信息。如果句柄在逻辑上没有映射到物理设备,则该句柄可能不一定支持设备路径协议。设备路径描述了该手柄所对应的设备的位置。设备路径的大小可以由组成设备路径的结构来确定。
typedef struct {UINT8 Type; ///< 0x01 Hardware Device Path.///< 0x02 ACPI Device Path.///< 0x03 Messaging Device Path.///< 0x04 Media Device Path.///< 0x05 BIOS Boot Specification Device Path.///< 0x7F End of Hardware Device Path.UINT8 SubType; ///< Varies by Type///< 0xFF End Entire Device Path, or///< 0x01 End This Instance of a Device Path and start a new///< Device Path.UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define///< type of data. Size of data is included in Length.} EFI_DEVICE_PATH_PROTOCOL;
0x01 Hardware Device Path:硬盘设备路径。
0x02 ACPI Device Path. ACPI设备路径,
0x03 Messaging Device Path. SCSI设备路径:
0x04 Media Device Path. 硬盘上的分区路径
0x05 BIOS Boot Specification Device Path. 指向引导旧的操作系统的设备路径
0x7F End of Hardware Device Path. 硬件设备路径的结束。
2、主要几种设备的类型举例
需要更多类型,应查看UEFI SPEC
2.1、PCI Device Path
Mnemonic | ByteOffset | Byte Length | Description |
---|---|---|---|
type | 0 | 1 | Type 1 – Hardware Device Path |
Sub-Type | 1 | 1 | Sub-Type 1 – PCI |
Length | 2 | 2 | Length of this structure is 6 bytes |
2.2、BMC Device Path | |||
Mnemonic | ByteOffset | Byte Length | Description |
-------- | ----- | ----- | ----- |
type | 0 | 1 | Type 1 – Hardware Device Path |
Sub-Type | 1 | 1 | Sub-Type 6 – BMC |
Length | 2 | 2 | Length of this structure in bytes. Length is 13 bytes |
2.3、ATAPI Device Path | |||
Mnemonic | ByteOffset | Byte Length | Description |
-------- | ----- | ----- | ----- |
type | 0 | 1 | Type 3 – Messaging Device Path |
Sub-Type | 1 | 1 | Sub-Type 6 – Sub-Type 1 – ATAPI |
Length | 2 | 2 | Length of this structure in bytes. Length is 13 bytes |
2.4、SCSI Device Path | |||
Mnemonic | ByteOffset | Byte Length | Description |
-------- | ----- | ----- | ----- |
type | 0 | 1 | Type 3 – Messaging Device Path |
Sub-Type | 1 | 1 | Sub-Type 6 – Sub-Type 2– SCSI |
Length | 2 | 2 | Length of this structure in bytes. Length is 8 bytes |
2.5、USB Device Paths | |||
Mnemonic | ByteOffset | Byte Length | Description |
-------- | ----- | ----- | ----- |
type | 0 | 1 | Type 3 – Messaging Device Path |
Sub-Type | 1 | 1 | Sub-Type 6 – Sub-Type 5– USB |
Length | 2 | 2 | Length of this structure in bytes. Length is 6 bytes |
2.6、 MAC Address Device Path | |||
Mnemonic | ByteOffset | Byte Length | Description |
-------- | ----- | ----- | ----- |
type | 0 | 1 | Type 3 – Messaging Device Path |
Sub-Type | 1 | 1 | Sub-Type 11 – MAC Address for a network interface |
Length | 2 | 2 | Length of this structure in bytes. Length is 37 bytes |
3、判断ClassCode的值
Status = gBS->LocateHandleBuffer(ByProtocol,&gEfiPciIoProtocolGuid,NULL,&HandleArrayCount,&HandleArray);if (EFI_ERROR(Status)) {return OCPPortNum;}for (Index2=0; Index2<HandleArrayCount; Index2++){Status = gBS->HandleProtocol(HandleArray[Index2],&gEfiPciIoProtocolGuid,(VOID **)&PciIo);Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint8,0x0B, //PCI_CLASSCODE_OFFSET1,&BaseClass);Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint8,0x0A, //PCI_CLASSCODE_OFFSET1,&SubClass);}if(BaseClass == 0x02){// 网卡}if((BaseClass == 0x01)&&((SubClass == 0x07)||(SubClass == 0x04)){// raid卡}