#!/bin/bash set -euo pipefail # Simple ARM64 Alpine Linux QEMU setup for hdmistat testing SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" WORK_DIR="${PROJECT_DIR}/qemu-alpine-test" # QEMU settings QEMU_MEM="2G" QEMU_CPUS="4" DISK_SIZE="4G" VNC_PORT="5902" # Alpine Linux ARM64 ALPINE_VERSION="3.19" ALPINE_ISO="alpine-virt-${ALPINE_VERSION}.0-aarch64.iso" ALPINE_URL="https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VERSION}/releases/aarch64/${ALPINE_ISO}" # Colors GREEN='\033[0;32m' RED='\033[0;31m' NC='\033[0m' log() { echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*" } error() { echo -e "${RED}[ERROR]${NC} $*" >&2 exit 1 } # Check dependencies check_dependencies() { log "Checking dependencies..." local deps=("qemu-system-aarch64" "wget") for dep in "${deps[@]}"; do if ! command -v "$dep" &> /dev/null; then error "$dep not found" fi done log "Dependencies OK" } # Setup directories setup_directories() { log "Setting up directories..." mkdir -p "$WORK_DIR" } # Download Alpine Linux download_alpine() { cd "$WORK_DIR" if [ -f "$ALPINE_ISO" ]; then log "Alpine Linux ISO already exists" return fi log "Downloading Alpine Linux ARM64..." wget -O "$ALPINE_ISO" "$ALPINE_URL" || error "Failed to download Alpine" } # Create disk image create_disk() { cd "$WORK_DIR" if [ -f "hdmistat-test.qcow2" ]; then log "Disk image already exists" return fi log "Creating disk image..." qemu-img create -f qcow2 hdmistat-test.qcow2 $DISK_SIZE } # Create setup script create_setup_script() { cat > "${WORK_DIR}/setup-hdmistat.sh" << 'EOF' #!/bin/sh set -e echo "===================================" echo "hdmistat Alpine Linux Setup Script" echo "===================================" # Update packages echo "Updating packages..." apk update # Install required packages echo "Installing build dependencies..." apk add --no-cache \ go \ git \ make \ gcc \ musl-dev \ linux-headers \ bash \ sudo \ fbset \ util-linux # Install newer Go if needed GO_VERSION="1.24.4" if ! go version | grep -q "$GO_VERSION"; then echo "Installing Go $GO_VERSION..." wget -q -O /tmp/go.tar.gz "https://go.dev/dl/go${GO_VERSION}.linux-aarch64.tar.gz" rm -rf /usr/local/go tar -C /usr/local -xzf /tmp/go.tar.gz rm /tmp/go.tar.gz export PATH="/usr/local/go/bin:$PATH" fi # Build hdmistat from mounted source if [ -d "/mnt/hdmistat" ]; then echo "Building hdmistat from source..." cd /mnt/hdmistat make build cp hdmistat /usr/local/bin/ echo "hdmistat installed successfully!" else echo "Warning: hdmistat source not mounted at /mnt/hdmistat" echo "Mount with: mount -t 9p -o trans=virtio,version=9p2000.L hdmistat /mnt/hdmistat" fi # Create test config mkdir -p /etc/hdmistat cat > /etc/hdmistat/config.yaml << 'CONFIG_EOF' framebuffer_device: /dev/fb0 rotation_interval: 10s update_interval: 1s log_level: info width: 1024 height: 768 screens: - overview - top_cpu - top_memory CONFIG_EOF echo "" echo "Setup complete!" echo "" echo "To test hdmistat:" echo "1. hdmistat info - Show system information" echo "2. hdmistat daemon - Run the framebuffer daemon" echo "3. hdmistat status - Check daemon status" echo "" echo "Note: Framebuffer access requires appropriate permissions" EOF chmod +x "${WORK_DIR}/setup-hdmistat.sh" } # Create run script create_run_script() { cat > "${WORK_DIR}/run-qemu.sh" << EOF #!/bin/bash cd "$WORK_DIR" echo "Starting QEMU ARM64 Alpine Linux..." echo "" echo "Instructions:" echo "1. Boot Alpine Linux and login as root (no password)" echo "2. Mount the hdmistat source: mkdir -p /mnt/hdmistat && mount -t 9p -o trans=virtio,version=9p2000.L hdmistat /mnt/hdmistat" echo "3. Run the setup script: sh /mnt/hdmistat/scripts/qemu-alpine-test/setup-hdmistat.sh" echo "" echo "VNC available on port $VNC_PORT" echo "Press Ctrl+A, X to quit" echo "" # Find EFI firmware EFI_CODE="" for path in /nix/store/*/share/qemu/edk2-aarch64-code.fd /run/current-system/sw/share/qemu/edk2-aarch64-code.fd; do if [ -f "\$path" ]; then EFI_CODE="\$path" break fi done BIOS_ARGS="" if [ -n "\$EFI_CODE" ]; then BIOS_ARGS="-bios \$EFI_CODE" fi qemu-system-aarch64 \\ -M virt \\ -accel hvf \\ -cpu host \\ -smp $QEMU_CPUS \\ -m $QEMU_MEM \\ -drive file=hdmistat-test.qcow2,format=qcow2,if=virtio \\ -cdrom $ALPINE_ISO \\ -boot d \\ -netdev user,id=net0,hostfwd=tcp::2223-:22 \\ -device virtio-net-pci,netdev=net0 \\ -device virtio-gpu-pci \\ -display default,show-cursor=on \\ -vnc :2 \\ -serial mon:stdio \\ -virtfs local,path="${PROJECT_DIR}",mount_tag=hdmistat,security_model=none,id=hdmistat \\ \$BIOS_ARGS \\ \${@} EOF chmod +x "${WORK_DIR}/run-qemu.sh" } # Create VNC helper create_vnc_helper() { cat > "${WORK_DIR}/view-vnc.sh" << EOF #!/bin/bash echo "Opening VNC viewer on localhost:$VNC_PORT" vncviewer localhost:$VNC_PORT || open vnc://localhost:$VNC_PORT || echo "Connect to VNC at localhost:$VNC_PORT" EOF chmod +x "${WORK_DIR}/view-vnc.sh" } # Print instructions print_instructions() { echo "" echo "=======================================" echo "QEMU ARM64 Alpine Setup Complete!" echo "=======================================" echo "" echo "To start testing:" echo " cd $WORK_DIR" echo " ./run-qemu.sh" echo "" echo "This creates a lightweight Alpine Linux ARM64 VM with:" echo " - Native ARM64 virtualization (hvf)" echo " - Framebuffer support" echo " - hdmistat source mounted via 9p" echo " - No cloud-init required" echo "" } # Main main() { log "Setting up QEMU ARM64 Alpine environment..." check_dependencies setup_directories download_alpine create_disk create_setup_script create_run_script create_vnc_helper print_instructions log "Setup complete!" } main "$@"