// guide

Features

What Visor does, and how each piece behaves.

Modular builds

Since 1.5.6 Visor is assembled from a registry of named features: every optional capability is a build-time switch, so you compile exactly the manager you want — from a tiny text-only booter to everything below. The feature list lives in features/features.json; each feature has a blurb, a stub (a no-op compile unit used when the feature is off, so the build always links), deps (features it requires), and a config list of boot.conf keys it brings in.

The graphical menu renders into a full-screen back buffer and presents via GOP — no flicker, ever. Selection changes slide and cross-fade, pages flip with an animation, and the whole screen fades in and out around boot. The selection highlight can be a flat rounded card or a frosted-glass blur. Entries beyond entries_per_page paginate with chevron indicators. A text-mode menu (text_menu=1) covers headless setups and firmware that refuses graphics — Visor falls back to it automatically.

Auto-detection (no boot.conf)

With no config, Visor builds the menu itself. Scan order, across every readable volume (by default — scan=quick restricts the walk to the volume Visor booted from plus the ESPs and any XBOOTLDR /boot partitions, widening back to a full scan if it finds nothing):

  1. Windows Boot Manager\EFI\Microsoft\Boot\bootmgfw.efi and friends.
  2. BLS entries\loader\entries\*.conf (systemd-boot style), including sort tries/ostree indexes.
  3. UKIs — every *.efi in \EFI\Linux.
  4. Raw kernelsvmlinuz*/bzImage* in \boot, \@\boot, and the volume root, each paired with its initramfs. This scan always runs (a UKI does not hide your plain kernels); it is only skipped when BLS entries already reference the same files.
  5. Distro loaders\EFI\<distro>\{shimx64,grubx64}.efi, as a last resort.

Automatic kernel cmdline

A detected raw kernel still needs root= to reach userspace, so Visor derives an accurate cmdline at boot, with no sidecar file, from the first available source:

  1. UKI .cmdline section — a UKI in \EFI\Linux embeds the distro's complete cmdline (root UUID, btrfs rootflags=subvol=, crypt flags). Visor parses the PE section table and reuses it.
  2. /etc/fstab — on any volume the firmware can read (e.g. via an EfiFs driver), the / line supplies the exact root spec and btrfs subvolume flags, honoring ro.
  3. GPT root partition type — the Discoverable Partitions root GUID for the build architecture yields root=PARTUUID=… rw, straight from the partition table via BlockIo — no filesystem access at all.

The boot log records which source was used and the exact line derived.

Live USB hotplug

When the menu is armed, Visor first scans all volumes that are already connected (including USB sticks that were plugged in before the menu appeared). It then watches for volumes that appear later and adds their entries live — the new icon fades and scales in while the existing row slides over. Entries are pinned to the stick's partition GUID and volume handle, so files load from the stick that brought them. Unplugging reverses it: the entries leave and the surviving icons slide back together. Replug never duplicates. Hotplugged and pre-connected volumes derive cmdlines only from sources on the stick itself. Disable with hotplug=0. The setting scan_existing=1 forces scanning of pre-connected volumes even when boot.conf has manual entries.

Btrfs snapshots

Press V to open the snapshot panel for the selected Linux entry and boot any snapshot once. Sources, in order:

  1. \EFI\visor\snapshots.conf, generated on the host by tools/visor-snapshot-sync — carries exact per-snapshot cmdlines/kernels, supports multiple OSes. Visor also reads \EFI\visor\snapshot.conf (singular) as a fallback.
  2. Direct btrfs detection (needs the btrfs EfiFs driver): snapper's .snapshots/N/snapshot, Timeshift's timeshift-btrfs/snapshots/<ts>/@, and named subvolumes under .snapshots, snapshots, @snapshots.

The scanner rewrites the entry's rootflags=subvol= to the snapshot subvolume and shows the newest twelve. Visor never makes a snapshot writable or performs a rollback — your initramfs must support the distro's read-only snapshot workflow. snapshots = 0 | manifest | 1 selects the mode.

Animated backgrounds

background= accepts PNG and BMP for static wallpapers, plus GIF and MP4/MOV (MJPEG) for animated looping wallpapers. The decoders are self-contained — GIF89a (LZW, disposal, loops) and MJPEG MP4 (bounded decode, loop budget) — with bounded memory; the accent palette is taken from frame one and the frosted-glass panels reuse their blur while the animation plays so the menu stays fast. Frames advance on a wall-clock schedule that drops time on a slow redraw instead of spiralling, and the animation stops cleanly when its loop budget is spent. For best results use the compact VBG format via visor convert --vbg — it is ~10–20× smaller than MJPEG and decodes cheaper at boot.

Tip — try background=\EFI\visor\backgrounds\witch.vbg from the gallery; it is a tiled-quantized delta stream with motion compensation that stays smooth even on slow firmware GOPs.

Live clock

A firmware-RTC clock rendered as a live overlay outside the selection cache — it ticks without forcing a full redraw. Configure with clock / show_clock (unified colorSpec: 0, 1, a palette role or #RRGGBB), clock_size, clock_format (24h/12h), clock_seconds, clock_position (topright, bottomleft, center … hyphens/spaces equivalent, auto-avoids the centered header), plus clock_date/clock_date_format (long, iso, dmy, mdy) and decoration clock_blur (frosted backing) / clock_shadow. See Configuration → Clock.

Screensaver

Two stages while the graphical menu is idle: after screensaver_delay (default 60 s) the UI cross-fades to the bare background (plus the clock if screensaver_clock=1); after screensaver_blank (default 600 s) the panel blanks to black and the render loop idles. The next key or pointer move cross-fades back and restarts the boot countdown so a stray key never instantly boots. Idle is suspended during the countdown, the command-line editor and the file browser. Animated wallpapers keep playing while dimmed, and are fully idle while blanked.

Enable with screensaver=1 or the shorthand screensaver=60 (on with 60 s delay). Configuration → Screensaver lists all keys.

Boot sound (built-in HDA audio)

Visor bundles a self-contained Intel HD Audio driver that plays a short sound at startup before the OS takes over — no external driver and no dependence on the OS having configured audio. It is built for the common case of a small menu_sound sting or a bundled occasional flash moment; see Architecture → Audio for how it fits the boot flow and Configuration → Sound for the key.

TPM2 measured boot

When a EFI_TCG2_PROTOCOL is present Visor measures the on-disk boot.conf into PCR 5 and the booted kernel command line (including its terminating NUL) into PCR 12 via HashLogExtendEvent, matching systemd's tpm_log_load_options layout so a sealed policy stays portable. The active PCR banks are published as volatile LoaderTpm2ActivePcrBanks and advertised in LoaderFeatures. Configure with tpm / measure and tpm_pcr_config / tpm_pcr_cmdline (0–23). Set tpm=0 to skip entirely.

Boot Loader Interface

Visor speaks the systemd Boot Loader Interface (vendor GUID 4a67b082-0a4c-41cf-b6c7-440b29bb8c4f). When loader_vars=1 (default, alias loader_interface) it publishes LoaderInfo, LoaderFirmwareInfo/Type, LoaderDevicePartUUID, LoaderImageIdentifier, LoaderFeatures, LoaderEntries, LoaderTimeInitUSec/MenuUSec/ExecUSec, LoaderTpm2ActivePcrBanks, and honors LoaderConfigTimeout / LoaderConfigTimeoutOneShot and LoaderEntryDefault / LoaderEntryOneShot (one-shot vars are consumed whether or not they match). One-shot is the one-boot mechanism for OS agents like bootctl and systemd-bless-boot. Disable all of it with loader_vars=0.

Accent colors (Material You)

With accent=1, Visor extracts a seed color from the wallpaper — Celebi quantization then scoring, the same pipeline as Android's Material You — and builds a tonal palette used for icons, underline, and text. Variants: tonal, vibrant, expressive, fidelity, content, neutral, monochrome (accent_variant=). The whole HCT/CAM16 color pipeline runs in Q16 fixed-point integer math (firmware has no floating point) and tracks the reference Material You implementation closely — chromatic wallpapers match hue within half a degree.

Immutable distros & OSTree

BLS configs from OSTree-based systems (Fedora Silverblue/Kinoite, etc.) are grouped into one entry per OS with a version panel: V cycles deployments (current, rollback, pinned), so an atomic system shows one clean icon instead of three near-identical entries.

Non-FAT filesystems

UEFI firmware only reads FAT. To auto-detect kernels living on ext4, btrfs, xfs, and friends, Visor loads EfiFs drivers from \EFI\visor\drivers\. The installer (and visor drivers) detects the /boot filesystem and downloads the matching driver — pinned to a fixed EfiFs release and SHA-256 verified. Drivers are deferred: loaded at startup but only started when a file actually needs them or the fast scan finds nothing, keeping the menu at ~1 second even with the btrfs driver installed.

File browser

Press B at the menu — or run browse [PATH] in the recovery shell — to open a full-screen browser over every readable volume. The boot volume comes first; others are labelled by partition UUID. Entries show sizes and sort directories-first, case-insensitively, with a merge sort, so even very large directories don't stall the menu.

Booting from the browser is a one-shot override: a kernel boots with a sibling initrd* paired automatically, an initrd sets the initrd override, and a .efi is chainloaded. The load is pinned to the volume the file was picked from (partition GUID and volume handle), so an MBR stick without a GUID can't be answered by a same-named file on the ESP. Rough edges: booting needs a selected entry to attach the override to, very slow USB media can make large listings take a moment, and filesystems without a loaded driver (ext4 without the EfiFs driver) don't appear in the browser.

Windows

Windows entries chainload bootmgfw.efi by device path, so BitLocker and the BCD store behave exactly as if the firmware had booted Windows directly. If an entry has no kernel path at all, Visor searches for the Windows Boot Manager across volumes (honoring the uuid= pin).

Editing & recovery

When a LUKS entry (luks=1) is selected, Visor shows a passphrase prompt. F2 toggles showing what you typed (check your keyboard layout). luks_confirm=1 requires typing the passphrase twice — a mismatch reprompts instead of booting. luks_verbose=1 removes quiet splash from the cmdline so the initramfs retry prompt is visible when a passphrase is rejected.

Immunity to Windows

Two layered defences that take over where OS updates like to break things: Visor repairs the boot entry and fallback path that Windows routinely rewrites, and it catches and fixes corrupted GPT tables before they strand a disk.