Safeguard
Supply Chain Security•

Firmware Updates on Linux With fwupd and LVFS: How UEFI Capsules Work

fwupd reads the ESRT, fetches signed metadata and firmware from LVFS, stages a UEFI capsule on the ESP and the firmware flashes it on reboot. Here is how.

Safeguard Security Team
47 min read

On Linux, firmware updates run through fwupd, a system daemon, and the Linux Vendor Firmware Service (LVFS), where hardware vendors upload signed firmware. For system firmware, fwupd reads the EFI System Resource Table (ESRT), stages a UEFI capsule on the EFI System Partition and reboots, and the platform firmware verifies and writes it. Run fwupdmgr refresh, then fwupdmgr update.

This guide goes one level deeper than our explainers on why firmware below the OS goes unpatched and A/B slots versus single slot firmware updates. It covers the capsule format, the ESRT fields you can read from sysfs, the LVFS signing chain, the Host Security ID report, how docks, SSDs and touchpads ride the same tooling, how Windows does the same job, and how a fleet should record firmware versions.

Key takeaways

  • A UEFI capsule is a firmware payload with a standard header that the operating system hands to the platform firmware through the UpdateCapsule() runtime service, or drops in \EFI\UpdateCapsule on the EFI System Partition for "capsule on disk" delivery. The firmware, not the OS, verifies and writes the flash.
  • The ESRT is a UEFI configuration table that lists every firmware resource the platform can update by capsule: a GUID, a type, the current version, the lowest version it will accept, and the result of the last attempt. Linux exposes it under /sys/firmware/efi/esrt/.
  • fwupd is the daemon and fwupdmgr is its command line client. LVFS is the service that hosts vendor uploads and publishes signed metadata. fwupd only installs firmware signed by LVFS unless an administrator changes that.
  • LVFS signs both the metadata catalog and the payload in each cabinet archive, and locks each vendor account to the hardware vendor IDs it owns, so one vendor cannot ship firmware for another vendor's devices.
  • Many devices (docks, Thunderbolt controllers, NVMe drives, touchpads) are updated directly by fwupd plugins at runtime, with no capsule and often no reboot.
  • fwupdmgr security prints the Host Security ID (HSI) report: a level from HSI:0 to HSI:5 built from checks such as SPI flash write protection, Secure Boot state, rollback protection and DMA protection. No HSI:5 tests exist yet.
  • Windows uses the same capsule and ESRT mechanism but packages each firmware resource as a signed driver package targeted at a UEFI\RES_{GUID} hardware ID.
  • Fleets should collect fwupdmgr get-devices --json, the ESRT and the HSI report into asset inventory, mirror LVFS internally if needed, and use an approved firmware list to stage rollouts.

How the pieces fit together

Five layers take part in one update, and each is owned by a different party.

LayerWhat it isWho owns it
Firmware codeThe binary image for a BIOS, embedded controller, SSD, dock or touchpadSilicon vendors, independent BIOS vendors, original design manufacturers (ODMs), device makers (OEMs)
Cabinet archiveA .cab file holding the payload plus a .metainfo.xml descriptionThe OEM or ODM that uploads it
LVFSThe web service that checks, signs, stores and publishes firmware and metadataA vendor neutral LVFS team, according to the fwupd threat model
fwupdThe privileged daemon that matches devices to updates and performs themYour Linux distribution, which packages it
Clientfwupdmgr, a graphical software center, or a management tool talking to fwupd over D-BusYou, as the user or administrator

The fwupd threat model draws the flow in that order: silicon and BIOS vendors feed the ODM, the ODM feeds the OEM, the OEM uploads to LVFS, and LVFS publishes signed metadata and archives to users. The final check happens in the device or platform itself.

What is a UEFI capsule update?

A capsule is the UEFI specification's way for an operating system to pass a blob of data to the platform firmware so the firmware can act on it, usually across a reset. Firmware updates are the main use. The structure starts with a small header, EFI_CAPSULE_HEADER, which the open source EDK II reference implementation defines with four fields:

FieldSizePurpose
CapsuleGuid16 bytesIdentifies what the capsule is for. For a firmware update this is the ESRT FwClass GUID of the target resource, or the generic firmware management capsule GUID
HeaderSize4 bytesSize of the header, so the payload offset is known
Flags4 bytesBits 0 to 15 are private to the target; bits 16 and up are defined by the specification
CapsuleImageSize4 bytesSize of header plus payload

The defined flags matter because they decide how the capsule travels:

FlagValueMeaning
CAPSULE_FLAGS_PERSIST_ACROSS_RESET0x00010000Keep the capsule in memory across a warm reset so firmware can process it after reboot
CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE0x00020000After processing, place a pointer to the capsule in the system configuration table
CAPSULE_FLAGS_INITIATE_RESET0x00040000Ask the firmware to reset the system itself after the call

The OS calls two runtime services. QueryCapsuleCapabilities() asks whether the firmware can accept a given capsule, what maximum size it supports and what kind of reset is needed. UpdateCapsule() hands over an array of capsule headers plus a scatter gather list describing where the data sits in memory. Microsoft's firmware update platform guide lists both as required, citing UEFI specification 2.8 section 8.5.3.

Capsule in memory versus capsule on disk

There are two ways to get a capsule to the firmware.

  1. In memory. The OS calls UpdateCapsule() with the persist flag, and the platform keeps the data across a warm reset. Memory contents must survive the reset, and the "coalesce" step that reassembles a scattered capsule has been a source of firmware bugs. The fwupd UEFI capsule plugin notes that on some laptops only one capsule can be scheduled at a time because of problems with that coalesce operation.
  2. On disk. The OS writes the capsule file to \EFI\UpdateCapsule on the EFI System Partition (ESP) and sets the EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit (value 0x4) in the OsIndications variable. On the next boot the firmware looks in that directory on the ESP of the active boot option, processes the file and deletes it. The fwupd plugin documentation says capsule on disk is the preferred method when the firmware supports it, and that some firmware (it names U-Boot) cannot set variables at runtime but applies capsules found on disk anyway.

What fwupd actually does with a capsule

fwupd adds one more step. With the runtime method, it copies the capsule and a small EFI program, fwupdx64.efi from the fwupd-efi project, to the ESP, sets the BootNext variable to a boot entry for that program and asks you to reboot. On the next boot the program runs before the boot loader, calls UpdateCapsule() and resets. The LVFS introduction describes exactly this: the firmware is unpacked into the ESP, several UEFI variables are set, the system reboots, fwupd.efi runs before the boot loader and calls the UpdateCapsule runtime service.

Under Secure Boot, that program must be signed by a key the platform or shim trusts; distribution builds ship it signed and chainload it through shim. A third party boot loader can implement fwupd's capsule protocol and advertise it with a one byte EFI variable called BootloaderSupportsFwupd, in which case fwupd skips its own EFI binary.

The firmware management capsule format and its signature

Inside most modern system firmware capsules is the Firmware Management Protocol (FMP) layout. The EDK II header FmpCapsule.h defines an outer capsule header with counts of embedded drivers and payload items, then an image header per payload with an UpdateImageTypeId GUID, an image index, the image size and an UpdateHardwareInstance. Each image that requires authentication starts with an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure: a 64 bit MonotonicCount and an AuthInfo certificate whose type must be PKCS #7. The EDK II comment explains that the signature covers both the image and the monotonic count, which exists "to ensure freshness/no replay."

This is the most important point in the whole design: the platform firmware checks the vendor's signature on the capsule before it writes anything. LVFS and fwupd add transport security and provenance on top, but the last gate is the key the OEM provisioned in the firmware. That is also why NIST SP 800-147 (April 2011) recommends an authenticated update mechanism for system BIOS, where updates are signed and verified with a key the platform trusts.

What is the EFI System Resource Table (ESRT)?

The ESRT is a UEFI configuration table that the firmware publishes at boot, identified by the GUID b122a263-3661-4f68-9929-78f8b0d62180 in the EFI configuration table. Microsoft's ESRT definition and the EDK II SystemResourceTable.h header give the same layout: a 16 byte table header with the entry count, the maximum count and a format version (set to 1), followed by one 40 byte entry per firmware resource.

FieldBytesWhat it tells you
FwClass16GUID of the updatable component. The OS puts this GUID in the capsule header's CapsuleGuid
FwType40 unknown, 1 system firmware, 2 device firmware, 3 UEFI driver
FwVersion4Current version as a 32 bit unsigned number; larger means newer
LowestSupportedFwVersion4The oldest version this resource will accept, which is the rollback floor
CapsuleFlags4Private flags the OS must pass in bits 0 to 15 of the capsule header
LastAttemptVersion4The version of the last attempted update
LastAttemptStatus4Result of that attempt

Microsoft requires exactly one entry describing system firmware, and an entry for every device whose firmware is updated separately from system firmware. Its guidance on LowestSupportedFwVersion is blunt: if a version contains a security fix, the lowest supported version should equal that version, which stops anyone from installing an older vulnerable image through the capsule path.

Reading the ESRT on Linux

The kernel has exposed the ESRT read only in sysfs since early 2015 (the kernel ABI document is dated February 2015). This is safe to run on any UEFI machine:

# Is this a UEFI boot at all?
[ -d /sys/firmware/efi ] && echo "UEFI boot" || echo "Legacy BIOS boot"

# How many updatable firmware resources does the platform declare?
cat /sys/firmware/efi/esrt/fw_resource_count

# Dump every entry
for e in /sys/firmware/efi/esrt/entries/entry*; do
  echo "== $e"
  for f in fw_class fw_type fw_version lowest_supported_fw_version \
           capsule_flags last_attempt_version last_attempt_status; do
    printf '%-30s %s\n' "$f" "$(cat "$e/$f")"
  done
done

On a typical laptop you will see one entry with fw_type 1 (the system firmware) and often one or two with fw_type 2, such as an embedded controller or a Thunderbolt retimer that the OEM chose to update through the capsule path.

Last attempt status codes, and a documentation mismatch

CodeEDK II nameMicrosoft descriptionNTSTATUS Windows records
0LAST_ATTEMPT_STATUS_SUCCESSSuccessSTATUS_SUCCESS
1ERROR_UNSUCCESSFULUnsuccessfulSTATUS_UNSUCCESSFUL
2ERROR_INSUFFICIENT_RESOURCESInsufficient resourcesSTATUS_INSUFFICIENT_RESOURCES
3ERROR_INCORRECT_VERSIONIncorrect versionSTATUS_REVISION_MISMATCH
4ERROR_INVALID_FORMATInvalid image formatSTATUS_INVALID_IMAGE_FORMAT
5ERROR_AUTH_ERRORAuthentication errorSTATUS_ACCESS_DENIED
6ERROR_PWR_EVT_ACAC not connectedSTATUS_POWER_STATE_INVALID
7ERROR_PWR_EVT_BATTInsufficient batterySTATUS_INSUFFICIENT_POWER
8ERROR_UNSATISFIED_DEPENDENCIES(EDK II only in our sources)

EDK II also reserves 0x1000 to 0x3FFF for vendor specific failure codes. One caution: the Linux kernel's sysfs ABI document lists the codes shifted by one (it shows 1 as "insufficient resources" and stops at 6 for battery). The EDK II header and Microsoft's ESRT page agree with each other, so treat the table above as authoritative and the kernel document as out of date. A last_attempt_status of 5 after an update means the firmware rejected the signature, and 6 or 7 means it refused to flash for power reasons.

Worked example: turning a raw 32 bit version into something readable

The ESRT only holds a 32 bit number, and vendors pack it differently. The fwupd UEFI capsule plugin documents the formats in use. Take a raw value of 0x01020304 (16909060 in decimal):

Format name in fwupdRuleResult
quad0xAA.0xBB.0xCC.0xDD1.2.3.4
triplet0xAA.0xBB.0xCCCC1.2.772 (because 0x0304 is 772)
dell-bios0xBB.0xCC.0xDD2.3.4
dell-bios-msb0xAA.0xBB.0xCC1.2.3

That is why fwupdmgr get-devices can show a UEFI device as a bare number on a fresh install and then as 1.2.3.4 after fwupdmgr refresh: the daemon copies the version format from the downloaded metadata. For inventory, store the raw integer as well as the string, because the integer comparison is what the firmware uses.

How do fwupd and LVFS fit together, and who uploads firmware?

fwupd is a system activated daemon with a D-Bus interface. Unprivileged clients ask it what devices exist and what updates apply, and PolicyKit decides whether the caller may install. The fwupd threat model says the daemon should run privileged with no network access, user facing clients should not run as root, and files pass from client to daemon as open file descriptors rather than names. In practice the client downloads metadata and archives, then hands them to the daemon.

Inside the daemon, plugins discover devices and assign each one a device ID plus a set of GUIDs. The GUIDs in the metadata are what match a firmware file to a device. For capsule devices the GUID is the ESRT FwClass; fwupd also adds UEFI\RES_{GUID} instance IDs so the same identifiers work on Windows.

Who uploads, and who can publish

LVFS is free for vendors. Its documentation describes an OEM facing console behind a username and password with two factor authentication, and account roles that separate who can upload from who can publish:

LVFS roleWhat it can do
Unprivileged userUpload files to a private area
Read only analytics userSee download and report data for a vendor
Quality assurance userModify any firmware uploaded to that vendor
Trusted userMove firmware to testing or stable, and from testing to stable
ManagerAdd new users to the vendor
AdminControl user permissions

An ODM can build and upload firmware without deciding when it goes public. The fwupd threat model adds that vendor accounts are verified by website and email domain.

Remotes: private, embargo, testing, stable

Firmware moves through stages that LVFS calls remotes.

  1. Private. Visible only to the uploader and the vendor's QA users.
  2. Embargo. Included in a private metadata catalog that anyone in the vendor group can install locally with a vendor-embargo.conf file and a user token, for end to end testing on real hardware before release.
  3. Testing. Public, but only to users who opt in to pre-release firmware. LVFS says this is typically a few thousand users.
  4. Stable. Public to everyone with the default lvfs remote enabled.

LVFS warns that regenerating the testing and stable catalogs can take a few hours and that clients may take up to 24 hours to download the new catalog, with most vendors seeing a download spike the day after a release goes stable. Firmware with unresolved automated test failures cannot be pushed to testing or stable unless a QA user waives the failure.

Vendor ID locking

LVFS describes the vendor ID as its most powerful protection. An LVFS administrator, not the vendor, assigns each vendor account the hardware vendor IDs it owns, such as a USB vendor ID. Every firmware from that vendor carries a requirement on that ID, and fwupd checks it against the physical device before flashing. A careless or malicious LVFS user cannot ship an update for another company's hardware. Because the ESRT carries no ownership information, capsule devices are locked using the platform's DMI vendor string instead, for example DMI: followed by the system maker.

How are LVFS payloads signed and verified, and what metadata travels with them?

There are three signatures to keep apart, and confusing them is the most common misunderstanding about LVFS.

SignatureCreated byChecked byWhat it proves
LVFS metadata signatureLVFS, as a detached PKCS #7 signature in a .jcat file next to the catalogfwupd or the client on refreshThe list of releases, GUIDs, versions and checksums came from LVFS unchanged
LVFS archive signatureLVFS, as a detached PKCS #7 or GPG signature added when it repacks the .cabfwupd before installThe payload and metainfo inside the archive are the ones LVFS published
Device or capsule signatureThe OEM or silicon vendor, inside the payloadThe platform firmware or device itself during flashingThe image is genuine vendor code that this hardware is willing to run

The fwupd threat model lists these facts: signing of metadata and firmware uses PKCS #7; end users only trust the LVFS signing signatures by default; metadata contains SHA-1 and SHA-256 hashes of each firmware archive; and both the archive's internal metadata and the payload are signed. The daemon "will only install firmware archives signed by the LVFS unless modified," and the OnlyTrusted setting in fwupd.conf documents that behaviour with a plain warning not to set it to false on a production system.

The Jcat format comes from libjcat: a gzip compressed JSON catalog in which each item (for example firmware.bin and firmware.metainfo.xml) can carry PKCS #7, GPG or SHA-256 blobs. Its README describes it as equivalent in purpose to Windows catalog files.

When LVFS repacks an upload it keeps only the files it needs, signs the payload, and prefixes the stored file name with the hash of the upload so download locations are not predictable. Any Windows Update signatures in the archive are copied across, but LVFS notes that Linux clients do not verify the Windows catalog file.

What the metainfo file says

The .metainfo.xml file is a subset of the AppStream component format. LVFS's metadata documentation shows these elements, among others:

<component type="firmware">
  <id>com.example.laptop.firmware</id>
  <provides>
    <firmware type="flashed">84f40464-9272-4ef7-9399-cd95f12da696</firmware>
  </provides>
  <releases>
    <release urgency="high" version="3.0.2" date="2017-02-09" install_duration="120">
      <checksum filename="my-custom-name.bin" target="content"/>
      <issues>
        <issue type="cve">CVE-2016-12345</issue>
      </issues>
    </release>
  </releases>
  <requires>
    <id compare="ge" version="0.8.0">org.freedesktop.fwupd</id>
    <firmware compare="ge" version="0.1.2"/>
  </requires>
  <custom>
    <value key="LVFS::UpdateProtocol">org.uefi.capsule</value>
    <value key="LVFS::DeviceIntegrity">signed</value>
  </custom>
</component>

The parts that matter for security and operations:

  • provides/firmware lists the device GUIDs the update applies to.
  • release urgency and issues let a vendor record the CVEs and vendor advisories a release fixes. That makes LVFS metadata one of the few places where firmware fix data is machine readable, when vendors fill it in.
  • requires can demand a minimum fwupd version, a minimum current firmware version (so an update can require a bootloader or an intermediate release first), or specific hardware IDs.
  • LVFS::UpdateProtocol names the flashing protocol, such as org.uefi.capsule, org.nvmexpress or com.intel.thunderbolt.
  • LVFS::DeviceIntegrity says whether the device verifies payloads with strong cryptography (signed) or accepts modified images (unsigned). LVFS notes that "generic" protocols such as NVMe, ATA and DFU only transport the image and make no guarantee about signing, which is why this field exists.

Step by step: get-devices, refresh, get-updates, update and history

This walkthrough uses a current distribution package of fwupd. Upstream supports the 2.1 and 2.2 branches fully, keeps 2.0 and 1.9 for security fixes only, and lists 1.8 as end of life from 1 January 2026, according to the fwupd security policy. The latest tagged release on GitHub when we checked was 2.1.8, published 24 September 2026. If your distribution ships something older than 1.9, expect missing HSI checks and plugin fixes.

Before you flash anything. A firmware update writes non-volatile memory. Plug in AC power, keep the battery above the level the vendor requires, close virtual machines, and do not interrupt the reboot. If the disk is encrypted with a key sealed to the TPM, make sure you have the recovery key, because measurements of the new firmware will change and automatic unlock may fail once. Read our TPM PCR guide for why.

Step 1: install and check the daemon

# Debian or Ubuntu
sudo apt install fwupd
# Fedora
sudo dnf install fwupd

fwupdmgr --version
systemctl status fwupd --no-pager

Step 2: check the EFI System Partition before any capsule update

The capsule path writes to the ESP, so confirm which partition is mounted there and that it has room. fwupd autodetects the ESP when it is mounted at /boot/efi, /boot or /efi and UDisks is available; otherwise set EspLocation in /etc/fwupd/fwupd.conf. By default the plugin wants free space of at least twice the payload size.

findmnt -no SOURCE,TARGET,FSTYPE /boot/efi /efi /boot 2>/dev/null
df -h /boot/efi
lsblk -o NAME,PARTTYPENAME,FSTYPE,MOUNTPOINT

Check that the device shown is the vfat partition with the "EFI System" partition type on the disk you boot from. If more than one ESP exists (common on dual boot machines with two disks), firmware looks only at the one referenced by the active boot option.

Step 3: list devices

fwupdmgr get-devices
fwupdmgr get-devices --json > devices.json

Each device shows a name, a device ID (a long hexadecimal string), the current version, the vendor ID used for locking, GUIDs, flags such as updatable or needs-reboot, and the plugin that owns it. The man page notes that terminal output is not guaranteed to be stable between versions and recommends --json for anything you parse.

Step 4: refresh metadata

fwupdmgr get-remotes
fwupdmgr refresh

refresh downloads the latest catalog and its .jcat signature from each enabled remote. If the signature does not verify, the catalog is not used.

Step 5: see what applies

fwupdmgr get-updates
fwupdmgr get-releases <device-id>

get-updates shows releases newer than what is installed for each device, with release notes, urgency and any listed CVEs. get-releases shows every installable version for one device, older and newer, which is useful when you need to confirm a fix version before approving it.

Step 6: update

# Everything, one device at a time
fwupdmgr update

# Or one device only
fwupdmgr update <device-id>

For a USB, Thunderbolt or touchpad device the update usually runs immediately. For a capsule device fwupd stages the file, sets BootNext and tells you a reboot is required. fwupdmgr check-reboot-needed confirms whether anything is pending.

Step 7: reboot and read the result

sudo systemctl reboot
# after the machine is back
fwupdmgr get-results <device-id>
fwupdmgr get-history
cat /sys/firmware/efi/esrt/entries/entry0/last_attempt_status
cat /sys/firmware/efi/esrt/entries/entry0/fw_version

get-history reads fwupd's local history database and shows every update attempt, the old and new versions and whether it succeeded. On the capsule path, the ESRT fw_version and last_attempt_status give you an independent check of what the firmware itself recorded. You can share that result with the vendor with fwupdmgr report-history, which helps vendors see success rates; it is optional and the history stays local unless you send it.

Exit codes for scripts

fwupdmgr returns 0 on success, 1 on a generic failure, 2 when the command ran but had nothing to do (for example no updates), and 3 when a resource was not found. Treat 2 as success in automation.

What happens during the reboot

StepWhere it runsWhat happens
1fwupd daemonVerifies the LVFS signature on the archive, checks requires and the vendor ID, extracts the capsule
2fwupd daemonCopies the capsule and fwupdx64.efi to the ESP, or puts the capsule in \EFI\UpdateCapsule for capsule on disk
3fwupd daemonSets BootNext (runtime method) or the OsIndications file capsule bit (on disk method)
4Firmware, early bootBoots the fwupd EFI program through shim under Secure Boot, which calls UpdateCapsule(), or finds the file on the ESP directly
5FirmwareChecks the PKCS #7 signature and monotonic count against its provisioned key, and the version against LowestSupportedFwVersion
6FirmwareChecks power, writes the flash (often showing a progress screen), updates LastAttemptVersion and LastAttemptStatus
7FirmwareResets, sometimes more than once, and boots normally
8fwupd daemonReads the ESRT and records success or failure in history

What is the Host Security ID (HSI) report, and what does each level check?

HSI is a specification written by fwupd maintainers to turn platform firmware protections into a single level a non-specialist can compare. It is marked as still in active development. Run it with:

fwupdmgr security
fwupdmgr security --json > hsi.json

HSI only measures what the user can verify without extra hardware, extra software or turning off any protection, and it targets laptops and desktops. The specification suggests HSI:1 might be fine for home use, a company might require HSI:2 or above for work laptops, and journalists or security researchers would want HSI:3 and above.

LevelName in the specWhat it representsExample checks from the fwupd test list
HSI:0InsecureLittle or no detected protection, or a level 1 test failedDefault if tests cannot run
HSI:1CriticalBasic protections whose failure could allow firmware compromise without physical accessSPI flash BIOS Write Enable off, BIOS Lock Enable on, SMM BIOS write protect, read-only SPI descriptor, Intel ME not in manufacturing mode, no flash descriptor override, Intel debug interface (DCI) disabled, part is fused, TPM 2.0 present and no empty PCR, UEFI Secure Boot on, Platform Key is not a test key, BIOS capsule updates enabled in setup, supported CPU, AMD SMM locked down, AMD microcode signature fix applied
HSI:2RiskyIssues that are theoretical or hard to exploit; boot path protected from local attackersBoot Guard enabled and verified, AMD Platform Secure Boot, AMD SPI write protection, BIOS rollback protection, IOMMU DMA protection, PCR0 matches the event log, part debug locked
HSI:3ProtectedOut of band protection of firmware, perhaps with recoveryBoot Guard policy, pre-boot DMA protection, control flow enforcement available and used, suspend to idle instead of suspend to RAM, AMD SPI replay protection, early boot UEFI memory protections
HSI:4SecureEncryption and execution protections for firmwareSupervisor mode access prevention, DRAM memory encryption, AMD secure processor rollback protection
HSI:5Secure provenOut of band attestationNo tests implemented, so this level cannot be reached yet

A level is only awarded when every applicable test at that level and below passes. The result can carry a ! suffix for runtime problems that do not change the core level: Secure Boot turned off, a tainted kernel, the kernel not locked down, an unencrypted swap partition, or fwupd running with custom or modified plugins.

The specification calls HSI:1 a safe baseline and says that a machine below it should have its firmware settings adjusted, its maker contacted or be replaced. Since fwupd 1.8.4, fwupdmgr security prints specific recommendations for failures. fwupdmgr security-fix attempts to fix a specific failing attribute, and security-undo reverses that fix if it causes a regression.

Two HSI checks tie directly to this guide. "BIOS capsule updates" fails at HSI:1 when an OEM setup switch for capsule updates exists but is off, because Linux firmware updates may then fail silently. "BIOS firmware rollback protection" at HSI:2 checks whether the OEM's optional protection against installing older vulnerable firmware is on.

How are SSD, dock, Thunderbolt, touchpad and embedded controller firmware updated by the same path?

fwupd is one front end over many back ends. The cabinet format, LVFS signing, vendor ID locking and history are the same for every device, but the plugin that writes the bytes differs.

Device classfwupd protocol IDHow the bytes get thereWhen the new firmware runs
System firmware (BIOS)org.uefi.capsuleCapsule through UpdateCapsule() or on diskAfter the firmware processes it on reboot
Embedded controller in a laptopUsually org.uefi.capsule as an ESRT device entry; some docks and models use a vendor pluginCapsule, or I2C over HID for some dock controllersAfter reboot or after the dock resets
NVMe SSDorg.nvmexpressFirmware Image Download in 4 kB chunks, then Firmware CommitOn next reboot, according to the fwupd NVMe plugin
Thunderbolt controller or retimercom.intel.thunderboltWritten to the controller at runtimeUsually immediately; the controller may reset and re-enumerate attached devices. Some docks finish on unplug
Touchpad (RMI4 protocol)Plugin specificSwitches the device from HID mode to a programming mode where it stops working, writes, then resetsImmediately after the reset
USB dock with several chipsDock plugin plus Thunderbolt and display controller pluginsUSB HID for hubs, I2C over HID for the embedded controller, DisplayPort AUX or I2C for the display stream controllerWhen the dock resets
Server components behind a BMCorg.dmtf.redfishPushed to the baseboard management controller over the Redfish REST APIAs the BMC schedules it

NVMe in more detail

The fwupd NVMe plugin enumerates drives from the Identify Controller data, builds GUIDs such as NVME\VEN_1179&DEV_010F (and variants with the firmware version or a serial number suffix), sends the image in 4 kB chunks and activates it on next reboot. Underneath, the NVMe specification gives drives up to seven firmware slots; the nvme fw-commit documentation in nvme-cli describes commit actions that replace a slot, replace and activate on next reset, set a slot active, or activate immediately without reset. That slot model is a real A/B (or A/B/C) mechanism on many drives, which we return to below.

For an SSD, you can see the slots and the active one with nvme-cli:

sudo nvme list
sudo nvme fw-log /dev/nvme0

These commands only read. Do not run nvme fw-download or nvme fw-commit by hand on a drive fwupd manages; let one tool own the update.

Docks

A modern USB-C or Thunderbolt dock is several devices in one box. The fwupd dock plugin documentation lists USB hubs, a display stream controller, a Thunderbolt controller and an embedded controller as separately updatable parts, shown nested under the dock in fwupdmgr get-devices. The Thunderbolt plugin has a DelayedActivation option that stages an update and completes it later with fwupdmgr activate, for example at logout.

Touchpads

During an RMI4 touchpad update the touchpad stops working until it resets, so keep a USB mouse handy. Vendor locking uses the HID vendor ID.

How does Windows Update deliver UEFI firmware by comparison?

Windows uses the same capsule and ESRT foundations, packaged as Plug and Play drivers. Microsoft's implementation guide says system and device firmware updates for UEFI systems are deployed as driver packages, with an INF file and the firmware binary, even though nothing in them is an actual driver.

  1. At boot, Windows reads the ESRT and creates a device node for each firmware resource, with hardware ID UEFI\RES_{FwClass GUID} under the Firmware device class.
  2. The OEM builds a driver package whose INF targets that hardware ID, sets FirmwareId, FirmwareVersion and the payload file name in the registry, and enables PnpLockdown so the payload cannot be modified outside the PnP system.
  3. In production the package is submitted to Microsoft's Partner Center for signing, which produces the catalog file that vouches for the INF and payload. Microsoft requires each ESRT resource to ship in its own package so versions move independently.
  4. Windows Update offers the package to matching machines. When installed, PnP stages it and requests a reboot.
  5. After the reboot, the Windows OS loader calls UpdateCapsule() with the payload. The firmware verifies and flashes it.
  6. The result appears in the registry under HKLM\SYSTEM\CurrentControlSet\Control\FirmwareResources\{GUID} as LastAttemptStatus, mapped to NTSTATUS codes, and the hardware ID gains a &REV_ suffix with the new version.
TopicLinux with fwupd and LVFSWindows Update
DiscoveryESRT plus fwupd plugins for non-capsule devicesESRT device nodes for capsule resources; other device firmware via ordinary drivers
Package format.cab with .metainfo.xml and payloadDriver package: INF, payload and signed catalog
Who signs the distribution packageLVFS (PKCS #7 or GPG)Microsoft, through Partner Center
Who verifies the image before writingThe platform firmwareThe platform firmware
Hand off to firmwarefwupd EFI program or capsule on diskWindows OS loader
PeripheralsSupported at runtime by pluginsMicrosoft says UEFI should not be used to update removable peripherals because they may be absent at reboot
Staged rolloutEmbargo, testing and stable remotes; local approved firmware listsManaged by Microsoft and OEM targeting, plus enterprise update management
Statusfwupd history database and ESRTRegistry FirmwareResources key and ESRT

LVFS chose the cabinet format so one deliverable can go to both systems without either signature overwriting the other. On a dual boot machine, installing the same capsule from either OS updates the same flash.

What can go wrong, and how do A/B and rollback protections help?

A short dated timeline

DateEventSource
April 2011NIST SP 800-147, BIOS Protection Guidelines, sets out authenticated BIOS updates and protection of system flashNIST CSRC
February 2015Linux kernel documents read access to the ESRT under /sys/firmware/efi/esrt/kernel.org ABI document
May 2018NIST SP 800-193, Platform Firmware Resiliency Guidelines, adds detection and recovery to protectionNIST CSRC
9 May 2023Microsoft publishes guidance on preventing rollback to a vulnerable boot file version, in response to the BlackLotus boot kit (as reported by CISA)CISA
3 August 2023CISA publishes "A Call to Action: Bolster UEFI Cybersecurity Now", asking for SBOMs for UEFI components and reliable update pathsCISA
24 September 2026fwupd 2.1.8 releasedGitHub releases

Failure modes and what limits the damage

What goes wrongWhat you seeWhat helps
Power lost mid flashMachine does not POST, or boots to a recovery screenFirmware refuses to start on low battery (status 6 or 7); dual image or recovery flash on platforms that have it; NIST SP 800-193 recovery requirements
Capsule never appliedVersion unchanged, status 0 or a stale valueCheck the BIOS setup switch for capsule updates (HSI "BIOS capsule updates"), Boot Order Lock settings, and which ESP the firmware uses
Signature rejectedlast_attempt_status 5Usually a wrong image for this board or a test key; do not override, report it to the vendor
Version refusedlast_attempt_status 3You tried to go below LowestSupportedFwVersion, which is the rollback floor working as intended
ESP fullfwupd refuses to stageClean old kernels or unified kernel images from the ESP; fwupd wants roughly twice the payload size free
Secure Boot blocks the fwupd EFI programUpdate silently not attemptedUse the distribution's signed fwupd-efi chainloaded through shim; with your own keys, sign it yourself (see our Secure Boot own keys guide)
TPM sealed disk key does not unsealRecovery key prompt on first bootExpected when PCR0 changes; have the recovery key and reseal afterwards
Dock or Thunderbolt update interrupted by unplugDevice in "safe mode"fwupd gives a controller in safe mode a fixed TBT-safemode GUID, so a matching image can still be found; retry on AC power with the dock connected
SSD activates a bad imageDrive missing or read onlyDrives with several firmware slots can be set back to the previous slot; otherwise vendor recovery

What rollback protection actually does

Rollback protection stops an attacker (or an unlucky administrator) from installing an older, signed, but vulnerable image. A signature alone does not stop that, because old images were validly signed too. The firmware needs a version floor that only moves upward. In UEFI that floor is the ESRT LowestSupportedFwVersion plus whatever secure storage the platform uses to hold it; the FMP monotonic count blocks replay of a captured authenticated image. In HSI terms, the OEM's "BIOS firmware rollback protection" counts toward HSI:2, and the AMD secure processor's rollback protection counts toward HSI:4. CISA's 2023 paper is a reminder that rollback is not theoretical: it describes BlackLotus as able to roll a boot file back to a vulnerable version, which is a failure of the update distribution channel rather than of any single signature.

The trade off: a strict floor makes a bad release hard to undo, because the firmware refuses anything below it even through fwupdmgr downgrade. Test on a few machines first with an approved firmware list.

Where A/B fits

A/B means two copies of the firmware, so a failed write leaves the other copy intact and bootable. Our A/B versus single slot explainer covers the design. On PCs it shows up in three places: system firmware with a protected backup or recovery region that can restore the main image (NIST SP 800-193 calls this recovery and wants it to be automatic and authenticated); NVMe drives with multiple firmware slots; and some docks and controllers with dual banks that only switch after a successful write. fwupd cannot add A/B to hardware that lacks it, and the HSI specification describes HSI:3 as out of band protection of system firmware, perhaps including recovery.

NIST SP 800-193 frames the whole problem in three verbs: protect the firmware from unauthorized change, detect when it has changed, and recover to a known good state. Signed capsules and rollback floors are protection. HSI and PCR0 event log reconstruction are detection. Dual images and vendor recovery are recovery. A fleet needs all three.

How should a fleet track firmware versions as part of its asset inventory?

Firmware is software, and the same inventory rules apply: know every component, its version, where it came from and which fixes it is missing. CISA's 2023 call to action says system owners should be able to audit, manage and update UEFI components like any other software, including with a software bill of materials. CycloneDX already has a firmware component type and a device type for this.

What to collect from each Linux machine

DataCommandWhy
Every fwupd device, version, GUIDs, vendor ID, flagsfwupdmgr get-devices --jsonThe firmware component list
Raw ESRT entries/sys/firmware/efi/esrt/entries/*Integer versions and last attempt status, independent of fwupd
HSI level and failing attributesfwupdmgr security --jsonPosture, comparable across models
Pending and past updatesfwupdmgr get-history --json (or plain text)Evidence of patching
Hardware IDsfwupdmgr hwidsLets you mirror only the firmware your models need
System firmware stringcat /sys/class/dmi/id/bios_version /sys/class/dmi/id/bios_dateA quick cross check readable without fwupd

A minimal collector that writes one JSON document per host:

#!/usr/bin/env bash
set -euo pipefail
out="/var/tmp/firmware-inventory-$(hostname -s).json"
devices="$(fwupdmgr get-devices --json 2>/dev/null || echo '{}')"
security="$(fwupdmgr security --json 2>/dev/null || echo '{}')"
esrt="[]"
if [ -d /sys/firmware/efi/esrt/entries ]; then
  esrt="$(for e in /sys/firmware/efi/esrt/entries/entry*; do
    jq -n --arg class "$(cat "$e/fw_class")" \
          --arg type "$(cat "$e/fw_type")" \
          --arg ver "$(cat "$e/fw_version")" \
          --arg low "$(cat "$e/lowest_supported_fw_version")" \
          --arg st "$(cat "$e/last_attempt_status")" \
          '{fw_class:$class, fw_type:$type, fw_version:$ver, lowest_supported:$low, last_attempt_status:$st}'
  done | jq -s '.')"
fi
jq -n --arg host "$(hostname -f)" \
      --arg bios "$(cat /sys/class/dmi/id/bios_version 2>/dev/null)" \
      --argjson devices "$devices" --argjson security "$security" --argjson esrt "$esrt" \
      '{host:$host, bios_version:$bios, fwupd:$devices, hsi:$security, esrt:$esrt}' > "$out"
echo "wrote $out"

The JSON field names inside fwupd's output can change between releases, so map them in your inventory system rather than hard coding them in the collector.

Control what gets installed

  • Mirror LVFS. LVFS documents three options for networks that cannot or should not reach it directly: ship .cab files inside an immutable OS image and enable the vendor-directory remote; mirror the public archive (over 10,000 files, around 50 GB according to LVFS) with Pulp or the sync-pulp.py helper, filtered by hardware ID or vendor tag; or export a shared directory. Unauthenticated clients are limited to 1,000 downloads per IP address per day, so mirrors need an LVFS user token.
  • Point clients at the mirror. Disable the public remote with fwupdmgr disable-remote lvfs and add a file in /etc/fwupd/remotes.d/ with MetadataURI and FirmwareBaseURI set to your server.
  • Approve before you deploy. fwupdmgr set-approved-firmware takes a list of SHA-1 or SHA-256 checksums of .cab archives (or, from fwupd 1.7.1, a file of them). Clients ignore anything not on the list, so you can mirror everything and release in rings.
  • Use Best Known Configurations where vendors publish them. fwupdmgr sync installs all releases with a matching BKC tag, which helps keep a model fleet on one tested set.
  • Pin the daemon itself. fwupd and fwupd-efi are open source packages with their own vulnerabilities and fixes. Track their versions like any other package and keep them on a supported branch.

Link versions to fixes

Join the CVEs in LVFS issues metadata against each machine's reported version to get a firmware fix gap per host. Where vendors list no CVEs, fall back to urgency, release notes and vendor advisories.

Common mistakes

  • Treating the LVFS signature as the firmware's signature. LVFS proves where the archive came from. The device or platform checks the vendor's own signature when it flashes. Both matter, and an unsigned device integrity value means the device itself accepts modified images.
  • Turning off OnlyTrusted to make a local file install. Use fwupdmgr local-install with a vendor-signed archive instead, and never leave unsigned installs enabled on production machines.
  • Ignoring the setup switch for capsule updates. Some OEMs ship it off. The update then appears to succeed on Linux but never applies. HSI flags it.
  • Running out of ESP space. Many unified kernel images or old kernels on a small ESP leave no room for a capsule and its backup.
  • Forgetting TPM sealed keys. A firmware update changes PCR0. Have the recovery key ready and reseal afterwards.
  • Updating on battery or over a flaky dock. The firmware may refuse (status 6 or 7), or worse, a dock update may be interrupted.
  • Letting two tools own one device. Do not mix vendor flashing utilities, nvme fw-commit and fwupd on the same device.
  • Pulling stable releases straight to the whole fleet. Use an approved firmware list and rings, and check get-history results before widening.

FAQ

How do I update BIOS on Linux without Windows?

If your machine's maker publishes to LVFS, run fwupdmgr refresh, fwupdmgr get-updates and fwupdmgr update, then reboot. fwupd stages a UEFI capsule and the firmware applies it during the reboot. If nothing is offered, the maker may not publish to LVFS for that model; check its support site for a capsule file or a bootable updater.

Is fwupd safe to use?

By default fwupd installs only LVFS-signed archives and checks the vendor ID, and the firmware still verifies the vendor's own signature. The practical risks are power loss and firmware bugs, so follow the power and recovery key precautions.

What is LVFS?

The Linux Vendor Firmware Service is a free web service where hardware vendors upload firmware in cabinet archives. It checks, signs and publishes the firmware and a signed metadata catalog that fwupd downloads. LVFS says millions of devices are updated through it every month.

What does fwupdmgr refresh do?

It downloads the latest metadata catalog and its signature from each enabled remote, so get-updates knows what releases exist. It does not install anything.

Why does fwupdmgr say no updates available?

Either your firmware is current, the vendor does not publish that device to LVFS, the release is still in testing or embargo, metadata has not refreshed yet (clients can take up to 24 hours to see a new catalog), or a requires condition such as a minimum current version is not met. fwupdmgr get-releases <device-id> shows what LVFS knows about.

What is the ESRT in UEFI?

A firmware-published table listing each component updatable by capsule, with its GUID, type, current and lowest supported versions and last update result. On Linux, read it under /sys/firmware/efi/esrt/.

What HSI level should a work laptop have?

The HSI specification suggests a company might require HSI:2 or above for work laptops and calls HSI:1 a safe baseline. Treat a ! suffix (Secure Boot off, tainted kernel, unencrypted swap and similar) as something to fix regardless of level.

Can I downgrade firmware with fwupd?

fwupdmgr downgrade installs an older release if one is available and the firmware allows it. Many platforms set LowestSupportedFwVersion equal to the latest security release, so the firmware will reject older images with an "incorrect version" status. That is rollback protection working.

Does fwupd update SSD firmware?

Yes, for NVMe drives whose makers publish to LVFS. The NVMe plugin sends the image in 4 kB chunks and the drive activates it on next reboot. Drives that are not in LVFS still need the maker's tool.

Do I need to disable Secure Boot to update firmware on Linux?

No. Distribution builds ship a signed fwupd EFI program that is chainloaded through shim. If you enrolled your own Secure Boot keys, you must sign that program with your key, or use capsule on disk where the firmware supports it.

Where Safeguard fits, and where it does not

Safeguard does not update firmware, read the ESRT, generate hardware bills of materials, scan firmware images, manage devices or protect endpoints. Everything in this guide is done with fwupd, LVFS, nvme-cli and your firmware setup screens. The honest link is the software around the update path. fwupd, fwupd-efi, libjcat, shim, the kernel and the jq or Python tooling you write for inventory are open source components with their own vulnerabilities and fixed versions, and fwupd itself publishes supported and end of life branches. If you build OS images, golden images or the collector scripts above from a repository, Safeguard can scan that repository, the container image or an SBOM of it, show which projects carry a given component version and match versions against vulnerability data. It cannot tell you which firmware version a given laptop is running.

A machine that has just had its firmware updated usually gets its operating system packages and tools refreshed in the same maintenance window, and the build systems that produce those images pull open source dependencies every time they run. The fit with firmware itself is indirect, but the hygiene below applies to the software side of the same fleet.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

None of these demos touch firmware, capsules or LVFS. They show the software side of a fleet you are keeping current.

This is a real Safeguard CLI session: install, open the interactive terminal, ask it to fix a lodash CVE, and approve each command as it edits package.json and runs npm install and npm test, with nothing pushed. After a firmware maintenance window, the same flow is how you would rescan and fix the projects and tooling on a machine, approving every command yourself.

Click through it at your own pace, or open it full screen.

This demo sets up the Safeguard runner on your own machine, approves it with a device code, and runs a scan from the terminal. If you build golden OS images or keep your inventory collector in a repository, the same runner can scan that repository or an SBOM of the image, so the fwupd, shim, kernel and scripting dependency versions you ship are checked against vulnerability data.

Click through it at your own pace, or open it full screen.

Here Claude connects to the Safeguard MCP server with OAuth, and you choose which Safeguard tools Claude can use. That is useful when you want to ask, in plain language, which of your projects or images carry a given fwupd or boot component version, while keeping the assistant's access limited to the tools you picked.

Click through it at your own pace, or open it full screen.

To try it on your own projects, download Safeguard or read the CLI documentation. For the wider firmware picture, see whether AI agents can modify BIOS or UEFI firmware and what TUF protects in firmware update systems.

Quick check

The LVFS signature verified, but the capsule failed with last attempt status 5. What does that mean?

The LVFS signature only proves the archive came from LVFS unchanged. Status 5 is an authentication error raised by the platform firmware itself: the image's own PKCS #7 signature did not verify against the key provisioned in this machine, usually because the image is for a different board or was signed with a test key.

Why can an NVMe update and a dock update finish without a capsule or a firmware reboot?

They are not system firmware resources in the ESRT. fwupd plugins write them directly over the device's own protocol (NVMe firmware download and commit, USB HID, I2C over HID or Thunderbolt), and the device activates the new image on its own reset, on the next reboot or on unplug.

Sources

Last reviewed: 23 October 2026. fwupd options and HSI tests change between releases; check the fwupd and LVFS documentation for the version you run.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.