cd3d9e04cf
OBS-URL: https://build.opensuse.org/request/show/223425 OBS-URL: https://build.opensuse.org/package/show/Kernel:kdump/kexec-tools?expand=0&rev=39
232 lines
6.2 KiB
Perl
232 lines
6.2 KiB
Perl
#!/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.
|
|
#
|
|
# Also emulate the behaviour when using GRUB which resets the 'magic once' flag
|
|
# when booting. Because we use kexec, we have to reset that 'magic once' flag
|
|
# ourselves.
|
|
sub get_grubonce_and_reset_magic() # {{{
|
|
{
|
|
# no /boot/grub/default file
|
|
if (! -f $GRUBDEFAULT) {
|
|
print_debug("get_grubonce_and_reset_magic(): 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_and_reset_magic(): ".
|
|
"Read returned $ret instead of 4.");
|
|
return -1;
|
|
}
|
|
|
|
|
|
$value =~ s/\n//g;
|
|
my $once = int($value);
|
|
|
|
# 0x4000 is the "magic once flag"
|
|
unless ($once & 0x4000) {
|
|
print_debug("get_grubonce_and_reset_magic(): No magic 0x40000.");
|
|
return -1;
|
|
}
|
|
|
|
my $defaultno = $once & ~0x4000;
|
|
my $buf = $defaultno . "\0" . "\n" x 9;
|
|
|
|
# now reset the grubonce flag
|
|
open(FH, ">$GRUBDEFAULT") or return $defaultno;
|
|
$ret = syswrite(FH, $buf, 10);
|
|
close(FH);
|
|
|
|
return $defaultno;
|
|
} # }}}
|
|
|
|
#
|
|
# 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_and_reset_magic();
|
|
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 (!$section) {
|
|
print STDERR "Unable to get default section of bootloader configuration.\n";
|
|
exit(1);
|
|
}
|
|
|
|
my $image=$section->{"image"};
|
|
my $initrd=$section->{"initrd"};
|
|
|
|
# handle btfs /@ -> /
|
|
if (substr ($image, 0, 3) eq "/@/") {
|
|
$image = substr ($image, 2);
|
|
}
|
|
if ($initrd && substr ($initrd, 0, 3) eq "/@/") {
|
|
$initrd = substr ($initrd, 2);
|
|
}
|
|
|
|
if ($debug) {
|
|
print "Type : " . $section->{"type"}."\n";
|
|
print "Name : " . $section->{"name"}."\n";
|
|
print "Image : " . $image."\n";
|
|
print "Initrd : " . $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.\n";
|
|
exit(1);
|
|
}
|
|
|
|
|
|
# check if the image exists
|
|
if (! -f $image) {
|
|
print STDERR "Image '" . $image . "' does not exist.\n";
|
|
exit(1);
|
|
}
|
|
|
|
# check if the initrd exists
|
|
if ($initrd && ! -f $initrd) {
|
|
print STDERR "Initrd '" . $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 '" . $image . "'";
|
|
|
|
# append initrd if available
|
|
if ($initrd) {
|
|
$cmd .= " --initrd='" . $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:
|