Safeguard
Supply Chain Security•

PCI Option ROMs Explained: UEFI Drivers on Cards and Secure Boot

A PCI option ROM is driver code on a GPU, NIC or storage card that firmware runs before the OS. Learn how Secure Boot verifies it and how PCRs record it.

Safeguard Security Team
47 min read

A PCI option ROM is a small block of driver code stored on an add-in card, such as a graphics card, network adapter or RAID controller, that the system firmware loads and runs on the main CPU before the operating system starts. On UEFI systems those drivers are PE/COFF images that Secure Boot checks against the db and dbx databases before they run, and that the firmware measures into TPM PCR 2.

That is the short answer. The rest of this guide goes one level below our posts on Secure Boot with your own keys, what each TPM PCR measures and the 2026 Secure Boot certificate rotation. Here we read the UEFI Specification 2.10 chapters on PCI option ROMs and image verification, Microsoft's Secure Boot key guidance and certificate expiry notice, NIST SP 800-147B, the NSA's UEFI Secure Boot customization report, the Linux kernel's PCI code and documentation, and the EDK II reference firmware source. Where firmware behaviour depends on the board vendor, we say so.

Key takeaways

  • An option ROM is code, not configuration. It runs on the host CPU with firmware privileges, before any operating system security control exists. NIST SP 800-147B describes option ROMs as "BIOS" found on "hard drive controllers, video cards, network cards and other add-in cards".
  • A single card ROM can hold several images: a legacy x86 BIOS image, one or more UEFI drivers for different CPU architectures, and more. The UEFI spec caps a PCI option ROM at 16 MiB and requires each image to start on a 512 byte boundary.
  • On UEFI firmware, the PCI bus driver copies the ROM into memory, finds images with code type 0x03 and signature 0x0EF1, and passes each UEFI driver to LoadImage(). That is where Secure Boot verification happens: the image must match db and must not match dbx.
  • Microsoft's 2011 third-party CA signed both Linux bootloaders and third-party option ROMs. Its 2023 replacement is split in two: Microsoft UEFI CA 2023 for bootloaders and applications, and Microsoft Option ROM UEFI CA 2023 for option ROMs. The 2011 CA expires on 27 June 2026.
  • In the TCG measurement scheme, PCR 2 holds option ROM code and PCR 3 holds option ROM data and configuration. Swapping a GPU or flashing a NIC changes PCR 2, which matters for any disk encryption policy that seals to it.
  • Option ROMs were the entry point for the 2014 Thunderstrike research on Macs, which led to not loading option ROMs during firmware updates.
  • On Linux you can read a card's ROM through sysfs, parse and hash it, and compare it with the TPM event log.

What is an option ROM, and why do GPUs, NICs and storage controllers carry one?

The one paragraph definition

When a computer powers on, its motherboard firmware knows how to drive the hardware it was built with. It does not know how to drive a graphics card that was designed three years later, a 100 gigabit network adapter that can boot from the network, or a RAID controller that presents a logical disk made of eight physical drives. The add-in card solves this by carrying its own driver in a small flash or EEPROM chip. During boot the firmware finds that code, copies it into memory and runs it, and from that point the firmware can draw on the card's display, boot over its network port or read the RAID volume. That driver is the option ROM. The PCI specifications call it the expansion ROM.

Where the idea came from

The concept predates PCI by more than a decade. Trammell Hudson's Thunderstrike FAQ puts it neatly: the original IBM PC had six option ROM sockets, and "at boot time, the BIOS would see if there were any chips installed and execute startup code from them". ISA adapter cards then carried expansion ROMs to initialize themselves, and the feature carried through to PCI and PCI Express. Our post on bus evolution from ISA to PCIe 7 and CXL covers the electrical side of that history.

Why each card type needs one

Card typeWhat its option ROM typically provides before the OSWhat you lose without it
Graphics cardA display driver so firmware setup screens, boot menus and the OS loader have a screenNo picture until the OS loads its own driver, if the board has no other display
Network adapterNetwork boot (PXE or HTTP boot), sometimes iSCSI boot, plus a configuration menuNo network boot from that port; no pre-OS configuration screen
RAID or HBA controllerA driver that exposes logical volumes as bootable disks, plus a setup utilityThe OS cannot boot from a volume behind that controller
NVMe add-in card (older boards)An NVMe driver for boards whose firmware predates NVMeThe drive is visible in the OS but not bootable
Thunderbolt and external PCIe devicesWhatever the attached device's ROM providesUsually nothing important, which is why external ROMs are often blocked

These are common patterns, not guarantees; many motherboards carry their own NVMe and network drivers, so the card's ROM is never needed.

Option ROM versus device firmware

NIST SP 800-147B draws a line that is easy to blur. Option ROMs are loaded by the system firmware and "executed on the host CPU". Device firmware is different: many devices contain their own microcontrollers that run their own firmware on the card. A network adapter can therefore carry two kinds of code: firmware for its on-card processor, and an option ROM that runs on your server's CPU. Both can be updated by the same vendor tool, and both matter, but only the option ROM runs inside your platform's boot chain. NIST also notes that its guidelines cover option ROMs stored with the system BIOS and updated by the same mechanism, but "do not apply to Option ROMs and other device firmware stored elsewhere in a server, such as on an add-on card." That gap is one reason card ROMs get less attention than the motherboard firmware.

Where the bytes live on the bus

Every PCI function's configuration space has an Expansion ROM Base Address Register. The Linux kernel's pci_regs.h defines it at offset 0x30 for normal devices (header type 0) and at 0x38 for bridges, with "bits 31..11" holding the address and bit 0 the enable bit. Firmware sizes the ROM by writing to that register, assigns it an address, enables decoding, reads the image, and then usually disables decoding again. That is why Linux tools often show a card's expansion ROM as present but disabled once the OS is running.

How did legacy BIOS option ROMs work, and how do UEFI driver option ROMs differ?

The legacy model

A legacy option ROM image begins with the two byte signature 0x55 0xAA. A 16 bit pointer at offset 0x18 leads to the PCI Data Structure, which starts with the ASCII signature PCIR and records the vendor and device IDs, the image length in 512 byte units, a code type and an indicator byte whose top bit marks the last image in the ROM. The Linux kernel's drivers/pci/rom.c walks exactly these fields: it checks 0xAA55, follows the pointer at 0x18, checks PCIR, reads the length at offset 0x10 of the data structure and stops when bit 7 of the indicator at 0x15 is set.

On a legacy BIOS, the firmware typically copied each x86 image into memory below 1 MiB and ran its initialization code in 16 bit real mode. The ROM then installed itself into the BIOS's video, disk or boot services, so that from the BIOS's point of view the new card simply worked. Video ROMs were special because they lived at a fixed, well known address. The Linux kernel still reflects this: for the boot display device it reserves a 128 KiB window starting at 0xC0000 as the shadowed video ROM and logs "Video device with shadowed ROM at" that range. The message records the kernel's assumption about that legacy window, so it appears on many UEFI machines too and is not proof that a legacy ROM ran.

Three properties of this design matter for security:

  1. No authentication. A legacy BIOS ran whatever image it found with a valid header. There was no signature format to check.
  2. Full privilege. The code ran on the main CPU with no isolation, with access to all memory and devices.
  3. No record. Unless the firmware implemented TCG measurement, nothing recorded which ROM code ran.

The UEFI model

UEFI keeps the container and changes what goes in it. The UEFI Specification 2.10, section 14.4, sets the rules for a PCI option ROM:

  • It "can be no larger than 16 MiB".
  • It "may contain one or more images", each starting on a 512 byte boundary and padded to a multiple of 512 bytes.
  • Each image must have a PCIR data structure in its first 64 KiB.
  • A UEFI image must be "a PE/COFF image or a compressed PE/COFF image following the UEFI Compression Algorithm".
  • If a legacy image is present, "it must be the first image", and images are placed in order "from highest to lowest priority".

The EFI image header that follows the 0x55 0xAA signature differs from the legacy one. The spec's EFI PCI Expansion ROM Header table defines these fields:

OffsetFieldMeaning
0x00ROM signature0x55, 0xAA
0x02Initialization SizeImage size in 512 byte units, including this header
0x04EFI signature0x0EF1
0x08SubsystemPE/COFF subsystem: 11 for a boot service driver, 12 for a runtime driver
0x0AMachine typeThe CPU architecture the driver is built for
0x0CCompression type0 uncompressed, 1 compressed with the UEFI algorithm
0x16Offset to EFI imageWhere the PE/COFF image starts
0x18Offset to PCIRSame pointer as in a legacy image

The spec also lists the code types in the PCIR structure: 0x00 for IA-32 PC-AT compatible (legacy), 0x01 for Open Firmware, 0x02 for PA-RISC and 0x03 for an EFI image.

How the firmware finds and loads a UEFI option ROM driver

Section 14.4.22 of the spec describes the PCI bus driver's job in a few steps:

  1. During PCI enumeration, if a card has an option ROM, the bus driver copies it into a memory buffer.
  2. It searches the images for code type 0x03 in PCIR and signature 0xEF1 in the EFI header.
  3. It checks the subsystem. Only boot service drivers (11) and runtime drivers (12) are loaded. The spec notes that UEFI applications in an option ROM are ignored by the bus driver.
  4. It decompresses the image if needed and calls LoadImage(). "All UEFI driver images discovered in the PCI Option ROM and meeting these requirements must be processed and loaded via LoadImage()". A driver for an unsupported machine type simply fails to load, which is how one ROM can carry x64 and AArch64 drivers side by side.
  5. It gives each image a device path made of the PCI controller's path followed by an offset range node, for example PciRoot(0)/PCI(5,0)/PCI(7,0)/Offset(0x8000,0x9FFF). You will see paths like this in firmware logs and in the TPM event log.
  6. It publishes the drivers in ROM order through the Bus Specific Driver Override Protocol, so the card vendor controls which driver binds first.

The spec lists the common layouts a card might ship: legacy only, a single UEFI driver for one architecture, legacy plus x64, legacy plus x64 plus AArch64, x64 plus AArch64, and even an EFI Byte Code driver that runs through an interpreter on any architecture. Firmware "must work with all of these".

Legacy and UEFI option ROMs compared

PropertyLegacy BIOS option ROMUEFI driver option ROM
Code formatRaw x86 real mode codePE/COFF image, optionally compressed
PCIR code type0x000x03
ExecutionCalled by BIOS, hooks BIOS servicesLoaded by LoadImage(), binds through the UEFI driver model
Architecturesx86 onlyOne image per architecture, several in one ROM
Signature checkNone definedAuthenticode style signature checked against db and dbx when Secure Boot is on
Measured into TPMOnly if the BIOS implemented TCG measurementEDK II measures each driver into PCR 2 as a boot or runtime services driver event
Needs CSM on UEFI systemsYesNo
Typical setting name"Legacy", "Legacy OROM", "CSM""UEFI", "UEFI only"

The last two rows explain most real world option ROM settings. A UEFI system can still run a legacy image, but only through the Compatibility Support Module, the firmware layer that emulates a legacy BIOS. When CSM is off, the firmware ignores legacy images and uses only the UEFI drivers. The NSA's 2020 guidance recommends exactly that: machines "running legacy BIOS or Compatibility Support Module (CSM) should be migrated to UEFI native mode", and its suggested settings table lists legacy option ROMs as "Disable unless required by expansion devices (video card, storage controller, etc.)".

How does UEFI Secure Boot verify option ROMs (db, dbx), and what is the 2011 versus 2023 CA question?

The verification rule

Secure Boot does not have a separate procedure for option ROMs. Because the PCI bus driver loads each UEFI driver through LoadImage(), the same image verification applies to an option ROM as to a bootloader. Microsoft's Secure Boot overview lists the modules covered: "UEFI firmware drivers (such as Option ROMs), boot loaders, and applications."

The UEFI Specification 2.10, section 32.6.3.3, states the rule. The db "must either contain an entry with a hash value of the image (with a supported hash type), or it must contain an entry with a certificate against which an entry in the image's certificate table can be verified." In either case, verification must fail if dbx contains the SHA-256 hash of the binary, or a certificate hash or certificate that matches any certificate in the signing chain. The spec adds that "multiple signatures are allowed to exist in the binary's certificate table" and only one needs to be trusted, "so long as neither the hash of the binary nor any present signature is reflected in dbx." That clause is what lets a card vendor dual sign a ROM for old and new certificates.

Microsoft's key management guidance for OEMs says the same thing in plainer words: "In all cases a UEFI driver (Option ROM) shall not execute if it is not trusted in the db." It also explains the one exception: drivers built into the system firmware image "do not need to be re-verified", because being part of the signed system image is assurance enough. Only drivers loaded from outside that image, such as card ROMs, are checked against db.

What firmware does when a ROM fails

The spec allows a firmware to approve images "for other reasons than those specified here", for example whether the image is in system flash or "whether the device providing the UEFI image is secured (in a case, etc.)". It also defines an Image Execution Information Table, where firmware records images it refused or deferred, with a Name field that for "a UEFI device driver (for option ROM, for example)" holds the device's name. An operating system can read that table to see which ROMs did not run.

EDK II, the open source reference implementation of UEFI, makes the policy a build time setting. In SecurityPkg.dec, PcdOptionRomImageVerificationPolicy defaults to 0x04, "Deny execution when there is security violation". The same file lists the other values: 0x00 always trust, 0x01 never trust, 0x03 defer, and two values (0x02 allow on violation and 0x05 query user) that it says must not be used because they violate the UEFI specification. Whether your board shipped with the default is up to the firmware vendor, which is why testing matters more than reading a datasheet.

The 2011 CA and why a GPU depends on it

For a decade, almost every signed third-party UEFI driver on a PC was signed through Microsoft's third-party CA. The NSA's report describes the split well: the Windows Production CA signs Windows components, while the third-party CA "signs content not related to Windows such as storage controller firmware, graphics card firmware, UEFI driver modules, and Linux bootloaders." In other words, the same certificate that lets a Linux shim boot also lets a graphics card's UEFI driver run.

That coupling caused two practical problems. Organizations that wanted to stop third-party bootloaders from running had to remove a CA that their graphics and storage cards also depended on. And Microsoft's own Secured-core PC requirements now ask that the "3rd party UEFI CA" is "not trusted by default, with BIOS option for enabling trust", which on a machine with a discrete GPU can leave the card without a trusted driver until the setting is changed.

What changes with the 2023 certificates

Microsoft's support article on Secure Boot certificate expiration (KB5062710, first published 26 June 2025 and last updated 18 May 2026) lists the replacements:

Expiring certificateExpiresReplacementStored inSigns
Microsoft Corporation KEK CA 201124 June 2026Microsoft Corporation KEK 2K CA 2023KEKUpdates to db and dbx
Microsoft Windows Production PCA 201119 October 2026Windows UEFI CA 2023dbThe Windows boot loader
Microsoft UEFI CA 201127 June 2026Microsoft UEFI CA 2023dbThird-party boot loaders and EFI applications
Microsoft UEFI CA 201127 June 2026Microsoft Option ROM UEFI CA 2023dbThird-party option ROMs

Microsoft explains the split directly: the two new certificates "separate boot loader signing from option ROM signing", so that "systems that need to trust option ROMs can add the Microsoft Option ROM UEFI CA 2023 without adding trust for third-party boot loaders." Microsoft's OEM guidance gives the certificate's SHA-1 thumbprint as 3FB39E2B8BD183BF9E4594E72183CA60AFCD4277 and describes two db configurations for new devices. The default for Windows 11 25H2 and later devices carries only the Windows UEFI CA 2023. The alternative, for devices "intended to support Linux, other 3rd party UEFI apps, or include special hardware requiring Option ROMs", adds the Microsoft UEFI CA 2023, the 2011 third-party CA and the Microsoft Option ROM UEFI CA 2023.

The practical question for third-party drivers

Put the db rule and the certificate table together and the question for any fleet becomes concrete:

  • A card whose ROM is signed only by the 2011 CA keeps working on any machine that still has the 2011 CA in db. Microsoft says devices without the new certificates "will continue to start and operate normally". What they lose is the ability to receive new boot level protections.
  • A card whose ROM is signed only by the Option ROM UEFI CA 2023 will verify only on machines whose db contains that 2023 certificate. On an older machine whose db was never updated, the driver fails verification, and with an EDK II style deny policy it does not run.
  • A card whose ROM carries both signatures works on both, because the spec needs only one trusted signature.
  • A machine whose db you replaced with your own keys trusts neither Microsoft CA unless you enrolled them. Its cards' UEFI drivers will fail unless you enrolled the Option ROM CA, the vendor's own certificate, or the SHA-256 hashes of the specific ROM images.

The last case is the one people hit when following a guide to Secure Boot with your own PK, KEK and db. The NSA report covers it: some systems can generate hashes of storage controllers and network interfaces, some vendors publish Secure Boot hashes of their expansion devices, and since "end users are usually not permitted to sign their own firmware images for expansion devices", hash capture and enrollment into db is the normal route. The NSA also suggests reserving db hashes for content "that cannot be signed or cannot be altered from the vendor-provided state", which describes card ROMs exactly.

Why are option ROMs a historical attack surface?

The structural reason

Every property of the legacy model listed earlier is also a property an attacker would want: code that runs before the operating system, on the main CPU, with no isolation, from storage the platform owner rarely inspects, on a part that moves between machines. Option ROMs also sit outside the protections that cover system firmware. NIST SP 800-147B describes the moment of handover: the system BIOS acts as the root of trust for update "prior to executing untrusted code (e.g., Option ROMs)". The guidance treats option ROMs as untrusted from the platform's point of view, which is the right model.

Thunderstrike, described conceptually

The best documented example is Trammell Hudson's Thunderstrike research, presented at the 31st Chaos Communication Congress (31C3) in December 2014. Thunderbolt brings PCI Express to an external port, so an external device can present an option ROM to the firmware at boot. Hudson's project page describes the core finding: a Thunderbolt option ROM could be used "to circumvent the cryptographic signature checks in Apple's EFI firmware update routines", which let someone with brief physical access write untrusted code to the motherboard's boot flash. Once there, that code ran from the first instruction, survived an OS reinstall and a disk replacement, and could in principle copy itself into other Thunderbolt devices' option ROMs.

The lesson is the trust gap, not the exploit: the firmware ran external option ROM code during the same boot in which it applied a signed update, so untrusted code ran while the boot flash was writable. Hudson notes the underlying option ROM weakness dated back two years, to a 2012 attack by a researcher known as snare.

The fixes and what they taught

Apple's fix, as quoted in Hudson's FAQ from security advisory APPLE-SA-2015-01-27-4 (OS X 10.10.2 and Security Update 2015-001), was described as: "This issue was addressed by not loading option ROMs during updates" (CVE-2014-4498). Hudson's assessment was that this stopped the proof of concept but left the 2012 option ROM attack working during normal boots, and that older machines remained exposed to downgrade.

The follow-up research, Thunderstrike 2, was presented at DEF CON 23 and Black Hat 2015 by Hudson with Xeno Kovah and Corey Kallenberg. It showed that firmware could be reached from software, not just from a device in a port. Hudson's page records that it was partially fixed in the Mac EFI Security Update 2015-001 in June 2015 (CVE-2015-3692, CERT/CC VU#577140), and lists remaining issues it disclosed, starting with "Option ROMs are still loaded during normal boots".

The FAQ also answers whether Secure Boot would have helped. Its answer is a useful summary of the limits: Secure Boot "does add signatures on Option ROMs, which would prevent a random Thunderbolt device from being able to inject untrusted code into the boot process", but signature checks in firmware cannot protect the firmware itself if an attacker can already write to the boot flash.

A dated timeline

DateEventSource
2011Microsoft's original Secure Boot certificates, all named for 2011 (KEK CA 2011, Windows Production PCA 2011, UEFI CA 2011), arrive with Windows 8, the first Windows release with Secure BootMicrosoft KB5062710
2012Option ROM based attack on Mac firmware by a researcher known as snareThunderstrike FAQ
August 2014NIST SP 800-147B, BIOS Protection Guidelines for Servers, defines option ROMs as host executed code distinct from device firmwareNIST
December 2014Thunderstrike presented at 31C3Thunderstrike page
27 January 2015OS X 10.10.2 stops loading option ROMs during firmware updates (CVE-2014-4498)Thunderstrike FAQ quoting the Apple advisory
June 2015Mac EFI Security Update 2015-001 partially fixes Thunderstrike 2 issues (CVE-2015-3692)Thunderstrike 2 page
2015Thunderstrike 2 presented at DEF CON 23 and Black Hat 2015Thunderstrike 2 page
September 2020NSA publishes UEFI Secure Boot Customization, recommending UEFI native mode and disabling legacy option ROMsNSA report
26 June 2025Microsoft publishes the Secure Boot certificate expiration notice, including the new Option ROM UEFI CA 2023Microsoft KB5062710
24 to 27 June 2026Microsoft KEK CA 2011 and third-party UEFI CA 2011 expireMicrosoft KB5062710
19 October 2026Microsoft Windows Production PCA 2011 expiresMicrosoft KB5062710

Thunderbolt and USB4 direct memory access risks are a related but separate topic, covered in our post on USB and Thunderbolt evolution and DMA attacks.

The lessons still apply: treat card and external ROMs as untrusted input, never run them while the platform is in a privileged state such as a firmware update, measure what ran, and keep an inventory of ROM hashes. For a practical approach to examining suspicious firmware without a large lab, see our post on analyzing UEFI malware without a big budget.

How do PCR 2 and PCR 3 record option ROMs, and what does that mean for BitLocker and disk encryption?

Which PCR gets what

The TCG PC Client Platform Firmware Profile assigns platform configuration registers by purpose. The Linux TPM PCR registry maintained by the UAPI Group summarizes the firmware PCRs: PCR 2 is "extended or pluggable executable code; includes option ROMs on pluggable hardware", and PCR 3 is "extended or pluggable firmware data; includes information about pluggable hardware". Microsoft's BitLocker documentation uses shorter labels for the same registers: PCR 2 "Option ROM code" and PCR 3 "Option ROM data and configuration".

EDK II shows how this happens in code. Its DxeTpm2MeasureBootLib measures every image loaded through the security architecture. For a boot service driver it writes an EV_EFI_BOOT_SERVICES_DRIVER event into PCR 2; for a runtime driver, an EV_EFI_RUNTIME_SERVICES_DRIVER event, also into PCR 2. UEFI applications, such as an OS loader, go to PCR 4. So every UEFI driver loaded from a card ROM produces a PCR 2 event whose digest is the hash of the PE image and whose device path ends in the Offset(...) node described earlier.

For a broader walk through all 24 registers, see our post on what each TPM 2.0 PCR measures.

What changes PCR 2

Anything that changes the set or the content of UEFI drivers loaded from outside the system firmware image:

  • Adding, removing or swapping a GPU, NIC, RAID controller or other card with a UEFI ROM.
  • Updating a card's option ROM, even to the same version string with a different build.
  • Moving a card to a different slot, if the firmware's load order or device path changes.
  • Changing a firmware setting that enables or disables option ROM execution for a slot.
  • Docking a laptop with an external PCIe device whose ROM is allowed to run.

Why BitLocker usually does not care, and when it does

Microsoft's BitLocker configuration documentation describes two default platform validation profiles on UEFI firmware.

  • When Secure Boot state (PCR 7) is available, which is the normal case on modern Windows devices, the default profile seals the key to PCR 7 and PCR 11 only. PCR 7 records the Secure Boot policy (whether it is on and the contents of PK, KEK, db and dbx), not the individual ROM digests. A card swap that changes PCR 2 does not, on its own, trigger recovery under this profile.
  • When PCR 7 is not used, the default profile seals to PCRs 0, 2, 4, 8, 9, 10 and 11. PCR 2 is in that list. Under this profile, a new GPU or a NIC ROM update changes PCR 2 and the TPM refuses to release the key, so the machine asks for the recovery password.

Microsoft's BitLocker recovery overview lists related triggers, including "Upgrading critical early startup components, such as a BIOS or UEFI firmware upgrade" and "Modifying the Platform Configuration Registers (PCRs) used by the TPM validation profile". It also gives the fix for planned work: suspend protection before the change, which "reseals the encryption key without requiring the entry of the recovery key". If you are deciding between TPM-only and TPM with PIN protection, our post on BitLocker TPM-only versus TPM with PIN covers the trade-off.

Linux disk encryption and PCR 2

Linux tools that seal LUKS keys to the TPM let you choose the PCRs. Including PCR 2 makes sense on servers with a locked card configuration, where you record the expected value per hardware build. On workstations where GPUs change, PCR 7 alone tolerates card swaps.

PCR choice at a glance

Sealing choiceUnlocks after a GPU swap?Detects a modified card ROM?Best fit
PCR 7 and 11 (Windows default with Secure Boot)YesOnly if the modified ROM fails Secure Boot and does not runLaptops and desktops with changing peripherals
PCRs 0, 2, 4, 8, 9, 10, 11 (Windows default without PCR 7)No, recovery requiredYes, PCR 2 changesLegacy configurations; avoid on modern UEFI systems
PCR 7 only (Linux)YesSame as aboveGeneral Linux workstations
PCR 2 and 7 (Linux)NoYesServers with a locked hardware build

How do you see which option ROMs load?

This section is a step by step walkthrough on Linux, the UEFI shell and Windows. All of the commands below only read information. Reading a ROM through sysfs is read only, but do it first on a test machine: some devices behave badly when ROM decoding is toggled while a driver is active.

Step 1: list PCI devices and their expansion ROMs (Linux)

# List every PCI function with vendor and device IDs
lspci -nn

# Show the expansion ROM line for one device (run as root for full output)
sudo lspci -vv -s 01:00.0 | grep -i 'expansion rom'

A line such as Expansion ROM at ... [disabled] means the card has a ROM BAR and the OS is not currently decoding it. That is normal after boot.

Step 2: read the ROM through sysfs

The kernel documentation for PCI sysfs describes the rom file as providing "read-only access to the device's ROM file, if available". It is disabled by default, so you write 1 to enable it, read it, and write 0 to disable it again. The device must be enabled for the read to return data.

DEV=/sys/bus/pci/devices/0000:01:00.0

# Confirm you have the right device before touching anything
cat $DEV/vendor $DEV/device $DEV/class

# Enable ROM access, copy it, then disable access again
echo 1 | sudo tee $DEV/rom > /dev/null
sudo cat $DEV/rom > ~/card-01-00-0.rom
echo 0 | sudo tee $DEV/rom > /dev/null

# Record its size and hash for your inventory
ls -l ~/card-01-00-0.rom
sha256sum ~/card-01-00-0.rom

On a UEFI boot, the x86 Linux EFI stub also preserves ROM images it sees through the firmware's PCI I/O protocol and hands them to the kernel as SETUP_PCI setup data. The stub rejects anything larger than 16 MiB, citing the UEFI size limit, because some firmware puts function pointers where the ROM size should be.

Step 3: parse the images in the ROM

A short Python script can walk the image chain using the offsets from the UEFI spec and the kernel's rom.c. It reads only the file you captured.

#!/usr/bin/env python3
# Walk a PCI option ROM file and print each image's type and size.
import struct, sys

data = open(sys.argv[1], "rb").read()
off = 0
code_types = {0x00: "legacy x86", 0x01: "Open Firmware", 0x02: "PA-RISC", 0x03: "UEFI"}
subsystems = {10: "application", 11: "boot service driver", 12: "runtime driver"}
machines = {0x014C: "IA-32", 0x8664: "x64", 0xAA64: "AArch64", 0x0EBC: "EBC"}

while off + 0x1A <= len(data):
    if data[off:off+2] != b"\x55\xaa":
        print(f"no ROM signature at 0x{off:x}, stopping")
        break
    pcir = off + struct.unpack_from("<H", data, off + 0x18)[0]
    if data[pcir:pcir+4] != b"PCIR":
        print(f"missing PCIR at 0x{pcir:x}, stopping")
        break
    vendor, device = struct.unpack_from("<HH", data, pcir + 4)
    length = struct.unpack_from("<H", data, pcir + 0x10)[0] * 512
    code_type = data[pcir + 0x14]
    last = data[pcir + 0x15] & 0x80
    line = (f"image @0x{off:06x} len={length:>7} vendor={vendor:04x} "
            f"device={device:04x} type={code_types.get(code_type, hex(code_type))}")
    if code_type == 0x03 and struct.unpack_from("<H", data, off + 4)[0] == 0x0EF1:
        subsys, machine, comp = struct.unpack_from("<HHH", data, off + 8)
        line += (f" subsystem={subsystems.get(subsys, subsys)}"
                 f" machine={machines.get(machine, hex(machine))}"
                 f" compressed={'yes' if comp == 1 else 'no'}")
    print(line)
    if last or length == 0:
        break
    off += length

Run it with python3 walk_oprom.py ~/card-01-00-0.rom. A typical modern graphics card shows a legacy image followed by an x64 UEFI boot service driver. A server NIC may show several UEFI drivers. If you build firmware, the EDK II EfiRom tool does the same job and more: its -d option will "dump the headers of an existing option ROM image", and its -e and -ec options build ROMs from EFI drivers, uncompressed or compressed.

Step 4: see what the firmware actually measured

The TPM event log records each driver the firmware loaded, with its digest and device path. With tpm2-tools installed:

# Parse the firmware event log exposed by the kernel
sudo tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements > eventlog.yaml

# Find drivers loaded into PCR 2
grep -n -A14 'EV_EFI_BOOT_SERVICES_DRIVER' eventlog.yaml | less

# Compare against the current PCR values
sudo tpm2_pcrread sha256:2,3,7

Each EV_EFI_BOOT_SERVICES_DRIVER event names a device path. Paths that end in an Offset(...) node under a PCI device came from that card's option ROM. If you see a driver event you cannot tie to a card in lspci, investigate it.

Step 5: look from the UEFI shell

The EDK II UEFI shell has three commands that help on a test bench:

Shell> pci
Shell> pci 01 00 00 -i
Shell> drivers

pci lists every PCI function, and -i interprets a function's configuration space, including the expansion ROM register. drivers lists every UEFI driver with its version, type, the number of devices it manages and its IMAGE PATH, which for a card driver is the PCI device path with an offset range. The shell's loadpcirom command, which "loads PCI option ROM images into memory for execution", exists for driver developers. Do not run it on production machines.

Step 6: check Secure Boot state and db contents (Windows)

# Is Secure Boot on?
Confirm-SecureBootUEFI

# Is the new option ROM CA in db?
[System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Microsoft Option ROM UEFI CA 2023'

# Is the old third-party CA in db?
[System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Microsoft Corporation UEFI CA 2011'

# Which PCRs does BitLocker seal to on the OS volume?
manage-bde -protectors -get C:

On Linux, mokutil --db lists the certificates in db, so mokutil --db | grep -i 'Option ROM' gives the same answer.

Step 7: watch for firmware messages

sudo dmesg | grep -iE 'rom|shadow'
sudo journalctl -k -b | grep -i 'secure boot'

You will often see the kernel's "Video device with shadowed ROM" message for the boot display device. As explained earlier, it reflects the kernel reserving the legacy video window, not a record of which ROM code ran; the TPM event log in Step 4 is the better evidence.

What firmware settings control option ROM policy, and what breaks if you change them?

Setting names vary by board vendor, so the table below describes the usual choices rather than any one menu. Check your platform's manual for the exact wording.

SettingWhat it doesWhat can breakWhen to use it
CSM disabled, UEFI onlyFirmware runs only UEFI drivers from card ROMs; legacy images are ignoredCards with legacy-only ROMs: no display before the OS, no network boot, no boot from a RAID volumeDefault for any modern deployment, as the NSA recommends
CSM enabled, legacy option ROMsFirmware runs legacy images, sometimes in preference to UEFI onesSecure Boot is usually unavailable with CSM on; legacy code runs without signature checksOnly for an old card with no UEFI driver, on an isolated system
Per-slot "do not launch"Firmware skips the ROM for one slotThat card loses its pre-boot features; the OS driver still worksData GPUs and NICs that never need to boot or display before the OS
Secure Boot on, third-party CA trustedCard drivers signed through Microsoft's third-party CA runNothing new, but third-party bootloaders also run if the 2011 CA is presentTypical desktops and servers
Secure Boot on, third-party CA not trustedOnly Windows-signed and OEM-signed drivers runDiscrete GPUs and add-in cards lose their UEFI driver; possible blank screen until the OS loadsSecured-core style locked builds, with Option ROM CA 2023 or hashes added back
Custom db with your own keysOnly what you enrolled runsEvery card ROM fails unless you enrolled its CA or hashOwner-controlled builds; capture card hashes first
External PCIe and Thunderbolt pre-boot support offFirmware ignores devices on external ports during bootNo booting from external PCIe storage; no pre-OS docking station displayLaptops in any managed fleet

Three practical warnings come from experience with these settings:

  • Always keep a way to see the screen. If you turn off the third-party CA or move to your own keys on a machine whose only display is a discrete GPU, you may lose the firmware setup screen. Use integrated graphics, a serial console, or the BMC's remote console on servers, and test on one machine first.
  • Expect BitLocker or LUKS prompts if PCR 2 is in your profile. Suspend protection before changing option ROM settings on machines that seal to PCR 2.
  • Write down the before state. Record the db contents and the event log before any change, so you can tell whether a later difference came from you.

How do vendors update option ROMs, and how should fleets track them?

How updates reach a card

Card ROMs are updated in three main ways:

  1. Vendor flashing tools that write a new image to the card's flash. These often update the on-card device firmware and the option ROM together, which is why a "NIC firmware update" can change PCR 2.
  2. System firmware updates that include option ROMs for onboard devices. NIST SP 800-147B notes that option ROMs "stored with the system BIOS firmware and are updated by the same mechanism are considered part of the BIOS", so they inherit the platform's signed update process.
  3. Linux firmware update services. The Linux Vendor Firmware Service is, in its own words, "a secure web service that can be used by OEM's to upload firmware archives", and fwupd is the client that applies those updates. fwupd's plugin library includes an OpromFirmware parser, available since version 1.8.2, described as handling the OptionROM format that "can be found in nearly every PCI device". Whether fwupd can update a particular card depends on the vendor publishing that card's firmware to the LVFS. Our post on firmware updates on Linux with fwupd and the LVFS explains the capsule and metadata flow.

What changes under the 2023 certificates

When a vendor re-signs a ROM for the Option ROM UEFI CA 2023, ask three questions before you roll it out: is the new image dual signed or 2023-only; which of your machines already carry the 2023 certificate in db; and does the update change PCR 2 on machines that seal disk keys to it. The answers decide the rollout order: certificates first, then ROMs, with disk encryption suspended where needed.

A fleet inventory that actually works

Most inventories stop at "server model and BIOS version". To track option ROMs, record these per machine and per slot:

FieldWhere to get it
PCI vendor, device, subsystem vendor and subsystem device IDslspci -nn -vv, or the sysfs vendor, device, subsystem_vendor, subsystem_device files
Slot and bus addresslspci, firmware inventory, or the BMC
ROM size and SHA-256sysfs rom file, as in Step 2
Images present (legacy, UEFI per architecture)The parser in Step 3, or EfiRom -d
Signer of each UEFI driverExtract the PE image and inspect its Authenticode certificate table with standard PE signing tools
PCR 2 and PCR 3 valuestpm2_pcrread, and the event log for per-driver digests
Firmware option ROM settingsSetup screen exports or the BMC's management API
db contents, including which Microsoft CAs are presentGet-SecureBootUEFI db or mokutil --db

With this data you can answer the questions that matter during a certificate change or a firmware advisory: which machines have a card whose ROM is signed only by the 2011 CA, which hashes are new since last month, and which machines would ask for a recovery key after the next NIC update. If you run BMC-managed servers, the Redfish API can supply much of the slot and firmware data remotely.

Common mistakes

  • Treating the option ROM as device firmware. It runs on your CPU, inside your boot chain. Track it with the platform, not just with the card.
  • Removing the 2011 third-party CA without checking cards. Bootloaders are not the only thing it signs. Check every card's ROM signer first, and add the Option ROM UEFI CA 2023 or ROM hashes where needed.
  • Enrolling your own keys and forgetting the GPU. A custom db with only your certificate blocks every vendor-signed card driver. Capture card hashes before you switch to deployed mode.
  • Leaving CSM on "just in case". It brings back unsigned legacy option ROMs and usually disables Secure Boot. Turn it off unless a specific card needs it, and isolate that machine.
  • Sealing disk keys to PCR 2 on machines whose cards change. Every GPU swap becomes a recovery event. Use PCR 7 where Secure Boot state is available, or document expected PCR 2 values per build.
  • Updating NIC firmware without suspending disk encryption. If the update changes the option ROM and PCR 2 is in the profile, the next boot asks for the recovery key.
  • Assuming firmware denies unsigned ROMs. The UEFI spec lets firmware approve images for its own reasons, and EDK II's policy is a build setting. Test with a known unsigned or hash-mismatched ROM on a bench machine.
  • Allowing pre-boot support for external PCIe ports. Thunderstrike showed why. Turn it off where users do not boot from external devices.
  • Inventorying model numbers only. Two cards with the same model can carry different ROM builds. Hash the ROM.

FAQ

What is a PCI option ROM in simple terms?

It is a driver stored on an add-in card that the computer's firmware runs before the operating system starts. It lets the firmware use the card, for example to show a picture through a graphics card, boot over a network adapter, or boot from a RAID volume.

Do I need option ROMs enabled?

You need them for any card the firmware must use before the OS: the graphics card that shows your setup screen, a NIC you boot from, or a storage controller holding the boot volume. Cards used only by the OS, such as a second NIC or a compute GPU, can usually have their option ROM disabled in firmware.

Does Secure Boot check option ROMs?

Yes. On UEFI firmware, each UEFI driver from a card ROM is loaded through LoadImage() and checked against db and dbx like a bootloader. Legacy option ROMs are not checked, which is one reason to keep CSM off.

What is the Microsoft Option ROM UEFI CA 2023?

It is a new Microsoft certificate stored in the Secure Boot db that signs third-party option ROMs. It replaces the option ROM role of the Microsoft UEFI CA 2011, which expires on 27 June 2026. A separate certificate, Microsoft UEFI CA 2023, now signs third-party bootloaders and applications.

Will my graphics card stop working when the 2011 certificate expires?

Microsoft says devices without the 2023 certificates continue to start and operate normally. A card whose ROM is signed with the 2011 CA keeps working while that CA remains in db. The risk is a new card or a ROM update signed only with the 2023 Option ROM CA on a machine whose db was never updated.

Why did BitLocker ask for a recovery key after I changed my GPU?

If BitLocker on that machine seals its key to PCR 2, which holds option ROM code, a new card changes the measurement and the TPM refuses to release the key. On machines using the Secure Boot profile (PCR 7 and 11) a card swap alone does not usually cause this. Suspend BitLocker before planned hardware changes.

Can an option ROM be used to attack a computer?

Historically, yes. Research such as Thunderstrike in 2014 showed external option ROM code running at a privileged moment during firmware updates. Signature checks, not running ROMs during updates, turning off pre-boot support for external ports, and measuring ROMs into the TPM are the defences that followed.

Which PCR measures option ROMs?

PCR 2 records option ROM code, and PCR 3 records option ROM data and configuration. EDK II firmware writes a boot services driver or runtime services driver event into PCR 2 for each UEFI driver it loads from outside the system firmware image.

Where Safeguard fits

Option ROMs are firmware on hardware, and Safeguard does not scan firmware images, read option ROMs, manage devices or attest boot state. The fit is indirect and sits in the software around this work: the inventory scripts and services your team writes to collect PCI and TPM data, the container images that run those jobs, and any firmware build tree you maintain that vendors in open source code. Those projects pull open source dependencies that deserve the same patch discipline as the rest of your code, and that is where Safeguard helps.

A fleet audit of option ROMs, PCR baselines and db contents runs on ordinary software: Python and shell tooling, parsers, event log libraries and the containers you schedule them in, all built from open source components. When one of those components has a known vulnerability, the fix path is the same as for any application dependency, so the tooling you trust to check your boot chain should not itself be the weak link.

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

The demos below show Safeguard on ordinary software projects, not on firmware or option ROMs. The same flows apply to the code your platform team writes for this work: an inventory script that parses ROMs and event logs, a service that collects PCR baselines, or the container image that runs your nightly hardware audit. Safeguard can scan those with safeguard scan --dir ., --image for a container image, or --sbom for an SBOM file you already have, and it writes results as JSON under ./output.

The first demo is a real Safeguard CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repository, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan. Point the same flow at your hardware inventory repository and you get the same pattern: find the vulnerable dependency, propose the change, run your tests before anything is committed.

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

Firmware labs and management networks are often isolated. The local runner demo shows how to set up the runner on your own machine, approve it with its device code, and then scan from the terminal. A runner on a build host inside that isolated zone can scan the tooling that lives there without opening the network to the outside.

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

If your team already works with Claude, the third demo shows how to connect Claude to the Safeguard MCP server with OAuth and choose which tools Claude can use. An engineer can then ask about known vulnerabilities in the projects that hold your audit scripts and services, using only the tools you have allowed.

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

To try it on your own repositories, download Safeguard and follow the CLI documentation.

Quick check

You replaced the Secure Boot db with only your own certificate, and the discrete GPU now shows nothing until the OS loads. Why?

The GPU's UEFI driver in its option ROM is signed through a Microsoft third-party CA, which is no longer in db. Firmware refuses to load it, so there is no pre-boot display driver. Enroll the Microsoft Option ROM UEFI CA 2023, the card vendor's certificate, or the SHA-256 hash of that ROM image, and test before switching to deployed mode.

A Windows laptop with Secure Boot on gets a new Thunderbolt dock with an option ROM. Does BitLocker ask for recovery?

Usually not. With Secure Boot state available, BitLocker's default profile seals to PCR 7 and PCR 11, and a new option ROM changes PCR 2, which is not in that profile. It would trigger recovery on a machine whose profile includes PCR 2.

Sources

Last reviewed: 23 October 2026. Secure Boot certificate guidance and firmware option ROM settings change often; check the linked Microsoft, UEFI and kernel documentation and your platform vendor's manual for the settings your hardware supports.

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.