summaryrefslogtreecommitdiffstats
path: root/perl-install/standalone/bootloader-config
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/standalone/bootloader-config')
-rwxr-xr-xperl-install/standalone/bootloader-config253
1 files changed, 214 insertions, 39 deletions
diff --git a/perl-install/standalone/bootloader-config b/perl-install/standalone/bootloader-config
index 0115e6de6..187ca3eed 100755
--- a/perl-install/standalone/bootloader-config
+++ b/perl-install/standalone/bootloader-config
@@ -7,6 +7,9 @@ use common;
use bootloader;
$::isStandalone = 1; #- not using standalone which messes with @ARGV and usage
+c::openlog('bootloader-config' . "[$$]");
+
+$ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
my %options = (
'action=s' => \ (my $action),
@@ -25,39 +28,50 @@ my %options = (
'no-initrd' => \ (my $no_initrd),
);
-GetOptions(%options) or die <<'EOF';
-usage: Releve --action add-kernel (--image <vmlinuz> | --kernel-version <2.6.xxx>) [--label <...>] [--no-short-name] [--initrd-options <options>]
- Releve --action remove-kernel (--image <vmlinuz> | --kernel-version <2.6.xxx>)
+GetOptions(%options) && $action or die <<'EOF';
+usage: bootloader-config --action add-kernel (--image <vmlinuz> | --kernel-version <2.6.xxx>) [--label <...>] [--no-short-name] [--initrd-options <options>]
+ bootloader-config --action remove-kernel (--image <vmlinuz> | --kernel-version <2.6.xxx>)
- Releve --action add-entry (--image <image> | --chainload <device>) --label <...>
- Releve --action remove-entry (--image <image> | --chainload <device> | --label <...>)
+ bootloader-config --action add-entry (--image <image> | --chainload <device>) --label <...>
+ bootloader-config --action remove-entry (--image <image> | --chainload <device> | --label <...>)
- Releve --action update-splash
- Releve --action remove-splash
+ bootloader-config --action update-splash
+ bootloader-config --action remove-splash
+ bootloader-config --action rebuild-initrds
+ bootloader-config --action migrate-to-uuids
EOF
-my @known_actions = qw(add-kernel remove-kernel update-splash remove-splash detectloader add-entry remove-entry);
+my @known_actions = qw(add-kernel remove-kernel update-splash remove-splash rebuild-initrds migrate-to-uuids detectloader add-entry remove-entry add-resume2);
$action && member($action, @known_actions) or die "<action> must be one of " . join(' ', @known_actions) . "\n";
if ($image) {
if (my $ver = bootloader::vmlinuz2version($image)) {
if ($kernel_version) {
- $kernel_version eq $ver or die "$kernel_version and $ver don't match (hint: don't pass both --image and --kernel-version)\n";
+ $kernel_version eq $ver or die "$kernel_version and $ver do not match (hint: do not pass both --image and --kernel-version)\n";
} else {
$kernel_version = $ver;
}
}
$image = "/boot/$image" if $image !~ m!^/!;
} elsif ($kernel_version) {
- $image = "/boot/vmlinuz-$kernel_version";
+ $image = find { -e $_ } map { "/boot/$_-$kernel_version" } qw(vmlinux uImage vmlinuz);
}
my $all_hds = fsedit::get_hds();
-fs::get_info_from_fstab($all_hds, '');
-
-my $bootloader = bootloader::read([ fs::get::fstab($all_hds) ]) or die "Cannot find a boot loader installed\n";
+fs::get_info_from_fstab($all_hds);
+my $bootloader = bootloader::read($all_hds);
+if (!$bootloader) {
+ if (member($action, 'add-kernel', 'remove-kernel')) {
+ if ($no_initrd) {
+ die "Cannot find a bootloader installed and initrd build suppressed\n";
+ }
+ warn "Cannot find a boot loader installed. Only taking care of initrd\n";
+ } else {
+ die "Cannot find a boot loader installed\n";
+ }
+}
$action =~ s/-/_/g;
$::{$action}->();
@@ -73,8 +87,23 @@ sub remove_now_broken_boot_symlinks() {
}
sub remove_kernel() {
unlink "/lib/modules/$kernel_version/build";
+ unlink "/lib/modules/$kernel_version/source";
remove_now_broken_boot_symlinks();
+ if (!$bootloader) {
+ #- removing the initrd for weird configs where no mga bootloader is configured
+ my $kernel_str = bootloader::vmlinuz2kernel_str($image) or die "bad kernel name $image\n";
+ my $initrd_long = bootloader::kernel_str2initrd_long($kernel_str);
+ unlink "/boot/$initrd_long";
+ return;
+ }
+
+ remove_kernel_generic() if bootloader::main_method($bootloader->{method}) ne 'grub2';
+
+ modify_bootloader();
+}
+
+sub remove_kernel_generic() {
my %proposed_labels;
my @new_entries;
@@ -84,15 +113,17 @@ sub remove_kernel() {
} else {
my $vmlinuz = $_->{kernel_or_dev} && bootloader::expand_vmlinuz_symlink($_->{kernel_or_dev});
if ($vmlinuz && "/boot/$vmlinuz" eq $image) {
+ #- eg: removing kernel XXX and entry "linux" has /boot/vmlinuz -> vmlinuz-XXX
+ #- so finding out which kernel still installed is better suited to use label "linux"
if (!%proposed_labels) {
%proposed_labels = bootloader::get_kernels_and_labels_before_kernel_remove($vmlinuz);
}
- if (my $proposed = $proposed_labels{$_->{label}}) {
- my %to_add = %$_;
- put_in_hash(\%to_add, $proposed);
- push @new_entries, \%to_add;
+ if (my $kernel_str = $proposed_labels{$_->{label}}) {
+ push @new_entries, [ $kernel_str, $_ ];
+ 1;
+ } else {
+ 0;
}
- 1;
} else {
0;
}
@@ -104,36 +135,57 @@ sub remove_kernel() {
@{$bootloader->{entries}} = @$to_keep;
foreach (@new_entries) {
- bootloader::add_kernel($bootloader, $_, {});
+ my ($kernel_str, $v) = @$_;
+ bootloader::add_kernel($bootloader, $kernel_str, $v);
}
-
- modify_bootloader();
}
#-###############################################################################
sub add_kernel() {
- bootloader::create_link_source();
+ configure_ide_controller();
my $kernel_str = bootloader::vmlinuz2kernel_str($image) or die "bad kernel name $image\n";
- my $root_part = fs::get::root([ fs::get::fstab($all_hds) ]) or die "can't find root partition\n";
+ if (!$bootloader) {
+ #- building the initrd for weird configs where no mga bootloader is configured
+ my $fake_bootloader = { vga => undef };
+ my %opts = (initrd_options => $initrd_options);
+ my $initrd_long = bootloader::kernel_str2initrd_long($kernel_str);
+ bootloader::mkinitrd($kernel_str->{version}, $fake_bootloader, \%opts, "/boot/$initrd_long");
+ return;
+ }
+
+ my $root_part = fs::get::root_([ fs::get::fstab($all_hds) ]) or warn "cannot find root partition in /etc/fstab\n";
+ $root_part ||= fs::get::root_from_mounted() or die "cannot find root partition\n";
my %opts = (
- root => "/dev/$root_part->{device}",
+ root => fs::wild_device::from_part('', $root_part),
initrd_options => $initrd_options,
if_($label, label => $label),
- if_($bootloader->{default_vga}, vga => $bootloader->{default_vga}),
+ (grep_each { member($::a, 'vga', 'lock') } %{$bootloader->{default_options}}),
);
- #- short name
- bootloader::add_kernel($bootloader, $kernel_str, { %opts }, 0, $no_initrd) if !$no_short_name;
- #- long name
- $kernel_str->{use_long_name} = 1;
- bootloader::add_kernel($bootloader, $kernel_str, { %opts }, 1, $no_initrd);
+ #- short name
+ bootloader::add_kernel($bootloader, $kernel_str, { %opts }, 0, $no_initrd) if !$no_short_name;
+
+ #- long name
+ $kernel_str->{use_long_name} = 1;
+ bootloader::add_kernel($bootloader, $kernel_str, { %opts }, 1, $no_initrd);
modify_bootloader();
}
+sub configure_ide_controller() {
+ my $modules_conf = modules::any_conf->read;
+ if ($modules_conf->get_alias('ide-controller') ||
+ $modules_conf->get_probeall('ide-controller')) {
+ #- already configured
+ } elsif (my @l = detect_devices::probe_category('disk/ide')) {
+ $modules_conf->add_probeall('ide-controller', $_->{driver}) foreach @l;
+ $modules_conf->write;
+ }
+}
+
sub modify_bootloader() {
!$no_entry or return;
@@ -155,24 +207,147 @@ sub add_entry() {
modify_bootloader();
}
-sub remove_entry() {
+sub _get_entry() {
listlength(grep { $_ } $label, $image, $chainload) == 1 or die "you must give one of --label, --image and --chainload\n";
- my $e = $label ? bootloader::get_label($label, $bootloader) :
- find { $_->{kernel_or_dev} && $_->{kernel_or_dev} eq ($image || $chainload) } @{$bootloader->{entries}};
+ $label ? bootloader::get_label($label, $bootloader) :
+ find { $_->{kernel_or_dev} && $_->{kernel_or_dev} eq ($image || $chainload) } @{$bootloader->{entries}};
+}
- if ($e) {
- @{$bootloader->{entries}} = grep { $_ != $e } @{$bootloader->{entries}};
- }
+sub remove_entry() {
+ my $e = _get_entry() or return;
+ @{$bootloader->{entries}} = grep { $_ != $e } @{$bootloader->{entries}};
modify_bootloader();
}
+sub add_resume2() {
+ my $e = _get_entry() or return;
+
+ my ($simple, $dict) = bootloader::unpack_append($e->{append});
+ if (my $resume = find { $_->[0] eq 'resume' } @$dict) {
+ if (!any { $_->[0] eq 'resume2' } @$dict) {
+ push @$dict, [ resume2 => "swap:$resume->[1]" ];
+ $e->{append} = bootloader::pack_append($simple, $dict);
+
+ modify_bootloader();
+ }
+ }
+}
+
#-###############################################################################
-sub update_splash() {
- foreach (@{$bootloader->{entries}}) {
- bootloader::add_boot_splash($_->{initrd}, $_->{vga}) if $_->{initrd};
+sub rebuild_initrds() {
+ bootloader::rebuild_initrds($bootloader);
+ bootloader::action($bootloader, 'when_config_changed') if !$no_launch;
+}
+
+#-###############################################################################
+sub migrate_to_uuids() {
+ foreach (fs::get::fstab($all_hds)) {
+ _add_uuid_to_swap($_) if $_->{fs_type} eq 'swap' && !$_->{device_UUID};
}
+
+ my $fstab = [ fs::get::fstab($all_hds) ];
+
+ _migrate_to_uuids__fstab($fstab);
+
+ my $bootloader_migrated;
+ my $may_migrate = sub {
+ my ($label, $dev_ref) = @_;
+ my $dev_ = _migrate_dev_to_uuid($fstab, $$dev_ref) or return;
+
+ log::l("migrate_to_uuids: migrating bootloader $label=$$dev_ref entry");
+ $$dev_ref = $dev_;
+ $bootloader_migrated = 1;
+ };
+ # migrate root=
+ $may_migrate->('root', \$_->{root}) foreach grep { !$_->{keep_verbatim} } @{$bootloader->{entries}};
+
+ # migrate resume=
+ bootloader::modify_append($bootloader, sub {
+ my ($_simple, $dict) = @_;
+ foreach (grep { $_->[0] eq 'resume' } @$dict) {
+ $may_migrate->($_->[0], \$_->[1]);
+ }
+ });
+
+ if ($bootloader_migrated) {
+ bootloader::action($bootloader, 'write', $all_hds, '.before-migrate-to-uuids');
+ bootloader::action($bootloader, 'when_config_changed');
+ }
+}
+
+sub _migrate_to_uuids__fstab {
+ my ($fstab) = @_;
+
+ my @raw_fstab = fs::read_fstab('', '/etc/fstab', 'keep_freq_passno', 'verbatim_credentials');
+
+ my $fstab_migrated;
+ foreach my $part (@raw_fstab) {
+ _should_prefer_UUID($part) or next;
+
+ my $part_ = find { fs::get::is_same_hd($part, $_) } @$fstab
+ or log::l("migrate_to_uuids: do not know $part->{device}, cannot migrate it"), next;
+
+ $part->{device_UUID} = $part_->{device_UUID}
+ or log::l("migrate_to_uuids: no UUID for $part->{device}, cannot migrate it"), next;
+ $part->{prefer_device_UUID} = 1;
+ $part->{prefer_device} = 0;
+ delete $part->{device_alias} if $part->{device_alias} && $part->{device_alias} =~ m!\bmapper/!; # see fs::dmraid::migrate_device_names() for more
+
+ log::l("migrate_to_uuids: migrating fstab $part->{device} entry");
+ $fstab_migrated = 1;
+ }
+ if ($fstab_migrated) {
+ cp_af('/etc/fstab', '/etc/fstab.before-migrate-to-uuids');
+
+ my ($s) = fs::prepare_write_fstab(\@raw_fstab, '', 'keep_smb_credentials');
+ output('/etc/fstab', $s);
+ }
+}
+
+sub _migrate_dev_to_uuid {
+ my ($fstab, $dev) = @_;
+ $dev && $dev =~ m!/dev/! or return;
+
+ my $part = fs::get::device2part($dev, $fstab);
+ _should_prefer_UUID($part) or return;
+ $part && $part->{device_UUID} && "UUID=$part->{device_UUID}";
+}
+
+sub _should_prefer_UUID {
+ my ($part) = @_;
+ devices::should_prefer_UUID($part->{device})
+ || $part->{device} =~ m!\bmapper/!; # we want to migrate dmraid devices, because of xxx1 vs xxxp1 device name issue
+}
+
+# add UUID to swap v.2 in case the swap was created long ago when mkswap didn't do it by default
+sub _add_uuid_to_swap {
+ my ($part) = @_;
+
+ my $ids = fs::type::call_blkid($part);
+ $ids->{ID_FS_VERSION} eq '2'
+ or log::l("ERROR: do not know swap version $ids->{ID_FS_VERSION}, so cannot add UUID to it"), return;
+
+ my $uuid = run_program::get_stdout('uuidgen');
+ log::l("adding UUID=$uuid to $part->{device}");
+ $uuid =~ s/-//g;
+ $uuid =~ s/(..)/chr(hex($1))/ge;
+
+ {
+ my $F;
+ sysopen($F, devices::make($part->{device}), 2) or die "error opening device $part->{device} for writing";
+ sysseek($F, 1036, 0) && syswrite($F, $uuid) or log::l("writing UUID failed");
+ }
+
+ if (my $p = fs::type::type_subpart_from_magic($part)) {
+ $part->{device_UUID} = $p->{device_UUID};
+ }
+}
+
+#-###############################################################################
+sub update_splash() {
+ bootloader::update_splash($bootloader);
bootloader::action($bootloader, 'when_config_changed') if !$no_launch;
}