当前位置:网站首页>UEFI查找PCI设备
UEFI查找PCI设备
2022-06-11 06:25:00 【miachen-空中飞鸟】
问题:在做项目中,BIOS如何获得PCI外插卡设备信息?
1、使用rootbridge 定位
1、进入OS查看PCI设备
[email protected]:~$ lspci -tv
+-[0004:00]-+-00.0 Ampere Computing, LLC Device e110
| +-01.0-[01]--
| +-05.0-[02]--
| +-06.0-[03]--
| +-07.0-[04]--
| \-08.0-[05]--
+-[0003:00]-+-00.0 Ampere Computing, LLC Device e110
| +-01.0-[01]----00.0 Renesas Technology Corp. uPD720201 USB 3.0 Host Controller
| +-03.0-[02]--
| +-05.0-[03]--
| \-07.0-[04]--
+-[0002:00]-+-00.0 Ampere Computing, LLC Device e110
| +-01.0-[01]--
| +-03.0-[02]--
| +-05.0-[03]--
| \-07.0-[04]--
+-[0001:00]-+-00.0 Ampere Computing, LLC Device e100
| \-01.0-[01]----00.0 Huawei Technologies Co., Ltd. Device 3714
\-[0000:00]-+-00.0 Ampere Computing, LLC Device e100
+-01.0-[01]--
\-03.0-[02]--
0b:00:00.0 第一个是segment,后面依次是bus device function
下面01.0是device和function
[01]、[02]、[03]是rootport下面的bus号。
基本思路:循环扫描segment,bus ,device ,function,判断四个元素合成地址上是否有设备,XX:00:00:00 为PCI桥设备,其它就是PCI设备。
2、PCI Root Bridge I/O Support
PCI Root Bridge I/O Protocol 给通过PCI Host Bus Controller 产生的PCI Root Brideg 提供一个I/O抽象, 一个PCI主机总线控制器是一个硬件组件,它允许访问一组PCI设备,它们共享一个公共的PCII/O和PCI内存资源池。PCI设备驱动程序将不会直接使用此协议。相反,他们将使用由PCI总线驱动程序产生的I/O抽象,只有需要直接访问整个PCI总线的驱动程序才应该使用此协议。EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL中提供的接口用于对内存、I/O和PCI配置空间执行基本操作。
一个PCI segment是最多256 个共享PCI配置空间的PCI 总线的集合。根据芯片组的不同,单个EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL可以抽象出PCI Segment的一部分,或整个PCI Segment.一个PCI host bridge可以产生一个或多个PCI root bridges。当一个PCI主桥产生多个PCI root bridge时,可能有多个PCI segments.一个PCI root Bridge控制器包括一个EFI_DEVICE_PATH_Protocol实例和EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
下图显示了具有一个具有PCI root bridge 的PCI host bus的示例。此PCI root bridge 产生一个PCI本地总线,它可以包含在主板或PCI插槽上的PCI设备
3、代码实现
UINTN
PciSoltEnumeratedDevice (
OUT KL_SET_SYSTEM_INFO_FOR_PCIE_CARD *KLpSetSystemInfo,
OUT KL_SET_PCIE_CARD_BDF_INFO *pPcieCardInfo
)
{
EFI_STATUS Status;
EFI_HANDLE *RbHandleBuffer;
UINTN RbHandleCount=0;
UINTN Index;
PCI_CFG_ADDR addr;
UINT32 buff = 0;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RbIoProtocol;
UINT8 PriBus;
UINT8 SecBus;
UINT16 Device;
UINT16 Function;
UINT16 SoltNum1 = 0;
UINT16 SoltNum2 = 0;
UINT16 PortNum = 0;
UINT32 PciVidDid ;
UINT32 SubPciVidDid ;
UINT16 VendorId = 0xFFFF;
UINT16 DeviceId = 0xFFFF;
UINT8 BaseClass;
UINT8 SubClass;
UINT8 CardType;
// Locate all PciIo protocol
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
&RbHandleCount,
&RbHandleBuffer );
if(EFI_ERROR(Status)){
DEBUG((DEBUG_ERROR,"ERROR Locating RbIo Protocols: Status:%r \n", Status));
return FALSE;
}
DEBUG((DEBUG_ERROR, "RbHandleCount:%d\n",RbHandleCount));
/* Loop through each root complex */
for (Index = 0 ; Index < RbHandleCount; Index ++) { // Handle Count
Status = gBS->HandleProtocol (
RbHandleBuffer[Index],
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **)&RbIoProtocol );
if(EFI_ERROR(Status)){
continue;
}
/* Loop through each root port */
//device/function根据OS下 lspci布线得到,
for (Device = 1; Device <= 8; Device++) {
for (Function = 0;Function <8; Function++){
addr.Addr.Bus = 0;
addr.Addr.Device = Device;
addr.Addr.Function = Function;
addr.Addr.Register = 0;
addr.Addr.ExtendedRegister = 0;
Status = RbIoProtocol->Pci.Read(RbIoProtocol, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)&buff);
if(EFI_ERROR(Status)){
DEBUG((DEBUG_ERROR,"RbIo Protocols Pci Read Failed - Status: %r\n", Status));
continue;
}
if (buff == 0xFFFFFFFF){
//DEBUG((DEBUG_ERROR,"Device Not Exist!\n"));
continue;
}
DEBUG((DEBUG_ERROR,"buff:0x%04x\n",buff));
addr.Addr.Register = PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET;
Status = RbIoProtocol->Pci.Read(RbIoProtocol, EfiPciWidthUint8, addr.ADDR, 1, (VOID*)&SecBus);
addr.Addr.Bus = (UINT8)SecBus;
addr.Addr.Device = 0;
addr.Addr.Function = 0;
addr.Addr.Register = 0;
addr.Addr.ExtendedRegister = 0;
DEBUG((EFI_D_ERROR, " PCIE SECONDARY_BUS:0x%04x\n",SecBus));
Status = RbIoProtocol->Pci.Read(RbIoProtocol, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)&PciVidDid);
if(EFI_ERROR(Status)){
DEBUG((DEBUG_ERROR,"RbIo Protocols Pci Read Failed - Status: %r,SoltNum1:%d\n", Status,SoltNum1));
continue;
}
VendorId = (UINT16)(PciVidDid & 0xFFFF);
DeviceId = (UINT16)(PciVidDid >> 16) & 0xFFFF;
//过滤掉USB 设备
if (((VendorId == 0x1912) && (DeviceId == 0x0014))||((VendorId == 0x1CC4) && (DeviceId == 0x0123))){
continue;
}
if (PciVidDid != 0xFFFFFFFF){
addr.Addr.Register = 0x0B;
Status = RbIoProtocol->Pci.Read(RbIoProtocol, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)&BaseClass);
if ( BaseClass == 0x02 ){
continue;
}
SoltNum2++;
addr.Addr.Register = PCI_SVID_OFFSET;
Status = RbIoProtocol->Pci.Read(RbIoProtocol, EfiPciWidthUint32, addr.ADDR, 1, (VOID*)&SubPciVidDid);
KLpSetSystemInfo->PcieCardInfo[SoltNum2].VIDSLOT = (UINT16)(PciVidDid & 0xFFFF);
KLpSetSystemInfo->PcieCardInfo[SoltNum2].DIDSLOT = (UINT16)(PciVidDid >> 16) & 0xFFFF;
KLpSetSystemInfo->PcieCardInfo[SoltNum2].SUBVID = (UINT16)(SubPciVidDid & 0xFFFF);
KLpSetSystemInfo->PcieCardInfo[SoltNum2].SUBDID = (UINT16)(SubPciVidDid >> 16) & 0xFFFF;
}
}
} // Handle Count
}
DEBUG((EFI_D_ERROR,"%a() DeviceExist,SoltNum=%d\n",__FUNCTION__, SoltNum1));
return SoltNum1;
}
参考OS下的lspci结果,可以对应上
2、gEfiPciIoProtocolGuid 定位
BUS ,Device,Function ,可以识别网卡设备,但是网卡下面的 几个port口识别不出, port口插网卡的功能是相同的,每个port口都绑定了gEfiPciIoProtocol,可使用gEfiPciIoProtocol识别。网卡类型使用BaseClass == 2判断,raid卡使用 ((BaseClass == 0x01)&& ((SubClass == 0x07)||(SubClass == 0x04)))判断。
UINTN
ReportEthernetPortDeviceInfoToBMC(
OUT SET_SYSTEM_BDF_INFO_FOR_NET_PORT_ROOT_BDF *pSetNetPortRootInfo
)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN HandleArrayCount;
EFI_HANDLE *HandleArray;
UINTN Index;
UINTN Index2;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 PortNum = 0;
UINT8 Segment;
UINT8 BusNum;
UINT8 DevNum;
UINT8 FunNum;
UINT8 CardType;
EFI_HANDLE HandleSlot;
EFI_PCI_IO_PROTOCOL *PciIoSlot;
UINT8 BaseClass;
UINT8 SubClass;
Status = gBS->LocateHandleBuffer(
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&HandleArrayCount,
&HandleArray
);
if (EFI_ERROR(Status)) {
return PortNum;
}
DEBUG((EFI_D_ERROR, "HandleArrayCount=%d\n",HandleArrayCount ));
for (Index2=0; Index2<HandleArrayCount; Index2++){
Status = gBS->HandleProtocol(
HandleArray[Index2],
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo
);
Status = PciIo->Pci.Read(
PciIo,
EfiPciIoWidthUint8,
0x0B, //PCI_CLASSCODE_OFFSET
1,
&BaseClass
);
Status = PciIo->Pci.Read(
PciIo,
EfiPciIoWidthUint8,
0x0A, //PCI_CLASSCODE_OFFSET
1,
&SubClass
);
// network card
if (BaseClass == 0x02){
CardType = 0;
}
//raid card
if((BaseClass == 0x01)&& ((SubClass == 0x07)||(SubClass == 0x04))){
CardType = 2;
}
//report net port data here
//net card
if ((CardType == 0) || (CardType == 2)) {
PciIo->GetLocation(
PciIo,
&Segment,
&BusNum,
&DevNum,
&FunNum);
DEBUG((EFI_D_ERROR, "Index2=%d net card: seg=0x%x bus=0x%x dev=0x%x fun=0x%x\n", Index2, Segment, BusNum, DevNum, FunNum));
pSetNetPortRootInfo->BDF_Info[PortNum].CardType = CardType;
pSetNetPortRootInfo->BDF_Info[PortNum].BusNum = BusNum;
pSetNetPortRootInfo->BDF_Info[PortNum].DeviceNum = DevNum;
pSetNetPortRootInfo->BDF_Info[PortNum].FunctionNum = FunNum;
pSetNetPortRootInfo->BDF_Info[PortNum].Segment = Segment;
pSetNetPortRootInfo->BDF_Info[PortNum].SlotNum = PortNum;
PortNum++;
}
}
return PortNum;
}
···
边栏推荐
- QT socket设置连接超时时间
- 关于parseInt()
- FIFO最小深度计算的题目合集
- Why don't we have our own programming language?
- MySQL implements over partition by (sorting the data in the group after grouping)
- Docker安装Mysql、Redis
- FPGA面试题目笔记(三)——跨时钟域中握手信号同步的实现、任意分频、进制转换、RAM存储器等、原码反码和补码
- FPGA面试题目笔记(四)—— 序列检测器、跨时钟域中的格雷码、乒乓操作、降低静动态损耗、定点化无损误差、恢复时间和移除时间
- Chapter 4 of machine learning [series] naive Bayesian model
- fatal: refusing to merge unrelated histories
猜你喜欢

Convert text label of dataset to digital label

Teach you to write word formula

Autojs, read one line, delete one line, and stop scripts other than your own

autojs,读取一行删除一行,停止自己外的脚本

Markdown + typora + picgo experimental report template attached

A multi classification model suitable for discrete value classification -- softmax regression

Jenkins different styles of project construction

Shandong University machine learning experiment 5 SVM

On cursor in MySQL

This point of arrow function
随机推荐
Deployment of Flink
Record the first data preprocessing process
Servlet
Quantitative understanding (Quantitative deep revolutionary networks for effective information: a whitepaper)
[TP5 online export picture generation excel detailed explanation example]
MongoDB安装
Stock K-line drawing
Notes sur les questions d'entrevue de la FPGA (IV) - - détecteur de séquence, Code gris dans le domaine de l'horloge croisée, opération de ping - pong, réduction de la perte statique et dynamique, err
Installing and using sublist3r in Kali
This point of arrow function
Sharing of personal common software and browser plug-ins
SQLI_ LIBS range construction and 1-10get injection practice
Vulnhub's breach1.0 range exercise
Detailed installation instructions for MySQL
How to use the markdown editor
CCF 2013 12-5 I‘m stuck
Eureka cluster setup
解决ffmpeg獲取AAC音頻文件duration不准
Super explanation
Review XML and JSON