{ config, lib, pkgs, ... }: let cfg = config.boot.uki; inherit (pkgs.stdenv.hostPlatform) efiArch; format = pkgs.formats.ini { }; in { options = { boot.uki = { name = lib.mkOption { type = lib.types.str; description = lib.mdDoc "Name of the UKI"; }; version = lib.mkOption { type = lib.types.nullOr lib.types.str; default = config.system.image.version; defaultText = lib.literalExpression "config.system.image.version"; description = lib.mdDoc "Version of the image or generation the UKI belongs to"; }; tries = lib.mkOption { type = lib.types.nullOr lib.types.ints.unsigned; default = null; description = lib.mdDoc '' Number of boot attempts before this UKI is considered bad. If no tries are specified (the default) automatic boot assessment remains inactive. See documentation on [Automatic Boot Assessment](https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT/) and [boot counting](https://uapi-group.org/specifications/specs/boot_loader_specification/#boot-counting) for more information. ''; }; settings = lib.mkOption { type = format.type; description = lib.mdDoc '' The configuration settings for ukify. These control what the UKI contains and how it is built. ''; }; configFile = lib.mkOption { type = lib.types.path; description = lib.mdDoc '' The configuration file passed to {manpage}`ukify(1)` to create the UKI. By default this configuration file is created from {option}`boot.uki.settings`. ''; }; }; system.boot.loader.ukiFile = lib.mkOption { type = lib.types.str; internal = true; description = lib.mdDoc "Name of the UKI file"; }; }; config = { boot.uki.name = lib.mkOptionDefault (if config.system.image.id != null then config.system.image.id else "nixos"); boot.uki.settings = { UKI = { Linux = lib.mkOptionDefault "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}"; Initrd = lib.mkOptionDefault "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; Cmdline = lib.mkOptionDefault "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"; Stub = lib.mkOptionDefault "${pkgs.systemd}/lib/systemd/boot/efi/linux${efiArch}.efi.stub"; Uname = lib.mkOptionDefault "${config.boot.kernelPackages.kernel.modDirVersion}"; OSRelease = lib.mkOptionDefault "@${config.system.build.etc}/etc/os-release"; # This is needed for cross compiling. EFIArch = lib.mkOptionDefault efiArch; } // lib.optionalAttrs (config.hardware.deviceTree.enable && config.hardware.deviceTree.name != null) { DeviceTree = lib.mkOptionDefault "${config.hardware.deviceTree.package}/${config.hardware.deviceTree.name}"; }; }; boot.uki.configFile = lib.mkOptionDefault (format.generate "ukify.conf" cfg.settings); system.boot.loader.ukiFile = let name = config.boot.uki.name; version = config.boot.uki.version; versionInfix = if version != null then "_${version}" else ""; triesInfix = if cfg.tries != null then "+${builtins.toString cfg.tries}" else ""; in name + versionInfix + triesInfix + ".efi"; system.build.uki = pkgs.runCommand config.system.boot.loader.ukiFile { } '' mkdir -p $out ${pkgs.buildPackages.systemdUkify}/lib/systemd/ukify build \ --config=${cfg.configFile} \ --output="$out/${config.system.boot.loader.ukiFile}" ''; meta.maintainers = with lib.maintainers; [ nikstur ]; }; }