Files
beacon-buildroot/AGENTS.md

3.9 KiB

Beacon CM4 — Quick Reference

Full docs: beacon-buildroot/README.md

Build

cd ~/repos/buildroot-beacon
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot -j$(nproc)
# outputs: output/images/rootfs.raucb  update.raucb  sdcard.img.xz

Flash (initial, EMMC_DISABLE jumper bridged)

./beacon-buildroot/scripts/flash-cm4.sh          # auto-detect
./beacon-buildroot/scripts/flash-cm4.sh /dev/sda  # explicit device

SSH / find IP

# Non-secure-boot CM4 (MAC e4:5f:01:e9:13:96):
CM4=$(ip neigh show dev enp0s31f6 | awk '/e4:5f:01:e9:13:96/{print $1}')
# Secure-boot CM4 (MAC 2c:cf:67:fd:93:1a):
CM4=$(ip neigh show dev enp0s31f6 | awk '/2c:cf:67:fd:93:1a/{print $1}')
sshpass -p beacon ssh user@$CM4   # login: user / beacon

OTA Update

# transfer (scp broken on Dropbear — use tee pipe):
sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \
  < output/images/rootfs.raucb
# install + reboot:
sshpass -p beacon ssh -tt user@$CM4 'rauc install /upload/rootfs.raucb && sudo reboot'
# after reboot — find new IP, then mark-good (REQUIRED on every new boot to confirm slot):
sshpass -p beacon ssh -tt user@$CM4 'rauc status mark-good && rauc status'
# NOTE: rauc commands need -tt (PTY) on Dropbear SSH or output is silently dropped
# NOTE: mark-good MUST be called after each OTA reboot — without it RAUC falls back to previous slot

UART

picocom -b 115200 /dev/ttyUSB1                          # interactive (GPIO14/15)
socat -u /dev/ttyUSB1,b115200,rawer,crnl OPEN:/tmp/uart.log,creat,trunc &  # headless capture

Rescue

Short GPIO4 (pin 7) → GND (pin 9) during power-on → boots /dev/mmcblk0p2.

Secure Boot — Unlock as MSD

# Sign the MSD boot image with private.pem (once, or after rpi-eeprom submodule init):
cd usbboot/secure-boot-msd
../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k ../../private.pem
# Expose eMMC as USB mass storage (user must bridge EMMC_DISABLE jumper first):
sudo ./usbboot/rpiboot -d usbboot/secure-boot-msd
# Flash:
sudo bmaptool copy output/images/sdcard.img.xz /dev/sda

UART / Power Cycle

The user handles power cycling and UART logging manually. Ask user to: remove EMMC_DISABLE jumper → power-cycle → connect picocom.

picocom -b 115200 /dev/ttyUSB1   # user runs this to see boot log

Expected secure boot log lines: secure-boot, rsa-verify pass (0x0), then U-Boot.

Secure Boot — Provision (burn OTP)

update-pieeprom.sh -k private.pem && rpiboot -d secure-boot-recovery

Use existing private.pem — never regenerate it.

Disk Encryption (/data partition) COMPLETE

/dev/mmcblk0p3 is LUKS2-encrypted using the device-unique 256-bit OTP private key. Key is read from OTP at every boot via /dev/vcio (VideoCore mailbox). No key ever touches disk — tmpfs only.

Self-healing: If service finds a LUKS header that can't be opened (e.g. stale header surviving a sparse bmaptool flash), it wipes the first 4 MB and re-formats automatically.

Note: lsblk is not installed on target — use cryptsetup status instead.

# Check /data is mounted + encrypted:
sshpass -p beacon ssh user@$CM4 'sudo cryptsetup status data'
# Expected: type: LUKS2, cipher: aes-xts-plain64, keysize: 512 bits, mode: read/write

# Read OTP key (hex, stable across reboots) — requires root:
sshpass -p beacon ssh user@$CM4 'sudo beacon-otp-key'

# Verify LUKS2 header + keyslots:
sshpass -p beacon ssh user@$CM4 'sudo cryptsetup luksDump /dev/mmcblk0p3'

OTA update behavior: RAUC only writes to rootfs.0/1 — data partition is untouched. On reboot into new slot, service opens LUKS with same OTP key → same data accessible. Verified: A→B and B→A OTA both maintain encrypted /data correctly.

Security model: OTP key is protected by secure boot (only signed boot.img runs). Root processes within the signed OS can still read OTP via /dev/vcio (RPi hardware limitation).