Skip to content

Commit

Permalink
install-grub.pl: support bindmounts
Browse files Browse the repository at this point in the history
Specifically this allows bind-mounting your `/boot` directory with
NixOS impermanence.
  • Loading branch information
kira-bruneau committed Jan 17, 2025
1 parent 8f4a4fb commit 1dcd74f
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 32 deletions.
3 changes: 1 addition & 2 deletions nixos/modules/system/boot/loader/grub/grub.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ let
timeoutStyle
;
path = with pkgs; makeBinPath (
[ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ]
[ coreutils gnused gnugrep findutils diffutils util-linux mdadm ]
++ optional cfg.efiSupport efibootmgr
++ optionals cfg.useOSProber [ busybox os-prober ]);
font = lib.optionalString (cfg.font != null) (
Expand Down Expand Up @@ -730,7 +730,6 @@ in
install-grub-pl = pkgs.substituteAll {
src = ./install-grub.pl;
utillinux = pkgs.util-linux;
btrfsprogs = pkgs.btrfs-progs;
inherit (config.system.nixos) distroName;
};
perl = pkgs.perl.withPackages (p: with p; [
Expand Down
34 changes: 4 additions & 30 deletions nixos/modules/system/boot/loader/grub/install-grub.pl
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,20 @@ sub runCommand {
# Discover information about the location of the bootPath
struct(Fs => {
device => '$',
root => '$',
type => '$',
mount => '$',
});

# Figure out what filesystem is used for the directory with init/initrd/kernel files
sub GetFs {
my ($dir) = @_;
my ($status, @pathInfo) = runCommand("@utillinux@/bin/findmnt", "-n", "-v", "-o", "SOURCE,FSTYPE,TARGET", "-T", @{[$dir]});
my ($status, @pathInfo) = runCommand("@utillinux@/bin/findmnt", "-n", "-v", "-o", "SOURCE,FSROOT,FSTYPE,TARGET", "-T", @{[$dir]});
if ($status != 0 || @pathInfo != 1) {
die "Failed to get file system (returned $status) for @{[$dir]}";
}
my @fields = split /\s+/, $pathInfo[0];
return Fs->new(device => $fields[0], type => $fields[1], mount => $fields[2]);
return Fs->new(device => $fields[0], root => $fields[1], type => $fields[2], mount => $fields[3]);
}
struct (Grub => {
path => '$',
Expand All @@ -132,10 +133,7 @@ sub GetFs {
sub GrubFs {
my ($dir) = @_;
my $fs = GetFs($dir);
my $path = substr($dir, length($fs->mount));
if (substr($path, 0, 1) ne "/") {
$path = "/$path";
}
my $path = File::Spec->catdir($fs->root, substr($dir, length($fs->mount)));
my $search = "";

# ZFS is completely separate logic as zpools are always identified by a label
Expand Down Expand Up @@ -177,30 +175,6 @@ sub GrubFs {
}
$search .= $matches[0];
}

# BTRFS is a special case in that we need to fix the referenced path based on subvolumes
if ($fs->type eq 'btrfs') {
my ($status, @id_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "show", @{[$fs->mount]});
if ($status != 0) {
die "Failed to retrieve subvolume info for @{[$fs->mount]}\n";
}
my @ids = join("\n", @id_info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s;
if ($#ids > 0) {
die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
} elsif ($#ids == 0) {
my ($status, @path_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "list", @{[$fs->mount]});
if ($status != 0) {
die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n";
}
my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/;
if ($#paths > 0) {
die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n";
} elsif ($#paths != 0) {
die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n";
}
$path = "/$paths[0]$path";
}
}
}
if (not $search eq "") {
$search = "search --set=drive$driveid " . $search;
Expand Down

0 comments on commit 1dcd74f

Please sign in to comment.