Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Rikitav/Unified.Firmware/llms.txt

Use this file to discover all available pages before exploring further.

UEFI firmware variables are small, named key-value records stored in NVRAM. Each variable belongs to a namespace identified by a vendor GUID, carries a set of attribute flags that control its lifetime and access, and holds a binary payload. The UEFI specification defines a set of globally-scoped variables (boot order, secure boot state, OS indications, and more) under the well-known GlobalVariable GUID. OEM vendors extend the same storage mechanism with their own GUIDs for platform-specific settings. The FirmwareEnvironment class and its pre-configured GlobalFirmwareEnvironment subclass give you typed, marshal-free access to all of these.

Using GlobalFirmwareEnvironment

FirmwareEnvironment.Global is a lazily initialised singleton of type GlobalFirmwareEnvironment. It is scoped to the standard UEFI global namespace (8BE4DF61-93CA-11D2-AA0D-00E098032B8C) and exposes commonly needed variables as strongly typed properties.

Reading Secure Boot state

SecureBoot is read-only — it is set by the firmware during boot and indicates whether Secure Boot enforcement is currently active:
using Unified.Firmware;

bool isSecure = FirmwareEnvironment.Global.SecureBoot;
Console.WriteLine("Secure Boot: {0}", isSecure ? "Enabled" : "Disabled");

Reading and writing the boot timeout

Timeout is the number of seconds the firmware waits before auto-selecting the first boot entry. It can be read and written:
using Unified.Firmware;

// Read the current timeout
ushort currentTimeout = FirmwareEnvironment.Global.Timeout;
Console.WriteLine("Boot timeout: {0}s", currentTimeout);

// Change to 5 seconds
FirmwareEnvironment.Global.Timeout = 5;

Reading the BootOrder array

BootOrder exposes the ushort[] array of ordered boot indices. For most boot-management scenarios, prefer FirmwareBootService.LoadOrder (which wraps this in BootOptionIndex[]), but the raw array is useful for diagnostics:
using Unified.Firmware;

ushort[] order = FirmwareEnvironment.Global.BootOrder;
Console.WriteLine("Boot order: {0}", string.Join(", ", order.Select(x => $"Boot{x:X4}")));

OsIndications — reading and writing

OsIndications allows the OS to signal requests to the firmware across the next reboot. The flag is a ulong-backed [Flags] enum:
using Unified.Firmware;

// Read which OsIndications the firmware supports
OsIndications supported = FirmwareEnvironment.Global.OsIndicationsSupported;
Console.WriteLine("Supports boot-to-UI: {0}", supported.HasFlag(OsIndications.BOOT_TO_FW_UI));

// Read current value
OsIndications current = FirmwareEnvironment.Global.OsIndications;
Console.WriteLine("Current OsIndications: {0}", current);

// Set the boot-to-firmware-UI bit
FirmwareEnvironment.Global.OsIndications |= OsIndications.BOOT_TO_FW_UI;

Trigger boot to firmware UI

FirmwareInterface.BootToUserInterface() is a convenience wrapper that checks capability support and sets the BOOT_TO_FW_UI bit in one call. The system will enter the firmware setup screen on the next reboot — the call does not restart the computer.
using Unified.Firmware;

try
{
    FirmwareInterface.BootToUserInterface();
    Console.WriteLine("The firmware UI will open on next reboot.");
}
catch (PlatformNotSupportedException ex)
{
    Console.Error.WriteLine("Not supported: {0}", ex.Message);
}

Custom vendor namespace

Instantiate FirmwareEnvironment directly with any GUID to access vendor-specific variables. The constructor takes a backend (use FirmwareInterface.CurrentBackend) and the target namespace GUID:
using System;
using Unified.Firmware;
using Unified.Firmware.EnvironmentVendor;

// Access Microsoft-namespace variables
var msEnv = new FirmwareEnvironment(
    FirmwareInterface.CurrentBackend,
    FirmwareVendors.MicrosoftVendor
);

// Read a string variable from that namespace
string? policy = msEnv.ReadStringVariable("CurrentPolicy", out VariableAttributes attrs);
Console.WriteLine("CurrentPolicy attrs: {0}", attrs);
Reading from or writing to the wrong vendor GUID will either return null / a default value (if the variable does not exist under that GUID) or corrupt an unrelated variable (if a different variable happens to share the same name in that namespace). Always verify you are using the correct GUID before writing. If a read returns null or default, the variable does not exist in that namespace rather than having been deleted from a different one.

FirmwareVendors — known namespace GUIDs

FirmwareVendors is a static class that collects well-known vendor GUIDs as Guid fields:
FieldGUIDDescription
GlobalVariable8BE4DF61-93CA-11D2-AA0D-00E098032B8CStandard UEFI global namespace. Stores BootOrder, BootNext, Timeout, SecureBoot, SetupMode, etc.
ImageSecurityDatabaseD719B2CB-3D3A-4596-A3BC-DAD00E67656FSecure Boot key databases (db, dbx, dbt).
HardwareErrorVariable414E6BDD-E47B-47CC-B244-BB610208F4EFWHEA hardware error records (HwErrRec####).
CapsuleReport39B68C46-F7FB-441B-B6D1-E15C1B773062Firmware update capsule result variables.
MicrosoftVendor77FA9ABD-0359-4D32-BD60-28F4E78F784BMicrosoft-specific variables such as CurrentPolicy, BitLocker state, early-boot telemetry.
LenovoVendorC020489E-6DB2-4EF2-9AA5-CA06FC11D36ALenovo / ThinkPad BIOS settings accessible via WMI-to-UEFI bridge.
DellVendor4BCFDDBD-65F0-4FC7-BF96-981FBB0EBFF4Dell-specific variables for keyboard backlight, power profiles, CBOM.
HpVendor577FA4AD-1A3E-4BCE-A268-3F173B00DBECHP SureStart, security settings, and hardware tokens.
AsusVendor20C731A8-79C0-4E80-AFDE-0C3DEB22CDAEASUS ROG / Prime memory timings, Aura LED, and overclocking profiles.
AppleVendor7C436110-AB2A-4BBB-A880-FE41995C9F82Apple Mac EFI variables such as StartupMute, Bluetooth peripheral pairings, and efi-boot-device.

VariableAttributes

Every firmware variable is stored with a bitmask of VariableAttributes that controls its lifetime and who can read or write it. The most common combination for OS-facing variables is NON_VOLATILE | BOOTSERVICE_ACCESS | RUNTIME_ACCESS.
FlagValueMeaning
NON_VOLATILE0x01Persists across power cycles. Omit for variables that only exist during a single boot session.
BOOTSERVICE_ACCESS0x02Readable and writable during EFI boot services (before ExitBootServices()). All standard variables carry this flag.
RUNTIME_ACCESS0x04Readable and writable at OS runtime after ExitBootServices(). Required for variables that the OS or applications need to access.
AUTHENTICATED_WRITE_ACCESS0x10Writes must be accompanied by a valid authentication descriptor. Used for Secure Boot key management.
See the VariableAttributes API reference for the full set of flags.

Reading a struct variable

FirmwareEnvironment.ReadVariable<T> marshals the raw bytes of an NVRAM variable into any unmanaged struct:
using Unified.Firmware;

// Read the raw Timeout value and inspect its attributes
ushort timeout = FirmwareEnvironment.Global.ReadVariable<ushort>("Timeout", out VariableAttributes attrs);
Console.WriteLine("Timeout: {0}s, Attributes: {1}", timeout, attrs);

Writing a string variable

FirmwareEnvironment.WriteStringVariable serialises a .NET string as a null-terminated UTF-16LE string (the encoding expected by UEFI):
using Unified.Firmware;

var env = new FirmwareEnvironment(
    FirmwareInterface.CurrentBackend,
    FirmwareVendors.GlobalVariable
);

env.WriteStringVariable(
    "PlatformLang",
    "en-US",
    VariableAttributes.NON_VOLATILE |
    VariableAttributes.BOOTSERVICE_ACCESS |
    VariableAttributes.RUNTIME_ACCESS
);
Wrap all FirmwareEnvironment calls in a try/catch for FirmwareEnvironmentException. This exception surfaces OS-level errors such as missing privileges, unsupported variable names, or hardware write failures. On Windows, the calling process must hold the SE_SYSTEM_ENVIRONMENT_NAME privilege; on Linux, root access is required. Catching FirmwareEnvironmentException separately from PlatformNotSupportedException lets you distinguish a privilege error from a system that does not support UEFI at all.

Build docs developers (and LLMs) love