Files
RedBear-OS/local/patches/base/P2-pcid-cfg-access.patch
T
vasilito 65acab85bb Split base cumulative patch and add relibc AIO stubs, KDE recipes
Base patch extraction (8 topic-grouped patches from the 17k-line monolith):
- P2-ps2d-improvements: PS/2 controller flush/retry, mouse state machine, named producers
- P2-storage-error-handling: AHCI/IDE/NVMe/VirtIO unwrap/expect removal
- P2-usb-pm-and-drivers: suspend/resume, SCSI enablement, staged port fallback
- P2-network-error-handling: e1000/ixgbe/rtl8139/rtl8168d/virtio-net error propagation
- P2-pcid-cfg-access: PCI config I/O port and ECAM graceful fallbacks
- P2-ihdad-hda-stream: InputStream support, public stream types, Debug derives
- P2-init-acpid-wiring: acpid weak dependency on drivers/hwd/pcid-spawner
- P2-misc-daemon-fixes: audiod/usbhidd/zerod graceful degradation

relibc P3-aio.patch: synchronous POSIX AIO fallback (aio_read, aio_write,
aio_error, aio_return, aio_cancel, aio_suspend, aio_fsync, lio_listio)
for Qt6 QIODevice compatibility. 36 patches total in relibc recipe.

KDE recipes: breeze (widget style, decorations disabled), kde-cli-tools
(kioclient, kreadconfig, etc., kdesu disabled).
2026-04-25 19:10:00 +01:00

170 lines
7.8 KiB
Diff

# P2-pcid-cfg-access.patch
#
# PCI config access error handling: replace unwrap()/expect()/assert!() with
# proper error returns and graceful fallbacks in PCI configuration space access
# (both I/O port fallback and ECAM/DTB paths).
#
# Covers:
# - pcid/cfg_access/fallback.rs: I/O port rights error logging, offset overflow returns
# - pcid/cfg_access/mod.rs: DTB property access with proper error propagation,
# bus-range validation, interrupt-map phandle/property fallbacks
#
diff --git a/drivers/pcid/src/cfg_access/fallback.rs b/drivers/pcid/src/cfg_access/fallback.rs
index 671d17f7..ea8f69f8 100644
--- a/drivers/pcid/src/cfg_access/fallback.rs
+++ b/drivers/pcid/src/cfg_access/fallback.rs
@@ -33,7 +33,12 @@ impl Pci {
"PCI: couldn't find or access PCIe extended configuration, \
and thus falling back to PCI 3.0 io ports"
);
- common::acquire_port_io_rights().expect("pcid: failed to get IO port rights");
+ common::acquire_port_io_rights()
+ .map_err(|err| {
+ log::error!("pcid: failed to get IO port rights: {err}");
+ err
+ })
+ .expect("pcid: IO port rights required for PCI 3.0 fallback");
}
});
}
@@ -61,8 +66,9 @@ impl ConfigRegionAccess for Pci {
Self::set_iopl();
- let offset =
- u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space");
+ let Ok(offset) = u8::try_from(offset) else {
+ return 0xFFFFFFFF;
+ };
let address = Self::address(address, offset);
Pio::<u32>::new(0xCF8).write(address);
@@ -74,8 +80,9 @@ impl ConfigRegionAccess for Pci {
Self::set_iopl();
- let offset =
- u8::try_from(offset).expect("offset too large for PCI 3.0 configuration space");
+ let Ok(offset) = u8::try_from(offset) else {
+ return;
+ };
let address = Self::address(address, offset);
Pio::<u32>::new(0xCF8).write(address);
diff --git a/drivers/pcid/src/cfg_access/mod.rs b/drivers/pcid/src/cfg_access/mod.rs
index c2552448..0fe215a6 100644
--- a/drivers/pcid/src/cfg_access/mod.rs
+++ b/drivers/pcid/src/cfg_access/mod.rs
@@ -38,42 +38,57 @@ fn locate_ecam_dtb<T>(
)
})?;
- let address = node.reg().unwrap().next().unwrap().starting_address as u64;
+ let mut reg = node.reg().ok_or_else(|| {
+ io::Error::new(io::ErrorKind::NotFound, "pci-host-ecam-generic missing 'reg' property")
+ })?;
+ let address = reg.next().ok_or_else(|| {
+ io::Error::new(io::ErrorKind::NotFound, "pci-host-ecam-generic 'reg' has no entries")
+ })?.starting_address as u64;
- let bus_range = node.property("bus-range").unwrap();
- assert_eq!(bus_range.value.len(), 8);
- let start_bus = u32::from_be_bytes(<[u8; 4]>::try_from(&bus_range.value[0..4]).unwrap());
- let end_bus = u32::from_be_bytes(<[u8; 4]>::try_from(&bus_range.value[4..8]).unwrap());
+ let bus_range = node.property("bus-range").ok_or_else(|| {
+ io::Error::new(io::ErrorKind::NotFound, "pci-host-ecam-generic missing 'bus-range' property")
+ })?;
+ if bus_range.value.len() != 8 {
+ return Err(io::Error::new(io::ErrorKind::InvalidData, "pci-host-ecam-generic 'bus-range' not 8 bytes"));
+ }
+ let start_bus = u32::from_be_bytes(<[u8; 4]>::try_from(&bus_range.value[0..4]).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "bus-range start parse failed"))?);
+ let end_bus = u32::from_be_bytes(<[u8; 4]>::try_from(&bus_range.value[4..8]).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "bus-range end parse failed"))?);
- // address-cells == 3, size-cells == 2, interrupt-cells == 1
- let mut interrupt_map_data = node
- .property("interrupt-map")
- .unwrap()
+ let interrupt_map_prop = node.property("interrupt-map").ok_or_else(|| {
+ io::Error::new(io::ErrorKind::NotFound, "pci-host-ecam-generic missing 'interrupt-map' property")
+ })?;
+ let mut interrupt_map_data = interrupt_map_prop
.value
.chunks_exact(4)
- .map(|x| u32::from_be_bytes(<[u8; 4]>::try_from(x).unwrap()));
+ .map(|x| u32::from_be_bytes(<[u8; 4]>::try_from(x).unwrap_or([0, 0, 0, 0])));
let mut interrupt_map = Vec::<InterruptMap>::new();
while let Ok([addr1, addr2, addr3, int1, phandle]) = interrupt_map_data.next_chunk::<5>() {
- let parent = dt.find_phandle(phandle).unwrap();
- let parent_address_cells = u32::from_be_bytes(
- parent.property("#address-cells").unwrap().value[..4]
- .try_into()
- .unwrap(),
- );
+ let Some(parent) = dt.find_phandle(phandle) else {
+ log::warn!("pcid: DTB interrupt-map references phandle {phandle} not found, skipping");
+ continue;
+ };
+ let parent_address_cells = match parent.property("#address-cells") {
+ Some(prop) => u32::from_be_bytes(
+ prop.value[..4]
+ .try_into()
+ .unwrap_or([0, 0, 0, 0]),
+ ),
+ None => 0,
+ };
match parent_address_cells {
0 => {}
1 => {
- assert_eq!(interrupt_map_data.next().unwrap(), 0);
+ let _ = interrupt_map_data.next();
}
2 => {
- assert_eq!(interrupt_map_data.next_chunk::<2>().unwrap(), [0, 0]);
+ let _ = interrupt_map_data.next_chunk::<2>();
}
3 => {
- assert_eq!(interrupt_map_data.next_chunk::<3>().unwrap(), [0, 0, 0]);
+ let _ = interrupt_map_data.next_chunk::<3>();
}
_ => break,
};
- let parent_interrupt_cells = parent.interrupt_cells().unwrap();
+ let parent_interrupt_cells = parent.interrupt_cells().unwrap_or(1);
let parent_interrupt = match parent_interrupt_cells {
1 if let Some(a) = interrupt_map_data.next() => [a, 0, 0],
2 if let Ok([a, b]) = interrupt_map_data.next_chunk::<2>() => [a, b, 0],
@@ -94,8 +109,8 @@ fn locate_ecam_dtb<T>(
let mut cells = interrupt_mask_node
.value
.chunks_exact(4)
- .map(|x| u32::from_be_bytes(<[u8; 4]>::try_from(x).unwrap()));
- cells.next_chunk::<4>().unwrap().to_owned()
+ .map(|x| u32::from_be_bytes(<[u8; 4]>::try_from(x).unwrap_or([0, 0, 0, 0])));
+ cells.next_chunk::<4>().unwrap_or([u32::MAX, u32::MAX, u32::MAX, u32::MAX]).to_owned()
} else {
[u32::MAX, u32::MAX, u32::MAX, u32::MAX]
};
@@ -104,8 +119,8 @@ fn locate_ecam_dtb<T>(
PcieAllocs(&[PcieAlloc {
base_addr: address,
seg_group_num: 0,
- start_bus: start_bus.try_into().unwrap(),
- end_bus: end_bus.try_into().unwrap(),
+ start_bus: start_bus.try_into().map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "start_bus overflow"))?,
+ end_bus: end_bus.try_into().map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "end_bus overflow"))?,
_rsvd: [0; 4],
}]),
interrupt_map,
@@ -165,7 +180,10 @@ impl Mcfg {
// crashing. `as_encoded_bytes()` returns some superset
// of ASCII, so directly comparing it with an ASCII name
// is fine.
- let table_filename = table_path.file_name().unwrap().as_encoded_bytes();
+ let table_filename = match table_path.file_name() {
+ Some(name) => name.as_encoded_bytes(),
+ None => continue,
+ };
if table_filename.get(0..4) == Some(&MCFG_NAME) {
let bytes = fs::read(table_path)?.into_boxed_slice();
match Mcfg::parse(&*bytes) {