diff options
Diffstat (limited to 'docs/BOOT_LOADER_SPECIFICATION.md')
-rw-r--r-- | docs/BOOT_LOADER_SPECIFICATION.md | 745 |
1 files changed, 1 insertions, 744 deletions
diff --git a/docs/BOOT_LOADER_SPECIFICATION.md b/docs/BOOT_LOADER_SPECIFICATION.md index 9188033768..33066b2875 100644 --- a/docs/BOOT_LOADER_SPECIFICATION.md +++ b/docs/BOOT_LOADER_SPECIFICATION.md @@ -1,744 +1 @@ ---- -title: Boot Loader Specification -category: Booting -layout: default -SPDX-License-Identifier: LGPL-2.1-or-later ---- - -# The Boot Loader Specification - -This document defines a set of file formats and naming conventions that allow -the boot loader menu entries to be shared between multiple operating systems -and boot loaders installed on one device. - -Operating systems cooperatively manage boot loader menu entry directories that -contain drop-in files, making multi-boot scenarios easy to support. Boot menu -entries are defined via two simple formats that can be understood by different -boot loader implementations, operating systems, and userspace programs. The -same scheme can be used to prepare OS media for cases where the firmware -includes a boot loader. - -## Target Audience - -The target audience for this specification is: - -* Boot loader developers, to write a boot loader that directly reads its - menu entries from these files -* Firmware developers, to add generic boot loading support directly to the - firmware itself -* OS installer developers, to create appropriate partitions and set up the - initial boot loader menu entries -* Distribution developers, to create appropriate menu entry snippets when - installing or updating kernel packages -* UI developers, to implement user interfaces that list and select among the - available boot options - -## The Partitions - -Everything described below is located on one or two partitions. The boot loader -or user-space programs reading the boot loader menu entries should locate them -in the following manner: - -* On disks with an MBR partition table: - - * The boot partition — a partition with the type ID of `0xEA` — shall be used - as the single location for boot loader menu entries. - -* On disks with GPT (GUID Partition Table) - - * The EFI System Partition (ESP for short) — a partition with a GPT type GUID - of `c12a7328-f81f-11d2-ba4b-00a0c93ec93b` — may be used as one of two locations for - boot loader menu entries. - - * Optionally, an Extended Boot Loader Partition (XBOOTLDR partition for - short) — a partition with GPT type GUID of - `bc13c2ff-59e6-4262-a352-b275fd6f7172` — may be used as the second of two - locations for boot loader menu entries. This partition must be located on - the same disk as the ESP. - -There may be at most one partition of each of the types listed above on the -same disk. - -**Note:** _These partitions are **shared** among all OS installations on the -same disk. Instead of maintaining one boot partition per installed OS (as -`/boot/` was traditionally handled), all installed OSes use the same place for -boot loader menu entries._ - -For systems where the firmware is able to read file systems directly, the ESP -must — and the MBR boot and GPT XBOOTLDR partition should — be a file system -readable by the firmware. For most systems this means VFAT (16 or 32 -bit). Applications accessing both partitions should hence not assume that -fancier file system features such as symlinks, hardlinks, access control or -case sensitivity are supported. - -### The `$BOOT` Partition Placeholder - -In the text below, the placeholder `$BOOT` will be used to refer to the -partition determined as follows: - - 1. On disks with an MBR partition table: → the boot partition, as described above - - 2. On disks with a GPT partition table: → the XBOOTLDR partition if it exists - - 3. Otherwise, on disks with a GPT partition table: → the ESP - -`$BOOT` is the *primary* place to put boot menu entry resources into, but -typically not the only one. Most importantly, boot loaders should also pick up -menu entries from the ESP, even if XBOOTLDR exists (for details see below). - -### Creating These Partitions - -An installer for an operating system should use this logic when selecting or -creating partitions: - - * If a boot partition (in case of MBR) or an XBOOTLDR partition (in case of - GPT) already exists it should be used as `$BOOT` and used as primary - location to place boot loader menu resources in. - - * Otherwise, if on GPT and an ESP is found and it is large enough (let's say - at least 1G) it should be used as `$BOOT` and used as primary location to - place boot loader menu resources in. - - * Otherwise, if on GPT and neither XBOOTLDR nor ESP exist, an ESP should be - created of the appropriate size and be used as `$BOOT`, and used as primary - location to place boot loader menu resources in. - - * Otherwise, a boot partition (in case of MBR) or XBOOTLDR partition (in case - of GPT) should be created of an appropriate size, and be used as `$BOOT`, - and used as primary location to place boot loader menu resources in. - -These partitions shall be determined during _installation time_, and -`/etc/fstab` entries may be created. - -### Mount Points - -It is recommended to mount `$BOOT` to `/boot/`, and the ESP to `/efi/`. If -`$BOOT` and the ESP are the same, then either a bind mount or a symlink should -be established making the partition available under both paths. - -(Mounting the ESP to `/boot/efi/`, as was traditionally done, is not -recommended. Such a nested setup complicates an implementation via direct -`autofs` mounts — as implemented by `systemd` for example —, as establishing -the inner `autofs` will trigger the outer one. Mounting the two partitions via -`autofs` is recommended because the simple VFAT file system has weak data -integrity properties and should remain unmounted whenever possible.) - -## Boot Loader Entries - -This specification defines two types of boot loader entries. The first type is -text based, very simple, and suitable for a variety of firmware, architecture -and image types ("Type #1"). The second type is specific to EFI, but allows -single-file images that embed all metadata in the kernel binary itself, which -is useful to cryptographically sign them as one file for the purpose of -SecureBoot ("Type #2"). - -Not all boot loader entries will apply to all systems. For example, Type #1 -entries that use the `efi` key and all Type #2 entries only apply to EFI -systems. Entries using the `architecture` key might specify an architecture that -doesn't match the local one. Boot loaders should ignore all entries that don't -match the local platform and what the boot loader can support, and hide them -from the user. Only entries matching the feature set of boot loader and system -shall be considered and displayed. This allows image builders to put together -images that transparently support multiple different architectures. - -Note that the three partitions described above are not supposed to be the -exclusive territory of this specification. This specification only defines -semantics of the `/loader/entries/` directory (along with the companion file -`/loader/entries.srel`) and the `/EFI/Linux/` directory inside the file system, -but it doesn't intend to define contents of the rest of the file system. Boot -loaders, firmware, and other software implementing this specification may -choose to place other files and directories in the same file system. For -example, boot loaders that implement this specification might install their own -boot code on the same partition; this is particularly common in the case of the -ESP. Implementations of this specification must be able to operate correctly if -files or directories other than `/loader/entries/` and `/EFI/Linux/` are found -in the top level directory. Implementations that add their own files or -directories to the file systems should use well-named directories, to make name -collisions between multiple users of the file system unlikely. - -### Type #1 Boot Loader Specification Entries - -`/loader/entries/` in `$BOOT` is the primary directory containing Type #1 -drop-in snippets defining boot entries, one `.conf` file for each boot menu -item. Each OS may provide one or more such entries. - -If the ESP is separate from `$BOOT` it may also contain a `/loader/entries/` -directory, where the boot loader should look for boot entry snippets, as an -additional source. The boot loader should enumerate both directories and -present a merged list to the user. Note that this is done for compatibility -only: while boot loaders should look in both places, OSes should only add their -files to `$BOOT`. - -**Note:** _In all cases the `/loader/entries/` directory should be located -directly in the root of the file system. Specifically, the `/loader/entries/` -directory should **not** be located under the `/EFI/` subdirectory on the ESP._ - -The file name of the boot entry snippets is used for identification of the boot -item but shall never be presented to the user in the UI. The file name may be -chosen freely but should be unique enough to avoid clashes between OS -installations. More specifically, it is suggested to include the `entry-token` -(see -[kernel-install](https://www.freedesktop.org/software/systemd/man/kernel-install.html)) -or machine ID (see -[/etc/machine-id](https://www.freedesktop.org/software/systemd/man/machine-id.html)), -and the kernel version (as returned by `uname -r`, including the OS -identifier), so that the whole filename is -`$BOOT/loader/entries/<entry-token-or-machine-id>-<version>.conf`. - -Example: `$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf`. - -In order to maximize compatibility with file system implementations and -restricted boot loader environments, and to minimize conflicting character use -with other programs, file names shall be chosen from a restricted character -set: ASCII upper and lower case characters, digits, "+", "-", "_" and ".". -Also, the file names should have a length of at least one and at most 255 -characters (including the file name suffix). - -These boot loader menu snippets shall be UNIX-style text files (i.e. lines -separated by a single newline character), in the UTF-8 encoding. The -boot loader menu snippets are loosely inspired by Grub1's configuration syntax. -Lines beginning with "#" are used for comments and shall be ignored. The first -word of a line is used as key and is separated by one or more spaces from the -value. - -#### Type #1 Boot Loader Entry Keys - -The following keys are recognized: - -* `title` is a human-readable title for this menu item to be displayed in the - boot menu. It is a good idea to initialize this from the `PRETTY_NAME=` of - [os-release](https://www.freedesktop.org/software/systemd/man/os-release.html). - This name should be descriptive and does not have to be unique. If a boot - loader discovers two entries with the same title it should show more than - just the raw title in the UI, for example by appending the `version` - field. This field is optional. - - Example: `title Fedora 18 (Spherical Cow)` - -* `version` is a human-readable version for this menu item. This is usually the - kernel version and is intended for use by OSes to install multiple kernel - versions with the same `title` field. This field is used for sorting entries, - so that the boot loader can order entries by age or select the newest one - automatically. This field is optional. - - See [Sorting](#sorting) below. - - Example: `version 3.7.2-201.fc18.x86_64` - -* `machine-id` is the machine ID of the OS. This can be used by boot loaders - and applications to filter out boot entries, for example to show only a - single newest kernel per OS, to group items by OS, or to filter out the - currently booted OS when showing only other installed operating systems. - This ID shall be formatted as 32 lower case hexadecimal characters - (i.e. without any UUID formatting). This key is optional. - - Example: `machine-id 4098b3f648d74c13b1f04ccfba7798e8` - -* `sort-key` is a short string used for sorting entries on display. This should - typically be initialized from the `IMAGE_ID=` or `ID=` fields of - [os-release](https://www.freedesktop.org/software/systemd/man/os-release.html), - possibly with an additional suffix. This field is optional. - - Example: `sort-key fedora` - -* `linux` is the Linux kernel image to execute and takes a path relative to the - root of the file system containing the boot entry snippet itself. It is - recommended that every distribution creates an entry-token/machine-id and - version specific subdirectory and places its kernels and initrd images there - (see below). - - Example: `linux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux` - -* `initrd` is the initrd `cpio` image to use when executing the kernel. This key - may appear more than once in which case all specified images are used, in the - order they are listed. - - Example: `initrd 6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd` - -* `efi` refers to an arbitrary EFI program. If this key is set, and the system - is not an EFI system, this entry should be hidden. - -* `options` shall contain kernel parameters to pass to the Linux kernel to - spawn. This key is optional and may appear more than once in which case all - specified parameters are combined in the order they are listed. - - Example: `options root=UUID=6d3376e4-fc93-4509-95ec-a21d68011da2 quiet` - -* `devicetree` refers to the binary device tree to use when executing the - kernel. This key is optional. - - Example: `devicetree 6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb` - -* `devicetree-overlay` refers to a list of device tree overlays that should be - applied by the boot loader. Multiple overlays are separated by spaces and - applied in the same order as they are listed. This key is optional but - depends on the `devicetree` key. - - Example: `devicetree-overlay /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_A.dtbo /6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_B.dtbo` - -* `architecture` refers to the architecture this entry is for. The argument - should be an architecture identifier, using the architecture vocabulary - defined by the EFI specification (i.e. `IA32`, `x64`, `IA64`, `ARM`, `AA64`, - …). If specified and it does not match the local system architecture this - entry should be hidden. The comparison should be done case-insensitively. - - Example: `architecture aa64` - -Each boot loader menu entry drop-in snippet must include at least a `linux` or an `efi` -key. Here is an example for a complete drop-in file: - - # /boot/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf - title Fedora 19 (Rawhide) - sort-key fedora - machine-id 6a9857a393724b7a981ebb5b8495b9ea - version 3.8.0-2.fc19.x86_64 - options root=UUID=6d3376e4-fc93-4509-95ec-a21d68011da2 quiet - architecture x64 - linux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux - initrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd - -On EFI systems all Linux kernel images should be EFI images. In order to -increase compatibility with EFI systems it is highly recommended only to -install EFI kernel images, even on non-EFI systems, if that's applicable and -supported on the specific architecture. - -Conversely, in order to increase compatibility it is recommended to install -generic kernel images that make few assumptions about the firmware they run on, -i.e. it is a good idea that both images shipped as UEFI PE images and those -which are not don't make unnecessary assumption on the underlying firmware, -i.e. don't hard depend on legacy BIOS calls or UEFI boot services. - -When Type #1 boot loader menu entry snippets refer to other files (for `linux`, -`initrd`, `efi`, `devicetree`, and `devicetree-overlay`), those files must be -located on the same partition, and the paths must be absolute paths relative to -the root of that file system. The naming of those files can be chosen by the -installer. A recommended scheme is described in the next section. Paths should -be normalized, i.e. not include `..`, `.` or a sequence of more than one -`/`. Paths may be prefixed with a `/`, but this is optional and has the same -effect as paths without it: all paths are always relative to the root directory -of the partition they are referenced from. - -Even though the backing file system is typically case-insensitive (i.e. VFAT) -it is strongly recommended to reference files in the casing actually used for -the directories/files, so that placing these files on other file systems is -still safe and robust. - -### Recommended Directory Layout for Additional Files - -It is recommended to place the kernel and other other files comprising a single -boot loader entry in a separate directory: -`/<entry-token-or-machine-id>/<version>/`. This naming scheme uses the same -elements as the boot loader menu entry snippet, providing the same level of -uniqueness. - -Example: `$BOOT/6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux` - `$BOOT/6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd` - -Other naming schemes are possible. In particular, traditionally a flat naming -scheme with files in the root directory was used. This is not recommended -because it is hard to avoid conflicts in a multi-boot installation. - -### Standard-conformance Marker File - -Unfortunately, there are implementations of boot loading infrastructure that -are also using the `/loader/entries/` directory, but install files that do not -follow this specification. In order to minimize confusion, a boot loader -implementation may place the file `/loader/entries.srel` next to the -`/loader/entries/` directory containing the ASCII string `type1` (followed by a -UNIX newline). Tools that need to determine whether an existing directory -implements the semantics described here may check for this file and contents: -if it exists and contains the mentioned string, it shall assume a -standards-compliant implementation is in place. If it exists but contains a -different string it shall assume other semantics are implemented. If the file -does not exist, no assumptions should be made. - -### Type #2 EFI Unified Kernel Images - -A unified kernel image is a single EFI PE executable combining an EFI stub -loader, a kernel image, an initrd image, and the kernel command line. See -[systemd-stub(7)](https://www.freedesktop.org/software/systemd/man/systemd-stub.html) -for details. The primary place for such unified images is the `/EFI/Linux/` -directory in `$BOOT`. Operating systems should place unified EFI kernels only -in the `$BOOT` partition. Boot loaders should also look in the `/EFI/Linux/` of -the ESP — if it is different from `$BOOT` — and present a merged list of menu -entries from both partitions. Regardless if placed in the primary or secondary -location: the files must have the extension `.efi`. Support for images of this -type is of course specific to systems with EFI firmware. Ignore this section if -you work on systems not supporting EFI. - -Type #2 file names should be chosen from the same restricted character set as -Type #1 described above (but with the file name suffix of `.efi` instead of -`.conf`). - -Images of this type have the advantage that all metadata and payload that makes -up the boot entry is contained in a single PE file that can be signed -cryptographically as one for the purpose of EFI SecureBoot. - -A valid unified kernel image in the `/EFI/Linux/` directory must contain two PE sections: - -* `.cmdline` section with the kernel command line, -* `.osrel` section with an embedded copy of the - [os-release](https://www.freedesktop.org/software/systemd/man/os-release.html) - file describing the image. - -The `PRETTY_NAME=` and `VERSION_ID=` fields in the embedded `os-release` file -are used the same as `title` and `version` in the Type #1 entries. The -`.cmdline` section is used instead of the `options` field. `linux` and `initrd` -fields are not necessary, and there is no counterpart for the `machine-id` -field. - -On EFI, any such images shall be added to the list of valid boot entries. - -### Additional Notes - -Note that these boot entry snippets and unified kernels do not need to be the -only menu entry sources for a boot loader. It may extend this list of -entries with additional items from other configuration files (for example its -own native configuration files) or automatically detected other entries without -explicit configuration. - -To make this explicitly clear: this specification is designed with "free" -operating systems in mind, starting Windows or MacOS is out of focus with these -boot loader menu entry snippets, use boot-loader specific solutions for -that. In the text above, if we say "OS" we hence imply "free", i.e. primarily -Linux (though this could be easily be extended to the BSDs and whatnot). - -Note that all paths used in the boot loader menu entry snippets use a -Unix-style "/" as path separator. This needs to be converted to an EFI-style -"\\" separator in EFI boot loaders. - - -## Locating Boot Entries - -A _boot loader_ locates the XBOOTLDR partition and the ESP, then simply reads -all the files `/loader/entries/*.conf` in them, and populates its boot menu -(and handle gracefully if one of the two partitions is missing). On EFI, it -then extends this with any unified kernel images found in `/EFI/Linux/*.efi` in -the two partitions. It may also add additional entries, for example a "Reboot -into firmware" option. Optionally it may sort the menu based on the -`sort-key`, `machine-id` and `version` fields, and possibly others. It uses the -file name to identify specific items, for example in case it supports storing -away default entry information somewhere. A boot loader should generally not -modify these files. - -For "Boot Loader Specification Entries" (Type #1), the _kernel package -installer_ installs the kernel and initrd images to `$BOOT`. It is recommended -to place these files in a vendor and OS and installation specific directory. It -then generates a boot loader menu entry snippet, placing it in -`$BOOT/loader/entries/xyz.conf`, with "xyz" as concatenation of -entry-token/machine-id and version information (see above). The files created -by a kernel package are tied to the kernel package and should be removed along -with it. - -For "EFI Unified Kernel Images" (Type #2), the vendor or kernel package -installer should create the combined image and drop it into -`$BOOT/EFI/Linux/`. This file is also tied to the kernel package and should be -removed along with it. - -A _UI application_ intended to show available boot options shall operate -similarly to a boot loader (and thus search both `$BOOT` and the ESP if -distinct), but might apply additional filters, for example by filtering the -booted OS via the machine ID, or by suppressing all but the newest kernel -versions. - -An _OS installer_ picks the right place for `$BOOT` as defined above (possibly -creating a partition and file system for it) and creates the `/loader/entries/` -directory and the `/loader/entries.srel` file in it (the latter only if the -directory didn't exist yet). It then installs an appropriate boot loader that -can read these snippets. Finally, it installs one or more kernel packages. - -## Boot counting - -The main idea is that when boot entries are initially installed, they are -marked as "indeterminate" and assigned a number of boot attempts. Each time the -boot loader tries to boot an entry, it decreases this count by one. If the -operating system considers the boot as successful, it removes the counter -altogether and the entry becomes "good". Otherwise, once the assigned number of -boots is exhausted, the entry is marked as "bad". - -Which boots are "successful" is determined by the operating system. systemd -provides a generic mechanism that can be extended with arbitrary checks and -actions, see [Automatic Boot Assessment](AUTOMATIC_BOOT_ASSESSMENT.md), but the -boot counting mechanism described in this specification can also be used with -other implementations. - -The boot counting data is stored in the name of the boot loader entry. A boot -loader entry file name may contain a plus (`+`) followed by a number. This may -optionally be followed by a minus (`-`) followed by a second number. The dot -(`.`) and file name suffix (`conf` of `efi`) must immediately follow. Boot -counting is enabled for entries which match this pattern. - -The first number is the "tries left" counter signifying how many attempts to boot -this entry shall still be made. The second number is the "tries done" counter, -showing how many failed attempts to boot it have already been made. Each time -a boot loader entry marked this way is booted, the first counter is decremented, -and the second one incremented. (If the second counter is missing, -then it is assumed to be equivalent to zero.) If the "tries left" counter is -above zero the entry is still considered "indeterminate". A boot entry with the -"tries left" counter at zero is considered "bad". - -If the boot attempt completed successfully the entry's counters are removed -from the name (entry state becomes "good"), thus turning off boot counting for -this entry. - -## Sorting - -The boot loader menu should generally show entries in some order meaningful to -the user. The `title` key is free-form and not suitable to be used as the -primary sorting key. Instead, the boot loader should use the following rules: - -1. Entries which are subject to boot counting and are marked as "bad", should - be sorted later than all other entries. Entries which are marked as - "indeterminate" or "good" (or were not subject to boot counting at all), - are thus sorted earlier. - -2. If `sort-key` is set on both entries, use in order of priority, - the `sort-key` (A-Z, increasing [alphanumerical order](#alphanumerical-order)), - `machine-id` (A-Z, increasing alphanumerical order), - and `version` keys (decreasing [version order](#version-order)). - -3. If `sort-key` is set on one entry, it sorts earlier. - -4. At the end, if necessary, when `sort-key` is not set or those fields are not - set or are all equal, the boot loader should sort using the file name of the - entry (decreasing version sort), with the suffix removed. - -**Note:** _This description assumes that the boot loader shows entries in a -traditional menu, with newest and "best" entries at the top, thus entries with -a higher version number are sorter *earlier*. The boot loader is free to -use a different direction (or none at all) during display._ - -**Note:** _The boot loader should allow booting "bad" entries, e.g. in case no -other entries are left or they are unusable for other reasons. It may -deemphasize or hide such entries by default._ - -**Note:** _"Bad" boot entries have a suffix of "+0-`n`", where `n` is the -number of failed boot attempts. Removal of the suffix is not necessary for -comparisons described by the last point above. In the unlikely scenario that we -have multiple such boot entries that differ only by the boot counting data, we -would sort them by `n`._ - -### Alphanumerical Order - -Free-form strings and machine IDs should be compared using a method equivalent -to [strcmp(3)](https://man7.org/linux/man-pages/man3/strcmp.3.html) on their -UTF-8 representations. If just one of the strings is unspecified or empty, it -compares lower. If both strings are unspecified or empty, they compare equal. - -### Version Order - -The following method should be used to compare version strings. The algorithm -is based on rpm's `rpmvercmp()`, but not identical. - -ASCII letters (`a-z`, `A-Z`) and digits (`0-9`) form alphanumerical components of the version. -Minus (`-`) separates the version and release parts. -Dot (`.`) separates parts of version or release. -Tilde (`~`) is a prefix that always compares lower. -Caret (`^`) is a prefix that always compares higher. - -Both strings are compared from the beginning until the end, or until the -strings are found to compare as different. In a loop: -1. Any characters which are outside of the set of listed above (`a-z`, `A-Z`, `0-9`, `-`, `.`, `~`, `^`) - are skipped in both strings. In particular, this means that non-ASCII characters - that are Unicode digits or letters are skipped too. -2. If one of the strings has ended: if the other string hasn't, the string that - has remaining characters compares higher. Otherwise, the strings compare - equal. -3. If the remaining part of one of strings starts with `~`: - if other remaining part does not start with `~`, - the string with `~` compares lower. Otherwise, both tilde characters are skipped. -4. The check from point 2. is repeated here. -5. If the remaining part of one of strings starts with `-`: - if the other remaining part does not start with `-`, - the string with `-` compares lower. Otherwise, both minus characters are skipped. -6. If the remaining part of one of strings starts with `^`: - if the other remaining part does not start with `^`, - the string with `^` compares higher. Otherwise, both caret characters are skipped. -6. If the remaining part of one of strings starts with `.`: - if the other remaining part does not start with `.`, - the string with `.` compares lower. Otherwise, both dot characters are skipped. -7. If either of the remaining parts starts with a digit, numerical prefixes are - compared numerically. Any leading zeroes are skipped. - The numerical prefixes (until the first non-digit character) are evaluated as numbers. - If one of the prefixes is empty, it evaluates as 0. - If the numbers are different, the string with the bigger number compares higher. - Otherwise, the comparison continues at the following characters at point 1. -8. Leading alphabetical prefixes are compared alphabetically. - The substrings are compared letter-by-letter. - If both letters are the same, the comparison continues with the next letter. - Capital letters compare lower than lower-case letters (`A < a`). - When the end of one substring has been reached (a non-letter character or the end - of the whole string), if the other substring has remaining letters, it compares higher. - Otherwise, the comparison continues at the following characters at point 1. - -Examples (with '' meaning the empty string): - -* `11 == 11` -* `systemd-123 == systemd-123` -* `bar-123 < foo-123` -* `123a > 123` -* `123.a > 123` -* `123.a < 123.b` -* `123a > 123.a` -* `11α == 11β` -* `A < a` -* '' < `0` -* `0.` > `0` -* `0.0` > `0` -* `0` < `~` -* '' < `~` - -Note: [systemd-analyze](https://www.freedesktop.org/software/systemd/man/systemd-analyze.html) -implements this version comparison algorithm as -``` -systemd-analyze compare-versions <version-a> <version-b> -``` - -## Additional discussion - -### Why is there a need for this specification? - -This specification brings the following advantages: - -* Installation of new boot entries is more robust, as no explicit rewriting of - configuration files is required. - -* It allows an out-of-the-box boot experience on any platform without the need - of traditional firmware mechanisms (e.g. BIOS calls, UEFI Boot Services). - -* It improves dual-boot scenarios. Without cooperation, multiple Linux - installations tend to fight over which boot loader becomes the primary one in - possession of the MBR or the boot partition, and only that one installation - can then update the boot loader configuration. Other Linux installs have to - be manually configured to never touch the MBR and instead install a - chain-loaded boot loader in their own partition headers. In this new scheme - all installations share a loader directory and no manual configuration has to - take place. All participants implicitly cooperate due to removal of name - collisions and can install/remove their own boot menu entries without - interfering with the entries of other installed operating systems. - -* Drop-in directories are now pretty ubiquitous on Linux as an easy way to - extend boot loader menus without having to edit, regenerate or manipulate - configuration files. For the sake of uniformity, we should do the same for - the boot menu. - -* Userspace code can sanely parse boot loader menu entries which is essential - with modern firmware which does not necessarily initialize USB keyboards - during boot, which makes boot menus hard to reach for the user. If userspace - code can parse the boot loader menu entries too, UI can be written that - select a boot menu item to boot into before rebooting the machine, thus not - requiring interactivity during early boot. - -* To unify and thus simplify menu entries of the various boot loaders, which - makes configuration of the boot loading process easier for users, - administrators, and developers alike. - -* For boot loaders with configuration _scripts_ such as grub2, adopting this - spec allows for mostly static scripts that are generated only once at first - installation, but then do not need to be updated anymore as that is done via - drop-in files exclusively. - -### Why not simply rely on the EFI boot menu logic? - -EFI is not ubiquitous, especially not in embedded systems. But even on systems -with EFI, which provides a boot options logic that can offer similar -functionality, this specification is still needed for the following reasons: - -* The various EFI implementations implement the boot order/boot item logic to - different levels. Some firmware implementations do not offer a boot menu at - all and instead unconditionally follow the EFI boot order, booting the first - item that is working. - -* If the firmware setup is used to reset data, usually all EFI boot entries - are lost, making the system entirely unbootable, as the firmware setups - generally do not offer a UI to define additional boot items. By placing the - menu item information on disk, it is always available, even if the firmware - configuration is lost. - -* Harddisk images should be movable between machines and be bootable without - requiring firmware configuration. This also requires that the list - of boot options is defined on disk, and not in EFI variables alone. - -* EFI is not universal yet (especially on non-x86 platforms), this - specification is useful both for EFI and non-EFI boot loaders. - -* Many EFI systems disable USB support during early boot to optimize boot - times, thus making keyboard input unavailable in the EFI menu. It is thus - useful if the OS UI has a standardized way to discover available boot options - which can be booted to. - -### Why is the version comparison logic so complicated? - -The `sort-key` allows us to group entries by "operating system", e.g. all -versions of Fedora together, no matter if they identify themselves as "Fedora -Workstation" or "Fedora Rawhide (prerelease)". The `sort-key` was introduced -only recently, so we need to provide a meaningful order for entries both with -and without it. Since it is a new concept, it is assumed that entries with -`sort-key` are newer. - -In a traditional menu with entries displayed vertically, we want names to be -sorter alpabetically (CentOS, Debian, Fedora, OpenSUSE, …), it would be strange -to have them in reverse order. But when multiple kernels are available for the -same installation, we want to display the latest kernel with highest priority, -i.e. earlier in the list. - -### Why do you use file renames to store the counter? Why not a regular file? - -Mainly two reasons: it's relatively likely that renames can be implemented -atomically even in simpler file systems, as renaming generally avoids -allocating or releasing data blocks. Writing to file contents has a much bigger -chance to be result in incomplete or corrupt data. Moreover renaming has the -benefit that the boot count metadata is directly attached to the boot loader -entry file, and thus the lifecycle of the metadata and the entry itself are -bound together. This means no additional clean-up needs to take place to drop -the boot loader counting information for an entry when it is removed. - -### Why not use EFI variables for storing the boot counter? - -The memory chips used to back the persistent EFI variables are generally not of -the highest quality, hence shouldn't be written to more than necessary. This -means we can't really use it for changes made regularly during boot, but should -use it only for seldom-made configuration changes. - -### Out of Focus - -There are a couple of items that are out of focus for this specification: - -* If userspace can figure out the available boot options, then this is only - useful so much: we'd still need to come up with a way how userspace could - communicate to the boot loader the default boot loader entry temporarily or - persistently. Defining a common scheme for this is certainly a good idea, but - out of focus for this specification. - -* This specification is just about "Free" Operating systems. Hooking in other - operating systems (like Windows and macOS) into the boot menu is a different - story and should probably happen outside of this specification. For example, - boot loaders might choose to detect other available OSes dynamically at - runtime without explicit configuration (like `systemd-boot` does it), or via - native configuration (for example via explicit Grub2 configuration generated - once at installation). - -* This specification leaves undefined what to do about systems which are - upgraded from an OS that does not implement this specification. As the - previous boot loader logic was largely handled by in distribution-specific - ways we probably should leave the upgrade path (and whether there actually is - one) to the distributions. The simplest solution might be to simply continue - with the old scheme for old installations and use this new scheme only for - new installations. - -* Referencing kernels or initrds on other partitions other than the partition - containing the Type #1 boot loader entry. This is by design, as specifying - other partitions or devices would require a non-trivial language for denoting - device paths. In particular this means that on non-EFI systems boot loader - menu entry snippets following this specification cannot be used to spawn - other operating systems (such as Windows). - - -## Links - -[GUID Partition Table](https://en.wikipedia.org/wiki/GUID_Partition_Table)<br> -[Boot Loader Interface](BOOT_LOADER_INTERFACE.md)<br> -[Discoverable Partitions Specification](DISCOVERABLE_PARTITIONS.md)<br> -[`systemd-boot(7)`](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)<br> -[`bootctl(1)`](https://www.freedesktop.org/software/systemd/man/bootctl.html)<br> -[`systemd-gpt-auto-generator(8)`](https://www.freedesktop.org/software/systemd/man/systemd-gpt-auto-generator.html) +[This content has moved to the UAPI group website](https://uapi-group.org/specifications/specs/boot_loader_specification/) |