Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/saf/device/build.md
Fimeg bde961c6f2 saf: one spine — device, state, and work under the index
PAF becomes saf/device (history kept), STATE.md dissolves
into saf/state.md with the dated era archived, the substrate
SAF moves up from souveraine, and every agreement points at
saf/INDEX.md and nowhere else. one map, nothing to remember
2026-08-18 09:47:30 -04:00

64 lines
3.3 KiB
Markdown

# PAF · Build & deploy (Arch era)
The loop that turns a kernel commit into a verified boot on glass. pmOS-era
pmbootstrap notes preserved at `evidence/build-pmos-era.md` — dead path now.
## The three places
| Where | Role |
|---|---|
| gitea `10.10.20.120:4455``Fimeg/Pixel3Arch` + `Fimeg/linux-blueline` (branch `blueline`) | **Source of truth.** Uncommitted work does not build — commit or it doesn't exist. |
| ArchDev LXC `casey@10.10.20.123` (ani key) | **Build host.** Cross toolchain installed, MAKEFLAGS system-wide. |
| Laptop | **Device ops only** — flashing, fastboot, USB tether, boot.img assembly. |
## The loop
1. Commit + push kernel changes to gitea (`kernel/src/linux-blueline-src`
on the laptop is a clone with remote `gitea`).
2. Build on ArchDev:
`ssh ... casey@10.10.20.123 'cd ~/Projects/Pixel3Arch/kernel && ./build.sh blueline'`
- build.sh **self-locks with flock** — invoke it directly, never wrap it
in an outer flock on the same lockfile (deadlock, cost a session).
- It force-fresh-clones from gitea and **hard-asserts the built package's
embedded commit hash matches the gitea branch tip** — a mismatch means
stale source; the build fails loud instead of shipping it.
3. Pull `kernel/linux-blueline-7.1.1-1-aarch64.pkg.tar.zst` to the laptop.
4. Assemble the boot image (pmOS-chain — the currently proven ramdisk path):
```
bash boot/build-bootimg-pmos-chain.sh <vmlinuz-from-pkg> <dtb-from-pkg> \
staging/deploy-139aa/boot-139aa7748181-pmoschain.img <out.img>
```
Kernel is Image.gz + **appended DTB** (header v0 ignores --dtb); ramdisk
and cmdline are lifted from the reference image. Migrating to our own
mkinitcpio ramdisk (`boot/build-bootimg.sh`) is a parked one-variable task.
5. Deploy: `scripts/deploy-kernel.sh <pkg.tar.zst> <boot.img>`
## Deploy doctrine — no chimera boots
`deploy-kernel.sh` exists because a kernel was once booted 28 seconds before
its module tree was installed: no evdev, no input, dead services, and a
night of void test results. The script enforces the only safe order:
1. **Modules first** — scp the pkg, `pacman -U`, verify the module dir exists.
2. Flash boot_a, reboot.
3. **Refuse to bless the boot** unless `uname -r` matches the installed tree.
Never flash-then-install. If `uname -r` and `/usr/lib/modules/` disagree,
every test result on that boot is garbage — reboot properly before
concluding anything.
## Gotchas ledger (each cost a session)
- makepkg needs `CARCH=aarch64 ... --ignorearch` — CARCH comes from the
environment, not the PKGBUILD, or you get x86_64-labeled aarch64 packages.
- makepkg builds in its own clone of `source=()`, not your working tree —
a dirty tree silently builds without your changes.
- The kernel release string embeds the git hash (`-g<hash>`) — it is the
ground truth for "what am I actually running" (`uname -r`).
- `modules_install` needs CROSS_COMPILE too, or strip fails on aarch64 .ko.
- ArchDev is unprivileged LXC: qemu-emulated execution (binfmt) does NOT
work there — chroot-based work stays on the laptop or on-device.
- Commit messages: history in this repo proved that "evidence" cited in
rapid-fire commits can be wrong (see touch.md, display.md post-mortems).
Cite the actual file:line / register / boot you verified on, and note
whether the boot was clean.