diff options
Diffstat (limited to 'perl-install/standalone/bootloader-config')
| -rwxr-xr-x | perl-install/standalone/bootloader-config | 253 |
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; } |
