From b15e1fbb08eb94534ccc1aa8717816a042b260b8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 25 Jul 2012 10:47:32 -0400 Subject: [PATCH] Boot loader refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renamed system.build.menuBuilder to system.build.installBootLoader. - ‘install-grub.pl’ (formerly grub-menu-builder.pl) now generates the GRUB menu *and* installs GRUB (if necessary). - ‘switch-to-configuration.sh’ has no boot loader specific knowledge anymore. It just calls installBootLoader. --- modules/installer/cd-dvd/iso-image.nix | 1 - .../cd-dvd/system-tarball-fuloong2f.nix | 3 -- .../cd-dvd/system-tarball-sheevaplug.nix | 3 -- .../installer/efi-boot-stub/efi-boot-stub.nix | 4 +- .../generations-dir/generations-dir.nix | 4 +- modules/installer/grub/grub.nix | 7 ++-- .../{grub-menu-builder.pl => install-grub.pl} | 39 +++++++++++++++---- .../activation/switch-to-configuration.sh | 28 +------------ modules/system/activation/top-level.nix | 21 ++-------- 9 files changed, 43 insertions(+), 67 deletions(-) rename modules/installer/grub/{grub-menu-builder.pl => install-grub.pl} (84%) diff --git a/modules/installer/cd-dvd/iso-image.nix b/modules/installer/cd-dvd/iso-image.nix index c1094daa49fa..4f87f29f2e92 100644 --- a/modules/installer/cd-dvd/iso-image.nix +++ b/modules/installer/cd-dvd/iso-image.nix @@ -168,7 +168,6 @@ in boot.loader.grub.enable = false; # !!! Hack - attributes expected by other modules. - system.build.menuBuilder = "true"; system.boot.loader.kernelFile = "bzImage"; environment.systemPackages = [ pkgs.grub2 ]; diff --git a/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/modules/installer/cd-dvd/system-tarball-fuloong2f.nix index 5a23a394f7f7..5b6e0036639b 100644 --- a/modules/installer/cd-dvd/system-tarball-fuloong2f.nix +++ b/modules/installer/cd-dvd/system-tarball-fuloong2f.nix @@ -170,9 +170,6 @@ in boot.loader.generationsDir.enable = false; system.boot.loader.kernelFile = "vmlinux"; - # Needed for nixos to evaluate - system.build.menuBuilder = "true"; - nixpkgs.config = { platform = pkgs.platforms.fuloong2f_n32; }; diff --git a/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/modules/installer/cd-dvd/system-tarball-sheevaplug.nix index 24e7a0063149..f53079ecd9b0 100644 --- a/modules/installer/cd-dvd/system-tarball-sheevaplug.nix +++ b/modules/installer/cd-dvd/system-tarball-sheevaplug.nix @@ -177,9 +177,6 @@ in services.ttyBackgrounds.enable = false; jobs.openssh.startOn = pkgs.lib.mkOverrideTemplate 50 {} ""; - # Needed for nixos to evaluate - system.build.menuBuilder = "true"; - nixpkgs.config = { platform = pkgs.platforms.sheevaplug; }; diff --git a/modules/installer/efi-boot-stub/efi-boot-stub.nix b/modules/installer/efi-boot-stub/efi-boot-stub.nix index 1ca3cb0001eb..a4e0ebd9845f 100644 --- a/modules/installer/efi-boot-stub/efi-boot-stub.nix +++ b/modules/installer/efi-boot-stub/efi-boot-stub.nix @@ -123,9 +123,7 @@ in system = mkIf (config.boot.loader.efiBootStub.enable && (assert (config.boot.kernelPackages.kernel.features ? efiBootStub && config.boot.kernelPackages.kernel.features.efiBootStub); true)) { - build = { - menuBuilder = efiBootStubBuilder; - }; + build.installBootLoader = efiBootStubBuilder; boot.loader.id = "efiBootStub"; boot.loader.kernelFile = platform.kernelTarget; }; diff --git a/modules/installer/generations-dir/generations-dir.nix b/modules/installer/generations-dir/generations-dir.nix index db9fa32c55a9..b67cf7e56e73 100644 --- a/modules/installer/generations-dir/generations-dir.nix +++ b/modules/installer/generations-dir/generations-dir.nix @@ -63,9 +63,7 @@ in ]; system = mkIf config.boot.loader.generationsDir.enable { - build = { - menuBuilder = generationsDirBuilder; - }; + build.installBootLoader = generationsDirBuilder; boot.loader.id = "generationsDir"; boot.loader.kernelFile = platform.kernelTarget; }; diff --git a/modules/installer/grub/grub.nix b/modules/installer/grub/grub.nix index 3a76e08f26ad..0a9b374cc60c 100644 --- a/modules/installer/grub/grub.nix +++ b/modules/installer/grub/grub.nix @@ -13,10 +13,11 @@ let grubConfig = pkgs.writeText "grub-config.xml" (builtins.toXML { splashImage = f config.boot.loader.grub.splashImage; grub = f grub; + fullVersion = (builtins.parseDrvName config.system.build.grub.name).version; inherit (config.boot.loader.grub) version extraConfig extraPerEntryConfig extraEntries extraEntriesBeforeNixOS configurationLimit copyKernels timeout - default; + default devices; }); in @@ -199,9 +200,9 @@ in system.build = mkAssert (cfg.devices != []) "You must set the ‘boot.loader.grub.device’ option to make the system bootable." - { menuBuilder = + { installBootLoader = "PERL5LIB=${makePerlPath [ pkgs.perlPackages.XMLLibXML pkgs.perlPackages.XMLSAX ]} " + - "${pkgs.perl}/bin/perl ${./grub-menu-builder.pl} ${grubConfig}"; + "${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig}"; inherit grub; }; diff --git a/modules/installer/grub/grub-menu-builder.pl b/modules/installer/grub/install-grub.pl similarity index 84% rename from modules/installer/grub/grub-menu-builder.pl rename to modules/installer/grub/install-grub.pl index 6ac55f3b7afe..76fa71c827fd 100644 --- a/modules/installer/grub/grub-menu-builder.pl +++ b/modules/installer/grub/install-grub.pl @@ -5,7 +5,6 @@ use File::Basename; use File::Path; use File::stat; use File::Copy; -use IO::File; use POSIX; use Cwd; @@ -15,6 +14,19 @@ my $dom = XML::LibXML->load_xml(location => $ARGV[0]); sub get { my ($name) = @_; return $dom->findvalue("/expr/attrs/attr[\@name = '$name']/*/\@value"); } +sub readFile { + my ($fn) = @_; local $/ = undef; + open FILE, "<$fn" or return undef; my $s = ; close FILE; + local $/ = "\n"; chomp $s; return $s; +} + +sub writeFile { + my ($fn, $s) = @_; + open FILE, ">$fn" or die "cannot create $fn: $!\n"; + print FILE $s or die; + close FILE or die; +} + my $grub = get("grub"); my $grubVersion = int(get("version")); my $extraConfig = get("extraConfig"); @@ -151,8 +163,8 @@ sub addEntry { my $kernelParams = "systemConfig=" . Cwd::abs_path($path) . " " . "init=" . Cwd::abs_path("$path/init") . " " . - join " ", IO::File->new("$path/kernel-params")->getlines; - my $xenParams = $xen && -e "$path/xen-params" ? join " ", IO::File->new("$path/xen-params")->getlines : ""; + readFile("$path/kernel-params"); + my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; if ($grubVersion == 1) { $conf .= "title $name\n"; @@ -192,7 +204,7 @@ foreach my $link (@links) { my $date = strftime("%F", localtime(lstat($link)->mtime)); my $version = -e "$link/nixos-version" - ? IO::File->new("$link/nixos-version")->getline + ? readFile("$link/nixos-version") : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); } @@ -203,9 +215,7 @@ $conf .= "}\n" if $grubVersion == 2; # Atomically update the GRUB config. my $confFile = $grubVersion == 1 ? "/boot/grub/menu.lst" : "/boot/grub/grub.cfg"; my $tmpFile = $confFile . ".tmp"; -open CONF, ">$tmpFile" or die "cannot open $tmpFile for writing\n"; -print CONF $conf or die; -close CONF; +writeFile($tmpFile, $conf); rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n"; @@ -215,3 +225,18 @@ foreach my $fn (glob "/boot/kernels/*") { print STDERR "removing obsolete file $fn\n"; unlink $fn; } + + +# Install GRUB if the version changed from the last time we installed +# it. FIXME: shouldn't we reinstall if ‘devices’ changed? +my $prevVersion = readFile("/boot/grub/version") // ""; +if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1" || get("fullVersion") ne $prevVersion) { + foreach my $dev ($dom->findnodes('/expr/attrs/attr[@name = "devices"]/list/string/@value')) { + $dev = $dev->findvalue(".") or die; + next if $dev eq "nodev"; + print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n"; + system("$grub/sbin/grub-install", "--recheck", Cwd::abs_path($dev)) == 0 + or die "$0: installation of GRUB on $dev failed\n"; + } + writeFile("/boot/grub/version", get("fullVersion")); +} diff --git a/modules/system/activation/switch-to-configuration.sh b/modules/system/activation/switch-to-configuration.sh index 5958df1ed483..fea0b05ef34f 100644 --- a/modules/system/activation/switch-to-configuration.sh +++ b/modules/system/activation/switch-to-configuration.sh @@ -23,32 +23,8 @@ fi # Install or update the bootloader. if [ "$action" = "switch" -o "$action" = "boot" ]; then - - if [ "@bootLoader@" = "grub" ]; then - - @menuBuilder@ @out@ - - # If the GRUB version has changed, then force a reinstall. - oldGrubVersion="$(cat /boot/grub/version 2>/dev/null || true)" - newGrubVersion="@grubVersion@" - - if [ "$NIXOS_INSTALL_GRUB" = 1 -o "$oldGrubVersion" != "$newGrubVersion" ]; then - for dev in @grubDevices@; do - if [ "$dev" != nodev ]; then - echo "installing the GRUB bootloader on $dev..." - @grub@/sbin/grub-install --recheck "$(readlink -f "$dev")" --no-floppy - fi - done - echo "$newGrubVersion" > /boot/grub/version - fi - - 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 + + @installBootLoader@ @out@ if [ -n "@initScriptBuilder@" ]; then @initScriptBuilder@ @out@ diff --git a/modules/system/activation/top-level.nix b/modules/system/activation/top-level.nix index 3edc92d502cc..0e1a9a3d2adc 100644 --- a/modules/system/activation/top-level.nix +++ b/modules/system/activation/top-level.nix @@ -101,9 +101,6 @@ let ln -s ${kernelPath} $out/kernel ln -s ${config.system.modulesTree} $out/kernel-modules - if [ -n "$grub" ]; then - ln -s $grub $out/grub - fi ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd @@ -152,7 +149,9 @@ let inherit children; kernelParams = config.boot.kernelParams ++ config.boot.extraKernelParams; - menuBuilder = config.system.build.menuBuilder or "true"; + installBootLoader = + config.system.build.installBootLoader + or "echo 'Warning: don't know how to make this configuration bootable; please enable a boot loader.' 1>&2; true"; initScriptBuilder = config.system.build.initScriptBuilder; activationScript = config.system.activationScripts.script; nixosVersion = config.system.nixosVersion; @@ -176,20 +175,6 @@ let config.system.build.upstart # for initctl ]; - # Boot loaders - bootLoader = config.system.boot.loader.id; - grub = - if config.boot.loader.grub.enable - then config.system.build.grub - else null; - grubVersion = - if config.boot.loader.grub.enable - then (builtins.parseDrvName config.system.build.grub.name).version - else ""; - grubDevices = - let - wrapQuotes = s: "\"" + s + "\""; - in map wrapQuotes config.boot.loader.grub.devices; configurationName = config.boot.loader.grub.configurationName; };