boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

commit 8e53781e5a0dd5b1a6b264ffee145d7e8a0f925a
parent 66f47611dd938c3f3a445b94fe4e42df02f8d175
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed,  6 May 2026 13:12:46 -0700

B (kernel.c polish): name DTB/PVH/cpio magics; document sys_unlinkat ignored args

- PVH_HVM_START_{MAGIC,OFF_CMDLINE} constants with the EBX-handoff ABI
  note from the (now-deleted) SEED-AMD64-TODO inlined where they're
  defined; parse_dtb's amd64 branch uses the names instead of literals.
- CPIO_NEWC_{MAGIC,HDR_SIZE,FIELD,MODE_TYPE_*}; parse_cpio + the
  blk_init probe drop the inline byte-by-byte magic check for
  str_starts(p, CPIO_NEWC_MAGIC).
- DTB header constants now have a one-line spec reference.
- sys_unlinkat: comment explaining why dirfd and flags are both ignored
  (flat path map; no dirs, so AT_REMOVEDIR is a no-op).

Diffstat:
Mseed-kernel/kernel.c | 59+++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 18 deletions(-)

diff --git a/seed-kernel/kernel.c b/seed-kernel/kernel.c @@ -118,6 +118,8 @@ static u64 be64(const u8 *p) { return ((u64)be32(p) << 32) | (u64)be32(p + 4); } /* ─── Flattened Device Tree walker ──────────────────────────────────────── */ +/* DTB ("flattened device tree blob") header + token codes — devicetree + * spec §5.1 (header) + §5.4.1 (struct block tokens). */ #define FDT_MAGIC 0xd00dfeedu #define FDT_BEGIN_NODE 1 #define FDT_END_NODE 2 @@ -125,6 +127,26 @@ static u64 be64(const u8 *p) { return ((u64)be32(p) << 32) | (u64)be32(p + 4); } #define FDT_NOP 4 #define FDT_END 9 +/* Xen PVH ABI handoff (see Xen's docs/misc/pvh.pandoc). On PVH boot QEMU + * points EBX at a `struct hvm_start_info`; the amd64 long-mode init in + * arch/amd64/kernel.S preserves EBX through to kmain's `dtb_phys` arg. + * First word is the magic; cmdline_paddr sits at offset 0x18. microvm + * has no DTB, so this is the only path for `qemu -append "..."`. */ +#define PVH_HVM_START_MAGIC 0x336ec578u +#define PVH_HVM_START_OFF_CMDLINE 0x18 + +/* cpio "newc" (SVR4 portable) format — first 6 bytes of every header + * record are the magic; header is fixed-size (110 bytes) followed by + * the NUL-terminated name and the file data, both 4-byte padded. The + * 13 numeric fields are 8-char ASCII hex starting at offset 6. Spec: + * cpio(5) under "New ASCII Format". */ +#define CPIO_NEWC_MAGIC "070701" +#define CPIO_NEWC_HDR_SIZE 110 +#define CPIO_NEWC_FIELD(p, n) ((p) + 6 + (n) * 8) +#define CPIO_MODE_TYPE_MASK 0xf000 /* st_mode file-type bits */ +#define CPIO_MODE_TYPE_DIR 0x4000 +#define CPIO_MODE_TYPE_REG 0x8000 + /* QEMU virt has 32 virtio-mmio slots (0x0a000000..0x0a004000, 0x200 each). * Most are unpopulated and report MagicValue=0/DeviceID=0 — we capture all * slots advertised by the DTB and the driver init filters at probe time. */ @@ -146,11 +168,9 @@ static int str_starts(const char *s, const char *prefix) { static void parse_dtb(const void *dtb, struct dtb_info *out) { #ifdef ARCH_STATIC_VIRTIO_MMIO_BASE - /* amd64 (microvm) has no DTB. mem + virtio-mmio come from arch.h - * defines, and the kernel cmdline (qemu -append "...") arrives via - * the PVH `hvm_start_info` struct that QEMU points EBX at. The - * Xen-defined magic is XEN_HVM_START_MAGIC_VALUE = 0x336ec578; - * cmdline_paddr lives at offset 0x18. */ + /* No DTB on this arch (amd64 microvm). mem + virtio-mmio come from + * arch.h compile-time constants; the kernel cmdline arrives via the + * PVH hvm_start_info struct (see PVH_HVM_START_* above). */ out->mem_start = ARCH_STATIC_MEM_START; out->mem_size = ARCH_STATIC_MEM_SIZE; out->virtio_mmio_n = ARCH_STATIC_VIRTIO_MMIO_COUNT; @@ -160,8 +180,8 @@ static void parse_dtb(const void *dtb, struct dtb_info *out) { if ((u64)dtb != 0) { const u8 *p = dtb; u32 magic = (u32)p[0] | ((u32)p[1] << 8) | ((u32)p[2] << 16) | ((u32)p[3] << 24); - if (magic == 0x336ec578U) { - const u8 *cp = p + 0x18; + if (magic == PVH_HVM_START_MAGIC) { + const u8 *cp = p + PVH_HVM_START_OFF_CMDLINE; u64 cmdline_paddr = 0; for (int i = 0; i < 8; i++) cmdline_paddr |= (u64)cp[i] << (i * 8); if (cmdline_paddr) { @@ -567,8 +587,7 @@ static void blk_init(struct dtb_info *dt) { uart_putd((i64)i); uart_puts("\n"); hang(); } - int is_cpio = (probe[0]=='0' && probe[1]=='7' && probe[2]=='0' && - probe[3]=='7' && probe[4]=='0' && probe[5]=='1'); + int is_cpio = str_starts((const char *)probe, CPIO_NEWC_MAGIC); if (is_cpio) { if (g_blk_input >= 0) { uart_puts("[seed] virtio-blk: multiple cpio disks\n"); @@ -707,20 +726,20 @@ static u64 hex_n(const char *s, int n) { static void parse_cpio(const void *cpio, u64 total) { const u8 *p = cpio; const u8 *end = p + total; - while (p + 110 <= end) { - if (!(p[0]=='0'&&p[1]=='7'&&p[2]=='0'&&p[3]=='7'&&p[4]=='0'&&p[5]=='1')) break; - u64 mode = hex_n((const char *)(p + 6 + 1*8), 8); - u64 fsz = hex_n((const char *)(p + 6 + 6*8), 8); - u64 nsz = hex_n((const char *)(p + 6 + 11*8), 8); - const char *name = (const char *)(p + 110); + while (p + CPIO_NEWC_HDR_SIZE <= end) { + if (!str_starts((const char *)p, CPIO_NEWC_MAGIC)) break; + u64 mode = hex_n((const char *)CPIO_NEWC_FIELD(p, 1), 8); + u64 fsz = hex_n((const char *)CPIO_NEWC_FIELD(p, 6), 8); + u64 nsz = hex_n((const char *)CPIO_NEWC_FIELD(p, 11), 8); + const char *name = (const char *)(p + CPIO_NEWC_HDR_SIZE); if (str_eq(name, "TRAILER!!!")) break; - u64 hstride = (110 + nsz + 3) & ~3UL; + u64 hstride = (CPIO_NEWC_HDR_SIZE + nsz + 3) & ~3UL; u64 fstride = (fsz + 3) & ~3UL; const u8 *fdata = p + hstride; - int is_dir = ((mode & 0xf000) == 0x4000); - int is_reg = ((mode & 0xf000) == 0x8000); + int is_dir = ((mode & CPIO_MODE_TYPE_MASK) == CPIO_MODE_TYPE_DIR); + int is_reg = ((mode & CPIO_MODE_TYPE_MASK) == CPIO_MODE_TYPE_REG); if (is_reg && !str_eq(name, ".")) { int idx = new_file(name); if (idx >= 0) { @@ -940,6 +959,10 @@ static i64 sys_brk(u64 addr) { } static i64 sys_unlinkat(int dirfd, const char *path, int flags) { + /* dirfd is ignored: tmpfs is a flat path map, all callers pass + * AT_FDCWD. flags (AT_REMOVEDIR) is ignored too — there are no + * directories in our tmpfs, so the dir-vs-file distinction the + * flag selects has no observable effect. */ (void)dirfd; (void)flags; int fidx = find_file(path); if (fidx < 0) return -ENOENT;