uefi-firmware-parser: reading UEFI volumes, Intel ME regions and Dell PFS updates
Parse BIOS/Intel ME/UEFI firmware related structures: Volumes, FileSystems, Files, etc
At a glance
- What is it?
- uefi-firmware-parser is a Python module and set of scripts for parsing, extracting and recreating UEFI firmware volumes, with parsers for BIOS images, OptionROMs, Intel ME and Dell PFS updates. It also does GUID injection and can regenerate a firmware descriptor from parsed volumes, which makes it a reverse engineering tool rather than only an extractor.
- Who is it for?
- uefi-firmware-parser suits a firmware reverse engineer or a security researcher who needs to inspect vendor BIOS images across many vendors, and it is the wrong tool for patching a live machine, since the injection path is interactive and the README says it is not yet scriptable.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Parsing, extracting and recreating firmware volumes
The uefi-firmware-parser project describes itself as a simple module and set of scripts for parsing, extracting and recreating UEFI firmware volumes. Those three verbs set the scope, and the third one is the interesting one. Extracting files from a firmware image is a solved problem. Regenerating a firmware descriptor from the volumes you just parsed, and injecting a file section into a specific place in the hierarchy, is the part that turns a reader into an editor.
The feature list is explicit about what is covered. UEFI Firmware Volumes, Capsules, FileSystems, Files and Sections are parsed. Intel PCH Flash Descriptors are parsed. Intel ME modules are parsed, covering ME and TXE. Dell PFS (HDR) updates are parsed. Tiano/EFI and native LZMA compression and decompression are supported. There is complete display of the UEFI firmware volume object hierarchy, firmware descriptor regeneration using the parsed input volumes, and firmware file section injection.
So the coverage is not just the modern UEFI container. It reaches back into the older BIOS world through OptionROM parsing, and across vendors through the Intel and Dell specific formats. The vendor list at the end of the README names ASRock, Dell, Gigabyte, Intel, Lenovo, HP, MSI, VMware, Apple and Qualcomm, and immediately qualifies it: not every update for every product parses, and some may require prior decompression or extraction from the distribution update mechanism, typically a PE.
That qualification is the honest summary of what any firmware parser faces. The container formats are specified, but the files that vendors ship inside them are not always the raw container.
AutoParser picks the parser, and brute modes pick it harder
The entry point for programmatic use is the `AutoParser` class, and the README describes it as the simplest way to detect or parse firmware:
import uefi_firmware
with open('/path/to/firmware.rom', 'r') as fh:
file_content = fh.read()
parser = uefi_firmware.AutoParser(file_content)
if parser.type() != 'unknown':
firmware = parser.parse()
firmware.showinfo()The pattern is worth internalising: construct the parser with the raw bytes, ask `type()` what it thinks the input is, and only then call `parse()`. The `type()` check before parsing is not defensive noise. It is the normal path, because the type checker sometimes cannot identify an image, and in that case the right response is to try harder rather than to crash.
That is what the brute modes are for. The `-b` flag treats the input as a blob that may contain FV headers, and `--superbrute` performs a byte-by-byte type checker for a blob that may contain any sort of firmware object. The README describes the sequence: run `--test` first, and if it returns `unknown`, retry with `-b` or `--superbrute`.
The `--test` output is a compact identification line per file, which makes it usable as a triage step over a directory of images:
$ uefi-firmware-parser --test ~/firmware/*
~/firmware/970E32_1.40: UEFIFirmwareVolume
~/firmware/CO5975P.BIO: EFICapsule
~/firmware/me-03.obj: IntelME
~/firmware/O990-A03.exe: None
~/firmware/O990-A03.exe.hdr: DellPFSNote the last two lines. A vendor `.exe` wrapper is reported as `None`, while the `.hdr` file extracted from it is reported as `DellPFS`. That is the qualification from the vendor section made concrete: the Dell update arrives inside a Windows executable, and the parser needs the inner file.
The same three methods on every object in the hierarchy
The architecture is uniform in a way that makes the tool easy to script against. The README describes several classes across the `uefi`, `pfs`, `me` and `flash` packages that accept file contents in their constructor, and in all cases there are abstract methods implemented.
Three of them matter. `process()` performs the parsing work and returns `True` or `False`, so you always have a success flag rather than an exception as the only signal. `showinfo()` prints a hierarchy of information about the structure. `dump()` walks the hierarchy and writes each element to a file.
That uniformity is what makes bulk extraction practical. The same three calls work whether you are holding a firmware volume, a filesystem, an Intel ME module or a flash descriptor, so a script does not need to know in advance what it has found in order to handle it.
The command line exposes the same operations with different ergonomics depending on the job. `-o OUTPUT` dumps firmware objects to a chosen folder, while `-O` dumps them to a folder derived from the input filename, which the README recommends for parsing a large number of firmware files since it keeps each file's output separate. `-e` extracts all files, sections and volumes. `-q` suppresses the info output, which is what you want when running over a directory where the hierarchy dump would flood the log. `-c` echoes the filename before parsing or extracting, described as useful when parsing and searching for internals in a shell.
The `--generate GENERATE` option produces an FDF, a firmware descriptor, and it implies extraction, with volumes only.
GUID injection works on sections and files, and is not yet scriptable
The write side of the tool is the GUID injector. The README describes injection or GUID replacement on sections within a UEFI firmware file, or on UEFI firmware files within a firmware filesystem, and notes that there is no addition or subtraction of GUIDs yet.
The script lives in `scripts/fv_injector.py` and its interface is narrow:
$ python ./scripts/fv_injector.py -h
usage: fv_injector.py [-h] [-c] [-p] [-f] [--guid GUID] --injection INJECTION
[-o OUTPUT]
fileThe flags map to input interpretation and target selection. `-c` says the input file is a firmware capsule, `-p` says it is a Dell PFS, and `-f` injects a payload into a firmware file. `--guid GUID` names the GUID to replace, `--injection INJECTION` points at a pre-generated EFI file to inject, and `-o OUTPUT` names the output file.
The important limitation is stated plainly in the README: when injecting into a firmware file, the user is prompted for which section to replace, and at the moment this is not yet scriptable.
That single sentence sets the boundary of the whole project. The parser is scriptable and the injector is interactive. Anyone planning a pipeline that rewrites firmware automatically has to work around a prompt, and anyone who wants an unattended patch job needs to supply their own automation around the tool rather than get it from the tool.
The pre-generated EFI file requirement is the other constraint. You do not get to inject arbitrary content; you inject a file that was built elsewhere, which keeps the injector focused on relocation rather than on generating EFI payloads.
uefi_guids.py feeds IDA with vendor labels
The second script in the `scripts/` directory targets reverse engineers working in IDA. It generates additional GUID labels for import into IDA Python using Snare's plugins, and the README says the project will try to keep up to date with popular vendor GUIDs automatically.
Its interface:
$ python ./scripts/uefi_guids.py -h
usage: uefi_guids.py [-h] [-c] [-b] [-d] [-g GENERATE] [-u] file
Output GUIDs for files, optionally write GUID structure file.Here `-g GENERATE` produces a behemoth style GUID output, `-u` also prints unknown GUIDs, `-b` treats the input as a blob and searches for firmware volume headers, `-c` means the input is a capsule and should not be searched, and `-d` selects a flash descriptor.
The reason this matters is that GUIDs in a firmware image are opaque 128 bit identifiers. On their own they tell you nothing. A GUID database maps them to driver names, vendor strings and firmware component identities, and that mapping is what turns a directory listing of opaque hex into something a reverse engineer can reason about. The `-u` flag for unknowns is the useful part during an investigation, since the GUIDs you cannot identify are often the interesting ones.
The two scripts share a design assumption worth noticing. Both take a file, both interpret it according to flags rather than trying to auto-detect everything, and both write output that is meant to be consumed by the next tool in a chain, whether that is another parse or an IDA import. This is a toolkit of stages rather than a single monolithic tool.
Installing needs headers and gcc, and the licence is not a standard one
Installation is through PyPI as `uefi_firmware`, and the README gives two routes. The package install is `sudo pip install uefi_firmware`. To install from GitHub you check out the repository and run `sudo python ./setup.py install`.
The requirements section names two things beyond Python itself. Python development headers, usually in the `python-dev` package, are required. The compression and decompression features use the Python headers and `gcc`, which is why a compiler shows up in the requirements of a pure Python project: the LZMA and Tiano decompression paths are implemented as compiled extensions.
That extension build is visible in `setup.py`, which walks the `uefi_firmware/compression` directory collecting `.h` headers and `.c` sources. The same file also shows an attention to modern Python packaging: it reads `sysconfig.get_config_var('Py_GIL_DISABLED')` to detect a free-threaded build, and when the interpreter is not free-threaded it compiles the extensions against the limited API with `Py_LIMITED_API` set to `0x030A0000`, that is Python 3.10. That means the compiled extensions work across Python 3.10 and later on a normal build, while a free-threaded build takes a different path.
The packaging metadata in `pyproject.toml` is modern in the other direction, requiring `setuptools>=61.0.0` and `setuptools-scm>=8.0` with the setuptools build backend, and the version itself is derived from the source tree through setuptools_scm rather than written by hand.
On licensing, the licence field on the repository says it is a custom licence GitHub cannot classify, so the LICENSE file at the root is the authoritative text. Read it before reusing the code in a product, particularly given that this project sits in a domain where tooling gets vendored into security research pipelines.
Maintenance is current. The last push was on 2026-10-12, and the releases listed are v1.16 on 2026-06-04, v1.15 on 2026-06-04 and v1.13 on 2026-02-17. The 1.x line is stable in shape but still gaining vendor coverage, so a version bump is often a new parser rather than a refactor. The repository also carries a `tests/` directory, a `bin/` directory, an AUTHORS file and a `MANIFEST.in`.
Editorial conclusion
uefi-firmware-parser suits a firmware reverse engineer or a security researcher who needs to inspect vendor BIOS images across many vendors, and it is the wrong tool for patching a live machine, since the injection path is interactive and the README says it is not yet scriptable. Verify three things before you rely on it: that the licence file at the repository root satisfies your use, since the licence field on the repository says it is a custom licence GitHub cannot classify, that your platform has the Python development headers and gcc available because the compression and decompression features need them, and that your specific vendor image parses without pre-decompression, since the README warns that some updates require a prior extraction step from the distribution mechanism.
Frequently asked questions
How do I install uefi-firmware-parser?
From PyPI with `sudo pip install uefi_firmware`, or from a GitHub checkout with `sudo python ./setup.py install`. The requirements are the Python development headers and gcc, because the compression and decompression features are compiled extensions.
What file formats does uefi-firmware-parser handle?
UEFI Firmware Volumes, Capsules, FileSystems, Files and Sections, Intel PCH Flash Descriptors, Intel ME modules including TXE, Dell PFS (HDR) updates, and OptionROMs. It also supports Tiano/EFI and native LZMA compression and decompression.
Why does uefi-firmware-parser report my firmware file as unknown?
The README says to retry with the `-b` option, which treats the input as a blob that may contain FV headers, or with `--superbrute`, which performs a byte-by-byte type checker. Some vendor updates also need prior extraction from the distribution mechanism, typically a PE.
Can uefi-firmware-parser inject a file into a firmware image automatically?
Not fully. The `fv_injector.py` script supports GUID replacement and section injection, but the README states that when injecting into a firmware file the user is prompted for which section to replace, and that this is not yet scriptable.
How do I get GUID labels into IDA?
Run `python ./scripts/uefi_guids.py` against a firmware file. The script generates GUID labels for import into IDA Python using Snare's plugins, with `-g GENERATE` producing a behemoth style output and `-u` also printing unknown GUIDs.
How do I use uefi-firmware-parser from Python?
Use the AutoParser class: read the file contents, construct `uefi_firmware.AutoParser(file_content)`, check `parser.type()` for something other than unknown, then call `parse()` and `showinfo()`. The `dump()` method walks the hierarchy and writes each element to a file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/theopolis-uefi-firmware-parser)Was this useful?