Files
danos/system/initial-ramdisk.zig
Daniel Samson ceacc6b514 Post-reorg cleanup: POSIX layer, and naming fixes
Follow-up to the monorepo re-org. Suite 35/35 plus host tests green.

POSIX compatibility is now its own library, library/posix/ (unistd, stdio),
layered strictly over the runtime — it calls the runtime's IPC/heap, never
system calls directly. The runtime is now POSIX-free (the danos-native
application ABI). The VFS wire protocol is danos-native throughout
(Stat -> FileStatus, .stat -> .status, O_CREAT -> create); the POSIX layer
maps the POSIX spellings at the boundary. The coding standard's ABI-name
exception is scoped to one place: a file is allowed POSIX spellings only if it
lives under library/posix/ — everywhere else, danos naming with no exception.

Naming fixes, all mechanical:
- initrd -> initial-ramdisk: the source file, the module, the tool
  (make-initial-ramdisk.py), the artifact (initial-ramdisk.img, including the
  bootloader's load path), and the identifiers.
- system/kernel/device-service.zig -> devices-broker.zig: it is ring-0 kernel
  code (the trusted device table + claim capability), not a ring-3 service. The
  future user-space device *manager* (policy) will live in system/services/.
- Dropped the daemon `d` suffix: hpetd -> hpet, busd -> bus. A driver lives in
  system/drivers/, so the folder already says what it is; encoding the role in
  the name too is redundant. The coding standard drops that exception.
- system/devices/aml/interp.zig -> interpreter.zig (the type was already
  Interpreter).
2026-07-10 13:33:06 +01:00

59 lines
2.4 KiB
Zig

//! The initial_ramdisk (initial ramdisk) container format — shared by the build-time
//! packer (tools/make-initial-ramdisk.py) and the kernel that unpacks it. Deliberately
//! trivial: a header, a table of fixed-size entries, then the concatenated file
//! blobs. We own both producer and consumer, so it need be no fancier.
//!
//! Layout:
//! Header (magic, count)
//! Entry * count (name, offset, len) — offset/len into the image
//! blob bytes... (each entry's file, at its offset)
const std = @import("std");
/// "DNRD" — identifies a danos initial_ramdisk image.
pub const magic: u32 = 0x444E5244;
pub const Header = extern struct {
magic: u32,
count: u32,
};
pub const Entry = extern struct {
name: [32]u8, // NUL-padded file name (basename)
offset: u64, // byte offset of the blob within the image
len: u64, // blob length in bytes
};
/// A validated view over an initial_ramdisk image. `init` checks the magic and that the
/// entry table fits; `entry` bounds-checks each blob against the image.
pub const Reader = struct {
image: []const u8,
count: u32,
pub fn init(image: []const u8) ?Reader {
if (image.len < @sizeOf(Header)) return null;
const h = std.mem.bytesToValue(Header, image[0..@sizeOf(Header)]);
if (h.magic != magic) return null;
const table_end = @sizeOf(Header) + @as(usize, h.count) * @sizeOf(Entry);
if (table_end > image.len) return null;
return .{ .image = image, .count = h.count };
}
pub const Item = struct { name: []const u8, blob: []const u8 };
pub fn entry(self: Reader, i: u32) ?Item {
if (i >= self.count) return null;
const off = @sizeOf(Header) + @as(usize, i) * @sizeOf(Entry);
const e = std.mem.bytesToValue(Entry, self.image[off..][0..@sizeOf(Entry)]);
if (e.offset > self.image.len or e.len > self.image.len - e.offset) return null;
// The name is stored in the entry's fixed field; return a stable slice
// into the image (not the value copy) up to the NUL terminator.
const name_field = self.image[off .. off + 32];
const nlen = std.mem.indexOfScalar(u8, name_field, 0) orelse name_field.len;
return .{
.name = name_field[0..nlen],
.blob = self.image[@intCast(e.offset)..][0..@intCast(e.len)],
};
}
};