diff options
Diffstat (limited to 'perl-install/bootloader.pm')
-rw-r--r-- | perl-install/bootloader.pm | 109 |
1 files changed, 107 insertions, 2 deletions
diff --git a/perl-install/bootloader.pm b/perl-install/bootloader.pm index 7c8a6c15c..947ef4f77 100644 --- a/perl-install/bootloader.pm +++ b/perl-install/bootloader.pm @@ -242,7 +242,7 @@ sub read { my $f = $bootloader::{"read_$main_method"} or die "unknown bootloader method $main_method (read)"; my $bootloader = $f->($fstab); - cleanup_entries($bootloader); + cleanup_entries($bootloader) if $main_method ne 'refind'; # handle raid-extra-boot (lilo) my @devs = $bootloader->{boot}; @@ -263,6 +263,8 @@ sub read { } elsif (my $type = partition_table::raw::typeOfMBR($_)) { warn "typeOfMBR $type on $_ for method $main_method\n" if $ENV{DEBUG}; $type; + } elsif (-e "$::prefix/boot/refind_linux.conf") { + 'refind'; } else { () } } @devs; @@ -633,6 +635,34 @@ sub read_uboot() { \%b; } +=item read_refind ($fstab) + +Read back rEFInd config + C</boot/refind_linux.conf> + +=cut + +sub read_refind() { + my %bootloader = (entries => []); + foreach (cat_utf8("$::prefix/boot/refind_linux.conf")) { + next if /^#/; + my ($label, $append) = /"(.*)"\s"(.*)"/; + my $root = $1 if $append =~ s/root=(\S*)\s*//; + my $vga = $1 if $append =~ s/vga=(\S*)\s*//; + if ($label && $root) { + push @{$bootloader{entries}}, { + type => 'image', + kernel_or_dev => '/boot/vmlinuz', + label => $label, + root => $root, + append => $append, + vga => $vga + }; + } + } + $bootloader{method} = 'refind'; + \%bootloader; +} + # FIXME: actually read back previous conf sub read_cromwell() { +{ method => 'cromwell' }; @@ -1358,6 +1388,7 @@ sub method2text { 'grub2' => N("GRUB2 with text menu"), 'grub-graphic' => N("GRUB with graphical menu"), 'grub-menu' => N("GRUB with text menu"), + 'refind' => N("rEFInd with graphical menu"), 'uboot' => N("U-Boot/Extlinux with text menu"), }->{$method}; } @@ -1381,7 +1412,8 @@ sub method_choices_raw { arch() =~ /arm/ ? 'uboot' : if_(!$b_prefix_mounted || whereis_binary('grub2-reboot', $::prefix), 'grub2-graphic', 'grub2'), - # only grub2 works on UEFI: + if_(is_uefi() && (!$b_prefix_mounted || -e "$::prefix/boot/EFI/EFI/refind"), 'refind'), + # only grub2 & rEFInd work on UEFI: # lilo & grub-legacy do not suppport new ext4/xfs format and are unmainted so only allow them on upgrade: if_(!is_uefi() && !($::isInstall && !$::o->{isUpgrade} || $::isLiveInstall), ( if_(!$b_prefix_mounted || whereis_binary('grub', $::prefix) && -f "$::prefix/boot/grub/install.sh", @@ -2295,6 +2327,77 @@ sub when_config_changed_grub { update_copy_in_boot($_) foreach glob($::prefix . boot_copies_dir() . '/*.link'); } +sub write_refind { + my ($bootloader, $_all_hds, $o_backup_extension) = @_; + + my @config; + + foreach my $entry (@{$bootloader->{entries}}) { + if ($entry->{type} eq 'image' && $entry->{kernel_or_dev} eq '/boot/vmlinuz') { + my $vga = $entry->{vga} || $bootloader->{vga}; + my $boot_params = join(' ', + "root=$entry->{root}", + $entry->{append}, + if_($entry->{'read-write'}, 'rw'), + if_($vga && $vga ne "normal", "vga=$vga") + ); + push @config, '"' . simplify_label($entry->{label}) . '" "' . $boot_params . '"'; + } + } + if (@config) { + my $f = "$::prefix/boot/refind_linux.conf"; + log::l("writing rEFInd config to $f"); + renamef($f, $f . ($o_backup_extension || '.old')); + output_with_perm($f, 0600, map { "$_\n" } @config); + check_enough_space(); + } else { + log::l("config has no entries - rEFInd config file not written"); + } + + my $default_kernel = readlink("$::prefix/boot/vmlinuz"); + if ($default_kernel) { + my $efivars = '/sys/firmware/efi/efivars'; + my $already_mounted = cat_('/proc/mounts') =~ /$efivars/; + run_program::run('mount', '-t', 'efivarfs', 'none', $efivars) if !$already_mounted; + my $previous_boot = "$efivars/PreviousBoot-36d08fa7-cf0b-42f5-8f14-68df73ed3740"; + run_program::run('chattr', '-i', $previous_boot) if -e $previous_boot; + if (open(my $efivar, '>:raw', $previous_boot)) { + require Encode; + log::l("writing rEFInd PreviousBoot variable"); + print $efivar "\x07\x00\x00\x00"; + print $efivar Encode::encode('UTF16-LE', $default_kernel); + print $efivar "\x00\x00"; + close($efivar); + } else { + log::l("failed to write rEFInd PreviousBoot variable: $@ ($!)"); + } + run_program::run('umount', $efivars) if !$already_mounted; + } +} + +sub install_refind { + my ($bootloader, $all_hds) = @_; + + if ($bootloader->{install_mode} ne 'no_install') { + my (@options, $error); + if ($bootloader->{install_mode} eq 'as_default') { + $bootloader->{esp_device} or die "ESP device is unknown"; + push @options, '--usedefault'; + push @options, $bootloader->{esp_device}; + } elsif ($bootloader->{install_mode} eq 'nvram_only') { + push @options, '--nvramonly'; + } + run_program::rooted($::prefix, '/sbin/refind-install', '2>', \$error, @options) + or die "refind-install failed: $error"; + } + write_refind($bootloader, $all_hds); +} + +sub when_config_changed_refind { + my ($_bootloader) = @_; + #- do not do anything +} + =item action($bootloader, $action, @para) Calls the C<$action> function with @para parameters: @@ -2339,6 +2442,8 @@ sub ensure_pkg_is_installed { my $pkg = is_uefi() ? 'grub2-efi' : 'grub2'; my $prefix = is_uefi() ? (arch() eq 'x86_64' ? 'x86_64-efi' : 'i386-efi') : 'i386-pc'; $do_pkgs->ensure_is_installed($pkg, "/usr/lib/grub/$prefix/ext2.mod", 1) or return 0; + } elsif ($main_method eq 'refind') { + $do_pkgs->ensure_is_installed('refind', '/sbin/refind-install', 1) or return 0; } elsif (member($main_method, qw(grub grub2 lilo))) { $do_pkgs->ensure_binary_is_installed($main_method, $main_method, 1) or return 0; } |