Update the grub configuration script to handle more complex filesystem layouts including full zfs / and /boot
This commit is contained in:
parent
02ab48d0ee
commit
c5bdb469ce
@ -1,5 +1,6 @@
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
use Class::Struct;
|
||||||
use XML::LibXML;
|
use XML::LibXML;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
use File::Path;
|
use File::Path;
|
||||||
@ -47,20 +48,64 @@ print STDERR "updating GRUB $grubVersion menu...\n";
|
|||||||
|
|
||||||
mkpath("/boot/grub", 0, 0700);
|
mkpath("/boot/grub", 0, 0700);
|
||||||
|
|
||||||
|
|
||||||
# Discover whether /boot is on the same filesystem as / and
|
# Discover whether /boot is on the same filesystem as / and
|
||||||
# /nix/store. If not, then all kernels and initrds must be copied to
|
# /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
|
# /boot.
|
||||||
# root of the /boot filesystem. `$bootRoot' is the path to be
|
if (stat("/boot")->dev != stat("/nix")->dev) {
|
||||||
# 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) {
|
|
||||||
$copyKernels = 1;
|
$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.
|
# Generate the header.
|
||||||
my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n";
|
my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n";
|
||||||
@ -72,12 +117,14 @@ if ($grubVersion == 1) {
|
|||||||
";
|
";
|
||||||
if ($splashImage) {
|
if ($splashImage) {
|
||||||
copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n";
|
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 {
|
else {
|
||||||
$conf .= "
|
$conf .= "
|
||||||
|
" . $grubBoot->search . "
|
||||||
|
" . $grubStore->search . "
|
||||||
if [ -s \$prefix/grubenv ]; then
|
if [ -s \$prefix/grubenv ]; then
|
||||||
load_env
|
load_env
|
||||||
fi
|
fi
|
||||||
@ -98,7 +145,7 @@ else {
|
|||||||
set timeout=$timeout
|
set timeout=$timeout
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if loadfont $bootRoot/grub/fonts/unicode.pf2; then
|
if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
|
||||||
set gfxmode=640x480
|
set gfxmode=640x480
|
||||||
insmod gfxterm
|
insmod gfxterm
|
||||||
insmod vbe
|
insmod vbe
|
||||||
@ -112,7 +159,7 @@ else {
|
|||||||
copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
|
copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
|
||||||
$conf .= "
|
$conf .= "
|
||||||
insmod png
|
insmod png
|
||||||
if background_image $bootRoot/background.png; then
|
if background_image " . $grubBoot->path . "/background.png; then
|
||||||
set color_normal=white/black
|
set color_normal=white/black
|
||||||
set color_highlight=black/white
|
set color_highlight=black/white
|
||||||
else
|
else
|
||||||
@ -134,7 +181,7 @@ mkpath("/boot/kernels", 0, 0755) if $copyKernels;
|
|||||||
|
|
||||||
sub copyToKernelsDir {
|
sub copyToKernelsDir {
|
||||||
my ($path) = @_;
|
my ($path) = @_;
|
||||||
return $path unless $copyKernels;
|
return $grubStore->path . substr($path, length("/nix")) unless $copyKernels;
|
||||||
$path =~ /\/nix\/store\/(.*)/ or die;
|
$path =~ /\/nix\/store\/(.*)/ or die;
|
||||||
my $name = $1; $name =~ s/\//-/g;
|
my $name = $1; $name =~ s/\//-/g;
|
||||||
my $dst = "/boot/kernels/$name";
|
my $dst = "/boot/kernels/$name";
|
||||||
@ -147,7 +194,7 @@ sub copyToKernelsDir {
|
|||||||
rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
|
rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
|
||||||
}
|
}
|
||||||
$copied{$dst} = 1;
|
$copied{$dst} = 1;
|
||||||
return "$bootRoot/kernels/$name";
|
return $grubBoot->path . "/kernels/$name";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub addEntry {
|
sub addEntry {
|
||||||
@ -174,6 +221,8 @@ sub addEntry {
|
|||||||
$conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n";
|
$conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n";
|
||||||
} else {
|
} else {
|
||||||
$conf .= "menuentry \"$name\" {\n";
|
$conf .= "menuentry \"$name\" {\n";
|
||||||
|
$conf .= $grubBoot->search . "\n";
|
||||||
|
$conf .= $grubStore->search . "\n";
|
||||||
$conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig;
|
$conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig;
|
||||||
$conf .= " multiboot $xen $xenParams\n" if $xen;
|
$conf .= " multiboot $xen $xenParams\n" if $xen;
|
||||||
$conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
|
$conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";
|
||||||
@ -191,7 +240,7 @@ addEntry("NixOS - Default", $defaultConfig);
|
|||||||
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
|
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
|
||||||
|
|
||||||
# extraEntries could refer to @bootRoot@, which we have to substitute
|
# 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.
|
# Emit submenus for all system profiles.
|
||||||
sub addProfile {
|
sub addProfile {
|
||||||
|
Loading…
Reference in New Issue
Block a user