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:
+16
-10
@@ -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**
|
||||
|
||||
Reference in New Issue
Block a user