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 boot options are named variables stored in NVRAM — each Boot#### entry holds a human-readable description, a set of attributes, and a packed device path that tells the firmware exactly which EFI application to launch. This guide walks through every read-side operation provided by FirmwareBootService: enumerating all entries in boot order, reading a single entry by index, checking the current and next boot selection, and inspecting the device path protocols attached to each option.
All operations that read firmware variables require elevated privileges. On Windows, run your process as Administrator. On Linux, the calling user must have root access or the CAP_SYS_ADMIN capability so that the kernel’s efivarfs or GetFirmwareEnvironmentVariable syscall succeeds.

Enumerate all boot options

FirmwareBootService.EnumerateBootOptions() returns all boot entries in the order defined by the BootOrder variable. Each element is a FirmwareBootOption with a Description, an Attributes flags value, and a Protocols array containing the decoded device path.
using Unified.Firmware.BootService;
using Unified.Firmware.BootService.LoadOption;
using Unified.Firmware.BootService.Protocols;

int index = 0;
foreach (FirmwareBootOption bootOption in FirmwareBootService.EnumerateBootOptions())
{
    Console.WriteLine("\n===[ Boot option #{0} ]{1}", index++, new string('=', 60));
    Console.WriteLine("Option name : \"{0}\"", bootOption.Description);
    Console.WriteLine("Attributes  : {0}", bootOption.Attributes);

    // Print each device path protocol in order
    foreach (DevicePathProtocolBase protocol in bootOption.Protocols)
        Console.WriteLine(protocol.ToString());
}

Read a specific option by index

When you know the exact Boot#### index, call FirmwareBootService.ReadLoadOption(index) directly. The index is a ushort and can be written as a hexadecimal literal for readability.
using Unified.Firmware.BootService;
using Unified.Firmware.BootService.LoadOption;
using Unified.Firmware.BootService.Protocols;

// Read the Boot0003 variable
FirmwareBootOption bootOption = FirmwareBootService.ReadLoadOption(0x0003);

Console.WriteLine("Option name : \"{0}\"", bootOption.Description);
Console.WriteLine("Attributes  : {0}", bootOption.Attributes);

foreach (DevicePathProtocolBase protocol in bootOption.Protocols)
    Console.WriteLine(protocol.ToString());
The returned FirmwareBootOption is a fully deserialized in-memory object; modifying its properties does not automatically persist changes back to NVRAM.

Access the boot order

The BootOrder NVRAM variable holds the sequence in which the firmware tries each Boot#### entry. FirmwareBootService.LoadOrder exposes this as a BootOptionIndex[] array.
using Unified.Firmware.BootService;

BootOptionIndex[] order = FirmwareBootService.LoadOrder;

Console.WriteLine("Current boot order:");
for (int i = 0; i < order.Length; i++)
    Console.WriteLine("  [{0}] {1}", i, order[i]); // Prints e.g. "Boot0001"
BootOptionIndex implicitly converts to and from ushort and provides a ToString() that formats the value as Boot#### (four uppercase hex digits with leading zeroes).

Get the current boot option

FirmwareBootService.CurrentLoadOptionIndex reads the BootCurrent NVRAM variable, which the firmware sets before transferring control to the OS. Its value is the index of the entry that was actually used to boot.
using Unified.Firmware.BootService;

BootOptionIndex current = FirmwareBootService.CurrentLoadOptionIndex;
Console.WriteLine("Booted from: {0}", current); // e.g. Boot0001

FirmwareBootOption option = FirmwareBootService.ReadLoadOption(current);
Console.WriteLine("Description: {0}", option.Description);

Inspect device path protocols

Each FirmwareBootOption carries a Protocols array of DevicePathProtocolBase instances representing the UEFI device path nodes. Calling ToString() on each protocol produces a compact human-readable summary:
Protocol classToString() output
PciProtocolPci(0x{Device:X}, 0x{Function:X})
HardDriveProtocolThe GPT partition GUID as a string
FilePathProtocolThe EFI file path string, e.g. EFI\ubuntu\grubx64.efi
CdRomProtocolThe boot entry number as a string
using Unified.Firmware.BootService;
using Unified.Firmware.BootService.Protocols;

FirmwareBootOption bootOption = FirmwareBootService.ReadLoadOption(0x0001);

foreach (DevicePathProtocolBase protocol in bootOption.Protocols)
{
    Console.WriteLine("Type={0} SubType={1} => {2}",
        protocol.Type, protocol.SubType, protocol.ToString());

    // Inspect concrete type for structured access
    if (protocol is HardDriveProtocol hd)
        Console.WriteLine("  Partition GUID : {0}", hd.GptPartitionSignature);

    if (protocol is FilePathProtocol fp)
        Console.WriteLine("  File path : {0}", fp.PathName);
}

Read as a custom type

If you need to deserialize a boot entry into your own strongly-typed model, derive a class from LoadOptionBase and call the generic overload:
using Unified.Firmware.BootService;
using Unified.Firmware.BootService.LoadOption;

// T must inherit LoadOptionBase and have a public parameterless constructor
MyBootOption option = FirmwareBootService.ReadLoadOption<MyBootOption>(0x0002);
See the LoadOptionBase API reference for the full contract your subclass must satisfy.
Wrap firmware read calls in a try/catch for FirmwareEnvironmentException. This exception is thrown when the underlying platform call fails — for example when the variable does not exist, when the buffer is too small, or when the process does not hold the necessary privilege. Catching it lets you distinguish a missing entry from a permission error.

Build docs developers (and LLMs) love