Version: 0.16.5 Updated: 2026-06-08 Audience: new contributors, integrators, and anyone reading the LamBoot source
lamboot-dev/
├── Cargo.toml Workspace manifest
├── .cargo/config.toml Default target = x86_64-unknown-uefi, build-std flags
├── build.sh Build both targets + modules, prepare dist/
├── package-release.sh Build + sign + produce release tarball
├── run-qemu.sh QEMU test harness
├── lamboot-core/ The bootloader
│ ├── Cargo.toml
│ └── src/
│ ├── main.rs Layer 7 — orchestration, 10-phase boot flow
│ ├── boot_types.rs Layer 3 — shared BootEntry/EntryKind/Icon + preflight result types
│ ├── bls_parse.rs Layer 3 — pure BLS Type 1 parser (UAPI.10 version sort)
│ ├── bls.rs Layer 4 — BLS coordinator (boot counting, default selection inputs)
│ ├── boot.rs Chainload, UKI, native PE-loaded Linux boot under SecurityOverride (firmware LoadImage fallback)
│ ├── console.rs Serial/text console fallback menu
│ ├── discovery.rs BLS-first entry discovery with ESP fallback
│ ├── drivers.rs EFI filesystem driver loader, trust events
│ ├── fs.rs Layer 2 — ESP mount, volume I/O, multi-partition scan
│ ├── block_source.rs Layer 2 — BlockSource (Seam A) + SourceReader<S> (Seam B): the generic block seam every byte-addressed FS reader sits on
│ ├── fs_backend.rs Layer 2 — FsBackend trait + FsError; read-only by construction (writes go through fs_writer, FAT-ESP only)
│ ├── fs_backend_ext4.rs Layer 2 — native read-only ext4 reader
│ ├── fs_backend_btrfs.rs Layer 2 — native read-only btrfs reader
│ ├── fs_backend_fat.rs Layer 2 — firmware-served FAT (ESP)
│ ├── fs_backend_fat_ro.rs Layer 2 — native read-only FAT (FatRo, via lamfat) for non-ESP FAT volumes
│ ├── fs_backend_xfs.rs Layer 2 — native read-only XFS reader (lamxfs); also LV + .iso loopback
│ ├── fs_backend_exfat.rs Layer 2 — native read-only exFAT reader (lamexfat), whole partitions only
│ ├── fs_backend_zfs.rs Layer 2 — native read-only ZFS boot-pool reader (lamzfs); single/mirror/RAIDZ1 only
│ ├── fs_backend_lamfold.rs Layer 2 — native read-only media stack (lamfold): EROFS, ISO 9660, SquashFS, cramfs, romfs, UDF
│ ├── fs_backend_lvm*.rs Layer 2 — LVM logical-volume dispatch + per-FS LV adapters
│ ├── distro_iso.rs Layer 3 — boot-from-ISO Path A2 distro-family fallback table
│ ├── loopback_cfg.rs Layer 3 — boot-from-ISO Path A1 loopback.cfg resolver
│ ├── gui.rs Double-buffered framebuffer, boot menu
│ ├── health.rs NVRAM state machine, Boot Loader Interface vars
│ ├── initrd.rs LoadFile2 provider for Linux initrd
│ ├── input.rs Keyboard + mouse dispatch
│ ├── policy.rs policy.toml parser
│ ├── report.rs Boot reports, audit logging
│ ├── secure.rs Secure Boot state detection + shim integration
│ ├── security_override.rs PATH F — Security/Security2 arch protocol hooks
│ ├── pe_loader.rs Layer 3 — native PE loader (I/O shell over pe_loader_pure)
│ ├── pe_loader_pure.rs Layer 3 — v0.16.1 hand-rolled no_std PE/COFF reader (load-bearing COFF + PE32+ fields from fixed offsets; no goblin, no DOS-stub parse)
│ ├── smbios.rs SMBIOS string extraction for diagnostics
│ ├── tpm.rs TPM 2.0 measured boot (TCG2)
│ ├── trust_log.rs v0.8.3 — JSON-lines audit log
│ ├── boot_entry.rs Layer 4 — v0.16.3 boot-entry identity + NVRAM Boot#### self-install
│ └── boot_entry_pure.rs Layer 4 — host-tested EFI_LOAD_OPTION/BootOrder byte codecs
├── lamboot-modules/ Chainloaded diagnostic EFI applications
│ ├── diag-shell/
│ ├── mem-quick/
│ ├── nvme-diag/
│ └── pci-inventory/
├── tools/ Host-side tooling
│ ├── lamboot-install Install script (bash)
│ ├── sign-lamboot.sh Sign bootloader + drivers + modules
│ ├── sign-unlock / sign-lock Session-cached signing-key unlock
│ ├── lamboot-monitor.py Proxmox host-side VM boot health monitor
│ ├── layer-map.toml Source of truth for the 8-layer module map
│ ├── check-layers.py Enforces layer declarations + acyclic dependency DAG
│ └── build-ovmf-vars.sh Build pre-enrolled OVMF_VARS
├── docs/ User-facing documentation (ARCHITECTURE-LAYERS.md is authoritative for layers)
├── examples/ Sample policy.toml, BLS entries
├── dist/ Build output (gitignored)
├── keys/ Signing keys (gitignored)
├── .github/workflows/ci.yml CI: fmt + clippy + cargo check + layer contract
└── .githooks/ pre-commit: fmt + clippy + cargo check + layer contract
Required:
- Rust stable (builds everything, including both UEFI targets; >= 1.88, verified on 1.96.0).
rust-toolchain.tomlpins thestablechannel. The UEFI crates still buildcore/alloc/compiler_builtinsfrom source via the per-crate-Zbuild-stdflags, but those cargo flags are unlocked on stable throughRUSTC_BOOTSTRAP=1— no nightly toolchain required. - Rust nightly (only for
cargo fmtimport-ordering):rustup install nightly - Targets:
rustup target add x86_64-unknown-uefi aarch64-unknown-uefi sbsign,sbverify,mkfs.vfat(for testing / signing)llvm-objcopy(strongly preferred over GNU objcopy for PE section embedding — GNU objcopy corrupts UEFI PE binaries)qemu-system-x86_64,qemu-system-aarch64,ovmf/edk2-ovmf(for QEMU tests)openssl(for key generation; seedocs/KEY-GENERATION.md)
Optional:
swtpm(for QEMU TPM tests)virt-fw-varsfrom virt-firmware (for OVMF_VARS editing)
# Build both targets + modules (primary dev loop)
./build.sh
# Fast iteration: x86_64 only
cargo build --target x86_64-unknown-uefi --release -p lamboot-core
# Format + lint — pre-commit hook runs these, but do it yourself first
rustup run nightly cargo fmt
cargo clippy
# QEMU smoke test (Secure Boot off)
./run-qemu.shNo cargo test for UEFI targets — UEFI binaries cannot run on the host. Tests that must run cross-compiled live inside in-tree runtime check modules; QEMU is the integration-test vehicle.
See CLAUDE.md in the repo root for the canonical rules. Summary:
- Write why comments, not what comments. If the code's intent isn't obvious, add a one-line rationale. Don't restate the code.
- Every
unsafeblock requires a// SAFETY:comment explaining the invariant.
- Verbs describe domain actions:
parse_entry,discover_partitions,measure_pcr— neverprocess,handle,do_thing. - No generic suffixes: no
-Manager,-Helper,-Utility. UseOrchestrator,Bridge,Providerwhen a role word helps. - No helper modules — no
utils.rs,common.rs,helpers.rs.
- No single-implementation traits. If there's one impl, use the concrete type.
- Max nesting: 3 levels. Use early returns for preconditions.
- Happy path left-aligned; guard clauses at the top.
- Never
#[allow(clippy::...)]. Use#[expect(..., reason = "...")]. #[expect]requires a documented reason. If you can't explain why, fix the code.
- UEFI errors propagate with
?anduefi::Result. - Panic for unrecoverable init only (allocator, UEFI helpers init).
- Optional features degrade gracefully — a missing TPM logs and continues, it doesn't abort boot.
Adding a filesystem reader? The common path in the 0.16.0 era is a new Layer-2
FsBackend. Implement theFsBackendtrait infs_backend.rs, sit your byte-addressed reader on theBlockSource/SourceReader<S>seam inblock_source.rs(so it reads off a whole partition, an LVM LV, or an.isoloopback region for free), keep it read-only by construction (the ESP writer infs_writer.rsis FAT-ESP-only), and register the superblock-magic probe with the source-generic dispatcher. See theFsBackendtrait inlamboot-core/src/fs_backend.rs.
Example: adding a network-boot subsystem.
- Create the module.
lamboot-core/src/netboot.rs. - Choose a domain-specific name. Not
network.rs; maybepxe.rsorhttp_boot.rsdepending on the protocol. - Declare the module's layer. Add a
//! Layer: Ndoc comment at the top of the file, choosing the layer perdocs/ARCHITECTURE-LAYERS.md(a network-boot subsystem that loads external code is typically Layer 4). Add a matching entry totools/layer-map.toml, then runpython3 tools/check-layers.py. The checker fails on a missing declaration or any upward dependency (a lower layer importing a higher one) — the module graph must stay an acyclic DAG. The pre-commit hook and CI both enforce this, so run it before you commit. - Declare in
main.rs.mod netboot;
- Wire into the boot flow.
main.rsis the orchestration (Layer 7). Add a phase with a log line and explicit ordering relative to other phases. Don't hide cross-phase state in globals; pass it through function arguments. - Record trust events. If your subsystem loads code from an external source, push a
TrustEventso the boot-trust log captures the decision. - Test in QEMU. Add a harness script if the setup is non-trivial.
Example: adding a diagnostic module.
mkdir lamboot-modules/my-diag; cd lamboot-modules/my-diagCargo.toml:[package] name = "my-diag" version.workspace = true edition.workspace = true license.workspace = true [[bin]] name = "my-diag" path = "src/main.rs" [dependencies] uefi.workspace = true log.workspace = true
src/main.rs:#![no_std] #![no_main] use uefi::prelude::*; #[entry] fn main() -> Status { uefi::helpers::init().unwrap(); log::info!("my-diag: hello from a diagnostic module"); // ... do stuff ... Status::SUCCESS }
- Add
"lamboot-modules/my-diag"to the rootCargo.tomlworkspace.members. - Add a manifest entry in
dist/EFI/LamBoot/modules/manifest.toml:[modules.my-diag] name = "My Diagnostic" description = "What it does in one sentence" version = "0.1.0"
- Rebuild via
./build.sh. The module appears in the LamBoot menu.
# One-time: generate production keys (see docs/KEY-GENERATION.md)
# Stores keys/pk.{key,crt}, keys/kek.{key,crt}, keys/db.{key,crt}
# One-time per session: unlock the signing key into tmpfs
./tools/sign-unlock
# Prompts for the db.key passphrase, stashes it in
# /run/user/$UID/lamboot-signing/db.key, exports LAMBOOT_SIGN_KEY.
# Build + sign
./build.sh
./tools/sign-lamboot.sh
# Produces dist/EFI/LamBoot/lambootx64-signed.efi and db.der.
# End of session
./tools/sign-lock # Drops the unlocked key from tmpfsThe signing script uses llvm-objcopy to embed the SBAT section; falls back to GNU objcopy with a warning because GNU objcopy corrupts UEFI PE binaries in some configurations.
.githooks/pre-commit runs on every commit:
cargo fmt --check(nightly)cargo clippy— all warnings treated as errorscargo check --target x86_64-unknown-uefipython3 tools/check-layers.py— the layer contract: every module must carry a//! Layer: Ndeclaration matchingtools/layer-map.toml, and the dependency graph must stay an acyclic DAG with no upward edges..github/workflows/ci.ymlruns the same four checks on every push.
Enabled via git config core.hooksPath .githooks (already set in this repo). To run manually:
.githooks/pre-commit- Land features on
mainwith feature-complete commits. - Bump version in
Cargo.toml(workspace.package.version). - Update
CHANGELOG.mdwith a new dated section. - Build + sign:
./build.sh && ./tools/sign-lamboot.sh. - Package:
./package-release.sh. - Tag:
git tag -a vX.Y.Z -m '...'and push.
- QEMU serial log. Every test harness pipes to a file — grep that first for
ERROR/trust:/Security. - SB failures leave artefacts. If the firmware refuses to boot LamBoot with SB enabled, check the trust log —
\loader\boot-trust.logis written before handoff, readable from any Linux booted afterward. - Binary integrity after signing.
sbverify --cert keys/db.crt dist/EFI/LamBoot/lambootx64-signed.efi— if this fails, the signing pipeline is broken. If it passes but firmware refuses, the cert isn't enrolled. - Shim ACCESS_DENIED on kernel. This is typically not LamBoot; it's ShimLock::Verify failing on the kernel. Check the kernel's signature separately with
sbverify. - Driver loading failures. Under SB, filesystem drivers must be signed and SecurityOverride must be active. Check the trust log; look for
driver_rejectedevents with reason.
See CONTRIBUTING.md for:
- Branch and PR conventions (conventional commits)
- CI expectations
- DCO / sign-off (recommended but not required)
Good first issues:
- Diagnostic modules (NVMe SMART richness, PCI enumeration completeness, memory-test patterns)
- New filesystem driver packaging (testing, signing)
- Distro-specific install script hardening (OpenSUSE, Arch, Gentoo equivalence)
- Documentation refinements for unusual hardware platforms
- Localization of the GUI
Not a good first issue:
security_override.rs— needs deep UEFI protocol understandingtpm.rsTCG2 work — bring a TPM test harnesslamboot-core/src/main.rsboot-flow ordering — almost every change is subtle
- Code-level: open a GitHub Discussion on the public repo.
- Security:
security@lamco.ioonly. Do not file public issues for suspected vulnerabilities. - Packaging / distro integration: GitHub Issues on the public repo.
For full architecture, see docs/ARCHITECTURE.md.