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

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

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 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.

  1. 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:

output/host/bin/rauc --keyring beacon-buildroot/openssl-ca/dev/ca.cert.pem \
  info output/images/rootfs.raucb

Find the CM4

# 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.

# 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.

# 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:

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)
Description
No description provided
Readme 78 KiB
Languages
Shell 84.8%
C 11.8%
Makefile 3.4%