diff --git a/local/scripts/test-usb-maturity-qemu.sh b/local/scripts/test-usb-maturity-qemu.sh new file mode 100755 index 00000000..64ab915d --- /dev/null +++ b/local/scripts/test-usb-maturity-qemu.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Run the bounded USB maturity proof helpers in sequence. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +usage() { + cat <<'USAGE' +Usage: test-usb-maturity-qemu.sh [config] + +Run the bounded USB maturity proof helpers in sequence. +Defaults to redbear-desktop. + +Checks run: + - xHCI interrupt mode + - full USB stack proof + - USB storage bounded readback proof +USAGE +} + +for arg in "$@"; do + case "$arg" in + --help|-h|help) + usage + exit 0 + ;; + esac +done + +config="${1:-redbear-desktop}" + +echo ">>> Running xHCI interrupt proof" +bash "$SCRIPT_DIR/test-xhci-irq-qemu.sh" --check "$config" + +echo ">>> Running full USB stack proof" +bash "$SCRIPT_DIR/test-usb-qemu.sh" --check "$config" + +echo ">>> Running USB storage readback proof" +bash "$SCRIPT_DIR/test-usb-storage-qemu.sh" "$config" + +echo "All bounded USB maturity checks passed for $config" diff --git a/local/scripts/test-usb-qemu.sh b/local/scripts/test-usb-qemu.sh index 59c17b70..ed2debfc 100755 --- a/local/scripts/test-usb-qemu.sh +++ b/local/scripts/test-usb-qemu.sh @@ -6,6 +6,25 @@ set -euo pipefail +seed_usb_image() { + local image_path="$1" + python3 - "$image_path" <<'PY' +import base64 +import pathlib +import sys + +path = pathlib.Path(sys.argv[1]) +payload = (b"REDBEAR-USB-FULL-STACK-CHECK\0" * 32)[:512] +payload = payload.ljust(512, b'\0') + +with path.open("r+b") as fh: + fh.seek(0) + fh.write(payload) + +print(base64.b64encode(payload).decode("ascii")) +PY +} + find_uefi_firmware() { local candidates=( "/usr/share/ovmf/x64/OVMF.4m.fd" @@ -37,8 +56,9 @@ Checks performed: 1. xHCI controller initializes and reports interrupt mode 2. USB HID driver spawns for keyboard/tablet 3. USB SCSI driver spawns for mass storage - 4. BOS descriptor fetched (or gracefully skipped for USB 2) - 5. No panics or crash-class errors in USB daemons + 4. USB storage sector-0 readback matches a seeded host pattern + 5. BOS descriptor fetched (or gracefully skipped for USB 2) + 6. No panics or crash-class errors in USB daemons USAGE } @@ -84,6 +104,8 @@ if [[ ! -f "$usb_img" ]]; then truncate -s 64M "$usb_img" fi +expected_sector_b64="$(seed_usb_image "$usb_img")" + pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true sleep 1 @@ -136,7 +158,7 @@ else failures=$((failures + 1)) fi -# Check 3: USB SCSI driver spawn +# Check 3: USB SCSI driver spawn + bounded data readback if grep -q "USB SCSI driver spawned" "$log_file"; then echo " [PASS] USB SCSI driver spawned" else @@ -144,6 +166,13 @@ else failures=$((failures + 1)) fi +if grep -Fq "DISK CONTENT: $expected_sector_b64" "$log_file"; then + echo " [PASS] USB storage sector readback matched seeded pattern" +else + echo " [FAIL] USB storage sector readback did not match seeded pattern" >&2 + failures=$((failures + 1)) +fi + # Check 4: BOS descriptor handling (info or debug log) if grep -q "BOS:" "$log_file"; then echo " [PASS] BOS descriptor processing active" diff --git a/local/scripts/test-usb-storage-qemu.sh b/local/scripts/test-usb-storage-qemu.sh index 4facd968..6077e79e 100644 --- a/local/scripts/test-usb-storage-qemu.sh +++ b/local/scripts/test-usb-storage-qemu.sh @@ -3,6 +3,25 @@ set -euo pipefail +seed_usb_image() { + local image_path="$1" + python3 - "$image_path" <<'PY' +import base64 +import pathlib +import sys + +path = pathlib.Path(sys.argv[1]) +payload = (b"REDBEAR-USB-STORAGE-CHECK\0" * 32)[:512] +payload = payload.ljust(512, b'\0') + +with path.open("r+b") as fh: + fh.seek(0) + fh.write(payload) + +print(base64.b64encode(payload).decode("ascii")) +PY +} + find_uefi_firmware() { local candidates=( "/usr/share/ovmf/x64/OVMF.4m.fd" @@ -66,6 +85,8 @@ if [[ ! -f "$usb_img" ]]; then truncate -s 64M "$usb_img" fi +expected_sector_b64="$(seed_usb_image "$usb_img")" + pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true sleep 1 @@ -101,9 +122,14 @@ if ! grep -q "USB SCSI driver spawned" "$log_file"; then exit 1 fi +if ! grep -Fq "DISK CONTENT: $expected_sector_b64" "$log_file"; then + echo "ERROR: USB storage sector 0 readback did not match the seeded pattern; see $log_file" >&2 + exit 1 +fi + if grep -q "panic\|usbscsid: .*IO ERROR\|usbscsid: startup failed\|usbscsid: event queue error\|usbscsid: scheme tick failed\|bulk .* endpoint stalled" "$log_file"; then echo "ERROR: USB storage path hit a crash/error; see $log_file" >&2 exit 1 fi -echo "USB mass-storage autospawn detected in $log_file" +echo "USB mass-storage readback verified in $log_file"