How Hypervisors Pass Configuration via UEFI Variables
This article provides an overview of how modern hypervisors utilize Unified Extensible Firmware Interface (UEFI) variables to deliver custom configuration data to guest operating systems. By leveraging virtualized Non-Volatile RAM (NVRAM), hypervisors can stage early-boot configuration settings, cloud-init metadata, and network provisions directly into guest memory space. The following sections break down the underlying architecture, the variable injection process, variable attributes, and how guest operating systems access this data post-boot.
The Role of Virtualized NVRAM
In a physical machine, UEFI variables reside in non-volatile flash memory (SPI flash) on the motherboard. Hypervisors like QEMU/KVM, Hyper-V, and VMware ESXi emulate this behavior using virtual flash devices.
In QEMU/KVM with OVMF (Open Virtual Machine Firmware), for example, UEFI execution relies on two distinct images:
- The Code Image (
OVMF_CODE.fd): Contains the read-only executable UEFI firmware. - The Variables Image (
OVMF_VARS.fd): Acts as a virtual flash drive (pflash) representing the NVRAM storage where UEFI variables persist across reboots.
To supply custom data to a guest, the hypervisor creates an instance-specific copy of this variable file for each virtual machine.
Injecting Configuration Data
Hypervisors pass custom data into this environment primarily through two methods:
- Pre-boot Image Modification: The virtualization
orchestrator reads the guest's template
VARSfile and writes custom key-value pairs directly into the binary structure before starting the VM process. Tools and libraries (such asvirt-fw-varsor python-based UEFI variable editors) parse the variable store format and insert custom entries. - Hypervisor Injection via Firmware Interfaces: Some
platforms support firmware communication channels (such as QEMU's
fw_cfginterface). The hypervisor passes raw configuration payloads over this synthetic bus, and a custom build of the UEFI firmware reads this data during early initialization, subsequently registering it as standard UEFI variables via internal firmware services.
Variable Structure: Namespaces and Attributes
UEFI variables do not rely on simple string names alone; they are scoped using a combination of a string name and a unique 128-bit Vendor GUID (Globally Unique Identifier). This design prevents namespace collisions between hardware vendors, operating systems, and hypervisor-specific metadata.
When creating a variable for guest consumption, the hypervisor assigns specific bitmask attributes:
EFI_VARIABLE_NON_VOLATILE(NV): Ensures the variable survives power cycles and reboots.EFI_VARIABLE_BOOTSERVICE_ACCESS(BS): Allows the UEFI firmware and bootloaders to access the data before the operating system kernel takes over.EFI_VARIABLE_RUNTIME_ACCESS(RT): Crucial for hypervisor-to-OS communication. This flag directs the UEFI firmware to map the variable into runtime memory that remains accessible after the kernel invokesExitBootServices().
Without EFI_VARIABLE_RUNTIME_ACCESS, the guest operating
system cannot read the custom configuration data once the kernel
initializes.
Retrieving Data in the Guest Operating System
Once the guest operating system boots, it queries the runtime services preserved by the firmware to retrieve the injected data.
Linux Environments
The Linux kernel exposes UEFI runtime services via the
efivarfs filesystem, typically mounted automatically at
/sys/firmware/efi/efivars/.
Variables appear as files formatted as
[VariableName]-[VendorGUID]. The first four bytes of each
file contain the 32-bit attribute mask, while the remaining bytes
contain the actual payload. Guest applications, such as custom bootstrap
scripts or provisioning agents, can read this payload directly:
# Example path for a custom hypervisor variable
cat /sys/firmware/efi/efivars/HypervisorConfig-12345678-1234-1234-1234-123456789abc | tail -c +5Linux tools such as efivar or efibootmgr
can also interact with these entries using standard system calls.
Windows Environments
Windows provides native Win32 APIs for interacting with firmware
environments. Applications running with administrator privileges
(SE_SYSTEM_ENVIRONMENT_NAME) invoke:
GetFirmwareEnvironmentVariableExW(): Retrieves the variable's value, GUID, and attribute flags.
Common Use Cases
Passing configuration through UEFI variables eliminates the need for
secondary synthetic devices, emulated CD-ROM drives (such as traditional
cloud-init ISO attachments), or early network dependency.
Common applications include:
- Supplying network configuration (static IPs, gateways) before network interfaces are brought online.
- Delivering cloud-init user-data and meta-data payloads.
- Passing cryptographically signed identity certificates or hardware tokens to prove VM identity to internal guest agents.