From 32c0944ba7c69356aecda6540f377d751f02af65 Mon Sep 17 00:00:00 2001 From: Markus Ebner Date: Fri, 21 Nov 2025 01:29:37 +0100 Subject: [PATCH 1/2] uefi: Fix broken bridge recursion in PCI enumeration --- uefi/src/proto/pci/enumeration.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/uefi/src/proto/pci/enumeration.rs b/uefi/src/proto/pci/enumeration.rs index 49395cabb..4564cc96f 100644 --- a/uefi/src/proto/pci/enumeration.rs +++ b/uefi/src/proto/pci/enumeration.rs @@ -37,10 +37,10 @@ struct PciRegister3 { #[allow(unused)] #[derive(Clone, Copy, Debug)] struct PciHeader1Register6 { - secondary_latency_timer: u8, - subordinate_bus: u8, - secondary_bus: u8, primary_bus: u8, + secondary_bus: u8, + subordinate_bus: u8, + secondary_latency_timer: u8, } /// Read the 4byte pci register with the given `addr` and cast it into the given structured representation. @@ -93,7 +93,8 @@ fn visit_function( } queue.insert(FullPciIoAddress::new(proto.segment_nr(), addr)); let (base_class, sub_class) = get_classes(proto, addr)?; - if base_class == 0x6 && sub_class == 0x4 && get_header_type(proto, addr)? == 0x01 { + let header_type = get_header_type(proto, addr)? & 0b01111111; + if base_class == 0x6 && sub_class == 0x4 && header_type == 0x01 { // This is a PCI-to-PCI bridge controller. The current `addr` is the address with which it's // mounted in the PCI tree we are currently traversing. Now we query its header, where // the bridge tells us a range of addresses [secondary;subordinate], with which the other From 677583a7f3267dabef4f4d38fc659913fcc723ee Mon Sep 17 00:00:00 2001 From: Markus Ebner Date: Fri, 21 Nov 2025 02:28:35 +0100 Subject: [PATCH 2/2] uefi: Change PciRootBridgeIo::enumerate() start only at first bus nr --- uefi/src/proto/pci/root_bridge.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/uefi/src/proto/pci/root_bridge.rs b/uefi/src/proto/pci/root_bridge.rs index 39e9e926e..c17975085 100644 --- a/uefi/src/proto/pci/root_bridge.rs +++ b/uefi/src/proto/pci/root_bridge.rs @@ -101,17 +101,18 @@ impl PciRootBridgeIo { use crate::proto::pci::enumeration; let mut devices = BTreeSet::new(); - for descriptor in self.configuration()? { - // In the descriptors we can query for the current root bridge, Bus entries contain ranges of valid - // bus addresses. These are starting points for the recursive scanning process performed in - // enumeration::enum_bus - if descriptor.resource_range_type == ResourceRangeType::Bus { - for bus in (descriptor.address_min as u8)..=(descriptor.address_max as u8) { - let addr = PciIoAddress::new(bus, 0, 0); - enumeration::visit_bus(self, addr, &mut devices)?; - } - } + // In the descriptors, the entry with range_type bus specifies the bus numbers that were + // allocated to devices below this root bridge. The first bus number in this range is + // the starting point. All subsequent numbers are reached via PCI bridge recursion during enumeration. + if let Some(descriptor) = self + .configuration()? + .iter() + .find(|d| d.resource_range_type == ResourceRangeType::Bus) + { + let addr = PciIoAddress::new(descriptor.address_min as u8, 0, 0); + enumeration::visit_bus(self, addr, &mut devices)?; } + Ok(devices) } }