summary refs log tree commit diff
path: root/nixos/modules/system
diff options
context:
space:
mode:
authorWilliam A. Kennington III <william@wkennington.com>2013-10-21 01:17:23 -0500
committerWilliam A. Kennington III <william@wkennington.com>2014-08-28 13:35:35 -0700
commitc5bdb469ce06cd0b36d1dcd4a977f97644776546 (patch)
treea6fb33e0251ba861ff3682b27d02a84b1fb50337 /nixos/modules/system
parent02ab48d0eea6e37d3432f6b8ce4c31b85e8d3ffe (diff)
downloadnixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar.gz
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar.bz2
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar.lz
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar.xz
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.tar.zst
nixlib-c5bdb469ce06cd0b36d1dcd4a977f97644776546.zip
Update the grub configuration script to handle more complex filesystem layouts including full zfs / and /boot
Diffstat (limited to 'nixos/modules/system')
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl79
1 files changed, 64 insertions, 15 deletions
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index a83733db63b0..b9f61337cefd 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -1,5 +1,6 @@
 use strict;
 use warnings;
+use Class::Struct;
 use XML::LibXML;
 use File::Basename;
 use File::Path;
@@ -47,20 +48,64 @@ print STDERR "updating GRUB $grubVersion menu...\n";
 
 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";
@@ -72,12 +117,14 @@ if ($grubVersion == 1) {
     ";
     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
@@ -98,7 +145,7 @@ else {
           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
@@ -112,7 +159,7 @@ else {
         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
@@ -134,7 +181,7 @@ mkpath("/boot/kernels", 0, 0755) if $copyKernels;
 
 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";
@@ -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 {
@@ -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";
@@ -191,7 +240,7 @@ addEntry("NixOS - Default", $defaultConfig);
 $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 {