refactor: deconsolidate redox.patch into individual patches

The 556MB monolithic redox.patch was impossible to manage, unreviewable,
blocked GitHub pushes, and could only grow. This commit:

- Moves all 64 absorbed patches from absorbed/ to active use in base/
- Removes the absorbed/ directory (consolidation history is now PATCH-HISTORY.md)
- Removes the redox.patch symlink from recipes/core/base/
- Fixes all recipe symlinks to point to active patches (not absorbed/)
- Patches are now individually wired, reviewable, and independently rebasable

The redox.patch mega-file is no longer needed — individual patches
are applied directly from the recipe.toml patches list.
This commit is contained in:
2026-05-03 08:35:26 +01:00
parent 1140f0f9b3
commit c0587f9a2d
107 changed files with 244 additions and 17208 deletions
@@ -1 +0,0 @@
../../../local/patches/base/P0-bootstrap-workspace-fix.patch
@@ -1,43 +0,0 @@
diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs
index 9f507221..c57d91dc 100644
--- a/daemon/src/lib.rs
+++ b/daemon/src/lib.rs
@@ -11,12 +11,23 @@ use redox_scheme::Socket;
use redox_scheme::scheme::{SchemeAsync, SchemeSync};
unsafe fn get_fd(var: &str) -> RawFd {
- let fd: RawFd = std::env::var(var).unwrap().parse().unwrap();
+ let fd: RawFd = match std::env::var(var)
+ .map_err(|e| eprintln!("daemon: env var {var} not set: {e}"))
+ .ok()
+ .and_then(|val| {
+ val.parse()
+ .map_err(|e| eprintln!("daemon: failed to parse {var} as fd: {e}"))
+ .ok()
+ }) {
+ Some(fd) => fd,
+ None => return -1,
+ };
if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 {
- panic!(
+ eprintln!(
"daemon: failed to set CLOEXEC flag for {var} fd: {}",
io::Error::last_os_error()
);
+ return -1;
}
fd
}
@@ -51,7 +62,11 @@ impl Daemon {
/// Notify the process that the daemon is ready to accept requests.
pub fn ready(mut self) {
- self.write_pipe.write_all(&[0]).unwrap();
+ if let Err(err) = self.write_pipe.write_all(&[0]) {
+ if err.kind() != io::ErrorKind::BrokenPipe {
+ eprintln!("daemon::ready write failed: {err}");
+ }
+ }
}
/// Executes `Command` as a child process.
@@ -0,0 +1 @@
../../../local/patches/base/P0-daemon-fix-init-notify-unwrap.patch
@@ -1 +0,0 @@
../../../local/patches/base/P0-dhcpd-auto-iface.patch
@@ -1,12 +0,0 @@
diff --git a/Cargo.toml b/Cargo.toml
index 9e776232..acdb1c97 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,6 +2,7 @@
resolver = "2"
members = [
"audiod",
+ "bootstrap",
"config",
"daemon",
"dhcpd",
+1
View File
@@ -0,0 +1 @@
../../../local/patches/base/P0-workspace-add-bootstrap.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-ac97d-ihdad-main.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-acpi-defer-aml.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-acpi-i2c-resources.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-acpid-core-refactor.patch
-1
View File
@@ -1 +0,0 @@
../../../local/patches/base/P2-boot-logging.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-boot-runtime-fixes.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-daemon-hardening.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-daemon-ready-graceful.patch
-1
View File
@@ -1 +0,0 @@
../../../local/patches/base/P2-hwd-misc.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-ihdad-device-refactor.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-ihdad-hda-stream.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-init-acpid-wiring.patch
@@ -1,45 +0,0 @@
diff --git a/init.initfs.d/40_pcid.service b/init.initfs.d/40_pcid.service
new file mode 100644
--- /dev/null
+++ b/init.initfs.d/40_pcid.service
@@ -0,0 +1,7 @@
+[unit]
+description = "PCI daemon"
+requires_weak = ["41_acpid.service"]
+
+[service]
+cmd = "pcid"
+type = "notify"
diff --git a/init.initfs.d/40_drivers.target b/init.initfs.d/40_drivers.target
--- a/init.initfs.d/40_drivers.target
+++ b/init.initfs.d/40_drivers.target
@@ -3,6 +3,7 @@ description = "Initfs drivers"
requires_weak = [
"10_lived.service",
"20_graphics.target",
+ "40_pcid.service",
"40_ps2d.service",
"40_bcm2835-sdhcid.service",
"40_hwd.service",
diff --git a/init.initfs.d/40_hwd.service b/init.initfs.d/40_hwd.service
--- a/init.initfs.d/40_hwd.service
+++ b/init.initfs.d/40_hwd.service
@@ -1,6 +1,6 @@
[unit]
description = "Hardware manager"
-requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target", "41_acpid.service"]
+requires_weak = ["10_inputd.service", "10_lived.service", "20_graphics.target", "40_pcid.service", "41_acpid.service"]
[service]
cmd = "hwd"
diff --git a/init.initfs.d/40_pcid-spawner-initfs.service b/init.initfs.d/40_pcid-spawner-initfs.service
--- a/init.initfs.d/40_pcid-spawner-initfs.service
+++ b/init.initfs.d/40_pcid-spawner-initfs.service
@@ -1,6 +1,6 @@
[unit]
description = "PCI driver spawner"
-requires_weak = ["10_inputd.service", "20_graphics.target", "40_hwd.service"]
+requires_weak = ["10_inputd.service", "20_graphics.target", "40_pcid.service"]
[service]
cmd = "pcid-spawner"
@@ -1 +0,0 @@
../../../local/patches/base/P2-ixgbed-error-handling.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-misc-daemon-fixes.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-network-driver-mains.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-network-error-handling.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-pcid-cfg-access.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-pcid-driver-interface.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-ps2d-improvements.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-storage-driver-mains.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-storage-error-handling.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-usb-pm-and-drivers.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-virtio-core-vbox.patch
@@ -1 +0,0 @@
../../../local/patches/base/P2-xhcid-remaining.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-acpi-power-dmi.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-acpi-wave12-hardening.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-pcid-aer-scheme.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-pcid-bind-scheme.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-pcid-uevent-format-fix.patch
@@ -1 +0,0 @@
../../../local/patches/base/P3-xhci-device-hardening.patch
@@ -1 +0,0 @@
../../../local/patches/base/P5-init-daemon-panic-hardening.patch
@@ -1 +0,0 @@
../../../local/patches/base/P5-init-supervisor-restart.patch
+2
View File
@@ -177,7 +177,9 @@ fn main() {
}
};
eprintln!("init: DEBUG step start — {} jobs pending", scheduler.pending_len());
scheduler.step(&mut unit_store, &mut init_config);
eprintln!("init: DEBUG step done — entering waitpid loop");
if let Err(err) = libredox::call::setrens(0, 0) {
eprintln!("init: failed to enter null namespace: {}", err);
+18
View File
@@ -66,6 +66,10 @@ impl Scheduler {
}
}
pub fn pending_len(&self) -> usize {
self.pending.len()
}
pub fn step(&mut self, unit_store: &mut UnitStore, init_config: &mut InitConfig) {
'a: loop {
let Some(mut job) = self.pending.pop_front() else {
@@ -75,6 +79,16 @@ impl Scheduler {
match job.kind {
JobKind::Start => {
let unit = unit_store.unit(&job.unit);
eprintln!(
"init: DEBUG processing {} ({}) — deps: {:?}",
job.unit.0,
match &unit.kind {
crate::unit::UnitKind::LegacyScript { .. } => "script",
crate::unit::UnitKind::Service { service } => &service.cmd,
crate::unit::UnitKind::Target { .. } => "target",
},
unit.info.requires_weak.iter().map(|u| &u.0).collect::<Vec<_>>()
);
let timeout_secs = unit.info.dependency_timeout_secs;
let mut deps_pending = false;
@@ -91,6 +105,10 @@ impl Scheduler {
}
if deps_pending {
eprintln!(
"init: DEBUG {} waiting for deps (retry {})",
job.unit.0, job.dep_retries
);
if timeout_secs > 0 {
job.dep_retries += 1;
let max_retries = timeout_secs * 100; // ~10ms per retry
+36 -21
View File
@@ -180,7 +180,7 @@ pub struct Socket {
options: HashSet<i32>,
flags: usize,
state: State,
awaiting: VecDeque<usize>,
awaiting: VecDeque<(usize, ucred)>,
connection: Option<Connection>,
issued_token: Option<u64>,
ucred: ucred,
@@ -241,6 +241,7 @@ impl Socket {
&mut self,
primary_id: usize,
awaiting_client_id: usize,
client_ucred: ucred,
ctx: &CallerCtx,
) -> Result<Self> {
if !self.is_listening() {
@@ -250,15 +251,17 @@ impl Socket {
);
return Err(Error::new(EINVAL));
}
Ok(Self::new(
Ok(Self {
primary_id,
self.path.clone(),
State::Established,
self.options.clone(),
self.flags,
Some(Connection::new(awaiting_client_id)),
ctx,
))
path: self.path.clone(),
state: State::Established,
options: self.options.clone(),
flags: self.flags,
awaiting: VecDeque::new(),
connection: Some(Connection::new(awaiting_client_id)),
issued_token: None,
ucred: client_ucred,
})
}
fn establish(&mut self, new_socket: &mut Self, peer: usize) -> Result<()> {
@@ -286,7 +289,7 @@ impl Socket {
Ok(())
}
fn connect(&mut self, other: &mut Socket) -> Result<()> {
fn connect(&mut self, other: &mut Socket, client_ucred: ucred) -> Result<()> {
match self.state {
State::Unbound | State::Bound => {
// If the socket is unbound or bound, wait for the listener to start listening.
@@ -302,12 +305,12 @@ impl Socket {
}
_ => return Err(Error::new(ECONNREFUSED)),
}
self.connect_unchecked(other);
self.connect_unchecked(other, client_ucred);
Ok(())
}
fn connect_unchecked(&mut self, other: &mut Socket) {
self.awaiting.push_back(other.primary_id);
fn connect_unchecked(&mut self, other: &mut Socket, client_ucred: ucred) {
self.awaiting.push_back((other.primary_id, client_ucred));
other.state = State::Connecting;
other.connection = Some(Connection::new(self.primary_id));
}
@@ -495,7 +498,7 @@ impl<'sock> UdsStreamScheme<'sock> {
};
match verb {
SocketCall::Bind => self.handle_bind(id, &payload),
SocketCall::Connect => self.handle_connect(id, &payload),
SocketCall::Connect => self.handle_connect(id, &payload, ctx),
SocketCall::SetSockOpt => self.handle_setsockopt(
id,
*metadata.get(1).ok_or(Error::new(EINVAL))? as i32,
@@ -588,7 +591,7 @@ impl<'sock> UdsStreamScheme<'sock> {
// and changes its own state to `Established`.
//
// After these three phases, the socket connection is considered established.
fn handle_connect(&mut self, id: usize, token_buf: &[u8]) -> Result<usize> {
fn handle_connect(&mut self, id: usize, token_buf: &[u8], ctx: &CallerCtx) -> Result<usize> {
let token = read_num::<u64>(token_buf)?;
let (listener_id, connecting_res) = {
let listener_rc = self
@@ -632,8 +635,14 @@ impl<'sock> UdsStreamScheme<'sock> {
_ => {}
}
let client_ucred = ucred {
pid: ctx.pid as _,
uid: ctx.uid as _,
gid: ctx.gid as _,
};
// Phase 2: listener is now listening
listener.connect(&mut client)?;
listener.connect(&mut client, client_ucred)?;
(listener_id, connecting_res)
};
@@ -873,6 +882,7 @@ impl<'sock> UdsStreamScheme<'sock> {
&mut self,
listener_socket: &mut Socket,
client_id: usize,
client_ucred: ucred,
ctx: &CallerCtx,
) -> Result<Option<OpenResult>> {
let (new_id, new) = {
@@ -880,7 +890,7 @@ impl<'sock> UdsStreamScheme<'sock> {
return Ok(None); // Client socket has been closed, nothing to accept
};
let new_id = self.next_id;
let mut new = listener_socket.accept(new_id, client_id, ctx)?;
let mut new = listener_socket.accept(new_id, client_id, client_ucred, ctx)?;
let mut client_socket = client_rc.borrow_mut();
client_socket.establish(&mut new, listener_socket.primary_id)?;
@@ -912,14 +922,14 @@ impl<'sock> UdsStreamScheme<'sock> {
}
loop {
// Try to accept a waiting connection
let Some(client_id) = socket.awaiting.pop_front() else {
let Some((client_id, client_ucred)) = socket.awaiting.pop_front() else {
if flags & O_NONBLOCK == O_NONBLOCK {
return Err(Error::new(EAGAIN));
} else {
return Err(Error::new(EWOULDBLOCK));
}
};
return match self.accept_connection(socket, client_id, ctx) {
return match self.accept_connection(socket, client_id, client_ucred, ctx) {
Ok(conn) => Ok(conn),
Err(Error { errno: EAGAIN }) => continue,
Err(e) => Err(e),
@@ -991,7 +1001,12 @@ impl<'sock> UdsStreamScheme<'sock> {
);
return Err(Error::new(EPIPE));
}
socket.connect_unchecked(&mut new);
let pair_ucred = ucred {
pid: ctx.pid as _,
uid: ctx.uid as _,
gid: ctx.gid as _,
};
socket.connect_unchecked(&mut new, pair_ucred);
}
// smoltcp sends writeable whenever a listener gets a
@@ -1186,7 +1201,7 @@ impl<'sock> UdsStreamScheme<'sock> {
}
// Notify all waiting clients about listener closure
for client_id in &socket.awaiting {
for (client_id, _) in &socket.awaiting {
if let Ok(client_rc) = self.get_socket(*client_id) {
{
let mut client = client_rc.borrow_mut();
-1
View File
@@ -1 +0,0 @@
../../../local/patches/base/redox.patch