#!/usr/bin/env bash # ============================================================================= # run_qemu.sh — Launch the QEMU v8 OP-TEE environment # # Reference: https://optee.readthedocs.io/en/latest/building/devices/qemu.html#qemu-v8 # # Architecture: # - Normal World UART: TCP 54320 (Linux console) # - Secure World UART: TCP 54321 (OP-TEE TEE core log) # - GDB server: TCP 1234 (optional debugging) # # Usage: # ./run_qemu.sh # Start QEMU (two terminal windows needed for UART) # ./run_qemu.sh --help # Show help # ============================================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OPTEE_DIR="${SCRIPT_DIR}/optee" BINARIES_DIR="${OPTEE_DIR}/out/bin" # Colored output helpers info() { echo -e "\033[1;34m[INFO]\033[0m $*"; } die() { echo -e "\033[1;31m[FAIL]\033[0m $*" >&2; exit 1; } # --------------------------------------------------------------------------- # # Help # --------------------------------------------------------------------------- # if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then cat <<'EOF' Usage: ./run_qemu.sh [options] Options: --no-gdb Do not attach a GDB server (default: attach -s -S) --virtfs Enable VirtFS shared directory (host optee/ mounted at /mnt/host) --help Show this help Ports: 54320 Normal World UART (Linux console) 54321 Secure World UART (OP-TEE secure log) 1234 GDB server (-S flag: waits for GDB to connect before continuing boot) Recommended: open three terminals and connect separately: # Terminal 1 (Normal World): python3 optee/build/soc_term.py 54320 # Terminal 2 (Secure World): python3 optee/build/soc_term.py 54321 # Terminal 3 (optional GDB): aarch64-linux-gnu-gdb -q (gdb) target remote localhost:1234 (gdb) c After QEMU starts, type 'c' at the QEMU monitor prompt to continue execution. EOF exit 0 fi # --------------------------------------------------------------------------- # # Check required files # --------------------------------------------------------------------------- # [[ -d "${OPTEE_DIR}" ]] || die "optee/ directory not found. Please run ./setup.sh first" # Locate QEMU binary (OP-TEE 3.18.0 requires QEMU v7.0.0) QEMU_BIN="${OPTEE_DIR}/qemu/build/aarch64-softmmu/qemu-system-aarch64" [[ -x "${QEMU_BIN}" ]] || die "qemu-system-aarch64 not found. Please build QEMU first" info "Using QEMU: ${QEMU_BIN}" # Check required binaries for f in bl1.bin Image rootfs.cpio.gz; do [[ -f "${BINARIES_DIR}/${f}" ]] || die "Missing ${BINARIES_DIR}/${f}. Please run ./setup.sh first" done # --------------------------------------------------------------------------- # # QEMU arguments # --------------------------------------------------------------------------- # GDB_ARGS="-s -S" VIRTFS_ARGS="" for arg in "$@"; do case "$arg" in --no-gdb) GDB_ARGS="" ;; --virtfs) VIRTFS_ARGS="-fsdev local,id=fsdev0,path=${OPTEE_DIR},security_model=none \ -device virtio-9p-device,fsdev=fsdev0,mount_tag=host" ;; esac done # --------------------------------------------------------------------------- # # Launch helper terminals (soc_term.py acts as TCP server; QEMU connects as client) # --------------------------------------------------------------------------- # SOC_TERM="${OPTEE_DIR}/build/soc_term.py" launch_uart() { local port=$1 title=$2 if command -v gnome-terminal &>/dev/null; then gnome-terminal --title="$title" -- bash -c \ "python3 ${SOC_TERM} ${port}; read" & elif command -v xterm &>/dev/null; then xterm -title "$title" -e \ "bash -c 'python3 ${SOC_TERM} ${port}; read'" & else info "Please run in another terminal: python3 ${SOC_TERM} ${port}" fi } wait_for_ports() { info "Waiting for UART ports to be ready (54320, 54321)..." while ! nc -z 127.0.0.1 54320 || ! nc -z 127.0.0.1 54321; do sleep 1 done info "UART ports ready" } info "Starting UART terminals..." launch_uart 54320 "OP-TEE Normal World (Linux)" launch_uart 54321 "OP-TEE Secure World (TEE Core)" wait_for_ports # --------------------------------------------------------------------------- # # Start QEMU # --------------------------------------------------------------------------- # info "Starting QEMU v8 (AArch64)..." info "Normal World UART: TCP:54320" info "Secure World UART: TCP:54321" [[ -n "${GDB_ARGS}" ]] && info "GDB server: TCP:1234 (waiting for GDB to connect)" echo "" info "Type 'c' at the QEMU monitor prompt to continue booting..." cd "${BINARIES_DIR}" ln -sf "${OPTEE_DIR}/out-br/images/rootfs.cpio.gz" "${BINARIES_DIR}/rootfs.cpio.gz" 2>/dev/null || true exec "${QEMU_BIN}" \ -nographic \ -serial tcp:localhost:54320 \ -serial tcp:localhost:54321 \ ${GDB_ARGS} \ -smp 2 \ -machine virt,secure=on,mte=off,gic-version=3,virtualization=false \ -cpu max,sve=off \ -d unimp \ -semihosting-config enable=on,target=native \ -m 1057 \ -bios bl1.bin \ -initrd rootfs.cpio.gz \ -kernel Image \ -no-acpi \ -append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2' \ ${VIRTFS_ARGS}