diff options
author | Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> | 2015-05-02 05:56:48 +0300 |
---|---|---|
committer | Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> | 2015-05-17 23:38:03 +0300 |
commit | 6d176afe5e3664e2a522afcc59c5dc3a5b40c455 (patch) | |
tree | 7f1fe38eacac21844d70410800137fb0b07a2e9b /nixos/modules/system/boot/loader/generic-extlinux-compatible | |
parent | e47fe46e031d2df000f2baee598b2553e5ca93f6 (diff) |
generic-extlinux-compatible: Add new bootloader for ARM
This module generates a /boot/extlinux/extlinux.conf bootloader
configuration file that is supported by e.g. U-Boot:
http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro;hb=refs/heads/master
With this, all ARM boards supported by U-Boot can be booted in a common
way (a single boot file generator, all boards booting via initrd like
x86) and with same boot menu functionality as GRUB has.
-- sample extlinux.conf file --
# Generated file, all changes will be lost on nixos-rebuild!
# Change this to e.g. nixos-42 to temporarily boot to an older configuration.
DEFAULT nixos-default
TIMEOUT 50
LABEL nixos-default
MENU LABEL NixOS - Default
LINUX ../nixos/n7vxfk60nb5h0mcbhkwwxhcz2q2nvxzv-linux-4.1.0-rc3-cpufreq-zImage
INITRD ../nixos/0ss2zs8sb6d1qn4gblxpwlxkfjsgs5f0-initrd-initrd
FDTDIR ../nixos/n7vxfk60nb5h0mcbhkwwxhcz2q2nvxzv-linux-4.1.0-rc3-cpufreq-dtbs
APPEND systemConfig=/nix/store/469qvr43ln8bfsnk5lzcz6m6jfcgdd4r-nixos-15.06.git.0b7a7a6M init=/nix/store/469qvr43ln8bfsnk5lzcz6m6jfcgdd4r-nixos-15.06.git.0b7a7a6M/init loglevel=8 console=ttyS0,115200n8 drm.debug=0xf
LABEL nixos-71
MENU LABEL NixOS - Configuration 71 (2015-05-17 21:32 - 15.06.git.0b7a7a6M)
LINUX ../nixos/n7vxfk60nb5h0mcbhkwwxhcz2q2nvxzv-linux-4.1.0-rc3-cpufreq-zImage
INITRD ../nixos/0ss2zs8sb6d1qn4gblxpwlxkfjsgs5f0-initrd-initrd
FDTDIR ../nixos/n7vxfk60nb5h0mcbhkwwxhcz2q2nvxzv-linux-4.1.0-rc3-cpufreq-dtbs
APPEND systemConfig=/nix/store/469qvr43ln8bfsnk5lzcz6m6jfcgdd4r-nixos-15.06.git.0b7a7a6M init=/nix/store/469qvr43ln8bfsnk5lzcz6m6jfcgdd4r-nixos-15.06.git.0b7a7a6M/init loglevel=8 console=ttyS0,115200n8 drm.debug=0xf
Diffstat (limited to 'nixos/modules/system/boot/loader/generic-extlinux-compatible')
3 files changed, 184 insertions, 0 deletions
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix b/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix new file mode 100644 index 000000000000..af39c7bb6841 --- /dev/null +++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + blCfg = config.boot.loader; + cfg = blCfg.generic-extlinux-compatible; + + timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout; + + builder = import ./extlinux-conf-builder.nix { inherit pkgs; }; +in +{ + options = { + boot.loader.generic-extlinux-compatible = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to generate an extlinux-compatible configuration file + under <literal>/boot/extlinux.conf</literal>. For instance, + U-Boot's generic distro boot support uses this file format. + + See <link xlink:href="http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro;hb=refs/heads/master">U-boot's documentation</link> + for more information. + ''; + }; + + configurationLimit = mkOption { + default = 20; + example = 10; + type = types.int; + description = '' + Maximum number of configurations in the boot menu. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + system.build.installBootLoader = "${builder} -g ${toString cfg.configurationLimit} -t ${timeoutStr} -c"; + system.boot.loader.id = "generic-extlinux-compatible"; + }; +} diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix new file mode 100644 index 000000000000..261192c6d24e --- /dev/null +++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix @@ -0,0 +1,8 @@ +{ pkgs }: + +pkgs.substituteAll { + src = ./extlinux-conf-builder.sh; + isExecutable = true; + inherit (pkgs) bash; + path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; +} diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh new file mode 100644 index 000000000000..8f2a496de8b6 --- /dev/null +++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh @@ -0,0 +1,132 @@ +#! @bash@/bin/sh -e + +shopt -s nullglob + +export PATH=/empty +for i in @path@; do PATH=$PATH:$i/bin; done + +usage() { + echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>]" >&2 + exit 1 +} + +timeout= # Timeout in centiseconds +default= # Default configuration +target=/boot # Target directory +numGenerations=0 # Number of other generations to include in the menu + +while getopts "t:c:d:g:" opt; do + case "$opt" in + t) # U-Boot interprets '0' as infinite and negative as instant boot + if [ "$OPTARG" -lt 0 ]; then + timeout=0 + elif [ "$OPTARG" = 0 ]; then + timeout=-10 + else + timeout=$((OPTARG * 10)) + fi + ;; + c) default="$OPTARG" ;; + d) target="$OPTARG" ;; + g) numGenerations="$OPTARG" ;; + \?) usage ;; + esac +done + +[ "$timeout" = "" -o "$default" = "" ] && usage + +mkdir -p $target/nixos +mkdir -p $target/extlinux + +# 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 $target/nixos. +declare -A filesCopied + +copyToKernelsDir() { + local src=$(readlink -f "$1") + local dst="$target/nixos/$(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 -r $src $dstTmp + mv $dstTmp $dst + fi + filesCopied[$dst]=1 + result=$dst +} + +# Copy its kernel, initrd and dtbs to $target/nixos, and echo out an +# extlinux menu entry +addEntry() { + local path=$(readlink -f "$1") + local tag="$2" # Generation number or 'default' + + if ! test -e $path/kernel -a -e $path/initrd; then + return + fi + + copyToKernelsDir "$path/kernel"; kernel=$result + copyToKernelsDir "$path/initrd"; initrd=$result + # XXX UGLY: maybe the system config should have a top-level "dtbs" entry? + copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result + + timestampEpoch=$(stat -L -c '%Z' $path) + + timestamp=$(date "+%Y-%m-%d %H:%M" -d @$timestampEpoch) + nixosVersion="$(cat $path/nixos-version)" + extraParams="$(cat $path/kernel-params)" + + echo + echo "LABEL nixos-$tag" + if [ "$tag" = "default" ]; then + echo " MENU LABEL NixOS - Default" + else + echo " MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosVersion)" + fi + echo " LINUX ../nixos/$(basename $kernel)" + echo " INITRD ../nixos/$(basename $initrd)" + echo " FDTDIR ../nixos/$(basename $dtbs)" + echo " APPEND systemConfig=$path init=$path/init $extraParams" +} + +tmpFile="$target/extlinux/extlinux.conf.tmp.$$" + +cat > $tmpFile <<EOF +# Generated file, all changes will be lost on nixos-rebuild! + +# Change this to e.g. nixos-42 to temporarily boot to an older configuration. +DEFAULT nixos-default + +TIMEOUT $timeout +$(addEntry $default default) +EOF + +# Add up to $numGenerations 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 \ + | head -n $numGenerations); do + link=/nix/var/nix/profiles/system-$generation-link + addEntry $link $generation +done >> $tmpFile + +mv -f $tmpFile $target/extlinux/extlinux.conf + +# Remove obsolete files from $target/nixos. +for fn in $target/nixos/*; do + if ! test "${filesCopied[$fn]}" = 1; then + echo "Removing no longer needed boot file: $fn" + chmod +w -- "$fn" + rm -rf -- "$fn" + fi +done |