Phase 8 C (1/n): QEMU harness now preserves NVRAM across runs
Scoping Phase C (the MINT word) surfaced a real blocker: "mint one Zuse, ever" needs the cert to survive reboots, but the qemu target copied a fresh, pristine OVMF_VARS.fd on every invocation -- a UEFI-NVRAM-based cert would never persist under this project's own normal test workflow. Digging further, aarch64 had no persistent NVRAM store at all (single -bios arg, no split VARS pflash like amd64/riscv64). Fixed rather than switching storage substrates: amd64/riscv64 now only copy the VARS template if the destination doesn't already exist, so `clean` (which deletes the whole build tree) is the bleach step and a bare `make qemu` preserves NVRAM -- matching the existing "always clean before qemu" acceptance convention exactly. aarch64 restructured to split CODE(ro)/VARS(rw) pflash drives matching the other two, with a graceful fallback to the old -bios mode on hosts without split firmware. Also resolves two design questions before any cert code: Zuse doesn't need Milestone 6's CA (that's the capsule-signing chain, a separate trust domain -- Zuse is a self-sovereign instance-local root of trust), and flags that this session's own earlier vm_zuse_cert_install() storage (16 bytes) is too small for a real Ed25519 keypair. Verified: all three architectures boot clean to ok> with the new pflash arrangement, Stadium conservation intact, no panics or guest errors. Infrastructure-only -- no cert code yet. Documented in FABRIC-3.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
53e6c5709f
commit
f223a31cec
+43
@@ -432,6 +432,49 @@ decisions get added here, not to `FABRIC-2.md`. Follow the same discipline `FABR
|
||||
keypair needs to chain to the Milestone 6 offline root CA or is a self-sovereign
|
||||
instance-local root of trust.
|
||||
|
||||
**Phase C scoping, 2026-08-26.** Three findings before any code:
|
||||
|
||||
1. **Resolved, not a real conflict: Zuse doesn't need Milestone 6's CA.** That CA chain is
|
||||
specifically for *capsule/code signing* (root → snakeoil intermediate → per-capsule
|
||||
Ed25519 signatures verified at capsule-load time) — a different trust domain from *user
|
||||
identity*. The vision's own framing ("we mint one and only one Zuse user and blow a fuse
|
||||
... the only way around is a new system") already implies Zuse's authority comes from
|
||||
being the unique first-boot mint on *this instance*, not from an external chain.
|
||||
**Decided: Zuse is a self-sovereign, instance-local root of trust**, keypair generated
|
||||
on-device from real entropy (Phase A+B). Regular users, minted later via `MINT`, get
|
||||
certs signed by *Zuse's* key, not the Milestone 6 CA — two independent PKI domains.
|
||||
2. **A real gap in this session's own earlier work:** `vm_zuse_cert_install(vm, lo, hi)`
|
||||
(the very first change this session made, before Phase A existed) only holds two
|
||||
`uint64_t` (16 bytes) — sized against the old placeholder `ZUSE-CERT-LO`/`HI` FORTH-cell
|
||||
design, not against what a real Ed25519 keypair needs (32-byte pubkey alone, well over
|
||||
100 bytes for a full cert). Needs expanding before Phase C can store anything real.
|
||||
3. **A genuine blocker, found by asking where the cert would actually live:** "mint once,
|
||||
ever" requires surviving reboots, but `Makefile.starkernel`'s `qemu` target copied a
|
||||
fresh, pristine `OVMF_VARS.fd` on *every* invocation (not just after `clean`) — so a
|
||||
UEFI-NVRAM-based cert (the real-hardware-compatible option, and this codebase already has
|
||||
a live `SetVariable`/`GetVariable` precedent via `SF_VAR_REBOOT_TRIES`/`SF_VAR_BOOT_ARGS`)
|
||||
would never actually persist under this project's own normal test workflow. Digging
|
||||
further: aarch64's `qemu` recipe had no persistent NVRAM store *at all* — a single
|
||||
combined `-bios $AAVMF_CODE` argument, no separate writable VARS pflash drive like
|
||||
amd64/riscv64 have. **Decided (on request): fix the harness rather than switch
|
||||
substrates.** amd64/riscv64: the VARS-template copy is now conditional on the destination
|
||||
not already existing, so `clean` (which deletes the whole `build/$(ARCH)/kernel` tree,
|
||||
`OVMF_VARS.fd`/`RISCV_VARS.fd` included) is the bleach step, and a bare `make qemu` now
|
||||
preserves NVRAM across runs — exactly matching the existing "always pass `clean` before
|
||||
`qemu`" acceptance convention, no new bleach script needed. aarch64: restructured to
|
||||
split CODE(ro)/VARS(rw) pflash drives matching the other two (host has
|
||||
`/usr/share/AAVMF/AAVMF_VARS.fd` alongside the existing `AAVMF_CODE.fd`), with a
|
||||
graceful fallback to the old single-`-bios` mode (and a console note) on a host that only
|
||||
has non-split firmware packaged, so this doesn't regress environments without one.
|
||||
**Verified live:** all three architectures still boot clean to `ok>` with the new
|
||||
pflash arrangement, Stadium conservation intact, no panics or guest errors — this is
|
||||
infrastructure-only (no cert code yet), so a plain boot-regression check is the right
|
||||
verification tier.
|
||||
|
||||
**Still open:** the actual cert struct (expanding past the 16-byte placeholder), the
|
||||
first-boot mint-vs-already-minted boot sequence using `SetVariable`/`GetVariable`, and the
|
||||
`MINT` word itself.
|
||||
|
||||
### From FABRIC-2.md §X, Milestone 5 — Console/VM key-match binding
|
||||
|
||||
- [ ] Settle the still-open question: reuse `ACL-PIN`/`acl_allow` directly, or build a
|
||||
|
||||
Reference in New Issue
Block a user