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.

Creating a UEFI boot entry means serializing a device path — the chain of protocol nodes that describes where your EFI application lives — along with a human-readable label and attribute flags, then writing the result into a free Boot#### NVRAM variable and registering its index in the BootOrder list. This guide walks through each part of that process using FirmwareBootService.CreateLoadOption.
NVRAM writes are immediately persistent in hardware. A malformed or conflicting boot entry can make a system unbootable in edge cases. Test on a virtual machine first, or keep recovery media (live USB, Windows Recovery Environment) available before writing boot entries to a physical machine.
1

Choose your device path protocols

The Protocols array on a FirmwareBootOption encodes the UEFI device path. Each node narrows the location of the bootloader further — typically you need at least a partition node and a file path node.HardDriveProtocol identifies a GPT partition by its unique partition GUID. Pass the partition’s GUID directly, and the library queries the OS for the matching partition geometry:
using Unified.Firmware.BootService.Protocols;

// Identify the partition by its GPT partition GUID
var hardDrive = new HardDriveProtocol(new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));
FilePathProtocol provides the path to the EFI executable within the partition, using backslashes as separators (the UEFI convention):
var filePath = new FilePathProtocol(@"EFI\MyApplication\bootx64.efi");
Assemble the two nodes into an array in order — partition first, then file path:
DevicePathProtocolBase[] protocols =
[
    new HardDriveProtocol(new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")),
    new FilePathProtocol(@"EFI\MyApplication\bootx64.efi"),
];
2

Create a FirmwareBootOption

Construct a FirmwareBootOption using the four-argument constructor. Pass the desired attributes, a display name, the protocols array, and an optional data byte array (use Array.Empty<byte>() if you have no data to pass to the loaded image):
using Unified.Firmware.BootService.LoadOption;

FirmwareBootOption bootOption = new FirmwareBootOption(
    LoadOptionAttributes.ACTIVE,     // Mark entry as active so the firmware boots it
    "MyLoader",                      // Human-readable label shown in firmware UI
    protocols,                       // Device path from Step 1
    Array.Empty<byte>()              // No optional data
);
3

Write to NVRAM

Call FirmwareBootService.CreateLoadOption to find the first free Boot#### slot, write the serialized entry, and insert its index into BootOrder. Pass AddFirst: true to prepend the new entry to the top of the boot order:
using Unified.Firmware.BootService;

BootOptionIndex newIndex = FirmwareBootService.CreateLoadOption(bootOption, AddFirst: true);

Console.WriteLine("Boot option created at index: {0}", newIndex); // e.g. Boot0005
If no free slot is found (all 65 535 indices are occupied), a FreeLoadOptionIndexNotFound exception is thrown.
4

Verify the result

Read the entry back to confirm it was written correctly:
FirmwareBootOption saved = FirmwareBootService.ReadLoadOption(newIndex);
Console.WriteLine("Verified description: {0}", saved.Description);
Console.WriteLine("Verified attributes : {0}", saved.Attributes);

Full example

using System;
using Unified.Firmware.BootService;
using Unified.Firmware.BootService.LoadOption;
using Unified.Firmware.BootService.Protocols;

// 1. Build the device path
DevicePathProtocolBase[] protocols =
[
    new HardDriveProtocol(new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")),
    new FilePathProtocol(@"EFI\MyApplication\bootx64.efi"),
];

// 2. Create the option object
FirmwareBootOption bootOption = new FirmwareBootOption(
    LoadOptionAttributes.ACTIVE,
    "MyLoader",
    protocols,
    Array.Empty<byte>()
);

// 3. Persist to NVRAM at the top of the boot order
BootOptionIndex newIndex = FirmwareBootService.CreateLoadOption(bootOption, AddFirst: true);
Console.WriteLine("Boot option successfully created, new option index: {0}", newIndex);

LoadOptionAttributes

LoadOptionAttributes is a [Flags] enum. The most common values are:
FlagValueDescription
ACTIVE0x00000001The firmware will attempt to boot this entry automatically. Entries without this flag are skipped during normal boot processing.
HIDDEN0x00000008The entry will not appear in the firmware’s boot menu, though it can still be selected programmatically.
CATEGORY_BOOT0x00000000Default category; the entry is part of normal OS boot processing. This is the zero value and is always present unless CATEGORY_APP is set.
CATEGORY_APP0x00000100Marks the entry as an EFI application (e.g. a diagnostic tool) rather than an OS loader. These entries are excluded from the normal boot sequence and are accessible only via hot key or explicit selection.
You can combine flags with the bitwise OR operator:
// Active OS entry, hidden from the menu
var attrs = LoadOptionAttributes.ACTIVE | LoadOptionAttributes.HIDDEN;

HardDriveProtocol constructors

Two constructors are available depending on what partition information you have at hand:
// Construct from the partition's unique GPT GUID — the recommended approach
var byGuid = new HardDriveProtocol(new Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"));

// Construct from a low-level PARTITION_INFORMATION_EX structure (advanced use)
// PARTITION_INFORMATION_EX partition = ...;
// var byPartition = new HardDriveProtocol(partition);
The GUID-based constructor calls into the OS to retrieve the full partition geometry (start LBA, size, partition format, and signature type) automatically. Only GPT partitions are supported; passing information describing an MBR or RAW partition throws InvalidDataException, and an empty GUID throws ArgumentException.

OptionalData

The OptionalData byte array is appended verbatim to the EFI_LOAD_OPTION structure and is passed as a pointer to the loaded EFI image. Most OS bootloaders ignore it, but some EFI applications use it to receive configuration parameters or device paths for chained loading. Pass Array.Empty<byte>() if you have no data to supply.

Build docs developers (and LLMs) love