From 896b4fc56a99a13086e229018229b31069b0ba55 Mon Sep 17 00:00:00 2001 From: grossmj Date: Mon, 13 Jul 2026 11:08:17 +0200 Subject: [PATCH 1/2] UEFI improvements for Qemu VMs * Add OVMF firmware directory configuration * Automatically add a Random Number Generator (RNG) device when using uefi option is enabled --- conf/gns3_server.conf | 2 ++ gns3server/compute/qemu/qemu_vm.py | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/conf/gns3_server.conf b/conf/gns3_server.conf index aa54d57c8..7bb2aa6bd 100644 --- a/conf/gns3_server.conf +++ b/conf/gns3_server.conf @@ -103,6 +103,8 @@ enable_hardware_acceleration = True require_hardware_acceleration = False ; Allow unsafe additional command line options allow_unsafe_options = False +; Path to the OVMF firmware directory +ovmf_firmware_dir = "/usr/share/OVMF" [VMware] ; First vmnet interface of the range that can be managed by the GNS3 server diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index f97e5db31..11399a0ed 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -35,6 +35,7 @@ import time import json import psutil +from pathlib import Path from gns3server.utils import parse_version, shlex_quote from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor from .qemu_error import QemuError @@ -2057,15 +2058,17 @@ class QemuVM(BaseNode): options.extend(["-bios", self._bios_image.replace(",", ",,")]) elif self._uefi: - + ovmf_firmware_dir = self._manager.config.get_section_config("Qemu").get("ovmf_firmware_dir", "/usr/share/OVMF") + system_ovmf_firmware_dir = Path(ovmf_firmware_dir) + log.info("Using OVMF firmware directory: {}".format(system_ovmf_firmware_dir)) old_ovmf_vars_path = os.path.join(self.working_dir, "OVMF_VARS.fd") if os.path.exists(old_ovmf_vars_path): # the node has its own UEFI variables store already, we must also use the old UEFI firmware ovmf_firmware_path = self.manager.get_abs_image_path("OVMF_CODE.fd") else: - system_ovmf_firmware_path = "/usr/share/OVMF/OVMF_CODE_4M.fd" - if os.path.exists(system_ovmf_firmware_path): - ovmf_firmware_path = system_ovmf_firmware_path + system_ovmf_firmware_path = next(system_ovmf_firmware_dir.glob("OVMF_CODE_4M.fd", case_sensitive=False), None) + if system_ovmf_firmware_path: + ovmf_firmware_path = str(system_ovmf_firmware_path) else: # otherwise, get the UEFI firmware from the images directory ovmf_firmware_path = self.manager.get_abs_image_path("OVMF_CODE_4M.fd") @@ -2074,9 +2077,9 @@ class QemuVM(BaseNode): options.extend(["-drive", "if=pflash,format=raw,readonly,file={}".format(ovmf_firmware_path)]) # try to use the UEFI variables store from the system first - system_ovmf_vars_path = "/usr/share/OVMF/OVMF_VARS_4M.fd" - if os.path.exists(system_ovmf_vars_path): - ovmf_vars_path = system_ovmf_vars_path + system_ovmf_vars_path = next(system_ovmf_firmware_dir.glob("OVMF_VARS_4M.fd", case_sensitive=False), None) + if system_ovmf_vars_path: + ovmf_vars_path = str(system_ovmf_vars_path) else: # otherwise, get the UEFI variables store from the images directory ovmf_vars_path = self.manager.get_abs_image_path("OVMF_VARS_4M.fd") @@ -2092,6 +2095,10 @@ class QemuVM(BaseNode): except OSError as e: raise QemuError("Cannot copy OVMF_VARS_4M.fd file to the node working directory: {}".format(e)) options.extend(["-drive", "if=pflash,format=raw,file={}".format(ovmf_vars_node_path)]) + + # edk2 firmware requires a Random Number Generator (RNG) device in order to turn network adapters on + options.extend(["-object", "rng-random,filename=/dev/urandom,id=rng0 "]) + options.extend(["-device", "virtio-rng-pci,rng=rng0"]) return options def _linux_boot_options(self): From 61c7f4469dda6b755b93762e9efe95c63330d97c Mon Sep 17 00:00:00 2001 From: grossmj Date: Mon, 13 Jul 2026 11:34:29 +0200 Subject: [PATCH 2/2] Search for system UEFI that is compatible with Python < 3.12 --- gns3server/compute/qemu/qemu_vm.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index 11399a0ed..fa7757a62 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -2066,7 +2066,13 @@ class QemuVM(BaseNode): # the node has its own UEFI variables store already, we must also use the old UEFI firmware ovmf_firmware_path = self.manager.get_abs_image_path("OVMF_CODE.fd") else: - system_ovmf_firmware_path = next(system_ovmf_firmware_dir.glob("OVMF_CODE_4M.fd", case_sensitive=False), None) + # Use a manual case-insensitive search instead + try: + system_ovmf_firmware_path = next((f for f in system_ovmf_firmware_dir.glob("*.fd") + if f.name.lower() == "ovmf_code_4m.fd"), None) + except (FileNotFoundError, StopIteration): + system_ovmf_firmware_path = None + if system_ovmf_firmware_path: ovmf_firmware_path = str(system_ovmf_firmware_path) else: @@ -2077,7 +2083,11 @@ class QemuVM(BaseNode): options.extend(["-drive", "if=pflash,format=raw,readonly,file={}".format(ovmf_firmware_path)]) # try to use the UEFI variables store from the system first - system_ovmf_vars_path = next(system_ovmf_firmware_dir.glob("OVMF_VARS_4M.fd", case_sensitive=False), None) + try: + system_ovmf_vars_path = next((f for f in system_ovmf_firmware_dir.glob("*.fd") + if f.name.lower() == "ovmf_vars_4m.fd"), None) + except (FileNotFoundError, StopIteration): + system_ovmf_vars_path = None if system_ovmf_vars_path: ovmf_vars_path = str(system_ovmf_vars_path) else: