bias-loader-uefi 1.0.0

A Rust library for parsing and loading UEFI firmware images
Documentation

bias-loader-uefi

Rust bindings for UEFITool with additional parsers for AMI PFAT and Dell PFS formats.

Parse UEFI firmware images to extract modules, NVRAM variables, microcode updates, buf sections, and Secure Boot signature databases.

Building

The UEFITool sources are compiled automatically via build.rs.

git clone git@github.com:binarly-io/bias-loader-uefi.git
git submodule update --init
cargo build --release

Usage

Parse a UEFI firmware image

use bias_loader_uefi::Uefi;

let bytes = std::fs::read("firmware.bin")?;
let fw = Uefi::new(&bytes)?;

// iterate over all modules
fw.for_each(|module| {
    println!("{} [{}] {:?}", module.name(), module.guid(), module.module_type());
});

// count extracted components
println!("modules: {}", fw.count_modules());
println!("nvram vars: {}", fw.count_vars());
println!("microcode: {}", fw.count_microcode());

NVRAM variables

fw.for_each_var(|var| {
    println!("{} type={:?} valid={}", var.name(), var.var_type(), var.is_valid());
});

Microcode updates

fw.for_each_microcode(|mc| {
    println!("{:?} date={} cpuid={:#x} rev={}", mc.vendor(), mc.date(), mc.cpu_signature(), mc.update_revision());
});

Early termination

use bias_loader_uefi::ContinueOrStop;

fw.for_each_until(|module| {
    if module.guid() == "A2DF5376-C2ED-49C0-90FF-8B173B0FD066" {
        // found it, stop iterating
        return ContinueOrStop::Stop;
    }
    ContinueOrStop::Continue
});

Dependency expressions

use bias_loader_uefi::depex::DepExOpcode;
use uuid::Uuid;

fw.for_each(|module| {
    if !module.depex().is_empty() {
        println!("{}:", module.name());
        for op in module.depex() {
            match op {
                DepExOpcode::Push(guid) => println!("  Push({})", Uuid::from_bytes_le(*guid)),
                DepExOpcode::Before(guid) => println!("  Before({})", Uuid::from_bytes_le(*guid)),
                DepExOpcode::After(guid) => println!("  After({})", Uuid::from_bytes_le(*guid)),
                other => println!("  {other:?}"),
            }
        }
    }
});

Unpack AMI PFAT / Dell PFS firmware

Auto-detect and unpack proprietary firmware containers before parsing:

use bias_loader_uefi::{try_unpack, Uefi};

let buf = std::fs::read("image.cap")?;
let unpacked = try_unpack(&buf)?;
let fw = Uefi::new(&unpacked)?;

For firmware images containing multiple UEFI images (common with Dell PFS):

use bias_loader_uefi::UefiMulti;

let buf = std::fs::read("image.cap")?;
let multi = UefiMulti::new(&buf)?;

for (uefi, image) in multi.iter_full() {
    println!("image: {} ({} modules)", image.name(), uefi.count_modules());
}

Format detection

use bias_loader_uefi::parsers::Hint;

match Hint::parse(&bytes) {
    Hint::Pfat => println!("AMI PFAT"),
    Hint::Pfs  => println!("Dell PFS"),
    Hint::Unknown => println!("Unknown"),
}

Secure Boot signature extraction

use bias_loader_uefi::secureboot::extract_sb_signatures_from_nvram;

fw.for_each_var(|var| {
    let sigs = extract_sb_signatures_from_nvram(var.name(), var.data());
    for sig in sigs {
        println!("{:?} owner={} type={}", sig.database_type, sig.signature_owner, sig.signature_type);
    }
});

Acknowledgements

Special thanks to: