当前位置:网站首页>UEFI finding PCI devices
UEFI finding PCI devices
2022-06-11 06:28:00 【Miachen- birds in the air】
problem : In doing projects ,BIOS How to get PCI External card device information ?
1、 Use rootbridge location
1、 Get into OS see PCI equipment
[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 The first is segment, In turn bus device function
below 01.0 yes device and function
[01]、[02]、[03] yes rootport Below bus Number .
The basic idea : Circular scanning segment,bus ,device ,function, Determine whether there is a device on the composite address of the four elements ,XX:00:00:00 by PCI Bridge equipment , The others are PCI equipment .
2、PCI Root Bridge I/O Support
PCI Root Bridge I/O Protocol To pass PCI Host Bus Controller Produced PCI Root Brideg Provide a I/O abstract , One PCI The host bus controller is a hardware component , It allows access to a set of PCI equipment , They share a common PCII/O and PCI Memory resource pool .PCI Device drivers will not use this protocol directly . contrary , They will use the PCI Generated by bus driver I/O abstract , Only direct access to the entire PCI Bus drivers should use this protocol .EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL The interface provided in is used for memory 、I/O and PCI Configure the space to perform basic operations .
One PCI segment It's the most 256 Share PCI Configuration space PCI A collection of buses . Depending on the chipset , Single EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Can abstract out PCI Segment Part of , Or the whole PCI Segment. One PCI host bridge Can produce one or more PCI root bridges. When one PCI The main bridge produces multiple PCI root bridge when , There may be more than one PCI segments. One PCI root Bridge The controller includes a EFI_DEVICE_PATH_Protocol Instance and EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
The following figure shows a with PCI root bridge Of PCI host bus An example of . this PCI root bridge Produce a PCI Local bus , It can be included on the motherboard or PCI On slot PCI equipment 
3、 Code implementation
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 according to OS Next lspci Wiring obtained ,
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;
// To filter out USB equipment
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;
}
Reference resources OS Under the lspci result , It can correspond to
2、gEfiPciIoProtocolGuid location
BUS ,Device,Function , Can identify the network card device , But under the network card How many? port I can't recognize , port The functions of the plug-in network card are the same , Every port The mouth is bound gEfiPciIoProtocol, You can use gEfiPciIoProtocol distinguish . The network card type uses BaseClass == 2 Judge ,raid Card use ((BaseClass == 0x01)&& ((SubClass == 0x07)||(SubClass == 0x04))) Judge .
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;
}
···
边栏推荐
- 动态import
- Résoudre le problème de la durée inexacte du fichier audio AAC obtenu par ffmpeg
- EasyGBS接入的设备视频直播突然全部无法播放是为什么?数据库读写不够
- text-overflow失效
- Differences between FindIndex and indexof
- Squid agent
- 617. 合并二叉树
- Who is stronger, zip or 7-Zip, and how to choose?
- Sqoop installation tutorial
- FPGA面试题目笔记(三)——跨时钟域中握手信号同步的实现、任意分频、进制转换、RAM存储器等、原码反码和补码
猜你喜欢

不同VLAN间的通信

Matlab实现均值滤波与FPGA进行对比,并采用modelsim波形仿真

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

CCS安装编译器的方法

FPGA interview notes (III) -- implementation of handshake signal synchronization in cross clock domain, arbitrary frequency division, binary conversion, RAM memory, original code inversion and complem

FPGA设计中提高工作频率及降低功耗题目合集

Cenos7 builds redis-3.2.9 and integrates jedis

Markdown + typora + picgo experimental report template attached

C language war "minesweeping"

Vulnhub's breach1.0 range exercise
随机推荐
Communication between different VLANs
Why is it that the live video of the devices connected to easygbs suddenly cannot be played? Insufficient database read / write
QT socket setting connection timeout
QT socket设置连接超时时间
go的fmt包使用和字符串的格式化
Record the first data preprocessing process
Error code in ijkplayer
Graphsage paper reading
Invert an array with for
fatal: refusing to merge unrelated histories
FPGA面试题目笔记(三)——跨时钟域中握手信号同步的实现、任意分频、进制转换、RAM存储器等、原码反码和补码
021-MongoDB数据库从入门到放弃
The difference between call and apply and bind
Basic usage of MySQL
Sqoop installation tutorial
修复鼠标右键没有vscode快捷入口的问题
解决ffmpeg獲取AAC音頻文件duration不准
Why don't we have our own programming language?
Résoudre le problème de la durée inexacte du fichier audio AAC obtenu par ffmpeg
学好C语言从关键字开始