update readme
This commit is contained in:
108
AGENTS.md
108
AGENTS.md
@@ -1,101 +1,43 @@
|
|||||||
# Beacon CM4 — Quick Reference
|
# Beacon CM4 — Agent Quick Reference
|
||||||
|
|
||||||
> Full docs: `beacon-buildroot/README.md`
|
> Full docs: `beacon-buildroot/README.md`
|
||||||
|
|
||||||
|
## Device
|
||||||
|
- **Login**: `user` / `beacon` (sudo passwordless; root login disabled)
|
||||||
|
- **MAC**: `d8:3a:dd:a8:9a:40` — IP is DHCP, changes on reboot
|
||||||
|
- **Find IP**: `CM4=$(ip neigh show dev enp0s31f6 | awk '/d8:3a:dd:a8:9a:40/{print $1; exit}')`
|
||||||
|
- **SSH**: `sshpass -p beacon ssh user@$CM4` — use `-tt` for `rauc` commands
|
||||||
|
- **File transfer**: `scp` broken on Dropbear → use `ssh 'sudo tee /upload/file >/dev/null' < localfile`
|
||||||
|
- **UART**: `picocom -b 115200 /dev/ttyUSB0` — user handles power cycling manually
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
```bash
|
```bash
|
||||||
cd ~/repos/buildroot-beacon
|
cd ~/repos/buildroot-beacon
|
||||||
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot -j$(nproc)
|
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)
|
## Flash (secure-boot CM4)
|
||||||
|
Bridge EMMC_DISABLE jumper + connect USB, then:
|
||||||
```bash
|
```bash
|
||||||
./beacon-buildroot/scripts/flash-cm4.sh # auto-detect
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh # auto-detect
|
||||||
./beacon-buildroot/scripts/flash-cm4.sh /dev/sda # explicit device
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh /dev/sda # explicit
|
||||||
```
|
|
||||||
|
|
||||||
## SSH / find IP
|
|
||||||
```bash
|
|
||||||
# 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
|
|
||||||
```
|
```
|
||||||
|
Script auto-signs `usbboot/secure-boot-msd/boot.img` with `private.pem` if needed.
|
||||||
|
|
||||||
## OTA Update
|
## OTA Update
|
||||||
```bash
|
```bash
|
||||||
# transfer (scp broken on Dropbear — use tee pipe):
|
# Transfer bundle
|
||||||
sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \
|
sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \
|
||||||
< output/images/rootfs.raucb
|
< output/images/rootfs.raucb
|
||||||
# install + reboot:
|
# Install + reboot
|
||||||
sshpass -p beacon ssh -tt user@$CM4 'rauc install /upload/rootfs.raucb && sudo reboot'
|
sshpass -p beacon ssh -tt user@$CM4 'sudo rauc install /upload/rootfs.raucb && sudo reboot'
|
||||||
# after reboot — find new IP, then mark-good (REQUIRED on every new boot to confirm slot):
|
# After reboot: find new IP, then MUST mark-good or slot rolls back
|
||||||
sshpass -p beacon ssh -tt user@$CM4 'rauc status mark-good && rauc status'
|
sshpass -p beacon ssh -tt user@$CM4 'sudo 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
|
## Key gotchas
|
||||||
```bash
|
- `lsblk` not on target — use `cryptsetup status data` to check `/data`
|
||||||
picocom -b 115200 /dev/ttyUSB1 # interactive (GPIO14/15)
|
- `rauc` needs `-tt` on Dropbear or output is silently dropped
|
||||||
socat -u /dev/ttyUSB1,b115200,rawer,crnl OPEN:/tmp/uart.log,creat,trunc & # headless capture
|
- `mark-good` is required after every OTA reboot
|
||||||
```
|
- `/data` is LUKS2 (AES-XTS-256, OTP key) — untouched by RAUC, self-heals on bad header
|
||||||
|
- `private.pem` at repo root — **never regenerate** it
|
||||||
## Rescue
|
|
||||||
Short GPIO4 (pin 7) → GND (pin 9) during power-on → boots `/dev/mmcblk0p2`.
|
|
||||||
|
|
||||||
## Secure Boot — Unlock as MSD
|
|
||||||
```bash
|
|
||||||
# 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.
|
|
||||||
```bash
|
|
||||||
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)
|
|
||||||
```bash
|
|
||||||
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.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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).
|
|
||||||
252
README.md
252
README.md
@@ -1,20 +1,20 @@
|
|||||||
# Beacon CM4 — Buildroot + RAUC
|
# Beacon CM4 — Buildroot + RAUC
|
||||||
|
|
||||||
Buildroot BR2_EXTERNAL for a Raspberry Pi CM4 with A/B OTA updates via [RAUC](https://rauc.io/).
|
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
|
## Partition layout
|
||||||
|
|
||||||
| # | Label | Size | Content |
|
| Dev | Size | Mount | Content |
|
||||||
|---|-------|------|---------|
|
|-----|------|-------|---------|
|
||||||
| p1 | boot_a | 64 MiB | FAT32 — firmware + U-Boot (slot A) |
|
| p1 | 256 MiB | — | FAT32 outer boot (firmware, boot.img, boot.sig, boot.scr) |
|
||||||
| p2 | boot_b | 64 MiB | FAT32 — firmware + U-Boot (slot B) |
|
| p2 | 64 MiB | — | Rescue rootfs (ext4) |
|
||||||
| p3 | data | 256 MiB | ext4 — persistent data (`/data`) |
|
| p3 | 128 MiB | `/data` | LUKS2 encrypted persistent data |
|
||||||
| p4 | (extended) | — | — |
|
| p5 | 900 MiB | `/` | Rootfs slot A (ext4) |
|
||||||
| p5 | rootfs0 | 250 MiB | ext4 — rootfs slot A |
|
| p6 | 900 MiB | — | Rootfs slot B (ext4) |
|
||||||
| p6 | rootfs1 | 250 MiB | ext4 — rootfs slot B |
|
| p7 | 900 MiB | `/upload` | OTA bundle staging (ext4) |
|
||||||
| p7 | upload | 256 MiB | ext4 — staging area for bundles (`/upload`) |
|
|
||||||
|
|
||||||
U-Boot reads `BOOT_ORDER`/`BOOT_x_LEFT` env vars from eMMC and selects the active slot before loading the kernel. RAUC uses `boot-mbr-switch` to toggle between slots.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -22,241 +22,119 @@ U-Boot reads `BOOT_ORDER`/`BOOT_x_LEFT` env vars from eMMC and selects the activ
|
|||||||
|
|
||||||
### 1. Generate RAUC signing certificates
|
### 1. Generate RAUC signing certificates
|
||||||
|
|
||||||
Run **once** from the `beacon-buildroot/` directory:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/repos/buildroot-beacon/beacon-buildroot
|
cd beacon-buildroot
|
||||||
./openssl-ca.sh "Beacon" "Beacon RAUC CA"
|
./openssl-ca.sh "Beacon" "Beacon RAUC CA"
|
||||||
```
|
```
|
||||||
|
|
||||||
This creates `openssl-ca/dev/` with:
|
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.
|
||||||
openssl-ca/dev/
|
|
||||||
ca.cert.pem ← keyring installed into target /etc/rauc/keyring.pem
|
|
||||||
development-1.cert.pem ← signing cert (build host)
|
|
||||||
private/
|
|
||||||
development-1.key.pem ← signing key (build host, keep secret)
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Do not regenerate** the CA once devices are flashed — bundles signed with
|
### 2. Build
|
||||||
> a new CA will be rejected by devices that have the old keyring.
|
|
||||||
|
|
||||||
### 2. Initial full build
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/repos/buildroot-beacon
|
cd ~/repos/buildroot-beacon
|
||||||
|
|
||||||
make -C rpi-buildroot-fork \
|
# First time: load defconfig
|
||||||
O=$(pwd)/output \
|
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot beacon_cm4_rauc_defconfig
|
||||||
BR2_EXTERNAL=$(pwd)/beacon-buildroot \
|
|
||||||
beacon_cm4_rauc_defconfig
|
|
||||||
|
|
||||||
make -C rpi-buildroot-fork \
|
# Build (incremental on subsequent runs)
|
||||||
O=$(pwd)/output \
|
make -C rpi-buildroot-fork O=$(pwd)/output BR2_EXTERNAL=$(pwd)/beacon-buildroot -j$(nproc)
|
||||||
BR2_EXTERNAL=$(pwd)/beacon-buildroot \
|
|
||||||
-j$(nproc)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Output artifacts in `output/images/`:
|
Outputs in `output/images/`:
|
||||||
|
- `sdcard.img.xz` + `.bmap` — full eMMC image for initial flash
|
||||||
| File | Purpose |
|
- `rootfs.raucb` — OTA bundle (rootfs only)
|
||||||
|------|---------|
|
- `update.raucb` — OTA bundle (bootfs + rootfs)
|
||||||
| `sdcard.img.xz` | Full eMMC image for initial flash |
|
|
||||||
| `sdcard.img.bmap` | Block map for fast flash with bmaptool |
|
|
||||||
| `rootfs.raucb` | **OTA bundle** — rootfs only |
|
|
||||||
| `update.raucb` | OTA bundle — bootfs + rootfs (full system) |
|
|
||||||
|
|
||||||
### 3. Initial flash (EMMC_DISABLE jumper bridged)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./beacon-buildroot/scripts/flash-cm4.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Remove the jumper and power-cycle after the script completes.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Creating an OTA update
|
## Initial flash
|
||||||
|
|
||||||
### What triggers a new bundle
|
The CM4 uses **secure boot** — the eMMC can only be exposed as MSD using a `boot.img` signed with `private.pem`.
|
||||||
|
|
||||||
Any source change that results in a different `rootfs.ext4` or `boot.vfat` will produce a new bundle on the next build. Typical triggers:
|
|
||||||
|
|
||||||
- Package version bump / new package in defconfig
|
|
||||||
- File added/changed under `rootfs-overlay/`
|
|
||||||
- `post-build.sh` changes
|
|
||||||
- Kernel or U-Boot update
|
|
||||||
|
|
||||||
### Build the update
|
|
||||||
|
|
||||||
Incremental build — only changed packages and the rootfs/image stage are rebuilt:
|
|
||||||
|
|
||||||
|
1. Bridge the **EMMC_DISABLE** jumper and connect USB
|
||||||
|
2. Run:
|
||||||
```bash
|
```bash
|
||||||
cd ~/repos/buildroot-beacon
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh # auto-detect
|
||||||
|
bash beacon-buildroot/scripts/flash-cm4-sb.sh /dev/sda # explicit
|
||||||
# Optional: set a human-readable version string
|
|
||||||
export VERSION="1.2.0"
|
|
||||||
|
|
||||||
make -C rpi-buildroot-fork \
|
|
||||||
O=$(pwd)/output \
|
|
||||||
BR2_EXTERNAL=$(pwd)/beacon-buildroot \
|
|
||||||
-j$(nproc)
|
|
||||||
```
|
```
|
||||||
|
The script auto-signs `usbboot/secure-boot-msd/boot.img` if needed, exposes eMMC via `rpiboot`, then flashes with `bmaptool`.
|
||||||
|
|
||||||
`post-image.sh` runs automatically at the end and:
|
3. Remove jumper → power-cycle
|
||||||
1. Builds `boot.vfat` from U-Boot + firmware blobs
|
|
||||||
2. Creates `rootfs.raucb` (rootfs-only bundle)
|
|
||||||
3. Creates `update.raucb` (full bootfs+rootfs bundle)
|
|
||||||
4. Signs both bundles with `development-1.key.pem`
|
|
||||||
5. Assembles `sdcard.img.xz` + `.bmap`
|
|
||||||
|
|
||||||
### Bundle contents
|
---
|
||||||
|
|
||||||
`rootfs.raucb` manifest (`format=verity`):
|
## OTA update
|
||||||
```ini
|
|
||||||
[update]
|
|
||||||
compatible=beacon-cm4
|
|
||||||
version=<VERSION>
|
|
||||||
[bundle]
|
|
||||||
format=verity
|
|
||||||
[image.rootfs]
|
|
||||||
filename=rootfs.ext4
|
|
||||||
```
|
|
||||||
|
|
||||||
`update.raucb` additionally contains `[image.bootloader]` → `boot.vfat`.
|
### Build the bundle
|
||||||
|
|
||||||
### Signing details
|
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).
|
||||||
|
|
||||||
Signing is done by the host `rauc` binary during `post-image.sh`:
|
|
||||||
|
|
||||||
|
To inspect a bundle:
|
||||||
```bash
|
```bash
|
||||||
rauc bundle \
|
output/host/bin/rauc --keyring beacon-buildroot/openssl-ca/dev/ca.cert.pem \
|
||||||
--cert openssl-ca/dev/development-1.cert.pem \
|
|
||||||
--key openssl-ca/dev/private/development-1.key.pem \
|
|
||||||
--keyring openssl-ca/dev/ca.cert.pem \
|
|
||||||
<bundle-dir>/ <output>.raucb
|
|
||||||
```
|
|
||||||
|
|
||||||
The target verifies the bundle signature against `/etc/rauc/keyring.pem`
|
|
||||||
(= `ca.cert.pem` installed during build by `post-build.sh`).
|
|
||||||
|
|
||||||
To inspect a bundle without installing it:
|
|
||||||
```bash
|
|
||||||
output/host/bin/rauc \
|
|
||||||
--keyring beacon-buildroot/openssl-ca/dev/ca.cert.pem \
|
|
||||||
info output/images/rootfs.raucb
|
info output/images/rootfs.raucb
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
### Find the CM4
|
||||||
|
|
||||||
## Deploying the update to the CM4
|
|
||||||
|
|
||||||
### Find the CM4's IP
|
|
||||||
|
|
||||||
The CM4 gets a DHCP address on eth0 (changes on each reboot):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# By MAC address:
|
# Secure-boot CM4 (MAC d8:3a:dd:a8:9a:40):
|
||||||
ip neigh show dev enp0s31f6 | grep e4:5f:01:e9:13:96
|
CM4=$(ip neigh show dev enp0s31f6 | awk '/d8:3a:dd:a8:9a:40/{print $1; exit}')
|
||||||
```
|
```
|
||||||
|
|
||||||
### Transfer the bundle
|
### Transfer, install, reboot
|
||||||
|
|
||||||
Dropbear has no sftp-server — standard `scp` does **not** work.
|
`scp` does **not** work on Dropbear — use stdin pipe. `rauc` needs `-tt`.
|
||||||
Use stdin pipe instead:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CM4=10.11.0.xx # replace with actual IP
|
# 1. Transfer
|
||||||
|
sshpass -p beacon ssh user@$CM4 'sudo tee /upload/rootfs.raucb >/dev/null' \
|
||||||
sshpass -p beacon ssh user@$CM4 \
|
|
||||||
'sudo tee /upload/rootfs.raucb > /dev/null' \
|
|
||||||
< output/images/rootfs.raucb
|
< output/images/rootfs.raucb
|
||||||
|
|
||||||
|
# 2. Install + reboot
|
||||||
|
sshpass -p beacon ssh -tt user@$CM4 'sudo rauc install /upload/rootfs.raucb && sudo reboot'
|
||||||
```
|
```
|
||||||
|
|
||||||
~51 MiB transfers in ~5 s on LAN.
|
### Mark-good after reboot (required)
|
||||||
|
|
||||||
### Install
|
After reboot the new slot is in **trial mode** — it will roll back after 3 boots without `mark-good`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sshpass -p beacon ssh user@$CM4 'rauc install /upload/rootfs.raucb'
|
# Find new IP (DHCP changes on reboot):
|
||||||
```
|
CM4=$(ip neigh show dev enp0s31f6 | awk '/d8:3a:dd:a8:9a:40/{print $1; exit}')
|
||||||
|
|
||||||
Expected output:
|
sshpass -p beacon ssh -tt user@$CM4 'sudo rauc status mark-good && rauc status'
|
||||||
```
|
|
||||||
0% Installing
|
|
||||||
20% Checking bundle done.
|
|
||||||
40% Determining target install group done.
|
|
||||||
46% Checking slot rootfs.1 done.
|
|
||||||
99% Copying image to rootfs.1 done.
|
|
||||||
100% Installing done.
|
|
||||||
Installing `/upload/rootfs.raucb` succeeded
|
|
||||||
```
|
|
||||||
|
|
||||||
RAUC automatically selects the **inactive** slot as the target.
|
|
||||||
|
|
||||||
### Reboot into the new slot
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sshpass -p beacon ssh user@$CM4 'rauc status && sudo reboot'
|
|
||||||
```
|
|
||||||
|
|
||||||
`rauc status` should show `Activated: rootfs.1 (B)` before the reboot.
|
|
||||||
|
|
||||||
### Confirm and mark-good
|
|
||||||
|
|
||||||
After reboot the system boots into the new slot in **trial mode**
|
|
||||||
(U-Boot decrements `BOOT_x_LEFT`). You must mark it good or it will
|
|
||||||
roll back on the next reboot.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Find new IP (DHCP address changes):
|
|
||||||
CM4_NEW=$(ip neigh show dev enp0s31f6 | awk '/e4:5f:01:e9:13:96/{print $1}')
|
|
||||||
|
|
||||||
sshpass -p beacon ssh user@$CM4_NEW 'rauc status mark-good && rauc status'
|
|
||||||
```
|
|
||||||
|
|
||||||
Expected final `rauc status`:
|
|
||||||
```
|
|
||||||
Booted from: rootfs.1 (B)
|
|
||||||
Activated: rootfs.1 (B)
|
|
||||||
x [rootfs.1] boot status: good ← currently running, committed
|
|
||||||
o [rootfs.0] boot status: good ← fallback
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Rollback behaviour
|
## Disk encryption
|
||||||
|
|
||||||
If `mark-good` is **not** called after a reboot, U-Boot decrements
|
`/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.
|
||||||
`BOOT_x_LEFT`. After 3 failed attempts it switches back to the previous
|
|
||||||
slot automatically — no manual intervention needed.
|
|
||||||
|
|
||||||
To force an immediate rollback:
|
- **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
|
```bash
|
||||||
# On the CM4:
|
sshpass -p beacon ssh user@$CM4 'sudo cryptsetup status data'
|
||||||
sudo fw_setenv BOOT_ORDER "A B" # or "B A" depending on current slot
|
# type: LUKS2, cipher: aes-xts-plain64, keysize: 512 bits
|
||||||
sudo reboot
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Rescue partition
|
|
||||||
|
|
||||||
Short **GPIO4** (pin 7) to **GND** (pin 9) on the 40-pin header during
|
|
||||||
power-on. U-Boot detects this and boots the read-only rescue rootfs from
|
|
||||||
`/dev/mmcblk0p2`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
| Path | Purpose |
|
| Path | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `configs/beacon_cm4_rauc_defconfig` | Buildroot defconfig |
|
| `configs/beacon_cm4_rauc_defconfig` | Buildroot defconfig |
|
||||||
| `board/beacon-cm4/genimage.cfg` | Partition layout |
|
| `board/beacon-cm4/genimage.cfg` | Partition layout |
|
||||||
| `board/beacon-cm4/post-image.sh` | Bundle creation + signing |
|
| `board/beacon-cm4/post-image.sh` | Bundle signing + image assembly |
|
||||||
| `board/beacon-cm4/post-build.sh` | Target rootfs customisation |
|
| `board/beacon-cm4/post-build.sh` | Target rootfs customisation |
|
||||||
| `board/beacon-cm4/rootfs-overlay/etc/rauc/system.conf` | RAUC slot config |
|
| `board/beacon-cm4/rootfs-overlay/etc/rauc/system.conf` | RAUC slot config |
|
||||||
| `openssl-ca/dev/` | Signing certificates (generated once) |
|
| `openssl-ca/dev/` | RAUC signing certificates |
|
||||||
| `scripts/flash-cm4.sh` | Automated initial flash script |
|
| `scripts/flash-cm4-sb.sh` | Initial flash (secure-boot CM4) |
|
||||||
|
| `package/beacon-otp/` | OTP key reader (`beacon-otp-key`) |
|
||||||
|
|||||||
Reference in New Issue
Block a user