// internals

Architecture

How ~20k lines of freestanding C become a boot menu.

Boot flow

firmware ─▶ efi_main (src/core/main.c)
              │  arch_clock_init(), loader_mark_init() → LoaderTimeInitUSec
              │  init gnu-efi, open boot.log
              ├─ GUI init: locate GOP, pick mode, allocate back buffer,
              │            make framebuffer write-combining (arch_*)
              ├─ load EfiFs drivers from \EFI\visor\drivers (deferred start)
              ├─ config_parse(\EFI\visor\boot.conf)
              │     └─ missing? detect_entries(): BLS ▸ Windows ▸ UKIs ▸
              │        raw kernels (+ cmdline derivation) ▸ vendor loaders
              ├─ tpm_init() → measure boot.conf (PCR 5); publish Loader* vars
              │              LoaderDevicePartUUID / LoaderImageIdentifier /
              │              LoaderInfo / FirmwareInfo / LoaderFeatures /
              │              LoaderEntries; apply LoaderEntryDefault/OneShot &
              │              LoaderConfigTimeout overrides (consume OneShot)
              ├─ load background (PNG/BMP/GIF/MP4→VBG), decode icons,
              │  accent_generate() from frame 0, arm hotplug watch
              ├─ gui_run(): event loop — input, animation inc. clock 1 Hz band,
              │             mouse, hotplug poll, timeout, editor, snapshot panel,
              │             screensaver (dim → blank), video frame scheduler
              │             loader_mark_menu() → LoaderTimeMenuUSec
              ▼
        entry selected
              │  (password prompt if encrypted/LUKS)
              ├─ tpm_measure_cmdline() → PCR 12, loader_mark_selected()
              │  → LoaderEntrySelected + LoaderTimeExecUSec
              ├─ visor_boot (src/boot/linux_boot.c)
              │     ├─ read image (uuid-pinned volume first)
              │     ├─ VISORENC decrypt + HMAC verify, sha256= pin check,
              │     │  SHIM_LOCK verify under Secure Boot
              │     ├─ PE image  ─▶ LoadImage(device path) ─▶ cmdline via
              │     │  LoadOptions, initrd via LINUX_EFI_INITRD_MEDIA
              │     │  (LoadFile2), LUKS keyfile cpio appended ─▶ StartImage
              │     └─ raw kernel ─▶ x86-64 EFI handover protocol
              ▼
        control transfers — or on failure: recovery console

Module map (src/)

Sources are clustered by domain; modules that ship inside a feature live in that feature's cluster and compile a no-op stub from src/stubs/ when the feature is off. Public types live in src/include/, shared internals in *_internal.h headers next to their cluster.

FileRole
core/main.cEntry point and orchestration: init, config, GUI loop, password capture, boot dispatch, recovery console; early loader_mark_init() and tpm_init().
config/config.c + config_*.cboot.conf parser (unified colorSpec grammar, file-syntax from boot.conf.schema.json), theme loading, BLS parsing (config_bls.c), entry auto-detection (config_discover.c), cmdline derivation (UKI section / fstab / GPT, config_cmdline.c), snapshot sources, live hotplug scan/poll (config_hotplug.c), LUKS (config_luks.c), recovery (config_recovery.c), key schema (config_keys.c).
gui/gui.c + gui_*.cThe renderer: back buffer, partial-redraw bands, text, PNG icons, blur, animations (selection, page flip, fades, hotplug pop-in/out), mouse, editor overlay, snapshot/version panels, scene cache (gui_blur.c, gui_card.c, gui_draw.c, gui_fade.c, gui_image.c, gui_menu.c, gui_panels.c, gui_run.c, gui_text.c…). Live clock overlay (1 Hz band, frost/shadow, header-aware layout), screensaver state machine (dim → blank) with video-aware idle handling (gui_clock.c, gui_screensaver.c), and sound_start/sound_poll hooks so the boot sound starts with the fade-in.
text/text_menu.cText-mode menu with the same feature set minus pixels (also respects Loader timeout overrides); config_gpt equivalents in text_gptcmd.c. A standalone text_recovery.c backs the text-mode recovery console.
boot/linux_boot.cBoot engine: file loading, decryption hooks, verification, PE LoadImage/StartImage path, LoadFile2 initrd serving, LUKS keyfile injection, x86-64 EFI handover, Windows chainload; plus tpm_measure_cmdline() before hand-off. File/initrd plumbing split into linux_file.c, linux_initrd.c, linux_rawboot.c.
boot/windows_boot.cbootmgfw.efi discovery across volumes.
core/efi_*.cWrappers over UEFI protocols: file I/O (uuid-pinned volume resolution, efi_file.c), device paths (efi_path.c), handle/partition GUID matching, logging (efi_log.c), Secure Boot state, pool helpers, NVRAM vars (efi_var.c), driver loading (efi_fsdrv.c), and boot-entry self-heal (efi_selfheal.c) — plus Boot Loader Interface helpers.
security/crypto.cVISORENC v2: PBKDF2-HMAC-SHA256, ChaCha20, HMAC verification, secure wipe.
security/sha256.c / hash_verify.c / luks_keyfile.c / tcg2.cSHA-256, the sha256= image pin, LUKS keyfile injection, and TPM2 measured boot (EFI_TCG2_PROTOCOL: PCR 5 config / PCR 12 cmdline, LoaderTpm2ActivePcrBanks).
decoders/png_decoder.cSelf-contained PNG (and BMP) decoder with decode budgets.
decoders/gif_decoder.cGIF89a decoder (LZW, disposal, loop handling, bounded memory) — supplies frames for animated backgrounds.
decoders/mp4_decoder.c + vbg_decoder.c / anim.c / mjpeg_decoder.cMJPEG MP4/MOV decoder plus VBG (tiled-quantized delta + motion compensation) — loop budget, bounded scratch, drops time on slow redraws; frame scheduling in anim.c.
audio/hda.cBuilt-in Intel HD Audio driver for the boot sound: HDA controller programming, widget walk, jack-presence detection, pin scoring (headphones before built-in speakers), muting of other output pins sharing a converter, and a split prepare/start/done playback flow. AArch64 builds compile to stubs.
audio/menu_sound.c / rbd.cBoot-sound PCM helpers (resample, trim, single-play prepared stream) and the RBD easter-egg audio pipeline; owns the bundled PCM audio blob.
gpt/gpt.c + friendsGPT scan (gpt.c), diagnosis (gpt_diagnose.c), primary/backup repair (gpt_repair.c), and text-mode commands (text_gptcmd.c); core/gpt_disk.c maps whole-disk block devices.
browse/filebrowse.c / text_browse.cFile browser (GUI / text): volume enumeration, directory merge-sort, pinned-volume loads, one-shot boot overrides.
capture/capture.c + friendsScreenshot / F10 animation capture (capture_png.c for F6, capture_gif.c, capture_file.c).
gui/accent.c (+ gui_accent.c)Material You palette extraction: Celebi quantizer, HCT/CAM16 color space, scoring, palette variants — all Q16 fixed-point; includes the clock role.
gui/font_jetbrains.cPre-baked JetBrains Mono glyph bitmaps (generated by tools/bake_font.py).
arch/arch_x86_64.c / arch/arch_aarch64.cArchitecture layer behind include/arch.h: monotonic clock (calibrated TSC / generic timer, arch_clock_init / arch_now_us / efi_get_tick) and framebuffer write-combining (MTRR+PAT / EFI CPU protocol).
stubs/No-op stub_*.c units swapped in for features that are off, so the build always links.
include/Public headers; gui.h holds the central boot_entry_t and gui_state_t types (with clock_*, screensaver and sound_* fields); hda.h/menu_sound.h/rbd.h declare the audio API, *_internal.h the shared private headers.

The rendering pipeline

Everything draws into a full-screen 32-bit back buffer, then blits to the framebuffer. On x86_64 the framebuffer is mapped write-combining via MTRR and a PAT slot; on AArch64 via the EFI CPU Architecture Protocol — this is the difference between a 2 ms and a 200 ms present on real hardware. Redraws are banded: only the horizontal strips that changed (icon row, title, info line) are recomposed and blitted each frame. Static pixels (background, title, power actions) live in a scene cache. Animations interpolate a small set of scalar targets (card position, underline, page cross-fade, hotplug offsets) with a smoothstep easing, at integer millisecond timing from the arch clock.

The clock lives outside the scene cache as a live overlay: it repaints only its own band on a 1 Hz tick (or every second with clock_seconds=1), with header-aware placement, optional frost and shadow. The screensaver is a two-stage state machine (idle → dim → blank) that composes a saver frame (background + optional clock) and cross-fades via gui_crossfade; while blanked the decoder and scheduler are idle and the cursor backing store is dropped so no ghost remains. MJPEG/VBG video frames advance on a wall-clock budget that drops time on slow redraws; frost panels reuse the blur cache while the animation plays.

Audio

Audio runs through a small built-in Intel HD Audio driver (src/audio/hda.c). It is a two-phase job: hda_play_prepare() opens the controller and codec and begins streaming, and a separate hda_play_start() actually unmutes at the moment the boot sound should be heard, so the sound and the menu fade-in are simultaneous. hda_play_done() drains the stream and stops it once the audible end is reached; the buffer is padded with silence so DMA never wraps and replays the clip.

The driver walks the codec widget graph to find usable analog output pins. With jack-presence support it scores each pin — a plugged-in headphone outranks a fixed line-out, both outrank the built-in speaker, and a live HDMI/DP pin loses to all analog options. When two output pins share a converter, the non-selected one is muted for the duration (silence_other_outputs()) and restored in hda_cleanup(). On AArch64 the same symbols compile to no-op stubs. Visor plays before ExitBootServices, so it never touches the OS's audio state.

Firmware constraints the code lives under

Key design decisions

Repository layout

bootloader/
├── src/               firmware C sources, clustered by domain (arch/,
│                      audio/ boot/ browse/ capture/ config/ core/,
│                      decoders/ gpt/ gui/ security/ text/) + stubs/
│                      + include/ + linker scripts
├── features/          feature registry (features.json) and Makefile hook
├── assets/            default icons and backgrounds (PNG)
├── tools/             host-side tools (encrypt, font baking, snapshot
│                      sync, aarch64 gnu-efi setup, feature checks)
├── docs/              screenshots
├── Makefile           x86_64 + aarch64 builds, profiles & features
├── install.sh · get.sh · visor    installer, bootstrapper, host CLI
└── boot.conf.example  fully-commented config reference