mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 18:42:21 +00:00
CONFIG.md documents every section of sprout.toml, the command line options, BLS support and strict mode. The README keeps the overview and minimal examples and links to it. Adds an update-config-docs skill to keep the reference in sync with the code.
577 lines
29 KiB
Markdown
577 lines
29 KiB
Markdown
# Configuring Sprout
|
|
|
|
Sprout reads a TOML file, `\sprout.toml`, from the root of the EFI partition it was loaded from. This page
|
|
covers everything that file can hold, the command line options that override it, and the BLS behavior that
|
|
sits next to it. For installing Sprout, see the [setup guides](./docs/setup).
|
|
|
|
- [Command line options](#command-line-options)
|
|
- [The file at a glance](#the-file-at-a-glance)
|
|
- [Values](#values)
|
|
- [`options`](#options)
|
|
- [`menu-styles`](#menu-styles)
|
|
- [`drivers`](#drivers)
|
|
- [`extractors`](#extractors)
|
|
- [`actions`](#actions)
|
|
- [`entries`](#entries)
|
|
- [`generators`](#generators)
|
|
- [`phases`](#phases)
|
|
- [Autoconfiguration](#autoconfiguration)
|
|
- [Bootloader Specification support](#bootloader-specification-support)
|
|
- [Strict mode](#strict-mode)
|
|
|
|
Sprout reads the file once at startup. A key it doesn't know is ignored with a warning that names the key, so
|
|
a typo shows up in the boot log instead of silently doing nothing. A `version` other than `1` stops Sprout.
|
|
|
|
## Command line options
|
|
|
|
These are passed to `sprout.efi` as load options, which is how GRUB or `efibootmgr` hand them over. They
|
|
override the matching setting in the file.
|
|
|
|
| Option | What it does |
|
|
|---------------------------|-----------------------------------------------------------------------------|
|
|
| `--config=PATH` | Load a configuration file other than `\sprout.toml`. |
|
|
| `--autoconfigure` | Skip the configuration file and build one from what Sprout finds. |
|
|
| `--boot=ENTRY` | Boot an entry without showing the menu. See [entries](#entries) for matching. |
|
|
| `--force-menu` | Show the menu even when `--boot` picked an entry. |
|
|
| `--menu-style=STYLE` | `basic`, `simple` or `graphical`. |
|
|
| `--menu-timeout=SECONDS` | How long the menu waits before booting the default entry. |
|
|
| `--retain-boot-console` | Don't clear the screen before handing off to the entry. |
|
|
| `--bls-strict-mode` | Turn on [strict mode](#strict-mode). |
|
|
| `--help` | Print the options. |
|
|
|
|
```bash
|
|
# Boot a specific configuration file.
|
|
$ sprout.efi --config=\path\to\config.toml
|
|
# Boot "Boot Xen" at once, but only show the menu if it can't be found.
|
|
$ sprout.efi --boot="Boot Xen"
|
|
# Show the graphical menu for 10 seconds.
|
|
$ sprout.efi --menu-style=graphical --menu-timeout=10
|
|
```
|
|
|
|
An argument Sprout can't parse is dropped with a warning and the rest are used, since a typo in a boot
|
|
entry shouldn't leave a machine unbootable.
|
|
|
|
## The file at a glance
|
|
|
|
Every section is optional. An empty file is a valid configuration that has no entries.
|
|
|
|
```toml
|
|
version = 1
|
|
|
|
[options] # settings for Sprout itself
|
|
[menu-styles.x] # settings for a style of menu
|
|
[values] # named strings for use anywhere with $name
|
|
[drivers.x] # EFI drivers to load
|
|
[extractors.x] # values worked out at boot
|
|
[actions.x] # things Sprout can do
|
|
[entries.x] # items in the boot menu
|
|
[generators.x] # makes entries from data
|
|
[[phases.early]] # actions to run at set points
|
|
```
|
|
|
|
The pieces fit together like this: an **entry** is a menu item that runs **actions**; an action is configured
|
|
with strings that can contain **values**; values come from the `[values]` table, from **extractors**, and
|
|
from **generators**. **Drivers** run first so the filesystems the rest of the file points at exist.
|
|
|
|
Order at boot:
|
|
|
|
1. `phases.early`
|
|
2. drivers load
|
|
3. autoconfiguration, if enabled
|
|
4. extractors run
|
|
5. `phases.startup`
|
|
6. entries and generators produce the menu
|
|
7. an entry is chosen
|
|
8. `phases.late`, then the entry's actions
|
|
|
|
## Values
|
|
|
|
A value is a named string. Anywhere a string is accepted in an entry, action, driver path or phase, `$name`
|
|
is replaced with the value called `name`.
|
|
|
|
```toml
|
|
[values]
|
|
root-options = "root=/dev/sda2 ro"
|
|
kernel = "\\vmlinuz"
|
|
|
|
[actions.boot]
|
|
chainload.path = "$kernel"
|
|
chainload.options = ["$root-options", "quiet"]
|
|
```
|
|
|
|
Some details that matter in practice:
|
|
|
|
- Values can refer to other values. Sprout keeps substituting until nothing changes, so
|
|
`a = "$b"`, `b = "x"` gives `x` for both. A value that never settles, such as one that contains itself,
|
|
is an error once it hits an iteration or length limit.
|
|
- When two keys share a prefix, the longer one wins, so `$kernel-options` is never read as `$kernel` plus
|
|
`-options`.
|
|
- A `$name` that has no value is left in the string as written.
|
|
- Values are layered. A key in a generator or entry overrides the same key set globally, and only for that
|
|
entry. From weakest to strongest: `[values]`, extractor results, generator values (and `variants`), then the
|
|
`values` of the entry itself.
|
|
- Windows-style paths need doubled backslashes in TOML strings: `"\\EFI\\Linux"`. Literal strings
|
|
(`'\EFI\Linux'`) work too.
|
|
|
|
## `options`
|
|
|
|
```toml
|
|
[options]
|
|
default-entry = "boot-linux"
|
|
menu-timeout = 5
|
|
menu-style = "graphical"
|
|
autoconfigure = false
|
|
bls-strict-mode = false
|
|
```
|
|
|
|
| Key | Type | Default | Meaning |
|
|
|-------------------|---------|----------|-------------------------------------------------------------------------|
|
|
| `default-entry` | string | none | The entry that is selected first, and booted when the timeout ends. Without it, the first entry in the menu is. |
|
|
| `menu-timeout` | integer | see below | Seconds to show the menu before booting the default entry. |
|
|
| `menu-style` | string | `simple` | `basic` prints entries and takes a number. `simple` is a full-screen list moved with the arrow keys. `graphical` is a menu drawn on the screen (the mouse is off unless you enable it, see [`menu-styles`](#menu-styles)). |
|
|
| `autoconfigure` | boolean | `false` | Add entries for what Sprout finds. See [autoconfiguration](#autoconfiguration). |
|
|
| `bls-strict-mode` | boolean | `false` | See [strict mode](#strict-mode). |
|
|
|
|
When `menu-timeout` is not set anywhere, the menu shows for 10 seconds, or is hidden in strict mode. The
|
|
sources are ranked in [The bootloader interface](#the-bootloader-interface).
|
|
|
|
## `menu-styles`
|
|
|
|
Settings for a particular menu style. Only the graphical menu has any.
|
|
|
|
```toml
|
|
[menu-styles.graphical]
|
|
enable-mouse = true
|
|
```
|
|
|
|
| Key | Type | Default | Meaning |
|
|
|----------------|---------|---------|----------------------------------------------------------------------|
|
|
| `enable-mouse` | boolean | `false` | Select entries with the mouse and show the cursor. Without it, or when the firmware has no pointing device, the menu takes the keyboard only. |
|
|
|
|
## `drivers`
|
|
|
|
Drivers are EFI executables that add features, most often a filesystem driver for something the firmware
|
|
can't read, such as ext4. Each is started once and expected to return. Afterwards Sprout reconnects every
|
|
controller so the new filesystems appear. Drivers have no defined load order.
|
|
|
|
```toml
|
|
[drivers.ext4]
|
|
path = "\\sprout\\drivers\\ext4.efi"
|
|
```
|
|
|
|
| Key | Meaning |
|
|
|--------|--------------------------------------------------------|
|
|
| `path` | Path to the driver image. Required. Can use values. |
|
|
|
|
The name (`ext4` above) is only for error messages and doesn't have to match the file.
|
|
|
|
## `extractors`
|
|
|
|
An extractor works out a value when Sprout boots, so a configuration doesn't need to hardcode where things
|
|
are. The name of the extractor is the name of the value it sets.
|
|
|
|
There is one kind, `filesystem-device-match`, which finds a filesystem and returns its device root. The
|
|
result has a trailing slash, so you append a path to it directly: `$boot\\vmlinuz`.
|
|
|
|
```toml
|
|
[extractors.boot]
|
|
filesystem-device-match.has-label = "BOOT"
|
|
filesystem-device-match.fallback = "PciRoot(0x0)/Pci(0x1,0x1)/Sata(0,0,0)/HD(1,GPT,c2a4f1b6-0000-0000-0000-000000000000)/"
|
|
```
|
|
|
|
| Key | Meaning |
|
|
|--------------------------|----------------------------------------------------------------------|
|
|
| `has-label` | The filesystem volume label equals this. |
|
|
| `has-item` | This file or directory exists on the filesystem. |
|
|
| `has-partition-uuid` | The unique GUID of the partition. |
|
|
| `has-partition-type-uuid`| The partition type GUID, such as the one for XBOOTLDR. |
|
|
| `fallback` | What to use when no filesystem matches. Without it, no match is an error. |
|
|
|
|
Every criterion you give must match, and you must give at least one. The first matching filesystem wins.
|
|
`has-label` and `has-item` can use values.
|
|
|
|
## `actions`
|
|
|
|
An action is a named, configured piece of work. Entries and phases refer to actions by name, and an action
|
|
can be used by as many of them as you like.
|
|
|
|
Each action sets exactly one of `chainload`, `print` or `edera`. If you set more than one Sprout warns and
|
|
uses the first of them in that order.
|
|
|
|
### `chainload`
|
|
|
|
Loads and starts another EFI image. That covers Linux through its EFI stub, Windows, and any other EFI
|
|
application. If the image returns, Sprout returns to its own flow.
|
|
|
|
```toml
|
|
[actions.boot-linux]
|
|
chainload.path = "\\vmlinuz"
|
|
chainload.options = ["root=/dev/sda1", "quiet"]
|
|
chainload.linux-initrd = "\\initrd"
|
|
```
|
|
|
|
| Key | Type | Meaning |
|
|
|----------------------|-----------------|----------------------------------------------------------------------|
|
|
| `path` | string | The image to start. Required. |
|
|
| `options` | list of strings | Joined with spaces and given to the image as its command line. |
|
|
| `linux-initrd` | string | One initrd, handed to the Linux EFI stub through the initrd media loader. |
|
|
| `linux-initrd-chain` | list of strings | Several initrds, concatenated in order into one. Can't be used together with `linux-initrd`. |
|
|
| `devicetree` | string | A flattened devicetree to install until the image returns. |
|
|
|
|
Notes:
|
|
|
|
- `linux-initrd` is better than an `initrd=` option, because it doesn't depend on the stub resolving a path.
|
|
- Entries in `linux-initrd-chain` that are empty after substitution are skipped, which is what makes a
|
|
chain with spare slots safe.
|
|
- The devicetree is ignored with a warning when Secure Boot is on, as Sprout can't verify it. If it can't be
|
|
installed, Sprout warns and boots without it, unless [strict mode](#strict-mode) is on.
|
|
- When the image is a Windows boot manager or another non-Linux image, leave the initrd keys out.
|
|
|
|
### `print`
|
|
|
|
Writes a line to the console. It's mostly for phases, such as a message while drivers load.
|
|
|
|
```toml
|
|
[actions.hello]
|
|
print.text = "Booting $version"
|
|
```
|
|
|
|
### `edera`
|
|
|
|
Boots the Edera hypervisor and its root operating system, as an extension of the Xen EFI stub. Sprout hands
|
|
the Xen config, dom0 kernel and optional initrd to Xen as media loaders, then starts Xen.
|
|
|
|
```toml
|
|
[actions.edera]
|
|
edera.xen = "\\EFI\\edera\\xen.efi"
|
|
edera.kernel = "\\EFI\\edera\\kernel"
|
|
edera.initrd = "\\EFI\\edera\\initrd"
|
|
edera.xen-options = ["dom0_mem=512M"]
|
|
edera.kernel-options = ["console=hvc0"]
|
|
```
|
|
|
|
| Key | Type | Meaning |
|
|
|------------------|-----------------|-------------------------------------------------------------|
|
|
| `xen` | string | The Xen EFI image. Required. |
|
|
| `kernel` | string | The dom0 kernel. Required. |
|
|
| `initrd` | string | The dom0 initrd. |
|
|
| `initrd-chain` | list of strings | Several initrds, concatenated in order. Can't be used with `initrd`. |
|
|
| `kernel-options` | list of strings | Command line of the dom0 kernel. |
|
|
| `xen-options` | list of strings | Command line of Xen. |
|
|
|
|
When a TPM is present, the Xen options and dom0 command line are measured into PCR 12, the kernel into
|
|
PCR 11, and the initrd into PCR 9.
|
|
|
|
## `entries`
|
|
|
|
An entry is something the user can pick from the menu. The table name identifies it.
|
|
|
|
```toml
|
|
[entries.boot-linux]
|
|
title = "Boot Linux"
|
|
actions = ["boot-linux"]
|
|
values.kernel = "\\vmlinuz"
|
|
sort-key = "10"
|
|
```
|
|
|
|
| Key | Type | Meaning |
|
|
|------------|-----------------|------------------------------------------------------------------------|
|
|
| `title` | string | The text in the menu. Required, and can use values. |
|
|
| `actions` | list of strings | Actions to run, in order, when the entry is chosen. |
|
|
| `values` | table | Values that exist only for this entry. |
|
|
| `sort-key` | string | Orders the entry in the menu. Compared as versions, not as text, so `10` sorts after `9`. Defaults to the entry's name. |
|
|
|
|
The menu lists entries in reverse sort order, newest first. That is what you want for kernel versions and
|
|
is why `sort-key = "$version"` gives a sensible menu.
|
|
|
|
`--boot` and the bootloader interface find an entry by its name, by its title, or by its position in the
|
|
menu counted from 0. A `*` in the pattern matches anything.
|
|
|
|
If an entry fails Sprout reports the error and waits ten seconds. Then it exits to the firmware, or resets the
|
|
machine when `reboot-on-error` applies (see [boot counting](#boot-counting)).
|
|
|
|
## `generators`
|
|
|
|
A generator makes entries from data when Sprout starts. Each has a kind (`matrix`, `list` or `bls`), and
|
|
optionally `variants` and `exclude`, which work on the result of any kind. Set only one kind per generator.
|
|
|
|
The entries a generator makes are named `<generator>-<n>`, with `n` counting from 0, and a BLS generator
|
|
uses the name of the entry file instead. Every one of them is built from the `entry` template you give,
|
|
which takes the same keys as an [entry](#entries).
|
|
|
|
### `matrix`
|
|
|
|
Makes an entry for every combination of the lists you give.
|
|
|
|
```toml
|
|
[generators.kernels]
|
|
matrix.entry.title = "Boot $kernel with $console"
|
|
matrix.entry.actions = ["boot-kernel"]
|
|
matrix.values.kernel = ["\\vmlinuz", "\\vmlinuz-lts"]
|
|
matrix.values.console = ["ttyS0", "tty0"]
|
|
```
|
|
|
|
That is four entries. A list of two and a list of three give six.
|
|
|
|
### `list`
|
|
|
|
Makes one entry per item. Each item is a table of values. Use it when the combinations aren't a clean grid.
|
|
|
|
```toml
|
|
[generators.systems]
|
|
list.entry.title = "Boot $name"
|
|
list.entry.actions = ["boot-system"]
|
|
list.values = [
|
|
{ name = "Alpine", kernel = "\\alpine\\vmlinuz" },
|
|
{ name = "Debian", kernel = "\\debian\\vmlinuz" },
|
|
]
|
|
```
|
|
|
|
### `bls`
|
|
|
|
Makes entries from the files of the [Bootloader Specification](#bootloader-specification-support).
|
|
|
|
```toml
|
|
[generators.bls]
|
|
bls.path = "\\loader"
|
|
bls.entry.title = "$title"
|
|
bls.entry.actions = ["boot-bls"]
|
|
```
|
|
|
|
| Key | Type | Default | Meaning |
|
|
|--------------|---------|-------------------|-------------------------------------------------------------------|
|
|
| `entry` | table | | The template entry. Required. |
|
|
| `path` | string | `\loader` | The directory that holds the `entries` directory. Can include a device, like `$boot\\loader`. |
|
|
| `uki-path` | string | `\EFI\Linux` on the device of `path` | Where to look for unified kernel images. An empty string turns them off. |
|
|
| `xbootldr` | boolean | `false` | Also read the extended boot loader partition of the same disk. |
|
|
| `pin-names` | boolean | `true` | Keep the entry file's name as the entry name, instead of prefixing the generator name. |
|
|
|
|
Two generators reading the same directory produce entries with the same name. Sprout warns about it, since
|
|
picking by name becomes ambiguous. `pin-names` is what makes names match the ids that `bootctl` uses.
|
|
|
|
The values each BLS entry provides are listed under [BLS values](#bls-values).
|
|
|
|
### `variants`
|
|
|
|
Variants multiply the entries of a generator. Each key is an axis, and each axis is a list of choices.
|
|
Every entry is made once for each combination of choices, taking one from each axis.
|
|
|
|
```toml
|
|
[generators.kernels]
|
|
matrix.entry.title = "Boot $kernel ($console)"
|
|
matrix.entry.actions = ["boot-kernel"]
|
|
matrix.values.kernel = ["\\vmlinuz", "\\vmlinuz-lts"]
|
|
variants.console = [
|
|
{ name = "serial", values.console-options = "console=ttyS0" },
|
|
{ name = "graphics", values.console-options = "console=tty0" },
|
|
]
|
|
```
|
|
|
|
This makes "Boot \vmlinuz (serial)", "Boot \vmlinuz (graphics)" and the same two for `\vmlinuz-lts`. Four
|
|
entries from a matrix of two kernels and two choices.
|
|
|
|
A choice has a `name` and optional `values`. The axis name becomes a value holding the choice's name
|
|
(`$console` is `serial` here), and the choice's own values are added next to it. Names are appended to the
|
|
entry name, so the entries above are called `kernels-0-serial`, `kernels-0-graphics` and so on. Axes apply in
|
|
alphabetical order, choices in the order written. An axis with no choices, or two choices that share a name,
|
|
is an error.
|
|
|
|
### `exclude`
|
|
|
|
Drops generated entries. It's a list of rules, and a rule is a table of value names to patterns, where `*`
|
|
matches anything. An entry is dropped if every value in at least one rule matches. It runs after variants,
|
|
and compares values before they are substituted.
|
|
|
|
```toml
|
|
[generators.bls]
|
|
# ...
|
|
exclude = [
|
|
{ version = "0-rescue-*" },
|
|
{ console = "graphics", mode = "debug" },
|
|
]
|
|
```
|
|
|
|
The first rule drops BLS rescue entries. The second drops only the one combination.
|
|
|
|
## `phases`
|
|
|
|
Phases run actions at fixed points in the boot. Each phase is a list, and each item names actions and can
|
|
add values for them.
|
|
|
|
| Phase | Runs |
|
|
|-----------|------------------------------------------------------------|
|
|
| `early` | Before drivers load. |
|
|
| `startup` | After drivers, autoconfiguration and extractors, before the menu is built. |
|
|
| `late` | After an entry is chosen, before its actions run. |
|
|
|
|
```toml
|
|
[[phases.early]]
|
|
actions = ["splash"]
|
|
|
|
[[phases.startup]]
|
|
actions = ["announce"]
|
|
values.message = "drivers are loaded"
|
|
```
|
|
|
|
Items run in order, and an action that fails stops the boot with an error. Note the double brackets: each
|
|
item is one element of a list.
|
|
|
|
## Autoconfiguration
|
|
|
|
With `autoconfigure = true`, or `--autoconfigure`, Sprout looks at every filesystem it can read and adds
|
|
configuration for what it finds. With the option, the result is added to your file. With the flag, your file
|
|
is not read at all, which makes it a good way to get a machine booting before you've written one.
|
|
|
|
For each filesystem:
|
|
|
|
- **BLS**: if it has `\loader\loader.conf`, a `\loader\entries` directory with `.conf` files, or `.efi` files
|
|
in `\EFI\Linux`, Sprout adds a `bls` generator and the action that boots its entries. These are named
|
|
`auto-bls-<hash>`.
|
|
- **Linux**: if there was no BLS, kernels in `\boot` and `\` are found by name (`vmlinuz` or `Image`,
|
|
optionally followed by `-` and a version), paired with an `initramfs`, `initrd` or `initrd.img` of the same
|
|
suffix. The entries are named `auto-linux-<hash>` and titled "Boot Linux" plus the path. Command line
|
|
options come from the value `linux-options`, which you can set in `[values]` and which otherwise is the
|
|
placeholder `placeholder`.
|
|
- **Windows**: if `\EFI\Microsoft\Boot\bootmgfw.efi` exists, an entry "Boot Windows" named
|
|
`auto-windows-<hash>` chainloads it.
|
|
|
|
`<hash>` is a short hash of the filesystem's device path, so two disks never collide. [Strict
|
|
mode](#strict-mode) narrows which filesystems the BLS part reads.
|
|
|
|
## Bootloader Specification support
|
|
|
|
Sprout implements the [Boot Loader Specification](https://uapi-group.org/specifications/specs/boot_loader_specification/)
|
|
to read the entries that distributions install, and sorts them as the specification says.
|
|
|
|
It reads Type #1 entries from `\loader\entries` and Type #2 unified kernel images (UKIs) from `\EFI\Linux`. A
|
|
UKI with several profiles is one entry per profile. Entries for another architecture than the machine's are
|
|
hidden. In a Type #1 entry Sprout uses the keys `title`, `version`, `machine-id`, `sort-key`, `linux`, `efi`,
|
|
`uki`, `initrd`, `options`, `devicetree`, `architecture` and `profile`.
|
|
|
|
The simplest way to get this is `autoconfigure = true`. To write it out by hand, you need a `bls` generator
|
|
and an action that boots what it makes:
|
|
|
|
```toml
|
|
[generators.bls]
|
|
bls.entry.title = "$title"
|
|
bls.entry.actions = ["boot-bls"]
|
|
bls.xbootldr = true
|
|
|
|
[actions.boot-bls]
|
|
chainload.path = "$entry-root\\$chainload"
|
|
chainload.options = ["$options"]
|
|
chainload.devicetree = "$entry-root\\$devicetree"
|
|
chainload.linux-initrd-chain = [
|
|
"$entry-root\\$initrd-0",
|
|
"$entry-root\\$initrd-1",
|
|
"$entry-root\\$initrd-2",
|
|
"$entry-root\\$initrd-3",
|
|
]
|
|
```
|
|
|
|
An entry can have up to 32 initrds, and Sprout warns when it has one that the chain doesn't list, because
|
|
the kernel likely can't then find its root. Autoconfiguration lists all 32. Unused slots are empty and
|
|
skipped, so listing more than you need costs nothing.
|
|
|
|
### BLS values
|
|
|
|
| Value | Holds |
|
|
|----------------------|----------------------------------------------------------------------------|
|
|
| `$title` | The title, with the version added unless it already contains it. |
|
|
| `$title-base` | The title as written in the entry. |
|
|
| `$version` | The `version` field. |
|
|
| `$machine-id` | The `machine-id` field. |
|
|
| `$chainload` | The path of the `linux`, `efi` or `uki` file. |
|
|
| `$options` | The `options` field, with the profile prepended for a UKI profile. |
|
|
| `$cmdline` | The command line embedded in a UKI. |
|
|
| `$uname` | The kernel version embedded in a UKI. |
|
|
| `$devicetree` | The `devicetree` path. |
|
|
| `$initrd-0` to `$initrd-31` | The initrds, in order. A slot with none is empty. |
|
|
| `$initrd` | The last initrd. |
|
|
| `$entry-root` | The device the entry's files are on. Empty for Sprout's own partition. |
|
|
|
|
`$entry-root` matters once `xbootldr` is on, since an entry on the XBOOTLDR partition has its files there,
|
|
not next to Sprout. Always write BLS paths as `$entry-root\\$chainload`.
|
|
|
|
### Boot counting
|
|
|
|
A file named like `fedora+3.conf` or `fedora+3.efi` has three tries. Each boot renames it, say to
|
|
`fedora+2-1.conf`, and tells the system the new path in `LoaderBootCountPath` so `systemd-bless-boot` can
|
|
remove the counter once the boot works.
|
|
|
|
Entries with no tries left sort last and are never the default, but can still be booted by hand. If an entry
|
|
fails to start after it used a try, and it had tries left, the machine resets so the next boot can use the
|
|
next try or pick another entry. This is the `reboot-on-error` setting of `loader.conf`. Without boot counting
|
|
a failure to start goes back to the firmware.
|
|
|
|
### `loader.conf`
|
|
|
|
Sprout reads `\loader\loader.conf` from the partition it was loaded from, as systemd-boot does. It is
|
|
measured into the TPM, since it changes how Sprout boots.
|
|
|
|
| Key | Value |
|
|
|-------------------|--------------------------------------------------------------------|
|
|
| `default` | A pattern for the id of the default entry, or `@saved`. |
|
|
| `preferred` | Like `default`, but entries with no boot counter tries are skipped. |
|
|
| `timeout` | Seconds, `menu-hidden`, `menu-disabled` or `menu-force`. |
|
|
| `reboot-on-error` | `auto` (the default), `yes` or `no`. |
|
|
|
|
The id of an entry is its file name without the boot counter, like `fedora.conf` or `fedora.efi`. Patterns
|
|
ignore case and can use `*`, `?` and `[a-z]`. With `@saved` the entry booted last is the default.
|
|
|
|
`reboot-on-error = yes` resets after every failed start, which can loop forever. `auto` only resets when a
|
|
try was used up and some were left. Other keys are ignored with a warning.
|
|
|
|
A hidden menu, from a timeout of zero or `menu-hidden`, still opens when a key is pressed. `menu-disabled`
|
|
does not.
|
|
|
|
### The bootloader interface
|
|
|
|
Sprout uses the same firmware variables as systemd-boot, so `bootctl`, `systemctl reboot --boot-loader-entry`
|
|
and `systemd-bless-boot` work with it. It publishes `LoaderEntries`, `LoaderEntrySelected`,
|
|
`LoaderBootCountPath`, `LoaderFeatures` and `LoaderInfo`, and reads `LoaderEntryDefault`,
|
|
`LoaderEntryPreferred`, `LoaderEntryOneShot`, `LoaderEntryLastBooted`, `LoaderConfigTimeout` and
|
|
`LoaderConfigTimeoutOneShot`.
|
|
|
|
What `bootctl` sets outranks `sprout.toml`, which outranks `loader.conf`. The default entry is the first of
|
|
these that matches an entry:
|
|
|
|
1. `LoaderEntryPreferred`, then `preferred` in `loader.conf`
|
|
2. `LoaderEntryDefault`
|
|
3. `default-entry` in `sprout.toml`
|
|
4. `default` in `loader.conf`
|
|
|
|
The menu timeout is the first of these that is set:
|
|
|
|
1. the one-shot timeout, `LoaderConfigTimeoutOneShot`
|
|
2. `--menu-timeout`
|
|
3. `LoaderConfigTimeout`
|
|
4. `menu-timeout` in `sprout.toml`
|
|
5. `timeout` in `loader.conf`
|
|
|
|
A one-shot entry (`LoaderEntryOneShot`) is booted at once and without the menu, unless strict mode is on.
|
|
|
|
## Strict mode
|
|
|
|
By default Sprout departs from systemd-boot in a few places, where it is friendlier or safer for a
|
|
bootloader that reads the same files. Each departure is logged when it applies. `--bls-strict-mode`, or
|
|
`bls-strict-mode = true` under `[options]`, turns all of them off.
|
|
|
|
| Behavior | By default | In strict mode |
|
|
|---------------------------------------------------|---------------------------------------------------------|---------------------------------------------------------|
|
|
| One-shot entry (`LoaderEntryOneShot`) | Booted at once, without the menu. | Only the default for this boot. The menu and its timeout still apply. |
|
|
| Menu timeout that nothing sets | The menu is shown for 10 seconds. | The menu is hidden. |
|
|
| Default entry with no boot counter tries | Skipped for another entry. | Used, as `default` ignores the tries. |
|
|
| Entry with more than one of `linux`, `efi`, `uki` | Boots the first of them. | Hidden. |
|
|
| Entry whose file does not exist | Shown, and it fails when booted. | Hidden. |
|
|
| UKI without a name | Named after its file. | Hidden. |
|
|
| Name and version of a UKI | Name is `PRETTY_NAME` or `ID`. Version is `IMAGE_VERSION`, `VERSION_ID`, `BUILD_ID`, then `.uname`. | What systemd-boot uses. Name is `PRETTY_NAME`, `IMAGE_ID`, `NAME` or `ID`. Version is `IMAGE_VERSION`, `VERSION`, `VERSION_ID` or `BUILD_ID`. |
|
|
| Boot counter of a plain `efi` entry | Counted. | Not counted, but its tries still make it bad. |
|
|
| Extended boot loader partition | Read when `xbootldr` is set on the generator. | Always read. |
|
|
| Autoconfiguration | Reads BLS entries from every disk, one generator each. | Reads BLS entries from Sprout's partition and the XBOOTLDR of its disk, as one generator. Windows and Linux entries are found as before. |
|
|
| Boot entry that returns | Sprout exits to the firmware. | The menu is shown again. |
|
|
| Devicetree that can't be installed | Warns and boots without it. | The entry fails. |
|
|
|
|
In strict mode the actions of a hand-written generator have to use `$entry-root` for the files of an entry,
|
|
as entries can come from the extended boot loader partition.
|