forked from mirrors/nixpkgs
First shot at EFI booting.
Note: This feature is INCOMPLETE. Moreover, when runEfibootmgr is true it will MODIFY NVRAM and, on Apple systems, possibly brick your firmware. PLEASE be careful while further testing is performed svn path=/nixos/trunk/; revision=33047
This commit is contained in:
parent
db0e7787ce
commit
001fcad421
118
modules/installer/efi-boot-stub/efi-boot-stub-builder.sh
Normal file
118
modules/installer/efi-boot-stub/efi-boot-stub-builder.sh
Normal file
|
@ -0,0 +1,118 @@
|
|||
#! @bash@/bin/sh -e
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
export PATH=/empty
|
||||
for i in @path@; do PATH=$PATH:$i/bin:$i/sbin; done
|
||||
|
||||
default=$1
|
||||
if test -z "$1"; then
|
||||
echo "Syntax: efi-boot-stub-builder.sh <DEFAULT-CONFIG>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "updating the efi system partition..."
|
||||
|
||||
# Convert a path to a file in the Nix store such as
|
||||
# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
|
||||
# Also, efi executables need the .efi extension
|
||||
cleanName() {
|
||||
local path="$1"
|
||||
echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g' | sed 's|@kernelFile@$|@kernelFile@.efi|'
|
||||
}
|
||||
|
||||
# Copy a file from the Nix store to the EFI system partition
|
||||
declare -A filesCopied
|
||||
|
||||
copyToKernelsDir() {
|
||||
local src="$1"
|
||||
local dst="@efiSysMountPoint@/efi/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 $src $dstTmp
|
||||
mv $dstTmp $dst
|
||||
fi
|
||||
filesCopied[$dst]=1
|
||||
result=$dst
|
||||
}
|
||||
|
||||
# Copy its kernel, initrd, and startup script to the efi system partition
|
||||
# Add the efibootmgr entry if requested
|
||||
addEntry() {
|
||||
local path="$1"
|
||||
local generation="$2"
|
||||
|
||||
if ! test -e $path/kernel -a -e $path/initrd; then
|
||||
return
|
||||
fi
|
||||
|
||||
local kernel=$(readlink -f $path/kernel)
|
||||
local initrd=$(readlink -f $path/initrd)
|
||||
copyToKernelsDir $kernel; kernel=$result
|
||||
copyToKernelsDir $initrd; initrd=$result
|
||||
|
||||
local startup="@efiSysMountPoint@/efi/nixos/$(cleanName $(readlink -f $path))-startup.nsh"
|
||||
if ! test -e $startup; then
|
||||
local dstTmp=$startup.tmp.$$
|
||||
echo "$(echo $kernel | sed 's|@efiSysMountPoint@||' | sed 's|/|\\|g') systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) initrd=$(echo $initrd | sed 's|@efiSysMountPoint@||' | sed 's|/|\\|g') $(cat $path/kernel-params)" > $dstTmp
|
||||
mv $dstTmp $startup
|
||||
fi
|
||||
filesCopied[$startup]=1
|
||||
|
||||
if test -n "@runEfibootmgr@"; then
|
||||
set +e
|
||||
efibootmgr -c -d "@efiDisk@" -g -l $(echo $kernel | sed 's|@efiSysMountPoint@||' | sed 's|/|\\|g') -L "NixOS $generation Generation" -p "@efiPartition@" \
|
||||
-u systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) initrd=$(echo $initrd | sed 's|@efiSysMountPoint@||' | sed 's|/|\\|g') $(cat $path/kernel-params)
|
||||
set -e
|
||||
fi
|
||||
|
||||
if test $(readlink -f "$path") = "$default"; then
|
||||
if test -n "@runEfibootmgr@"; then
|
||||
set +e
|
||||
defaultbootnum=$(efibootmgr | grep "NixOS $generation Generation" | sed 's/Boot//' | sed 's/\*.*//')
|
||||
set -e
|
||||
fi
|
||||
if test -n "@installStartupNsh@"; then
|
||||
sed 's|.*@kernelFile@.efi|@kernelFile@.efi|' < $startup > "@efiSysMountPoint@/startup.nsh"
|
||||
cp $kernel "@efiSysMountPoint@/@kernelFile@.efi"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir -p "@efiSysMountPoint@/efi/nixos/"
|
||||
|
||||
# Remove all old boot manager entries
|
||||
if test -n "@runEfibootmgr@"; then
|
||||
set +e
|
||||
modprobe efivars
|
||||
for bootnum in $(efibootmgr | grep "NixOS" | grep "Generation" | sed 's/Boot//' | sed 's/\*.*//'); do
|
||||
efibootmgr -B -b "$bootnum"
|
||||
set -e
|
||||
done
|
||||
fi
|
||||
|
||||
# Add all generations of the system profile to the system partition, 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
|
||||
|
||||
if test -n "@runEfibootmgr@"; then
|
||||
set +e
|
||||
efibootmgr -o $defaultbootnum
|
||||
set -e
|
||||
fi
|
||||
|
||||
# Remove obsolete files from the EFI system partition
|
||||
for fn in "@efiSysMountPoint@/efi/nixos/"*; do
|
||||
if ! test "${filesCopied[$fn]}" = 1; then
|
||||
rm -vf -- "$fn"
|
||||
fi
|
||||
done
|
98
modules/installer/efi-boot-stub/efi-boot-stub.nix
Normal file
98
modules/installer/efi-boot-stub/efi-boot-stub.nix
Normal file
|
@ -0,0 +1,98 @@
|
|||
{pkgs, config, ...}:
|
||||
|
||||
###### interface
|
||||
let
|
||||
inherit (pkgs.lib) mkOption mkIf;
|
||||
|
||||
options = {
|
||||
boot = {
|
||||
loader = {
|
||||
efiBootStub = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to use the linux kernel as an EFI bootloader.
|
||||
When enabled, the kernel, initrd, and an EFI shell script
|
||||
to boot the system are copied to the EFI system partition.
|
||||
'';
|
||||
};
|
||||
|
||||
efiDisk = mkOption {
|
||||
default = "/dev/sda";
|
||||
description = ''
|
||||
The disk that contains the EFI system partition. Only used by
|
||||
efibootmgr
|
||||
'';
|
||||
};
|
||||
|
||||
efiPartition = mkOption {
|
||||
default = "1";
|
||||
description = ''
|
||||
The partition number of the EFI system partition. Only used by
|
||||
efibootmgr
|
||||
'';
|
||||
};
|
||||
|
||||
efiSysMountPoint = mkOption {
|
||||
default = "/boot";
|
||||
description = ''
|
||||
Where the EFI System Partition is mounted.
|
||||
'';
|
||||
};
|
||||
|
||||
runEfibootmgr = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to run efibootmgr to add the configuration to the boot options list.
|
||||
WARNING! efibootmgr has been rumored to brick Apple firmware! Use 'bless' on
|
||||
Apple efi systems.
|
||||
'';
|
||||
};
|
||||
|
||||
installStartupNsh = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to install a startup.nsh in the root of the EFI system partition.
|
||||
For now, it will just boot the latest version when run, the eventual goal
|
||||
is to have a basic menu-type interface.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
###### implementation
|
||||
let
|
||||
efiBootStubBuilder = pkgs.substituteAll {
|
||||
src = ./efi-boot-stub-builder.sh;
|
||||
isExecutable = true;
|
||||
inherit (pkgs) bash;
|
||||
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep] ++ (pkgs.stdenv.lib.optionals config.boot.loader.efiBootStub.runEfibootmgr [pkgs.efibootmgr pkgs.module_init_tools]);
|
||||
inherit (config.boot.loader.efiBootStub) efiSysMountPoint runEfibootmgr installStartupNsh efiDisk efiPartition;
|
||||
kernelFile = platform.kernelTarget;
|
||||
};
|
||||
|
||||
# Temporary check, for nixos to cope both with nixpkgs stdenv-updates and trunk
|
||||
platform = pkgs.stdenv.platform;
|
||||
in
|
||||
{
|
||||
require = [
|
||||
options
|
||||
|
||||
# config.system.build
|
||||
# ../system/system-options.nix
|
||||
];
|
||||
|
||||
system = mkIf config.boot.loader.efiBootStub.enable {
|
||||
build = {
|
||||
menuBuilder = efiBootStubBuilder;
|
||||
};
|
||||
boot.loader.id = "efiBootStub";
|
||||
boot.loader.kernelFile = platform.kernelTarget;
|
||||
};
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
./hardware/network/rtl8192c.nix
|
||||
./hardware/pcmcia.nix
|
||||
./hardware/all-firmware.nix
|
||||
./installer/efi-boot-stub/efi-boot-stub.nix
|
||||
./installer/generations-dir/generations-dir.nix
|
||||
./installer/grub/grub.nix
|
||||
./installer/init-script/init-script.nix
|
||||
|
|
|
@ -50,6 +50,8 @@ if [ "$action" = "switch" -o "$action" = "boot" ]; then
|
|||
|
||||
elif [ "@bootLoader@" = "generationsDir" ]; then
|
||||
@menuBuilder@ @out@
|
||||
elif [ "@bootLoader@" = "efiBootStub" ]; then
|
||||
@menuBuilder@ @out@
|
||||
else
|
||||
echo "Warning: don't know how to make this configuration bootable; please enable a boot loader." 1>&2
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue