#!/usr/bin/perl # # This program is free software; you can redistribute it and/or {{{ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. }}} # use Bootloader::Tools; use strict; use Getopt::Long; use constant FALSE => 0; use constant TRUE => 1; my $GRUBDIR = "/boot/grub"; my $GRUBDEFAULT = "$GRUBDIR/default"; my $debug = FALSE; my $showHelp = FALSE; # # Prints the given stuff (variable number of arguments) if debugging has # been enabled. Does nothing otherwise. sub print_debug(@) # {{{ { if ($debug) { print STDERR @_; print STDERR "\n"; } } # }}} # # Displays help. Does not exit. sub show_help() { print STDERR "kexec-bootloader\n"; print STDERR "Loads kexec kernel from bootloader configuration.\n\n"; print STDERR "Options:\n"; print STDERR " -h | --help Shows that help message.\n"; print STDERR " -D | --debug Prints debugging information.\n"; } # # Returns the value stored with "grubonce". If no value has been stored # or the /boot/grub/default file is not readable, then -1 is returned. sub get_grubonce() # {{{ { # no /boot/grub/default file if (! -f $GRUBDEFAULT) { print_debug("get_grubonce(): No $GRUBDEFAULT."); return -1; } # read /boot/grub/default open(FH, $GRUBDEFAULT) or return -1; my $value; my $ret = sysread(FH, $value, 10); close FH; # only if we have read 4 bytes it's valid if ($ret != 10) { print_debug("get_grubonce(): Read returned $ret instead of 4."); return -1; } $value =~ s/\n//g; my $once = int($value); # 0x4000 is the "magic once flag" if ($once & 0x4000) { return $once & ~0x4000; } else { print_debug("get_grubonce(): No magic 0x40000."); return -1; } } # }}} # # Parses command line options and sets global variables. sub parse_options() # {{{ { GetOptions( "D|debug" => \$debug, "h|help" => \$showHelp ); } # }}} parse_options(); if ($showHelp) { show_help(); exit(0); } Bootloader::Tools::InitLibrary(); my $loader = Bootloader::Tools::GetBootloader(); my $default = -1; if ($loader =~ m/GRUB/i) { $default = get_grubonce(); print_debug("GRUB Default: $default"); } my $section = undef; # do we have a default? if ($default > 0) { my @sections = Bootloader::Tools::GetSectionList(); print_debug("Number of sections: " . $#sections); if ($#sections < 0 || $#sections < $default) { print STDERR "WARNING: grubonce default number ($default) is invalid.\n"; print STDERR " Falling back to the default GRUB section.\n"; } else { my $sect_name = $sections[$default]; $section = Bootloader::Tools::GetSection($sect_name); } } # use the default section if we didn't get any default otherwise if (!$section) { $section = Bootloader::Tools::GetDefaultSection(); } if ($debug) { print "Type : " . $section->{"type"}."\n"; print "Name : " . $section->{"name"}."\n"; print "Image : " . $section->{"image"}."\n"; print "Initrd : " . $section->{"initrd"}."\n"; print "VGA : " . $section->{"vgamode"}."\n"; print "Append : " . $section->{"append"}."\n"; print "Root : " . $section->{"root"}."\n"; } if ($section->{"type"} ne "image") { print STDERR "Default boot section is no image."; exit(1); } # check if the image exists if (! -f $section->{"image"}) { print STDERR "Image '" . $section->{"image"} . "' does not exist.\n"; exit(1); } # check if the initrd exists if ($section->{"initrd"} && ! -f $section->{"initrd"}) { print STDERR "Initrd '" . $section->{"initrd"} . "' does not exist.\n"; exit(1); } # Do we have kexec? if (system("which kexec &>/dev/null") != 0) { print STDERR "kexec not available. Install kexec-tools.\n"; exit(1); } # build the command list my $cmd = "kexec"; # append image $cmd .= " -l '" . $section->{"image"} . "'"; # append initrd if available if ($section->{"initrd"}) { $cmd .= " --initrd='" . $section->{"initrd"} . "'"; } # build append line my $append = ""; if ($section->{"root"}) { $append .= "root=" . $section->{"root"}; } if ($section->{"vga"}) { $append .= " vga=" . $section->{"vga"}; } if ($section->{"append"}) { $append .= " " . $section->{"append"}; } # and tell that kexec $cmd .= " --append='" . $append . "'"; print_debug("Kexec call: " . $cmd); if (system($cmd) != 0) { print STDERR "kexec($cmd) failed."; exit(1); } exit(0); # :vim set ts=4 sw=4 et fdm=markers: :collapseFolds=1: