Ship more than one user binary: the bootloader now ferries an initrd bundle
(the VFS server + future drivers) alongside sbin/init, and the kernel unpacks
and spawns each program.
- src/user/proto/initrd.zig: the container format (Header{magic,count} +
Entry{name[32],offset,len} + blobs) with a validating Reader, shared by the
kernel and the packer.
- tools/mkinitrd.py: host-side packer (Python — trivial format, and sidesteps
the reworked Zig 0.16 std fs/args API). build.zig runs it on the built user
binaries via addSystemCommand and installs initrd.img to zig-out/bin + the
ESP root.
- BootInfo gains initrd_base/initrd_len; efi.zig loadInit refactored into a
shared loadFile, and loadInitrd ferries \initrd.img into surviving
LoaderData like init.
- main.zig startInitrdBinaries(): parse the image, spawn every entry (kernel-
spawns-all for now; init takes over via sys_spawn later).
- sbin/vfs.zig: a heartbeat stub (the real VFS server is M9), packed into the
initrd to prove the pipeline.
- New `initrd` test: parse + spawn + confirm the vfs stub reaches ring 3 and
heartbeats. Harness ships initrd.img on the ESP. Suite 30/30.
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Build-time initrd packer. Concatenates user binaries into one image the
|
|
bootloader ferries to the kernel.
|
|
|
|
Usage: mkinitrd.py <out.img> [<name> <file>]...
|
|
|
|
Image layout (little-endian), mirroring src/user/proto/initrd.zig:
|
|
Header : magic u32 ("DNRD"=0x444E5244), count u32
|
|
Entry*N : name [32]u8 (NUL-padded), offset u64, len u64
|
|
blobs : each entry's file bytes at its offset
|
|
"""
|
|
import struct
|
|
import sys
|
|
|
|
MAGIC = 0x444E5244
|
|
HEADER = struct.Struct("<II") # magic, count
|
|
ENTRY = struct.Struct("<32sQQ") # name[32], offset, len
|
|
|
|
|
|
def main() -> int:
|
|
out_path = sys.argv[1]
|
|
rest = sys.argv[2:]
|
|
if len(rest) % 2 != 0:
|
|
sys.stderr.write("usage: mkinitrd.py <out.img> [<name> <file>]...\n")
|
|
return 2
|
|
items = [(rest[i], rest[i + 1]) for i in range(0, len(rest), 2)]
|
|
|
|
table_end = HEADER.size + len(items) * ENTRY.size
|
|
entries = b""
|
|
blobs = []
|
|
off = table_end
|
|
for name, path in items:
|
|
with open(path, "rb") as f:
|
|
data = f.read()
|
|
entries += ENTRY.pack(name.encode()[:31], off, len(data))
|
|
blobs.append(data)
|
|
off += len(data)
|
|
|
|
with open(out_path, "wb") as f:
|
|
f.write(HEADER.pack(MAGIC, len(items)))
|
|
f.write(entries)
|
|
for b in blobs:
|
|
f.write(b)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|