feat(vm): add shared QEMU hardware profile arg builder
- commit
- 74d97ff95641bfa71c1ce5ee5730e0ea0197d765
- author
- brice · · 2026-02-27 04:39 UTC
- parent
- 588105a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +94 -0
A test/vm/lib/qemu-profile.sh +94 -0
| @@ -0,0 +1,94 @@ | |||
| 1 | + | #!/bin/bash | |
| 2 | + | # Shared QEMU argument builder for hardware profiles | |
| 3 | + | # Source this file then call: build_qemu_args PROFILE SECURE_BOOT SSH_PORT TEST_DIR | |
| 4 | + | # Result is stored in the QEMU_ARGS array. | |
| 5 | + | ||
| 6 | + | OVMF_CODE_NORMAL="/usr/share/edk2/x64/OVMF_CODE.4m.fd" | |
| 7 | + | OVMF_CODE_SECBOOT="/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd" | |
| 8 | + | OVMF_VARS_TEMPLATE="/usr/share/edk2/x64/OVMF_VARS.4m.fd" | |
| 9 | + | ||
| 10 | + | build_qemu_args() { | |
| 11 | + | local profile="$1" | |
| 12 | + | local secure_boot="$2" | |
| 13 | + | local ssh_port="$3" | |
| 14 | + | local test_dir="$4" | |
| 15 | + | ||
| 16 | + | QEMU_ARGS=() | |
| 17 | + | ||
| 18 | + | # ── Machine & CPU ──────────────────────────────────────────────────────────── | |
| 19 | + | QEMU_ARGS+=(-enable-kvm) | |
| 20 | + | QEMU_ARGS+=(-machine q35,vmport=off) | |
| 21 | + | QEMU_ARGS+=(-cpu host) | |
| 22 | + | QEMU_ARGS+=(-smp 4,cores=2,threads=2,sockets=1) | |
| 23 | + | QEMU_ARGS+=(-m 4096) | |
| 24 | + | QEMU_ARGS+=(-uuid "$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)") | |
| 25 | + | ||
| 26 | + | # ── Firmware ───────────────────────────────────────────────────────────────── | |
| 27 | + | if [[ "$secure_boot" == "on" ]]; then | |
| 28 | + | local vars_copy | |
| 29 | + | vars_copy="$(mktemp /tmp/OVMF_VARS_XXXXXXXX.fd)" | |
| 30 | + | cp "$OVMF_VARS_TEMPLATE" "$vars_copy" | |
| 31 | + | QEMU_ARGS+=(-machine q35,vmport=off,smm=on) # override previous -machine | |
| 32 | + | QEMU_ARGS+=(-global driver=cfi.pflash01,property=secure,value=on) | |
| 33 | + | QEMU_ARGS+=(-drive "if=pflash,readonly=on,format=raw,file=${OVMF_CODE_SECBOOT}") | |
| 34 | + | QEMU_ARGS+=(-drive "if=pflash,format=raw,file=${vars_copy}") | |
| 35 | + | # clean up temp VARS on exit | |
| 36 | + | trap "rm -f '$vars_copy'" EXIT | |
| 37 | + | else | |
| 38 | + | QEMU_ARGS+=(-bios /usr/share/edk2/x64/OVMF.4m.fd) | |
| 39 | + | fi | |
| 40 | + | ||
| 41 | + | # ── SMBIOS ─────────────────────────────────────────────────────────────────── | |
| 42 | + | # Type 0: BIOS | |
| 43 | + | QEMU_ARGS+=(-smbios "type=0,vendor=American Megatrends Inc.,version=F14,date=12/01/2021,uefi=on") | |
| 44 | + | ||
| 45 | + | case "$profile" in | |
| 46 | + | desktop) | |
| 47 | + | # Type 1: System | |
| 48 | + | QEMU_ARGS+=(-smbios "type=1,manufacturer=Gigabyte Technology Co. Ltd.,product=B550 AORUS ELITE V2,version=1.0,serial=SN-DESKTOP-001,uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid),sku=Default string,family=Desktop") | |
| 49 | + | # Type 2: Board | |
| 50 | + | QEMU_ARGS+=(-smbios "type=2,manufacturer=Gigabyte Technology Co. Ltd.,product=B550 AORUS ELITE V2,version=x.x,serial=SN-BOARD-DESKTOP,asset=Base Board Asset Tag,location=Default string") | |
| 51 | + | # Type 3: Chassis — desktop (type 3) | |
| 52 | + | QEMU_ARGS+=(-smbios "type=3,manufacturer=Default string,version=Default string,serial=Default string,asset=Default string,sku=Default string") | |
| 53 | + | ;; | |
| 54 | + | laptop) | |
| 55 | + | # Type 1: System — ThinkPad X1 Carbon Gen 10 | |
| 56 | + | QEMU_ARGS+=(-smbios "type=1,manufacturer=LENOVO,product=21CB,version=ThinkPad X1 Carbon Gen 10,serial=SN-LAPTOP-001,uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid),sku=LENOVO_MT_21CB,family=ThinkPad X1 Carbon Gen 10") | |
| 57 | + | # Type 2: Board | |
| 58 | + | QEMU_ARGS+=(-smbios "type=2,manufacturer=LENOVO,product=21CB,version=SDK0J40697 WIN,serial=SN-BOARD-LAPTOP,asset=Not Available,location=Not Available") | |
| 59 | + | # Type 3: Chassis — notebook (type 10) | |
| 60 | + | QEMU_ARGS+=(-smbios "type=3,manufacturer=LENOVO,version=None,serial=SN-CHASSIS-LAPTOP,asset=Not Available,sku=Not Available") | |
| 61 | + | ;; | |
| 62 | + | *) | |
| 63 | + | echo "Unknown profile: $profile (expected desktop or laptop)" >&2 | |
| 64 | + | return 1 | |
| 65 | + | ;; | |
| 66 | + | esac | |
| 67 | + | ||
| 68 | + | # ── Storage — NVMe ─────────────────────────────────────────────────────────── | |
| 69 | + | local nvme_serial | |
| 70 | + | case "$profile" in | |
| 71 | + | desktop) nvme_serial="TESTDESKTOP0001" ;; | |
| 72 | + | laptop) nvme_serial="TESTLAPTOP00001" ;; | |
| 73 | + | esac | |
| 74 | + | QEMU_ARGS+=(-drive "if=none,id=nvme0,format=qcow2,file=${test_dir}/arch-test.qcow2") | |
| 75 | + | QEMU_ARGS+=(-device "nvme,drive=nvme0,serial=${nvme_serial}") | |
| 76 | + | ||
| 77 | + | # ── Network ────────────────────────────────────────────────────────────────── | |
| 78 | + | QEMU_ARGS+=(-netdev "user,id=net0,hostfwd=tcp::${ssh_port}-:22") | |
| 79 | + | QEMU_ARGS+=(-device "e1000e,netdev=net0,mac=52:54:00:12:34:56") | |
| 80 | + | ||
| 81 | + | # ── USB Controller + Input ─────────────────────────────────────────────────── | |
| 82 | + | QEMU_ARGS+=(-device qemu-xhci) | |
| 83 | + | QEMU_ARGS+=(-device usb-kbd) | |
| 84 | + | QEMU_ARGS+=(-device usb-tablet) | |
| 85 | + | ||
| 86 | + | # ── Audio ───────────────────────────────────────────────────────────────────── | |
| 87 | + | QEMU_ARGS+=(-audiodev none,id=audio0) | |
| 88 | + | QEMU_ARGS+=(-device ich9-intel-hda) | |
| 89 | + | QEMU_ARGS+=(-device hda-duplex,audiodev=audio0) | |
| 90 | + | ||
| 91 | + | # ── GPU / Display ───────────────────────────────────────────────────────────── | |
| 92 | + | QEMU_ARGS+=(-device "virtio-vga,xres=1920,yres=1080") | |
| 93 | + | QEMU_ARGS+=(-display "gtk,zoom-to-fit=on") | |
| 94 | + | } | |
| @@ -0,0 +1,94 @@ | |||||
| 1 | + | #!/bin/bash | |||
| 2 | + | # Shared QEMU argument builder for hardware profiles | |||
| 3 | + | # Source this file then call: build_qemu_args PROFILE SECURE_BOOT SSH_PORT TEST_DIR | |||
| 4 | + | # Result is stored in the QEMU_ARGS array. | |||
| 5 | + | ||||
| 6 | + | OVMF_CODE_NORMAL="/usr/share/edk2/x64/OVMF_CODE.4m.fd" | |||
| 7 | + | OVMF_CODE_SECBOOT="/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd" | |||
| 8 | + | OVMF_VARS_TEMPLATE="/usr/share/edk2/x64/OVMF_VARS.4m.fd" | |||
| 9 | + | ||||
| 10 | + | build_qemu_args() { | |||
| 11 | + | local profile="$1" | |||
| 12 | + | local secure_boot="$2" | |||
| 13 | + | local ssh_port="$3" | |||
| 14 | + | local test_dir="$4" | |||
| 15 | + | ||||
| 16 | + | QEMU_ARGS=() | |||
| 17 | + | ||||
| 18 | + | # ── Machine & CPU ──────────────────────────────────────────────────────────── | |||
| 19 | + | QEMU_ARGS+=(-enable-kvm) | |||
| 20 | + | QEMU_ARGS+=(-machine q35,vmport=off) | |||
| 21 | + | QEMU_ARGS+=(-cpu host) | |||
| 22 | + | QEMU_ARGS+=(-smp 4,cores=2,threads=2,sockets=1) | |||
| 23 | + | QEMU_ARGS+=(-m 4096) | |||
| 24 | + | QEMU_ARGS+=(-uuid "$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)") | |||
| 25 | + | ||||
| 26 | + | # ── Firmware ───────────────────────────────────────────────────────────────── | |||
| 27 | + | if [[ "$secure_boot" == "on" ]]; then | |||
| 28 | + | local vars_copy | |||
| 29 | + | vars_copy="$(mktemp /tmp/OVMF_VARS_XXXXXXXX.fd)" | |||
| 30 | + | cp "$OVMF_VARS_TEMPLATE" "$vars_copy" | |||
| 31 | + | QEMU_ARGS+=(-machine q35,vmport=off,smm=on) # override previous -machine | |||
| 32 | + | QEMU_ARGS+=(-global driver=cfi.pflash01,property=secure,value=on) | |||
| 33 | + | QEMU_ARGS+=(-drive "if=pflash,readonly=on,format=raw,file=${OVMF_CODE_SECBOOT}") | |||
| 34 | + | QEMU_ARGS+=(-drive "if=pflash,format=raw,file=${vars_copy}") | |||
| 35 | + | # clean up temp VARS on exit | |||
| 36 | + | trap "rm -f '$vars_copy'" EXIT | |||
| 37 | + | else | |||
| 38 | + | QEMU_ARGS+=(-bios /usr/share/edk2/x64/OVMF.4m.fd) | |||
| 39 | + | fi | |||
| 40 | + | ||||
| 41 | + | # ── SMBIOS ─────────────────────────────────────────────────────────────────── | |||
| 42 | + | # Type 0: BIOS | |||
| 43 | + | QEMU_ARGS+=(-smbios "type=0,vendor=American Megatrends Inc.,version=F14,date=12/01/2021,uefi=on") | |||
| 44 | + | ||||
| 45 | + | case "$profile" in | |||
| 46 | + | desktop) | |||
| 47 | + | # Type 1: System | |||
| 48 | + | QEMU_ARGS+=(-smbios "type=1,manufacturer=Gigabyte Technology Co. Ltd.,product=B550 AORUS ELITE V2,version=1.0,serial=SN-DESKTOP-001,uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid),sku=Default string,family=Desktop") | |||
| 49 | + | # Type 2: Board | |||
| 50 | + | QEMU_ARGS+=(-smbios "type=2,manufacturer=Gigabyte Technology Co. Ltd.,product=B550 AORUS ELITE V2,version=x.x,serial=SN-BOARD-DESKTOP,asset=Base Board Asset Tag,location=Default string") | |||
| 51 | + | # Type 3: Chassis — desktop (type 3) | |||
| 52 | + | QEMU_ARGS+=(-smbios "type=3,manufacturer=Default string,version=Default string,serial=Default string,asset=Default string,sku=Default string") | |||
| 53 | + | ;; | |||
| 54 | + | laptop) | |||
| 55 | + | # Type 1: System — ThinkPad X1 Carbon Gen 10 | |||
| 56 | + | QEMU_ARGS+=(-smbios "type=1,manufacturer=LENOVO,product=21CB,version=ThinkPad X1 Carbon Gen 10,serial=SN-LAPTOP-001,uuid=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid),sku=LENOVO_MT_21CB,family=ThinkPad X1 Carbon Gen 10") | |||
| 57 | + | # Type 2: Board | |||
| 58 | + | QEMU_ARGS+=(-smbios "type=2,manufacturer=LENOVO,product=21CB,version=SDK0J40697 WIN,serial=SN-BOARD-LAPTOP,asset=Not Available,location=Not Available") | |||
| 59 | + | # Type 3: Chassis — notebook (type 10) | |||
| 60 | + | QEMU_ARGS+=(-smbios "type=3,manufacturer=LENOVO,version=None,serial=SN-CHASSIS-LAPTOP,asset=Not Available,sku=Not Available") | |||
| 61 | + | ;; | |||
| 62 | + | *) | |||
| 63 | + | echo "Unknown profile: $profile (expected desktop or laptop)" >&2 | |||
| 64 | + | return 1 | |||
| 65 | + | ;; | |||
| 66 | + | esac | |||
| 67 | + | ||||
| 68 | + | # ── Storage — NVMe ─────────────────────────────────────────────────────────── | |||
| 69 | + | local nvme_serial | |||
| 70 | + | case "$profile" in | |||
| 71 | + | desktop) nvme_serial="TESTDESKTOP0001" ;; | |||
| 72 | + | laptop) nvme_serial="TESTLAPTOP00001" ;; | |||
| 73 | + | esac | |||
| 74 | + | QEMU_ARGS+=(-drive "if=none,id=nvme0,format=qcow2,file=${test_dir}/arch-test.qcow2") | |||
| 75 | + | QEMU_ARGS+=(-device "nvme,drive=nvme0,serial=${nvme_serial}") | |||
| 76 | + | ||||
| 77 | + | # ── Network ────────────────────────────────────────────────────────────────── | |||
| 78 | + | QEMU_ARGS+=(-netdev "user,id=net0,hostfwd=tcp::${ssh_port}-:22") | |||
| 79 | + | QEMU_ARGS+=(-device "e1000e,netdev=net0,mac=52:54:00:12:34:56") | |||
| 80 | + | ||||
| 81 | + | # ── USB Controller + Input ─────────────────────────────────────────────────── | |||
| 82 | + | QEMU_ARGS+=(-device qemu-xhci) | |||
| 83 | + | QEMU_ARGS+=(-device usb-kbd) | |||
| 84 | + | QEMU_ARGS+=(-device usb-tablet) | |||
| 85 | + | ||||
| 86 | + | # ── Audio ───────────────────────────────────────────────────────────────────── | |||
| 87 | + | QEMU_ARGS+=(-audiodev none,id=audio0) | |||
| 88 | + | QEMU_ARGS+=(-device ich9-intel-hda) | |||
| 89 | + | QEMU_ARGS+=(-device hda-duplex,audiodev=audio0) | |||
| 90 | + | ||||
| 91 | + | # ── GPU / Display ───────────────────────────────────────────────────────────── | |||
| 92 | + | QEMU_ARGS+=(-device "virtio-vga,xres=1920,yres=1080") | |||
| 93 | + | QEMU_ARGS+=(-display "gtk,zoom-to-fit=on") | |||
| 94 | + | } | |||