package bootloader; # $Id$
use diagnostics;
use strict;
#-######################################################################################
#- misc imports
#-######################################################################################
use common;
use fs::type;
use fs::get;
use fs::loopback;
use fs::proc_partitions;
use log;
use any;
use devices;
use detect_devices;
use partition_table::raw;
use run_program;
use modules;
#-#####################################################################################
#- Functions
#-#####################################################################################
my $vmlinuz_regexp = 'vmlinuz|win4lin';
my $decompose_vmlinuz_name = qr/((?:$vmlinuz_regexp).*?)-(\d+\.\d+.*)/;
sub expand_vmlinuz_symlink {
my ($vmlinuz) = @_;
my $f = $::prefix . ($vmlinuz =~ m!^/! ? $vmlinuz : "/boot/$vmlinuz");
-l $f ? readlink($f) : $vmlinuz;
}
sub installed_vmlinuz_raw() { grep { /^($vmlinuz_regexp)/ } all("$::prefix/boot") }
sub installed_vmlinuz() { grep { ! -l "$::prefix/boot/$_" } installed_vmlinuz_raw() }
sub vmlinuz2version {
my ($vmlinuz) = @_;
expand_vmlinuz_symlink($vmlinuz) =~ /$decompose_vmlinuz_name/ && $2;
}
sub vmlinuz2kernel_str {
my ($vmlinuz) = @_;
my ($basename, $version) = expand_vmlinuz_symlink($vmlinuz) =~ /$decompose_vmlinuz_name/ or return;
{
basename => $basename,
version => $version,
$version =~ /(.*)-(\D.*)-(\d+(mdk|mdv|mnb))$/ ? #- eg: 2.6.22.5-server-1mdv
(ext => $2, version_no_ext => "$1-$3") :
$version =~ /(.*md[kv])-?(.*)/ ? #- (old) eg: 2.6.17-13mdventerprise
(ext => $2, version_no_ext => $1) : (version_no_ext => $version),
};
}
sub basename2initrd_basename {
my ($basename) = @_;
$basename =~ s!vmlinuz-?!!; #- here we do not use $vmlinuz_regexp since we explictly want to keep all that is not "vmlinuz"
'initrd' . ($basename ? "-$basename" : '');
}
sub kernel_str2vmlinuz_long {
my ($kernel) = @_;
$kernel->{basename} . '-' . $kernel->{version};
}
sub kernel_str2initrd_long {
my ($kernel) = @_;
basename2initrd_basename($kernel->{basename}) . '-' . $kernel->{version} . '.img';
}
sub kernel_str2vmlinuz_short {
my ($kernel) = @_;
if ($kernel->{use_long_name}) {
kernel_str2vmlinuz_long($kernel);
} else {
$kernel->{basename};
}
}
sub kernel_str2initrd_short {
my ($kernel) = @_;
if ($kernel->{use_long_name}) {
kernel_str2initrd_long($kernel);
} else {
basename2initrd_basename($kernel->{basename}) . '.img';
}
}
sub kernel_str2label {
my ($kernel, $o_use_long_name) = @_;
if ($o_use_long_name || $kernel->{use_long_name}) {
_sanitize_ver($kernel);
} else {
$kernel->{basename} eq 'vmlinuz' ? ($kernel->{ext} eq 'xen' ? $kernel->{ext} : 'linux') :
$kernel->{basename};
}
}
sub get {
my ($vmlinuz, $bootloader) = @_;
$_->{kernel_or_dev} && $_->{kernel_or_dev} eq $vmlinuz and return $_ foreach @{$bootloader->{entries}};
undef;
}
sub get_label {
my ($label, $bootloader) = @_;
$_->{label} && lc(make_label_lilo_compatible($_->{label})) eq lc(make_label_lilo_compatible($label)) and return $_ foreach @{$bootloader->{entries}};
undef;
}
sub mkinitrd {
my ($kernel_version, $bootloader, $entry, $initrd) = @_;
$::testing || -e "$::prefix/$initrd" and return $initrd;
my $loop_boot = fs::loopback::prepare_boot();
modules::load('loop');
my @options = (
"-v", "-f", $initrd, "--ifneeded", $kernel_version,
if_($entry->{initrd_options}, split(' ', $entry->{initrd_options})),
);
if (!run_program::rooted($::prefix, 'mkinitrd', @options)) {
unlink("$::prefix/$initrd");
die "mkinitrd failed:\n(mkinitrd @options))";
}
add_boot_splash($initrd, $entry->{vga} || $bootloader->{vga});
fs::loopback::save_boot($loop_boot);
-e "$::prefix/$initrd" && $initrd;
}
sub rebuild_initrd {
my ($kernel_version, $bootloader, $entry, $initrd) = @_;
my $old = $::prefix . $entry->{initrd} . '.old';
unlink $old;
rename "$::prefix$initrd", $old;
if (!mkinitrd($kernel_version, $bootloader, $entry, $initrd)) {
log::l("rebuilding initrd failed, putting back the old one");
rename $old, "$::prefix$initrd";
}
}
sub remove_boot_splash {
my ($initrd) = @_;
run_program::rooted($::prefix, '/usr/share/bootsplash/scripts/remove-boot-splash', $initrd);
}
sub add_boot_splash {
my ($initrd, $vga) = @_;
$vga or return;
eval { require Xconfig::resolution_and_depth } or return;
if (my $res = Xconfig::resolution_and_depth::from_bios($vga)) {
run_program::rooted($::prefix, '/usr/share/bootsplash/scripts/make-boot-splash', $initrd, $res->{X});
} else {
|