From bdd0f1a1a794674489918758b8e5ea5c9a52a99f Mon Sep 17 00:00:00 2001 From: Kroese Date: Wed, 12 Jun 2024 04:42:40 +0200 Subject: [PATCH] feat: Detect EFI-compatible images (#117) --- Dockerfile | 1 + readme.md | 4 ++-- src/boot.sh | 54 +++++++++++++++++++++++++++++--------------------- src/disk.sh | 28 ++++++++++++++------------ src/display.sh | 6 +++--- src/install.sh | 20 ++++++++++++++----- src/reset.sh | 1 - 7 files changed, 67 insertions(+), 47 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2d43e2a..3b6de84 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,7 @@ RUN set -eu && \ dnsmasq \ net-tools \ qemu-utils \ + genisoimage \ ca-certificates \ netcat-openbsd \ qemu-system-arm \ diff --git a/readme.md b/readme.md index 7593a36..736923d 100644 --- a/readme.md +++ b/readme.md @@ -22,9 +22,9 @@ Docker container for running ARM-based virtual machines using QEMU, for devices - Reduces the learning curve and eliminates the need for a dedicated Proxmox or ESXi server - - Has a web-based viewer to control the machine directly from your browser + - Web-based viewer to control the machine directly from your browser - - Uses high-performance QEMU options (like KVM acceleration, kernel-mode networking, IO threading, etc.) to achieve near-native speed + - High-performance QEMU options (like KVM acceleration, kernel-mode networking, IO threading, etc.) to achieve near-native speed *Note: for KVM acceleration you need a Linux-based operating system, as it's not available on MacOS unfortunately.* diff --git a/src/boot.sh b/src/boot.sh index 6616a6d..7866bbc 100644 --- a/src/boot.sh +++ b/src/boot.sh @@ -2,15 +2,24 @@ set -Eeuo pipefail # Docker environment variables -: "${BIOS:=""}" # Bios file +: "${BIOS:=""}" # BIOS file +: "${BOOT_MODE:="legacy"}" # Boot mode SECURE="off" BOOT_OPTS="" BOOT_DESC="" -DIR="/usr/share/qemu" + +if [ -n "$BIOS" ]; then + BOOT_OPTS="-bios $BIOS" + return 0 +fi case "${BOOT_MODE,,}" in + "legacy" ) + BOOT_OPTS="" + ;; "uefi" ) + BOOT_DESC=" with OVMF" ROM="AAVMF_CODE.no-secboot.fd" VARS="AAVMF_VARS.fd" ;; @@ -38,31 +47,30 @@ case "${BOOT_MODE,,}" in ;; esac -if [ -n "$BIOS" ]; then +case "${BOOT_MODE,,}" in + "uefi" | "secure" | "windows" | "windows_secure" ) - BOOT_OPTS+=" -bios $DIR/$BIOS" - return 0 + AAVMF="/usr/share/AAVMF/" + DEST="$STORAGE/${BOOT_MODE,,}" -fi + if [ ! -s "$DEST.rom" ] || [ ! -f "$DEST.rom" ]; then + [ ! -s "$AAVMF/$ROM" ] || [ ! -f "$AAVMF/$ROM" ] && error "UEFI boot file ($AAVMF/$ROM) not found!" && exit 44 + rm -f "$DEST.rom" + dd if=/dev/zero "of=$DEST.rom" bs=1M count=64 status=none + dd "if=$AAVMF/$ROM" "of=$DEST.rom" conv=notrunc status=none + fi -AAVMF="/usr/share/AAVMF/" -DEST="$STORAGE/${BOOT_MODE,,}" + if [ ! -s "$DEST.vars" ] || [ ! -f "$DEST.vars" ]; then + [ ! -s "$AAVMF/$VARS" ] || [ ! -f "$AAVMF/$VARS" ] && error "UEFI vars file ($AAVMF/$VARS) not found!" && exit 45 + rm -f "$DEST.vars" + dd if=/dev/zero "of=$DEST.vars" bs=1M count=64 status=none + dd "if=$AAVMF/$VARS" "of=$DEST.vars" conv=notrunc status=none + fi -if [ ! -s "$DEST.rom" ] || [ ! -f "$DEST.rom" ]; then - [ ! -s "$AAVMF/$ROM" ] || [ ! -f "$AAVMF/$ROM" ] && error "UEFI boot file ($AAVMF/$ROM) not found!" && exit 44 - rm -f "$DEST.rom" - dd if=/dev/zero "of=$DEST.rom" bs=1M count=64 status=none - dd "if=$AAVMF/$ROM" "of=$DEST.rom" conv=notrunc status=none -fi + BOOT_OPTS+=" -drive file=$DEST.rom,if=pflash,unit=0,format=raw,readonly=on" + BOOT_OPTS+=" -drive file=$DEST.vars,if=pflash,unit=1,format=raw" -if [ ! -s "$DEST.vars" ] || [ ! -f "$DEST.vars" ]; then - [ ! -s "$AAVMF/$VARS" ] || [ ! -f "$AAVMF/$VARS" ] && error "UEFI vars file ($AAVMF/$VARS) not found!" && exit 45 - rm -f "$DEST.vars" - dd if=/dev/zero "of=$DEST.vars" bs=1M count=64 status=none - dd "if=$AAVMF/$VARS" "of=$DEST.vars" conv=notrunc status=none -fi - -BOOT_OPTS+=" -drive file=$DEST.rom,if=pflash,unit=0,format=raw,readonly=on" -BOOT_OPTS+=" -drive file=$DEST.vars,if=pflash,unit=1,format=raw" + ;; +esac return 0 diff --git a/src/disk.sh b/src/disk.sh index c66eb17..bbb2877 100644 --- a/src/disk.sh +++ b/src/disk.sh @@ -531,13 +531,21 @@ case "${DISK_TYPE,,}" in * ) error "Invalid DISK_TYPE specified, value \"$DISK_TYPE\" is unrecognized!" && exit 80 ;; esac +case "${MACHINE,,}" in + "virt" ) + FALLBACK="usb" ;; + "pc-q35-2"* | "pc-i440fx-2"* ) + FALLBACK="auto" ;; + * ) + FALLBACK="ide" ;; +esac + if [ -z "${MEDIA_TYPE:-}" ]; then - case "${MACHINE,,}" in - "virt" | "pc-q35-2"* | "pc-i440fx-2"* ) - MEDIA_TYPE="auto" ;; - * ) - [[ "${DISK_TYPE,,}" != "blk" ]] && MEDIA_TYPE="$DISK_TYPE" || MEDIA_TYPE="ide" ;; - esac + if [[ "${DISK_TYPE,,}" == "blk" ]]; then + MEDIA_TYPE="$FALLBACK" + else + MEDIA_TYPE="$DISK_TYPE" + fi fi case "${MEDIA_TYPE,,}" in @@ -553,13 +561,7 @@ DRIVERS="/drivers.iso" [ ! -f "$DRIVERS" ] || [ ! -s "$DRIVERS" ] && DRIVERS="$STORAGE/drivers.iso" if [ -f "$DRIVERS" ] && [ -s "$DRIVERS" ]; then - case "${MACHINE,,}" in - "virt" | "pc-q35-2"* | "pc-i440fx-2"* ) - DRIVER_TYPE="auto" ;; - * ) - DRIVER_TYPE="ide" ;; - esac - DISK_OPTS+=$(addMedia "$DRIVERS" "$DRIVER_TYPE" "1" "" "0x6") + DISK_OPTS+=$(addMedia "$DRIVERS" "$FALLBACK" "1" "" "0x6") fi DISK1_FILE="$STORAGE/data" diff --git a/src/display.sh b/src/display.sh index a2af247..e5594b6 100644 --- a/src/display.sh +++ b/src/display.sh @@ -6,10 +6,10 @@ set -Eeuo pipefail : "${VGA:=""}" # VGA adaptor : "${DISPLAY:="web"}" # Display type -if [[ "${BOOT_MODE,,}" != "windows" ]]; then - [ -z "$VGA" ] && VGA="virtio-gpu" -else +if [[ "${BOOT_MODE:-}" == "windows"* ]]; then [ -z "$VGA" ] && VGA="ramfb" +else + [ -z "$VGA" ] && VGA="virtio-gpu" fi case "${DISPLAY,,}" in diff --git a/src/install.sh b/src/install.sh index f56d437..f480f8d 100644 --- a/src/install.sh +++ b/src/install.sh @@ -1,18 +1,28 @@ #!/usr/bin/env bash set -Eeuo pipefail -iso () { +detect () { + local dir="" local file="$1" [ ! -f "$file" ] && return 1 [ ! -s "$file" ] && return 1 + dir=$(isoinfo -f -i "$file") + + if [ -z "${BOOT_MODE:-}" ]; then + # Automaticly detect UEFI-compatible ISO's + dir=$(isoinfo -f -i "$file") + dir=$(echo "${dir^^}" | grep "^/EFI") + [ -n "$dir" ] && BOOT_MODE="uefi" + fi + BOOT="$file" return 0 } file=$(find / -maxdepth 1 -type f -iname boot.iso | head -n 1) [ ! -s "$file" ] && file=$(find "$STORAGE" -maxdepth 1 -type f -iname boot.iso | head -n 1) -iso "$file" && return 0 +detect "$file" && return 0 if [ -z "$BOOT" ] || [[ "$BOOT" == *"example.com/image.iso" ]]; then hasDisk && return 0 @@ -20,12 +30,12 @@ if [ -z "$BOOT" ] || [[ "$BOOT" == *"example.com/image.iso" ]]; then fi base=$(basename "$BOOT") -iso "$STORAGE/$base" && return 0 +detect "$STORAGE/$base" && return 0 base=$(basename "${BOOT%%\?*}") : "${base//+/ }"; printf -v base '%b' "${_//%/\\x}" base=$(echo "$base" | sed -e 's/[^A-Za-z0-9._-]/_/g') -iso "$STORAGE/$base" && return 0 +detect "$STORAGE/$base" && return 0 TMP="$STORAGE/${base%.*}.tmp" rm -f "$TMP" @@ -61,6 +71,6 @@ if ((size<100000)); then fi mv -f "$TMP" "$STORAGE/$base" -! iso "$STORAGE/$base" && exit 63 +! detect "$STORAGE/$base" && exit 63 return 0 diff --git a/src/reset.sh b/src/reset.sh index 6551308..11a3f84 100644 --- a/src/reset.sh +++ b/src/reset.sh @@ -25,7 +25,6 @@ echo "❯ For support visit $SUPPORT" : "${RAM_CHECK:="Y"}" # Check available RAM : "${DISK_SIZE:="16G"}" # Initial data disk size : "${BOOT_INDEX:="10"}" # Boot index of CD drive -: "${BOOT_MODE:="uefi"}" # Boot in UEFI mode # Helper variables