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:

  1. The Code Image (OVMF_CODE.fd): Contains the read-only executable UEFI firmware.
  2. 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 VARS file and writes custom key-value pairs directly into the binary structure before starting the VM process. Tools and libraries (such as virt-fw-vars or 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_cfg interface). 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 invokes ExitBootServices().

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 +5

Linux 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.