141 lines
4.3 KiB
Markdown
141 lines
4.3 KiB
Markdown
# Beacon CM4 — Buildroot + RAUC
|
|
|
|
Buildroot BR2_EXTERNAL for Raspberry Pi CM4 with:
|
|
- **RAUC A/B OTA updates** (rootfs.0 / rootfs.1)
|
|
- **Secure boot** (RPi EEPROM OTP, signed `boot.img`)
|
|
- **Disk encryption** (`/data` on LUKS2, key derived from device OTP)
|
|
|
|
## Partition layout
|
|
|
|
| Dev | Size | Mount | Content |
|
|
|-----|------|-------|---------|
|
|
| p1 | 256 MiB | — | FAT32 outer boot (firmware, boot.img, boot.sig, boot.scr) |
|
|
| p2 | 64 MiB | — | Rescue rootfs (ext4) |
|
|
| p3 | 128 MiB | `/data` | LUKS2 encrypted persistent data |
|
|
| p5 | 900 MiB | `/` | Rootfs slot A (ext4) |
|
|
| p6 | 900 MiB | — | Rootfs slot B (ext4) |
|
|
| p7 | 900 MiB | `/upload` | OTA bundle staging (ext4) |
|
|
|
|
---
|
|
|
|
## One-time setup
|
|
|
|
### 1. Generate RAUC signing certificates
|
|
|
|
```bash
|
|
cd beacon-buildroot
|
|
./openssl-ca.sh "Beacon" "Beacon RAUC CA"
|
|
```
|
|
|
|
Creates `openssl-ca/dev/`: `ca.cert.pem` (installed on device as keyring), `development-1.cert.pem` + `private/development-1.key.pem` (signing, host-only).
|
|
|
|
> **Never regenerate** the CA after devices are flashed — new CA = rejected bundles.
|
|
|
|
### 2. Build
|
|
|
|
```bash
|
|
cd ~/repos/buildroot-beacon
|
|
|
|
# First time: load defconfig
|
|
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot beacon_cm4_rauc_defconfig
|
|
|
|
# Build (incremental on subsequent runs)
|
|
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot -j$(nproc)
|
|
```
|
|
|
|
Outputs in `output/images/`:
|
|
- `sdcard.img.xz` + `.bmap` — full eMMC image for initial flash
|
|
- `rootfs.raucb` — OTA bundle (rootfs only)
|
|
- `update.raucb` — OTA bundle (bootfs + rootfs)
|
|
|
|
---
|
|
|
|
## Initial flash
|
|
|
|
The CM4 uses **secure boot** — the eMMC can only be exposed as MSD using a `boot.img` signed with `private.pem`.
|
|
|
|
1. Bridge the **EMMC_DISABLE** jumper and connect USB
|
|
2. Run:
|
|
```bash
|
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh # auto-detect
|
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh /dev/sda # explicit
|
|
```
|
|
The script auto-signs `usbboot/secure-boot-msd/boot.img` if needed, exposes eMMC via `rpiboot`, then flashes with `bmaptool`.
|
|
|
|
3. Remove jumper → power-cycle
|
|
|
|
---
|
|
|
|
## OTA update
|
|
|
|
### Build the bundle
|
|
|
|
Any change to packages, `rootfs-overlay/`, `post-build.sh`, or kernel triggers a new bundle on the next incremental build (same build command as above).
|
|
|
|
To inspect a bundle:
|
|
```bash
|
|
output/host/bin/rauc --keyring beacon-buildroot/openssl-ca/dev/ca.cert.pem \
|
|
info output/images/rootfs.raucb
|
|
```
|
|
|
|
### Find the CM4
|
|
|
|
```bash
|
|
# Secure-boot CM4 (MAC d8:3a:dd:a8:9a:40):
|
|
CM4=$(ip neigh show dev enp0s31f6 | awk '/d8:3a:dd:a8:9a:40/{print $1; exit}')
|
|
```
|
|
|
|
### Transfer, install, reboot
|
|
|
|
`scp` does **not** work on Dropbear — use stdin pipe. `rauc` needs `-tt`.
|
|
|
|
```bash
|
|
# 1. Transfer
|
|
sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \
|
|
< output/images/rootfs.raucb
|
|
|
|
# 2. Install + reboot
|
|
sshpass -p beacon ssh -tt user@$CM4 'sudo rauc install /upload/rootfs.raucb && sudo reboot'
|
|
```
|
|
|
|
### Mark-good after reboot (required)
|
|
|
|
After reboot the new slot is in **trial mode** — it will roll back after 3 boots without `mark-good`.
|
|
|
|
```bash
|
|
# Find new IP (DHCP changes on reboot):
|
|
CM4=$(ip neigh show dev enp0s31f6 | awk '/d8:3a:dd:a8:9a:40/{print $1; exit}')
|
|
|
|
sshpass -p beacon ssh -tt user@$CM4 'sudo rauc status mark-good && rauc status'
|
|
```
|
|
|
|
---
|
|
|
|
## Disk encryption
|
|
|
|
`/data` (`/dev/mmcblk0p3`) is LUKS2-encrypted at rest. The key is derived from the device-unique OTP private key via `/dev/vcio` (VideoCore mailbox) — never stored on disk.
|
|
|
|
- **First boot / stale header**: the service automatically wipes and reformats the partition.
|
|
- **OTA updates**: RAUC only writes to rootfs slots — `/data` is untouched and re-opens with the same OTP key.
|
|
|
|
Verify encryption on device:
|
|
```bash
|
|
sshpass -p beacon ssh user@$CM4 'sudo cryptsetup status data'
|
|
# type: LUKS2, cipher: aes-xts-plain64, keysize: 512 bits
|
|
```
|
|
|
|
---
|
|
|
|
## Reference
|
|
|
|
| Path | Purpose |
|
|
|------|---------|
|
|
| `configs/beacon_cm4_rauc_defconfig` | Buildroot defconfig |
|
|
| `board/beacon-cm4/genimage.cfg` | Partition layout |
|
|
| `board/beacon-cm4/post-image.sh` | Bundle signing + image assembly |
|
|
| `board/beacon-cm4/post-build.sh` | Target rootfs customisation |
|
|
| `board/beacon-cm4/rootfs-overlay/etc/rauc/system.conf` | RAUC slot config |
|
|
| `openssl-ca/dev/` | RAUC signing certificates |
|
|
| `scripts/flash-cm4-sb.sh` | Initial flash (secure-boot CM4) |
|
|
| `package/beacon-otp/` | OTP key reader (`beacon-otp-key`) |
|