From 40ba2caaf63e567abc2b4dae532436f7e68d3550 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Wed, 20 May 2026 13:57:47 +0300 Subject: [PATCH] base: Add missing P35-P43 boot-hardening patches Graceful init patches for fbcond, graphics scheme, smolnetd, vesad, PCI interrupt allocation, BAR probing, common init, inputd fallback, and dhcpd hard dependency ordering. --- .../base/P35-fbcond-fbbootlogd-init.patch | 12 + .../P36-graphics-scheme-graceful-init.patch | 106 +++++++++ .../base/P37-smolnetd-ready-after-init.patch | 10 + .../base/P38-vesad-eventqueue-deadlock.patch | 28 +++ ...i-allocate-interrupt-vector-graceful.patch | 217 ++++++++++++++++++ local/patches/base/P40-bar-rs-graceful.patch | 195 ++++++++++++++++ .../base/P41-common-init-graceful.patch | 176 ++++++++++++++ .../base/P42-inputd-graceful-fallback.patch | 87 +++++++ .../base/P43-dhcpd-requires-hard-dep.patch | 14 ++ 9 files changed, 845 insertions(+) create mode 100644 local/patches/base/P35-fbcond-fbbootlogd-init.patch create mode 100644 local/patches/base/P36-graphics-scheme-graceful-init.patch create mode 100644 local/patches/base/P37-smolnetd-ready-after-init.patch create mode 100644 local/patches/base/P38-vesad-eventqueue-deadlock.patch create mode 100644 local/patches/base/P39-pci-allocate-interrupt-vector-graceful.patch create mode 100644 local/patches/base/P40-bar-rs-graceful.patch create mode 100644 local/patches/base/P41-common-init-graceful.patch create mode 100644 local/patches/base/P42-inputd-graceful-fallback.patch create mode 100644 local/patches/base/P43-dhcpd-requires-hard-dep.patch diff --git a/local/patches/base/P35-fbcond-fbbootlogd-init.patch b/local/patches/base/P35-fbcond-fbbootlogd-init.patch new file mode 100644 index 0000000000..183250ceea --- /dev/null +++ b/local/patches/base/P35-fbcond-fbbootlogd-init.patch @@ -0,0 +1,12 @@ +--- a/drivers/graphics/fbbootlogd/Cargo.toml ++++ b/drivers/graphics/fbbootlogd/Cargo.toml +@@ -15,0 +16 @@ scheme-utils = { path = "../../../scheme-utils" } ++common = { path = "../../common" } +--- a/drivers/graphics/fbbootlogd/src/main.rs ++++ b/drivers/graphics/fbbootlogd/src/main.rs +@@ -23,0 +24 @@ fn main() { ++ common::init(); +--- a/drivers/graphics/fbcond/src/main.rs ++++ b/drivers/graphics/fbcond/src/main.rs +@@ -18,0 +19 @@ fn main() { ++ common::init(); diff --git a/local/patches/base/P36-graphics-scheme-graceful-init.patch b/local/patches/base/P36-graphics-scheme-graceful-init.patch new file mode 100644 index 0000000000..ab7403296e --- /dev/null +++ b/local/patches/base/P36-graphics-scheme-graceful-init.patch @@ -0,0 +1,106 @@ +diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs +index eab0be9c..b6683686 100644 +--- a/drivers/graphics/driver-graphics/src/lib.rs ++++ b/drivers/graphics/driver-graphics/src/lib.rs +@@ -138 +138 @@ impl GraphicsScheme { +- pub fn new(mut adapter: T, scheme_name: String, early: bool) -> Self { ++ pub fn new(mut adapter: T, scheme_name: String, early: bool) -> io::Result { +@@ -140 +140,6 @@ impl GraphicsScheme { +- let socket = Socket::nonblock().expect("failed to create graphics scheme"); ++ let socket = Socket::nonblock().map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to create graphics scheme socket: {e}"), ++ ) ++ })?; +@@ -143,2 +148,6 @@ impl GraphicsScheme { +- File::open("/scheme/debug/disable-graphical-debug") +- .expect("vesad: Failed to open /scheme/debug/disable-graphical-debug"), ++ File::open("/scheme/debug/disable-graphical-debug").map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to open /scheme/debug/disable-graphical-debug: {e}"), ++ ) ++ })?, +@@ -164,3 +173,12 @@ impl GraphicsScheme { +- let cap_id = inner.scheme_root().expect("failed to get this scheme root"); +- register_scheme_inner(&inner.socket, &inner.scheme_name, cap_id) +- .expect("failed to register graphics scheme root"); ++ let cap_id = inner.scheme_root().map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to get scheme root: {e}"), ++ ) ++ })?; ++ register_scheme_inner(&inner.socket, &inner.scheme_name, cap_id).map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to register graphics scheme root: {e}"), ++ ) ++ })?; +@@ -169 +187,6 @@ impl GraphicsScheme { +- DisplayHandle::new_early(&inner.scheme_name).unwrap() ++ DisplayHandle::new_early(&inner.scheme_name).map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to create early display handle: {e}"), ++ ) ++ })? +@@ -171 +194,6 @@ impl GraphicsScheme { +- DisplayHandle::new(&inner.scheme_name).unwrap() ++ DisplayHandle::new(&inner.scheme_name).map_err(|e| { ++ io::Error::new( ++ io::ErrorKind::Other, ++ format!("failed to create display handle: {e}"), ++ ) ++ })? +@@ -174 +202 @@ impl GraphicsScheme { +- Self { ++ Ok(Self { +@@ -178 +206 @@ impl GraphicsScheme { +- } ++ }) +diff --git a/drivers/graphics/ihdgd/src/main.rs b/drivers/graphics/ihdgd/src/main.rs +index a8b6cc60..990706c2 100644 +--- a/drivers/graphics/ihdgd/src/main.rs ++++ b/drivers/graphics/ihdgd/src/main.rs +@@ -43 +43,8 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { +- let mut scheme = GraphicsScheme::new(device, format!("display.ihdg.{}", name), false); ++ let mut scheme = match GraphicsScheme::new(device, format!("display.ihdg.{}", name), false) { ++ Ok(s) => s, ++ Err(e) => { ++ eprintln!("ihdgd: failed to create GraphicsScheme: {} — exiting", e); ++ daemon.ready(); ++ std::process::exit(0); ++ } ++ }; +diff --git a/drivers/graphics/vesad/src/main.rs b/drivers/graphics/vesad/src/main.rs +index 5e9526fe..acbcb3fa 100644 +--- a/drivers/graphics/vesad/src/main.rs ++++ b/drivers/graphics/vesad/src/main.rs +@@ -137,2 +137,8 @@ fn daemon(daemon: daemon::Daemon) -> ! { +- let mut scheme = +- GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true); ++ let mut scheme = match GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true) { ++ Ok(s) => s, ++ Err(e) => { ++ eprintln!("vesad: failed to create GraphicsScheme: {} — exiting", e); ++ daemon.ready(); ++ std::process::exit(0); ++ } ++ }; +diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs +index 22a985ee..96d8f964 100644 +--- a/drivers/graphics/virtio-gpud/src/scheme.rs ++++ b/drivers/graphics/virtio-gpud/src/scheme.rs +@@ -1,0 +2 @@ use std::fmt; ++use std::io; +@@ -511 +512 @@ impl<'a> GpuScheme { +- ) -> Result>, Error> { ++ ) -> io::Result>> { +@@ -522 +523 @@ impl<'a> GpuScheme { +- Ok(GraphicsScheme::new( ++ GraphicsScheme::new( +@@ -526 +527 @@ impl<'a> GpuScheme { +- )) ++ ) diff --git a/local/patches/base/P37-smolnetd-ready-after-init.patch b/local/patches/base/P37-smolnetd-ready-after-init.patch new file mode 100644 index 0000000000..2c68551959 --- /dev/null +++ b/local/patches/base/P37-smolnetd-ready-after-init.patch @@ -0,0 +1,10 @@ +diff --git a/netstack/src/main.rs b/netstack/src/main.rs +index b18f3226..0e4c1486 100644 +--- a/netstack/src/main.rs ++++ b/netstack/src/main.rs +@@ -103,2 +102,0 @@ fn run(daemon: daemon::Daemon) -> Result<()> { +- daemon.ready(); +- +@@ -160,0 +159,2 @@ fn run(daemon: daemon::Daemon) -> Result<()> { ++ daemon.ready(); ++ diff --git a/local/patches/base/P38-vesad-eventqueue-deadlock.patch b/local/patches/base/P38-vesad-eventqueue-deadlock.patch new file mode 100644 index 0000000000..a3e147d213 --- /dev/null +++ b/local/patches/base/P38-vesad-eventqueue-deadlock.patch @@ -0,0 +1,28 @@ +diff --git a/drivers/graphics/vesad/src/main.rs b/drivers/graphics/vesad/src/main.rs +index acbcb3fa..6f55913b 100644 +--- a/drivers/graphics/vesad/src/main.rs ++++ b/drivers/graphics/vesad/src/main.rs +@@ -137,9 +136,0 @@ fn daemon(daemon: daemon::Daemon) -> ! { +- let mut scheme = match GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true) { +- Ok(s) => s, +- Err(e) => { +- eprintln!("vesad: failed to create GraphicsScheme: {} — exiting", e); +- daemon.ready(); +- std::process::exit(0); +- } +- }; +- +@@ -152,0 +144,2 @@ fn daemon(daemon: daemon::Daemon) -> ! { ++ // EventQueue MUST be created before GraphicsScheme::new to avoid a deadlock with initnsmgr. ++ // See ihdgd fix (P0-driver-api-migration-fixes) for the same issue. +@@ -160,0 +154,10 @@ fn daemon(daemon: daemon::Daemon) -> ! { ++ ++ let mut scheme = match GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true) { ++ Ok(s) => s, ++ Err(e) => { ++ eprintln!("vesad: failed to create GraphicsScheme: {} — exiting", e); ++ daemon.ready(); ++ std::process::exit(0); ++ } ++ }; ++ diff --git a/local/patches/base/P39-pci-allocate-interrupt-vector-graceful.patch b/local/patches/base/P39-pci-allocate-interrupt-vector-graceful.patch new file mode 100644 index 0000000000..4b81db5f88 --- /dev/null +++ b/local/patches/base/P39-pci-allocate-interrupt-vector-graceful.patch @@ -0,0 +1,217 @@ +diff --git a/drivers/audio/ihdad/src/main.rs b/drivers/audio/ihdad/src/main.rs +index a9315902..75981cd9 100755 +--- a/drivers/audio/ihdad/src/main.rs ++++ b/drivers/audio/ihdad/src/main.rs +@@ -40,7 +40,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + + let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + +- let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdad"); ++ let irq_file = match pci_allocate_interrupt_vector(&mut pcid_handle, "ihdad") { ++ Some(iv) => iv, ++ None => { ++ log::error!("ihdad: no interrupt vector available, exiting"); ++ std::process::exit(1); ++ } ++ }; + + { + let vend_prod: u32 = ((pci_config.func.full_device_id.vendor_id as u32) << 16) +diff --git a/drivers/graphics/ihdgd/src/main.rs b/drivers/graphics/ihdgd/src/main.rs +index 990706c2..4aa21caa 100644 +--- a/drivers/graphics/ihdgd/src/main.rs ++++ b/drivers/graphics/ihdgd/src/main.rs +@@ -32,7 +32,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + let device = Device::new(&mut pcid_handle, &pci_config.func) + .expect("ihdgd: failed to initialize device"); + +- let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdgd"); ++ let irq_file = match pci_allocate_interrupt_vector(&mut pcid_handle, "ihdgd") { ++ Some(iv) => iv, ++ None => { ++ log::error!("ihdgd: no interrupt vector available, exiting"); ++ std::process::exit(1); ++ } ++ }; + + // Needs to be before GraphicsScheme::new to avoid a deadlock due to initnsmgr blocking on + // /scheme/event as it is already blocked on opening /scheme/display.ihdg.*. +diff --git a/drivers/net/rtl8139d/src/main.rs b/drivers/net/rtl8139d/src/main.rs +index d470e814..e372feda 100644 +--- a/drivers/net/rtl8139d/src/main.rs ++++ b/drivers/net/rtl8139d/src/main.rs +@@ -57,7 +57,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + + let bar = map_bar(&mut pcid_handle); + +- let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8139d"); ++ let irq_file = match pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8139d") { ++ Some(iv) => iv, ++ None => { ++ log::error!("rtl8139d: no interrupt vector available, exiting"); ++ std::process::exit(1); ++ } ++ }; + + let mut scheme = NetworkScheme::new( + move || unsafe { +diff --git a/drivers/net/rtl8168d/src/main.rs b/drivers/net/rtl8168d/src/main.rs +index 06d9ff58..29ebf799 100644 +--- a/drivers/net/rtl8168d/src/main.rs ++++ b/drivers/net/rtl8168d/src/main.rs +@@ -57,7 +57,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + + let bar = map_bar(&mut pcid_handle); + +- let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8168d"); ++ let irq_file = match pci_allocate_interrupt_vector(&mut pcid_handle, "rtl8168d") { ++ Some(iv) => iv, ++ None => { ++ log::error!("rtl8168d: no interrupt vector available, exiting"); ++ std::process::exit(1); ++ } ++ }; + + let mut scheme = NetworkScheme::new( + move || unsafe { +diff --git a/drivers/pcid/src/driver_interface/irq_helpers.rs b/drivers/pcid/src/driver_interface/irq_helpers.rs +index 39b0b048..f62cc055 100644 +--- a/drivers/pcid/src/driver_interface/irq_helpers.rs ++++ b/drivers/pcid/src/driver_interface/irq_helpers.rs +@@ -24,11 +24,13 @@ pub fn read_bsp_apic_id() -> io::Result { + buffer[0], buffer[1], buffer[2], buffer[3], + ])) + } else { +- panic!( +- "`/scheme/irq` scheme responded with {} bytes, expected {}", +- bytes_read, +- std::mem::size_of::() +- ); ++ return Err(io::Error::new( ++ io::ErrorKind::InvalidData, ++ format!( ++ "`/scheme/irq/bsp` responded with {} bytes, expected 4 or 8", ++ bytes_read ++ ), ++ )); + }) + .or(Err(io::Error::new( + io::ErrorKind::InvalidData, +@@ -83,7 +85,9 @@ pub fn allocate_aligned_interrupt_vectors( + alignment: NonZeroU8, + count: u8, + ) -> io::Result)>> { +- let cpu_id = u8::try_from(cpu_id).expect("usize cpu ids not implemented yet"); ++ let cpu_id = u8::try_from(cpu_id).map_err(|_| { ++ io::Error::new(io::ErrorKind::InvalidInput, "cpu_id does not fit in u8") ++ })?; + if count == 0 { + return Ok(None); + } +@@ -298,7 +302,7 @@ impl InterruptVector { + pub fn pci_allocate_interrupt_vector( + pcid_handle: &mut crate::driver_interface::PciFunctionHandle, + driver: &str, +-) -> InterruptVector { ++) -> Option { + let features = pcid_handle.fetch_all_features(); + + let has_msi = features.iter().any(|feature| feature.is_msi()); +@@ -307,7 +311,10 @@ pub fn pci_allocate_interrupt_vector( + if has_msix { + let msix_info = match pcid_handle.feature_info(super::PciFeature::MsiX) { + super::PciFeatureInfo::MsiX(msix) => msix, +- _ => unreachable!(), ++ _ => { ++ log::warn!("{driver}: MSI-X feature info mismatch, falling back"); ++ return None; ++ } + }; + let mut info = unsafe { msix_info.map_and_mask_all(pcid_handle) }; + +@@ -327,11 +334,11 @@ pub fn pci_allocate_interrupt_vector( + + pcid_handle.enable_feature(crate::driver_interface::PciFeature::MsiX); + +- return InterruptVector { ++ return Some(InterruptVector { + irq_handle, + vector: 0, + kind: InterruptVectorKind::MsiX { table_entry: entry }, +- }; ++ }); + } + log::warn!("{driver}: MSI-X vector allocation failed, falling back"); + // fall through to MSI +@@ -339,25 +346,26 @@ pub fn pci_allocate_interrupt_vector( + + if has_msi { + if let Some(irq_handle) = allocate_first_msi_interrupt_on_bsp(pcid_handle) { +- return InterruptVector { ++ return Some(InterruptVector { + irq_handle, + vector: 0, + kind: InterruptVectorKind::Msi, +- }; ++ }); + } + log::warn!("{driver}: MSI allocation failed, falling back to legacy"); + } + + if let Some(irq) = pcid_handle.config().func.legacy_interrupt_line { + // INTx# pin based interrupts. +- return InterruptVector { ++ return Some(InterruptVector { + irq_handle: irq.irq_handle(driver), + vector: 0, + kind: InterruptVectorKind::Legacy, +- }; ++ }); + } + +- panic!("{driver}: no interrupts supported at all") ++ log::warn!("{driver}: no interrupts supported at all"); ++ None + } + + // FIXME support MSI on non-x86 systems +@@ -365,15 +373,16 @@ pub fn pci_allocate_interrupt_vector( + pub fn pci_allocate_interrupt_vector( + pcid_handle: &mut crate::driver_interface::PciFunctionHandle, + driver: &str, +-) -> InterruptVector { ++) -> Option { + if let Some(irq) = pcid_handle.config().func.legacy_interrupt_line { + // INTx# pin based interrupts. +- InterruptVector { ++ Some(InterruptVector { + irq_handle: irq.irq_handle(driver), + vector: 0, + kind: InterruptVectorKind::Legacy, +- } ++ }) + } else { +- panic!("{driver}: no interrupts supported at all") ++ log::warn!("{driver}: no interrupts supported at all"); ++ None + } + } +diff --git a/drivers/storage/nvmed/src/main.rs b/drivers/storage/nvmed/src/main.rs +index beb1b689..59887186 100644 +--- a/drivers/storage/nvmed/src/main.rs ++++ b/drivers/storage/nvmed/src/main.rs +@@ -77,7 +77,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + + let address = unsafe { pcid_handle.map_bar(0).ptr }; + +- let interrupt_vector = irq_helpers::pci_allocate_interrupt_vector(&mut pcid_handle, "nvmed"); ++ let interrupt_vector = match irq_helpers::pci_allocate_interrupt_vector(&mut pcid_handle, "nvmed") { ++ Some(iv) => iv, ++ None => { ++ log::error!("nvmed: no interrupt vector available, exiting"); ++ std::process::exit(1); ++ } ++ }; + let iv = interrupt_vector.vector(); + let irq_handle = interrupt_vector.irq_handle().try_clone().unwrap(); + diff --git a/local/patches/base/P40-bar-rs-graceful.patch b/local/patches/base/P40-bar-rs-graceful.patch new file mode 100644 index 0000000000..9927517e24 --- /dev/null +++ b/local/patches/base/P40-bar-rs-graceful.patch @@ -0,0 +1,195 @@ +diff --git a/drivers/audio/ac97d/src/main.rs b/drivers/audio/ac97d/src/main.rs +index 641e3ef2..5878bf2d 100644 +--- a/drivers/audio/ac97d/src/main.rs ++++ b/drivers/audio/ac97d/src/main.rs +@@ -22,8 +22,20 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { + let mut name = pci_config.func.name(); + name.push_str("_ac97"); + +- let bar0 = pci_config.func.bars[0].expect_port(); +- let bar1 = pci_config.func.bars[1].expect_port(); ++ let bar0 = match pci_config.func.bars[0].try_port() { ++ Some(port) => port, ++ None => { ++ eprintln!("ac97d: BAR 0 is not a port BAR"); ++ std::process::exit(1); ++ } ++ }; ++ let bar1 = match pci_config.func.bars[1].try_port() { ++ Some(port) => port, ++ None => { ++ eprintln!("ac97d: BAR 1 is not a port BAR"); ++ std::process::exit(1); ++ } ++ }; + + let irq = pci_config + .func +diff --git a/drivers/graphics/ihdgd/src/device/mod.rs b/drivers/graphics/ihdgd/src/device/mod.rs +index ced9dd56..0423c617 100644 +--- a/drivers/graphics/ihdgd/src/device/mod.rs ++++ b/drivers/graphics/ihdgd/src/device/mod.rs +@@ -246,7 +246,7 @@ impl Device { + }; + + let gttmm = { +- let (phys, size) = func.bars[0].expect_mem(); ++ let (phys, size) = func.bars[0].try_mem().ok_or_else(|| Error::new(ENODEV))?; + Arc::new(MmioRegion::new( + phys, + size, +@@ -255,7 +255,7 @@ impl Device { + }; + log::info!("GTTMM {:X?}", gttmm); + let gm = { +- let (phys, size) = func.bars[2].expect_mem(); ++ let (phys, size) = func.bars[2].try_mem().ok_or_else(|| Error::new(ENODEV))?; + MmioRegion::new(phys, size, common::MemoryType::WriteCombining)? + }; + log::info!("GM {:X?}", gm); +diff --git a/drivers/pcid/src/driver_interface/bar.rs b/drivers/pcid/src/driver_interface/bar.rs +index b2c1d35b..dea0dce4 100644 +--- a/drivers/pcid/src/driver_interface/bar.rs ++++ b/drivers/pcid/src/driver_interface/bar.rs +@@ -29,27 +29,22 @@ impl PciBar { + } + } + +- pub fn expect_port(&self) -> u16 { ++ pub fn try_port(&self) -> Option { + match *self { +- PciBar::Port(port) => port, +- PciBar::Memory32 { .. } | PciBar::Memory64 { .. } => { +- panic!("expected port BAR, found memory BAR"); +- } +- PciBar::None => panic!("expected BAR to exist"), ++ PciBar::Port(port) => Some(port), ++ _ => None, + } + } + +- pub fn expect_mem(&self) -> (usize, usize) { ++ pub fn try_mem(&self) -> Option<(usize, usize)> { + match *self { +- PciBar::Memory32 { addr, size } => (addr as usize, size as usize), +- PciBar::Memory64 { addr, size } => ( +- addr.try_into() +- .expect("conversion from 64bit BAR to usize failed"), +- size.try_into() +- .expect("conversion from 64bit BAR size to usize failed"), +- ), +- PciBar::Port(_) => panic!("expected memory BAR, found port BAR"), +- PciBar::None => panic!("expected BAR to exist"), ++ PciBar::Memory32 { addr, size } => Some((addr as usize, size as usize)), ++ PciBar::Memory64 { addr, size } => { ++ let addr_usize = addr.try_into().ok()?; ++ let size_usize = size.try_into().ok()?; ++ Some((addr_usize, size_usize)) ++ } ++ _ => None, + } + } + } +diff --git a/drivers/pcid/src/driver_interface/mod.rs b/drivers/pcid/src/driver_interface/mod.rs +index 7cecaa56..8776dd4a 100644 +--- a/drivers/pcid/src/driver_interface/mod.rs ++++ b/drivers/pcid/src/driver_interface/mod.rs +@@ -457,7 +457,13 @@ impl PciFunctionHandle { + if let Some(mapped_bar) = mapped_bar { + mapped_bar + } else { +- let (bar, bar_size) = self.config.func.bars[bir as usize].expect_mem(); ++ let (bar, bar_size) = match self.config.func.bars[bir as usize].try_mem() { ++ Some(bar) => bar, ++ None => { ++ log::error!("pcid: BAR {bir} is not a memory BAR"); ++ process::exit(1); ++ } ++ }; + + let ptr = match unsafe { + common::physmap( +diff --git a/drivers/pcid/src/driver_interface/msi.rs b/drivers/pcid/src/driver_interface/msi.rs +index 0ca68ec5..e7e3f082 100644 +--- a/drivers/pcid/src/driver_interface/msi.rs ++++ b/drivers/pcid/src/driver_interface/msi.rs +@@ -80,8 +80,20 @@ impl MsixInfo { + let pba_offset = self.pba_offset as usize; + let pba_min_length = table_size.div_ceil(8); + +- let (_, table_bar_size) = bars[self.table_bar as usize].expect_mem(); +- let (_, pba_bar_size) = bars[self.pba_bar as usize].expect_mem(); ++ let (_, table_bar_size) = match bars[self.table_bar as usize].try_mem() { ++ Some(bar) => bar, ++ None => { ++ log::error!("MSI-X table BAR {} is not a memory BAR", self.table_bar); ++ return; ++ } ++ }; ++ let (_, pba_bar_size) = match bars[self.pba_bar as usize].try_mem() { ++ Some(bar) => bar, ++ None => { ++ log::error!("MSI-X PBA BAR {} is not a memory BAR", self.pba_bar); ++ return; ++ } ++ }; + + // Ensure that the table and PBA are within the BAR. + +diff --git a/drivers/storage/ided/src/main.rs b/drivers/storage/ided/src/main.rs +index 4197217d..9615710b 100644 +--- a/drivers/storage/ided/src/main.rs ++++ b/drivers/storage/ided/src/main.rs +@@ -43,7 +43,13 @@ fn daemon(daemon: daemon::Daemon, pcid_handle: PciFunctionHandle) -> ! { + // Get controller DMA capable + let dma = pci_config.func.full_device_id.interface & 0x80 != 0; + +- let busmaster_base = pci_config.func.bars[4].expect_port(); ++ let busmaster_base = match pci_config.func.bars[4].try_port() { ++ Some(port) => port, ++ None => { ++ log::error!("ided: BAR 4 is not a port BAR"); ++ std::process::exit(1); ++ } ++ }; + let (primary, primary_irq) = if pci_config.func.full_device_id.interface & 1 != 0 { + panic!("TODO: IDE primary channel is PCI native"); + } else { +diff --git a/drivers/vboxd/src/main.rs b/drivers/vboxd/src/main.rs +index bcb9bb15..52328e79 100644 +--- a/drivers/vboxd/src/main.rs ++++ b/drivers/vboxd/src/main.rs +@@ -199,7 +199,13 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { + let mut name = pci_config.func.name(); + name.push_str("_vbox"); + +- let bar0 = pci_config.func.bars[0].expect_port(); ++ let bar0 = match pci_config.func.bars[0].try_port() { ++ Some(port) => port, ++ None => { ++ eprintln!("vboxd: BAR 0 is not a port BAR"); ++ std::process::exit(1); ++ } ++ }; + + let irq = pci_config + .func +diff --git a/drivers/virtio-core/src/probe.rs b/drivers/virtio-core/src/probe.rs +index 5631ef67..06f0ba1a 100644 +--- a/drivers/virtio-core/src/probe.rs ++++ b/drivers/virtio-core/src/probe.rs +@@ -55,7 +55,13 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result continue, + } + +- let (addr, _) = pci_config.func.bars[capability.bar as usize].expect_mem(); ++ let (addr, _) = match pci_config.func.bars[capability.bar as usize].try_mem() { ++ Some(bar) => bar, ++ None => { ++ log::warn!("virtio-core: BAR {} is not a memory BAR, skipping capability", capability.bar); ++ continue; ++ } ++ }; + + let address = unsafe { + let addr = addr + capability.offset as usize; diff --git a/local/patches/base/P41-common-init-graceful.patch b/local/patches/base/P41-common-init-graceful.patch new file mode 100644 index 0000000000..909b5172df --- /dev/null +++ b/local/patches/base/P41-common-init-graceful.patch @@ -0,0 +1,176 @@ +diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs +index b05102f6..a9d47e09 100644 +--- a/drivers/acpid/src/main.rs ++++ b/drivers/acpid/src/main.rs +@@ -204,6 +204,6 @@ fn daemon(daemon: daemon::Daemon) -> ! { + } + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("acpid: failed to initialize common: {err}"); std::process::exit(1); } + daemon::Daemon::new(daemon); + } +diff --git a/drivers/common/src/lib.rs b/drivers/common/src/lib.rs +index b6661e3a..a55014b9 100644 +--- a/drivers/common/src/lib.rs ++++ b/drivers/common/src/lib.rs +@@ -29,22 +29,13 @@ use std::sync::OnceLock; + static MEMORY_ROOT_FD: OnceLock = OnceLock::new(); + + /// Initializes a file descriptor to be used as the root memory for a driver. +-/// +-/// # Panics +-/// +-/// This function will panic if: +-/// - `libredox` is unable to open a file descriptor. +-/// - The memory root file descriptor has already been set (this function has already been called). +-pub fn init() { +- if MEMORY_ROOT_FD +- .set( +- libredox::Fd::open("/scheme/memory/scheme-root", 0, 0) +- .expect("drivers common: failed to open memory root fd"), +- ) +- .is_err() +- { +- panic!("drivers common: failed to set memory root fd"); +- } ++pub fn init() -> std::io::Result<()> { ++ let fd = libredox::Fd::open("/scheme/memory/scheme-root", 0, 0) ++ .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, format!("failed to open memory root fd: {err}")))?; ++ MEMORY_ROOT_FD ++ .set(fd) ++ .map_err(|_| std::io::Error::new(std::io::ErrorKind::AlreadyExists, "memory root fd already initialized"))?; ++ Ok(()) + } + + /// Gets the memory root file descriptor. +diff --git a/drivers/gpio/intel-gpiod/src/main.rs b/drivers/gpio/intel-gpiod/src/main.rs +index aa651713..e9671068 100644 +--- a/drivers/gpio/intel-gpiod/src/main.rs ++++ b/drivers/gpio/intel-gpiod/src/main.rs +@@ -95,7 +95,7 @@ fn daemon_runner(daemon: daemon::Daemon) -> ! { + } + + fn daemon_main(daemon: daemon::Daemon) -> Result<()> { +- common::init(); ++ common::init().map_err(|err| anyhow::anyhow!("failed to initialize common: {err}"))?; + + let controllers = + discover_controllers(SUPPORTED_IDS).context("failed to discover Intel GPIO controllers")?; +diff --git a/drivers/graphics/fbbootlogd/src/main.rs b/drivers/graphics/fbbootlogd/src/main.rs +index 055e1db6..b8ad2294 100644 +--- a/drivers/graphics/fbbootlogd/src/main.rs ++++ b/drivers/graphics/fbbootlogd/src/main.rs +@@ -21,7 +21,7 @@ use crate::scheme::FbbootlogScheme; + mod scheme; + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("fbbootlogd: failed to initialize common: {err}"); std::process::exit(1); } + daemon::SchemeDaemon::new(daemon); + } + fn daemon(daemon: daemon::SchemeDaemon) -> ! { +diff --git a/drivers/graphics/fbcond/src/main.rs b/drivers/graphics/fbcond/src/main.rs +index 2e428353..003527ba 100644 +--- a/drivers/graphics/fbcond/src/main.rs ++++ b/drivers/graphics/fbcond/src/main.rs +@@ -16,7 +16,7 @@ mod scheme; + mod text; + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("fbcond: failed to initialize common: {err}"); std::process::exit(1); } + daemon::SchemeDaemon::new(daemon); + } + fn daemon(daemon: daemon::SchemeDaemon) -> ! { +diff --git a/drivers/graphics/vesad/src/main.rs b/drivers/graphics/vesad/src/main.rs +index 6f55913b..5fee9041 100644 +--- a/drivers/graphics/vesad/src/main.rs ++++ b/drivers/graphics/vesad/src/main.rs +@@ -12,7 +12,7 @@ use crate::scheme::{FbAdapter, FrameBuffer}; + mod scheme; + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("vesad: failed to initialize common: {err}"); std::process::exit(1); } + daemon::Daemon::new(daemon); + } + fn daemon(daemon: daemon::Daemon) -> ! { +diff --git a/drivers/i2c/dw-acpi-i2cd/src/main.rs b/drivers/i2c/dw-acpi-i2cd/src/main.rs +index 796d0ed3..f3491103 100644 +--- a/drivers/i2c/dw-acpi-i2cd/src/main.rs ++++ b/drivers/i2c/dw-acpi-i2cd/src/main.rs +@@ -80,7 +80,7 @@ fn daemon_runner(daemon: daemon::Daemon) -> ! { + } + + fn daemon_main(daemon: daemon::Daemon) -> Result<()> { +- common::init(); ++ common::init().map_err(|err| anyhow::anyhow!("failed to initialize common: {err}"))?; + + let controllers = discover_controllers(SUPPORTED_IDS) + .context("failed to discover DesignWare ACPI I2C controllers")?; +diff --git a/drivers/i2c/intel-lpss-i2cd/src/main.rs b/drivers/i2c/intel-lpss-i2cd/src/main.rs +index 7b29d737..e651610b 100644 +--- a/drivers/i2c/intel-lpss-i2cd/src/main.rs ++++ b/drivers/i2c/intel-lpss-i2cd/src/main.rs +@@ -80,7 +80,7 @@ fn daemon_runner(daemon: daemon::Daemon) -> ! { + } + + fn daemon_main(daemon: daemon::Daemon) -> Result<()> { +- common::init(); ++ common::init().map_err(|err| anyhow::anyhow!("failed to initialize common: {err}"))?; + + let controllers = discover_controllers(SUPPORTED_IDS) + .context("failed to discover Intel LPSS ACPI I2C controllers")?; +diff --git a/drivers/pcid/src/driver_interface/mod.rs b/drivers/pcid/src/driver_interface/mod.rs +index 8776dd4a..3b6a98a1 100644 +--- a/drivers/pcid/src/driver_interface/mod.rs ++++ b/drivers/pcid/src/driver_interface/mod.rs +@@ -491,7 +491,7 @@ impl PciFunctionHandle { + + pub fn pci_daemon !>(f: F) -> ! { + Daemon::new(|daemon| { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("pci_daemon: failed to initialize common: {err}"); std::process::exit(1); } + let pcid_handle = PciFunctionHandle::connect_default(); + f(daemon, pcid_handle) + }) +diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs +index bda473e4..e844249f 100644 +--- a/drivers/pcid/src/main.rs ++++ b/drivers/pcid/src/main.rs +@@ -245,7 +245,7 @@ fn enable_function( + } + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("pcid: failed to initialize common: {err}"); std::process::exit(1); } + daemon::Daemon::new(daemon); + } + +diff --git a/drivers/usb/usbctl/src/main.rs b/drivers/usb/usbctl/src/main.rs +index 9b5773d9..51a63f75 100644 +--- a/drivers/usb/usbctl/src/main.rs ++++ b/drivers/usb/usbctl/src/main.rs +@@ -2,7 +2,7 @@ use clap::{Arg, Command}; + use xhcid_interface::{PortId, XhciClientHandle}; + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("usbctl: failed to initialize common: {err}"); std::process::exit(1); } + let matches = Command::new("usbctl") + .arg( + Arg::new("SCHEME") +diff --git a/drivers/usb/usbhubd/src/main.rs b/drivers/usb/usbhubd/src/main.rs +index 2c8b9876..7e69842a 100644 +--- a/drivers/usb/usbhubd/src/main.rs ++++ b/drivers/usb/usbhubd/src/main.rs +@@ -6,7 +6,7 @@ use xhcid_interface::{ + }; + + fn main() { +- common::init(); ++ if let Err(err) = common::init() { eprintln!("usbhubd: failed to initialize common: {err}"); std::process::exit(1); } + let mut args = env::args().skip(1); + + const USAGE: &'static str = "usbhubd "; diff --git a/local/patches/base/P42-inputd-graceful-fallback.patch b/local/patches/base/P42-inputd-graceful-fallback.patch new file mode 100644 index 0000000000..d2816c7e8f --- /dev/null +++ b/local/patches/base/P42-inputd-graceful-fallback.patch @@ -0,0 +1,87 @@ +diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs +index b6683686..cd064ae6 100644 +--- a/drivers/graphics/driver-graphics/src/lib.rs ++++ b/drivers/graphics/driver-graphics/src/lib.rs +@@ -133 +133 @@ pub struct GraphicsScheme { +- inputd_handle: DisplayHandle, ++ inputd_handle: Option, +@@ -187,6 +187 @@ impl GraphicsScheme { +- DisplayHandle::new_early(&inner.scheme_name).map_err(|e| { +- io::Error::new( +- io::ErrorKind::Other, +- format!("failed to create early display handle: {e}"), +- ) +- })? ++ DisplayHandle::new_early(&inner.scheme_name) +@@ -194,6 +189,13 @@ impl GraphicsScheme { +- DisplayHandle::new(&inner.scheme_name).map_err(|e| { +- io::Error::new( +- io::ErrorKind::Other, +- format!("failed to create display handle: {e}"), +- ) +- })? ++ DisplayHandle::new(&inner.scheme_name) ++ }; ++ ++ let inputd_handle = match display_handle { ++ Ok(handle) => Some(handle), ++ Err(err) => { ++ log::warn!( ++ "{}: display input handle unavailable ({}), continuing without VT input", ++ inner.scheme_name, ++ err ++ ); ++ None ++ } +@@ -204 +206 @@ impl GraphicsScheme { +- inputd_handle: display_handle, ++ inputd_handle, +@@ -213,2 +215,2 @@ impl GraphicsScheme { +- pub fn inputd_event_handle(&self) -> BorrowedFd<'_> { +- self.inputd_handle.inner() ++ pub fn inputd_event_handle(&self) -> Option> { ++ self.inputd_handle.as_ref().map(|h| h.inner()) +@@ -238,2 +240,5 @@ impl GraphicsScheme { +- while let Some(vt_event) = self +- .inputd_handle ++ let inputd_handle = match self.inputd_handle.as_mut() { ++ Some(h) => h, ++ None => return, ++ }; ++ while let Some(vt_event) = inputd_handle + +diff --git a/drivers/graphics/ihdgd/src/main.rs b/drivers/graphics/ihdgd/src/main.rs +index 4aa21caa..964510f5 100644 +--- a/drivers/graphics/ihdgd/src/main.rs ++++ b/drivers/graphics/ihdgd/src/main.rs +@@ -65,0 +66 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ if let Some(inputd_fd) = scheme.inputd_event_handle() { +@@ -68 +69 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { +- scheme.inputd_event_handle().as_raw_fd() as usize, ++ inputd_fd.as_raw_fd() as usize, +@@ -72,0 +74 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { ++ } + +diff --git a/drivers/graphics/vesad/src/main.rs b/drivers/graphics/vesad/src/main.rs +index 6f55913b..c19629aa 100644 +--- a/drivers/graphics/vesad/src/main.rs ++++ b/drivers/graphics/vesad/src/main.rs +@@ -163,0 +164 @@ fn daemon(daemon: daemon::Daemon) -> ! { ++ if let Some(inputd_fd) = scheme.inputd_event_handle() { +@@ -165 +166 @@ fn daemon(daemon: daemon::Daemon) -> ! { +- scheme.inputd_event_handle().as_raw_fd() as usize, ++ inputd_fd.as_raw_fd() as usize, +@@ -172,0 +174 @@ fn daemon(daemon: daemon::Daemon) -> ! { ++ } + +diff --git a/drivers/graphics/virtio-gpud/src/main.rs b/drivers/graphics/virtio-gpud/src/main.rs +index b27f4c56..3aa41c74 100644 +--- a/drivers/graphics/virtio-gpud/src/main.rs ++++ b/drivers/graphics/virtio-gpud/src/main.rs +@@ -552,0 +553 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow: ++ if let Some(inputd_fd) = scheme.inputd_event_handle() { +@@ -555 +556 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow: +- scheme.inputd_event_handle().as_raw_fd() as usize, ++ inputd_fd.as_raw_fd() as usize, +@@ -559,0 +561 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow: ++ } diff --git a/local/patches/base/P43-dhcpd-requires-hard-dep.patch b/local/patches/base/P43-dhcpd-requires-hard-dep.patch new file mode 100644 index 0000000000..39614855a5 --- /dev/null +++ b/local/patches/base/P43-dhcpd-requires-hard-dep.patch @@ -0,0 +1,14 @@ +diff --git a/init.d/10_dhcpd.service b/init.d/10_dhcpd.service +index daba3bd1..494fb536 100644 +--- a/init.d/10_dhcpd.service ++++ b/init.d/10_dhcpd.service +@@ -3 +3 @@ description = "Configure network using DHCP" +-requires_weak = [ ++requires = [ +diff --git a/init.initfs.d/61_dhcpd.service b/init.initfs.d/61_dhcpd.service +index 37379761..858bc297 100644 +--- a/init.initfs.d/61_dhcpd.service ++++ b/init.initfs.d/61_dhcpd.service +@@ -3 +3 @@ description = "DHCP Client" +-requires_weak = ["60_smolnetd.service"] ++requires = ["60_smolnetd.service"]