From 0fee261866dadcffb894b2256bfc048dd5df0e8a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 18 Dec 2025 12:15:23 -0700 Subject: [PATCH] Allow reading PCI ROM address and size --- drivers/pcid/src/driver_interface/mod.rs | 10 ++++++ drivers/pcid/src/main.rs | 40 ++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/pcid/src/driver_interface/mod.rs b/drivers/pcid/src/driver_interface/mod.rs index f7c93b51f8..10d725e8e7 100644 --- a/drivers/pcid/src/driver_interface/mod.rs +++ b/drivers/pcid/src/driver_interface/mod.rs @@ -88,6 +88,13 @@ impl From for PciAddress { } } +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +pub struct PciRom { + pub addr: u32, + pub size: u32, + pub enabled: bool, +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct PciFunction { /// Address of the PCI function. @@ -97,6 +104,9 @@ pub struct PciFunction { /// PCI Base Address Registers pub bars: [PciBar; 6], + /// PCI Option ROM + pub rom: Option, + /// Legacy IRQ line: It's the responsibility of pcid to make sure that it be mapped in either /// the I/O APIC or the 8259 PIC, so that the subdriver can map the interrupt vector directly. /// The vector to map is always this field, plus 32. diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs index 9991fe029c..d3375ff1ad 100644 --- a/drivers/pcid/src/main.rs +++ b/drivers/pcid/src/main.rs @@ -13,7 +13,7 @@ use pci_types::{ use redox_scheme::{RequestKind, SignalBehavior}; use crate::cfg_access::Pcie; -use pcid_interface::{FullDeviceId, LegacyInterruptLine, PciBar, PciFunction}; +use pcid_interface::{FullDeviceId, LegacyInterruptLine, PciBar, PciFunction, PciRom}; mod cfg_access; mod driver_handler; @@ -78,6 +78,41 @@ fn handle_parsed_header( debug!(" BAR{}", string); } + //TODO: submit to pci_types + let get_rom = |pci_address, offset| -> Option { + use pci_types::ConfigRegionAccess; + + const ROM_ENABLED: u32 = 1; + const ROM_ADDRESS_MASK: u32 = 0xfffff800; + + let data = unsafe { pcie.read(pci_address, offset) }; + let enabled = (data & ROM_ENABLED) == ROM_ENABLED; + let addr = data & ROM_ADDRESS_MASK; + + let size = unsafe { + pcie.write(pci_address, offset, ROM_ADDRESS_MASK | if enabled { ROM_ENABLED } else { 0 }); + let mut readback = pcie.read(pci_address, offset); + pcie.write(pci_address, offset, data); + + /* + * If the entire readback value is zero, the BAR is not implemented, so we return `None`. + */ + if readback == 0x0 { + return None; + } + + readback &= ROM_ADDRESS_MASK; + 1 << readback.trailing_zeros() + }; + + Some(PciRom { addr, size, enabled }) + }; + + let rom = get_rom(endpoint_header.header().address(), 0x30); + if let Some(rom) = rom { + debug!(" ROM={:08X}", rom.addr); + } + let capabilities = if endpoint_header.status(pcie).has_capability_list() { endpoint_header.capabilities(pcie).collect::>() } else { @@ -91,8 +126,9 @@ fn handle_parsed_header( let func = Func { inner: pcid_interface::PciFunction { - bars, addr: endpoint_header.header().address(), + bars, + rom, legacy_interrupt_line: None, // Will be filled in when enabling the device full_device_id: full_device_id.clone(), },