danos/tools/make-initial-ramdisk.py

49 lines
1.4 KiB
Python

#!/usr/bin/env python3
"""Build-time initial_ramdisk packer. Concatenates user binaries into one image the
bootloader ferries to the kernel.
Usage: make-initial-ramdisk.py <out.img> [<name> <file>]...
Image layout (little-endian), mirroring src/user/proto/initial-ramdisk.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: make-initial-ramdisk.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())