bootupd

repository·main·Indexed 41 days ago

https://github.com/coreos/bootupd

A distribution-independent tool for managing updates for bootloaders like GRUB and shim across x86_64, aarch64, riscv64, and ppc64le architectures. It provides a consistent update mechanism for UEFI and BIOS firmware, filling the gap where traditional OS updates may fail to update bootloader data consistently. Version 0.3.2 includes the bootupctl CLI for status checks, updates, and system validation.

Tokens
7.3K
Snippets
33
Records
46
Agent score
52%

What's inside bootupd

  1. What is bootupd?

    main
    bootupd is a distribution-independent tool designed to manage updates for bootloaders, such as /boot/efi, x86 BIOS MBR, and other architecture-specific bootloaders. It aims to provide a consistent update mechanism that is agnostic to the underlying OS update system (like OSTree or package managers), filling the gap where traditional OS updates often fail to update bootloader data consistently.
  2. Safety and reliability of bootupd updates

    main

    The reliability of updates depends on the firmware type:

    • UEFI firmware: Updates performed by bootupd are considered safe, even in the event of power failures.
    • BIOS and other systems: Updates are not safe against power failures occurring at the wrong time.

    Note: bootupd does not currently protect against a buggy bootloader update that results in a system that fails to boot.

  3. How bootupd interacts with other system tools

    main

    bootupd is designed to coexist with other low-level system tools:

    • dbxtool: Manages Secure Boot database updates. bootupd typically performs shimx64.efi binary updates before dbxtool.service starts.
    • fwupd: Used for hardware device firmware updates. bootupd focuses on GRUB and shim rather than hardware firmware.
    • systemd bootctl: If systemd-boot is detected, bootupd will likely proxy bootctl to perform updates.
  4. Understanding the bootupd execution model

    main

    Contrary to its name, bootupd is not a daemon. It is a CLI tool. To ensure safe and robust execution, it uses systemd-run to provide:

    • Locking: A robust natural locking mechanism to prevent concurrent updates.
    • Logging: Ensures critical logging metadata is consistently captured in the systemd journal.
    • Sandboxing: Allows the use of systemd sandboxing options even though the tool requires privileged access.
  5. Install bootupd files to disk images

    main

    To ensure bootupd can correctly manage updates, it must be responsible for the initial file layout in disk images (e.g., injecting files into the EFI system partition).

    Use the bootupctl backend install command to lay out these files. You must provide the path to the ostree deployment root and the target physical root partition.

    Command syntax:

    /usr/bin/bootupctl backend install --src-root <ostree_deploy_root> <physical_root_partition>
    /usr/bin/bootupctl backend install --src-root /path/to/ostree/deploy /sysroot
  6. Implement package ownership detection for bootupd

    main

    To integrate bootupd with a specific package manager (e.g., dpkg, pacman, apk, or rpm), you must provide a query-file-owner script. This script is used by packagesystem.rs to detect package ownership.

    Requirements for the script:

    • The script must accept one or more file paths as arguments: query-file-owner [FILE] [FILE...].
    • The output must be a list of package information, with one package per line in the format: NAME VERSION.

    Example output format:

    grub2-efi-x64 1:2.06-95.fc38
    shim-x64 15.6-2

    Testing existing implementations: You can install and test existing implementations for supported package systems using make:

    make install-all PACKAGESYSTEM=rpm

    Supported PACKAGESYSTEM values: dpkg, rpm, pacman, apk.

  7. Build and test bootupd

    main

    You can use standard Rust tools for basic development. For end-to-end (e2e) testing, you can use cosa and kola to run tests against a Fedora CoreOS image.

    Basic development: Use cargo build and cargo test.

    E2E testing example:

    export COSA_DIR=/path/to/fcos
    cosa build-fast
    kola run -E $(pwd) --qemu-image fastbuild-fedora-coreos-bootupd-qemu.qcow2  --qemu-firmware uefi ext.bootupd.*
    cargo build
    cargo test
  8. Generate a bootupd update payload

    main

    An "update payload" must be generated as part of your OS image creation process (e.g., during an ostree commit).

    To generate the metadata, invoke the bootupctl backend command. This command scrapes metadata (such as RPM versions) for components like shim and grub and places the component files and metadata into /usr/lib/bootupd/updates/.

    Command:

    bootupctl backend generate-update-metadata /
    bootupctl backend generate-update-metadata /
  9. Add drop-in GRUB configuration fragments

    main

    To include custom GRUB configuration settings in the final generated configuration, add drop-in fragment files to the src/grub2/configs.d/ directory.

    Each fragment must use the .cfg file extension to be recognized and installed into the final configuration.

    # Example: Creating a new fragment
    touch src/grub2/configs.d/my-custom-settings.cfg
  10. Use the bootupd CLI

    main

    The bootupd utility provides sub-commands for generating update metadata, installing bootloader components, and managing default bootloaders on EFI systems. You can control the verbosity of the output using the global -v flag.

    Verbosity levels:

    • (no flag): Warn level
    • -v: Info level
    • -vv: Debug level
    • -vvv: Trace level
    # Example: Install components with info verbosity
    bootupd -v install --dest-root /mnt/efi --device /dev/nvme0n1p1
  11. Manage EFI System Partitions (ESP)

    main

    The Efi struct provides methods to locate, mount, and manage the EFI System Partition (ESP).

    • get_mounted_esp(root): Searches common mount points (boot/efi, efi, or boot) to find an existing ESP mount.
    • mount_esp_device(root, esp_device): If no ESP is mounted, this mounts the specified device to a temporary location to avoid shadowing existing files.
    • ensure_mounted_esp(root, esp_device): A high-level method that returns the path to the ESP, either by finding an existing mount or creating a temporary one.
    • unmount(): Cleans up and unmounts any temporary ESP mounts managed by the Efi instance.
    let mut efi = Efi::default();
    let esp_path = efi.ensure_mounted_esp(Path::new("/"), Path::new("/dev/sda1"))?;
    // ... use esp_path ...
    efi.unmount()?;
  12. Component lifecycle methods

    main

    The Component trait defines the following primary operations used by bootupd to manage bootloaders:

    MethodPurpose
    installPerforms bootupd install. Used during disk image builds to move files from src_root to dest_root.
    generate_update_metadataPerforms bootupd generate-update-metadata. Used during image builds to create metadata for future updates.
    query_updateUsed on a running client to check if an update is cached in the current OS.
    run_updateUsed on a running client to apply an update using RootContext and InstalledContent.
    validateValidates the currently installed version against a Device.
    query_adoptDetects if an existing (non-bootupd) installation can be managed by bootupd.
    migrate_static_grub_configBacks up current GRUB config and installs a static version from a directory tree.