Skip to content

Commit 3ffcd2f

Browse files
committed
uefi: Add integration test for PCI_ROOT_BRIDGE_IO_PROTOCOL
1 parent 895ae1f commit 3ffcd2f

File tree

3 files changed

+95
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)