diff options
Diffstat (limited to 'nixos/modules/system/boot/loader/generations-dir')
-rw-r--r-- | nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh | 106 | ||||
-rw-r--r-- | nixos/modules/system/boot/loader/generations-dir/generations-dir.nix | 62 |
2 files changed, 168 insertions, 0 deletions
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh b/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh new file mode 100644 index 00000000000..8ae23dc988c --- /dev/null +++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh @@ -0,0 +1,106 @@ +#! @bash@/bin/sh -e + +shopt -s nullglob + +export PATH=/empty +for i in @path@; do PATH=$PATH:$i/bin; done + +default=$1 +if test -z "$1"; then + echo "Syntax: generations-dir-builder.sh <DEFAULT-CONFIG>" + exit 1 +fi + +echo "updating the boot generations directory..." + +mkdir -p /boot + +rm -Rf /boot/system* || true + +target=/boot/grub/menu.lst +tmp=$target.tmp + +# Convert a path to a file in the Nix store such as +# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>. +cleanName() { + local path="$1" + echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g' +} + +# Copy a file from the Nix store to /boot/kernels. +declare -A filesCopied + +copyToKernelsDir() { + local src="$1" + local dst="/boot/kernels/$(cleanName $src)" + # Don't copy the file if $dst already exists. This means that we + # have to create $dst atomically to prevent partially copied + # kernels or initrd if this script is ever interrupted. + if ! test -e $dst; then + local dstTmp=$dst.tmp.$$ + cp $src $dstTmp + mv $dstTmp $dst + fi + filesCopied[$dst]=1 + result=$dst +} + + +# Copy its kernel and initrd to /boot/kernels. +addEntry() { + local path="$1" + local generation="$2" + local outdir=/boot/system-$generation + + if ! test -e $path/kernel -a -e $path/initrd; then + return + fi + + local kernel=$(readlink -f $path/kernel) + local initrd=$(readlink -f $path/initrd) + + if test -n "@copyKernels@"; then + copyToKernelsDir $kernel; kernel=$result + copyToKernelsDir $initrd; initrd=$result + fi + + mkdir -p $outdir + ln -sf $(readlink -f $path) $outdir/system + ln -sf $(readlink -f $path/init) $outdir/init + ln -sf $initrd $outdir/initrd + ln -sf $kernel $outdir/kernel + + if test $(readlink -f "$path") = "$default"; then + cp "$kernel" /boot/nixos-kernel + cp "$initrd" /boot/nixos-initrd + cp "$(readlink -f "$path/init")" /boot/nixos-init + + mkdir -p /boot/default + # ln -sfT: overrides target even if it exists. + ln -sfT $(readlink -f $path) /boot/default/system + ln -sfT $(readlink -f $path/init) /boot/default/init + ln -sfT $initrd /boot/default/initrd + ln -sfT $kernel /boot/default/kernel + fi +} + +if test -n "@copyKernels@"; then + mkdir -p /boot/kernels +fi + +# Add all generations of the system profile to the menu, in reverse +# (most recent to least recent) order. +for generation in $( + (cd /nix/var/nix/profiles && ls -d system-*-link) \ + | sed 's/system-\([0-9]\+\)-link/\1/' \ + | sort -n -r); do + link=/nix/var/nix/profiles/system-$generation-link + addEntry $link $generation +done + +# Remove obsolete files from /boot/kernels. +for fn in /boot/kernels/*; do + if ! test "${filesCopied[$fn]}" = 1; then + rm -vf -- "$fn" + fi +done diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix new file mode 100644 index 00000000000..1437ab38770 --- /dev/null +++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + generationsDirBuilder = pkgs.substituteAll { + src = ./generations-dir-builder.sh; + isExecutable = true; + inherit (pkgs) bash; + path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; + inherit (config.boot.loader.generationsDir) copyKernels; + }; + +in + +{ + options = { + + boot.loader.generationsDir = { + + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to create symlinks to the system generations under + <literal>/boot</literal>. When enabled, + <literal>/boot/default/kernel</literal>, + <literal>/boot/default/initrd</literal>, etc., are updated to + point to the current generation's kernel image, initial RAM + disk, and other bootstrap files. + + This optional is not necessary with boot loaders such as GNU GRUB + for which the menu is updated to point to the latest bootstrap + files. However, it is needed for U-Boot on platforms where the + boot command line is stored in flash memory rather than in a + menu file. + ''; + }; + + copyKernels = mkOption { + default = false; + type = types.bool; + description = '' + Whether copy the necessary boot files into /boot, so + /nix/store is not needed by the boot loader. + ''; + }; + + }; + + }; + + + config = mkIf config.boot.loader.generationsDir.enable { + + system.build.installBootLoader = generationsDirBuilder; + system.boot.loader.id = "generationsDir"; + system.boot.loader.kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target; + + }; +} |