summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Whitaker <mageia@martin-whitaker.me.uk>2018-09-14 01:01:09 +0100
committerMartin Whitaker <mageia@martin-whitaker.me.uk>2018-09-23 21:19:28 +0100
commit7c1fa8e6d5debac06726cec9d22e1120043ddd5a (patch)
tree57ceb798886764886987ac0c2ba1cbfbe15e4a2d
parent95e71ef9d338c52bfd99cfd072caf7142cc6e83e (diff)
downloaddrakx-7c1fa8e6d5debac06726cec9d22e1120043ddd5a.tar
drakx-7c1fa8e6d5debac06726cec9d22e1120043ddd5a.tar.gz
drakx-7c1fa8e6d5debac06726cec9d22e1120043ddd5a.tar.bz2
drakx-7c1fa8e6d5debac06726cec9d22e1120043ddd5a.tar.xz
drakx-7c1fa8e6d5debac06726cec9d22e1120043ddd5a.zip
drakboot: add support for the rEFInd boot manager (mga#15153)
-rw-r--r--perl-install/NEWS1
-rw-r--r--perl-install/any.pm86
-rw-r--r--perl-install/bootloader.pm109
-rw-r--r--perl-install/install/NEWS2
4 files changed, 190 insertions, 8 deletions
diff --git a/perl-install/NEWS b/perl-install/NEWS
index df6ef8476..db5d0e3dd 100644
--- a/perl-install/NEWS
+++ b/perl-install/NEWS
@@ -1,3 +1,4 @@
+- drakboot: add support for the rEFInd boot manager
- mdadm raid:
o raid10 can be created with just 2 disks as a high-performance raid1
o raid10: use layout f2 with 2 disks for performance
diff --git a/perl-install/any.pm b/perl-install/any.pm
index 36d201be6..13229965e 100644
--- a/perl-install/any.pm
+++ b/perl-install/any.pm
@@ -377,7 +377,7 @@ sub setupBootloader__mbr_or_not {
}
sub setupBootloader__general {
- my ($in, $b, $all_hds, $_fstab, $_security) = @_;
+ my ($in, $b, $all_hds, $fstab, $_security) = @_;
return if detect_devices::is_xbox();
my @method_choices = bootloader::method_choices($all_hds);
@@ -472,6 +472,54 @@ sub setupBootloader__general {
log::l("switching for lilo to grub, ensure we don't read lilo.conf anymore");
renamef("$::prefix/etc/lilo.conf", "$::prefix/etc/lilo.conf.unused");
}
+ if ($prev_method eq 'refind' && $b->{method} ne 'refind') {
+ log::l("switching from rEFInd, ensure we don't detect refind as the active boot method");
+ renamef("$::prefix/boot/refind_linux.conf", "$::prefix/boot/refind_linux.conf.unused");
+ }
+ if ($b->{method} eq 'refind') {
+ if (bootloader::main_method($prev_method) eq 'grub2') {
+ #- grub2 doesn't provide any entries we can use, so revert to the defaults
+ %$b = ();
+ setupBootloaderBeforeStandalone($in->do_pkgs, $b, $all_hds, $fstab);
+ $b->{method} = 'refind';
+ undef $b->{default};
+ }
+ setupBootloader__refind($in, $b, $fstab);
+ } else {
+ 1;
+ }
+}
+
+sub setupBootloader__refind {
+ my ($in, $b, $fstab) = @_;
+
+ my $already_in_refind = -e "$::prefix/boot/EFI/EFI/refind/refind.conf";
+ my $already_in_default = -e "$::prefix/boot/EFI/EFI/BOOT/refind.conf";
+ my $already_installed = $already_in_refind || $already_in_default;
+
+ my $update_esp = !$already_installed;
+ my $as_default = $already_in_default;
+ $in->ask_from_(
+ {
+ title => N("Bootloader Configuration"),
+ interactive_help_id => 'setupBootloader',
+ },
+ [
+ { text => N("Install or update rEFInd in the EFI system partition"),
+ val => \$update_esp, type => 'bool', disabled => sub { !$already_installed } },
+ { text => N("Install in /EFI/BOOT (workaround for some BIOSs)"),
+ val => \$as_default, type => 'bool', disabled => sub { !$update_esp } },
+ ]
+ ) or return 0;
+
+ if ($update_esp) {
+ $b->{install_mode} = $as_default ? 'as_default' : 'as_refind';
+ } else {
+ $b->{install_mode} = $as_default ? 'no_install' : 'nvram_only';
+ }
+ if (my @esp = grep { $_->{mntpoint} eq '/boot/EFI' } @$fstab) {
+ $b->{esp_device} = $esp[0]{real_device} || fs::wild_device::from_part('', $esp[0]);
+ }
1;
}
@@ -497,7 +545,14 @@ sub setupBootloader__entries {
} @$fstab;
my @l;
- if ($e->{type} eq "image") {
+ if ($b->{method} eq 'refind') {
+ @l = (
+ { label => N("Label"), val => \$e->{label} },
+ { label => N("Append"), val => \$append },
+ { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ],
+ format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 },
+ );
+ } elsif ($e->{type} eq "image") {
@l = (
{ label => N("Image"), val => \$e->{kernel_or_dev}, list => [ map { "/boot/$_" } bootloader::installed_vmlinuz() ], not_edit => 0 },
{ label => N("Root"), val => \$e->{root}, list => [ map { fs::wild_device::from_part('', $_) } grep { !isSwap($_) } @$fstab ], format => sub { $root_descr{$_[0]} } },
@@ -515,12 +570,13 @@ sub setupBootloader__entries {
{ label => N("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab, detect_devices::floppies() ] },
);
}
+ if ($b->{method} ne 'refind') {
@l = (
{ label => N("Label"), val => \$e->{label} },
@l,
{ text => N("Default"), val => \$default, type => 'bool' },
);
-
+ }
$in->ask_from_(
{
interactive_help_id => 'setupBootloaderAddEntry',
@@ -546,9 +602,15 @@ sub setupBootloader__entries {
my $Add = sub {
my @labels = map { $_->{label} } @{$b->{entries}};
my ($e, $prefix);
- if ($in->ask_from_list_('', N("Which type of entry do you want to add?"),
- [ N_("Linux"), N_("Other OS (Windows...)") ]
- ) eq "Linux") {
+ if ($b->{method} eq 'refind') {
+ $e = { type => 'image',
+ kernel_or_dev => '/boot/vmlinuz',
+ root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default.
+ };
+ $prefix = "linux";
+ } elsif ($in->ask_from_list_('', N("Which type of entry do you want to add?"),
+ [ N_("Linux"), N_("Other OS (Windows...)") ]
+ ) eq "Linux") {
$e = { type => 'image',
root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default.
};
@@ -594,6 +656,18 @@ sub setupBootloader__entries {
};
my @prev_entries = @{$b->{entries}};
+
+ #- the rEFInd configuration file just provides alternative kernel command lines
+ #- so we only want to display entries that relate to the default kernel.
+ if ($b->{method} eq 'refind') {
+ @{$b->{entries}} =
+ grep {
+ my $pb = $_->{type} ne 'image' || $_->{kernel_or_dev} ne '/boot/vmlinuz';
+ log::l("dropping bootloader entry $_->{label} because it is not needed by rEFInd") if $pb;
+ !$pb;
+ } @{$b->{entries}};
+ }
+
if ($in->ask_from__add_modify_remove(N("Bootloader Configuration"),
N("Here are the entries on your boot menu so far.
You can create additional entries or change the existing ones."), [ {
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;
}
diff --git a/perl-install/install/NEWS b/perl-install/install/NEWS
index 1202f00cc..56bafd8da 100644
--- a/perl-install/install/NEWS
+++ b/perl-install/install/NEWS
@@ -1,3 +1,5 @@
+- drakboot: add support for the rEFInd boot manager
+
Version 18.1 - 14 September 2018
- drakx-in-chroot: