Compare commits

...

20 Commits

Author SHA1 Message Date
Martin Wimpress
4d45cfbf9e
ci: install dependencies for quickget tests 2024-05-15 02:56:37 +01:00
Martin Wimpress
8075e2302a
fix(darwin): just use uuidgen to create session_id 2024-05-15 02:31:34 +01:00
Martin Wimpress
f92749f8cd
fix(darwin): disable huge pages 2024-05-15 02:31:34 +01:00
Martin Wimpress
bdbf4586f0
fix(darwin): convert CPU flags from Linux format to Darwin format 2024-05-15 02:31:34 +01:00
Martin Wimpress
68c4fa70bd
fix(darwin): call sw_vers with single switch for improved compatibility 2024-05-15 01:46:33 +01:00
Martin Wimpress
16808cc6b2
refactor(darwin): change DARWIN to OS_KERNEL for clear conditionals 2024-05-15 01:38:13 +01:00
Martin Wimpress
22adea53b6
refactor: rename HOST_OS to OS_RELEASE 2024-05-15 01:28:57 +01:00
Martin Wimpress
9d2ba7a2e0
refactor: change IN_VM to HYPERVISOR; 2024-05-15 01:19:39 +01:00
Martin Wimpress
d5e2cf2c98
fix(darwin): default display to cocoa on darwin 2024-05-15 01:07:43 +01:00
Martin Wimpress
8a2f0d5e7b
fix(darwin): disable viewer_param_check() for darwin 2024-05-15 01:04:38 +01:00
Martin Wimpress
24ae36e417
fix(darwin): update display_param_check() to correctly verify displays 2024-05-15 00:59:54 +01:00
Martin Wimpress
5766f865e6
refactor: check qemu-img, qemu-system-x86_64 and curl are executable 2024-05-14 23:45:37 +01:00
Martin Wimpress
b7b759e7f1
fix(quickget): find qemu-img 2024-05-14 23:43:58 +01:00
Martin Wimpress
eed96a72b2
style: add missing function prefix 2024-05-14 20:53:24 +01:00
Martin Wimpress
6a8d76a208
feat: detect if running in a VM and use an emulated CPU 2024-05-14 20:48:38 +01:00
Martin Wimpress
2e960f4803
refactor: add CPU_MODEL variable 2024-05-14 20:40:20 +01:00
Martin Wimpress
0beb51043d
fix(darwin): do not enable kvm-pit.lost_tick_policy=discard on darwin 2024-05-14 20:40:20 +01:00
Martin Wimpress
d83070384c
fix(darwin): do not enable kvm=on or kvm_pv_unhalt on darwin 2024-05-14 20:40:20 +01:00
Martin Wimpress
c9ee9d4e01
refactor: set NET before any other configuration 2024-05-14 20:40:20 +01:00
Martin Wimpress
ef20827b7e
fix(linux): resolve regression in check_cpu_flag() 2024-05-14 20:40:20 +01:00
3 changed files with 113 additions and 65 deletions

View File

@ -13,14 +13,20 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
install-deps:
name: "Install dependencies 📦"
runs-on: ubuntu-22.04
steps:
- name: "Install curl and qemu-utils 🚀"
run: |
apt-get -y update
apt-get -y install curl qemu-utils
list-all-supported:
needs: [install-deps]
name: "List all supported OS 📝"
runs-on: ubuntu-22.04
# The type of runner that the job will run on
#runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
@ -36,7 +42,7 @@ jobs:
path: results/supported.txt
list-all-urls:
needs: [list-all-supported]
needs: [install-deps, list-all-supported]
name: "List all URLs 🔗"
runs-on: ubuntu-22.04
steps:
@ -61,6 +67,7 @@ jobs:
path: results/urls.txt
check-all-urls:
needs: [install-deps]
name: "Check all image URLs 💿️"
runs-on: ubuntu-22.04
steps:

150
quickemu
View File

@ -22,7 +22,7 @@ function ignore_msrs_always() {
function ignore_msrs_alert() {
local ignore_msrs=""
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
return
elif [ -e /sys/module/kvm/parameters/ignore_msrs ]; then
ignore_msrs=$(cat /sys/module/kvm/parameters/ignore_msrs)
@ -223,7 +223,7 @@ function get_nproc() {
function get_cpu_info() {
local INFO_NAME="${1}"
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
if [ "^Model name:" == "${INFO_NAME}" ]; then
sysctl -n machdep.cpu.brand_string | sed 's/ //g'
elif [ "Socket" == "${INFO_NAME}" ]; then
@ -245,15 +245,17 @@ function get_cpu_info() {
function check_cpu_flag() {
local HOST_CPU_FLAG=""
if [ ${DARWIN} -eq 1 ]; then
HOST_CPU_FLAG="${1}^^"
if [ "${OS_KERNEL}" == "Darwin" ]; then
# Convert the flag to uppercase and replace _ with .
HOST_CPU_FLAG="${1^^}"
HOST_CPU_FLAG="${HOST_CPU_FLAG//_/.}"
if sysctl -n machdep.cpu.features | grep -o "${HOST_CPU_FLAG}" > /dev/null; then
return 0
else
return 1
fi
else
HOST_CPU_FLAG="${1},,"
HOST_CPU_FLAG="${1}"
if lscpu | grep -o "^Flags\b.*: .*\b${HOST_CPU_FLAG}\b" > /dev/null; then
return 0
else
@ -284,16 +286,37 @@ function configure_cpu() {
HOST_CPU_SOCKETS=$(get_cpu_info 'Socket')
HOST_CPU_VENDOR=$(get_cpu_info 'Vendor')
# A CPU with Intel VT-x / AMD SVM support is required
if [ "${HOST_CPU_VENDOR}" == "GenuineIntel" ]; then
if ! check_cpu_flag vmx; then
echo "ERROR! Intel VT-x support is required."
#exit 1
fi
elif [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
if ! check_cpu_flag svm; then
echo "ERROR! AMD SVM support is required."
exit 1
# Detect if running in a VM
if [ "${OS_KERNEL}" == "Darwin" ]; then
MANUFACTURER=$(ioreg -l | grep -e Manufacturer | grep -v iMan | cut -d'"' -f4 | sort -u)
else
MANUFACTURER=$(head -1 /sys/class/dmi/id/sys_vendor)
fi
case ${MANUFACTURER,,} in
qemu) CPU_MODEL="Penryn"
HYPERVISOR="${MANUFACTURER,,}";;
*) CPU_MODEL="host"
# Disable huge pages
# - https://stackoverflow.com/questions/60231203/qemu-qcow2-mmu-gva-to-gpa-crash-in-mac-os-x
if [ "${OS_KERNEL}" == "Darwin" ]; then
CPU_MODEL+=",-pdpe1gb"
fi
HYPERVISOR="";;
esac
if [ -z "${HYPERVISOR}" ]; then
# A CPU with Intel VT-x / AMD SVM support is required
if [ "${HOST_CPU_VENDOR}" == "GenuineIntel" ]; then
if ! check_cpu_flag vmx; then
echo "ERROR! Intel VT-x support is required."
exit 1
fi
elif [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
if ! check_cpu_flag svm; then
echo "ERROR! AMD SVM support is required."
exit 1
fi
fi
fi
@ -325,7 +348,7 @@ function configure_cpu() {
done
fi
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
# Get the number of physical cores
physicalcpu=$(sysctl -n hw.physicalcpu)
# Get the number of logical processors
@ -363,11 +386,11 @@ function configure_cpu() {
fi
}
configure_ram() {
function configure_ram() {
RAM_VM="2G"
if [ -z "${ram}" ]; then
local RAM_HOST=""
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
RAM_HOST=$(($(sysctl -n hw.memsize) / (1048576*1024)))
else
# Determine the number of gigabytes of RAM in the host by extracting the first numerical value from the output.
@ -450,7 +473,7 @@ function configure_bios() {
# does not support SMM.
local SHARE_PATH="/usr/share"
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
# Do not assume brew; quickemu could have been installed via Nix
if command -v brew &>/dev/null; then
SHARE_PATH="$(brew --prefix qemu)/share"
@ -541,7 +564,7 @@ function configure_os_quirks() {
# Make any OS specific adjustments
case ${guest_os} in
batocera|*bsd|freedos|haiku|linux*|*solaris)
CPU="-cpu host,kvm=on"
CPU="-cpu ${CPU_MODEL}${CPU_KVM}"
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
CPU="${CPU},topoext"
fi
@ -566,7 +589,7 @@ function configure_os_quirks() {
fi
;;
kolibrios|reactos)
CPU="-cpu qemu32,kvm=on"
CPU="-cpu qemu32${CPU_KVM}"
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
CPU="${CPU},topoext"
fi
@ -593,21 +616,21 @@ function configure_os_quirks() {
case ${macos_release} in
ventura|sonoma)
if check_cpu_flag sse4_2 && check_cpu_flag avx2; then
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+avx2,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
CPU="-cpu Haswell-v4${CPU_KVM},vendor=GenuineIntel,+avx,+avx2,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
else
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 and AVX2 support."
exit 1
fi;;
catalina|big-sur|monterey)
if check_cpu_flag sse4_2; then
CPU="-cpu Haswell-v4,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
CPU="-cpu Haswell-v4${CPU_KVM},vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.2,vmware-cpuid-freq=on"
else
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.2 support."
exit 1
fi;;
*)
if check_cpu_flag sse4_1; then
CPU="-cpu Penryn,kvm=on,vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.1,vmware-cpuid-freq=on"
CPU="-cpu Penryn${CPU_KVM},vendor=GenuineIntel,+avx,+sse,+sse2,+sse3,+sse4.1,vmware-cpuid-freq=on"
else
echo "ERROR! macOS ${macos_release} requires a CPU with SSE 4.1 support."
exit 1
@ -623,7 +646,7 @@ function configure_os_quirks() {
done
# Disable S3 support in the VM to prevent macOS suspending during install
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1 -device isa-applesmc,osk=$(echo "bheuneqjbexolgurfrjbeqfthneqrqcyrnfrqbagfgrny(p)NccyrPbzchgreVap" | tr 'A-Za-z' 'N-ZA-Mn-za-m')"
GUEST_TWEAKS="${KVM_GUEST_TWEAKS}-global ICH9-LPC.disable_s3=1 -device isa-applesmc,osk=$(echo "bheuneqjbexolgurfrjbeqfthneqrqcyrnfrqbagfgrny(p)NccyrPbzchgreVap" | tr 'A-Za-z' 'N-ZA-Mn-za-m')"
# Disable High Precision Timer
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
@ -662,16 +685,16 @@ function configure_os_quirks() {
;;
windows|windows-server)
if [ "${QEMU_VER_SHORT}" -gt 60 ]; then
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough"
CPU="-cpu ${CPU_MODEL}${CPU_KVM},+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough"
else
CPU="-cpu host,kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_frequencies,kvm_pv_unhalt,hv_reenlightenment,hv_relaxed,hv_spinlocks=8191,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vendor_id=1234567890ab,hv_vpindex"
CPU="-cpu ${CPU_MODEL}${CPU_KVM},+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_frequencies${CPU_KVM_UNHALT},hv_reenlightenment,hv_relaxed,hv_spinlocks=8191,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vendor_id=1234567890ab,hv_vpindex"
fi
if [ "${HOST_CPU_VENDOR}" == "AuthenticAMD" ]; then
CPU="${CPU},topoext"
fi
# Disable S3 support in the VM to ensure Windows can boot with SecureBoot enabled
# - https://wiki.archlinux.org/title/QEMU#VM_does_not_boot_when_using_a_Secure_Boot_enabled_OVMF
GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1"
GUEST_TWEAKS="${KVM_GUEST_TWEAKS}-global ICH9-LPC.disable_s3=1"
# Disable High Precision Timer
if [ "${QEMU_VER_SHORT}" -ge 70 ]; then
@ -681,7 +704,7 @@ function configure_os_quirks() {
fi
SMM="on"
;;
*) CPU="-cpu host,kvm=on"
*) CPU="-cpu ${CPU_MODEL}${CPU_KVM}"
NET_DEVICE="rtl8139"
echo "WARNING! Unrecognised guest OS: ${guest_os}";;
esac
@ -1027,7 +1050,7 @@ function vm_boot() {
KERNEL_NAME="Unknown"
KERNEL_NODE=""
KERNEL_VER="?"
local HOST_OS="Unknown OS"
OS_RELEASE="Unknown OS"
MACHINE_TYPE="${MACHINE_TYPE:-q35}"
MAC_BOOTLOADER=""
MAC_MISSING=""
@ -1044,22 +1067,24 @@ function vm_boot() {
KERNEL_NODE="$(uname -n | cut -d'.' -f 1)"
KERNEL_VER="$(uname -r)"
if [ ${DARWIN} -eq 1 ]; then
if [ "${OS_KERNEL}" == "Darwin" ]; then
# Get macOS product name and version using swvers
if [ -x "$(command -v sw_vers)" ]; then
HOST_OS="$(sw_vers --productName) $(sw_vers --productVersion)"
OS_RELEASE="$(sw_vers -productName) $(sw_vers -productVersion)"
fi
elif [ -e /etc/os-release ]; then
HOST_OS=$(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)
OS_RELEASE=$(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)
fi
echo "Quickemu ${VERSION} using ${QEMU} v${QEMU_VER_LONG}"
echo " - Host: ${HOST_OS} running ${KERNEL_NAME} ${KERNEL_VER} ${KERNEL_NODE}"
echo " - Host: ${OS_RELEASE} running ${KERNEL_NAME} ${KERNEL_VER} ${KERNEL_NODE}"
# Force to lowercase.
boot=${boot,,}
guest_os=${guest_os,,}
args=()
# Set the hostname of the VM
NET="user,hostname=${VMNAME}"
configure_cpu
configure_ram
@ -1068,8 +1093,6 @@ function vm_boot() {
configure_storage
configure_display
configure_audio
# Set the hostname of the VM
NET="user,hostname=${VMNAME}"
configure_ports
configure_file_sharing
configure_usb
@ -1077,11 +1100,12 @@ function vm_boot() {
echo "#!/usr/bin/env bash" > "${VMDIR}/${VMNAME}.sh"
# Changing process name is not supported on macOS
if [ ${DARWIN} -eq 1 ]; then
# shellcheck disable=SC2054,SC2206,SC2140
args+=(-accel hvf)
if [ "${OS_KERNEL}" == "Darwin" ]; then
if [ -z "${HYPERVISOR}" ]; then
# shellcheck disable=SC2054,SC2206,SC2140
args+=(-accel hvf)
fi
else
# shellcheck disable=SC2054,SC2206,SC2140
args+=(-name ${VMNAME},process=${VMNAME} -enable-kvm)
@ -1112,7 +1136,7 @@ function vm_boot() {
args+=(-device virtio-rng-pci,rng=rng0 -object rng-random,id=rng0,filename=/dev/urandom)
# macOS doesn't support SPICE
if [ ${DARWIN} -eq 0 ]; then
if [ "${OS_KERNEL}" == "Linux" ]; then
# shellcheck disable=SC2054
args+=(-device "${USB_HOST_PASSTHROUGH_CONTROLLER}",id=spicepass
-chardev spicevmc,id=usbredirchardev1,name=usbredir
@ -1169,7 +1193,7 @@ function vm_boot() {
fi
# Braille requires SDL, so disable for macOS
if [ -n "${BRAILLE}" ] && [ ${DARWIN} -eq 0 ]; then
if [ -n "${BRAILLE}" ] && [ "${OS_KERNEL}" == "Linux" ]; then
if ${QEMU} -chardev help | grep -q braille; then
# shellcheck disable=SC2054
#args+=(-chardev braille,id=brltty
@ -1541,16 +1565,17 @@ function display_param_check() {
display="sdl"
fi
if [ "${display}" != "gtk" ] && [ "${display}" != "none" ] && [ "${display}" != "sdl" ] && [ "${display}" != "spice" ] && [ "${display}" != "spice-app" ]; then
echo "ERROR! Requested output '${display}' is not recognised."
exit 1
elif [ "${display}" == "cocoa" ] && [ ${DARWIN} -eq 0 ]; then
echo "ERROR! Requested output '${display}' is only supported on macOS."
exit 1
elif [ "${display}" != "cocoa" ] && [ ${DARWIN} -eq 1 ]; then
echo "WARNING! Requested output '${display}' but only 'cocoa' is avalible on macOS."
echo " Setting display to 'cocoa'."
display="cocoa"
if [ "${OS_KERNEL}" == "Darwin" ]; then
if [ "${display}" != "cocoa" ]; then
echo "WARNING! Requested output '${display}' but only 'cocoa' is avalible on macOS."
echo " Setting display to 'cocoa'."
display="cocoa"
fi
else
if [ "${display}" != "gtk" ] && [ "${display}" != "none" ] && [ "${display}" != "sdl" ] && [ "${display}" != "spice" ] && [ "${display}" != "spice-app" ]; then
echo "ERROR! Requested output '${display}' is not recognised."
exit 1
fi
fi
# Set the default 3D acceleration.
@ -1627,6 +1652,10 @@ function tpm_param_check() {
}
function viewer_param_check() {
if [ "${OS_KERNEL}" == "Darwin" ]; then
return
fi
if [ "${viewer}" != "none" ] && [ "${viewer}" != "spicy" ] && [ "${viewer}" != "remote-viewer" ]; then
echo "ERROR! Requested viewer '${viewer}' is not recognised."
exit 1
@ -1787,8 +1816,8 @@ readonly VERSION="4.9.5"
# TODO: Make this run the native architecture binary
QEMU=$(command -v qemu-system-x86_64)
QEMU_IMG=$(command -v qemu-img)
if [ ! -e "${QEMU}" ] || [ ! -e "${QEMU_IMG}" ]; then
echo "ERROR! QEMU not found. Please make install qemu-system-x86_64 and qemu-img"
if [ ! -x "${QEMU}" ] || [ ! -x "${QEMU_IMG}" ]; then
echo "ERROR! QEMU not found. Please make sure 'qemu-system-x86_64' and 'qemu-img' are installed."
exit 1
fi
@ -1798,9 +1827,16 @@ if command -v gstat &>/dev/null; then
STAT="gstat"
fi
DARWIN=0
if [ "$(uname -s)" == "Darwin" ]; then
DARWIN=1
OS_KERNEL=$(uname -s)
CPU_KVM=",kvm=on"
CPU_KVM_UNHALT=",kvm_pv_unhalt"
KVM_GUEST_TWEAKS="-global kvm-pit.lost_tick_policy=discard "
# Detect macOS and disable KVM
if [ "${OS_KERNEL}" == "Darwin" ]; then
CPU_KVM=""
CPU_KVM_UNHALT=""
KVM_GUEST_TWEAKS=""
display="cocoa"
fi
QEMU_VER_LONG=$(${QEMU} -version | head -n1 | cut -d' ' -f4 | cut -d'(' -f1)

View File

@ -3145,8 +3145,7 @@ function download_windows_workstation() {
esac
local user_agent="Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0"
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
session_id="$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)"
session_id="$(uuidgen)"
# Get product edition ID for latest release of given Windows version
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
@ -3387,12 +3386,18 @@ fi
I18NS=()
OPERATION=""
CURL=$(command -v curl)
if [ ! -e "${CURL}" ]; then
if [ ! -x "${CURL}" ]; then
echo "ERROR! curl not found. Please install curl"
exit 1
fi
CURL_VERSION=$("${CURL}" --version | head -1 | cut -d' ' -f2)
QEMU_IMG=$(command -v qemu-img)
if [ ! -x "${QEMU_IMG}" ]; then
echo "ERROR! qemu-img not found. Please make sure qemu-img is installed."
exit 1
fi
#TODO: Deprecate `list`, `list_csv`, and `list_json` in favor of `--list`, `--list-csv`, and `--list-json`
case "${1}" in
--download|-download)