deb4f88c2c
partition from /. If so, copy the kernels and initrds to /boot and use paths relative to /boot in the GRUB configuration file. This makes the boot.loader.grub.bootDevice option obsolete. (Is there a way to mark obsolete options?) It also makes it unnecessary to set boot.loader.grub.copyKernels, although that option is still available since it can speed up GRUB if the Nix store is very large. svn path=/nixos/trunk/; revision=18998
257 lines
6.3 KiB
Bash
257 lines
6.3 KiB
Bash
#! @bash@/bin/sh -e
|
|
|
|
shopt -s nullglob
|
|
|
|
export PATH=/empty
|
|
for i in @path@; do PATH=$PATH:$i/bin; done
|
|
|
|
if test $# -ne 1; then
|
|
echo "Usage: grub-menu-builder.sh DEFAULT-CONFIG"
|
|
exit 1
|
|
fi
|
|
|
|
grubVersion="@version@"
|
|
defaultConfig="$1"
|
|
|
|
case "$grubVersion" in
|
|
1|2)
|
|
echo "updating GRUB $grubVersion menu..."
|
|
;;
|
|
*)
|
|
echo "Unsupported GRUB version \`$grubVersion'" >&2
|
|
echo "Supported versions are \`1' (GRUB Legacy) and \`2' (GRUB 1.9x)." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
|
|
# Discover whether /boot is on the same filesystem as /. If not, then
|
|
# all kernels and initrds must be copied to /boot, and all paths in
|
|
# the GRUB config file must be relative to the root of the /boot
|
|
# filesystem. `$bootRoot' is the path to be prepended to paths under
|
|
# /boot.
|
|
if [ "$(stat -f -c '%i' /)" = "$(stat -f -c '%i' /boot)" ]; then
|
|
bootRoot=/boot
|
|
copyKernels="@copyKernels@" # user can override in the NixOS config
|
|
else
|
|
bootRoot=
|
|
copyKernels=1
|
|
fi
|
|
|
|
|
|
prologue() {
|
|
case "$grubVersion" in
|
|
1)
|
|
cp -f "@splashImage@" /boot/background.xpm.gz
|
|
cat > "$1" << GRUBEND
|
|
# Automatically generated. DO NOT EDIT THIS FILE!
|
|
default @default@
|
|
timeout @timeout@
|
|
GRUBEND
|
|
if test -n "@splashImage@"; then
|
|
echo "splashimage $bootRoot/background.xpm.gz" >> "$1"
|
|
fi
|
|
;;
|
|
2)
|
|
cp -f @grub@/share/grub/unicode.pf2 /boot/grub/unicode.pf2
|
|
cat > "$1" <<EOF
|
|
# Automatically generated. DO NOT EDIT THIS FILE!
|
|
set default=@default@
|
|
set timeout=@timeout@
|
|
if loadfont $bootRoot/grub/unicode.pf2; then
|
|
set gfxmode=640x480
|
|
insmod gfxterm
|
|
insmod vbe
|
|
terminal_output gfxterm
|
|
fi
|
|
EOF
|
|
if test -n "@splashImage@"; then
|
|
cp -f "@splashImage@" /boot/background.png
|
|
# FIXME: GRUB 1.97 doesn't resize the background image
|
|
# if it doesn't match the video resolution.
|
|
cat >> "$1" <<EOF
|
|
insmod png
|
|
if background_image $bootRoot/background.png; then
|
|
set color_normal=white/black
|
|
set color_highlight=black/white
|
|
else
|
|
set menu_color_normal=cyan/blue
|
|
set menu_color_highlight=white/blue
|
|
fi
|
|
EOF
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
case "$grubVersion" in
|
|
1) target="/boot/grub/menu.lst";;
|
|
2) target="/boot/grub/grub.cfg";;
|
|
esac
|
|
|
|
tmp="$target.tmp"
|
|
|
|
prologue "$tmp"
|
|
|
|
|
|
configurationCounter=0
|
|
configurationLimit="@configurationLimit@"
|
|
numAlienEntries=`cat <<EOF | egrep '^[[:space:]]*title' | wc -l
|
|
@extraEntries@
|
|
EOF`
|
|
|
|
if test $((configurationLimit+numAlienEntries)) -gt 190; then
|
|
configurationLimit=$((190-numAlienEntries));
|
|
fi
|
|
|
|
|
|
# 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 p="kernels/$(cleanName $src)"
|
|
local dst="/boot/$p"
|
|
# 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="$bootRoot/$p"
|
|
}
|
|
|
|
|
|
# Add an entry for a configuration to the Grub menu, and if
|
|
# appropriate, copy its kernel and initrd to /boot/kernels.
|
|
addEntry() {
|
|
local name="$1"
|
|
local path="$2"
|
|
local shortSuffix="$3"
|
|
|
|
configurationCounter=$((configurationCounter + 1))
|
|
if test $configurationCounter -gt @configurationLimit@; then
|
|
return
|
|
fi
|
|
|
|
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 "$path" = "$defaultConfig"; then
|
|
cp "$kernel" /boot/nixos-kernel
|
|
cp "$initrd" /boot/nixos-initrd
|
|
cp "$(readlink -f "$path/init")" /boot/nixos-init
|
|
case "$grubVersion" in
|
|
1)
|
|
cat > /boot/nixos-grub-config <<EOF
|
|
title Emergency boot
|
|
kernel $bootRoot/nixos-kernel systemConfig=$(readlink -f "$path") init=/boot/nixos-init $(cat "$path/kernel-params")
|
|
initrd $bootRoot/nixos-initrd
|
|
EOF
|
|
;;
|
|
2)
|
|
cat > /boot/nixos-grub-config <<EOF
|
|
menuentry "Emergency boot" {
|
|
linux $bootRoot/nixos-kernel systemConfig=$(readlink -f "$path") init=/boot/nixos-init $(cat "$path/kernel-params")
|
|
initrd $bootRoot/initrd
|
|
}
|
|
EOF
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
if test -n "$copyKernels"; then
|
|
copyToKernelsDir $kernel; kernel=$result
|
|
copyToKernelsDir $initrd; initrd=$result
|
|
fi
|
|
|
|
local confName=$(cat $path/configuration-name 2>/dev/null)
|
|
if test -n "$confName"; then
|
|
name="$confName $3"
|
|
fi
|
|
|
|
case "$grubVersion" in
|
|
1)
|
|
cat >> "$tmp" << GRUBEND
|
|
title $name
|
|
kernel $kernel systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params)
|
|
initrd $initrd
|
|
GRUBEND
|
|
;;
|
|
2)
|
|
cat >> "$tmp" << GRUBEND
|
|
menuentry "$name" {
|
|
linux $kernel systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params)
|
|
initrd $initrd
|
|
}
|
|
GRUBEND
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
if test -n "$copyKernels"; then
|
|
mkdir -p /boot/kernels
|
|
fi
|
|
|
|
|
|
# Additional entries specified verbatim by the configuration.
|
|
extraEntries=`cat <<EOF
|
|
@extraEntries@
|
|
EOF`
|
|
|
|
|
|
if test -n "@extraEntriesBeforeNixOS@"; then
|
|
echo "$extraEntries" >> $tmp
|
|
fi
|
|
|
|
addEntry "NixOS - Default" $defaultConfig ""
|
|
|
|
if test -z "@extraEntriesBeforeNixOS@"; then
|
|
echo "$extraEntries" >> $tmp
|
|
fi
|
|
|
|
# Add all generations of the system profile to the menu, in reverse
|
|
# (most recent to least recent) order.
|
|
for link in $((ls -d $defaultConfig/fine-tune/* ) | sort -n); do
|
|
date=$(stat --printf="%y\n" $link | sed 's/\..*//')
|
|
addEntry "NixOS - variation" $link ""
|
|
done
|
|
|
|
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
|
|
date=$(stat --printf="%y\n" $link | sed 's/\..*//')
|
|
kernelVersion=$(cd $(dirname $(readlink -f $link/kernel))/lib/modules && echo *)
|
|
addEntry "NixOS - Configuration $generation ($date - $kernelVersion)" $link "$generation ($date)"
|
|
done
|
|
|
|
|
|
# Atomically update the GRUB configuration file.
|
|
mv $tmp $target
|
|
|
|
|
|
# Remove obsolete files from /boot/kernels.
|
|
for fn in /boot/kernels/*; do
|
|
if ! test "${filesCopied[$fn]}" = 1; then
|
|
rm -vf -- "$fn"
|
|
fi
|
|
done
|