Update stale /sbin/ references to real FHS paths
The reorg moved user binaries under /system (init -> /system/services/init, drivers -> /system/drivers/<name>, vfs-test -> /system/services/vfs/vfs-test), but many comments and log strings still named the old /sbin/ home. Retarget them all: kernel/loader/test comments and the two boot log lines, plus vision.md and the driver-model.md proposed tree (also dropped the stale `d` suffixes and rt->runtime there). The initial-ramdisk spawn log no longer fakes a /sbin/ prefix, since those binaries live in different homes (services vs drivers). Left the FSH design doc's /sbin and /lib rows alone — whether /sbin stays a directory at all is a design call for its owner, not a stale-comment fix.
This commit is contained in:
+4
-4
@@ -63,9 +63,9 @@ fn boot() !noreturn {
|
|||||||
|
|
||||||
const entry = try loadKernel(bs, &boot_information);
|
const entry = try loadKernel(bs, &boot_information);
|
||||||
|
|
||||||
// Best effort: a volume without sbin/init still boots (kernel-only).
|
// Best effort: a volume without /system/services/init still boots (kernel-only).
|
||||||
loadInit(bs, &boot_information) catch |err| {
|
loadInit(bs, &boot_information) catch |err| {
|
||||||
log("danos: no sbin/init (");
|
log("danos: no /system/services/init (");
|
||||||
logBytes(@errorName(err));
|
logBytes(@errorName(err));
|
||||||
log(") - booting without user space\r\n");
|
log(") - booting without user space\r\n");
|
||||||
};
|
};
|
||||||
@@ -389,13 +389,13 @@ fn loadFile(bs: *uefi.tables.BootServices, name: [*:0]const u16) ![]u8 {
|
|||||||
return image[0..size];
|
return image[0..size];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ferry the init program (sbin/init) to the kernel. The kernel does the ELF
|
/// Ferry the init program (/system/services/init) to the kernel. The kernel does the ELF
|
||||||
/// loading itself (into ring-3 mappings) — the loader just carries the bytes.
|
/// loading itself (into ring-3 mappings) — the loader just carries the bytes.
|
||||||
fn loadInit(bs: *uefi.tables.BootServices, boot_information: *BootInformation) !void {
|
fn loadInit(bs: *uefi.tables.BootServices, boot_information: *BootInformation) !void {
|
||||||
const image = try loadFile(bs, init_file_name);
|
const image = try loadFile(bs, init_file_name);
|
||||||
boot_information.init_base = @intFromPtr(image.ptr);
|
boot_information.init_base = @intFromPtr(image.ptr);
|
||||||
boot_information.init_len = image.len;
|
boot_information.init_len = image.len;
|
||||||
log("danos: sbin/init loaded\r\n");
|
log("danos: /system/services/init loaded\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ferry the initial_ramdisk (the VFS server + drivers) to the kernel, same as init.
|
/// Ferry the initial_ramdisk (the VFS server + drivers) to the kernel, same as init.
|
||||||
|
|||||||
+12
-12
@@ -99,21 +99,21 @@ danos already has one of each: `library/runtime/device.zig` is a logic module,
|
|||||||
and its clients. The pattern generalises directly:
|
and its clients. The pattern generalises directly:
|
||||||
|
|
||||||
```
|
```
|
||||||
lib/
|
library/
|
||||||
rt.zig module "rt" — syscalls, heap, ipc, dev, stdio
|
runtime/ module "runtime" — syscalls, heap, ipc, device, stdio
|
||||||
mmio.zig module "mmio" — volatile register access + barriers [M14]
|
mmio/ module "mmio" — volatile register access + barriers [M14]
|
||||||
bus/
|
bus/
|
||||||
pci.zig module "pci" — ECAM, BAR decode, capability walk
|
pci/ module "pci" — ECAM, BAR decode, capability walk
|
||||||
usb.zig module "usb" — descriptors, control transfers, hubs
|
usb/ module "usb" — descriptors, control transfers, hubs
|
||||||
proto/
|
proto/
|
||||||
vfs.zig module "proto.vfs" (today: system/services/vfs/protocol.zig)
|
vfs/ module "vfs-protocol" (today: system/services/vfs/protocol.zig)
|
||||||
block.zig module "proto.block"
|
block/ module "block-protocol"
|
||||||
hid.zig module "proto.hid"
|
hid/ module "hid-protocol"
|
||||||
|
|
||||||
sbin/
|
system/drivers/ one sub-project each → /system/drivers (no `d` suffix)
|
||||||
xhcid.zig HCD + bus driver imports rt, pci, usb, mmio
|
xhci/ HCD + bus driver imports runtime, pci, usb, mmio
|
||||||
usbhid.zig class driver imports rt, usb, proto.hid
|
usb-hid/ class driver imports runtime, usb, hid-protocol
|
||||||
blockd.zig class driver imports rt, proto.block
|
block/ class driver imports runtime, block-protocol
|
||||||
```
|
```
|
||||||
|
|
||||||
The only build change needed: [`addUserBinary`](build.zig) currently takes exactly one
|
The only build change needed: [`addUserBinary`](build.zig) currently takes exactly one
|
||||||
|
|||||||
+2
-2
@@ -84,13 +84,13 @@ interrupts](interrupts.md), a [calibrated timer + ns clock](device-interrupts.md
|
|||||||
in-kernel [IPC channels](ipc.md), SMP (all cores scheduling, with affinity), a
|
in-kernel [IPC channels](ipc.md), SMP (all cores scheduling, with affinity), a
|
||||||
**higher-half kernel** with a physmap, and **user space**: per-process address
|
**higher-half kernel** with a physmap, and **user space**: per-process address
|
||||||
spaces, `syscall`/`sysret` with the `swapgs` discipline, a user-ELF loader, and
|
spaces, `syscall`/`sysret` with the `swapgs` discipline, a user-ELF loader, and
|
||||||
`/sbin/init` — a real user ELF built from `sbin/`, running at CPL 3 as PID 1 on its
|
`/system/services/init` — a real user ELF built from `system/services/init/`, running at CPL 3 as PID 1 on its
|
||||||
own page tables — plus a [test harness](testing.md).
|
own page tables — plus a [test harness](testing.md).
|
||||||
|
|
||||||
- **Isolation track** — **user mode + address-space isolation**. *Done: a
|
- **Isolation track** — **user mode + address-space isolation**. *Done: a
|
||||||
higher-half kernel with a physmap (the low half is user space), per-process
|
higher-half kernel with a physmap (the low half is user space), per-process
|
||||||
address spaces with CR3 switched on context switch, the `swapgs` discipline,
|
address spaces with CR3 switched on context switch, the `swapgs` discipline,
|
||||||
`syscall`/`sysret`, a user-ELF loader, and `/sbin/init` running as a real
|
`syscall`/`sysret`, a user-ELF loader, and `/system/services/init` running as a real
|
||||||
preemptive ring-3 process (PID 1). Remaining polish: an address-space/stack
|
preemptive ring-3 process (PID 1). Remaining polish: an address-space/stack
|
||||||
reaper for exited tasks, SMAP + fault-recovering copy-in/out, the real IPC
|
reaper for exited tasks, SMAP + fault-recovering copy-in/out, the real IPC
|
||||||
syscalls (IPC_Call/IPC_ReplyWait — they arrive with the second user server),
|
syscalls (IPC_Call/IPC_ReplyWait — they arrive with the second user server),
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ pub const BootInformation = extern struct {
|
|||||||
/// A device-tree boot path leaves this 0 and (later) fills a `device_tree_blob`
|
/// A device-tree boot path leaves this 0 and (later) fills a `device_tree_blob`
|
||||||
/// field instead, so the kernel discovers devices without knowing what booted it.
|
/// field instead, so the kernel discovers devices without knowing what booted it.
|
||||||
acpi_rsdp: u64 = 0,
|
acpi_rsdp: u64 = 0,
|
||||||
/// The raw `/sbin/init` ELF image, read off the boot volume by the loader
|
/// The raw `/system/services/init` ELF image, read off the boot volume by the loader
|
||||||
/// into memory that survives the handoff (classified reserved, so the kernel
|
/// into memory that survives the handoff (classified reserved, so the kernel
|
||||||
/// identity-maps it and never allocates over it). 0/0 = no init found — the
|
/// identity-maps it and never allocates over it). 0/0 = no init found — the
|
||||||
/// kernel boots without user space. Grows into a full initial_ramdisk handoff later.
|
/// kernel boots without user space. Grows into a full initial_ramdisk handoff later.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! /sbin/bus — a user-space **bus driver**, and the smallest honest example of one.
|
//! /system/drivers/bus — a user-space **bus driver**, and the smallest honest example of one.
|
||||||
//!
|
//!
|
||||||
//! A bus driver owns a device that *contains other devices*, enumerates them by some
|
//! A bus driver owns a device that *contains other devices*, enumerates them by some
|
||||||
//! bus-specific protocol, and publishes each one into the kernel's device table so a
|
//! bus-specific protocol, and publishes each one into the kernel's device table so a
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! /sbin/hpet — a user-space HPET driver. It proves the whole driver model end to
|
//! /system/drivers/hpet — a user-space HPET driver. It proves the whole driver model end to
|
||||||
//! end: enumerate the device table, find the HPET, claim it, map its registers into
|
//! end: enumerate the device table, find the HPET, claim it, map its registers into
|
||||||
//! this ring-3 address space (strong-uncacheable), **bind its interrupt to an IPC
|
//! this ring-3 address space (strong-uncacheable), **bind its interrupt to an IPC
|
||||||
//! endpoint**, then sit blocked in `replyWait` until the hardware wakes it.
|
//! endpoint**, then sit blocked in `replyWait` until the hardware wakes it.
|
||||||
|
|||||||
@@ -272,18 +272,18 @@ fn kmain(boot_information: *const BootInformation) noreturn {
|
|||||||
log.checkpoint(cp_running);
|
log.checkpoint(cp_running);
|
||||||
status("kernel initialised.\n");
|
status("kernel initialised.\n");
|
||||||
|
|
||||||
// Hand over to user space: load /sbin/init (read off the boot volume by the
|
// 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. It runs on its own
|
// loader) and spawn it as a real ring-3 process, PID 1. It runs on its own
|
||||||
// address space, preemptively, alongside the kernel — no cooperative
|
// address space, preemptively, alongside the kernel — no cooperative
|
||||||
// borrowing. This boot context then becomes the BSP's idle loop.
|
// borrowing. This boot context then becomes the BSP's idle loop.
|
||||||
if (boot_information.init_len != 0) {
|
if (boot_information.init_len != 0) {
|
||||||
status("starting /sbin/init...\n");
|
status("starting /system/services/init...\n");
|
||||||
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
|
const image = @as([*]const u8, @ptrFromInt(boot_handoff.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
|
||||||
process.spawnProcess(image, 4) catch |err| {
|
process.spawnProcess(image, 4) catch |err| {
|
||||||
statusPrint("/sbin/init failed to load: {s}\n", .{@errorName(err)});
|
statusPrint("/system/services/init failed to load: {s}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
status("no /sbin/init on the boot volume.\n");
|
status("no /system/services/init on the boot volume.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn the extra user binaries the loader ferried in the initial_ramdisk (the VFS
|
// Spawn the extra user binaries the loader ferried in the initial_ramdisk (the VFS
|
||||||
@@ -294,7 +294,7 @@ fn kmain(boot_information: *const BootInformation) noreturn {
|
|||||||
// Become the idle task: drop below every real task and halt until an
|
// Become the idle task: drop below every real task and halt until an
|
||||||
// interrupt. The timer keeps preempting into init and any other work.
|
// interrupt. The timer keeps preempting into init and any other work.
|
||||||
scheduler.setPriority(0);
|
scheduler.setPriority(0);
|
||||||
status("\nkernel idle; /sbin/init is running.\n");
|
status("\nkernel idle; /system/services/init is running.\n");
|
||||||
architecture.halt();
|
architecture.halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ fn startInitialRamdiskBinaries(boot_information: *const boot_handoff.BootInforma
|
|||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < rd.count) : (i += 1) {
|
while (i < rd.count) : (i += 1) {
|
||||||
const item = rd.entry(i) orelse continue;
|
const item = rd.entry(i) orelse continue;
|
||||||
statusPrint("starting /sbin/{s} (from initial_ramdisk)...\n", .{item.name});
|
statusPrint("starting {s} (from initial-ramdisk)...\n", .{item.name});
|
||||||
process.spawnProcess(item.blob, 4) catch |err| {
|
process.spawnProcess(item.blob, 4) catch |err| {
|
||||||
statusPrint("initial_ramdisk: {s} failed to load: {s}\n", .{ item.name, @errorName(err) });
|
statusPrint("initial_ramdisk: {s} failed to load: {s}\n", .{ item.name, @errorName(err) });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! loader; in-kernel code is linked into the kernel image, not loaded here.
|
//! loader; in-kernel code is linked into the kernel image, not loaded here.
|
||||||
//!
|
//!
|
||||||
//! Two entry points:
|
//! Two entry points:
|
||||||
//! - `spawnProcess` loads a user ELF (`/sbin/init`, and later servers/drivers)
|
//! - `spawnProcess` loads a user ELF (`/system/services/init`, and later servers/drivers)
|
||||||
//! into a fresh address space and schedules it as a real preemptive ring-3
|
//! into a fresh address space and schedules it as a real preemptive ring-3
|
||||||
//! process on its own page tables. This is the production path.
|
//! process on its own page tables. This is the production path.
|
||||||
//! - `run` executes a raw code blob (the user-pf isolation test program) on the
|
//! - `run` executes a raw code blob (the user-pf isolation test program) on the
|
||||||
@@ -448,7 +448,7 @@ pub fn run(blob: []const u8) RunError!void {
|
|||||||
pmm.free(stack_frame);
|
pmm.free(stack_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- user ELF loading (/sbin/init) ------------------------------------------
|
// --- user ELF loading (/system/services/init) ------------------------------------------
|
||||||
|
|
||||||
pub const InitError = error{
|
pub const InitError = error{
|
||||||
BadElf, // malformed/inapplicable image (magic, class, machine, type, bounds)
|
BadElf, // malformed/inapplicable image (magic, class, machine, type, bounds)
|
||||||
|
|||||||
@@ -868,7 +868,7 @@ fn procWorker() void {
|
|||||||
scheduler.exit();
|
scheduler.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Real processes: load /sbin/init as TWO scheduled ring-3 processes, each with
|
/// Real processes: load /system/services/init as TWO scheduled ring-3 processes, each with
|
||||||
/// its own address space at the same virtual addresses, running concurrently
|
/// its own address space at the same virtual addresses, running concurrently
|
||||||
/// with a kernel task. Both must make heartbeat syscalls from CPL 3 — which can
|
/// with a kernel task. Both must make heartbeat syscalls from CPL 3 — which can
|
||||||
/// only happen if each runs on its own page tables (CR3 switched correctly per
|
/// only happen if each runs on its own page tables (CR3 switched correctly per
|
||||||
@@ -876,7 +876,7 @@ fn procWorker() void {
|
|||||||
/// strongest cheap proof of address-space isolation.
|
/// strongest cheap proof of address-space isolation.
|
||||||
fn processTest(boot_information: *const BootInformation) void {
|
fn processTest(boot_information: *const BootInformation) void {
|
||||||
log("DANOS-TEST-BEGIN: process\n", .{});
|
log("DANOS-TEST-BEGIN: process\n", .{});
|
||||||
check("bootloader handed over sbin/init", boot_information.init_len != 0);
|
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
|
||||||
if (boot_information.init_len == 0) {
|
if (boot_information.init_len == 0) {
|
||||||
result();
|
result();
|
||||||
return;
|
return;
|
||||||
@@ -920,14 +920,14 @@ fn userPfTest() void {
|
|||||||
log("DANOS-TEST-RESULT: FAIL (user read of kernel memory did not fault)\n", .{});
|
log("DANOS-TEST-RESULT: FAIL (user read of kernel memory did not fault)\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The full PID-1 path: the bootloader read sbin/init off the boot volume and
|
/// The full PID-1 path: the bootloader read /system/services/init off the boot volume and
|
||||||
/// handed it over; load it as a user ELF and spawn it as a real ring-3 process
|
/// handed it over; load it as a user ELF and spawn it as a real ring-3 process
|
||||||
/// — the same call the normal boot path makes — then confirm it beats. init
|
/// — the same call the normal boot path makes — then confirm it beats. init
|
||||||
/// heartbeats forever, so this proves it reaches ring 3, makes repeated syscalls
|
/// heartbeats forever, so this proves it reaches ring 3, makes repeated syscalls
|
||||||
/// (write + sleep), and stays alive rather than exiting.
|
/// (write + sleep), and stays alive rather than exiting.
|
||||||
fn initTest(boot_information: *const BootInformation) void {
|
fn initTest(boot_information: *const BootInformation) void {
|
||||||
log("DANOS-TEST-BEGIN: init\n", .{});
|
log("DANOS-TEST-BEGIN: init\n", .{});
|
||||||
check("bootloader handed over sbin/init", boot_information.init_len != 0);
|
check("bootloader handed over /system/services/init", boot_information.init_len != 0);
|
||||||
if (boot_information.init_len == 0) {
|
if (boot_information.init_len == 0) {
|
||||||
result();
|
result();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! /sbin/init — the first user-space program, PID 1. Built as its own
|
//! /system/services/init — the first user-space program, PID 1. Built as its own
|
||||||
//! freestanding binary (see build.zig), shipped on the boot volume at sbin/init,
|
//! freestanding binary (see build.zig), shipped on the boot volume at /system/services/init,
|
||||||
//! loaded by the bootloader, and started in ring 3 as a scheduled process by the
|
//! loaded by the bootloader, and started in ring 3 as a scheduled process by the
|
||||||
//! kernel (system/kernel/process.zig). It links against the shared user runtime
|
//! kernel (system/kernel/process.zig). It links against the shared user runtime
|
||||||
//! library `runtime` and talks to the kernel only through `runtime`'s system_call wrappers.
|
//! library `runtime` and talks to the kernel only through `runtime`'s system_call wrappers.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! /sbin/vfstest — a client that proves the VFS round trip end to end: open a
|
//! /system/services/vfs/vfs-test — a client that proves the VFS round trip end to end: open a
|
||||||
//! file through the `runtime` file API, write to it, seek back, read it, and compare.
|
//! file through the `runtime` file API, write to it, seek back, read it, and compare.
|
||||||
//! On success it heartbeats "vfstest: ok" so the kernel test can observe it;
|
//! On success it heartbeats "vfstest: ok" so the kernel test can observe it;
|
||||||
//! on failure it reports what went wrong. Shipped in the initial_ramdisk alongside vfs.
|
//! on failure it reports what went wrong. Shipped in the initial_ramdisk alongside vfs.
|
||||||
|
|||||||
+2
-2
@@ -169,12 +169,12 @@ CASES = [
|
|||||||
{"name": "user-pf",
|
{"name": "user-pf",
|
||||||
"expect": r"page fault \(vector 14\)[\s\S]*error code : 0x5[\s\S]*IP\s*: 0x00007000000000",
|
"expect": r"page fault \(vector 14\)[\s\S]*error code : 0x5[\s\S]*IP\s*: 0x00007000000000",
|
||||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||||
# The real user binary: the bootloader ships sbin/init off the ESP, the
|
# The real user binary: the bootloader ships /system/services/init off the ESP, the
|
||||||
# kernel loads the ELF and runs it in ring 3, and it writes + exits cleanly.
|
# kernel loads the ELF and runs it in ring 3, and it writes + exits cleanly.
|
||||||
{"name": "init",
|
{"name": "init",
|
||||||
"expect": r"DANOS-TEST-RESULT: PASS",
|
"expect": r"DANOS-TEST-RESULT: PASS",
|
||||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||||
# Real processes: /sbin/init loaded as a scheduled ring-3 process with its
|
# Real processes: /system/services/init loaded as a scheduled ring-3 process with its
|
||||||
# own address space, run twice (create/exit/teardown/recreate), coexisting
|
# own address space, run twice (create/exit/teardown/recreate), coexisting
|
||||||
# with a kernel task under preemption.
|
# with a kernel task under preemption.
|
||||||
{"name": "process",
|
{"name": "process",
|
||||||
|
|||||||
Reference in New Issue
Block a user