Skip to content

Latest commit

 

History

History
174 lines (132 loc) · 9.94 KB

File metadata and controls

174 lines (132 loc) · 9.94 KB

Heads Architecture

Heads is a firmware distribution that replaces proprietary BIOS/UEFI with coreboot, a minimal Linux kernel, and a security-focused initramfs. It establishes a hardware root of trust, implements measured boot via TPM, and verifies the OS boot environment before handing off control.

See also: security-model.md, boot-process.md, tpm.md — detailed subsystem documentation.

External reference: deepwiki.com/linuxboot/heads — validated against code in this repository.


Major components

┌─────────────────────────────────────────────────────┐
│  SPI Flash ROM                                       │
│  ┌──────────────┐  ┌───────────────┐  ┌──────────┐  │
│  │  coreboot    │  │ Linux kernel  │  │ initramfs │  │
│  │ (HW init +   │→ │ (minimal,     │→ │ (boot    │  │
│  │  PCR 2 SRTM) │  │  no initramfs)│  │  scripts)│  │
│  └──────────────┘  └───────────────┘  └──────────┘  │
└─────────────────────────────────────────────────────┘
         │                                    │
         ▼                                    ▼
   TPM (PCR values)                OS kernel via kexec

coreboot

Replaces vendor firmware. Performs hardware initialization (memory training, PCIe, USB), records each firmware stage (bootblock → romstage → ramstage → payload) into TPM PCR 2 as the Static Root of Trust for Measurement (SRTM), and launches the kernel directly without a second-stage bootloader. Measured boot is transitive: each stage measures the next before executing it. The CRTM (running in bootblock) measures FMAP and the bootblock image into the preram log. Measurements taken before the TPM hardware is initialized are cached in the preram log and flushed to PCR 2 once TPM setup is complete. See tpm.md for per-board TPM init timing.

The framebuffer initialized by coreboot (libgfxinit on pre-Alder Lake, FSP GOP on Alder Lake and newer) must survive across kexec for display to work in the booted OS. Boards without a coreboot framebuffer (talos-2: kernel AST DRM, librem_l1um: BMC serial, KGPE-D16: native VGA init — server variants output to BMC serial + AST VGA; workstation variants use external discrete NVIDIA/AMD GPUs with fbwhiptail) have different display paths that do not involve sysfb handoff. See boot-process.md and kexec_handoff.md for the display handoff mechanism, per-board GPU init paths, limitations, and the TPM Disk Unlock Key workaround.

Linux kernel (payload)

A minimal, stripped kernel compiled specifically for Heads. No initramfs — it boots directly into the Heads initramfs. Provides device drivers (TPM, USB, storage, network), filesystem support, and the platform for the boot scripts.

initramfs

The root filesystem that runs at boot. Contains all Heads logic: configuration loading, TPM operations, GPG verification, whiptail GUI, boot menu, LUKS key injection, and kexec execution. Source lives in initrd/.


initramfs subsystems

Subsystem Key files Purpose
Init / boot flow initrd/init, initrd/bin/gui-init.sh System initialization and main GUI loop
TPM abstraction initrd/bin/tpmr.sh Unified TPM 1.2 / TPM 2.0 wrapper
Boot signing initrd/bin/kexec-sign-config.sh GPG-sign /boot files, create checksums
Boot verification initrd/bin/kexec-select-boot.sh Verify checksums, select and kexec the OS
LUKS key sealing initrd/bin/kexec-seal-key.sh Seal disk encryption key to TPM
TOTP/HOTP initrd/bin/seal-totp.sh, initrd/bin/seal-hotpkey.sh Seal attestation secrets to TPM
OEM reset initrd/bin/oem-factory-reset.sh Full re-ownership: GPG, TPM, TOTP, checksums
Config GUI initrd/bin/config-gui.sh Runtime configuration menus
Functions lib initrd/etc/functions.sh Shared utilities: logging, INPUT, TPM helpers
GUI lib initrd/etc/gui_functions.sh Whiptail wrappers, integrity report

Configuration system

Three-layer hierarchy:

  1. /etc/config — Board defaults compiled into the ROM at build time
  2. /etc/config.user — User overrides extracted from CBFS at runtime
  3. /tmp/config — Combined result, sourced during boot

combine_configs() in initrd/etc/functions.sh merges these by concatenating /etc/config* into /tmp/config. User settings in CBFS take precedence because they appear last in the concatenation.

Changes to user configuration are persisted by reflashing the ROM (CBFS operations).


Build system

The top-level Makefile orchestrates:

  • Cross-compiler (musl-cross-make, target: x86_64-linux-musl or powerpc64le-linux-musl)
  • Modules (coreboot, Linux, busybox, GPG, cryptsetup, kexec, LVM2, …)
  • Six CPIO archives assembled into the initramfs:
    1. dev.cpio — device nodes
    2. modules.cpio — kernel modules
    3. tools.cpio — userspace tools + configuration
    4. board.cpio — board-specific scripts
    5. heads.cpio — security scripts (CONFIG_HEADS=y)
    6. data.cpio — data files
  • Final ROM image: coreboot ROM with Linux + initramfs payload embedded

Reproducible builds are achieved via Nix-pinned Docker images. See docker.md. The CI pipeline's workspace and cache behavior is documented in circleci.md.


Supported architectures

Architecture Target triplet Example boards
x86-64 x86_64-linux-musl ThinkPad, Librem, Dell OptiPlex, QEMU
PowerPC 64-bit LE powerpc64le-linux-musl Raptor Talos II

Key design principles

  • No network at boot — all verification is local; no certificate authorities
  • Hardware root of trust — the coreboot bootblock (IBB) is the Static Core Root of Trust for Measurement (S-CRTM): the first code executed by the CPU, directly from SPI flash. Coreboot implements a transitive measurement chain: the CRTM measures FMAP and the bootblock image into the preram log, then each subsequent stage measures the next before executing it — bootblock measures romstage, romstage measures ramstage, ramstage measures the Heads payload. Measurements are taken during CBFS file loading, before decompression, and are recorded in TPM PCR 2 (SRTM) once the TPM hardware is initialized (tpm_setup()). Measurements taken before TPM init are cached in the preram log and flushed to PCR 2 by tspi_measure_cache_to_pcr() during tpm_setup(). The full chain — bootblock → romstage → ramstage → Heads Linux kernel + initrd — is recorded into PCR 2. PCRs 0, 1, and 3 remain zero as policy anchors. See tpm.md for TPM init timing per board. See wp-notes.md for SPI write-protection and PR0 chipset locking details.
  • Fail-closed — failed integrity verification drops to a recovery shell. Recovery shell authentication via GPG smartcard is enforced when GPG key backup has been configured (CONFIG_HAVE_GPG_KEY_BACKUP=y), which is set by answering "y" to "Would you like to format an encrypted USB Thumb drive to store GPG key material? (Required to enable GPG authentication)" during OEM Factory Reset / Re-Ownership. Otherwise the recovery shell is unauthenticated. An "Ignore tampering and force a boot (Unsafe!)" option is available to override this.
  • Separation of duties — the public key that verifies /boot signatures is stored in CBFS (ROM). The private key that signs /boot stays on a USB security dongle and never leaves it.
  • Auditability — all source is open, builds are reproducible, ROM images are verifiable

Purism boot modes

Purism developed and upstreamed two boot enforcement modes for Heads as part of PureBoot (their integrated stack of coreboot + TPM + Heads + USB security dongle + LUKS). The modes are mutually exclusive and configurable via Options → Change Configuration Settings in config-gui.sh:

Mode Config Boot script Behavior
Normal (default) gui-init.sh Full GUI, hash verification, TPM checks, HOTP/TOTP, USB dongle, unsafe boot available
Basic CONFIG_BASIC=y gui-init-basic.shbasic-autoboot.sh /init overrides CONFIG_BOOTSCRIPT. No signature checks, no dongle, no HOTP. Auto-boots first OS entry.
Restricted CONFIG_RESTRICTED_BOOT=y gui-init.sh Same as Normal but: failsafe boot disabled, recovery console blocked, unsigned USB blocked. When disabled, erases TOTP/HOTP secret in TPM and reflashes.

Flash write protection

The SPI flash ROM is locked against writes via Intel chipset-level PR0 lockdown just before kexec. Coreboot prepares the SPI controller for SMM-initiated locking; Heads triggers the lock via io386 SMI:

kexec-boot.sh → lock_chip.sh → io386 0xb2 0xcb → SMI → FLOCKDN
                                                    └─ PR0 locked,
                                                       flash read-only
                                                       until reset

This is x86/Intel only — QEMU (emulated), Talos II (POWER9), Librem L1UM, and AMD-based boards (KGPE-D16) lack Intel chipset locking. 29 Intel boards across all generations from Sandy Bridge to Alder Lake use this mechanism.

See wp-notes.md for the full config requirements, runtime chain details, and board-level status.

See also: wp-notes.md — per-board write-protection status and tracking.