nixpkgs/nixos/modules/system/boot/uki.nix
Jared Baur 2837c0d9aa
nixos/uki: add ".dtb" section if devicetree is used
This ensures a ".dtb" PE section makes it into the UKI so systemd-stub
can install the correct devicetree for use by the Linux kernel. This is
often needed on systems that boot with u-boot since the devicetree used
by u-boot is often a paired down version of what the Linux kernel needs.
On those kinds of boards, the lack of this PE section means that u-boot
will end up installing its internal devicetree into the UEFI
configuration table, which is what the Linux kernel ends up using.
2024-03-11 12:42:21 -07:00

102 lines
3.4 KiB
Nix

{ config, lib, pkgs, ... }:
let
cfg = config.boot.uki;
inherit (pkgs.stdenv.hostPlatform) efiArch;
format = pkgs.formats.ini { };
ukifyConfig = format.generate "ukify.conf" cfg.settings;
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.
'';
};
};
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}";
};
};
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=${ukifyConfig} \
--output="$out/${config.system.boot.loader.ukiFile}"
'';
meta.maintainers = with lib.maintainers; [ nikstur ];
};
}