boot: the /system tree is the system image — loader-built ramdisk, spawn by path

Retire the build-time ramdisk packer and the packed initial-ramdisk.img.
make-fat-image.py now lays every user binary out at its FHS path on the
boot volume (system/services, system/drivers, system/tests), and the EFI
loader walks \system at boot, packing what it finds into an in-RAM v2
initial_ramdisk whose entry names are full FHS paths. init rides the
table like every other binary: its dedicated handoff fields are gone and
the kernel spawns PID 1 via the same lookup as everyone else
(process.spawnBundled).

system_spawn resolves names by exact path first, then unique basename,
and normalizes argv[0] to the stored path — so task names (and, next,
the tagged log ring's attribution) are honest binary paths everywhere.
initrd v2 rejects the old magic so a stale image fails loudly.

Groundwork for per-process logging (/var/log/<boot-stamp>/<binary-path>.log)
and the kernel-VFS /system mount.
This commit is contained in:
Daniel Samson
2026-07-21 14:47:26 +01:00
parent ec6e888076
commit 2d0858caf6
11 changed files with 413 additions and 324 deletions
+10 -14
View File
@@ -329,20 +329,16 @@ fn kmain(boot_information: *const BootInformation) noreturn {
// service supervisor and the device manager spawns the drivers it discovers.
publishInitialRamdisk(boot_information);
// Hand over to user space: load /system/services/init (read off the boot volume by
// the loader) and spawn it as a real ring-3 process, PID 1. As the supervisor it
// brings up the system services (the VFS server, the device manager); the device
// manager then discovers the hardware and spawns each driver. init runs on its own
// address space, preemptively — this boot context becomes the BSP's idle loop.
if (boot_information.init_len != 0) {
status("/system/kernel: starting /system/services/init...\n");
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
process.spawnProcess(image, 4, &.{"/system/services/init"}) catch |err| {
statusPrint("/system/kernel: /system/services/init failed to load: {s}\n", .{@errorName(err)});
};
} else {
status("no /system/services/init on the boot volume.\n");
}
// Hand over to user space: spawn /system/services/init out of the ramdisk as a
// real ring-3 process, PID 1 — it rides the same table as every other binary.
// As the supervisor it brings up the system services (the VFS server, the device
// manager); the device manager then discovers the hardware and spawns each
// driver. init runs on its own address space, preemptively — this boot context
// becomes the BSP's idle loop.
status("/system/kernel: starting /system/services/init...\n");
process.spawnBundled("/system/services/init") catch |err| {
statusPrint("/system/kernel: /system/services/init failed to start: {s}\n", .{@errorName(err)});
};
// Become the idle task: drop below every real task and halt until an
// interrupt. The timer keeps preempting into init and any other work.
+16 -10
View File
@@ -140,6 +140,16 @@ pub fn setInitialRamdisk(image: []const u8) void {
ramdisk_image = image;
}
/// Spawn a bundled binary from the kernel by path. Used exactly once, to start
/// /system/services/init (PID 1) — every other spawn goes through the
/// `system_spawn` syscall.
pub fn spawnBundled(name: []const u8) !void {
const image = ramdisk_image orelse return error.NoInitialRamdisk;
const rd = initial_ramdisk.Reader.init(image) orelse return error.BadInitialRamdisk;
const item = rd.find(name) orelse return error.NotBundled;
try spawnProcess(item.blob, 4, &.{item.name});
}
/// The system_call surface, dispatched on the saved system_call number (`abi.SystemCall`).
/// This is the microkernel-minimal set — memory + scheduling only; file/device
/// I/O will arrive as IPC to user-space servers (docs/syscall.md). The result is
@@ -656,8 +666,11 @@ fn systemSpawn(state: *architecture.CpuState) void {
const rd = initial_ramdisk.Reader.init(image) orelse return fail(state);
const name = @as([*]const u8, @ptrFromInt(ptr))[0..len];
// Exact path first, basename fallback second; either way argv[0] (and hence
// the task name, and the log ring's attribution) is the stored full path.
const item = rd.find(name) orelse return fail(state); // no bundled binary by that name
var argv: [maximum_arguments][]const u8 = undefined;
argv[0] = name;
argv[0] = item.name;
var argc: usize = 1;
if (arguments_len != 0) {
const blob = @as([*]const u8, @ptrFromInt(arguments_ptr))[0..arguments_len];
@@ -669,15 +682,8 @@ fn systemSpawn(state: *architecture.CpuState) void {
}
}
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!std.mem.eql(u8, item.name, name)) continue;
const child = spawnProcessSupervised(item.blob, 4, argv[0..argc], t.id, exit_endpoint) catch return fail(state);
architecture.setSystemCallResult(state, child);
return;
}
fail(state); // no bundled binary by that name
const child = spawnProcessSupervised(item.blob, 4, argv[0..argc], t.id, exit_endpoint) catch return fail(state);
architecture.setSystemCallResult(state, child);
}
/// thread_spawn(entry, stack_top, arg) -> tid: start a task that shares the **caller's**
+67 -61
View File
@@ -1327,12 +1327,12 @@ fn procWorker() void {
/// strongest cheap proof of address-space isolation.
fn processTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: process\n", .{});
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0) {
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
process.write_count = 0;
process.write_from_user = false;
@@ -1414,12 +1414,12 @@ fn spawnFaultingProcess() ?u32 {
/// time the harness out.
fn faultRecoveryTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: fault-recovery\n", .{});
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0) {
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
process.write_count = 0;
process.fault_kill_count = 0;
@@ -1550,7 +1550,7 @@ fn threadJoinTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "join" })) true else |_| false;
break;
}
@@ -1594,7 +1594,7 @@ fn threadFutexTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "futex" })) true else |_| false;
break;
}
@@ -1642,7 +1642,7 @@ fn threadMutexTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "mutex" })) true else |_| false;
break;
}
@@ -1683,7 +1683,7 @@ fn threadIdTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "id" })) true else |_| false;
break;
}
@@ -1726,7 +1726,7 @@ fn threadAllocTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "alloc" })) true else |_| false;
break;
}
@@ -1769,7 +1769,7 @@ fn threadTlsTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "tls" })) true else |_| false;
break;
}
@@ -1811,7 +1811,7 @@ fn threadRwlockTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "thread-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "thread-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "thread-test", "rwlock" })) true else |_| false;
break;
}
@@ -1876,12 +1876,12 @@ fn taskReapTest(boot_information: *const BootInformation) void {
/// (write + sleep), and stays alive rather than exiting.
fn initTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: init\n", .{});
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0) {
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
process.write_count = 0;
const spawned = if (process.spawnProcess(image, 4, &.{"/system/services/init"})) true else |err| blk: {
log("DANOS-INIT-ERR: {s}\n", .{@errorName(err)});
@@ -1912,12 +1912,12 @@ fn initTest(boot_information: *const BootInformation) void {
/// learns how big a buffer to bring).
fn processListTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: process-list\n", .{});
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0) {
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
var spawned: u32 = 0;
if (process.spawnProcess(image, 4, &.{"/system/services/init"})) spawned += 1 else |_| {}
@@ -1963,13 +1963,12 @@ fn processListTest(boot_information: *const BootInformation) void {
/// harness out rather than passing vacuously.
fn processKillTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: process-kill\n", .{});
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0 or boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over an initial_ramdisk", boot_information.initial_ramdisk_len != 0);
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
const ramdisk = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(ramdisk) orelse {
check("initial_ramdisk image is valid", false);
@@ -2024,7 +2023,7 @@ fn processKillTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "process-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "process-test")) continue;
spinner = process.spawnProcessSupervised(item.blob, 4, &.{ "process-test", "spinner" }, me, endpoint) catch 0;
break;
}
@@ -2041,7 +2040,7 @@ fn processKillTest(boot_information: *const BootInformation) void {
i = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "args-echo")) continue;
if (!eql(initial_ramdisk.basename(item.name), "args-echo")) continue;
clean = process.spawnProcessSupervised(item.blob, 4, &.{ "args-echo", "clean-exit" }, me, endpoint) catch 0;
break;
}
@@ -2089,12 +2088,12 @@ fn claimReleaseTest(boot_information: *const BootInformation) void {
check("cleanup released owner 222", devices_broker.ownerOf(1) == null);
// The death-path wiring: a real process dies holding a claim.
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
if (boot_information.init_len == 0) {
const image = bundledInit(boot_information) orelse {
check("initial_ramdisk carries /system/services/init", false);
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
};
check("initial_ramdisk carries /system/services/init", true);
const me = scheduler.currentId();
const endpoint = ipcsync.createIpcEndpoint() orelse {
check("exit endpoint allocated", false);
@@ -2148,7 +2147,7 @@ fn vfsClientDeathTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "vfs-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "vfs-test")) continue;
client = process.spawnProcessSupervised(item.blob, 4, &.{ "vfs-test", "park" }, me, endpoint) catch 0;
break;
}
@@ -2209,7 +2208,7 @@ fn signalsTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "process-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "process-test")) continue;
runner = process.spawnProcessSupervised(item.blob, 4, &.{ "process-test", "signal-run" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -2257,7 +2256,7 @@ fn driverRestartTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{ "device-manager", "test-restart" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -2295,7 +2294,7 @@ fn usbReportTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{ "device-manager", "test-usb-restart" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -2327,7 +2326,7 @@ fn deviceListTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{ "device-manager", "test-usb-restart" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -2368,7 +2367,7 @@ fn pciScanTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{ "device-manager", "test-pci-restart" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -2452,8 +2451,8 @@ fn usbStorageTest(boot_information: *const BootInformation) void {
/// the fat mount and the client's success.
fn fatMountTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: fat-mount\n", .{});
if (boot_information.init_len == 0 or boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over init and the initial_ramdisk", false);
if (boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over the initial_ramdisk", false);
result();
return;
}
@@ -2464,8 +2463,7 @@ fn fatMountTest(boot_information: *const BootInformation) void {
return;
};
process.setInitialRamdisk(ramdisk);
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
const init_ok = if (process.spawnProcess(image, 4, &.{"/system/services/init"})) true else |_| false;
const init_ok = if (process.spawnBundled("/system/services/init")) true else |_| false;
check("init spawned (boots the tree, incl. the fat server)", init_ok);
check("fat-test client spawned", spawnNamed(rd, "fat-test"));
result();
@@ -2473,30 +2471,28 @@ fn fatMountTest(boot_information: *const BootInformation) void {
fn bootServiceTreeTest(boot_information: *const BootInformation, comptime label: []const u8) void {
log("DANOS-TEST-BEGIN: " ++ label ++ "\n", .{});
if (boot_information.init_len == 0 or boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over init and the initial_ramdisk", false);
if (boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over the initial_ramdisk", false);
result();
return;
}
const ramdisk = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
process.setInitialRamdisk(ramdisk);
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
const spawned = if (process.spawnProcess(image, 4, &.{"/system/services/init"})) true else |_| false;
const spawned = if (process.spawnBundled("/system/services/init")) true else |_| false;
check("init spawned (boots vfs, input, device-manager, and the USB chain)", spawned);
result();
}
fn orderlyShutdownTest(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: orderly-shutdown\n", .{});
if (boot_information.init_len == 0 or boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over init and the initial_ramdisk", false);
if (boot_information.initial_ramdisk_len == 0) {
check("bootloader handed over the initial_ramdisk", false);
result();
return;
}
const ramdisk = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
process.setInitialRamdisk(ramdisk);
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
const spawned = if (process.spawnProcess(image, 4, &.{"/system/services/init"})) true else |_| false;
const spawned = if (process.spawnBundled("/system/services/init")) true else |_| false;
check("init spawned as PID root of user space", spawned);
result();
}
@@ -2524,7 +2520,7 @@ fn acpiReportTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
_ = process.spawnProcessSupervised(item.blob, 4, &.{"device-manager"}, scheduler.currentId(), null) catch 0;
spawned = true;
break;
@@ -2562,7 +2558,7 @@ fn acpiParseTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "discovery")) continue;
if (!eql(initial_ramdisk.basename(item.name), "discovery")) continue;
_ = process.spawnProcessSupervised(item.blob, 4, &.{ "discovery", "1" }, scheduler.currentId(), null) catch 0;
spawned = true;
break;
@@ -2597,7 +2593,7 @@ fn supervisionTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "process-test")) continue;
if (!eql(initial_ramdisk.basename(item.name), "process-test")) continue;
started = if (process.spawnProcess(item.blob, 4, &.{ "process-test", "run" })) true else |_| false;
break;
}
@@ -2921,7 +2917,7 @@ fn virtioGpuTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{"device-manager"}, scheduler.currentId(), null) catch 0;
break;
}
@@ -2962,7 +2958,7 @@ fn displayNativeTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{"device-manager"}, scheduler.currentId(), null) catch 0;
break;
}
@@ -3006,7 +3002,7 @@ fn displayReattachTest(boot_information: *const BootInformation) void {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (!eql(item.name, "device-manager")) continue;
if (!eql(initial_ramdisk.basename(item.name), "device-manager")) continue;
manager = process.spawnProcessSupervised(item.blob, 4, &.{ "device-manager", "test-scanout-restart" }, scheduler.currentId(), null) catch 0;
break;
}
@@ -3055,7 +3051,7 @@ fn argsTest(boot_information: *const BootInformation) void {
while (process.write_count < 1 and architecture.millis() < deadline) scheduler.yield();
scheduler.setPriority(4);
const expected = "args: args-echo alpha beta-42\n";
const expected = "args: /system/tests/args-echo alpha beta-42\n";
const echoed = process.write_len == expected.len and eql(process.write_buffer[0..process.write_len], expected);
if (!echoed and process.write_len > 0) log("DANOS-ARGS: got \"{s}\"\n", .{process.write_buffer[0..process.write_len]});
check("argv arrived intact (argv[0] = name, argv[1..] = spawn arguments)", echoed);
@@ -3065,11 +3061,21 @@ fn argsTest(boot_information: *const BootInformation) void {
/// Spawn the initial_ramdisk binary named `name` as a ring-3 process. Returns false if it
/// isn't in the image or fails to load.
/// The init ELF image out of the initial_ramdisk — init rides the table like
/// every other binary since the loader packs the whole /system tree.
fn bundledInit(boot_information: *const BootInformation) ?[]const u8 {
if (boot_information.initial_ramdisk_len == 0) return null;
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(image) orelse return null;
const item = rd.find("/system/services/init") orelse return null;
return item.blob;
}
fn spawnNamed(rd: initial_ramdisk.Reader, name: []const u8) bool {
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (eql(item.name, name)) {
if (eql(initial_ramdisk.basename(item.name), name)) {
return if (process.spawnProcess(item.blob, 4, &.{item.name})) true else |_| false;
}
}
@@ -3082,7 +3088,7 @@ fn spawnNamedWithArg(rd: initial_ramdisk.Reader, name: []const u8, arg: []const
var i: u32 = 0;
while (i < rd.count) : (i += 1) {
const item = rd.entry(i) orelse continue;
if (eql(item.name, name)) {
if (eql(initial_ramdisk.basename(item.name), name)) {
return if (process.spawnProcess(item.blob, 4, &.{ item.name, arg })) true else |_| false;
}
}