diff options
Diffstat (limited to 'perl-install/standalone/bootloader-config')
| -rwxr-xr-x | perl-install/standalone/bootloader-config | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/perl-install/standalone/bootloader-config b/perl-install/standalone/bootloader-config new file mode 100755 index 000000000..60afecd16 --- /dev/null +++ b/perl-install/standalone/bootloader-config @@ -0,0 +1,214 @@ +#!/usr/bin/perl + +use lib qw(/usr/lib/libDrakX); +use Getopt::Long; + +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), + + 'label=s' => \ (my $label), + + 'chainload=s' => \ (my $chainload), + + 'image=s' => \ (my $image), + 'kernel-version=s' => \ (my $kernel_version), + + 'initrd-options=s' => \ (my $initrd_options), + 'no-short-name' => \ (my $no_short_name), + 'no-entry' => \ (my $no_entry), + 'no-launch' => \ (my $no_launch), + 'no-initrd' => \ (my $no_initrd), + ); + +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>) + + bootloader-config --action add-entry (--image <image> | --chainload <device>) --label <...> + bootloader-config --action remove-entry (--image <image> | --chainload <device> | --label <...>) + + bootloader-config --action update-splash + bootloader-config --action remove-splash + + bootloader-config --action rebuild-initrds +EOF + +my @known_actions = qw(add-kernel remove-kernel update-splash remove-splash rebuild-initrds 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 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"; +} + + +my $all_hds = fsedit::get_hds(); +fs::get_info_from_fstab($all_hds); + +my $bootloader = bootloader::read($all_hds) or die "Cannot find a boot loader installed\n"; + + +$action =~ s/-/_/g; +$::{$action}->(); + + +#-############################################################################### +sub remove_now_broken_boot_symlinks() { + foreach (glob("/boot/vmlinuz*"), glob("/boot/initrd*")) { + -l $_ && !-e $_ or next; + log::l("removing now broken symlink $_"); + unlink $_; + } +} +sub remove_kernel() { + unlink "/lib/modules/$kernel_version/build"; + unlink "/lib/modules/$kernel_version/source"; + remove_now_broken_boot_symlinks(); + + my %proposed_labels; + my @new_entries; + + my ($to_remove, $to_keep) = partition { + if ($_->{kernel_or_dev} && $_->{kernel_or_dev} eq $image) { + 1; + } 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 $kernel_str = $proposed_labels{$_->{label}}) { + push @new_entries, [ $kernel_str, $_ ]; + } + 1; + } else { + 0; + } + } + } @{$bootloader->{entries}}; + + $_->{initrd} && unlink $_->{initrd} foreach @$to_remove; + + @{$bootloader->{entries}} = @$to_keep; + + foreach (@new_entries) { + my ($kernel_str, $v) = @$_; + bootloader::add_kernel($bootloader, $kernel_str, $v); + } + + modify_bootloader(); +} + + +#-############################################################################### +sub add_kernel() { + bootloader::create_link_source(); + + 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 not find root partition\n"; + my %opts = ( + root => fs::wild_device::from_part('', $root_part), + initrd_options => $initrd_options, + if_($label, label => $label), + (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); + + modify_bootloader(); +} + +sub modify_bootloader() { + !$no_entry or return; + + bootloader::action($bootloader, 'write', $all_hds); + bootloader::action($bootloader, 'when_config_changed') if !$no_launch; +} + +#-############################################################################### +sub add_entry() { + $label or die "you must give a label\n"; + ($image xor $chainload) or die "you must give an image or a chainload\n"; + + my $entry = { + type => $image ? 'image' : 'other', + label => $label, + kernel_or_dev => $image || $chainload, + }; + bootloader::add_entry($bootloader, $entry); + modify_bootloader(); +} + +sub _get_entry() { + listlength(grep { $_ } $label, $image, $chainload) == 1 or die "you must give one of --label, --image and --chainload\n"; + + $label ? bootloader::get_label($label, $bootloader) : + find { $_->{kernel_or_dev} && $_->{kernel_or_dev} eq ($image || $chainload) } @{$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 rebuild_initrds() { + bootloader::rebuild_initrds($bootloader); + bootloader::action($bootloader, 'when_config_changed') if !$no_launch; +} + +#-############################################################################### +sub update_splash() { + bootloader::update_splash($bootloader); + bootloader::action($bootloader, 'when_config_changed') if !$no_launch; +} + +sub remove_splash() { + foreach (@{$bootloader->{entries}}) { + bootloader::remove_boot_splash($_->{initrd}) if $_->{initrd}; + } + bootloader::action($bootloader, 'when_config_changed') if !$no_launch; +} + +sub detectloader() { + print uc(bootloader::main_method($bootloader->{method})), "\n" if $bootloader; +} |
