diff --git a/imx95-pqc-demo/demo/demo-uart.sh b/imx95-pqc-demo/demo/demo-uart.sh index cc4c73d..8725971 100755 --- a/imx95-pqc-demo/demo/demo-uart.sh +++ b/imx95-pqc-demo/demo/demo-uart.sh @@ -252,4 +252,11 @@ echo " Demo complete. Both cores booted firmware verified with ML-DSA-87:" echo " Cortex-A55 wolfBoot -> Linux (above, before this stream)" echo " Cortex-M7 wolfBoot -> Zephyr [M7 ]" echo " Power-cycle the board to run it again." +echo +# Printed here because the serial console is the only input at a show, and +# this is the last thing on it. +echo " Switch the boot chain, then power-cycle:" +echo " sudo ~/switch-boot.sh 0 # stock U-Boot chain" +echo " sudo ~/switch-boot.sh 1 # wolfBoot chain" +echo " sudo ~/switch-boot.sh --show # which one is selected now" echo "==================================================================" diff --git a/imx95-pqc-demo/demo/switch-boot.sh b/imx95-pqc-demo/demo/switch-boot.sh new file mode 100755 index 0000000..0de5be2 --- /dev/null +++ b/imx95-pqc-demo/demo/switch-boot.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Switch the board between the stock U-Boot chain and the wolfBoot chain. +# Runs ON THE BOARD, so it needs no host, no network and no ssh: +# +# sudo bash ~/demo/switch-boot.sh # flip to the other chain +# sudo bash ~/demo/switch-boot.sh 0 # force stock U-Boot (boot0) +# sudo bash ~/demo/switch-boot.sh 1 # force wolfBoot (boot1) +# sudo bash ~/demo/switch-boot.sh --show # report only, change nothing +# +# The i.MX95 boot ROM takes its AHAB container set from whichever eMMC boot +# partition EXT_CSD selects, so this is an EXT_CSD write plus a reboot. Both +# chains share the eMMC rootfs, so this script is present either way and the +# switch works in both directions. +set -uo pipefail + +MMC=/dev/mmcblk0 +# PARTITION_CONFIG bits [5:3]: 1 = boot0, 2 = boot1. mmc-utils uses the same +# numbering for "mmc bootpart enable". +name_of() { case "$1" in 1) echo "boot0 (stock U-Boot chain)" ;; 2) echo "boot1 (wolfBoot chain)" ;; *) echo "unknown ($1)" ;; esac; } + +if [ "$(id -u)" != "0" ]; then + echo "needs root: sudo bash $0 $*" >&2 + exit 1 +fi + +current() { + local v + v=$(mmc extcsd read $MMC 2>/dev/null \ + | grep -i "PARTITION_CONFIG" | grep -o "0x[0-9a-fA-F]*" | head -1) + [ -n "$v" ] || return 1 + echo $(( (v >> 3) & 7 )) +} + +CUR=$(current) || { echo "cannot read PARTITION_CONFIG" >&2; exit 1; } +echo "current: $(name_of "$CUR")" + +case "${1:-}" in + --show|-s) exit 0 ;; + 0) NEW=1 ;; + 1) NEW=2 ;; + "") NEW=$(( CUR == 1 ? 2 : 1 )) ;; + *) echo "usage: $0 [0|1|--show]" >&2; exit 1 ;; +esac + +if [ "$NEW" = "$CUR" ]; then + echo "already on $(name_of "$CUR") - nothing to do" + exit 0 +fi + +# Refuse to switch into a partition with no container. The ROM would find +# nothing to boot, and recovering from that needs the B4 button and uuu. +DEV=/dev/mmcblk0boot$(( NEW - 1 )) +TAG=$(dd if=$DEV bs=1 skip=32771 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n') +if [ "$TAG" != "87" ]; then + echo "$DEV has no AHAB container at 0x8000 (tag 0x$TAG) - refusing" >&2 + exit 1 +fi + +echo "switching to: $(name_of "$NEW")" +mmc bootpart enable "$NEW" 1 $MMC || { echo "mmc bootpart failed" >&2; exit 1; } +AFTER=$(current) +if [ "$AFTER" != "$NEW" ]; then + echo "PARTITION_CONFIG did not take (still $(name_of "$AFTER"))" >&2 + exit 1 +fi +sync +echo "now set to: $(name_of "$AFTER")" +echo +echo "Power-cycle the board to boot it. Run this again to switch back." diff --git a/imx95-pqc-demo/demo/whichbutton.py b/imx95-pqc-demo/demo/whichbutton.py new file mode 100755 index 0000000..39bc0e8 --- /dev/null +++ b/imx95-pqc-demo/demo/whichbutton.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +"""Print any button/switch event from the carrier. No root needed (group input). +Run on the board, press every button you can find, Ctrl-C when done.""" +import struct, sys, select +FMT = 'llHHi'; SZ = struct.calcsize(FMT) +TYPES = {1: 'KEY', 5: 'SWITCH'} +devs = {} +for n in (0, 1): + try: + devs[open(f'/dev/input/event{n}', 'rb', buffering=0)] = f'event{n}' + except OSError as e: + print(f'event{n}: {e}') +if not devs: + sys.exit('no readable input devices') +print('watching:', ', '.join(devs.values()), '- press buttons now') +try: + while True: + r, _, _ = select.select(list(devs), [], [], 60) + if not r: + print('(60s with no events)') + continue + for f in r: + sec, usec, typ, code, val = struct.unpack(FMT, f.read(SZ)) + if typ in TYPES: + print(f' {devs[f]} {TYPES[typ]} code={code} value={val}' + f' {"PRESS" if val else "release"}') +except KeyboardInterrupt: + print('\ndone')