deploy: bootable slim Sintra image + shared UP Board serial hardware #72

Merged
padreug merged 3 commits from deploy/sintra-boot-hardware into dev 2026-07-02 21:53:29 +00:00
Owner

Deploy/build-infra changes, split out from the #70 pairing arc (companion PR) since they're orthogonal to the app logic and independently reviewable/mergeable. All three verified on the physical Sintra.

Commits

  • perf(deploy): slim the kiosk closure — disable TTS (speechd), Qt, and docs in the kiosk config. Closure 6.2 → 5.0 GiB; distributable image 10 GiB → 2.2 GiB compressed.
  • fix(deploy): make disk-image-sintra-usb BIOS+UEFI bootable (GRUB) — make-disk-image's efi table produces a UEFI-only (systemd-boot) image; the Sintra's Aaeon firmware USB-boots in Legacy/BIOS mode (it boots the live ISO via isolinux, not the ESP), so a dd'd image wasn't recognised. Switch the USB target to GRUB with BIOS and UEFI on the hybrid table (adds a bios_grub partition; GRUB writes its BIOS stage to the MBR + a removable BOOTX64.EFI). Scoped to the USB image; the eMMC install keeps systemd-boot. Verified: the Sintra now lists + boots the USB.
  • refactor(deploy): share UP Board serial hardware between installed + live ISO — the sintra live ISO had no ftdi_sio / ttyJ5/ttyJ7 udev (validator + F56 dispenser failed on iso-sintra), while the installed image had them inline in upboard.nix — two definitions that had already drifted. Extract to hardware/upboard-serial.nix, imported by both upboard.nix (installed tejo + sintra) and live.nix (sintra). Single source of truth. Verified on hardware: validator + dispenser initialise off both the installed image and the live ISO.

Notes

  • Independent of the companion feat: seed-driven pairing (#70) PR — the two branches touch different files/sections and merge without conflict (verified: deploy ∪ feat == the pre-split dev tree, byte-identical).
  • No app/runtime code touched.

🤖 Generated with Claude Code

Deploy/build-infra changes, split out from the #70 pairing arc (companion PR) since they're orthogonal to the app logic and independently reviewable/mergeable. All three verified on the physical Sintra. ### Commits - **`perf(deploy): slim the kiosk closure`** — disable TTS (speechd), Qt, and docs in the kiosk config. Closure 6.2 → 5.0 GiB; distributable image 10 GiB → 2.2 GiB compressed. - **`fix(deploy): make disk-image-sintra-usb BIOS+UEFI bootable (GRUB)`** — `make-disk-image`'s `efi` table produces a UEFI-only (systemd-boot) image; the Sintra's Aaeon firmware USB-boots in **Legacy/BIOS** mode (it boots the live ISO via isolinux, not the ESP), so a dd'd image wasn't recognised. Switch the USB target to GRUB with BIOS **and** UEFI on the `hybrid` table (adds a `bios_grub` partition; GRUB writes its BIOS stage to the MBR + a removable `BOOTX64.EFI`). Scoped to the USB image; the eMMC install keeps systemd-boot. **Verified:** the Sintra now lists + boots the USB. - **`refactor(deploy): share UP Board serial hardware between installed + live ISO`** — the sintra live ISO had no `ftdi_sio` / `ttyJ5`/`ttyJ7` udev (validator + F56 dispenser failed on `iso-sintra`), while the installed image had them inline in `upboard.nix` — two definitions that had already drifted. Extract to `hardware/upboard-serial.nix`, imported by both `upboard.nix` (installed tejo + sintra) and `live.nix` (sintra). Single source of truth. **Verified on hardware:** validator + dispenser initialise off both the installed image and the live ISO. ### Notes - Independent of the companion `feat: seed-driven pairing (#70)` PR — the two branches touch different files/sections and merge without conflict (verified: `deploy ∪ feat` == the pre-split `dev` tree, byte-identical). - No app/runtime code touched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The disk image was ~6.2 GiB of closure, largely desktop/multimedia baggage a
single-purpose Electron kiosk never uses. Cut the clearly-unused stacks:

- services.speechd off → drops speech-dispatcher's espeak-ng + mbrola voices
  (~1 GB text-to-speech). An ATM does not talk.
- v4l-utils built withGUI=false → drops the entire Qt6 stack (~0.5 GB) that only
  backed the qv4l2 GUI; the v4l2-ctl CLI we actually use for the camera stays.
- documentation off (man/info/NixOS manual) — nobody reads them on a kiosk.

Closure 6.2 → 5.0 GiB. The remaining bulk is electron's own runtime (gtk4/
gstreamer/pipewire, unavoidable), mesa+llvm (GPU), and linux-firmware — those
need heavier / riskier work to touch. Distribute the image as .img.zst.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The USB disk image was systemd-boot (UEFI-only) with make-disk-image's "efi"
table (pure GPT + ESP, protective MBR). The Sintra's Aaeon UP Board firmware
USB-boots in Legacy/BIOS mode — it boots the live ISO via that ISO's isolinux
(BIOS) El Torito image, not the UEFI ESP — so a dd'd systemd-boot image has no
BIOS boot code to execute and the firmware won't list it (a hand-added hybrid
MBR didn't help: nothing to run).

Switch the USB target to GRUB with BIOS + UEFI on make-disk-image's "hybrid"
table: it adds a bios_grub partition, GRUB writes its BIOS stage to the MBR AND
a removable /EFI/BOOT/BOOTX64.EFI — mirroring the live ISO's dual boot. The
Aaeon now lists it (as two "ia android" entries, BIOS + UEFI) and boots it.
Scoped to disk-image-sintra-usb only; the eMMC install keeps systemd-boot.
ESP stays partition 1 so the ESP-USB relabel step is unchanged.

Verified on hardware: booted from USB into the wizard with the full upboard.nix
hardware config.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The sintra live ISO (live.nix) had no serial support — ftdi_sio and the
ttyJ5/ttyJ7 udev symlinks were only in hardware/upboard.nix (installed), so
booting iso-sintra on real hardware failed on the validator + F56 dispenser
while the disk image worked. The two definitions had already drifted (live's
tejo block lacked ttyS4).

Extract the UP Board serial peripherals (usbserial/ftdi_sio/cp210x, the
ttyJ4/ttyJ5/ttyJ7 udev symlinks + permissions, console=tty0) into
hardware/upboard-serial.nix and import it from both upboard.nix (installed
tejo + sintra) and live.nix (sintra only). Single source of truth — the two
artifacts can't drift again. Named upboard-serial (not sintra-serial) since
upboard.nix serves both tejo-installed and sintra-installed.

Camera + LED/SPI rules stay inline in upboard.nix (installed-specific; the
pairing camera works via getUserMedia without the scanner symlink). Verified
by eval: live sintra now carries ftdi_sio + console=tty0 + ttyJ7; installed
sintra/tejo unchanged (serial present, camera present, no console dupe).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
padreug deleted branch deploy/sintra-boot-hardware 2026-07-02 21:53:29 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/bitspire!72
No description provided.