Skip to content

Commit 43222e3

Browse files
authored
Merge pull request #1829 from seijikun/mr-pci-enumerate2
uefi: Fix broken bridge recursion in PCI enumeration
2 parents 039429b + 677583a commit 43222e3

File tree

2 files changed

+16
-14
lines changed

2 files changed

+16
-14
lines changed

uefi/src/proto/pci/enumeration.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ struct PciRegister3 {
3737
#[allow(unused)]
3838
#[derive(Clone, Copy, Debug)]
3939
struct PciHeader1Register6 {
40-
secondary_latency_timer: u8,
41-
subordinate_bus: u8,
42-
secondary_bus: u8,
4340
primary_bus: u8,
41+
secondary_bus: u8,
42+
subordinate_bus: u8,
43+
secondary_latency_timer: u8,
4444
}
4545

4646
/// Read the 4byte pci register with the given `addr` and cast it into the given structured representation.
@@ -93,7 +93,8 @@ fn visit_function(
9393
}
9494
queue.insert(FullPciIoAddress::new(proto.segment_nr(), addr));
9595
let (base_class, sub_class) = get_classes(proto, addr)?;
96-
if base_class == 0x6 && sub_class == 0x4 && get_header_type(proto, addr)? == 0x01 {
96+
let header_type = get_header_type(proto, addr)? & 0b01111111;
97+
if base_class == 0x6 && sub_class == 0x4 && header_type == 0x01 {
9798
// This is a PCI-to-PCI bridge controller. The current `addr` is the address with which it's
9899
// mounted in the PCI tree we are currently traversing. Now we query its header, where
99100
// the bridge tells us a range of addresses [secondary;subordinate], with which the other

uefi/src/proto/pci/root_bridge.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,18 @@ impl PciRootBridgeIo {
101101
use crate::proto::pci::enumeration;
102102

103103
let mut devices = BTreeSet::new();
104-
for descriptor in self.configuration()? {
105-
// In the descriptors we can query for the current root bridge, Bus entries contain ranges of valid
106-
// bus addresses. These are starting points for the recursive scanning process performed in
107-
// enumeration::enum_bus
108-
if descriptor.resource_range_type == ResourceRangeType::Bus {
109-
for bus in (descriptor.address_min as u8)..=(descriptor.address_max as u8) {
110-
let addr = PciIoAddress::new(bus, 0, 0);
111-
enumeration::visit_bus(self, addr, &mut devices)?;
112-
}
113-
}
104+
// In the descriptors, the entry with range_type bus specifies the bus numbers that were
105+
// allocated to devices below this root bridge. The first bus number in this range is
106+
// the starting point. All subsequent numbers are reached via PCI bridge recursion during enumeration.
107+
if let Some(descriptor) = self
108+
.configuration()?
109+
.iter()
110+
.find(|d| d.resource_range_type == ResourceRangeType::Bus)
111+
{
112+
let addr = PciIoAddress::new(descriptor.address_min as u8, 0, 0);
113+
enumeration::visit_bus(self, addr, &mut devices)?;
114114
}
115+
115116
Ok(devices)
116117
}
117118
}

0 commit comments

Comments
 (0)