How UEFI HII Forms Communicate with Variables

In Unified Extensible Firmware Interface (UEFI) development, Human Interface Infrastructure (HII) forms provide a visual setup interface, while underlying non-volatile (NVRAM) variables store the actual system configuration. This article explains how HII configuration forms bind to, extract from, and write back to underlying UEFI variables through Visual Forms Representation (VFR) definitions, Variable Stores, and the Config Routing architecture.

The Foundation: The Varstore Definition in VFR

Communication begins inside the Visual Forms Representation (VFR) file. Before any visual element (such as a checkbox, numeric field, or dropdown) can store or retrieve data, developers declare a storage mechanism known as a Variable Store.

There are two primary types of variable stores used for UEFI variable interaction:

  • efivarstore: Explicitly maps to a standard UEFI variable backed by a GUID, variable name, and a C-style structure.
  • varstore: Defines an internal buffer or structure, which relies on driver-level protocols to bridge the data to physical storage.

A typical efivarstore declaration links an internal C structure directly to the UEFI variable name and vendor GUID:

efivarstore MY_CONFIG_DATA,
    attribute = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    name  = MyConfigVar,
    guid  = MY_CONFIG_GUID;

Element-Level Data Binding

Individual form elements within the VFR script specify which field of the structure they represent. Using the varid keyword (or direct member referencing), an input control binds directly to an offset within the declared efivarstore.

For example:

checkbox varid = MyConfigVar.EnableFeature,
    prompt   = STRING_TOKEN(STR_ENABLE_FEATURE),
    help     = STRING_TOKEN(STR_ENABLE_FEATURE_HELP),
    flags    = 0,
    key      = QUESTION_ID_ENABLE_FEATURE,
endcheckbox;

The VFR compiler translates this into internal IFR (Internal Forms Representation) binary opcodes containing the variable GUID, variable name, and the specific byte offset and size corresponding to the struct field.

The Underlying Protocols

Two core protocols govern the communication pipeline between the rendered form and the underlying variable:

  1. EFI_HII_CONFIG_ROUTING_PROTOCOL: A central service provided by the UEFI HII framework. It handles the translation, routing, and packaging of configuration data requests between the setup browser and configuration drivers.
  2. EFI_HII_CONFIG_ACCESS_PROTOCOL: A driver-specific protocol produced by the driver that owns the form. It implements callback functions required to handle variable data queries and submissions.

The Read Path: Extracting Data into Forms

When the UEFI Setup Browser renders a configuration page, it must populate form fields with active configuration data:

  1. Browser Request: The browser queries the EFI_HII_CONFIG_ROUTING_PROTOCOL to obtain the current values for the form's questions.
  2. Calling ExtractConfig(): The routing service routes the request to the owning driver’s EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig() function, passing a configuration request string.
  3. Variable Retrieval: Inside ExtractConfig(), the driver calls the UEFI runtime service gRT->GetVariable() to read the serialized structure from NVRAM.
  4. Payload Generation: The driver copies the variable data into a Configuration Response string (or standard binary block) and returns it to the routing engine.
  5. Display: The browser parses the retrieved bytes according to the element's offset and renders the current values on screen.

The Write Path: Committing User Changes

When a user modifies a setting and saves changes (or exits the setup utility):

  1. Browser Submission: The browser constructs a Configuration Request string containing the altered byte offsets and values, then delivers it to the routing protocol.
  2. Calling RouteConfig(): The routing engine invokes the driver’s EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig() callback function.
  3. Data Deserialization: The driver validates the incoming configuration string and updates its local copy of the configuration structure.
  4. Hardware or Variable Persistence: The driver calls gRT->SetVariable() to write the updated data structure back to NVRAM, using the appropriate vendor GUID, variable name, and persistence attributes.

Default Handling via Browser Fallback

If a driver does not implement custom logic in EFI_HII_CONFIG_ACCESS_PROTOCOL, or if the form relies directly on standard standard-compliant variables, the Setup Browser can use the routing protocol's default handling. In this mode, the routing service directly invokes gRT->GetVariable() and gRT->SetVariable() to satisfy the offsets specified by the form's efivarstore definition without driver intervention.