From e86dbfa17e20abf2d88d87fde7b3d5715ee6c72e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 28 Feb 2026 16:55:26 +0100 Subject: [PATCH 1/2] Init: Introduce support for conditionally spawning services depending on the architecture and selected board. With this the migration of initfs daemons to service definitions is almost done. --- init.d.aarch64-unknown-redox/40_drivers | 3 --- .../40_drivers.raspi3bp | 2 -- init.d/40_bcm2835-sdhcid.service | 9 +++++++++ init.d/40_drivers | 4 ---- init.d/40_drivers.target | 10 ++++++++++ init.d/40_hwd.service | 11 +++++++++++ init.d/40_pcid-spawner.service | 8 ++++++++ init.d/40_ps2d.service | 8 ++++++++ init.d/50_rootfs | 2 +- init/src/main.rs | 19 ++++++++++++++++++- init/src/service.rs | 1 + init/src/unit.rs | 9 +++++++++ 12 files changed, 75 insertions(+), 11 deletions(-) delete mode 100644 init.d.aarch64-unknown-redox/40_drivers delete mode 100644 init.d.aarch64-unknown-redox/40_drivers.raspi3bp create mode 100644 init.d/40_bcm2835-sdhcid.service delete mode 100644 init.d/40_drivers create mode 100644 init.d/40_drivers.target create mode 100644 init.d/40_hwd.service create mode 100644 init.d/40_pcid-spawner.service create mode 100644 init.d/40_ps2d.service diff --git a/init.d.aarch64-unknown-redox/40_drivers b/init.d.aarch64-unknown-redox/40_drivers deleted file mode 100644 index a4ee8de9e8..0000000000 --- a/init.d.aarch64-unknown-redox/40_drivers +++ /dev/null @@ -1,3 +0,0 @@ -requires_weak 10_lived.service 20_graphics.target -notify RSDP_ADDR=$ RSDP_SIZE=$ hwd -pcid-spawner --initfs diff --git a/init.d.aarch64-unknown-redox/40_drivers.raspi3bp b/init.d.aarch64-unknown-redox/40_drivers.raspi3bp deleted file mode 100644 index 5e1f7cdd2a..0000000000 --- a/init.d.aarch64-unknown-redox/40_drivers.raspi3bp +++ /dev/null @@ -1,2 +0,0 @@ -requires_weak 10_lived.service 20_graphics.target -notify bcm2835-sdhcid diff --git a/init.d/40_bcm2835-sdhcid.service b/init.d/40_bcm2835-sdhcid.service new file mode 100644 index 0000000000..8c05462017 --- /dev/null +++ b/init.d/40_bcm2835-sdhcid.service @@ -0,0 +1,9 @@ +[unit] +description = "BCM2835 SD card driver" +requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target"] +condition_architecture = ["aarch64"] +condition_board = ["raspi3bp"] + +[service] +cmd = "bcm2835-sdhcid" +type = "notify" diff --git a/init.d/40_drivers b/init.d/40_drivers deleted file mode 100644 index 769d714048..0000000000 --- a/init.d/40_drivers +++ /dev/null @@ -1,4 +0,0 @@ -requires_weak 10_lived.service 20_graphics.target -notify ps2d -notify RSDP_ADDR=$ RSDP_SIZE=$ hwd -pcid-spawner --initfs diff --git a/init.d/40_drivers.target b/init.d/40_drivers.target new file mode 100644 index 0000000000..66f8fb251f --- /dev/null +++ b/init.d/40_drivers.target @@ -0,0 +1,10 @@ +[unit] +description = "Initfs drivers" +requires_weak = [ + "10_lived.service", + "20_graphics.target", + "40_ps2d.service", + "40_bcm2835-sdhcid.service", + "40_hwd.service", + "40_pcid-spawner.service", +] diff --git a/init.d/40_hwd.service b/init.d/40_hwd.service new file mode 100644 index 0000000000..c90650b5f8 --- /dev/null +++ b/init.d/40_hwd.service @@ -0,0 +1,11 @@ +[unit] +description = "Hardware manager" +requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target"] + +[service] +cmd = "hwd" +inherit_envs = [ + "RSDP_ADDR", + "RSDP_SIZE", +] +type = "notify" diff --git a/init.d/40_pcid-spawner.service b/init.d/40_pcid-spawner.service new file mode 100644 index 0000000000..6945b9eadc --- /dev/null +++ b/init.d/40_pcid-spawner.service @@ -0,0 +1,8 @@ +[unit] +description = "PCI driver spawner" +requires_weak = ["10_inputd.service", "20_graphics.target", "40_hwd.service"] + +[service] +cmd = "pcid-spawner" +args = ["--initfs"] +type = "oneshot" diff --git a/init.d/40_ps2d.service b/init.d/40_ps2d.service new file mode 100644 index 0000000000..881e75ea52 --- /dev/null +++ b/init.d/40_ps2d.service @@ -0,0 +1,8 @@ +[unit] +description = "PS/2 driver" +requires_weak = ["10_inputd.service", "20_graphics.target"] +condition_architecture = ["x86", "x86_64"] + +[service] +cmd = "ps2d" +type = "notify" diff --git a/init.d/50_rootfs b/init.d/50_rootfs index 798451ab66..550cd2b3ca 100644 --- a/init.d/50_rootfs +++ b/init.d/50_rootfs @@ -1,2 +1,2 @@ -requires_weak 40_drivers +requires_weak 40_drivers.target REDOXFS_PASSWORD_ADDR=$ REDOXFS_PASSWORD_SIZE=$ redoxfs --uuid $REDOXFS_UUID file $REDOXFS_BLOCK diff --git a/init/src/main.rs b/init/src/main.rs index 37b164e68e..dba212b229 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -50,6 +50,7 @@ impl InitConfig { } #[derive(Clone, Deserialize)] +#[serde(deny_unknown_fields)] struct SwitchRoot { prefix: PathBuf, etcdir: PathBuf, @@ -112,7 +113,7 @@ fn run( unit::UnitKind::Target {} => { if config.log_debug { eprintln!( - "Started target {}", + "Reached target {}", unit.info.description.as_ref().unwrap_or(&unit.id.0), ); } @@ -171,6 +172,22 @@ fn main() { let runtime_target = UnitId("00_runtime.target".to_owned()); 'a: while let Some(unit) = pending_units.pop_front() { + if let Some(condition_architecture) = &unit_store.unit(&unit).info.condition_architecture { + if !condition_architecture + .iter() + .any(|arch| arch == std::env::consts::ARCH) + { + continue 'a; + } + } + if let Some(condition_board) = &unit_store.unit(&unit).info.condition_board { + if !condition_board + .iter() + .any(|board| Some(&**board) == option_env!("BOARD")) + { + continue 'a; + } + } if unit_store.unit(&unit).info.default_dependencies { if pending_units.contains(&runtime_target) { pending_units.push_back(unit); diff --git a/init/src/service.rs b/init/src/service.rs index 529548819a..0fd8ba7c0d 100644 --- a/init/src/service.rs +++ b/init/src/service.rs @@ -6,6 +6,7 @@ use std::process::Command; use serde::Deserialize; #[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] pub struct Service { pub cmd: String, #[serde(default)] diff --git a/init/src/unit.rs b/init/src/unit.rs index 42fac48070..670d8c3db1 100644 --- a/init/src/unit.rs +++ b/init/src/unit.rs @@ -77,12 +77,16 @@ pub struct Unit { } #[derive(Deserialize)] +#[serde(deny_unknown_fields)] pub struct UnitInfo { pub description: Option, #[serde(default = "true_bool")] pub default_dependencies: bool, #[serde(default)] pub requires_weak: Vec, + pub condition_architecture: Option>, + // FIXME replace this with hwd reading from the devicetree + pub condition_board: Option>, } fn true_bool() -> bool { @@ -97,17 +101,20 @@ pub enum UnitKind { } #[derive(Deserialize)] +#[serde(deny_unknown_fields)] struct SerializedService { unit: UnitInfo, service: Service, } #[derive(Deserialize)] +#[serde(deny_unknown_fields)] struct SerializedTarget { unit: UnitInfo, } #[derive(Deserialize)] +#[serde(deny_unknown_fields)] struct SerializedSwitchRoot { unit: UnitInfo, switchroot: SwitchRoot, @@ -143,6 +150,8 @@ impl Unit { description: None, default_dependencies: true, requires_weak, + condition_architecture: None, + condition_board: None, }, UnitKind::LegacyScript { script }, warnings, From 6d243d666c686929eec38702897f0002dd043951 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 28 Feb 2026 17:03:06 +0100 Subject: [PATCH 2/2] init: Convert rootfs to a service With this the entire initfs now uses service definitions. --- init.d/40_hwd.service | 5 +---- init.d/50_rootfs | 2 -- init.d/50_rootfs.service | 9 +++++++++ init.d/90_exit_initfs.switchroot | 2 +- init/src/script.rs | 2 +- init/src/service.rs | 4 +++- 6 files changed, 15 insertions(+), 9 deletions(-) delete mode 100644 init.d/50_rootfs create mode 100644 init.d/50_rootfs.service diff --git a/init.d/40_hwd.service b/init.d/40_hwd.service index c90650b5f8..cba12dde61 100644 --- a/init.d/40_hwd.service +++ b/init.d/40_hwd.service @@ -4,8 +4,5 @@ requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target"] [service] cmd = "hwd" -inherit_envs = [ - "RSDP_ADDR", - "RSDP_SIZE", -] +inherit_envs = ["RSDP_ADDR", "RSDP_SIZE"] type = "notify" diff --git a/init.d/50_rootfs b/init.d/50_rootfs deleted file mode 100644 index 550cd2b3ca..0000000000 --- a/init.d/50_rootfs +++ /dev/null @@ -1,2 +0,0 @@ -requires_weak 40_drivers.target -REDOXFS_PASSWORD_ADDR=$ REDOXFS_PASSWORD_SIZE=$ redoxfs --uuid $REDOXFS_UUID file $REDOXFS_BLOCK diff --git a/init.d/50_rootfs.service b/init.d/50_rootfs.service new file mode 100644 index 0000000000..c2d8e47713 --- /dev/null +++ b/init.d/50_rootfs.service @@ -0,0 +1,9 @@ +[unit] +description = "Rootfs" +requires_weak = ["40_drivers.target"] + +[service] +cmd = "redoxfs" +args = ["--uuid" ,"$REDOXFS_UUID", "file", "$REDOXFS_BLOCK"] +inherit_envs = ["REDOXFS_PASSWORD_ADDR", "REDOXFS_PASSWORD_SIZE"] +type = "oneshot" diff --git a/init.d/90_exit_initfs.switchroot b/init.d/90_exit_initfs.switchroot index f91243b3c5..f4357eddbd 100644 --- a/init.d/90_exit_initfs.switchroot +++ b/init.d/90_exit_initfs.switchroot @@ -1,5 +1,5 @@ [unit] -requires_weak = ["50_rootfs"] +requires_weak = ["50_rootfs.service"] [switchroot] prefix = "/usr" diff --git a/init/src/script.rs b/init/src/script.rs index f61ff6fbcb..1b233d889b 100644 --- a/init/src/script.rs +++ b/init/src/script.rs @@ -4,7 +4,7 @@ use std::{env, io, iter}; use crate::service::{Service, ServiceType}; use crate::unit::UnitId; -fn subst_env<'a>(arg: &str) -> String { +pub fn subst_env<'a>(arg: &str) -> String { if arg.starts_with('$') { env::var(&arg[1..]).unwrap_or(String::new()) } else { diff --git a/init/src/service.rs b/init/src/service.rs index 0fd8ba7c0d..e0b1e682db 100644 --- a/init/src/service.rs +++ b/init/src/service.rs @@ -5,6 +5,8 @@ use std::process::Command; use serde::Deserialize; +use crate::script::subst_env; + #[derive(Clone, Debug, Deserialize)] #[serde(deny_unknown_fields)] pub struct Service { @@ -32,7 +34,7 @@ pub enum ServiceType { impl Service { pub fn spawn(&self, base_envs: &BTreeMap) { let mut command = Command::new(&self.cmd); - command.args(&self.args); + command.args(self.args.iter().map(|arg| subst_env(arg))); command.env_clear(); for env in &self.inherit_envs { if let Some(value) = env::var_os(env) {