fix: UEFI booting (#1)

This commit is contained in:
Kroese 2024-02-02 17:07:44 +01:00 committed by GitHub
parent 6b8eaa4eb1
commit c9f2231b55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 108 additions and 142 deletions

View file

@ -20,5 +20,5 @@ jobs:
uses: hadolint/hadolint-action@v3.1.0 uses: hadolint/hadolint-action@v3.1.0
with: with:
dockerfile: Dockerfile dockerfile: Dockerfile
ignore: DL3008,DL3003 ignore: DL3008,DL3003,DL3035,DL3059
failure-threshold: warning failure-threshold: warning

View file

@ -8,10 +8,10 @@ RUN apt-get update \
&& apt-get --no-install-recommends -y install \ && apt-get --no-install-recommends -y install \
tini \ tini \
wget \ wget \
ovmf \
nginx \ nginx \
swtpm \ swtpm \
procps \ procps \
seabios \
iptables \ iptables \
iproute2 \ iproute2 \
apt-utils \ apt-utils \
@ -21,6 +21,7 @@ RUN apt-get update \
ca-certificates \ ca-certificates \
netcat-openbsd \ netcat-openbsd \
qemu-system-arm \ qemu-system-arm \
qemu-efi-aarch64 \
&& apt-get clean \ && apt-get clean \
&& novnc="1.4.0" \ && novnc="1.4.0" \
&& mkdir -p /usr/share/novnc \ && mkdir -p /usr/share/novnc \

View file

@ -97,27 +97,13 @@ docker run -it --rm -e "BOOT=http://example.com/image.iso" -p 8006:8006 --device
Replace the example path `/var/qemu` with the desired storage folder. Replace the example path `/var/qemu` with the desired storage folder.
* ### How do I boot Windows? * ### How do I boot a x86 image?
To enable Windows booting, add the following line to your compose file: You can use [qemu-docker](https://github.com/qemus/qemu-docker/) to run x86 and x64 images on ARM.
```yaml * ### How do I boot a local image?
environment:
BOOT_MODE: "windows"
```
But you might want to give [dockur/windows](https://github.com/dockur/windows) a try instead, as it includes all the drivers required during installation and many other features. To skip the download, rename your image to `boot.iso` and place it in an empty `/storage` folder.
* ### How do I verify if my system supports KVM?
To verify if your system supports KVM, run the following commands:
```bash
sudo apt install cpu-checker
sudo kvm-ok
```
If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.
* ### How do I assign an individual IP address to the container? * ### How do I assign an individual IP address to the container?
@ -196,18 +182,16 @@ docker run -it --rm -e "BOOT=http://example.com/image.iso" -p 8006:8006 --device
- /dev/bus/usb - /dev/bus/usb
``` ```
* ### How do I boot with UEFI? * ### How do I verify if my system supports KVM?
To enable UEFI booting, add the following line to your compose file: To verify if your system supports KVM, run the following commands:
```yaml ```bash
environment: sudo apt install cpu-checker
BOOT_MODE: "uefi" sudo kvm-ok
``` ```
* ### How do I boot a local image? If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.
To skip the download, rename your image to `boot.iso` and place it in an empty `/storage` folder.
* ### How do I provide custom arguments to QEMU? * ### How do I provide custom arguments to QEMU?
@ -218,10 +202,6 @@ docker run -it --rm -e "BOOT=http://example.com/image.iso" -p 8006:8006 --device
ARGUMENTS: "-device usb-tablet" ARGUMENTS: "-device usb-tablet"
``` ```
* ### How do I run a x86 or x64 machine?
You can use [qemu-docker](https://github.com/qemus/qemu-docker/) to run x86 and x64 machines on ARM.
[build_url]: https://github.com/qemus/qemu-arm/ [build_url]: https://github.com/qemus/qemu-arm/
[hub_url]: https://hub.docker.com/r/qemux/qemu-arm/ [hub_url]: https://hub.docker.com/r/qemux/qemu-arm/
[tag_url]: https://hub.docker.com/r/qemux/qemu-arm/tags [tag_url]: https://hub.docker.com/r/qemux/qemu-arm/tags

View file

@ -2,99 +2,99 @@
set -Eeuo pipefail set -Eeuo pipefail
# Docker environment variables # Docker environment variables
: "${TPM:="Y"}" # Enable TPM : "${TPM:="Y"}" # Enable TPM
: "${BOOT_MODE:="legacy"}" # Boot mode : "${BIOS:=""}" # Bios file
: "${BOOT_MODE:="uefi"}" # Boot mode
SECURE="" SECURE=""
BOOT_OPTS="" DIR="/usr/share/qemu"
BOOT_OPTS="-device ramfb"
case "${BOOT_MODE,,}" in case "${BOOT_MODE,,}" in
uefi) uefi)
ROM="OVMF_CODE_4M.fd" ROM="AAVMF_CODE.fd"
VARS="OVMF_VARS_4M.fd" VARS="AAVMF_VARS.fd"
;; ;;
secure) secure)
ROM="OVMF_CODE_4M.secboot.fd" ROM="AAVMF_CODE.fd"
VARS="OVMF_VARS_4M.secboot.fd" VARS="AAVMF_VARS.fd"
;; ;;
windows) windows)
ROM="OVMF_CODE_4M.ms.fd" ROM="AAVMF_CODE.ms.fd"
VARS="OVMF_VARS_4M.ms.fd" VARS="AAVMF_VARS.ms.fd"
;;
windows_legacy)
USB="usb-ehci,id=ehci"
BOOT_OPTS=""
;;
legacy)
BOOT_OPTS=""
;; ;;
*) *)
info "Unknown boot mode '${BOOT_MODE}', defaulting to 'legacy'" info "Unknown boot mode '${BOOT_MODE}', defaulting to 'uefi'"
BOOT_MODE="legacy" BOOT_MODE="uefi"
ROM="AAVMF_CODE.fd"
VARS="AAVMF_VARS.fd"
;; ;;
esac esac
if [[ "${BOOT_MODE,,}" != "legacy" ]] && [[ "${BOOT_MODE,,}" != "windows_legacy" ]]; then if [ -n "$BIOS" ]; then
OVMF="/usr/share/OVMF" BOOT_OPTS="$BOOT_OPTS -bios $DIR/$BIOS"
DEST="$STORAGE/${BOOT_MODE,,}" return 0
if [ ! -f "$DEST.rom" ]; then
[ ! -f "$OVMF/$ROM" ] && error "UEFI boot file ($OVMF/$ROM) not found!" && exit 44
cp "$OVMF/$ROM" "$DEST.rom"
fi
if [ ! -f "$DEST.vars" ]; then
[ ! -f "$OVMF/$VARS" ] && error "UEFI vars file ($OVMF/$VARS) not found!" && exit 45
cp "$OVMF/$VARS" "$DEST.vars"
fi
if [[ "${BOOT_MODE,,}" != "uefi" ]]; then
SECURE=",smm=on"
BOOT_OPTS="$BOOT_OPTS -global driver=cfi.pflash01,property=secure,value=on"
fi
BOOT_OPTS="$BOOT_OPTS -drive file=$DEST.rom,if=pflash,unit=0,format=raw,readonly=on"
BOOT_OPTS="$BOOT_OPTS -drive file=$DEST.vars,if=pflash,unit=1,format=raw"
if [[ "${BOOT_MODE,,}" == "windows" ]]; then
BOOT_OPTS="$BOOT_OPTS -global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1"
if [[ "$TPM" == [Yy1]* ]]; then
rm -rf /run/shm/tpm
rm -f /var/run/tpm.pid
mkdir -p /run/shm/tpm
chmod 755 /run/shm/tpm
if ! swtpm socket -t -d --tpmstate dir=/run/shm/tpm --ctrl type=unixio,path=/run/swtpm-sock --pid file=/var/run/tpm.pid --tpm2; then
error "Failed to start TPM emulator, reason: $?" && exit 19
fi
for (( i = 1; i < 20; i++ )); do
[ -S "/run/swtpm-sock" ] && break
if (( i % 10 == 0 )); then
echo "Waiting for TPM socket to become available..."
fi
sleep 0.1
done
if [ ! -S "/run/swtpm-sock" ]; then
TPM="N"
error "TPM socket not found? Disabling TPM support..."
else
BOOT_OPTS="$BOOT_OPTS -chardev socket,id=chrtpm,path=/run/swtpm-sock"
BOOT_OPTS="$BOOT_OPTS -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0"
fi
fi
fi
fi fi
AAVMF="/usr/share/AAVMF/"
DEST="$STORAGE/${BOOT_MODE,,}"
if [ ! -f "$DEST.rom" ]; then
[ ! -f "$AAVMF/$ROM" ] && error "UEFI boot file ($AAVMF/$ROM) not found!" && exit 44
cp "$AAVMF/$ROM" "$DEST.rom"
fi
if [ ! -f "$DEST.vars" ]; then
[ ! -f "$AAVMF/$VARS" ] && error "UEFI vars file ($AAVMF/$VARS) not found!" && exit 45
cp "$AAVMF/$VARS" "$DEST.vars"
fi
if [[ "${BOOT_MODE,,}" != "uefi" ]]; then
SECURE=",smm=on"
BOOT_OPTS="$BOOT_OPTS -global driver=cfi.pflash01,property=secure,value=on"
fi
BOOT_OPTS="$BOOT_OPTS -drive file=$DEST.rom,if=pflash,unit=0,format=raw,readonly=on"
BOOT_OPTS="$BOOT_OPTS -drive file=$DEST.vars,if=pflash,unit=1,format=raw"
if [[ "${BOOT_MODE,,}" == "windows" ]]; then
BOOT_OPTS="$BOOT_OPTS -global kvm-pit.lost_tick_policy=discard -global ICH9-LPC.disable_s3=1"
if [[ "$TPM" == [Yy1]* ]]; then
rm -rf /run/shm/tpm
rm -f /var/run/tpm.pid
mkdir -p /run/shm/tpm
chmod 755 /run/shm/tpm
if ! swtpm socket -t -d --tpmstate dir=/run/shm/tpm --ctrl type=unixio,path=/run/swtpm-sock --pid file=/var/run/tpm.pid --tpm2; then
error "Failed to start TPM emulator, reason: $?" && exit 19
fi
for (( i = 1; i < 20; i++ )); do
[ -S "/run/swtpm-sock" ] && break
if (( i % 10 == 0 )); then
echo "Waiting for TPM socket to become available..."
fi
sleep 0.1
done
if [ ! -S "/run/swtpm-sock" ]; then
TPM="N"
error "TPM socket not found? Disabling TPM support..."
else
BOOT_OPTS="$BOOT_OPTS -chardev socket,id=chrtpm,path=/run/swtpm-sock"
BOOT_OPTS="$BOOT_OPTS -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0"
fi
fi
fi
return 0 return 0

View file

@ -8,10 +8,10 @@ set -Eeuo pipefail
DEF_OPTS="-nodefaults" DEF_OPTS="-nodefaults"
SERIAL_OPTS="-serial $SERIAL" SERIAL_OPTS="-serial $SERIAL"
MON_OPTS="-monitor $MONITOR" MON_OPTS="-monitor $MONITOR"
USB_OPTS="-device $USB -device usb-tablet" USB_OPTS="-device $USB -device usb-kbd -device usb-tablet"
RAM_OPTS=$(echo "-m $RAM_SIZE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g') RAM_OPTS=$(echo "-m $RAM_SIZE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
CPU_OPTS="-cpu $CPU_FLAGS -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1" CPU_OPTS="-cpu $CPU_FLAGS -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
MAC_OPTS="-machine type=${MACHINE}${SECURE},graphics=off,vmport=off,dump-guest-core=off,hpet=off${KVM_OPTS}" MAC_OPTS="-machine type=${MACHINE}${SECURE},graphics=off,dump-guest-core=off,${KVM_OPTS}"
DEV_OPTS="-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4" DEV_OPTS="-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4"
DEV_OPTS="$DEV_OPTS -object rng-random,id=objrng0,filename=/dev/urandom" DEV_OPTS="$DEV_OPTS -object rng-random,id=objrng0,filename=/dev/urandom"
DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c" DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c"

View file

@ -4,7 +4,7 @@ set -Eeuo pipefail
# Docker environment variables # Docker environment variables
: "${DISK_IO:="native"}" # I/O Mode, can be set to 'native', 'threads' or 'io_turing' : "${DISK_IO:="native"}" # I/O Mode, can be set to 'native', 'threads' or 'io_turing'
: "${DISK_FMT:=""}" # Disk file format, can be set to "raw" (default) or "qcow2" : "${DISK_FMT:=""}" # Disk file format, can be set to "raw" (default) or "qcow2"
: "${DISK_FLAGS:=""}" # Specifies the options for use with the qcow2 disk format : "${DISK_FLAGS:=""}" # Specifies the options for use with the qcow2 disk format
: "${DISK_CACHE:="none"}" # Caching mode, can be set to 'writeback' for better performance : "${DISK_CACHE:="none"}" # Caching mode, can be set to 'writeback' for better performance
: "${DISK_DISCARD:="on"}" # Controls whether unmap (TRIM) commands are passed to the host. : "${DISK_DISCARD:="on"}" # Controls whether unmap (TRIM) commands are passed to the host.
@ -15,20 +15,14 @@ BOOT="$STORAGE/$BASE"
DISK_OPTS="-object iothread,id=io2" DISK_OPTS="-object iothread,id=io2"
DISK_OPTS="$DISK_OPTS -drive id=cdrom0,media=cdrom,if=none,format=raw,readonly=on,file=$BOOT" DISK_OPTS="$DISK_OPTS -drive id=cdrom0,media=cdrom,if=none,format=raw,readonly=on,file=$BOOT"
DISK_OPTS="$DISK_OPTS -device virtio-scsi-pci,id=scsi0,iothread=io2,addr=0x5"
if [[ "${MACHINE,,}" != "pc-q35-2"* ]]; then DISK_OPTS="$DISK_OPTS -device scsi-cd,bus=scsi0.0,drive=cdrom0,bootindex=$BOOT_INDEX"
DISK_OPTS="$DISK_OPTS -device virtio-scsi-pci,id=scsi0,iothread=io2,addr=0x5"
DISK_OPTS="$DISK_OPTS -device scsi-cd,bus=scsi0.0,drive=cdrom0,bootindex=$BOOT_INDEX"
else
DISK_OPTS="$DISK_OPTS -device ide-cd,drive=cdrom0,bootindex=$BOOT_INDEX"
fi
DRIVERS="$STORAGE/drivers.iso" DRIVERS="$STORAGE/drivers.iso"
[ ! -f "$DRIVERS" ] && DRIVERS="/run/drivers.iso" [ ! -f "$DRIVERS" ] && DRIVERS="/run/drivers.iso"
if [ -f "$DRIVERS" ] && [[ "${MACHINE,,}" != "pc-q35-2"* ]]; then if [ -f "$DRIVERS" ]; then
DISK_OPTS="$DISK_OPTS -drive id=cdrom1,media=cdrom,if=none,format=raw,readonly=on,file=$DRIVERS" DISK_OPTS="$DISK_OPTS -drive id=cdrom1,media=cdrom,if=none,format=raw,readonly=on,file=$DRIVERS -device usb-storage,drive=cdrom1"
DISK_OPTS="$DISK_OPTS -device ide-cd,drive=cdrom1"
fi fi
fmt2ext() { fmt2ext() {
@ -357,17 +351,9 @@ createDevice () {
local result="-drive file=$DISK_FILE,if=none,id=drive-$DISK_ID,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on" local result="-drive file=$DISK_FILE,if=none,id=drive-$DISK_ID,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on"
if [[ "${MACHINE,,}" == "pc-q35-2"* ]]; then result="$result \
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
result="$result -device virtio-blk-pci,scsi=off,bus=pcie.0,addr=$DISK_ADDRESS,drive=drive-$DISK_ID,id=$DISK_ID,iothread=io2,bootindex=$DISK_INDEX" -device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
else
result="$result \
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
-device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
fi
echo "$result" echo "$result"
return 0 return 0

View file

@ -3,22 +3,21 @@ set -Eeuo pipefail
# Docker environment variables # Docker environment variables
: "${GPU:="N"}" # GPU passthrough : "${DISPLAY:="web"}" # Display
: "${VGA:="virtio"}" # VGA adaptor : "${VGA:="virtio-gpu"}" # GPU model
: "${DISPLAY:="web"}" # Display type
case "${DISPLAY,,}" in case "${DISPLAY,,}" in
vnc) vnc)
DISPLAY_OPTS="-display vnc=:0 -vga $VGA" DISPLAY_OPTS="-display vnc=:0 -device $VGA"
;; ;;
web) web)
DISPLAY_OPTS="-display vnc=:0,websocket=5700 -vga $VGA" DISPLAY_OPTS="-display vnc=:0,websocket=5700 -device $VGA"
;; ;;
none) none)
DISPLAY_OPTS="-display none -vga none" DISPLAY_OPTS="-display none"
;; ;;
*) *)
DISPLAY_OPTS="-display $DISPLAY -vga $VGA" DISPLAY_OPTS="-display $DISPLAY -device $VGA"
;; ;;
esac esac

View file

@ -33,9 +33,9 @@ fi
if [[ "$KVM" != [Nn]* ]]; then if [[ "$KVM" != [Nn]* ]]; then
CPU_FEATURES="kvm=on" CPU_FEATURES="kvm=on"
KVM_OPTS=",accel=kvm -enable-kvm" KVM_OPTS=",accel=kvm,virtualization=true -enable-kvm"
if [[ "${BOOT_MODE,,}" == "windows" ]] || [[ "${BOOT_MODE,,}" == "windows_legacy" ]]; then if [[ "${BOOT_MODE,,}" == "windows" ]]; then
CPU_FEATURES="kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough" CPU_FEATURES="kvm=on,+hypervisor,+invtsc,l3-cache=on,migratable=no,hv_passthrough"