Skip to content

Latest commit

 

History

History
159 lines (114 loc) · 5.65 KB

File metadata and controls

159 lines (114 loc) · 5.65 KB

Heads Boot Process

This document describes the complete boot flow from power-on to OS handoff.

See also: architecture.md for component overview, tpm.md for TPM PCR details, security-model.md for the trust model.


Overview

Power-on
  │
  ▼
coreboot (SPI flash)
  │  hardware init, SRTM measurement into PCR 2
  ▼
Linux kernel (coreboot payload, no initramfs)
  │
  ▼
/init  ← first userspace process
  │  mount filesystems, load config, combine user overrides
  ▼
/bin/gui-init  ← main interactive boot loop
  │  TPM preflight, GPG key check, TOTP/HOTP attestation
  ▼
kexec-select-boot
  │  verify /boot hashes + GPG signature, rollback counter
  ▼
kexec  ← hands off to OS kernel

Stage 1: /init

/init is the first userspace process. It:

  1. Mounts virtual filesystems (/dev, /proc, /sys).
  2. Loads board defaults from /etc/config and the functions library.
  3. Runs cbfs-init to extract user configuration from CBFS into /etc/config.user.
  4. Calls combine_configs() to merge all /etc/config* files into /tmp/config, then sources /tmp/config so all subsequent scripts see the merged settings.
  5. Checks for a quick r keypress (100 ms timeout) to drop to a recovery shell before any GUI starts.
  6. Execs cttyhack $CONFIG_BOOTSCRIPT (default: /bin/gui-init), which sets up a controlling TTY and hands off to the boot script.

Config file merge

/etc/config          (ROM, board defaults)
/etc/config.user     (CBFS, user overrides)
        │
        └─► combine_configs() ─► /tmp/config  (runtime, sourced by all scripts)

User settings appear last in the concatenation and therefore override board defaults. Changes are persisted by reflashing CBFS.


Stage 2: /bin/gui-init

gui-init is the main interactive boot agent. It runs as an infinite loop and handles all user interaction until the OS is handed off via kexec.

Initialization

On startup, gui-init detects the controlling TTY (set by cttyhack in /init) and exports it as HEADS_TTY and GPG_TTY. This ensures that all interactive prompts and GPG operations reach the correct terminal regardless of stdout/stderr redirections.

TPM rollback preflight

Before showing any menu, gui-init verifies that the TPM rollback counter is consistent with /boot/kexec_rollback.txt. An inconsistency indicates either a TPM reset (expected: user must re-seal secrets) or an unexpected state (possible tampering). On failure, the main menu background is set to error color and the user is offered recovery options.

GPG key check (check_gpg_key)

gui-init counts the keys in the GPG keyring. An empty keyring means no /boot signature can be verified. The user must add a key or perform OEM Factory Reset before booting.

TOTP generation (update_totp)

unseal-totp retrieves the TOTP secret from TPM NVRAM and generates the current 30-second code. If the unseal fails (PCR mismatch, TPM reset, tampered firmware), INTEGRITY_GATE_REQUIRED is set to y, which blocks all subsequent TPM secret sealing until an integrity check passes. See security-model.md.

HOTP / hardware token check (update_hotp)

If a hardware HOTP token is present (/bin/hotp_verification), gui-init obtains the HOTP secret (unsealed from TPM on boards with a TPM; derived from a ROM hash on boards without one) and asks the token to verify the current code. Result codes: 0 = success, 4 = wrong code, 7 = not a valid HOTP value. See security-model.md for the no-TPM path.

Auto-boot

If HOTP succeeded and CONFIG_AUTO_BOOT_TIMEOUT is set, a countdown starts and the default boot entry is selected automatically if the user does not intervene.

Main menu loop

show_main_menu displays the current date, TOTP code, and HOTP status in the menu title bar. The background color reflects the current integrity state (normal / warning / error). Options: default boot, refresh TOTP/HOTP, options menu, system info, power off.


Stage 3: kexec-select-boot

Called from the boot menu. Responsible for final verification and OS handoff.

TPM2 primary key hash check

For TPM2 systems, verifies the SHA-256 hash of the TPM2 primary key handle against /boot/kexec_primhdl_hash.txt (if the file exists). A mismatch means the TPM2 primary key was regenerated without updating the stored hash.

Boot hash verification (verify_global_hashes)

verify_checksums checks the SHA-256 of every /boot file against kexec_hashes.txt, then verifies kexec.sig with gpgv. A hash mismatch or invalid signature causes die — there is no "boot anyway" path.

Optionally, root partition hashes are also checked if CONFIG_ROOT_CHECK_AT_BOOT=y.

Rollback counter verification (verify_rollback_counter)

The TPM monotonic counter index is read from /boot/kexec_rollback.txt and the counter is read from the TPM. The SHA-256 of the counter file is then checked against the hash stored in kexec_rollback.txt. Any discrepancy aborts the boot.

OS boot execution (do_boot)

If a TPM-sealed LUKS Disk Unlock Key (DUK) is configured, kexec-insert-key unseals the DUK and injects it into a minimal initrd prepended to the OS initrd. The OS kernel then finds the key and unlocks LUKS without prompting the user.

kexec-boot performs the final kexec system call to hand off to the OS kernel.


Recovery shell

The recovery shell is an authenticated environment. Entering it extends TPM PCR 4 with "recovery", permanently invalidating TOTP/HOTP/LUKS unseal for the rest of the boot session. See tpm.md.