Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions nixos/modules/system/boot/loader/grub/install-grub.pl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use strict;
use warnings;
use Class::Struct;
use XML::LibXML;
use File::Basename;
use File::Path;
Expand Down Expand Up @@ -47,20 +48,64 @@ sub writeFile {

mkpath("/boot/grub", 0, 0700);


# Discover whether /boot is on the same filesystem as / and
# /nix/store. 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.
my $bootRoot = "/boot";
if (stat("/")->dev != stat("/boot")->dev) {
$bootRoot = "";
$copyKernels = 1;
} elsif (stat("/boot")->dev != stat("/nix/store")->dev) {
# /boot.
if (stat("/boot")->dev != stat("/nix")->dev) {
$copyKernels = 1;
}

# Discover information about the location of /boot
struct(Fs => {
device => '$',
type => '$',
mount => '$',
});
sub GetFs {
my ($dir) = @_;
my @boot = split(/[ \n\t]+/, `df -T "$dir" | tail -n 1`);
return Fs->new(device => $boot[0], type => $boot[1], mount => $boot[6]);
}
struct (Grub => {
path => '$',
search => '$',
});
my $driveid = 1;
sub GrubFs {
my ($dir) = @_;
my $fs = GetFs($dir);
my $path = "/" . substr($dir, length($fs->mount));
my $search = "";
if ($grubVersion > 1) {
if ($fs->type eq "zfs") {
my $sid = index($fs->device, "/");
if ($sid < 0) {
$search = "--label " . $fs->device;
$path = "/@" . $path;
} else {
$search = "--label " . substr($fs->device, 0, $sid);
$path = "/" . substr($fs->device, $sid) . "/@" . $path;
}
} else {
my $lbl = "/dev/disk/by-label/";
if (index($fs->device, $lbl) == 0) {
$search = "--label " . substr($fs->device, length($lbl));
}
my $uuid = "/dev/disk/by-uuid/";
if (index($fs->device, $uuid) == 0) {
$search = "--fs-uuid " . substr($fs->device, length($uuid));
}
}
if (not $search eq "") {
$search = "search --set=drive$driveid " . $search;
$path = "(\$drive$driveid)" . $path;
$driveid += 1;
}
}
return Grub->new(path => $path, search => $search);
}
my $grubBoot = GrubFs("/boot");
my $grubStore = GrubFs("/nix");

# Generate the header.
my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n";
Expand All @@ -72,12 +117,14 @@ sub writeFile {
";
if ($splashImage) {
copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n";
$conf .= "splashimage $bootRoot/background.xpm.gz\n";
$conf .= "splashimage " . $grubBoot->path . "/background.xpm.gz\n";
}
}

else {
$conf .= "
" . $grubBoot->search . "
" . $grubStore->search . "
if [ -s \$prefix/grubenv ]; then
load_env
fi
Expand All @@ -98,7 +145,7 @@ sub writeFile {
set timeout=$timeout
fi

if loadfont $bootRoot/grub/fonts/unicode.pf2; then
if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
set gfxmode=640x480
insmod gfxterm
insmod vbe
Expand All @@ -112,7 +159,7 @@ sub writeFile {
copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
$conf .= "
insmod png
if background_image $bootRoot/background.png; then
if background_image " . $grubBoot->path . "/background.png; then
set color_normal=white/black
set color_highlight=black/white
else
Expand All @@ -134,7 +181,7 @@ sub writeFile {

sub copyToKernelsDir {
my ($path) = @_;
return $path unless $copyKernels;
return $grubStore->path . substr($path, length("/nix")) unless $copyKernels;
$path =~ /\/nix\/store\/(.*)/ or die;
my $name = $1; $name =~ s/\//-/g;
my $dst = "/boot/kernels/$name";
Expand All @@ -147,7 +194,7 @@ sub copyToKernelsDir {
rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
}
$copied{$dst} = 1;
return "$bootRoot/kernels/$name";
return $grubBoot->path . "/kernels/$name";
}

sub addEntry {
Expand All @@ -174,6 +221,8 @@ sub addEntry {
$conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n";
} else {
$conf .= "menuentry \"$name\" {\n";
$conf .= $grubBoot->search . "\n";
$conf .= $grubStore->search . "\n";
$conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig;
$conf .= " multiboot $xen $xenParams\n" if $xen;
$conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
Expand All @@ -191,7 +240,7 @@ sub addEntry {
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;

# extraEntries could refer to @bootRoot@, which we have to substitute
$conf =~ s/\@bootRoot\@/$bootRoot/g;
$conf =~ s/\@bootRoot\@/$grubBoot->path/g;

# Emit submenus for all system profiles.
sub addProfile {
Expand Down
28 changes: 14 additions & 14 deletions pkgs/tools/misc/grub/2.0x.nix
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{ fetchurl, stdenv, flex, bison, gettext, ncurses, libusb, freetype, qemu
, devicemapper, EFIsupport ? false }:
{ fetchurl, fetchgit, stdenv, autogen, flex, bison, python, autoconf, automake, gettext, ncurses, libusb, freetype, qemu
, devicemapper, linuxPackages, EFIsupport ? false }:

let

prefix = "grub${if EFIsupport then "-efi" else ""}";

version = "2.00";
revision = "bc8a613";

unifont_bdf = fetchurl {
url = "http://unifoundry.com/unifont-5.1.20080820.bdf.gz";
Expand All @@ -15,15 +16,16 @@ let
in

stdenv.mkDerivation rec {
name = "${prefix}-${version}";
name = "${prefix}-${version}.${toString revision}";

src = fetchurl {
url = "mirror://gnu/grub/grub-${version}.tar.xz";
sha256 = "0n64hpmsccvicagvr0c6v0kgp2yw0kgnd3jvsyd26cnwgs7c6kkq";
src = fetchgit {
url = "http://git.savannah.gnu.org/r/grub.git/";
rev = "bc8a6137b23292771d8b1a9bd0b32288c3d94e7d";
sha256 = "10z3nyngplzmp7267w4cqwwrh986jfd5rq9mm2yyp68nabk1s806";
};

nativeBuildInputs = [ flex bison ];
buildInputs = [ ncurses libusb freetype gettext devicemapper ]
nativeBuildInputs = [ autogen flex bison python autoconf automake ];
buildInputs = [ ncurses libusb freetype gettext devicemapper linuxPackages.zfs ]
++ stdenv.lib.optional doCheck qemu;

preConfigure =
Expand All @@ -43,14 +45,11 @@ stdenv.mkDerivation rec {
# See <http://www.mail-archive.com/qemu-devel@nongnu.org/msg22775.html>.
sed -i "tests/util/grub-shell.in" \
-e's/qemu-system-i386/qemu-system-x86_64 -nodefaults/g'

# Fix for building on Glibc 2.16. Won't be needed once the
# gnulib in grub is updated.
sed -i '/gets is a security hole/d' grub-core/gnulib/stdio.in.h
'';

prePatch =
'' gunzip < "${unifont_bdf}" > "unifont.bdf"
'' sh autogen.sh
gunzip < "${unifont_bdf}" > "unifont.bdf"
sed -i "configure" \
-e "s|/usr/src/unifont.bdf|$PWD/unifont.bdf|g"
'';
Expand All @@ -62,7 +61,8 @@ stdenv.mkDerivation rec {
else if stdenv.system == "x86_64-linux" then "x86_64"
else throw "unsupported EFI firmware architecture";
in
stdenv.lib.optionals EFIsupport
[ "--enable-libzfs" ] ++
stdenv.lib.optionals EFIsupport
[ "--with-platform=efi" "--target=${arch}" "--program-prefix=" ];

doCheck = false;
Expand Down
2 changes: 1 addition & 1 deletion pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,7 @@ let
buggyBiosCDSupport = config.grub.buggyBiosCDSupport or true;
};

grub2 = callPackage ../tools/misc/grub/2.0x.nix { libusb = libusb1; };
grub2 = callPackage ../tools/misc/grub/2.0x.nix { };

grub2_efi = grub2.override { EFIsupport = true; };

Expand Down