Files
LithosAnanake/FABRIC-3.md
T
Robert Allan JamesandClaude Sonnet 5 7f9a4d4d4a
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run
FABRIC-3.md: three per-architecture bare-metal-boot planning sections
Per direct instruction: amd64's real goal is genericity (any x86_64
laptop/desktop/tower/mini, not just the Beelink SER5 reference
machine); aarch64 targets the Raspberry Pi 5 exclusively; riscv64
targets the Milk-V Mars exclusively -- no cross-board genericity
requirement for the latter two, unlike amd64.

Each section starts from what's already true (ROADMAP.md's existing
v2.2.0/v2.4.0/v2.5.0 board-by-board gates, the already-built
thumbdrive/iso-usb Makefile targets, the amd64 RDRAND backend) and
names what's genuinely still unknown rather than assuming -- most
notably whether the Milk-V Mars boots via UEFI (like this project's
QEMU riscv64 target) or via U-Boot+OpenSBI+devicetree, which would
need a different boot entry path, not just different peripheral
addresses.

Doc-only change, no acceptance build needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
2026-09-04 12:02:45 -04:00

207 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FABRIC-3.md — bare metal boot
**Status:** Living working document, opened 2026-09-04 as the successor to `FABRIC-2.md`
(now closed/archival — see its own header). Topic for this document, per direct instruction:
**bare metal boot** — getting LithosAnanke to actually boot on real hardware, not just QEMU.
`FABRIC-2.md` §I.6 (Milestone 8) already named this as the one item that pass couldn't close
from a coding session at all, for exactly this reason — it needs a real machine and a human
physically present. This document is where that work, and everything downstream of it, gets
tracked.
**How to use this document going forward.** New findings, new punch-list items, and new
decisions for bare-metal-boot work get added here, not to `FABRIC-2.md`. Same discipline every
prior document in this series used: write the decision and its reasoning down before building,
close items with a dated note citing real evidence, never silently drop a stale claim.
---
## I.1 — Task 1: merge `v2.0.1` into `master`, verify build/function equivalence
**Written up before executing**, per direct instruction and this series' own standing
discipline.
**Why this is task 1.** `FABRIC-2.md`'s entire 7-step closure pass (§I.1–§I.5, §I.7, plus
today's FABRIC-series rename) happened on the `v2.0.1` branch, not `master`. Before any real
bare-metal-boot work starts, that work needs to land where `.claude/CLAUDE.md` says the
project's sole production line actually lives: `master`. Doing this first, cleanly, before
starting new work avoids ever having two divergent lines to reconcile later.
**Investigated before writing this up, not assumed:**
- `git merge-base --is-ancestor master v2.0.1`**true**. `master` (local HEAD `d2a0305`) is
a strict ancestor of `v2.0.1` (HEAD `b031b80`) — `v2.0.1` is exactly `master` plus 47 commits
forward, no divergent history on either side. This means the "merge" is a pure **fast-forward**,
not a real three-way merge — nothing to resolve, no conflict possible.
- `origin/master` carries exactly one commit beyond local `master` (`58c59e8`, "Initial
commit") that local `master` hadn't fetched yet — confirmed already contained in `v2.0.1`'s
own history (`git merge-base --is-ancestor 58c59e8 v2.0.1` — true), so it introduces no
discrepancy either.
- `master`'s own tree still has the *old* `FABRIC.md`/`FABRIC-2.md`/`FABRIC-3.md` naming
(unrenamed) — expected, since today's rename commit (`b031b80`) only exists on `v2.0.1` so
far. The fast-forward brings the rename to `master` along with everything else; nothing
separate needs doing for it.
**Plan:**
1. Fast-forward `master` to `v2.0.1`'s tip (`git checkout master && git merge --ff-only v2.0.1`)
— refuses loudly instead of silently doing a real merge if the ancestor relationship somehow
isn't what the investigation above found, so this step re-verifies its own precondition.
2. Push `master` to `origin`.
3. **Verify build/function equivalence on a genuinely clean tree**, not by inference: `git clean`
(after confirming nothing untracked-but-wanted is present), then the full acceptance sequence
`.claude/CLAUDE.md` already mandates for any kernel change — `clean qemu` on all three
architectures, in the foreground, one at a time, each reaching `ok>` and shutting down
cleanly. Since the tree is byte-identical to `v2.0.1`'s post-fast-forward, this is expected
to reproduce exactly what `v2.0.1`'s own last acceptance pass already showed — the point of
re-running it here is to confirm that expectation holds on `master` itself, not to assume it
from the fast-forward alone.
4. Return to `v2.0.1` as the working branch afterward (`.claude/CLAUDE.md`'s own rule: always
return to the correct working branch after any out-of-branch work), unless told otherwise.
**DONE 2026-09-04, exactly as planned:**
1. Committed the write-up above on `v2.0.1` first (`72c14cb`), pushed. This became `v2.0.1`'s
new tip.
2. `git checkout master && git merge --ff-only v2.0.1`**Fast-forward**, `d2a0305..72c14cb`,
confirming the investigated ancestor relationship held exactly as expected; no conflict, no
merge commit.
3. `git push origin master``origin/master` moved `58c59e8..72c14cb`.
4. **Verified on a genuinely clean `master` tree**, not inferred from the fast-forward:
- Hosted build (`make clean && make`): clean compile, zero warnings, same as `v2.0.1`.
- Full 3-arch kernel acceptance (`clean qemu`, amd64/aarch64/riscv64, each in the foreground):
all three reached `(zuse) ok>`/`ok>` and shut down cleanly, zero build errors, zero
unexpected warnings — identical outcome to `v2.0.1`'s own last acceptance pass, confirmed
directly rather than assumed. Logs: `logs/20260904-113208/amd64/`,
`logs/20260904-113320/aarch64/`, `logs/20260904-113552/riscv64/`.
5. `master` and `v2.0.1` are now identical (`72c14cb` on both, `origin` and local). Returned to
`v2.0.1` as the working branch per plan step 4.
**Task 1 closed.** `master` genuinely is the production line again, current through today's
FABRIC-series rename and the full `FABRIC-2.md` §I closure. Bare-metal-boot work (this
document's actual topic) starts from here.
## I.2 — Task 2: version correction — the `v2.0.1` bump and `v2.0.0` tag were premature
**Direct instruction, 2026-09-04**: the `LITHOS_VERSION` bump to `2.0.1` (and the branch name
that followed it) got ahead of the real state — per `Makefile.starkernel`'s own versioning
policy (`v2.0.0` = QEMU release, even major/LTS; `v2.0.1` = the SER5 hardware-track *line*,
RDRAND backend + thumbdrive image goal), claiming `2.0.1` implies hardware-track progress that
was never actually verified on real hardware — that verification is precisely `FABRIC-3.md`'s
whole open topic (§I.6 in the closed `FABRIC-2.md`). The current `master` HEAD is, correctly,
still a `v2.0.0`-class QEMU-only release. "Nothing harmful" — a version-label correction, not a
functional rollback.
**Found and fixed while correcting this, not left half-done:**
- A real gap in the FABRIC-series rename from earlier today: `Makefile.starkernel`,
`Kconfig.kernel`, `scripts/bleach_zuse_img.sh`, four `proof/*.thy` files, and
`src/starkernel/arch/amd64/isr.S` all still had stale `FABRIC.md`/`FABRIC-2.md`/`FABRIC-3.md`
citations — the original sweep's file-list only matched `--include=*.md/*.c/*.h/*.4th`, which
silently skipped every file without one of those four extensions. Found by re-grepping with
the extensions excluded instead of included. Fixed with the same safe placeholder-substitution
technique the original rename used (each file, one pass, ordered `FABRIC-3→2→1→0` placeholders
then resolved) — verified no double-shifted or broken references remained afterward.
`.claude/settings.local.json`'s own historical Bash-permission-grant log (literal past command
strings naming the file as it was called *at the time*) was deliberately left alone — rewriting
it would falsify an audit trail, not fix a stale citation.
- `ClaudeEXPORT/memories.json`/`conversations.json` also still reference the old names — left
untouched on purpose, same reasoning as the memory note on that archive: it's a frozen export,
mining material, not live documentation to keep in sync.
**Changes:**
1. `Makefile.starkernel`: `LITHOS_VERSION ?= 2.0.1``2.0.0`.
2. The rename-gap fix above (7 files).
3. Verified 3-arch boot (`clean qemu`, amd64/aarch64/riscv64, each in the foreground): all three
show `LithosAnanke v2.0.0` in the boot banner (confirmed directly in each serial log, not
assumed from the Makefile edit alone), zero build errors, zero unexpected warnings, clean
shutdown.
4. Moved the existing `v2.0.0` git tag (previously at `2efd7fe`, the original QEMU-release
milestone commit — that commit and its own message stay fully intact in history, only the
tag pointer moves) to the current `master`/`v2.0.1`-branch HEAD, per explicit instruction —
the prior tag placement was itself part of the same "got ahead of myself" correction, not a
separate decision. No remote tag existed yet (`git ls-remote --tags origin` was empty for
`v2.0.0`), so no destructive remote operation was needed, only a local move-and-push.
5. **Follow-up, same day**: `v2.0.1` (the working branch this and Task 1 happened on) deleted,
local and `origin` — confirmed a strict ancestor of `master`'s new HEAD first, so nothing
was lost. `master` is the repo's only branch from here on.
---
## II. Three architectures, three different hardware scopes
Per direct instruction, 2026-09-04. The real-hardware targets are **not** symmetric across
architectures — each gets its own section below because the actual scope of "done" is
different for each:
- **amd64 — genericity is the goal, not just the SER5.** The Beelink SER5 is the machine in
hand and the development/reference target, but the real requirement is broader: this needs
to boot on *any* x86_64 machine — laptop, desktop, tower, or mini PC — not just one vendor's
quirks. SER5-only success is necessary but not sufficient; anything that works only because
of an SER5-specific assumption (a particular ACPI table shape, a specific UEFI
implementation's quirks) is a bug against this goal, not a deferred nice-to-have.
- **aarch64 — Raspberry Pi 5, and only the Raspberry Pi 5.** No genericity requirement across
aarch64 boards — this is the one and only target for this architecture.
- **riscv64 — Milk-V Mars, and only the Milk-V Mars.** Same as aarch64: one specific board,
not a generic riscv64-SBC goal.
**How to use sections IIIV below.** Same discipline as everything else in this series: plan
before building, one section at a time, iterating — not all three architectures in parallel,
and not front-loading a complete plan before any real hardware is in front of us. Each section
starts with what's already true (existing repo infrastructure, already-decided policy) and
what's still genuinely unknown, not assumed.
## III. amd64 — generic x86_64 bare metal (reference hardware: Beelink SER5)
**Already true, not to be re-derived:**
- `ROADMAP.md`'s "Board-by-board hardware rollout" already names this `v2.2.0`'s gate: the
generic GPT/FAT32 thumbdrive image (`make -f Makefile.starkernel ARCH=amd64 thumbdrive`,
already built — `Makefile.starkernel:1018`) flashes to and boots on the real SER5 via its
real UEFI, reaching POST + `ok>`, with the amd64 RDRAND entropy backend
(`src/starkernel/rng/rng.c`, already built and part of `master`) serving live entropy.
- `iso-usb` (`Makefile.starkernel:1060`) is the alternate, novice-friendly path (UEFI
isohybrid ISO for tools like GNOME Disks "Restore Disk Image...") — same underlying image,
different flashing UX.
- `FABRIC-2.md` §I.6's own 8-step physical-boot sequence (build ISO, identify the target
device, flash it, physically boot, decide an observation method, confirm POST, confirm
`ok>`, document) is the closest thing to an existing plan — but it predates the genericity
requirement and was written with no hardware in hand yet.
**Genuinely open, not yet decided:**
- What "generic enough" actually needs to be verified against, beyond the SER5 — is there a
second, different machine available to cross-check against, or does genericity get argued
from firmware-standards-compliance (real UEFI, no vendor-specific assumptions in the boot
code) rather than a second physical test right away?
- Observation method for a headless/serial-less real machine (no QMP/serial socket the way
QEMU gives us) — HDMI + keyboard? A serial console cable if the board exposes UART pins?
- Whether Secure Boot needs handling, and how, on real UEFI firmware (QEMU/OVMF's own Secure
Boot behavior may not match every real vendor's).
## IV. aarch64 — Raspberry Pi 5
**Already true:** `ROADMAP.md` names this `v2.4.0`'s gate: boots on the real board, aarch64
peripheral-RNG backend live, Zuse mint/attach on real media. The peripheral-RNG backend itself
is **not yet built** — today's `rng_get_bytes()` (`src/starkernel/rng/rng.c`) only has a
`virtio-rng` path, real on QEMU, meaningless on real Pi 5 hardware (no virtio device there).
**Genuinely open, not yet decided:**
- Raspberry Pi 5's own boot chain — UEFI (e.g. via the community EDK2 port) or the Pi's native
boot flow? This determines whether the existing UEFI-targeted boot code needs a different
entry path for this board at all, or just different ACPI/DTB-provided data.
- Which peripheral RNG the Pi 5 actually exposes, and how to read it (memory-mapped peripheral
vs. a firmware call) — not yet researched.
- Same observation-method question as amd64 (no QEMU serial socket on real hardware) —
possibly shared tooling/approach across both boards once decided once.
## V. riscv64 — Milk-V Mars
**Already true:** `ROADMAP.md` names this (generically, "Milk-V") as part of `v2.5.0`'s gate:
boots on the real board, the Zkr (RNDR) entropy backend live. Same gap as aarch64:
`rng_get_bytes()` has no riscv64 hardware-RNG path today, only `virtio-rng`.
**Genuinely open, not yet decided:**
- Milk-V Mars's actual boot chain — this project's QEMU riscv64 target boots via UEFI
(EDK2 `RISCV_VIRT` firmware, confirmed in `Makefile.starkernel`'s own `qemu` recipe), but
real riscv64 SBCs commonly boot via U-Boot + OpenSBI + a devicetree instead of UEFI. Which
one the Mars actually uses is not yet confirmed — this is the single most consequential
unknown across all three sections, since it could mean this board needs a genuinely
different boot entry path, not just different peripheral addresses.
- Zkr/RNDR instruction availability on the Mars's actual CPU (riscv64 Scalar Crypto extension
support varies by implementation) — not yet confirmed.
- Same observation-method question as the other two boards.