Skip to content

Commit eb74040

Browse files
committed
uefi: Add integration test for PCI_ROOT_BRIDGE_IO_PROTOCOL
1 parent f8a8c23 commit eb74040

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

uefi-test-runner/src/proto/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub fn test() {
2020
loaded_image::test();
2121
media::test();
2222
network::test();
23+
pci::test();
2324
pi::test();
2425
rng::test();
2526
shell_params::test();
@@ -83,6 +84,7 @@ mod media;
8384
mod misc;
8485
mod network;
8586
mod nvme;
87+
mod pci;
8688
mod pi;
8789
mod rng;
8890
mod scsi;

uefi-test-runner/src/proto/pci/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
pub mod root_bridge;
4+
5+
pub fn test() {
6+
root_bridge::test();
7+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
use core::mem;
4+
use uefi::Handle;
5+
use uefi::boot::{OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, image_handle};
6+
use uefi::proto::ProtocolPointer;
7+
use uefi::proto::pci::PciIoAddress;
8+
use uefi::proto::pci::root_bridge::PciRootBridgeIo;
9+
10+
const RED_HAT_PCI_VENDOR_ID: u16 = 0x1AF4;
11+
const MASS_STORAGE_CTRL_CLASS_CODE: u8 = 0x1;
12+
const SATA_CTRL_SUBCLASS_CODE: u8 = 0x6;
13+
14+
const REG_SIZE: u8 = mem::size_of::<u32>() as u8;
15+
16+
pub fn test() {
17+
let pci_handles = uefi::boot::find_handles::<PciRootBridgeIo>().unwrap();
18+
19+
let mut red_hat_dev_cnt = 0;
20+
let mut mass_storage_ctrl_cnt = 0;
21+
let mut sata_ctrl_cnt = 0;
22+
23+
for pci_handle in pci_handles {
24+
let mut pci_proto = get_open_protocol::<PciRootBridgeIo>(pci_handle);
25+
26+
for bus in 0..=255 {
27+
for dev in 0..32 {
28+
for fun in 0..8 {
29+
let addr = PciIoAddress::new(bus, dev, fun);
30+
let Ok(reg0) = pci_proto.pci().read_one::<u32>(addr.with_register(0)) else {
31+
continue;
32+
};
33+
if reg0 == 0xFFFFFFFF {
34+
continue; // not a valid device
35+
}
36+
let reg1 = pci_proto
37+
.pci()
38+
.read_one::<u32>(addr.with_register(2 * REG_SIZE))
39+
.unwrap();
40+
41+
let vendor_id = (reg0 & 0xFFFF) as u16;
42+
let device_id = (reg0 >> 16) as u16;
43+
if vendor_id == RED_HAT_PCI_VENDOR_ID {
44+
red_hat_dev_cnt += 1;
45+
}
46+
47+
let class_code = (reg1 >> 24) as u8;
48+
let subclass_code = ((reg1 >> 16) & 0xFF) as u8;
49+
if class_code == MASS_STORAGE_CTRL_CLASS_CODE {
50+
mass_storage_ctrl_cnt += 1;
51+
52+
if subclass_code == SATA_CTRL_SUBCLASS_CODE {
53+
sata_ctrl_cnt += 1;
54+
}
55+
}
56+
57+
log::info!(
58+
"PCI Device: [{}, {}, {}]: vendor={:04X}, device={:04X}, class={:02X}, subclass={:02X}",
59+
bus,
60+
dev,
61+
fun,
62+
vendor_id,
63+
device_id,
64+
class_code,
65+
subclass_code
66+
);
67+
}
68+
}
69+
}
70+
}
71+
72+
assert!(red_hat_dev_cnt > 0);
73+
assert!(mass_storage_ctrl_cnt > 0);
74+
assert!(sata_ctrl_cnt > 0);
75+
}
76+
77+
fn get_open_protocol<P: ProtocolPointer + ?Sized>(handle: Handle) -> ScopedProtocol<P> {
78+
let open_opts = OpenProtocolParams {
79+
handle,
80+
agent: image_handle(),
81+
controller: None,
82+
};
83+
let open_attrs = OpenProtocolAttributes::GetProtocol;
84+
unsafe { uefi::boot::open_protocol(open_opts, open_attrs).unwrap() }
85+
}

0 commit comments

Comments
 (0)