qemu: full OTA apply scenario — write rootfs_b, flip AvbABData, boot it
Closes the loop every prior harness stopped short of, entirely off-hardware: the real flared (WARDEN_HARD_RESET-gated build) pulls a real signed tier-1 .wfw whose payload is a BOOTABLE rootfs stamped 0.0.2, verifies it, writes /dev/block/by-name/rootfs_b inside disk.img, and flips the AvbABData (slot B: priority 15, 3 tries, unsuccessful — the exact pre-first-boot arming state, round-tripped through a portal check-in). The harness then boots slot _b and asserts the applied version + marker are what runs. OTA-APPLY-PASS verified end to end. - mkimage: the misc partition now carries REAL provisioned AvbABData (bytes mirror flare-edge's provisioning defaults) — slotctl fail-closes on bad AB magic before writing, which a zeroed misc tripped. - run.sh --allow-apply / cmdline warden.fwapply: per-boot opt-in that makes stage-2 init export WARDEN_FW_ALLOW_APPLY=1; never the default. - stage-2 init also exports WARDEN_HARD_RESET=0 (the CRU poke is fatal on virt, same class as the HPMCU probe); the harness performs the reboot. - ADR-0006 boundary documented in the scenario and README: BCB slot CHOICE and the physical reset remain emulated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
This commit is contained in:
co-authored by
Claude Fable 5
parent
ff62991e8d
commit
d63c2117c1
+25
-1
@@ -96,10 +96,15 @@ place_partition() {
|
||||
rootfs_a|rootfs_b) stage="$ROOT" ;;
|
||||
userdata) stage="$UDATA" ;;
|
||||
oem_a|oem_b) stage="$SCRATCH/empty" ;;
|
||||
# misc carries REAL AvbABData (byte 2048): flared's slotctl fail-closes
|
||||
# on a bad magic before any OTA write, so a zeroed misc blocks apply
|
||||
# scenarios. Bytes mirror flare-edge tools/mk-misc.py provisioning
|
||||
# defaults (A: prio 15 successful, B: prio 14 successful, CRC32-BE).
|
||||
misc) stage="__misc__" ;;
|
||||
# Boot-chain partitions the VM never reads: present at the right offsets,
|
||||
# left zeroed. Enumerated (not a wildcard) so a typo'd name in
|
||||
# blkdevparts.conf fails HERE, not as a confusing mount error at boot.
|
||||
env|idblock|uboot|misc|boot_a|boot_b|recovery) stage="" ;;
|
||||
env|idblock|uboot|boot_a|boot_b|recovery) stage="" ;;
|
||||
*) echo "FATAL: unknown partition name '$name' in blkdevparts.conf" >&2; exit 1 ;;
|
||||
esac
|
||||
# dd in 4K blocks — every offset in the canonical layout is 4K-aligned;
|
||||
@@ -112,6 +117,25 @@ place_partition() {
|
||||
[ $((off + size)) -gt "$DISK_END" ] && DISK_END=$((off + size))
|
||||
[ -z "$stage" ] && return 0
|
||||
local img="$SCRATCH/$name.img"
|
||||
if [ "$stage" = "__misc__" ]; then
|
||||
python3 - "$img" "$size" <<'PYMISC'
|
||||
import struct, sys, zlib
|
||||
img, size = sys.argv[1], int(sys.argv[2])
|
||||
s = bytearray(28)
|
||||
s[0:4] = b"\0AB0" # AB_MAGIC
|
||||
s[4] = 1 # major
|
||||
s[8:12] = bytes([15, 0, 1, 0]) # slot A: priority, tries, successful
|
||||
s[12:16] = bytes([14, 0, 1, 0]) # slot B
|
||||
meta = bytes(s) + struct.pack(">I", zlib.crc32(bytes(s)) & 0xFFFFFFFF)
|
||||
buf = bytearray(size)
|
||||
buf[2048:2048 + len(meta)] = meta
|
||||
open(img, "wb").write(buf)
|
||||
PYMISC
|
||||
dd if="$img" of="$DISK" bs=4096 seek=$((off / 4096)) \
|
||||
conv=notrunc,sparse status=none
|
||||
qemu_log " $name: AvbABData provisioned @ +2048"
|
||||
return 0
|
||||
fi
|
||||
mkfs_part "$stage" "$size" "$img"
|
||||
dd if="$img" of="$DISK" bs=4096 seek=$((off / 4096)) \
|
||||
conv=notrunc,sparse status=none
|
||||
|
||||
Reference in New Issue
Block a user