# QEMU uefi variable store Starting with version 10.0 (released April 2025) qemu can provide an uefi variable store to the guest. ## Motivation Main difference to the traditional approach to provide pflash storage for the variables is that qemu will also handle access control and signature verification for authenticated variable updates. Moving that functionality from priviledged guest mode (SMM on x64) to the host makes it much easier to support secure boot. The requirement to have some priviledged guest mode for VMs goes away. ## Build the firmware Support for the qemu uefi variable store is a compile time option. It is disabled by default and can be enabled using the QEMU_PV_VARS option. It makes sense to also enable secure boot support, i.e. build with '-D QEMU_PV_VARS=TRUE -D SECURE_BOOT_ENABLE=TRUE'. Supported platforms: * OvmfPkg/OvmfPkgX64.dsc * ArmVirtPkg/ArmVirtQemu.dsc * ArmVirtPkg/ArmVirtQemuKernel.dsc * OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc ## Using the qemu uefi variable store The variable store is implemented as qemu device and it comes in two variants. The first is `uefi-vars-x64`, for the x64 platform, using the 'etc/hardware-info' fw_cfg file for device discovery. The second is `uefi-vars-sysbus`, used by all other platforms, using device tree for device discovery. Simplest way to use it is this: ``` qemu-system-x86_64 \ -bios OVMF.qemuvars.fd \ -device uefi-vars-x64 \ $otherargs ``` This runs the uefi variable store without persistence, i.e. the variables will be lost on VM poweroff (i.e. qemu exit). The variables will survive reboots though. QEMU can save the variable store in json format for persistence. This is enabled by passing a filename for the varstore to qemu: ``` touch /path/to/varstore.json qemu-system-x86_64 \ -bios OVMF.qemuvars.fd \ -device uefi-vars-x64,jsonfile=/path/to/varstore.json \ $otherargs ``` ## Enroll secure boot variables There are two projects which can handle the json format variable store: https://gitlab.com/kraxel/virt-firmware and https://github.com/awslabs/python-uefivars. virt-firmware can be installed via `pip install virt-firmware`. Your linux distro might also have packages for you. On Fedora, RHEL and Centos Stream `dnf install virt-firmware` works. Creating a variable store with secure boot variables enrolled works this way: ``` virt-fw-vars \ --secure-boot \ --enroll-redhat \ --set-dbx /usr/share/edk2/ovmf/DBXUpdate-${date}.x64.bin \ --output-json /path/to/varstore.json ``` This will enroll the standard set of microsoft certificates (both 2011 and 2023). There are a number of config options to change default behavior, check out `virt-fw-vars --help`. If your linux distro does not ship the dbx revocation database you can get it from https://github.com/microsoft/secureboot_objects/ (subdirectory `PostSignedObjects/DBX`) instead.