home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-2 / Inter.Net 55-2.iso / Mandrake / mdkinst / usr / bin / perl-install / lilo.pm < prev    next >
Encoding:
Perl POD Document  |  2000-01-12  |  7.2 KB  |  268 lines

  1. package lilo;
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10. use common qw(:common :file);
  11. use partition_table qw(:types);
  12. use log;
  13. use fsedit;
  14. use detect_devices;
  15. use partition_table_raw;
  16. use run_program;
  17. use modules;
  18.  
  19.  
  20. %vga_modes = (
  21.  "Ask at boot" => 'ask',
  22.  "Normal" => 'normal',
  23.  "80x50" => '0x0f01',
  24.  "80x43" => '0x0f02',
  25.  "80x28" => '0x0f03',
  26.  "80x30" => '0x0f04',
  27.  "80x34" => '0x0f05',
  28.  "80x60" => '0x0f06',
  29. );
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. sub mkinitrd($$$) {
  37.     my ($prefix, $kernelVersion, $initrdImage) = @_;
  38.  
  39.     $::testing and return;
  40.  
  41.     modules::load('loop');
  42.     run_program::rooted($prefix, "mkinitrd", "-f", $initrdImage, "--ifneeded", $kernelVersion) or unlink("$prefix/$initrdImage");
  43.     -e "$prefix/$initrdImage" or die "mkinitrd failed";
  44. }
  45.  
  46. sub mkbootdisk($$$;$) {
  47.     my ($prefix, $kernelVersion, $dev, $append) = @_;
  48.  
  49.     modules::load('loop');
  50.     my @l = qw(mkbootdisk --noprompt); push @l, "--appendargs", $append if $append;
  51.     run_program::rooted($prefix, @l, "--device", "/dev/$dev", $kernelVersion) or die "mkbootdisk failed";
  52. }
  53.  
  54. sub read($$) {
  55.     my ($prefix, $file) = @_;
  56.     my $global = 1;
  57.     my ($e, $v, $f);
  58.     my %b;
  59.     foreach (cat_("$prefix$file")) {
  60.     ($_, $v) = /^\s*(.*?)\s*(?:=\s*(.*?))?\s*$/;
  61.  
  62.     if (/^(image|other)$/) {
  63.         $b{entries}{$v} = $e = { type => $_ };
  64.         $global = 0;
  65.     } elsif ($global) {
  66.         $b{$_} = $v || 1;
  67.     } else {
  68.         if ((/map-drive/ .. /to/) && /to/) {
  69.         $e->{mapdrive}{$e->{'map-drive'}} = $v;
  70.         } else {
  71.         $e->{$_} = $v || 1;
  72.         }
  73.     }
  74.     }
  75.     delete $b{timeout} unless $b{prompt};
  76.     $b{timeout} = $b{timeout} / 10 if $b{timeout};
  77.     $b{message} = cat_("$prefix$b{message}") if $b{message};
  78.     \%b;
  79. }
  80.  
  81. sub suggest_onmbr($) {
  82.     my ($hds) = @_;
  83.     
  84.     my $type = partition_table_raw::typeOfMBR($hds->[0]{device});
  85.     !$type || member($type, qw(dos dummy lilo empty)), !$type;
  86. }
  87.  
  88. sub add_entry($$$) {
  89.     my ($entries, $image, $v) = @_;
  90.     my (%usedold, $freeold);
  91.  
  92.     do { $usedold{$1 || 0} = 1 if $_->{label} =~ /^old ([^_]*)_/x } foreach (values %$entries);
  93.     foreach (0..scalar keys %usedold) { exists $usedold{$_} or $freeold = $_ || '', last }
  94.  
  95.     do { $_->{label} = "old${freeold}_$_->{label}" if $_->{label} eq $v->{label} } foreach (values %$entries);
  96.     $entries->{$image} = $v;
  97. }
  98.  
  99. sub add_kernel($$$$$) {
  100.     my ($prefix, $lilo, $kernelVersion, $specific, $v) = @_;
  101.     my $ext = $specific && "-$specific";
  102.     my ($vmlinuz, $image, $initrdImage) = ("vmlinuz-$kernelVersion$specific", "/boot/vmlinuz$ext", "/boot/initrd$ext.img");
  103.     if (-e "$prefix/boot/$vmlinuz") {
  104.     {
  105.         my $f = "initrd-$kernelVersion$specific.img";
  106.         eval { mkinitrd($prefix, "$kernelVersion$specific", "/boot/$f") };
  107.         undef $initrdImage if $@;
  108.         symlinkf $f, "$prefix$initrdImage" if $initrdImage;
  109.     }
  110.     add2hash($v,
  111.          {
  112.           type => 'image',
  113.           label => 'linux',
  114.           initrd => $initrdImage,
  115.           append => $lilo->{perImageAppend},
  116.          });
  117.     symlinkf "$vmlinuz", "$prefix/$image" if $specific;
  118.     add_entry($lilo->{entries}, $image, $v);
  119.     1;
  120.     } else {
  121.     log::l("unable to find kernel image $prefix/boot/$vmlinuz");
  122.     0;
  123.     }
  124. }
  125.  
  126. sub suggest($$$$$) {
  127.     my ($prefix, $lilo, $hds, $fstab, $kernelVersion) = @_;
  128.     my $root = fsedit::get_root($fstab)->{device};
  129.     my ($onmbr, $unsafe) = $lilo->{crushMbr} ? (1, 0) : suggest_onmbr($hds);
  130.     add2hash_($lilo, 
  131.     {
  132.      boot => "/dev/" . ($onmbr ? $hds->[0]{device} : fsedit::get_root($fstab, 'boot')->{device}),
  133.      bootUnsafe => $unsafe,
  134.      map => "/boot/map",
  135.      default => "linux",
  136.      timeout => $onmbr && 5,
  137.      install => "/boot/boot.b",
  138.     });
  139.     $lilo->{disk} ||= "/dev/$hds->[0]{device} bios=0x80" if $hds->[0]{device} =~ /^hd[be]$/;
  140.  
  141.     if (!$lilo->{message} || $lilo->{message} eq "1") {
  142.     $lilo->{message} = join('', cat_("$prefix/boot/message"));
  143.     if (!$lilo->{message}) {
  144.         my $msg_en =
  145. __("Welcome to LILO the operating system chooser!
  146.  
  147. To list the possible choices, press <TAB>.
  148.  
  149. To load one of them, write its name and press <ENTER> or wait %d seconds for default boot.
  150.  
  151. ");
  152.         my $msg = translate($msg_en);
  153.         
  154.         $msg = $msg_en if int(grep { $_ & 0x80 } unpack "c*", $msg) / length($msg) > 0.2;
  155.         $lilo->{message} = sprintf $msg, $lilo->{timeout};
  156.     }
  157.     }
  158.  
  159.     my $isSecure = -e "$prefix/boot/vmlinuz-${kernelVersion}secure";
  160.  
  161.     my $isSMP = detect_devices::hasSMP();
  162.     if ($isSMP && !-e "$prefix/boot/vmlinuz-${kernelVersion}smp") {
  163.     log::l("SMP machine, but no SMP kernel found") unless $isSecure;
  164.     $isSMP = 0;
  165.     }
  166.     add_kernel($prefix, $lilo, $kernelVersion, $isSecure ? 'secure' : 'smp',
  167.            {
  168.         label => 'linux',
  169.         root  => "/dev/$root",
  170.            }) if $isSecure || $isSMP;
  171.     add_kernel($prefix, $lilo, $kernelVersion, '',
  172.            {
  173.         label => $isSecure || $isSMP ? 'linux-up' : 'linux',
  174.         root  => "/dev/$root",
  175.            });
  176.  
  177.     
  178.     my ($dos, $win) = 0, 0;
  179.     foreach (@$hds) {
  180.     foreach (@{$_->{primary}{normal}}) {
  181.         add_entry($lilo->{entries}, "/dev/$_->{device}",
  182.           {
  183.            type => 'other',
  184.            label => isDos($_) ? "dos"     . ($dos++ ? $dos : '') :
  185.                                 "windows" . ($win++ ? $win : '') ,
  186.            table => "/dev/$_->{rootDevice}",
  187.           }) if isFat($_) && isFat({ type => fsedit::typeOfPart($_->{device}) });
  188.     }
  189.     }
  190.  
  191.     add_entry($lilo->{entries}, '/dev/fd0',
  192.       {
  193.        type => 'other',
  194.        label => 'floppy',
  195.        unsafe => 1
  196.       });
  197. }
  198.  
  199. sub keytable($$) {
  200.     my ($prefix, $f) = @_;
  201.     local $_ = $f;
  202.     if ($_ && !/\.klt$/) {
  203.     $f = "/boot/$_.klt";
  204.     run_program::rooted($prefix, "keytab-lilo.pl", ">", $f, $_) or undef $f;
  205.     }
  206.     $f && -r "$prefix/$f" && $f;
  207. }
  208.  
  209. sub install($$) {
  210.     my ($prefix, $lilo) = @_;
  211.     $lilo->{prompt} = $lilo->{timeout};
  212.  
  213.     $lilo->{keytable} = keytable($prefix, $lilo->{keytable});
  214.  
  215.     if ($lilo->{message}) {
  216.     local *F;
  217.     open F, ">$prefix/boot/message" and print F $lilo->{message} or $lilo->{message} = 0;
  218.     }
  219.     {
  220.     local *F;
  221.         local $\ = "\n";
  222.     my $f = "$prefix/etc/lilo.conf";
  223.     open F, ">$f" or die "cannot create lilo config file: $f";
  224.     log::l("writing lilo config to $f");
  225.  
  226.     $lilo->{$_} and print F "$_=$lilo->{$_}" foreach qw(boot map install vga default append keytable disk);
  227.     $lilo->{$_} and print F $_ foreach qw(linear compact prompt restricted);
  228.     
  229.     print F "timeout=", round(10 * $lilo->{timeout}) if $lilo->{timeout};
  230.     print F "message=/boot/message" if $lilo->{message};
  231.  
  232.     while (my ($v, $e) = each %{$lilo->{entries}}) {
  233.         print F "$e->{type}=$v";
  234.         print F "\tlabel=$e->{label}";
  235.  
  236.         if ($e->{type} eq "image") {
  237.         print F "\troot=$e->{root}";
  238.         print F "\tinitrd=$e->{initrd}" if $e->{initrd};
  239.         print F "\tappend=\"$1\"" if $e->{append} =~ /^\s*"?(.*?)"?\s*$/;
  240.         print F "\tvga=$e->{vga}" if $e->{vga};
  241.         print F "\tread-write" if $e->{'read-write'};
  242.         print F "\tread-only" if !$e->{'read-write'};
  243.         } else {
  244.         print F "\ttable=$e->{table}" if $e->{table};
  245.         print F "\tunsafe" if $e->{unsafe} && !$e->{table};
  246.         
  247.         
  248.         $e->{mapdrive} ||= { '0x80' => '0x81', '0x81' => '0x80' } 
  249.           if $e->{table} && $lilo->{boot} !~ /$e->{table}/;
  250.  
  251.         while (my ($from, $to) = each %{$e->{mapdrive} || {}}) {
  252.             print F "\tmap-drive=$from";
  253.             print F "\t   to=$to";
  254.         }
  255.         }
  256.     }
  257.     }
  258.     log::l("Installing boot loader...");
  259.     $::testing and return;
  260.     run_program::rooted($prefix, "lilo", "2>", "/tmp/.error") or die "lilo failed";
  261.     unlink "$prefix/tmp/.error";
  262. }
  263.  
  264.  
  265.  
  266.  
  267. 1; #
  268.