rpms/kexec-tools/devel firstboot_kdump.py, NONE, 1.1 kdump.sysconfig.i386, NONE, 1.1 kdump.sysconfig.ia64, NONE, 1.1 kdump.sysconfig.ppc64, NONE, 1.1 kdump.sysconfig.x86_64, NONE, 1.1 kexec-tools-1.101-elf-core-type.patch, NONE, 1.1 kexec-tools-1.101-elf-format.patch, NONE, 1.1 kexec-tools-1.101-ia64-EFI.patch, NONE, 1.1 kexec-tools-1.101-ia64-dash-l-fix.patch, NONE, 1.1 kexec-tools-1.101-ia64-icache-align.patch, NONE, 1.1 kexec-tools-1.101-ia64-kdump.patch, NONE, 1.1 kexec-tools-1.101-ia64-load-offset.patch, NONE, 1.1 kexec-tools-1.101-ia64-noio-eat.patch, NONE, 1.1 kexec-tools-1.101-ia64-noio.patch, NONE, 1.1 kexec-tools-1.101-ia64-phdr-malloc.patch, NONE, 1.1 kexec-tools-1.101-ia64-tools.patch, NONE, 1.1 kexec-tools-1.101-ifdown.patch, NONE, 1.1 kexec-tools-1.101-makedumpfile-configfile.patch, NONE, 1.1 kexec-tools-1.101-ppc64-64k-pages.patch, NONE, 1.1 kexec-tools-1.101-reloc-update.patch, NONE, 1.1 kexec-tools-1.101-x86_64-crashdump.patch, NONE, 1.1 kexec-tools-1.101-x86_64-exactmap.patch, NONE, 1.1 kdum! p.conf, 1.3, 1.4 kdump.init, 1.11, 1.12 kdump.sysconfig, 1.4, 1.5 kexec-tools-1.101-Makefile.patch, 1.3, 1.4 kexec-tools-1.101-ppc64-usage.patch, 1.1, 1.2 kexec-tools.spec, 1.64, 1.65 mkdumprd, 1.10, 1.11 sources, 1.3, 1.4
fedora-cvs-commits at redhat.com
fedora-cvs-commits at redhat.com
Fri Dec 15 21:05:04 UTC 2006
Author: nhorman
Update of /cvs/dist/rpms/kexec-tools/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv24284
Modified Files:
kdump.conf kdump.init kdump.sysconfig
kexec-tools-1.101-Makefile.patch
kexec-tools-1.101-ppc64-usage.patch kexec-tools.spec mkdumprd
sources
Added Files:
firstboot_kdump.py kdump.sysconfig.i386 kdump.sysconfig.ia64
kdump.sysconfig.ppc64 kdump.sysconfig.x86_64
kexec-tools-1.101-elf-core-type.patch
kexec-tools-1.101-elf-format.patch
kexec-tools-1.101-ia64-EFI.patch
kexec-tools-1.101-ia64-dash-l-fix.patch
kexec-tools-1.101-ia64-icache-align.patch
kexec-tools-1.101-ia64-kdump.patch
kexec-tools-1.101-ia64-load-offset.patch
kexec-tools-1.101-ia64-noio-eat.patch
kexec-tools-1.101-ia64-noio.patch
kexec-tools-1.101-ia64-phdr-malloc.patch
kexec-tools-1.101-ia64-tools.patch
kexec-tools-1.101-ifdown.patch
kexec-tools-1.101-makedumpfile-configfile.patch
kexec-tools-1.101-ppc64-64k-pages.patch
kexec-tools-1.101-reloc-update.patch
kexec-tools-1.101-x86_64-crashdump.patch
kexec-tools-1.101-x86_64-exactmap.patch
Log Message:
Updating fc7 with all RHEL5 work
--- NEW FILE firstboot_kdump.py ---
#
# firstboot_kdump.py - kdump configuration page for firstboot
# Copyright 2006 Red Hat, Inc.
# Author: Jarod Wilson <jwilson at redhat.com>
# Contributors:
# Neil Horman <nhorman at redhat.com>
# Dave Lehman <dlehman at redhat.com>
#
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
import sys
sys.path.append('/usr/share/system-config-kdump/')
from gtk import *
import string
import os
import os.path
import time
import gtk
import gobject
import functions
import commands
import rhpl.executil as executil
from firstboot import start_process
from rhpl.translate import _, N_
from rhpl import translate
translate.textdomain("firstboot")
class childWindow:
# runPriority determines the order in which this module runs in firstboot
runPriority = 70
moduleName = _("Kdump")
windowName = moduleName
needsReboot = False
# possible bootloaders we'll need to adjust
# bootloader : (config file, kdump offset)
bootloaders = { "grub" : ("/boot/grub/grub.conf", 16),
"yaboot" : ("/boot/etc/yaboot.conf", 32),
"elilo" : ("/boot/efi/EFI/redhat/elilo.conf", 256) }
bootloader = None
offset = 0
# list of architectures without kdump support
unsupportedArches = [ "ppc", "s390", "s390x", "i386", "i586" ]
# list of platforms that have a separate kernel-kdump
kernelKdumpArches = [ "ppc64" ]
kernelKdumpInstalled = False
# toggle sensitivity of kdump config bits
def showHide(self, status):
self.totalMem.set_sensitive(status)
self.kdumpMem.set_sensitive(status)
self.systemUsableMem.set_sensitive(status)
self.labelTotal.set_sensitive(status)
self.labelKdump.set_sensitive(status)
self.labelSys.set_sensitive(status)
self.kdumpEnabled = status
def on_enableKdumpCheck_toggled(self, *args):
showHideStatus = self.enableKdumpCheck.get_active()
self.showHide(showHideStatus)
def updateAvail(self, widget, spin):
self.remMem = self.availMem - spin.get_value_as_int()
self.systemUsableMem.set_text("%s" % self.remMem)
def getBootloader(self):
for (name, (conf, offset)) in self.bootloaders.items():
if os.access(conf, os.W_OK):
self.bootloader = name
return self.bootloader
def launch(self, doDebug = None):
self.doDebug = doDebug
if doDebug:
print "initializing kdump module"
# What kernel are we running?
self.runningKernel = os.popen("/bin/uname -r").read().strip()
# What arch are we running on?
self.arch = os.popen("/bin/uname -m").read().strip()
# Check for a xen kernel, kdump doesn't work w/xen just yet...
self.xenKernel = self.runningKernel.find("xen")
# Fedora or RHEL?
releaseFile = '/etc/redhat-release'
self.distro = 'rhel'
lines = open(releaseFile).readlines()
for line in lines:
if line.find("Fedora") != -1:
self.distro = 'fedora'
kernelKdumpArchesFC = [ "i686", "x86_64" ]
self.kernelKdumpArches.extend(kernelKdumpArchesFC)
break
# If we need kernel-kdump, check to see if its already installed
if self.arch in self.kernelKdumpArches:
self.kernelKdump = "/boot/vmlinux-%skdump" % self.runningKernel
if os.access(self.kernelKdump, os.R_OK):
self.kernelKdumpInstalled = True
# Ascertain how much memory is in the system
memInfo = open("/proc/meminfo").readlines()
self.availMem = 0
for line in memInfo:
if line.startswith("MemTotal:"):
self.availMem = int(line.split()[1]) / 1024
break
# Fix up memory calculations if kdump is already on
cmdLine = open("/proc/cmdline").read()
self.kdumpMem = 0
self.kdumpOffset = 0
self.origCrashKernel = ""
chkConfigStatus=commands.getoutput('/sbin/chkconfig --list kdump')
if chkConfigStatus.find("on") > -1:
self.kdumpEnabled = True
self.kdumpMemInitial = 0
if cmdLine.find("crashkernel") > -1:
crashString = filter(lambda t: t.startswith("crashkernel="),
cmdLine.split())[0].split("=")[1]
if self.doDebug:
print "crashString is %s" % crashString
(self.kdumpMem, self.kdumpOffset) = [int(m[:-1]) for m in crashString.split("@")]
self.availMem += self.kdumpMem
self.origCrashKernel = "%dM@%dM" % (self.kdumpMem, self.kdumpOffset)
self.kdumpMemInitial = self.kdumpMem
else:
self.kdumpEnabled = False
self.kdumpMemInitial = 0
self.initialState = self.kdumpEnabled
# Do some sanity-checking and try to present only sane options.
#
# Defaults
lowerBound = 128
minUsable = 256
step = 64
self.enoughMem = True
if self.arch == 'ia64':
# ia64 usually needs at *least* 256M, page-aligned... :(
lowerBound = 256
minUsable = 512
step = 256
elif self.arch == 'ppc64':
# ppc64 often fails w/128M lately, and we want at least 1G
# of RAM for normal use, due to 64k page size... :\
lowerBound = 256
minUsable = 1024
upperBound = (self.availMem - minUsable) - (self.availMem % step)
if upperBound < lowerBound:
self.enoughMem = False
# Set spinner to lowerBound unless already set on kernel command line
if self.kdumpMem == 0:
self.kdumpMem = lowerBound
else:
# round down to a multiple of step value
self.kdumpMem = self.kdumpMem - (self.kdumpMem % step)
# kdump enable/disable checkbox
self.enableKdumpCheck = gtk.CheckButton("Enable kdump?")
self.enableKdumpCheck.set_alignment(xalign=0, yalign=0)
# detected total amount of system memory
self.totalMem = gtk.Label(_("%s" % self.availMem))
self.labelTotal = gtk.Label(_("_Total System Memory (MB):"))
self.labelTotal.set_use_underline(True)
self.labelTotal.set_mnemonic_widget(self.totalMem)
self.labelTotal.set_alignment(0.0, 0.5)
self.labelTotal.set_width_chars(32)
# how much ram to reserve for kdump
self.memSpin = gtk.Adjustment(self.kdumpMem, lowerBound, upperBound, step, step, 64)
self.kdumpMem = gtk.SpinButton(self.memSpin, 0, 0)
self.kdumpMem.set_update_policy(gtk.UPDATE_IF_VALID)
self.kdumpMem.set_numeric(True)
self.memSpin.connect("value_changed", self.updateAvail, self.kdumpMem)
self.labelKdump = gtk.Label(_("_Kdump Memory (MB):"))
self.labelKdump.set_use_underline(True)
self.labelKdump.set_mnemonic_widget(self.kdumpMem)
self.labelKdump.set_alignment(0.0, 0.5)
# remaining usable system memory
self.resMem = eval(string.strip(self.kdumpMem.get_text()))
self.remMem = self.availMem - self.resMem
self.systemUsableMem = gtk.Label(_("%s" % self.remMem))
self.labelSys = gtk.Label(_("_Usable System Memory (MB):"))
self.labelSys.set_use_underline(True)
self.labelSys.set_mnemonic_widget(self.systemUsableMem)
self.labelSys.set_alignment(0.0, 0.5)
self.vbox = gtk.VBox()
self.vbox.set_size_request(400, 200)
title_pix = functions.imageFromFile("workstation.png")
internalVBox = gtk.VBox()
internalVBox.set_border_width(10)
internalVBox.set_spacing(10)
label = gtk.Label(_("Kdump is a kernel crash dumping mechanism. In the event of a "
"system crash, kdump will capture information from your system "
"that can be invaluable in determining the cause of the crash. "
"Note that kdump does require reserving a portion of system "
"memory that will be unavailable for other uses."))
label.set_line_wrap(True)
label.set_alignment(0.0, 0.5)
label.set_size_request(500, -1)
internalVBox.pack_start(label, False, True)
table = gtk.Table(2, 4)
table.attach(self.enableKdumpCheck, 0, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)
table.attach(self.labelTotal, 0, 1, 1, 2, gtk.FILL)
table.attach(self.totalMem, 1, 2, 1, 2, gtk.SHRINK, gtk.FILL, 5, 5)
table.attach(self.labelKdump, 0, 1, 2, 3, gtk.FILL)
table.attach(self.kdumpMem, 1, 2, 2, 3, gtk.SHRINK, gtk.FILL, 5, 5)
table.attach(self.labelSys, 0, 1, 3, 4, gtk.FILL)
table.attach(self.systemUsableMem, 1, 2, 3, 4, gtk.SHRINK, gtk.FILL, 5, 5)
# disable until user clicks check box, if not already enabled
if self.initialState is False:
self.showHide(False)
else:
self.enableKdumpCheck.set_active(True)
internalVBox.pack_start(table, True, 15)
# toggle sensitivity of Mem items
self.enableKdumpCheck.connect("toggled", self.on_enableKdumpCheck_toggled)
self.vbox.pack_start(internalVBox, False, 15)
return self.vbox, title_pix, self.moduleName
def grabFocus(self):
self.enableKdumpCheck.grab_focus()
def apply(self, *args):
if self.kdumpEnabled:
totalSysMem = self.totalMem.get_text()
totalSysMem = eval(string.strip(totalSysMem))
reservedMem = self.kdumpMem.get_value_as_int()
remainingMem = totalSysMem - reservedMem
else:
reservedMem = self.kdumpMemInitial
if self.doDebug:
print "Running kernel %s on %s architecture" % (self.runningKernel, self.arch)
if self.enableKdumpCheck.get_active():
print "System Mem: %s MB Kdump Mem: %s MB Avail Mem: %s MB" % (totalSysMem, reservedMem, remainingMem)
else:
print "Kdump will be disabled"
# If the user simply doesn't have enough memory for kdump to be viable/supportable, tell 'em
if self.enoughMem is False and self.kdumpEnabled:
self.showErrorMessage(_("Sorry, your system does not have enough memory for kdump to be viable!"))
self.enableKdumpCheck.set_active(False)
self.showHide(False)
return 0
# Alert user that we're not going to turn on kdump if they're running a xen kernel
elif self.xenKernel != -1 and self.kdumpEnabled:
self.showErrorMessage(_("Sorry, Xen kernels do not support kdump at this time!"))
self.enableKdumpCheck.set_active(False)
self.showHide(False)
return 0
# If there's no kdump support on this arch, let the user know and don't configure
elif self.arch in self.unsupportedArches:
self.showErrorMessage(_("Sorry, the %s architecture does not support kdump at this time!" % self.arch))
self.enableKdumpCheck.set_active(False)
self.showHide(False)
return 0
# If running on an arch w/a separate kernel-kdump (i.e., non-relocatable kernel), check to
# see that its installed, otherwise, alert the user they need to install it, and give them
# the chance to abort configuration.
if self.arch in self.kernelKdumpArches and self.kernelKdumpInstalled is False:
kernelKdumpNote = "\n\nNote that the %s architecture does not feature a relocatable kernel at this time, and thus requires a separate kernel-kdump package to be installed for kdump to function. This can be installed via 'yum install kernel-kdump' at your convenience.\n\n" % self.arch
else:
kernelKdumpNote = ""
# Don't alert if nothing has changed
if self.initialState != self.kdumpEnabled or reservedMem != self.kdumpMemInitial:
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
gtk.BUTTONS_YES_NO,
_("Changing Kdump settings requires rebooting the "
"system to reallocate memory accordingly. %sWould you "
"like to continue with this change and reboot the "
"system after firstboot is complete?" % kernelKdumpNote))
dlg.set_position(gtk.WIN_POS_CENTER)
dlg.show_all()
rc = dlg.run()
dlg.destroy()
if rc == gtk.RESPONSE_NO:
self.needsReboot = False
return None
else:
self.needsReboot = True
# Find bootloader if it exists, and update accordingly
if self.getBootloader() == None:
self.showErrorMessage(_("Error! No bootloader config file found, aborting configuration!"))
self.enableKdumpCheck.set_active(False)
self.showHide(False)
return 0
else:
self.offset = self.bootloaders[self.bootloader][1]
# Are we adding or removing the crashkernel param?
if self.kdumpEnabled:
grubbyCmd = "/sbin/grubby --%s --update-kernel=/boot/vmlinuz-%s --args=crashkernel=%iM@%iM" \
% (self.bootloader, self.runningKernel, reservedMem, self.offset)
chkconfigStatus = "on"
else:
grubbyCmd = "/sbin/grubby --%s --update-kernel=/boot/vmlinuz-%s --remove-args=crashkernel=%s" \
% (self.bootloader, self.runningKernel, self.origCrashKernel)
chkconfigStatus = "off"
if self.doDebug:
print "Using %s bootloader with %iM offset" % (self.bootloader, self.offset)
print "Grubby command would be:\n %s" % grubbyCmd
else:
os.system(grubbyCmd)
os.system("/sbin/chkconfig kdump %s" % chkconfigStatus)
if self.bootloader == 'yaboot':
os.system('/sbin/ybin')
else:
self.needsReboot = False
return 0
def showErrorMessage(self, text):
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text)
dlg.set_position(gtk.WIN_POS_CENTER)
dlg.set_modal(True)
rc = dlg.run()
dlg.destroy()
return None
--- NEW FILE kdump.sysconfig.i386 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=" --args-linux"
#Where to find the boot image
KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""
--- NEW FILE kdump.sysconfig.ia64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
KDUMP_BOOTDIR="/boot/efi/efi/redhat"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""
--- NEW FILE kdump.sysconfig.ppc64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinux"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT="kdump"
--- NEW FILE kdump.sysconfig.x86_64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=" --args-linux"
#Where to find the boot image
KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""
kexec-tools-1.101-elf-core-type.patch:
kexec-x86.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
--- NEW FILE kexec-tools-1.101-elf-core-type.patch ---
--- kexec-tools-1.101/kexec/arch/i386/kexec-x86.c.orig 2006-11-15 16:28:04.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-x86.c 2006-11-15 16:28:13.000000000 -0500
@@ -145,7 +145,7 @@
.serial_baud = 0,
.console_vga = 0,
.console_serial = 0,
- .core_header_type = CORE_TYPE_ELF64,
+ .core_header_type = CORE_TYPE_ELF32,
};
int arch_process_options(int argc, char **argv)
kexec-tools-1.101-elf-format.patch:
i386/kexec-elf-x86.c | 2 +-
x86_64/kexec-elf-x86_64.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- NEW FILE kexec-tools-1.101-elf-format.patch ---
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c.fix 2006-08-29 20:07:34.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c 2006-08-29 20:08:03.000000000 -0400
@@ -120,7 +120,7 @@ int elf_x86_64_load(int argc, char **arg
/*
* Parse the command line arguments
*/
- arg_style = ARG_STYLE_ELF;
+ arg_style = ARG_STYLE_LINUX;
command_line = 0;
modified_cmdline = 0;
modified_cmdline_len = 0;
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c.fix 2006-08-29 20:07:14.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c 2006-08-29 20:07:24.000000000 -0400
@@ -121,7 +121,7 @@ int elf_x86_load(int argc, char **argv,
/*
* Parse the command line arguments
*/
- arg_style = ARG_STYLE_ELF;
+ arg_style = ARG_STYLE_LINUX;
command_line = 0;
modified_cmdline = 0;
modified_cmdline_len = 0;
kexec-tools-1.101-ia64-EFI.patch:
kexec/arch/ia64/kexec-elf-ia64.c | 10 +++++
kexec/arch/ia64/kexec-ia64.c | 40 ++++++++++++++++++++++
purgatory/arch/ia64/entry.S | 3 +
purgatory/arch/ia64/purgatory-ia64.c | 62 ++++++++++++++++++-----------------
4 files changed, 83 insertions(+), 32 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-EFI.patch ---
--- kexec-tools-1.101/purgatory/arch/ia64/entry.S.orig1 2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/entry.S 2006-10-12 14:48:04.000000000 -0400
@@ -46,6 +46,8 @@
br.call.sptk.many b0=ia64_env_setup
movl r10=__kernel_entry;;
ld8 r14=[r10];;
+ movl r10=__boot_param_base;;
+ ld8 r28=[r10];;
mov b6=r14;;
mov ar.lc=r0
mov ar.ec=r0
@@ -61,6 +63,7 @@
DECLARE_DATA8(__command_line_len)
DECLARE_DATA8(__efi_memmap_base)
DECLARE_DATA8(__efi_memmap_size)
+DECLARE_DATA8(__boot_param_base)
DECLARE_DATA8(__loaded_segments)
DECLARE_DATA8(__loaded_segments_num)
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig1 2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c 2006-10-12 14:48:04.000000000 -0400
@@ -123,11 +123,12 @@
uint64_t command_line_len;
uint64_t efi_memmap_base;
uint64_t efi_memmap_size;
+ uint64_t boot_param_base;
struct loaded_segment *loaded_segments;
unsigned long loaded_segments_num;
};
-void
+void
setup_arch(void)
{
reset_vga();
@@ -138,11 +139,11 @@
return addr - PAGE_OFFSET;
}
-void
-patch_efi_memmap(struct kexec_boot_params *params,
+void
+patch_efi_memmap(struct kexec_boot_params *params,
struct ia64_boot_param *boot_param)
{
- void *dest = (void *)params->efi_memmap_base;
+ void *dest = (void *)params->efi_memmap_base;
void *src = (void *)boot_param->efi_memmap;
unsigned long len = boot_param->efi_memmap_size;
unsigned long memdesc_size = boot_param->efi_memdesc_size;
@@ -150,15 +151,15 @@
efi_memory_desc_t *md1, *md2;
void *p1, *p2, *src_end = src + len;
int i;
- for (p1 = src, p2 = dest; p1 < src_end;
+ for (p1 = src, p2 = dest; p1 < src_end;
p1 += memdesc_size, p2 += memdesc_size) {
unsigned long mstart, mend;
md1 = p1;
md2 = p2;
- if (md1->num_pages == 0)
+ if (md1->num_pages == 0)
continue;
mstart = md1->phys_addr;
- mend = md1->phys_addr + (md1->num_pages
+ mend = md1->phys_addr + (md1->num_pages
<< EFI_PAGE_SHIFT);
switch (md1->type) {
case EFI_LOADER_DATA:
@@ -168,7 +169,7 @@
default:
*md2 = *md1;
}
- // segments are already sorted and aligned to 4K
+ // segments are already sorted and aligned to 4K
orig_type = md2->type;
for (i = 0; i < params->loaded_segments_num; i++) {
struct loaded_segment *seg;
@@ -177,50 +178,50 @@
unsigned long start_pages, mid_pages, end_pages;
if (seg->end > mend) {
p1 += memdesc_size;
- for(; p1 < src_end;
+ for(; p1 < src_end;
p1 += memdesc_size) {
md1 = p1;
/* TODO check contig and attribute here */
- mend = md1->phys_addr
+ mend = md1->phys_addr
+ (md1->num_pages << EFI_PAGE_SHIFT);
if (seg->end < mend)
break;
}
}
- start_pages = (seg->start - mstart)
+ start_pages = (seg->start - mstart)
>> EFI_PAGE_SHIFT;
mid_pages = (seg->end - seg->start)
>> EFI_PAGE_SHIFT;
- end_pages = (mend - seg->end)
+ end_pages = (mend - seg->end)
>> EFI_PAGE_SHIFT;
if (start_pages) {
md2->num_pages = start_pages;
- p2 += memdesc_size;
+ p2 += memdesc_size;
md2 = p2;
*md2 = *md1;
}
md2->phys_addr = seg->start;
md2->num_pages = mid_pages;
- md2->type = seg->reserved ?
+ md2->type = seg->reserved ?
EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA;
if (end_pages) {
- p2 += memdesc_size;
+ p2 += memdesc_size;
md2 = p2;
*md2 = *md1;
md2->phys_addr = seg->end;
md2->num_pages = end_pages;
md2->type = orig_type;
mstart = seg->end;
- } else
+ } else
break;
}
}
}
-
+
boot_param->efi_memmap_size = p2 - dest;
}
-void
+void
flush_icache_range(char *start, unsigned long len)
{
unsigned long i;
@@ -233,7 +234,7 @@
extern char __dummy_efi_function[], __dummy_efi_function_end[];
-void
+void
ia64_env_setup(struct ia64_boot_param *boot_param,
struct kexec_boot_params *params)
{
@@ -243,13 +244,15 @@
unsigned long *set_virtual_address_map;
char *command_line = (char *)params->command_line;
uint64_t command_line_len = params->command_line_len;
-
+ struct ia64_boot_param *new_boot_param =
+ (struct ia64_boot_param *) params->boot_param_base;
+ memcpy(new_boot_param, boot_param, 4096);
// patch efi_runtime->set_virtual_address_map to a
// dummy function
len = __dummy_efi_function_end - __dummy_efi_function;
- memcpy(command_line + command_line_len,
+ memcpy(command_line + command_line_len,
__dummy_efi_function, len);
- systab = (efi_system_table_t *)boot_param->efi_systab;
+ systab = (efi_system_table_t *)new_boot_param->efi_systab;
runtime = (efi_runtime_services_t *)PA(systab->runtime);
set_virtual_address_map =
(unsigned long *)PA(runtime->set_virtual_address_map);
@@ -257,15 +260,14 @@
(unsigned long)(command_line + command_line_len);
flush_icache_range(command_line + command_line_len, len);
- patch_efi_memmap(params, boot_param);
-
- boot_param->efi_memmap = params->efi_memmap_base;
+ patch_efi_memmap(params, new_boot_param);
- boot_param->command_line = params->command_line;
- boot_param->console_info.orig_x = 0;
- boot_param->console_info.orig_y = 0;
- boot_param->initrd_start = params->ramdisk_base;
- boot_param->initrd_size = params->ramdisk_size;
+ new_boot_param->efi_memmap = params->efi_memmap_base;
+ new_boot_param->command_line = params->command_line;
+ new_boot_param->console_info.orig_x = 0;
+ new_boot_param->console_info.orig_y = 0;
+ new_boot_param->initrd_start = params->ramdisk_base;
+ new_boot_param->initrd_size = params->ramdisk_size;
}
/* This function can be used to execute after the SHA256 verification. */
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig1 2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c 2006-10-12 14:47:57.000000000 -0400
@@ -36,6 +36,38 @@
static struct memory_range memory_range[MAX_MEMORY_RANGES];
+/* Reserve range for EFI memmap and Boot parameter */
+static int split_range(int range, unsigned long start, unsigned long end)
+{
+ unsigned long ram_end = memory_range[range - 1].end;
+ unsigned int type = memory_range[range - 1].type;
+ int i;
+ //align end and start to page size of EFI
+ start = start & ~((1UL<<12) - 1);
+ end = (end + (1UL<<12) - 1)& ~((1UL<<12) - 1);
+ for (i = 0; i < range; i++)
+ if(memory_range[i].start <= start && memory_range[i].end >=end)
+ break;
+ if (i >= range)
+ return range;
+ range = i;
+ if (memory_range[range].start < start) {
+ memory_range[range].end = start;
+ range++;
+ }
+ memory_range[range].start = start;
+ memory_range[range].end = end;
+ memory_range[range].type = RANGE_RESERVED;
+ range++;
+ if (end < ram_end) {
+ memory_range[range].start = end;
+ memory_range[range].end = ram_end;
+ memory_range[range].type = type;
+ range++;
+ }
+ return range;
+}
+
/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
unsigned long kexec_flags)
@@ -85,6 +117,12 @@
mem_max = end;
}
continue;
+ } else if (memcmp(str, "Boot parameter\n", 14) == 0) {
+ memory_ranges = split_range(memory_ranges, start, end);
+ continue;
+ } else if (memcmp(str, "EFI Memory Map\n", 14) == 0) {
+ memory_ranges = split_range(memory_ranges, start, end);
+ continue;
} else
continue;
/*
@@ -125,7 +163,7 @@
{
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
- { 0, 0, NULL, 0 },
+ { 0, 0, NULL, 0 },
};
static const char short_options[] = KEXEC_ARCH_OPT_STR;
int opt;
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig1 2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-10-12 14:48:04.000000000 -0400
@@ -115,9 +115,10 @@
unsigned long entry, max_addr, gp_value;
unsigned long command_line_base, ramdisk_base;
unsigned long efi_memmap_base, efi_memmap_size;
+ unsigned long boot_param_base;
int result;
int opt;
- char *efi_memmap_buf;
+ char *efi_memmap_buf, *boot_param;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
static const struct option options[] = {
@@ -191,6 +192,13 @@
&command_line) < 0)
return -1;
+ // reverve 4k for ia64_boot_param
+ boot_param = xmalloc(4096);
+ boot_param_base = add_buffer(info, boot_param, 4096, 4096, 4096, 0,
+ max_addr, -1);
+ elf_rel_set_symbol(&info->rhdr, "__boot_param_base",
+ &boot_param_base, sizeof(long));
+
// reserve 8k for efi_memmap
efi_memmap_size = 1UL<<14;
efi_memmap_buf = xmalloc(efi_memmap_size);
kexec-tools-1.101-ia64-dash-l-fix.patch:
kexec-elf-ia64.c | 15 +++++++++++----
kexec-ia64.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
kexec-ia64.h | 4 ++++
3 files changed, 57 insertions(+), 6 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-dash-l-fix.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h.orig 2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h 2006-12-01 14:49:13.000000000 -0500
@@ -7,6 +7,10 @@
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
void elf_ia64_usage(void);
+int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr);
+void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
+ unsigned long addr);
+
#define MAX_MEMORY_RANGES 1024
#define EFI_PAGE_SIZE (1UL<<12)
#define ELF_PAGE_SIZE (1UL<<16)
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig 2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c 2006-12-01 14:55:16.000000000 -0500
@@ -28,14 +28,16 @@
#include <string.h>
#include <getopt.h>
#include <sched.h>
+#include <limits.h>
#include <sys/utsname.h>
#include "../../kexec.h"
#include "../../kexec-syscall.h"
+#include "elf.h"
#include "kexec-ia64.h"
#include <arch/options.h>
static struct memory_range memory_range[MAX_MEMORY_RANGES];
-
+static int memory_ranges;
/* Reserve range for EFI memmap and Boot parameter */
static int split_range(int range, unsigned long start, unsigned long end)
{
@@ -73,7 +75,6 @@
unsigned long kexec_flags)
{
const char iomem[]= "/proc/iomem";
- int memory_ranges = 0;
char line[MAX_LINE];
FILE *fp;
fp = fopen(iomem, "r");
@@ -209,6 +210,45 @@
return 0;
}
+int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+{
+ int i;
+ struct mem_phdr *phdr;
+ unsigned long start_addr = ULONG_MAX, end_addr = 0;
+ unsigned long align = 1UL<<26; // 64M
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ if (phdr->p_paddr < start_addr)
+ start_addr = phdr->p_paddr;
+ if ((phdr->p_paddr + phdr->p_memsz) > end_addr)
+ end_addr = phdr->p_paddr + phdr->p_memsz;
+ }
+
+ }
+
+ for (i = 0; i < memory_ranges
+ && memory_range[i].start <= start_addr; i++) {
+ if (memory_range[i].type == RANGE_RAM &&
+ memory_range[i].end > end_addr)
+ return;
+ }
+
+ for (i = 0; i < memory_ranges; i++) {
+ if (memory_range[i].type == RANGE_RAM) {
+ unsigned long start =
+ (memory_range[i].start + align - 1)&~(align - 1);
+ unsigned long end = memory_range[i].end;
+ if (end > start &&
+ (end - start) > (end_addr - start_addr)) {
+ move_loaded_segments(info, ehdr, start);
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
void arch_update_purgatory(struct kexec_info *info)
{
}
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-12-01 14:59:29.000000000 -0500
@@ -84,7 +84,8 @@
/* Move the crash kerenl physical offset to reserved region
*/
-static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
+ unsigned long addr)
{
int i;
long offset;
@@ -92,7 +93,7 @@
for(i = 0; i < ehdr->e_phnum; i++) {
phdr = &ehdr->e_phdr[i];
if (phdr->p_type == PT_LOAD) {
- offset = mem_min - phdr->p_paddr;
+ offset = addr - phdr->p_paddr;
break;
}
}
@@ -174,8 +175,14 @@
fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n");
return -1;
}
- move_loaded_segments(info, &ehdr);
- }
+ move_loaded_segments(info, &ehdr, mem_min);
+ } else {
+ if (update_loaded_segments(info, &ehdr)) {
+ fprintf(stderr, "Failed to place kernel\n");
+ return -1;
+ }
+ }
+
entry = ehdr.e_entry;
max_addr = elf_max_addr(&ehdr);
kexec-tools-1.101-ia64-icache-align.patch:
purgatory-ia64.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletion(-)
--- NEW FILE kexec-tools-1.101-ia64-icache-align.patch ---
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig 2006-10-20 13:45:49.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c 2006-10-20 13:46:56.000000000 -0400
@@ -224,7 +224,9 @@
void
flush_icache_range(char *start, unsigned long len)
{
- unsigned long i;
+ unsigned long i,addr;
+ addr = (unsigned long)start & ~31UL;
+ len += (unsigned long)start - addr;
for (i = 0;i < len; i += 32)
asm volatile("fc.i %0"::"r"(start + i):"memory");
asm volatile (";;sync.i;;":::"memory");
kexec-tools-1.101-ia64-kdump.patch:
kexec/arch/ia64/Makefile | 2
kexec/arch/ia64/crashdump-ia64.c | 351 +++++++++++++++++++++++++++++++++++
kexec/arch/ia64/crashdump-ia64.h | 13 +
kexec/arch/ia64/kexec-elf-ia64.c | 80 +++++++
kexec/arch/ia64/kexec-elf-rel-ia64.c | 37 +++
kexec/arch/ia64/kexec-ia64.h | 4
kexec/kexec-sha256.h | 2
kexec/kexec.c | 3
purgatory/arch/ia64/Makefile | 2
purgatory/arch/ia64/console-ia64.c | 44 ++++
purgatory/arch/ia64/entry.S | 54 +----
purgatory/arch/ia64/io.h | 94 +++++++++
purgatory/arch/ia64/purgatory-ia64.c | 188 +++++++++++++++++-
purgatory/arch/ia64/purgatory-ia64.h | 3
purgatory/arch/ia64/vga.c | 143 ++++++++++++++
15 files changed, 955 insertions(+), 65 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-kdump.patch ---
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.c
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.c 2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,351 @@
+/*
+ * kexec: crashdum support
+ * Copyright (C) 2005-2006 Zou Nan hai <nanhai.zou at intel.com> Intel Corp
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
+#include "kexec-ia64.h"
+#include "crashdump-ia64.h"
+
+int memory_ranges = 0;
+#define LOAD_OFFSET (0xa000000000000000UL + 0x100000000UL - (1UL<<26))
+#define MAX_LINE 160
+/* Stores a sorted list of RAM memory ranges for which to create elf headers.
+ * A separate program header is created for backup region */
+static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+/* Memory region reserved for storing panic kernel and other data. */
+static struct memory_range crash_reserved_mem;
+unsigned long elfcorehdr;
+static unsigned long kernel_code_start;
+struct loaded_segment {
+ unsigned long start;
+ unsigned long end;
+ unsigned long reserved;
+};
+
+#define MAX_LOAD_SEGMENTS 128
+struct loaded_segment loaded_segments[MAX_LOAD_SEGMENTS];
+
+unsigned long loaded_segments_num, loaded_segments_base;
+static int seg_comp(const void *a, const void *b)
+{
+ const struct loaded_segment *x = a, *y = b;
+ /* avoid overflow */
+ if (x->start > y->start) return 1;
+ if (x->start < y->start) return -1;
+ return 0;
+}
+
+/* purgatory code need this info to patch the EFI memmap
+ */
+static void add_loaded_segments_info(struct kexec_info *info,
+ struct mem_ehdr *ehdr, unsigned long max_addr)
+{
+ int i;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ unsigned long start, end;
+ struct mem_phdr *phdr;
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type != PT_LOAD)
+ continue;
+ start = phdr->p_paddr;
+ end = phdr->p_paddr + phdr->p_memsz;
+
+ loaded_segments[loaded_segments_num].start =
+ start&~(ELF_PAGE_SIZE-1);
+ loaded_segments[loaded_segments_num].end =
+ (end + ELF_PAGE_SIZE - 1)&~(ELF_PAGE_SIZE - 1);
+ loaded_segments[loaded_segments_num].reserved = 0;
+ loaded_segments_num++;
+ }
+}
+
+static int get_crash_notes_section_addr(unsigned long *addr, int cpu)
+{
+ char crash_notes[128];
+ char line[MAX_LINE];
+ FILE *fp;
+ sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu);
+ fp = fopen(crash_notes, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ crash_notes, strerror(errno));
+ fprintf(stderr, "Try mounting sysfs\n");
+ return -1;
+ }
+ if (fscanf(fp, "%lx", addr) != 1) {
+ *addr = 0;
+ return -1;
+ }
+ return 0;
+}
+
+/* Removes crash reserve region from list of memory chunks for whom elf program
+ * headers have to be created. Assuming crash reserve region to be a single
+ * continuous area fully contained inside one of the memory chunks */
+static int exclude_crash_reserve_region(int *nr_ranges)
+{
+ int i, j, tidx = -1;
+ unsigned long cstart, cend;
+ struct memory_range temp_region;
+
+ /* Crash reserved region. */
+ cstart = crash_reserved_mem.start;
+ cend = crash_reserved_mem.end;
+
+ for (i = 0; i < (*nr_ranges); i++) {
+ unsigned long mstart, mend;
+ mstart = crash_memory_range[i].start;
+ mend = crash_memory_range[i].end;
+ if (cstart < mend && cend > mstart) {
+ if (cstart != mstart && cend != mend) {
+ /* Split memory region */
+ crash_memory_range[i].end = cstart - 1;
+ temp_region.start = cend + 1;
+ temp_region.end = mend;
+ temp_region.type = RANGE_RAM;
+ tidx = i+1;
+ } else if (cstart != mstart)
+ crash_memory_range[i].end = cstart - 1;
+ else
+ crash_memory_range[i].start = cend + 1;
+ }
+ }
+ /* Insert split memory region, if any. */
+ if (tidx >= 0) {
+ if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
+ /* No space to insert another element. */
+ fprintf(stderr, "Error: Number of crash memory ranges"
+ " excedeed the max limit\n");
+ return -1;
+ }
+ for (j = (*nr_ranges - 1); j >= tidx; j--)
+ crash_memory_range[j+1] = crash_memory_range[j];
+ crash_memory_range[tidx].start = temp_region.start;
+ crash_memory_range[tidx].end = temp_region.end;
+ crash_memory_range[tidx].type = temp_region.type;
+ (*nr_ranges)++;
+ }
+ return 0;
+}
+
+static int prepare_crash_memory_elf64_headers(struct kexec_info *info,
+ void *buf, unsigned long size)
+{
+ Elf64_Ehdr *elf;
+ Elf64_Phdr *phdr;
+ int i;
+ long int nr_cpus = 0;
+ char *bufp = buf;
+ unsigned long notes_addr, notes_offset;
+
+ /* Setup ELF Header*/
+ elf = (Elf64_Ehdr *) bufp;
+ bufp += sizeof(Elf64_Ehdr);
+ memcpy(elf->e_ident, ELFMAG, SELFMAG);
+ elf->e_ident[EI_CLASS] = ELFCLASS64;
+ elf->e_ident[EI_DATA] = ELFDATA2LSB;
+ elf->e_ident[EI_VERSION]= EV_CURRENT;
+ elf->e_ident[EI_OSABI] = ELFOSABI_NONE;
+ memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+ elf->e_type = ET_CORE;
+ elf->e_machine = EM_IA_64;
+ elf->e_version = EV_CURRENT;
+ elf->e_entry = 0;
+ elf->e_phoff = sizeof(Elf64_Ehdr);
+ elf->e_shoff = 0;
+ elf->e_flags = 0;
+ elf->e_ehsize = sizeof(Elf64_Ehdr);
+ elf->e_phentsize= sizeof(Elf64_Phdr);
+ elf->e_phnum = 0;
+ elf->e_shentsize= 0;
+ elf->e_shnum = 0;
+ elf->e_shstrndx = 0;
+
+ /* PT_NOTE program headers. One per cpu*/
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (nr_cpus < 0) {
+ return -1;
+ }
+
+ /* Need to find a better way to determine per cpu notes section size. */
+#define MAX_NOTE_BYTES 1024
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (get_crash_notes_section_addr (¬es_addr, i) < 0)
+ break;
+ notes_offset = notes_addr;
+ phdr = (Elf64_Phdr *) bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_NOTE;
+ phdr->p_flags = 0;
+ phdr->p_offset = notes_offset;
+ phdr->p_vaddr = phdr->p_paddr = notes_offset;
+ phdr->p_filesz = phdr->p_memsz = MAX_NOTE_BYTES;
+ /* Do we need any alignment of segments? */
+ phdr->p_align = 0;
+
+ /* Increment number of program headers. */
+ (elf->e_phnum)++;
+ }
+
+ for (i = 0; i < memory_ranges; i++) {
+ unsigned long mstart, mend;
+ mstart = crash_memory_range[i].start;
+ mend = crash_memory_range[i].end;
+ if (!mstart && !mend)
+ break;
+ phdr = (Elf64_Phdr *) bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_LOAD;
+ phdr->p_flags = PF_R|PF_W|PF_X;
+ phdr->p_offset = mstart;
+ /*add region 5 mapping for kernel*/
+ if (kernel_code_start >= mstart && kernel_code_start < mend) {
+ phdr->p_vaddr = mstart + LOAD_OFFSET;
+ phdr->p_paddr = mstart;
+ phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
+ phdr->p_align = 0;
+ (elf->e_phnum)++;
+
+ phdr = (Elf64_Phdr *) bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_LOAD;
+ phdr->p_flags = PF_R|PF_W|PF_X;
+ phdr->p_offset = mstart;
+ }
+ phdr->p_vaddr = mstart + PAGE_OFFSET;
+ phdr->p_paddr = mstart;
+ phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
+ phdr->p_align = 0;
+ (elf->e_phnum)++;
+ }
+ return 0;
+}
+
+static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
+{
+ const char iomem[]= "/proc/iomem";
+ char line[MAX_LINE];
+ FILE *fp;
+ unsigned long start, end;
+
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ char *str;
+ int type, consumed, count;
+ if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%lx-%lx : %n",
+ &start, &end, &consumed);
+ str = line + consumed;
+ if (count != 2)
+ continue;
+
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ } else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+ /* Reserved memory region. New kernel can
+ * use this region to boot into. */
+ crash_reserved_mem.start = start;
+ crash_reserved_mem.end = end;
+ crash_reserved_mem.type = RANGE_RAM;
+ continue;
+ }
+ else if (memcmp(str, "Kernel code\n", 12) == 0) {
+ kernel_code_start = start;
+ continue;
+ }else
+ continue;
+ crash_memory_range[memory_ranges].start = start;
+ crash_memory_range[memory_ranges].end = end;
+ crash_memory_range[memory_ranges].type = type;
+ memory_ranges++;
+ }
+ fclose(fp);
+ if (exclude_crash_reserve_region(&memory_ranges) < 0)
+ return -1;
+ *ranges = memory_ranges;
+ return 0;
+}
+
+static void
+cmdline_add_elfcorehdr(char **cmdline, unsigned long addr)
+{
+ char *str = *cmdline;
+ char buf[64];
+ size_t len;
+ sprintf(buf, " elfcorehdr=%ldK", addr/1024);
+ len = strlen(str) + strlen(buf) + 1;
+ str = xmalloc(len);
+ sprintf(str, "%s%s", *cmdline, buf);
+ *cmdline = str;
+}
+
+int load_crashdump_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
+ unsigned long max_addr, unsigned long min_base,
+ char **cmdline)
+{
+ //struct memory_range *mem_range, *memmap_p;
+ struct memory_range *mem_range;
+ int nr_ranges;
+ size_t size;
+ void *tmp;
+ if (info->kexec_flags & KEXEC_ON_CRASH ) {
+ if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) {
+ size = sizeof(Elf64_Ehdr) +
+ (nr_ranges + 1) * sizeof(Elf64_Phdr);
+ size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1);
+ tmp = xmalloc(size);
+ memset(tmp, 0, size);
+ if (prepare_crash_memory_elf64_headers(info, tmp, size) < 0)
+ return -1;
+ elfcorehdr = add_buffer(info, tmp, size, size, EFI_PAGE_SIZE, min_base,
+ max_addr, -1);
+ loaded_segments[loaded_segments_num].start = elfcorehdr;
+ loaded_segments[loaded_segments_num].end = elfcorehdr + size;
+ loaded_segments[loaded_segments_num].reserved = 1;
+ loaded_segments_num++;
+ cmdline_add_elfcorehdr(cmdline, elfcorehdr);
+ }
+ }
+ add_loaded_segments_info(info, ehdr, max_addr);
+ size = sizeof(struct loaded_segment) * loaded_segments_num;
+ qsort(loaded_segments, loaded_segments_num,
+ sizeof(struct loaded_segment), seg_comp);
+ loaded_segments_base = add_buffer(info, loaded_segments,
+ size, size, 16, 0, max_addr, -1);
+
+ elf_rel_set_symbol(&info->rhdr, "__loaded_segments",
+ &loaded_segments_base, sizeof(long));
+ elf_rel_set_symbol(&info->rhdr, "__loaded_segments_num",
+ &loaded_segments_num, sizeof(long));
+ return 0;
+}
+
+
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.h
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.h 2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,13 @@
+#ifndef CRASHDUMP_IA64_H
+#define CRASHDUMP_IA64_H
+
+#define PAGE_OFFSET 0xe000000000000000UL
+#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
+extern int load_crashdump_segments(struct kexec_info *info,
+ struct mem_ehdr *ehdr, unsigned long max_addr,
+ unsigned long min_base, char **cmdline);
+
+#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1)
+#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
+
+#endif
diff -puN kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-ia64.c
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-ia64.c 2006-07-13 14:42:05.000000000 +0530
@@ -40,7 +40,9 @@
#include <boot/elf_boot.h>
#include <ip_checksum.h>
#include "../../kexec.h"
+#include "../../kexec-syscall.h"
#include "../../kexec-elf.h"
+#include "crashdump-ia64.h"
#include <arch/options.h>
static const int probe_debug = 0;
@@ -80,6 +82,28 @@ void elf_ia64_usage(void)
" --initrd=FILE Use FILE as the kernel's initial ramdisk.\n");
}
+/* Move the crash kerenl physical offset to reserved region
+ */
+static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+{
+ int i;
+ long offset;
+ struct mem_phdr *phdr;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ offset = mem_min - phdr->p_paddr;
+ break;
+ }
+ }
+ ehdr->e_entry += offset;
+ for(i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type == PT_LOAD)
+ phdr->p_paddr += offset;
+ }
+}
+
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info)
{
@@ -89,9 +113,11 @@ int elf_ia64_load(int argc, char **argv,
off_t ramdisk_size = 0;
unsigned long command_line_len;
unsigned long entry, max_addr, gp_value;
- unsigned command_line_base, ramdisk_base;
+ unsigned long command_line_base, ramdisk_base;
+ unsigned long efi_memmap_base, efi_memmap_size;
int result;
int opt;
+ char *efi_memmap_buf;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
static const struct option options[] = {
@@ -135,6 +161,15 @@ int elf_ia64_load(int argc, char **argv,
free_elf_info(&ehdr);
return result;
}
+
+ if (info->kexec_flags & KEXEC_ON_CRASH ) {
+ if ((mem_min == 0x00) && (mem_max = ULONG_MAX)) {
+ fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n");
+ return -1;
+ }
+ move_loaded_segments(info, &ehdr);
+ }
+
entry = ehdr.e_entry;
max_addr = elf_max_addr(&ehdr);
@@ -149,17 +184,48 @@ int elf_ia64_load(int argc, char **argv,
/* Load the setup code */
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- 0x80000, ULONG_MAX, 1);
+ 0x0, ULONG_MAX, -1);
- if (command_line_len) {
+
+ if (load_crashdump_segments(info, &ehdr, max_addr, 0,
+ &command_line) < 0)
+ return -1;
+
+ // reserve 8k for efi_memmap
+ efi_memmap_size = 1UL<<14;
+ efi_memmap_buf = xmalloc(efi_memmap_size);
+ efi_memmap_base = add_buffer(info, efi_memmap_buf,
+ efi_memmap_size, efi_memmap_size, 4096, 0,
+ max_addr, -1);
+
+ elf_rel_set_symbol(&info->rhdr, "__efi_memmap_base",
+ &efi_memmap_base, sizeof(long));
+
+ elf_rel_set_symbol(&info->rhdr, "__efi_memmap_size",
+ &efi_memmap_size, sizeof(long));
+ if (command_line) {
+ command_line_len = strlen(command_line) + 1;
+ }
+ if (command_line_len || (info->kexec_flags & KEXEC_ON_CRASH )) {
char *cmdline = xmalloc(command_line_len);
strcpy(cmdline, command_line);
+
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ char buf[128];
+ sprintf(buf," max_addr=%lluM min_addr=%lluM",
+ mem_max>>20, mem_min>>20);
+ command_line_len = strlen(cmdline) + strlen(buf) + 1;
+ cmdline = xrealloc(cmdline, command_line_len);
+ strcat(cmdline, buf);
+ }
+
command_line_len = (command_line_len + 15)&(~15);
+ command_line_base = add_buffer(info, cmdline,
+ command_line_len, command_line_len,
+ getpagesize(), 0UL,
+ max_addr, -1);
elf_rel_set_symbol(&info->rhdr, "__command_line_len",
&command_line_len, sizeof(long));
- command_line_base = add_buffer(info, cmdline,
- command_line_len, command_line_len,
- 16, 0, max_addr, 1);
elf_rel_set_symbol(&info->rhdr, "__command_line",
&command_line_base, sizeof(long));
}
@@ -168,7 +234,7 @@ int elf_ia64_load(int argc, char **argv,
ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
ramdisk_size,
- getpagesize(), 0, max_addr, 1);
+ getpagesize(), 0, max_addr, -1);
elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
&ramdisk_base, sizeof(long));
elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
diff -puN kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-rel-ia64.c
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-rel-ia64.c 2006-07-13 14:42:05.000000000 +0530
@@ -1,3 +1,26 @@
+/*
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* pugatory relocation code
+ * Most of the code in this file is
+ * based on arch/ia64/kernel/module.c in Linux kernel
+ */
+
+
/* Most of the code in this file is
* based on arch/ia64/kernel/module.c in Linux kernel
*/
@@ -43,6 +66,15 @@ ia64_patch (uint64_t insn_addr, uint64_t
b[1] = (b1 & ~m1) | (v1 & m1);
}
+static void
+put_unaligned64(unsigned long val, unsigned char *location)
+{
+ unsigned char *src = (unsigned char *)&val;
+ int i;
+ for (i = 0; i < sizeof(long); i++)
+ *location++ = *src++;
+}
+
static inline uint64_t
bundle (const uint64_t insn)
{
@@ -102,6 +134,11 @@ void machine_apply_elf_rel(struct mem_eh
| ((value & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
}
break;
+ case R_IA64_PCREL64LSB: {
+ value = value - address;
+ put_unaligned64(value, location);
+ } break;
+ case R_IA64_GPREL22:
case R_IA64_LTOFF22X:
if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
die("value out of gp relative range");
diff -puN kexec/arch/ia64/kexec-ia64.h~kdump-ia64 kexec/arch/ia64/kexec-ia64.h
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-ia64.h 2006-07-13 14:42:05.000000000 +0530
@@ -7,5 +7,7 @@ int elf_ia64_probe(const char *buf, off_
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
void elf_ia64_usage(void);
-
+#define MAX_MEMORY_RANGES 1024
+#define EFI_PAGE_SIZE (1UL<<12)
+#define ELF_PAGE_SIZE (1UL<<16)
#endif /* KEXEC_IA64_H */
diff -puN kexec/arch/ia64/Makefile~kdump-ia64 kexec/arch/ia64/Makefile
--- kexec-tools-1.101-kdump/kexec/arch/ia64/Makefile~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/Makefile 2006-07-13 14:42:05.000000000 +0530
@@ -4,3 +4,5 @@
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-ia64.c
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-ia64.c
KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-rel-ia64.c
+KEXEC_C_SRCS+= kexec/arch/ia64/crashdump-ia64.c
+
diff -puN kexec/kexec.c~kdump-ia64 kexec/kexec.c
--- kexec-tools-1.101-kdump/kexec/kexec.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec.c 2006-07-13 14:42:05.000000000 +0530
@@ -96,6 +96,9 @@ int valid_memory_range(unsigned long sst
continue;
mstart = memory_range[i].start;
mend = memory_range[i].end;
+ if (i < memory_ranges - 1 && mend == memory_range[i+1].start)
+ mend = memory_range[i+1].end;
+
/* Check to see if we are fully contained */
if ((mstart <= sstart) && (mend >= send)) {
return 1;
diff -puN kexec/kexec-sha256.h~kdump-ia64 kexec/kexec-sha256.h
--- kexec-tools-1.101-kdump/kexec/kexec-sha256.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec-sha256.h 2006-07-13 14:42:05.000000000 +0530
@@ -6,6 +6,6 @@ struct sha256_region {
unsigned long len;
};
-#define SHA256_REGIONS 8
+#define SHA256_REGIONS 16
#endif /* KEXEC_SHA256_H */
diff -puN purgatory/arch/ia64/console-ia64.c~kdump-ia64 purgatory/arch/ia64/console-ia64.c
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/console-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/console-ia64.c 2006-07-13 14:42:05.000000000 +0530
@@ -1,5 +1,47 @@
#include <purgatory.h>
+#include "io.h"
+
+#define VGABASE UNCACHED(0xb8000)
+
+/* code based on i386 console code
+ * TODO add serial support
+ */
+#define MAX_YPOS 25
+#define MAX_XPOS 80
+
+unsigned long current_ypos = 1, current_xpos = 0;
+
+static void putchar_vga(int ch)
+{
+ int i, k, j;
+
+ if (current_ypos >= MAX_YPOS) {
+ /* scroll 1 line up */
+ for (k = 1, j = 0; k < MAX_YPOS; k++, j++) {
+ for (i = 0; i < MAX_XPOS; i++) {
+ writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
+ VGABASE + 2*(MAX_XPOS*j + i));
+ }
+ }
+ for (i = 0; i < MAX_XPOS; i++)
+ writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
+ current_ypos = MAX_YPOS-1;
+ }
+ if (ch == '\n') {
+ current_xpos = 0;
+ current_ypos++;
+ } else if (ch != '\r') {
+ writew(((0x7 << 8) | (unsigned short) ch),
+ VGABASE + 2*(MAX_XPOS*current_ypos +
+ current_xpos++));
+ if (current_xpos >= MAX_XPOS) {
+ current_xpos = 0;
+ current_ypos++;
+ }
+ }
+}
+
void putchar(int ch)
{
- /* Nothing for now */
+ putchar_vga(ch);
}
diff -puN purgatory/arch/ia64/entry.S~kdump-ia64 purgatory/arch/ia64/entry.S
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/entry.S~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/entry.S 2006-07-13 14:42:05.000000000 +0530
@@ -1,7 +1,7 @@
/*
* purgatory: setup code
*
- * Copyright (C) 2005 Zou Nan hai (nanhai.zou at intel.com)
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou at intel.com)
*
* 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
@@ -16,6 +16,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define DECLARE_DATA8(name) \
+.global name; \
+.size name, 8; \
+name: data8 0x0
.global __dummy_efi_function
.align 32
@@ -35,18 +39,10 @@ purgatory_start:
ld8 gp=[r2];;
br.call.sptk.many b0=purgatory
;;
- alloc r2 = ar.pfs, 0, 0, 5, 0
+ alloc r2 = ar.pfs, 0, 0, 2, 0
;;
mov out0=r28
-
- movl r2=__command_line;;
- ld8 out1=[r2];;
- movl r2=__command_line_len;;
- ld8 out2=[r2];;
- movl r2=__ramdisk_base;;
- ld8 out3=[r2];;
- movl r2=__ramdisk_size;;
- ld8 out4=[r2];;
+ movl out1=__ramdisk_base;;
br.call.sptk.many b0=ia64_env_setup
movl r10=__kernel_entry;;
ld8 r14=[r10];;
@@ -58,28 +54,14 @@ purgatory_start:
br.call.sptk.many b0=b6
.endp purgatory_start
-.align 32
-.global __kernel_entry
-.size __kernel_entry, 8
-__kernel_entry:
- data8 0x0
-.global __command_line
-.size __command_line, 8
-__command_line:
- data8 0x0
-.global __command_line_len
-.size __command_line_len, 8
-__command_line_len:
- data8 0x0
-.global __ramdisk_base
-.size __ramdisk_base, 8
-__ramdisk_base:
- data8 0x0
-.global __ramdisk_size
-.size __ramdisk_size, 8
-__ramdisk_size:
- data8 0x0
-.global __gp_value
-.size __gp_value, 8
-__gp_value:
- data8 0x0
+DECLARE_DATA8(__kernel_entry)
+DECLARE_DATA8(__ramdisk_base)
+DECLARE_DATA8(__ramdisk_size)
+DECLARE_DATA8(__command_line)
+DECLARE_DATA8(__command_line_len)
+DECLARE_DATA8(__efi_memmap_base)
+DECLARE_DATA8(__efi_memmap_size)
+DECLARE_DATA8(__loaded_segments)
+DECLARE_DATA8(__loaded_segments_num)
+
+DECLARE_DATA8(__gp_value)
diff -puN /dev/null purgatory/arch/ia64/io.h
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/io.h 2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,94 @@
+#ifndef IO_H
+#define IO_H
+#define UNCACHED(x) (void *)((x)|(1UL<<63))
+#define MF() asm volatile ("mf.a" ::: "memory")
+#define IO_SPACE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff))
+
+static inline void *io_addr (unsigned long port)
+{
+ unsigned long offset;
+ unsigned long io_base;
+ asm volatile ("mov %0=ar.k0":"=r"(io_base));
+ offset = IO_SPACE_ENCODING(port);
+ return UNCACHED(io_base | offset);
+}
+
+static inline unsigned int inb (unsigned long port)
+{
+ volatile unsigned char *addr = io_addr(port);
+ unsigned char ret;
+ ret = *addr;
+ MF();
+ return ret;
+}
+
+static inline unsigned int inw (unsigned long port)
+{
+ volatile unsigned short *addr = io_addr(port);
+ unsigned short ret;
+
+ ret = *addr;
+ MF();
+ return ret;
+}
+
+static inline unsigned int ia64_inl (unsigned long port)
+{
+ volatile unsigned int *addr = __ia64_mk_io_addr(port);
+ unsigned int ret;
+ ret = *addr;
+ MF();
+ return ret;
+}
+
+static inline void outb (unsigned char val, unsigned long port)
+{
+ volatile unsigned char *addr = io_addr(port);
+
+ *addr = val;
+ MF();
+}
+
+static inline void outw (unsigned short val, unsigned long port)
+{
+ volatile unsigned short *addr = io_addr(port);
+
+ *addr = val;
+ MF();
+}
+
+static inline void outl (unsigned int val, unsigned long port)
+{
+ volatile unsigned int *addr = io_addr(port);
+
+ *addr = val;
+ MF();
+}
+
+
+static inline unsigned char readb(const volatile void *addr)
+{
+ return *(volatile unsigned char *) addr;
+}
+static inline unsigned short readw(const volatile void *addr)
+{
+ return *(volatile unsigned short *) addr;
+}
+static inline unsigned int readl(const volatile void *addr)
+{
+ return *(volatile unsigned int *) addr;
+}
+
+static inline void writeb(unsigned char b, volatile void *addr)
+{
+ *(volatile unsigned char *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void *addr)
+{
+ *(volatile unsigned short *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void *addr)
+{
+ *(volatile unsigned int *) addr = b;
+}
+#endif
diff -puN purgatory/arch/ia64/Makefile~kdump-ia64 purgatory/arch/ia64/Makefile
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/Makefile~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/Makefile 2006-07-13 14:42:05.000000000 +0530
@@ -5,5 +5,5 @@ PCFLAGS += -ffixed-r28
PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
-PURGATORY_C_SRCS+=
+PURGATORY_C_SRCS+= purgatory/arch/ia64/vga.c
diff -puN purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.c
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.c 2006-07-13 14:42:05.000000000 +0530
@@ -1,9 +1,47 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include <purgatory.h>
#include <stdint.h>
#include <string.h>
#include "purgatory-ia64.h"
-#define PAGE_OFFSET 0xe000000000000000
+#define PAGE_OFFSET 0xe000000000000000UL
+
+#define EFI_PAGE_SHIFT 12
+#define EFI_PAGE_SIZE (1UL<<EFI_PAGE_SHIFT)
+#define EFI_PAGE_ALIGN(x) ((x + EFI_PAGE_SIZE - 1)&~(EFI_PAGE_SIZE-1))
+/* Memory types: */
+#define EFI_RESERVED_TYPE 0
+#define EFI_LOADER_CODE 1
+#define EFI_LOADER_DATA 2
+#define EFI_BOOT_SERVICES_CODE 3
+#define EFI_BOOT_SERVICES_DATA 4
+#define EFI_RUNTIME_SERVICES_CODE 5
+#define EFI_RUNTIME_SERVICES_DATA 6
+#define EFI_CONVENTIONAL_MEMORY 7
+#define EFI_UNUSABLE_MEMORY 8
+#define EFI_ACPI_RECLAIM_MEMORY 9
+#define EFI_ACPI_MEMORY_NVS 10
+#define EFI_MEMORY_MAPPED_IO 11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE 13
+#define EFI_MAX_MEMORY_TYPE 14
typedef struct {
uint64_t signature;
@@ -63,53 +101,171 @@ struct ia64_boot_param {
uint64_t initrd_size;
};
-void setup_arch(void)
+typedef struct {
+ uint32_t type;
+ uint32_t pad;
+ uint64_t phys_addr;
+ uint64_t virt_addr;
+ uint64_t num_pages;
+ uint64_t attribute;
+} efi_memory_desc_t;
+
+struct loaded_segment {
+ unsigned long start;
+ unsigned long end;
+ unsigned long reserved;
+};
+
+struct kexec_boot_params {
+ uint64_t ramdisk_base;
+ uint64_t ramdisk_size;
+ uint64_t command_line;
+ uint64_t command_line_len;
+ uint64_t efi_memmap_base;
+ uint64_t efi_memmap_size;
+ struct loaded_segment *loaded_segments;
+ unsigned long loaded_segments_num;
+};
+
+void
+setup_arch(void)
{
- /* Nothing for now */
+ reset_vga();
}
+
inline unsigned long PA(unsigned long addr)
{
return addr - PAGE_OFFSET;
}
-void flush_icache_range(char *start, unsigned long len)
+void
+patch_efi_memmap(struct kexec_boot_params *params,
+ struct ia64_boot_param *boot_param)
+{
+ void *dest = (void *)params->efi_memmap_base;
+ void *src = (void *)boot_param->efi_memmap;
+ unsigned long len = boot_param->efi_memmap_size;
+ unsigned long memdesc_size = boot_param->efi_memdesc_size;
+ uint64_t orig_type;
+ efi_memory_desc_t *md1, *md2;
+ void *p1, *p2, *src_end = src + len;
+ int i;
+ for (p1 = src, p2 = dest; p1 < src_end;
+ p1 += memdesc_size, p2 += memdesc_size) {
+ unsigned long mstart, mend;
+ md1 = p1;
+ md2 = p2;
+ if (md1->num_pages == 0)
+ continue;
+ mstart = md1->phys_addr;
+ mend = md1->phys_addr + (md1->num_pages
+ << EFI_PAGE_SHIFT);
+ switch (md1->type) {
+ case EFI_LOADER_DATA:
+ *md2 = *md1;
+ md2->type = EFI_CONVENTIONAL_MEMORY;
+ break;
+ default:
+ *md2 = *md1;
+ }
+ // segments are already sorted and aligned to 4K
+ orig_type = md2->type;
+ for (i = 0; i < params->loaded_segments_num; i++) {
+ struct loaded_segment *seg;
+ seg = ¶ms->loaded_segments[i];
+ if (seg->start >= mstart && seg->start < mend) {
+ unsigned long start_pages, mid_pages, end_pages;
+ if (seg->end > mend) {
+ p1 += memdesc_size;
+ for(; p1 < src_end;
+ p1 += memdesc_size) {
+ md1 = p1;
+ /* TODO check contig and attribute here */
+ mend = md1->phys_addr
+ + (md1->num_pages << EFI_PAGE_SHIFT);
+ if (seg->end < mend)
+ break;
+ }
+ }
+ start_pages = (seg->start - mstart)
+ >> EFI_PAGE_SHIFT;
+ mid_pages = (seg->end - seg->start)
+ >> EFI_PAGE_SHIFT;
+ end_pages = (mend - seg->end)
+ >> EFI_PAGE_SHIFT;
+ if (start_pages) {
+ md2->num_pages = start_pages;
+ p2 += memdesc_size;
+ md2 = p2;
+ *md2 = *md1;
+ }
+ md2->phys_addr = seg->start;
+ md2->num_pages = mid_pages;
+ md2->type = seg->reserved ?
+ EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA;
+ if (end_pages) {
+ p2 += memdesc_size;
+ md2 = p2;
+ *md2 = *md1;
+ md2->phys_addr = seg->end;
+ md2->num_pages = end_pages;
+ md2->type = orig_type;
+ mstart = seg->end;
+ } else
+ break;
+ }
+ }
+ }
+
+ boot_param->efi_memmap_size = p2 - dest;
+}
+
+void
+flush_icache_range(char *start, unsigned long len)
{
unsigned long i;
for (i = 0;i < len; i += 32)
- asm volatile("fc.i %0"::"r"(start+i):"memory");
+ asm volatile("fc.i %0"::"r"(start + i):"memory");
asm volatile (";;sync.i;;":::"memory");
asm volatile ("srlz.i":::"memory");
}
extern char __dummy_efi_function[], __dummy_efi_function_end[];
-void ia64_env_setup(struct ia64_boot_param *boot_param,
- uint64_t command_line, uint64_t command_line_len,
- uint64_t ramdisk_base, uint64_t ramdisk_size)
+
+void
+ia64_env_setup(struct ia64_boot_param *boot_param,
+ struct kexec_boot_params *params)
{
unsigned long len;
efi_system_table_t *systab;
efi_runtime_services_t *runtime;
unsigned long *set_virtual_address_map;
+ char *command_line = (char *)params->command_line;
+ uint64_t command_line_len = params->command_line_len;
// patch efi_runtime->set_virtual_address_map to a
// dummy function
len = __dummy_efi_function_end - __dummy_efi_function;
- memcpy((char *)command_line + command_line_len, __dummy_efi_function,
- len);
+ memcpy(command_line + command_line_len,
+ __dummy_efi_function, len);
systab = (efi_system_table_t *)boot_param->efi_systab;
runtime = (efi_runtime_services_t *)PA(systab->runtime);
set_virtual_address_map =
(unsigned long *)PA(runtime->set_virtual_address_map);
- *(set_virtual_address_map)=
- (unsigned long)((char *)command_line + command_line_len);
- flush_icache_range((char *)command_line+command_line_len, len);
+ *(set_virtual_address_map) =
+ (unsigned long)(command_line + command_line_len);
+ flush_icache_range(command_line + command_line_len, len);
+
+ patch_efi_memmap(params, boot_param);
+
+ boot_param->efi_memmap = params->efi_memmap_base;
- boot_param->command_line = command_line;
+ boot_param->command_line = params->command_line;
boot_param->console_info.orig_x = 0;
boot_param->console_info.orig_y = 0;
- boot_param->initrd_start = ramdisk_base;
- boot_param->initrd_size = ramdisk_size;
+ boot_param->initrd_start = params->ramdisk_base;
+ boot_param->initrd_size = params->ramdisk_size;
}
/* This function can be used to execute after the SHA256 verification. */
diff -puN purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.h
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64 2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.h 2006-07-13 14:42:05.000000000 +0530
@@ -1,6 +1,5 @@
#ifndef PURGATORY_IA64_H
#define PURGATORY_IA64_H
-/* nothing yet */
-
+void reset_vga(void);
#endif /* PURGATORY_IA64_H */
diff -puN /dev/null purgatory/arch/ia64/vga.c
--- /dev/null 2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/vga.c 2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,143 @@
+#include "io.h"
+void reset_vga(void)
+{
+ /* Hello */
+ inb(0x3da);
+ outb(0, 0x3c0);
+
+ /* Sequencer registers */
+ outw(0x0300, 0x3c4);
+ outw(0x0001, 0x3c4);
+ outw(0x0302, 0x3c4);
+ outw(0x0003, 0x3c4);
+ outw(0x0204, 0x3c4);
+
+ /* Ensure CRTC regs 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+ outw(0x0e11, 0x3d4);
+ /* CRTC registers */
+ outw(0x5f00, 0x3d4);
+ outw(0x4f01, 0x3d4);
+ outw(0x5002, 0x3d4);
+ outw(0x8203, 0x3d4);
+ outw(0x5504, 0x3d4);
+ outw(0x8105, 0x3d4);
+ outw(0xbf06, 0x3d4);
+ outw(0x1f07, 0x3d4);
+ outw(0x0008, 0x3d4);
+ outw(0x4f09, 0x3d4);
+ outw(0x200a, 0x3d4);
+ outw(0x0e0b, 0x3d4);
+ outw(0x000c, 0x3d4);
+ outw(0x000d, 0x3d4);
+ outw(0x010e, 0x3d4);
+ outw(0xe00f, 0x3d4);
+ outw(0x9c10, 0x3d4);
+ outw(0x8e11, 0x3d4);
+ outw(0x8f12, 0x3d4);
+ outw(0x2813, 0x3d4);
+ outw(0x1f14, 0x3d4);
+ outw(0x9615, 0x3d4);
+ outw(0xb916, 0x3d4);
+ outw(0xa317, 0x3d4);
+ outw(0xff18, 0x3d4);
+
+ /* Graphic registers */
+ outw(0x0000, 0x3ce);
+ outw(0x0001, 0x3ce);
+ outw(0x0002, 0x3ce);
+ outw(0x0003, 0x3ce);
+ outw(0x0004, 0x3ce);
+ outw(0x1005, 0x3ce);
+ outw(0x0e06, 0x3ce);
+ outw(0x0007, 0x3ce);
+ outw(0xff08, 0x3ce);
+
+ /* Attribute registers */
+ inb(0x3da);
+ outb(0x00, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ inb(0x3da);
+ outb(0x01, 0x3c0);
+ outb(0x01, 0x3c0);
+
+ inb(0x3da);
+ outb(0x02, 0x3c0);
+ outb(0x02, 0x3c0);
+
+ inb(0x3da);
+ outb(0x03, 0x3c0);
+ outb(0x03, 0x3c0);
+
+ inb(0x3da);
+ outb(0x04, 0x3c0);
+ outb(0x04, 0x3c0);
+
+ inb(0x3da);
+ outb(0x05, 0x3c0);
+ outb(0x05, 0x3c0);
+
+ inb(0x3da);
+ outb(0x06, 0x3c0);
+ outb(0x14, 0x3c0);
+
+ inb(0x3da);
+ outb(0x07, 0x3c0);
+ outb(0x07, 0x3c0);
+
+ inb(0x3da);
+ outb(0x08, 0x3c0);
+ outb(0x38, 0x3c0);
+
+ inb(0x3da);
+ outb(0x09, 0x3c0);
+ outb(0x39, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0a, 0x3c0);
+ outb(0x3a, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0b, 0x3c0);
+ outb(0x3b, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0c, 0x3c0);
+ outb(0x3c, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0d, 0x3c0);
+ outb(0x3d, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0e, 0x3c0);
+ outb(0x3e, 0x3c0);
+
+ inb(0x3da);
+ outb(0x0f, 0x3c0);
+ outb(0x3f, 0x3c0);
+
+ inb(0x3da);
+ outb(0x10, 0x3c0);
+ outb(0x0c, 0x3c0);
+
+ inb(0x3da);
+ outb(0x11, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ inb(0x3da);
+ outb(0x12, 0x3c0);
+ outb(0x0f, 0x3c0);
+
+ inb(0x3da);
+ outb(0x13, 0x3c0);
+ outb(0x08, 0x3c0);
+
+ inb(0x3da);
+ outb(0x14, 0x3c0);
+ outb(0x00, 0x3c0);
+
+ /* Goodbye */
+ inb(0x3da);
+ outb(0x20, 0x3c0);
+}
_
kexec-tools-1.101-ia64-load-offset.patch:
crashdump-ia64.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
--- NEW FILE kexec-tools-1.101-ia64-load-offset.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c.orig 2006-12-01 14:16:07.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c 2006-12-01 14:18:34.000000000 -0500
@@ -28,7 +28,7 @@
#include "crashdump-ia64.h"
int memory_ranges = 0;
-#define LOAD_OFFSET (0xa000000000000000UL + 0x100000000UL - (1UL<<26))
+#define LOAD_OFFSET (0xa000000000000000UL + 0x100000000UL - kernel_code_start)
#define MAX_LINE 160
/* Stores a sorted list of RAM memory ranges for which to create elf headers.
* A separate program header is created for backup region */
kexec-tools-1.101-ia64-noio-eat.patch:
kexec-elf-ia64.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
--- NEW FILE kexec-tools-1.101-ia64-noio-eat.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2006-12-01 14:30:59.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-12-01 14:31:04.000000000 -0500
@@ -128,7 +128,7 @@
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
{"initrd", 1, 0, OPT_RAMDISK},
- {"noio", 1, 0, OPT_NOIO},
+ {"noio", 0, 0, OPT_NOIO},
{0, 0, 0, 0},
};
kexec-tools-1.101-ia64-noio.patch:
kexec/arch/ia64/kexec-elf-ia64.c | 10 +++++
purgatory/arch/ia64/entry.S | 1
purgatory/arch/ia64/include/arch/io.h | 25 -------------
purgatory/arch/ia64/io.h | 64 ++++++++++++++++++++--------------
4 files changed, 50 insertions(+), 50 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-noio.patch ---
On Thu, Sep 21, 2006 at 01:06:08PM +0800, Zou Nan hai wrote:
> SN platform support PIO in a different way to generic IA64 platform. It
> does not support most of the legacy I/O ports.
>
> Give an --noio option to kexec-tools to disable I/O in purgatory code.
>
> This patch also removed an unused io.h in kexec-tools.
>
> Signed-off-by: Zou Nan hai <nanhai.zou at intel.com>
I have merged the following into kexec-tools-test.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
From: Zou Nan hai <nanhai.zou at intel.com>
Date: 21 Sep 2006 13:06:08 +0800
Subject: kexec-tools: --noio option to disable I/O in purgatory code.
SN platform support PIO in a different way to generic IA64 platform. It
does not support most of the legacy I/O ports.
Give an --noio option to kexec-tools to disable I/O in purgatory code.
This patch also removed an unused io.h in kexec-tools.
Signed-off-by: Zou Nan hai <nanhai.zou at intel.com>
Edited to consistently use tabs instead of spaces for intentation,
remove one instance of trailing whitespace, and fix indentation
of noio line in options[].
Signed-off-by: Simon Horman <horms at verge.net.au>
diff -Nraup kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c
kexec-tools-1.101-fix/kexec/arch/ia64/kexec-elf-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-09-20 15:30:40.000000000 +0800
+++ kexec-tools-1.101-fix/kexec/arch/ia64/kexec-elf-ia64.c 2006-09-21 15:12:20.000000000 +0800
@@ -116,16 +116,19 @@ int elf_ia64_load(int argc, char **argv,
unsigned long command_line_base, ramdisk_base;
unsigned long efi_memmap_base, efi_memmap_size;
unsigned long boot_param_base;
+ unsigned long noio=0;
int result;
int opt;
char *efi_memmap_buf, *boot_param;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_NOIO (OPT_ARCH_MAX+2)
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
{"initrd", 1, 0, OPT_RAMDISK},
+ {"noio", 1, 0, OPT_NOIO},
{0, 0, 0, 0},
};
@@ -148,6 +151,9 @@ int elf_ia64_load(int argc, char **argv,
case OPT_RAMDISK:
ramdisk = optarg;
break;
+ case OPT_NOIO: /* disable PIO and MMIO in purgatory code*/
+ noio = 1;
+ break;
}
}
command_line_len = 0;
@@ -196,6 +202,10 @@ int elf_ia64_load(int argc, char **argv,
boot_param = xmalloc(4096);
boot_param_base = add_buffer(info, boot_param, 4096, 4096, 4096, 0,
max_addr, -1);
+
+ elf_rel_set_symbol(&info->rhdr, "__noio",
+ &noio, sizeof(long));
+
elf_rel_set_symbol(&info->rhdr, "__boot_param_base",
&boot_param_base, sizeof(long));
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/entry.S
kexec-tools-1.101-fix/purgatory/arch/ia64/entry.S
--- kexec-tools-1.101/purgatory/arch/ia64/entry.S 2006-09-20 15:30:40.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/entry.S 2006-09-21 15:11:36.000000000 +0800
@@ -68,3 +68,4 @@ DECLARE_DATA8(__loaded_segments)
DECLARE_DATA8(__loaded_segments_num)
DECLARE_DATA8(__gp_value)
+DECLARE_DATA8(__noio)
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h
kexec-tools-1.101-fix/purgatory/arch/ia64/include/arch/io.h
--- kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h 2006-09-20 15:29:29.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/include/arch/io.h 1970-01-01 08:00:00.000000000 +0800
@@ -1,25 +0,0 @@
-#ifndef ARCH_IO_H
-#define ARCH_IO_H
-
-#include <stdint.h>
-/* Helper functions for directly doing I/O */
-
-extern inline uint8_t inb(void *port)
-{
- volatile unsigned char *addr = (unsigned char *)port;
- uint8_t result;
-
- result = *addr;
- asm volatile ("mf.a"::: "memory");
- return result;
-}
-
-extern inline void outb (uint8_t value, void *port)
-{
- volatile unsigned char *addr = (unsigned char *)port;
-
- *addr = value;
- asm volatile ("mf.a"::: "memory");
-}
-
-#endif /* ARCH_IO_H */
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/io.h
kexec-tools-1.101-fix/purgatory/arch/ia64/io.h
--- kexec-tools-1.101/purgatory/arch/ia64/io.h 2006-09-20 15:29:29.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/io.h 2006-09-21 15:11:19.000000000 +0800
@@ -3,7 +3,7 @@
#define UNCACHED(x) (void *)((x)|(1UL<<63))
#define MF() asm volatile ("mf.a" ::: "memory")
#define IO_SPACE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff))
-
+extern long __noio;
static inline void *io_addr (unsigned long port)
{
unsigned long offset;
@@ -16,28 +16,34 @@ static inline void *io_addr (unsigned lo
static inline unsigned int inb (unsigned long port)
{
volatile unsigned char *addr = io_addr(port);
- unsigned char ret;
- ret = *addr;
- MF();
+ unsigned char ret = 0;
+ if (!__noio) {
+ ret = *addr;
+ MF();
+ }
return ret;
}
static inline unsigned int inw (unsigned long port)
{
volatile unsigned short *addr = io_addr(port);
- unsigned short ret;
+ unsigned short ret = 0;
- ret = *addr;
- MF();
+ if (!__noio) {
+ ret = *addr;
+ MF();
+ }
return ret;
}
-static inline unsigned int ia64_inl (unsigned long port)
+static inline unsigned int inl (unsigned long port)
{
- volatile unsigned int *addr = __ia64_mk_io_addr(port);
- unsigned int ret;
- ret = *addr;
- MF();
+ volatile unsigned int *addr = io_addr(port);
+ unsigned int ret ;
+ if (!__noio) {
+ ret = *addr;
+ MF();
+ }
return ret;
}
@@ -45,50 +51,58 @@ static inline void outb (unsigned char v
{
volatile unsigned char *addr = io_addr(port);
- *addr = val;
- MF();
+ if (!__noio) {
+ *addr = val;
+ MF();
+ }
}
static inline void outw (unsigned short val, unsigned long port)
{
volatile unsigned short *addr = io_addr(port);
- *addr = val;
- MF();
+ if (!__noio) {
+ *addr = val;
+ MF();
+ }
}
static inline void outl (unsigned int val, unsigned long port)
{
volatile unsigned int *addr = io_addr(port);
- *addr = val;
- MF();
+ if (!__noio) {
+ *addr = val;
+ MF();
+ }
}
-
static inline unsigned char readb(const volatile void *addr)
{
- return *(volatile unsigned char *) addr;
+ return __noio ? 0 :*(volatile unsigned char *) addr;
}
static inline unsigned short readw(const volatile void *addr)
{
- return *(volatile unsigned short *) addr;
+ return __noio ? 0 :*(volatile unsigned short *) addr;
}
static inline unsigned int readl(const volatile void *addr)
{
- return *(volatile unsigned int *) addr;
+ return __noio ? 0 :*(volatile unsigned int *) addr;
}
static inline void writeb(unsigned char b, volatile void *addr)
{
- *(volatile unsigned char *) addr = b;
+ if (!__noio)
+ *(volatile unsigned char *) addr = b;
}
static inline void writew(unsigned short b, volatile void *addr)
{
- *(volatile unsigned short *) addr = b;
+ if (!__noio)
+ *(volatile unsigned short *) addr = b;
}
static inline void writel(unsigned int b, volatile void *addr)
{
- *(volatile unsigned int *) addr = b;
+ if (!__noio)
+ *(volatile unsigned int *) addr = b;
}
#endif
kexec-tools-1.101-ia64-phdr-malloc.patch:
crashdump-ia64.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-phdr-malloc.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c.orig 2006-11-14 13:38:45.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c 2006-11-14 14:52:34.000000000 -0500
@@ -316,10 +316,14 @@
int nr_ranges;
size_t size;
void *tmp;
+ long int nr_cpus;
+ if ((nr_cpus = sysconf(_SC_NPROCESSORS_CONF)) < 0)
+ return -1;
if (info->kexec_flags & KEXEC_ON_CRASH ) {
if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) {
- size = sizeof(Elf64_Ehdr) +
- (nr_ranges + 1) * sizeof(Elf64_Phdr);
+ size = (sizeof(Elf64_Ehdr) +
+ ((nr_cpus +1) * sizeof(Elf64_Phdr)) +
+ ((nr_ranges + 1) * sizeof(Elf64_Phdr)));
size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1);
tmp = xmalloc(size);
memset(tmp, 0, size);
kexec-tools-1.101-ia64-tools.patch:
Makefile | 1
kdump/kdump.8 | 39 ++++++++++++
kexec/Makefile | 4 +
kexec/arch/ia64/kexec-elf-ia64.c | 60 ++++++++++++++++---
kexec/arch/ia64/kexec-elf-rel-ia64.c | 96 ++++++++++++++++++++++++++++--
kexec/arch/ia64/kexec-ia64.c | 107 ++++++++++++++++++++++++----------
kexec/arch/ia64/kexec-ia64.h | 2
kexec/kexec.8 | 46 ++++++++++++--
purgatory/arch/ia64/Makefile | 4 -
purgatory/arch/ia64/entry.S | 85 +++++++++++++++++++++++++++
purgatory/arch/ia64/include/arch/io.h | 25 +++++++
purgatory/arch/ia64/purgatory-ia64.c | 106 +++++++++++++++++++++++++++++++++
12 files changed, 521 insertions(+), 54 deletions(-)
--- NEW FILE kexec-tools-1.101-ia64-tools.patch ---
--- kexec-tools-1.101/Makefile.orig 2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/Makefile 2006-10-20 13:39:08.000000000 -0400
@@ -43,6 +43,7 @@
PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
MAN_PAGES:= kexec/kexec.8
+MAN_PAGES+= kdump/kdump.8
BINARIES_i386:= $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump
BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
BINARIES:=$(SBINDIR)/kexec $(BINARIES_$(ARCH))
--- /dev/null 2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/kdump/kdump.8 2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,39 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH KDUMP 8 "Jul 27, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+kdump \- This is just a placeholder until real man page has been written
+.SH SYNOPSIS
+.B kdump
+.RI [ options ] " start_address" ...
+.SH DESCRIPTION
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBkdump\fP does not have a man page yet.
+.SH OPTIONS
+.\"These programs follow the usual GNU command line syntax, with long
+.\"options starting with two dashes (`-').
+.\"A summary of options is included below.
+.\"For a complete description, see the Info files.
+.SH SEE ALSO
+.SH AUTHOR
+kdump was written by Eric Biederman.
+.PP
+This manual page was written by Khalid Aziz <khalid.aziz at hp.com>,
+for the Debian project (but may be used by others).
--- kexec-tools-1.101/purgatory/arch/ia64/Makefile.orig 2004-12-20 17:44:22.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/ia64/Makefile 2006-10-20 13:39:08.000000000 -0400
@@ -1,8 +1,8 @@
#
# Purgatory ia64
#
-
-PURGATORY_S_SRCS+=
+PCFLAGS += -ffixed-r28
+PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
PURGATORY_C_SRCS+=
--- /dev/null 2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h 2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,25 @@
+#ifndef ARCH_IO_H
+#define ARCH_IO_H
+
+#include <stdint.h>
+/* Helper functions for directly doing I/O */
+
+extern inline uint8_t inb(void *port)
+{
+ volatile unsigned char *addr = (unsigned char *)port;
+ uint8_t result;
+
+ result = *addr;
+ asm volatile ("mf.a"::: "memory");
+ return result;
+}
+
+extern inline void outb (uint8_t value, void *port)
+{
+ volatile unsigned char *addr = (unsigned char *)port;
+
+ *addr = value;
+ asm volatile ("mf.a"::: "memory");
+}
+
+#endif /* ARCH_IO_H */
--- /dev/null 2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/entry.S 2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * purgatory: setup code
+ *
+ * Copyright (C) 2005 Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * 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 (version 2 of the License).
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+.global __dummy_efi_function
+.align 32
+.proc __dummy_efi_function
+__dummy_efi_function:
+ mov r8=r0;;
+ br.ret.sptk.many rp;;
+.global __dummy_efi_function_end
+__dummy_efi_function_end:
+.endp __dummy_efi_function
+
+.global purgatory_start
+.align 32
+.proc purgatory_start
+purgatory_start:
+ movl r2=__gp_value;;
+ ld8 gp=[r2];;
+ br.call.sptk.many b0=purgatory
+ ;;
+ alloc r2 = ar.pfs, 0, 0, 5, 0
+ ;;
+ mov out0=r28
+
+ movl r2=__command_line;;
+ ld8 out1=[r2];;
+ movl r2=__command_line_len;;
+ ld8 out2=[r2];;
+ movl r2=__ramdisk_base;;
+ ld8 out3=[r2];;
+ movl r2=__ramdisk_size;;
+ ld8 out4=[r2];;
+ br.call.sptk.many b0=ia64_env_setup
+ movl r10=__kernel_entry;;
+ ld8 r14=[r10];;
+ mov b6=r14;;
+ mov ar.lc=r0
+ mov ar.ec=r0
+ cover;;
+ invala;;
+ br.call.sptk.many b0=b6
+.endp purgatory_start
+
+.align 32
+.global __kernel_entry
+.size __kernel_entry, 8
+__kernel_entry:
+ data8 0x0
+.global __command_line
+.size __command_line, 8
+__command_line:
+ data8 0x0
+.global __command_line_len
+.size __command_line_len, 8
+__command_line_len:
+ data8 0x0
+.global __ramdisk_base
+.size __ramdisk_base, 8
+__ramdisk_base:
+ data8 0x0
+.global __ramdisk_size
+.size __ramdisk_size, 8
+__ramdisk_size:
+ data8 0x0
+.global __gp_value
+.size __gp_value, 8
+__gp_value:
+ data8 0x0
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig 2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c 2006-10-20 13:39:08.000000000 -0400
@@ -1,10 +1,116 @@
#include <purgatory.h>
+#include <stdint.h>
+#include <string.h>
#include "purgatory-ia64.h"
+#define PAGE_OFFSET 0xe000000000000000
+
+typedef struct {
+ uint64_t signature;
+ uint32_t revision;
+ uint32_t headersize;
+ uint32_t crc32;
+ uint32_t reserved;
+} efi_table_hdr_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ unsigned long get_time;
+ unsigned long set_time;
+ unsigned long get_wakeup_time;
+ unsigned long set_wakeup_time;
+ unsigned long set_virtual_address_map;
+ unsigned long convert_pointer;
+ unsigned long get_variable;
+ unsigned long get_next_variable;
+ unsigned long set_variable;
+ unsigned long get_next_high_mono_count;
+ unsigned long reset_system;
+} efi_runtime_services_t;
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string
+ */
+ uint32_t fw_revision;
+ unsigned long con_in_handle;
+ unsigned long con_in;
+ unsigned long con_out_handle;
+ unsigned long con_out;
+ unsigned long stderr_handle;
+ unsigned long stderr;
+ unsigned long runtime;
+ unsigned long boottime;
+ unsigned long nr_tables;
+ unsigned long tables;
+} efi_system_table_t;
+
+struct ia64_boot_param {
+ uint64_t command_line; /* physical address of command line arguments */
+ uint64_t efi_systab; /* physical address of EFI system table */
+ uint64_t efi_memmap; /* physical address of EFI memory map */
+ uint64_t efi_memmap_size; /* size of EFI memory map */
+ uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */
+ uint32_t efi_memdesc_version; /* memory descriptor version */
+ struct {
+ uint16_t num_cols; /* number of columns on console output device */
+ uint16_t num_rows; /* number of rows on console output device */
+ uint16_t orig_x; /* cursor's x position */
+ uint16_t orig_y; /* cursor's y position */
+ } console_info;
+ uint64_t fpswa; /* physical address of the fpswa interface */
+ uint64_t initrd_start;
+ uint64_t initrd_size;
+};
+
void setup_arch(void)
{
/* Nothing for now */
}
+inline unsigned long PA(unsigned long addr)
+{
+ return addr - PAGE_OFFSET;
+}
+
+void flush_icache_range(char *start, unsigned long len)
+{
+ unsigned long i;
+ for (i = 0;i < len; i += 32)
+ asm volatile("fc.i %0"::"r"(start+i):"memory");
+ asm volatile (";;sync.i;;":::"memory");
+ asm volatile ("srlz.i":::"memory");
+}
+
+extern char __dummy_efi_function[], __dummy_efi_function_end[];
+
+void ia64_env_setup(struct ia64_boot_param *boot_param,
+ uint64_t command_line, uint64_t command_line_len,
+ uint64_t ramdisk_base, uint64_t ramdisk_size)
+{
+ unsigned long len;
+ efi_system_table_t *systab;
+ efi_runtime_services_t *runtime;
+ unsigned long *set_virtual_address_map;
+
+ // patch efi_runtime->set_virtual_address_map to a
+ // dummy function
+ len = __dummy_efi_function_end - __dummy_efi_function;
+ memcpy((char *)command_line + command_line_len, __dummy_efi_function,
+ len);
+ systab = (efi_system_table_t *)boot_param->efi_systab;
+ runtime = (efi_runtime_services_t *)PA(systab->runtime);
+ set_virtual_address_map =
+ (unsigned long *)PA(runtime->set_virtual_address_map);
+ *(set_virtual_address_map)=
+ (unsigned long)((char *)command_line + command_line_len);
+ flush_icache_range((char *)command_line+command_line_len, len);
+
+ boot_param->command_line = command_line;
+ boot_param->console_info.orig_x = 0;
+ boot_param->console_info.orig_y = 0;
+ boot_param->initrd_start = ramdisk_base;
+ boot_param->initrd_size = ramdisk_size;
+}
/* This function can be used to execute after the SHA256 verification. */
void post_verification_setup_arch(void)
--- kexec-tools-1.101/kexec/Makefile.orig 2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/kexec/Makefile 2006-10-20 13:39:08.000000000 -0400
@@ -28,6 +28,7 @@
KEXEC_OBJS:= $(KEXEC_C_OBJS) $(KEXEC_S_OBJS)
KEXEC_DEPS:= $(KEXEC_C_DEPS) $(KEXEC_S_DEPS)
KEXEC:= $(SBINDIR)/kexec
+KEXEC_MANPAGE:= $(MANDIR)/man8/kexec.8
include $(KEXEC_DEPS)
@@ -51,6 +52,9 @@
mkdir -p $(@D)
$(CC) $(KCFLAGS) -o $@ $(KEXEC_OBJS) $(UTIL_LIB) $(LIBS)
+$(KEXEC_MANPAGE): kexec/kexec.8
+ $(MKDIR) -p $(MANDIR)/man8
+ cp kexec/kexec.8 $(KEXEC_MANPAGE)
echo::
@echo "KEXEC_C_SRCS $(KEXEC_C_SRCS)"
@echo "KEXEC_C_DEPS $(KEXEC_C_DEPS)"
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h.orig 2004-12-19 18:52:38.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h 2006-10-20 13:39:08.000000000 -0400
@@ -1,6 +1,8 @@
#ifndef KEXEC_IA64_H
#define KEXEC_IA64_H
+#define MAX_MEMORY_RANGES 1024
+
int elf_ia64_probe(const char *buf, off_t len);
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c.orig 2004-12-20 17:43:23.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c 2006-10-20 13:39:08.000000000 -0400
@@ -1,8 +1,14 @@
+/* Most of the code in this file is
+ * based on arch/ia64/kernel/module.c in Linux kernel
+ */
+
#include <stdio.h>
#include <elf.h>
#include "../../kexec.h"
#include "../../kexec-elf.h"
+#define MAX_LTOFF ((uint64_t) (1 << 22))
+
int machine_verify_elf_rel(struct mem_ehdr *ehdr)
{
if (ehdr->ei_data != ELFDATA2LSB) {
@@ -17,12 +23,40 @@
return 1;
}
+static void
+ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
+{
+ uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
+# define insn_mask ((1UL << 41) - 1)
+ unsigned long shift;
+
+ b0 = b[0]; b1 = b[1];
+ shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+ if (shift >= 64) {
+ m1 = mask << (shift - 64);
+ v1 = val << (shift - 64);
+ } else {
+ m0 = mask << shift; m1 = mask >> (64 - shift);
+ v0 = val << shift; v1 = val >> (64 - shift);
+ b[0] = (b0 & ~m0) | (v0 & m0);
+ }
+ b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static inline uint64_t
+bundle (const uint64_t insn)
+{
+ return insn & ~0xfUL;
+}
+
void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
void *location, unsigned long address, unsigned long value)
{
+ uint64_t gp_value = ehdr->rel_addr + 0x200000;
switch(r_type) {
case R_IA64_NONE:
break;
+ case R_IA64_SEGREL64LSB:
case R_IA64_DIR64LSB:
*((uint64_t *)location) = value;
break;
@@ -31,15 +65,67 @@
if (value != *((uint32_t *)location))
goto overflow;
break;
- case R_IA64_PCREL21B:
+ case R_IA64_IMM64:
+ ia64_patch((uint64_t)location, 0x01fffefe000UL,
+ /* bit 63 -> 36 */
+ (((value & 0x8000000000000000UL) >> 27)
+ /* bit 21 -> 21 */
+ | ((value & 0x0000000000200000UL) << 0)
+ /* bit 16 -> 22 */
+ | ((value & 0x00000000001f0000UL) << 6)
+ /* bit 7 -> 27 */
+ | ((value & 0x000000000000ff80UL) << 20)
+ /* bit 0 -> 13 */
+ | ((value & 0x000000000000007fUL) << 13)));
+ ia64_patch((uint64_t)location - 1, 0x1ffffffffffUL, value>>22);
+ break;
+ case R_IA64_IMM22:
+ if (value + (1 << 21) >= (1 << 22))
+ die("value out of IMM22 range\n");
+ ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+ /* bit 21 -> 36 */
+ (((value & 0x200000UL) << 15)
+ /* bit 16 -> 22 */
+ | ((value & 0x1f0000UL) << 6)
+ /* bit 7 -> 27 */
+ | ((value & 0x00ff80UL) << 20)
+ /* bit 0 -> 13 */
+ | ((value & 0x00007fUL) << 13) ));
+ break;
+ case R_IA64_PCREL21B: {
+ uint64_t delta = ((int64_t)value - (int64_t)address)/16;
+ if (delta + (1 << 20) >= (1 << 21))
+ die("value out of IMM21B range\n");
+ value = ((int64_t)(value - bundle(address)))/16;
+ ia64_patch((uint64_t)location, 0x11ffffe000UL,
+ (((value & 0x100000UL) << 16) /* bit 20 -> 36 */
+ | ((value & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
+ }
+ break;
+ case R_IA64_LTOFF22X:
+ if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+ die("value out of gp relative range");
+ value -= gp_value;
+ ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+ (((value & 0x200000UL) << 15) /* bit 21 -> 36 */
+ |((value & 0x1f0000UL) << 6) /* bit 16 -> 22 */
+ |((value & 0x00ff80UL) << 20) /* bit 7 -> 27 */
+ |((value & 0x00007fUL) << 13) /* bit 0 -> 13 */));
+ break;
+ case R_IA64_LDXMOV:
+ if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+ die("value out of gp relative range");
+ ia64_patch((uint64_t)location, 0x1fff80fe000UL, 0x10000000000UL);
+ break;
case R_IA64_LTOFF22:
- case R_IA64_SEGREL64LSB:
+
default:
- die("Unknown rela relocation: %lu\n", r_type);
+ die("Unknown rela relocation: 0x%lx 0x%lx\n",
+ r_type, address);
break;
}
return;
- overflow:
+overflow:
die("overflow in relocation type %lu val %Lx\n",
- r_type, value);
+ r_type, value);
}
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2004-12-21 15:01:37.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-10-20 13:39:08.000000000 -0400
@@ -6,6 +6,7 @@
* Copyright (C) 2004 Silicon Graphics, Inc.
* Jesse Barnes <jbarnes at sgi.com>
* Copyright (C) 2004 Khalid Aziz <khalid.aziz at hp.com> Hewlett Packard Co
+ * Copyright (C) 2005 Zou Nan hai <nanhai.zou at intel.com> Intel Corp
*
* 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
@@ -34,6 +35,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
+#include <limits.h>
#include <elf.h>
#include <boot/elf_boot.h>
#include <ip_checksum.h>
@@ -74,23 +76,29 @@
{
printf(
" --command-line=STRING Set the kernel command line to STRING.\n"
- " --append=STRING Set the kernel command line to STRING.\n");
+ " --append=STRING Set the kernel command line to STRING.\n"
+ " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n");
}
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info)
{
struct mem_ehdr ehdr;
- const char *command_line;
- int command_line_len;
- unsigned long entry, max_addr;
+ const char *command_line, *ramdisk=0;
+ char *ramdisk_buf = NULL;
+ off_t ramdisk_size = 0;
+ unsigned long command_line_len;
+ unsigned long entry, max_addr, gp_value;
+ unsigned command_line_base, ramdisk_base;
int result;
int opt;
#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{"command-line", 1, 0, OPT_APPEND},
{"append", 1, 0, OPT_APPEND},
+ {"initrd", 1, 0, OPT_RAMDISK},
{0, 0, 0, 0},
};
@@ -110,11 +118,14 @@
case OPT_APPEND:
command_line = optarg;
break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
}
}
command_line_len = 0;
if (command_line) {
- command_line_len = strlen(command_line) + 1;
+ command_line_len = strlen(command_line) + 16;
}
/* Parse the Elf file */
@@ -129,13 +140,46 @@
/* Load the Elf data */
result = elf_exec_load(&ehdr, info);
- free_elf_info(&ehdr);
if (result < 0) {
fprintf(stderr, "ELF load failed\n");
+ free_elf_info(&ehdr);
return result;
}
+
+
+ /* Load the setup code */
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+ 0x80000, ULONG_MAX, 1);
+
+ if (command_line_len) {
+ char *cmdline = xmalloc(command_line_len);
+ strcpy(cmdline, command_line);
+ command_line_len = (command_line_len + 15)&(~15);
+ elf_rel_set_symbol(&info->rhdr, "__command_line_len",
+ &command_line_len, sizeof(long));
+ command_line_base = add_buffer(info, cmdline,
+ command_line_len, command_line_len,
+ 16, 0, max_addr, 1);
+ elf_rel_set_symbol(&info->rhdr, "__command_line",
+ &command_line_base, sizeof(long));
+ }
- /* For now we don't have arguments to pass :( */
- info->entry = (void *)entry;
+ if (ramdisk) {
+ ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
+ ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
+ ramdisk_size,
+ getpagesize(), 0, max_addr, 1);
+ elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
+ &ramdisk_base, sizeof(long));
+ elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
+ &ramdisk_size, sizeof(long));
+ }
+
+ gp_value = info->rhdr.rel_addr + 0x200000;
+ elf_rel_set_symbol(&info->rhdr, "__gp_value", &gp_value,
+ sizeof(gp_value));
+
+ elf_rel_set_symbol(&info->rhdr, "__kernel_entry", &entry, sizeof(entry));
+ free_elf_info(&ehdr);
return 0;
}
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig 2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c 2006-10-20 13:39:08.000000000 -0400
@@ -27,42 +27,87 @@
#include <stdint.h>
#include <string.h>
#include <getopt.h>
+#include <sched.h>
#include <sys/utsname.h>
#include "../../kexec.h"
#include "../../kexec-syscall.h"
#include "kexec-ia64.h"
#include <arch/options.h>
-#define MAX_MEMORY_RANGES 64
static struct memory_range memory_range[MAX_MEMORY_RANGES];
/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
unsigned long kexec_flags)
{
- int memory_ranges;
- /*
- * /proc/iomem on ia64 does not show where all memory is. If
- * that is fixed up, we can make use of that to validate
- * the memory range kernel will be loade din. Until then.....
- * -- Khalid Aziz
- */
-
- /* Note that the ia64 architecture mandates all systems will
- * have at least 64MB at 0-64M. The SGI altix does not follow
- * that restriction, but a reasonable guess is better than nothing
- * at all.
- * -- Eric Biederman
- */
- fprintf(stderr, "Warning assuming memory at 0-64MB is present\n");
- memory_ranges = 0;
- memory_range[memory_ranges].start = 0x00010000;
- memory_range[memory_ranges].end = 0x10000000;
- memory_range[memory_ranges].type = RANGE_RAM;
- memory_ranges++;
- *range = memory_range;
- *ranges = memory_ranges;
- return 0;
+ const char iomem[]= "/proc/iomem";
+ int memory_ranges = 0;
+ char line[MAX_LINE];
+ FILE *fp;
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+
+ while(fgets(line, sizeof(line), fp) != 0) {
+ unsigned long start, end;
+ char *str;
+ int type;
+ int consumed;
+ int count;
+ if (memory_ranges >= MAX_MEMORY_RANGES)
+ break;
+ count = sscanf(line, "%lx-%lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+ end = end + 1;
+ if (memcmp(str, "System RAM\n", 11) == 0) {
+ type = RANGE_RAM;
+ }
+ else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
+ }
+ else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+ /* Redefine the memory region boundaries if kernel
+ * exports the limits and if it is panic kernel.
+ * Override user values only if kernel exported
+ * values are subset of user defined values.
+ */
+
+ if (kexec_flags & KEXEC_ON_CRASH) {
+ if (start > mem_min)
+ mem_min = start;
+ if (end < mem_max)
+ mem_max = end;
+ }
+ continue;
+ } else
+ continue;
+ /*
+ * Check if this memory range can be coalesced with
+ * the previous range
+ */
+ if ((memory_ranges > 0) &&
+ (start == memory_range[memory_ranges-1].end) &&
+ (type == memory_range[memory_ranges-1].type)) {
+ memory_range[memory_ranges-1].end = end;
+ }
+ else {
+ memory_range[memory_ranges].start = start;
+ memory_range[memory_ranges].end = end;
+ memory_range[memory_ranges].type = type;
+ memory_ranges++;
+ }
+ }
+ fclose(fp);
+ *range = memory_range;
+ *ranges = memory_ranges;
+
+ return 0;
}
/* Supported file types and callbacks */
@@ -76,9 +121,6 @@
{
}
-static struct {
-} arch_options = {
-};
int arch_process_options(int argc, char **argv)
{
static const struct option options[] = {
@@ -88,6 +130,12 @@
static const char short_options[] = KEXEC_ARCH_OPT_STR;
int opt;
+ /* execute from monarch processor */
+ cpu_set_t affinity;
+ CPU_ZERO(&affinity);
+ CPU_SET(0, &affinity);
+ sched_setaffinity(0, sizeof(affinity), &affinity);
+
opterr = 0; /* Don't complain about unrecognized options here */
while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
switch(opt) {
@@ -113,10 +161,7 @@
}
if (strcmp(utsname.machine, "ia64") == 0)
{
- /* For compatibility with older patches
- * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here.
- */
- info->kexec_flags |= KEXEC_ARCH_DEFAULT;
+ info->kexec_flags |= KEXEC_ARCH_IA_64;
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
--- kexec-tools-1.101/kexec/kexec.8.orig 2004-12-19 17:27:31.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.8 2006-10-20 13:39:08.000000000 -0400
@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
-.TH KEXEC-TOOLS 8 "October 13, 2004"
+.TH KEXEC 8 "October 13, 2004"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -16,30 +16,60 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
-kexec-tools \- Tool to load a kernel for warm reboot and initiate a warm reboot
+kexec \- Tool to load a kernel for warm reboot and initiate a warm reboot
.SH SYNOPSIS
-.B kexec-tools
+.B kexec
.RI [ options ] " files" ...
.SH DESCRIPTION
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
-\fBkexec-tools\fP does not have a man page yet. Please use "kexec -h" for help.
+\fBkexec\fP allows one to load another kernel from the currently running
+Linux kernel. Normally one would load a kernel, and possibly an initial
+ramdisk, into the currently running kernel using kexec and then initiate
+a warm reboot by executing kexec again with appropriate option.
.SH OPTIONS
These programs follow the usual GNU command line syntax, with long
options starting with two dashes (`-').
A summary of options is included below.
-For a complete description, see the Info files.
.TP
.B \-h, \-\-help
Show summary of options.
.TP
.B \-v, \-\-version
Show version of program.
-.SH SEE ALSO
+.TP
+.B \-f, \-\-force
+Force an immediate kexec without calling shutdown.
+.TP
+.B \-x, \-\-no-ifdown
+Don't bring down network interfaces. (if used, must be last option specified)
+.TP
+.B \-l, \-\-load
+Load the new kernel into the current kernel.
+.TP
+.B \-p, \-\-load-panic
+Load the new kernel for use on panic.
+.TP
+.B \-u, \-\-unload
+Unload the current kexec target kernel.
+.TP
+.B \-e, \-\-exec
+Execute a currently loaded kernel.
+.TP
+.B \-t, \-\-type=TYPE
+Specify the new kernel is of this type.
+.TP
+.B \-\-mem\-min=<addr>
+Specify the lowest memory addres to load code into.
+.TP
+.B \-\-mem\-max=<addr>
+Specify the highest memory addres to load code into.
+.TP
+There may be additional options supported on individual architectures. Use --help option to see those options.
.SH AUTHOR
-kexec-tools was written by Eric Biederman.
+kexec was written by Eric Biederman.
.PP
-This manual page was written by Khalid Aziz <khalid_aziz at hp.com>,
+This manual page was written by Khalid Aziz <khalid.aziz at hp.com>,
for the Debian project (but may be used by others).
kexec-tools-1.101-ifdown.patch:
kexec.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+)
--- NEW FILE kexec-tools-1.101-ifdown.patch ---
--- kexec-tools-1.101/kexec/kexec.c.orig1 2006-10-13 14:01:39.000000000 -0400
+++ kexec-tools-1.101/kexec/kexec.c 2006-10-13 14:10:28.000000000 -0400
@@ -698,6 +698,19 @@ void usage(void)
printf("\n");
}
+static int kexec_loaded(void)
+{
+ int ret;
+ FILE *fp;
+
+ fp = fopen("/sys/kernel/kexec_loaded", "r");
+ if (fp == NULL)
+ return -1;
+ fscanf(fp, "%d", &ret);
+ fclose(fp);
+ return ret;
+}
+
int main(int argc, char *argv[])
{
int do_load = 1;
@@ -801,6 +814,10 @@ int main(int argc, char *argv[])
if (do_load && (result == 0)) {
result = my_load(type, fileind, argc, argv, kexec_flags);
}
+ /* Don't shutdown unless there is something to reboot to! */
+ if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded()) {
+ die("Nothing has been loaded!\n");
+ }
if ((result == 0) && do_shutdown) {
result = my_shutdown();
}
kexec-tools-1.101-makedumpfile-configfile.patch:
Makefile | 2
dwarfinfo/dwarf_incl.h | 11
dwarfinfo/dwarfdump.c | 8
dwarfinfo/print_die.c | 20 +
makedumpfile.c | 767 ++++++++++++++++++++++++++++++++++++++-----------
makedumpfile.h | 27 +
makedumpfile.h.orig |only
7 files changed, 663 insertions(+), 172 deletions(-)
--- NEW FILE kexec-tools-1.101-makedumpfile-configfile.patch ---
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarfdump.c kexec-tools-1.101/makedumpfile/dwarfinfo/dwarfdump.c
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarfdump.c 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/dwarfdump.c 2006-09-07 10:09:25.000000000 -0400
@@ -107,18 +107,18 @@ main(int argc, char *argv[])
dwarf_info.no_of_member = 3;
dwarf_info.cur_member = DWARF_INFO_MAX;
dwarf_info.member[0].name = "flags";
- dwarf_info.member[0].offset = 0;
+ dwarf_info.member[0].offset = -1;
dwarf_info.member[1].name = "_count";
- dwarf_info.member[1].offset = 0;
+ dwarf_info.member[1].offset = -1;
if (argc >= 3 && !strcmp(argv[2], "15")) {
dwarf_info.location_member = DWARF_INFO_MAX;
dwarf_info.member[2].name = "mapping";
- dwarf_info.member[2].offset = 0;
+ dwarf_info.member[2].offset = -1;
} else {
dwarf_info.location_member = 2;
dwarf_info.member[2].name = NULL; /* has no name */
- dwarf_info.member[2].offset = 0;
+ dwarf_info.member[2].offset = -1;
}
dwarfinfo();
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarf_incl.h kexec-tools-1.101/makedumpfile/dwarfinfo/dwarf_incl.h
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarf_incl.h 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/dwarf_incl.h 2006-09-07 10:09:25.000000000 -0400
@@ -64,13 +64,14 @@
#define DWARF_INFO_TAG_MEMBER 0x0002
#define DWARF_INFO_DONE 0x0004
#define DWARF_INFO_FILE_NAME_MATCH 0x0008
-#define DWARF_INFO_STRUCT_SIZE_DONE 0x0010
-#define DWARF_INFO_NAME_FOUND 0x0020
-#define DWARF_INFO_NAME_MATCH 0x0040
-#define DWARF_INFO_OFFSET_DONE 0x0080
+#define DWARF_INFO_STRUCT_NAME_MATCH 0x0010
+#define DWARF_INFO_STRUCT_SIZE_DONE 0x0020
+#define DWARF_INFO_NAME_FOUND 0x0040
+#define DWARF_INFO_NAME_MATCH 0x0080
+#define DWARF_INFO_OFFSET_DONE 0x0100
#define DWARF_INFO_MEMBER_DONE 0x1000
#define DWARF_INFO_STATUS_SHIFT 4
-#define DWARF_INFO_MAX 3
+#define DWARF_INFO_MAX 5
struct dwarf_info {
unsigned long status; /* TEMP */
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/print_die.c kexec-tools-1.101/makedumpfile/dwarfinfo/print_die.c
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/print_die.c 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/print_die.c 2006-09-07 10:09:25.000000000 -0400
@@ -171,6 +171,12 @@ print_one_die(Dwarf_Debug dbg, Dwarf_Die
tres = dwarf_tag(die, &tag, &err);
dwarf_info.tmp_status = 0;
if (tag == DW_TAG_structure_type) {
+ if ((dwarf_info.status &
+ (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE))
+ == (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE)) {
+ dwarf_info.status |= DWARF_INFO_DONE;
+ return;
+ }
dwarf_info.status = DWARF_INFO_TAG_STRUCT;
#ifdef DEBUG
fprintf(stderr, "DWARF_INFO_TAG_STRUCT set 1\n"); /* debug */
@@ -181,6 +187,12 @@ print_one_die(Dwarf_Debug dbg, Dwarf_Die
fprintf(stderr, "DWARF_INFO_TAG_MEMBER set 1\n"); /* debug */
#endif
} else {
+ if ((dwarf_info.status &
+ (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE))
+ == (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE)) {
+ dwarf_info.status |= DWARF_INFO_DONE;
+ return;
+ }
dwarf_info.status = 0;
return;
}
@@ -834,8 +846,11 @@ get_attr_value(Dwarf_Debug dbg, Dwarf_Ha
if (attr == DW_AT_name) {
if (dwarf_info.status & DWARF_INFO_TAG_STRUCT) {
if (!(dwarf_info.status & DWARF_INFO_TAG_MEMBER)) {
- if (strcmp(temps, dwarf_info.struct_name)) {
+ if (!strcmp(temps, dwarf_info.struct_name)) {
+ dwarf_info.status |= DWARF_INFO_STRUCT_NAME_MATCH;
+ } else {
dwarf_info.status &= ~DWARF_INFO_TAG_STRUCT;
+ dwarf_info.status &= ~DWARF_INFO_STRUCT_NAME_MATCH;
#ifdef DEBUG
fprintf(stderr, "DWARF_INFO_TAG_STRUCT reset 4\n"); /* debug */
#endif
@@ -846,9 +861,6 @@ get_attr_value(Dwarf_Debug dbg, Dwarf_Ha
if (dwarf_info.member[i].name == NULL) {
continue;
}
-#ifdef DEBUG
- fprintf(stderr, "&dwarf_info.member[ %d ].name = %p\n", i, &dwarf_info.member[i].name[0]); /* debug */
-#endif
if (strcmp(temps, dwarf_info.member[i].name) == 0) {
dwarf_info.cur_member = i;
dwarf_info.tmp_status |= DWARF_INFO_NAME_MATCH;
diff -urp kexec-tools-1.101-orig/makedumpfile/makedumpfile.c kexec-tools-1.101/makedumpfile/makedumpfile.c
--- kexec-tools-1.101-orig/makedumpfile/makedumpfile.c 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/makedumpfile.c 2006-09-07 10:09:39.000000000 -0400
@@ -193,7 +193,7 @@ vaddr_to_fileoffset(struct DumpInfo *inf
* Get the number of the page descriptors from the ELF info.
*/
unsigned int
-num_page_descriptor(struct DumpInfo *info)
+get_max_mapnr(struct DumpInfo *info)
{
int i;
off_t max_paddr;
@@ -234,22 +234,101 @@ readmem(struct DumpInfo *info, unsigned
return size;
}
+int
+get_kernel_version(char *release)
+{
+ if (!strncmp(release, "2.6.15", strlen("2.6.15"))) {
+ return VERSION_2_6_15;
+ } else if (!strncmp(release, "2.6.16", strlen("2.6.16"))) {
+ return VERSION_2_6_16;
+ } else if (!strncmp(release, "2.6.17", strlen("2.6.17"))) {
+ return VERSION_2_6_17;
+ } else if (!strncmp(release, "2.6.18", strlen("2.6.18"))) {
+ return VERSION_2_6_18;
+ } else {
+ ERRMSG("Can't get kernel version from system_utsname.\n");
+ return FALSE;
+ }
+}
+
+int
+is_page_size(unsigned long page_size)
+{
+ unsigned long bitbuf = page_size;
+ unsigned int i, sum = 0;
+
+ /* Only 1 bit is set because of page size. */
+ for (i = 0; i < sizeof(bitbuf) * 8; i++) {
+ sum += bitbuf & 1;
+ bitbuf = bitbuf >> 1;
+ }
+ if (sum != 1) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+check_release(struct DumpInfo *info)
+{
+ unsigned long sym_system_utsname;
+ struct utsname system_utsname;
+
+ sym_system_utsname = info->sym_system_utsname;
+ /*
+ * Get the kernel version from the symbol "system_utsname".
+ */
+ if (!sym_system_utsname) {
+ ERRMSG("Can't get the symbol of system_utsname.\n");
+ return FALSE;
+ }
+ if (!readmem(info, sym_system_utsname, &system_utsname, sizeof(struct utsname))) {
+ ERRMSG("Can't get the address of system_utsname.\n");
+ return FALSE;
+ }
+
+ if (info->flag_read_config) {
+ if (strcmp(system_utsname.release, info->release)) {
+ ERRMSG("%s doesn't suit the dump_mem.\n", info->name_configfile);
+ info->retcd = WRONG_RELEASE;
+ return FALSE;
+ }
+ }
+
+ info->kernel_version = get_kernel_version(system_utsname.release);
+ if (info->kernel_version == FALSE)
+ return FALSE;
+
+ return TRUE;
+}
+
void
print_usage()
{
MSG("\n");
MSG("Usage:\n");
- MSG(" makedumpfile [-c|-E] [-d dump_level] [-x vmlinux] [map_file] dump_mem dump_file\n");
+ MSG(" makedumpfile [-c|-E] [-d dump_level] [-g config_file]|[-i config_file]\n");
+ MSG(" [-x vmlinux] [map_file] dump_mem dump_file\n");
+ MSG("\n");
+ MSG(" Making dump_file with vmlinux and map_file:\n");
+ MSG(" makedumpfile [-c|-E] [-d dump_level] -x vmlinux map_file dump_mem dump_file\n");
+ MSG("\n");
+ MSG(" Making dump_file with config_file:\n");
+ MSG(" makedumpfile [-c|-E] [-d dump_level] -i config_file dump_mem dump_file\n");
+ MSG("\n");
+ MSG(" Generating config_file:\n");
+ MSG(" makedumpfile -g config_file -x vmlinux map_file\n");
MSG("\n");
MSG("Available options:\n");
MSG(" [-c]:\n");
MSG(" This option enables the compression function of each page.\n");
- MSG(" This is only for crash.\n");
+ MSG(" You can not specify this opiton with [-E].\n");
+ MSG(" This is only for crash. [dump_mem] and [dump_file] must be specified.\n");
MSG("\n");
MSG(" [-E]:\n");
MSG(" Create the ELF dump file.\n");
MSG(" You can not specify this opiton with [-c].\n");
- MSG(" This is only for gdb.\n");
+ MSG(" This is only for gdb. [dump_mem] and [dump_file] must be specified.\n");
MSG("\n");
MSG(" [-d dump_level]:\n");
MSG(" This is specification of the skipped pages. \n");
@@ -275,14 +354,40 @@ print_usage()
// MSG(" 14 | X X X\n");
MSG(" 15 | X X X X\n");
MSG("\n");
+ MSG(" [-i config_file] or ([-x vmlinux] and [map_file]) must be specified,\n");
+ MSG(" when dump_level is two or more.\n");
+ MSG(" [dump_mem] and [dump_file] must be specified.\n");
+ MSG("\n");
+ MSG(" [-g config_file]:\n");
+ MSG(" Generate the configuration file. Debugging information\n");
+ MSG(" necessary for executing a partial dump is output to this file. A partial\n");
+ MSG(" dump can be executed even if the output this file is read by -i option,\n");
+ MSG(" and there is no kernel file with debugging information. When this option\n");
+ MSG(" is specified, the dump is not output. [-x vmlinux] and [map_file] must\n");
+ MSG(" be specified.\n");
+ MSG("\n");
+ MSG(" [-i config_file]:\n");
+ MSG(" Read the configuration file. This file is the one\n");
+ MSG(" output beforehand by specifying -g option, and debugging information\n");
+ MSG(" necessary for executing a partial dump is contained. A partial dump can\n");
+ MSG(" be executed even if this file is read, and there is no kernel file with\n");
+ MSG(" debugging information. When this option is specified, -g option,\n");
+ MSG(" [-x vmlinux], and [map_file] cannot be specified.\n");
+ MSG(" Note:\n");
+ MSG(" When this file is not specified, this command uses the page size of\n");
+ MSG(" the system under operation(Capture kernel) as the one of dump_mem\n");
+ MSG(" (First-kernel).\n");
+ MSG("\n");
MSG(" [-x vmlinux]:\n");
- MSG(" This is a pathname to a vmlinux file compiled with -g option\n");
- MSG(" for first-kernel.\n");
- MSG(" This is necessary when dump_level is 2 or more.\n");
+ MSG(" This is a pathname to the first-kernel's vmlinux file compiled with\n");
+ MSG(" -g option.\n");
+ MSG(" This is necessary when dump_level is 2 or more and [-i config_file] is\n");
+ MSG(" not specified.\n");
MSG("\n");
MSG(" [map_file]:\n");
- MSG(" This is a pathname to a system.map file of first-kernel.\n");
- MSG(" This is necessary when dump_level is 2 or more.\n");
+ MSG(" This is a pathname to a System.map file of first-kernel.\n");
+ MSG(" This is necessary when dump_level is 2 or more and [-i config_file]\n");
+ MSG(" is not specified. [-x vmlinux] must be specified.\n");
MSG("\n");
MSG(" dump_mem:\n");
MSG(" This is a pathname to a first-kernel memory core image.\n");
@@ -312,6 +417,20 @@ open_system_map(struct DumpInfo *info)
}
int
+open_config_file(struct DumpInfo *info, char *mode)
+{
+ FILE *file_configfile;
+
+ if ((file_configfile = fopen(info->name_configfile, mode)) == NULL) {
+ ERRMSG("Can't open the config file(%s). %s\n",
+ info->name_configfile, strerror(errno));
+ return FALSE;
+ }
+ info->file_configfile = file_configfile;
+ return TRUE;
+}
+
+int
open_dump_memory(struct DumpInfo *info)
{
int fd;
@@ -322,7 +441,6 @@ open_dump_memory(struct DumpInfo *info)
return FALSE;
}
info->fd_memory = fd;
-
return TRUE;
}
@@ -364,6 +482,65 @@ open_dump_bitmap(struct DumpInfo *info)
return TRUE;
}
+/*
+ * Open the following files when it generates the configuration file.
+ * - vmlinux
+ * - system.map
+ * - configuration file
+ */
+int
+open_files_for_generating_configfile(struct DumpInfo *info)
+{
+ if ((dwarf_info.vmlinux_fd
+ = open_kernel_file(dwarf_info.vmlinux_name)) == -1)
+ return FALSE;
+
+ if (!open_system_map(info))
+ return FALSE;
+
+ if (!open_config_file(info, "w"))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Open the following files when it creates the dump file.
+ * - dump mem
+ * - dump file
+ * - bit map
+ * if it reads the configuration file
+ * - configuration file
+ * else
+ * - vmlinux
+ * - system.map
+ */
+int
+open_files_for_creating_dumpfile(struct DumpInfo *info)
+{
+ if (info->flag_read_config) {
+ if (!open_config_file(info, "r"))
+ return FALSE;
+ } else if (info->dump_level >= 2) {
+ if ((dwarf_info.vmlinux_fd
+ = open_kernel_file(dwarf_info.vmlinux_name)) == -1)
+ return FALSE;
+
+ if (!open_system_map(info))
+ return FALSE;
+ }
+ if (!open_dump_memory(info))
+ return FALSE;
+
+ if (!open_dump_file(info))
+ return FALSE;
+
+ if (!open_dump_bitmap(info))
+ return FALSE;
+
+ return TRUE;
+}
+
int
dump_Elf32_pt_load(struct DumpInfo *info, Elf32_Phdr *prog, int num_load)
{
@@ -380,7 +557,6 @@ dump_Elf32_pt_load(struct DumpInfo *info
pls->virt_start = prog->p_vaddr;
pls->virt_end = pls->virt_start + prog->p_filesz;
pls->file_offset = prog->p_offset;
-
return TRUE;
}
@@ -407,6 +583,7 @@ int
get_elf_info(struct DumpInfo *info)
{
int i;
+ unsigned long tmp;
const off_t failed = (off_t)-1;
Elf32_Ehdr *elf32;
@@ -436,7 +613,6 @@ get_elf_info(struct DumpInfo *info)
&header[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
info->num_load_memory = elf32->e_phnum - 1;
info->offset_load_memory = (Elf32_Off)load32->p_offset;
- info->page_size = (uint32_t)load32->p_align;
} else if (STRNEQ(elf64->e_ident, ELFMAG)
&& (elf64->e_ident[EI_CLASS] == ELFCLASS64)) {
info->flag_elf = ELF64;
@@ -444,7 +620,6 @@ get_elf_info(struct DumpInfo *info)
&header[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
info->num_load_memory = elf64->e_phnum - 1;
info->offset_load_memory = (Elf64_Off)load64->p_offset;
- info->page_size = (uint64_t)load64->p_align;
} else {
ERRMSG("%s isn't the dump memory.\n", info->name_memory);
goto out;
@@ -455,11 +630,8 @@ get_elf_info(struct DumpInfo *info)
* If the page_size of 1st-kernel is different from the one of
* capture(2nd)-kernel, the problem will happen.
*/
- if (!info->page_size)
- info->page_size = (size_t)sysconf(_SC_PAGE_SIZE);
if (!info->page_size) {
- ERRMSG("Can't get the size of page.\n");
- goto out;
+ info->page_size = sysconf(_SC_PAGE_SIZE);
}
if (!info->num_load_memory) {
ERRMSG("Can't get the number of PT_LOAD.\n");
@@ -517,6 +689,11 @@ get_elf_info(struct DumpInfo *info)
if(!dump_Elf64_pt_load(info, load64 + i, i))
goto out;
}
+ info->max_mapnr = get_max_mapnr(info);
+ tmp = 2*divideup(info->max_mapnr, BITPERBYTE);
+ tmp = divideup(tmp, info->page_size);
+ info->len_bitmap = tmp*info->page_size;
+
g_free(tmp_elf_header);
return TRUE;
out:
@@ -528,21 +705,16 @@ out:
int
get_symbol_info(struct DumpInfo *info)
{
- unsigned int max_mapnr;
- unsigned long sym_mem_map = 0, sym_num_physpages = 0;
+ unsigned long sym_mem_map = 0;
unsigned long sym_system_utsname = 0;
- unsigned long addr_mem_map;
- struct new_utsname system_utsname;
char buf[BUFSIZE_FGETS], *mapitems[MAXARGS], *endp;
if (info->name_sysmap == NULL) {
- info->max_mapnr = num_page_descriptor(info);
- info->len_bitmap = 2*divideup(info->max_mapnr, BITPERBYTE);
return TRUE;
}
/*
- * Get a symbol info from the System.map.
+ * Get symbol info from the System.map.
*/
while (fgets(buf, BUFSIZE_FGETS, info->map)) {
if (parse_line(buf, mapitems) != 3)
@@ -557,16 +729,6 @@ get_symbol_info(struct DumpInfo *info)
return FALSE;
}
}
- if (strcmp(mapitems[2], "num_physpages") == 0) {
- sym_num_physpages = strtoul(mapitems[0], &endp, 16);
- if ((!sym_num_physpages
- || sym_num_physpages == ULONG_MAX)
- || strlen(endp) != 0) {
- ERRMSG("The map file has invalid address of %s",
- mapitems[2]);
- return FALSE;
- }
- }
if (strcmp(mapitems[2], "system_utsname") == 0) {
sym_system_utsname = strtoul(mapitems[0], &endp, 16);
if ((!sym_system_utsname
@@ -577,69 +739,11 @@ get_symbol_info(struct DumpInfo *info)
return FALSE;
}
}
- if ((sym_mem_map != 0)
- && (sym_num_physpages != 0)
- && (sym_system_utsname != 0))
+ if (sym_mem_map != 0 && sym_system_utsname != 0)
break;
}
-
- /*
- * Get the address of the symbol "mem_map".
- * FIXME
- * If this command get the feature of analysing a struct,
- * the info of the memory management will be gotten from "pgdat_list".
- */
- if (!sym_mem_map) {
- ERRMSG("Can't get the symbol of mem_map.\n");
- return FALSE;
- }
- if (!readmem(info, sym_mem_map, &addr_mem_map, sizeof addr_mem_map)) {
- ERRMSG("Can't get the address of mem_map.\n");
- return FALSE;
- }
-
- if (!addr_mem_map) {
- ERRMSG("Can't get the address of mem_map.\n");
- return FALSE;
- }
- info->addr_mem_map = addr_mem_map;
-
- /*
- * Get the number of the page descriptors.
- */
- if (!sym_num_physpages || !readmem(info, sym_num_physpages, &max_mapnr,
- sizeof max_mapnr) || !max_mapnr)
- max_mapnr = num_page_descriptor(info);
-
- if (!max_mapnr) {
- ERRMSG("Can't get the number of the page descriptors.\n");
- return FALSE;
- }
- info->max_mapnr = max_mapnr;
- info->len_bitmap = 2*divideup(info->max_mapnr, BITPERBYTE);
-
- /*
- * Get the kernel version from the symbol "system_utsname".
- */
- if (!sym_system_utsname) {
- ERRMSG("Can't get the symbol of system_utsname.\n");
- return FALSE;
- }
- if (!readmem(info, sym_system_utsname, &system_utsname, sizeof(struct new_utsname))) {
- ERRMSG("Can't get the address of system_utsname.\n");
- return FALSE;
- }
-
- if (!strncmp(system_utsname.release, "2.6.15", strlen("2.6.15"))) {
- info->kernel_version = VERSION_2_6_15;
- } else if (!strncmp(system_utsname.release, "2.6.16", strlen("2.6.16"))) {
- info->kernel_version = VERSION_2_6_16;
- } else if (!strncmp(system_utsname.release, "2.6.17", strlen("2.6.17"))) {
- info->kernel_version = VERSION_2_6_17;
- } else {
- ERRMSG("Can't get kernel version from system_utsname.\n");
- return FALSE;
- }
+ info->sym_mem_map = sym_mem_map;
+ info->sym_system_utsname = sym_system_utsname;
return TRUE;
}
@@ -647,9 +751,10 @@ get_symbol_info(struct DumpInfo *info)
int
get_pagedesc_offset(struct DumpInfo *info)
{
+ int i;
/*
- * Get a offset of the page_discriptor's member.
+ * Get offsets of the page_discriptor's members.
*/
dwarf_info.status = 0;
@@ -659,20 +764,23 @@ get_pagedesc_offset(struct DumpInfo *inf
dwarf_info.no_of_member = 3;
dwarf_info.cur_member = DWARF_INFO_MAX;
dwarf_info.member[0].name = "flags";
- dwarf_info.member[0].offset = 0;
+ dwarf_info.member[0].offset = -1;
dwarf_info.member[1].name = "_count";
- dwarf_info.member[1].offset = 0;
+ dwarf_info.member[1].offset = -1;
if (info->kernel_version == VERSION_2_6_15) { /* linux-2.6.15 */
dwarf_info.location_member = DWARF_INFO_MAX;
dwarf_info.member[2].name = "mapping";
- dwarf_info.member[2].offset = 0;
+ dwarf_info.member[2].offset = -1;
} else {
dwarf_info.location_member = 2;
dwarf_info.member[2].name = NULL; /* has no name */
- dwarf_info.member[2].offset = 0;
+ dwarf_info.member[2].offset = -1;
}
if (dwarfinfo())
return FALSE;
+ for (i = 0; i < dwarf_info.no_of_member; i++)
+ if (dwarf_info.member[i].offset == -1)
+ return FALSE;
info->size_pagedesc = dwarf_info.struct_size;
info->offset_page_flags = dwarf_info.member[0].offset;
@@ -690,16 +798,248 @@ get_pagedesc_offset(struct DumpInfo *inf
}
int
-initial(struct DumpInfo *info)
+generate_config(struct DumpInfo *info)
{
- if (!get_elf_info(info))
+ struct utsname utsname_buf;
+ long tmp_long;
+
+ /*
+ * write 1st kernel's OSRELEASE
+ */
+ if (uname(&utsname_buf)) {
+ ERRMSG("Can't get uname. %s\n", strerror(errno));
return FALSE;
+ }
+ fprintf(info->file_configfile, "%s%s\n", STR_OSRELEASE,
+ utsname_buf.release);
+ /*
+ * write 1st kernel's PAGESIZE
+ */
+ if (!info->page_size) {
+ tmp_long = sysconf(_SC_PAGE_SIZE);
+ if (tmp_long == -1) {
+ ERRMSG("Can't get the size of page.\n");
+ return FALSE;
+ }
+ info->page_size = (size_t)tmp_long;
+ }
+ fprintf(info->file_configfile, "%s%d\n", STR_PAGESIZE,
+ (int)info->page_size);
+
+ /*
+ * write 1st kernel's address of SYMBOL(mem_map)
+ */
if (!get_symbol_info(info))
return FALSE;
+ if (!info->sym_mem_map || !info->sym_system_utsname) {
+ ERRMSG("Can't get the symbol of mem_map.\n");
+ return FALSE;
+ }
+ fprintf(info->file_configfile, "%s%lx\n", STR_SYMBOL("mem_map"),
+ info->sym_mem_map);
+
+ /*
+ * write 1st kernel's address of SYMBOL(system_utsname)
+ */
+ fprintf(info->file_configfile, "%s%lx\n", STR_SYMBOL("system_utsname"),
+ info->sym_system_utsname);
+
+ /*
+ * get 1st kernel's version
+ */
+ info->kernel_version = get_kernel_version(utsname_buf.release);
+ if (info->kernel_version == FALSE)
+ return FALSE;
+ /*
+ * write 1st kernel's size of struct page
+ */
if (!get_pagedesc_offset(info))
return FALSE;
+ fprintf(info->file_configfile, "%s%d\n", STR_SIZE("page"),
+ info->size_pagedesc);
+
+ /*
+ * write 1st kernel's offset of page.flags
+ */
+ fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page.flags"),
+ info->offset_page_flags);
+
+ /*
+ * write 1st kernel's offset of page._count
+ */
+ fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page._count"),
+ info->offset_page__count);
+
+ /*
+ * write 1st kernel's offset of page.mapping
+ */
+ fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page.mapping"),
+ info->offset_page_mapping);
+
+ return TRUE;
+}
+
+int
+read_config(struct DumpInfo *info)
+{
+ unsigned long tmp_ulong;
+ char buf[BUFSIZE_FGETS], *endp;
+ unsigned int ok_flag = 0, i;
+
+ while (fgets(buf, BUFSIZE_FGETS, info->file_configfile)) {
+ i = strlen(buf);
+ if (buf[i - 1] == '\n')
+ buf[i - 1] = '\0';
+ if (strncmp(buf, STR_OSRELEASE, strlen(STR_OSRELEASE)) == 0) {
+ strcpy(info->release, buf + strlen(STR_OSRELEASE));
+ ok_flag = 1;
+ }
+ if (strncmp(buf, STR_PAGESIZE, strlen(STR_PAGESIZE)) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_PAGESIZE), &endp, 10);
+ if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ if (!is_page_size(tmp_ulong)) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->page_size = tmp_ulong;
+ }
+ if (strncmp(buf, STR_SYMBOL("mem_map"), strlen(STR_SYMBOL("mem_map"))) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_SYMBOL("mem_map")),
+ &endp, 16);
+ if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->sym_mem_map = tmp_ulong;
+ }
+ if (strncmp(buf, STR_SYMBOL("system_utsname"), strlen(STR_SYMBOL("system_utsname"))) == 0) {
+ tmp_ulong = strtoul(buf
+ + strlen(STR_SYMBOL("system_utsname")), &endp, 16);
+ if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->sym_system_utsname = tmp_ulong;
+ }
+ if (strncmp(buf, STR_SIZE("page"), strlen(STR_SIZE("page"))) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_SIZE("page")), &endp, 10);
+ if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->size_pagedesc = tmp_ulong;
+ }
+ if (strncmp(buf, STR_OFFSET("page.flags"), strlen(STR_OFFSET("page.flags"))) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page.flags")),
+ &endp, 10);
+ if (tmp_ulong == ULONG_MAX
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->offset_page_flags = tmp_ulong;
+ }
+ if (strncmp(buf, STR_OFFSET("page._count"), strlen(STR_OFFSET("page._count"))) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page._count")),
+ &endp, 10);
+ if (tmp_ulong == ULONG_MAX
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->offset_page__count = tmp_ulong;
+ }
+ if (strncmp(buf, STR_OFFSET("page.mapping"), strlen(STR_OFFSET("page.mapping"))) == 0) {
+ tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page.mapping")),
+ &endp, 10);
+ if (tmp_ulong == ULONG_MAX
+ || strlen(endp) != 0) {
+ ERRMSG("Invalid data in %s: %s",
+ info->name_configfile, buf);
+ return FALSE;
+ }
+ info->offset_page_mapping = tmp_ulong;
+ }
+ }
+ if (!ok_flag || !info->page_size) {
+ ERRMSG("Invalid format in %s", info->name_configfile);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+get_mem_map(struct DumpInfo *info)
+{
+ unsigned long sym_mem_map = info->sym_mem_map;
+ unsigned long addr_mem_map;
+
+ /*
+ * Get the address of the symbol "mem_map".
+ * FIXME
+ * If this command get the feature of analysing a struct,
+ * the info of the memory management will be gotten from "pgdat_list".
+ */
+ if (!sym_mem_map) {
+ ERRMSG("Can't get the symbol of mem_map.\n");
+ return FALSE;
+ }
+ if (!readmem(info, sym_mem_map, &addr_mem_map, sizeof addr_mem_map)) {
+ ERRMSG("Can't get the address of mem_map.\n");
+ return FALSE;
+ }
+ if (!addr_mem_map) {
+ ERRMSG("Can't get the address of mem_map.\n");
+ return FALSE;
+ }
+ info->addr_mem_map = addr_mem_map;
+
+ return TRUE;
+}
+
+int
+initial(struct DumpInfo *info)
+{
+ if (!get_elf_info(info))
+ return FALSE;
+
+ if (!info->flag_read_config) {
+ if (info->dump_level <= 1)
+ return TRUE;
+ if (!get_symbol_info(info))
+ return FALSE;
+ if (!check_release(info))
+ return FALSE;
+ if (!get_pagedesc_offset(info))
+ return FALSE;
+ } else {
+ if (!read_config(info))
+ return FALSE;
+ if (!info->sym_mem_map || !info->sym_system_utsname) {
+ ERRMSG("Invalid format in %s", info->name_configfile);
+ return FALSE;
+ }
+ if (!check_release(info))
+ return FALSE;
+ }
+ if (!get_mem_map(info))
+ return FALSE;
return TRUE;
}
@@ -997,7 +1337,8 @@ create_dump_bitmap(struct DumpInfo *info
strerror(errno));
goto out;
}
- if ((page_cache = g_malloc(info->size_pagedesc*PGMM_CACHED)) == NULL) {
+ if (info->dump_level > DL_EXCLUDE_ZERO &&
+ (page_cache = g_malloc(info->size_pagedesc*PGMM_CACHED)) == NULL) {
ERRMSG("Can't allocate memory for the pagedesc cache. %s\n",
strerror(errno));
goto out;
@@ -1135,7 +1476,8 @@ create_dump_bitmap(struct DumpInfo *info
if (info->flag_elf_dumpfile && !create_contig_bitmap(info))
goto out;
- g_free(page_cache);
+ if (page_cache != NULL)
+ g_free(page_cache);
g_free(buf);
g_free(bm1.buf);
g_free(bm2.buf);
@@ -1625,6 +1967,8 @@ write_pages(struct DumpInfo *info)
if (!write_cache_bufsz(&bm2))
goto out;
}
+ if (info->len_bitmap - bm2.offset < BUFSIZE_BITMAP)
+ bm2.cache_size = info->len_bitmap - bm2.offset;
if (!read_cache(&bm2))
goto out;
flag_change_bitmap = 0;
@@ -1751,7 +2095,7 @@ out:
int write_dump_bitmap(struct DumpInfo *info)
{
struct cache_data bm;
- unsigned long buf_size;
+ long buf_size;
const off_t failed = (off_t)-1;
if (info->flag_elf_dumpfile)
@@ -1812,6 +2156,14 @@ close_system_map(struct DumpInfo *info)
}
void
+close_config_file(struct DumpInfo *info)
+{
+ if(fclose(info->file_configfile) < 0)
+ ERRMSG("Can't close the config file(%s). %s\n",
+ info->name_configfile, strerror(errno));
+}
+
+void
close_dump_memory(struct DumpInfo *info)
{
if (close(info->fd_memory) < 0)
@@ -1844,6 +2196,54 @@ close_kernel_file(int fd)
dwarf_info.vmlinux_name, strerror(errno));
}
+/*
+ * Close the following files when it generates the configuration file.
+ * - vmlinux
+ * - system.map
+ * - configuration file
+ */
+int
+close_files_for_generating_configfile(struct DumpInfo *info)
+{
+ close_kernel_file(dwarf_info.vmlinux_fd);
+
+ close_system_map(info);
+
+ close_config_file(info);
+
+ return TRUE;
+}
+
+/*
+ * Close the following files when it creates the dump file.
+ * - dump mem
+ * - dump file
+ * - bit map
+ * if it reads the configuration file
+ * - configuration file
+ * else
+ * - vmlinux
+ * - system.map
+ */
+int
+close_files_for_creating_dumpfile(struct DumpInfo *info)
+{
+ if (info->flag_read_config) {
+ close_config_file(info);
+ } else if (info->dump_level >= 2) {
+ close_kernel_file(dwarf_info.vmlinux_fd);
+
+ close_system_map(info);
+ }
+ close_dump_memory(info);
+
+ close_dump_file(info);
+
+ close_dump_bitmap(info);
+
+ return TRUE;
+}
+
int
main(int argc, char *argv[])
{
@@ -1862,7 +2262,7 @@ main(int argc, char *argv[])
goto out;
}
- while ((opt = getopt(argc, argv, "b:cd:Ex:")) != -1) {
+ while ((opt = getopt(argc, argv, "b:cd:Eg:i:x:")) != -1) {
switch (opt) {
case 'b':
info->block_order = atoi(optarg);
@@ -1876,7 +2276,16 @@ main(int argc, char *argv[])
case 'E':
info->flag_elf_dumpfile = 1;
break;
+ case 'g':
+ info->flag_generate_config = 1;
+ info->name_configfile = optarg;
+ break;
+ case 'i':
+ info->flag_read_config = 1;
+ info->name_configfile = optarg;
+ break;
case 'x':
+ info->flag_vmlinux = 1;
dwarf_info.vmlinux_name = optarg;
break;
case '?':
@@ -1885,75 +2294,114 @@ main(int argc, char *argv[])
goto out;
}
}
- if ((info->dump_level < MIN_DUMP_LEVEL)
- || (MAX_DUMP_LEVEL < info->dump_level)) {
- ERRMSG("Dump_level is invalid.\n");
- print_usage();
- goto out;
- }
- if ((optind + 3 < argc)
- || ((info->dump_level <= 1) && (argc < optind + 2))
- || ((info->dump_level >= 2) && (argc != optind + 3))
- || ((info->flag_compress == 1) && (info->flag_elf_dumpfile == 1))) {
- ERRMSG("Commandline parameter is invalid.\n");
- print_usage();
- goto out;
- }
- if ((info->dump_level <= 1) && (argc == optind + 2)) {
+
+ if (info->flag_generate_config) {
+ /*
+ * generate the configuration file
+ */
+ if (argc != optind + 1) {
+ ERRMSG("Commandline parameter is invalid.\n");
+ print_usage();
+ goto out;
+ }
+ if (info->flag_compress || info->dump_level ||
+ info->flag_elf_dumpfile || info->flag_read_config ||
+ !info->flag_vmlinux) {
+ ERRMSG("Commandline parameter is invalid.\n");
+ print_usage();
+ goto out;
+ }
+ info->name_sysmap = argv[optind];
+ } else if (info->flag_read_config) {
+ /*
+ * check parameters to read the configuration file
+ */
+ if ((info->dump_level < MIN_DUMP_LEVEL)
+ || (MAX_DUMP_LEVEL < info->dump_level)) {
+ ERRMSG("Dump_level is invalid.\n");
+ print_usage();
+ goto out;
+ }
+ if ((argc != optind + 2)
+ || ((info->flag_compress == 1)
+ && (info->flag_elf_dumpfile == 1))
+ /* || info->flag_generate_config */
+ || info->flag_vmlinux) {
+ ERRMSG("Commandline parameter is invalid.\n");
+ print_usage();
+ goto out;
+ }
info->name_sysmap = NULL;
info->name_memory = argv[optind];
info->name_dumpfile = argv[optind+1];
} else {
- info->name_sysmap = argv[optind];
- info->name_memory = argv[optind+1];
- info->name_dumpfile = argv[optind+2];
+ if ((info->dump_level < MIN_DUMP_LEVEL)
+ || (MAX_DUMP_LEVEL < info->dump_level)) {
+ ERRMSG("Dump_level is invalid.\n");
+ print_usage();
+ goto out;
+ }
+ if ((optind + 3 < argc)
+ || ((info->dump_level <= 1) && (argc < optind + 2))
+ || ((info->dump_level >= 2) && (argc != optind + 3))
+ || ((info->dump_level >= 2) && (!info->flag_vmlinux))
+ || ((info->flag_compress == 1)
+ && (info->flag_elf_dumpfile == 1))) {
+ ERRMSG("Commandline parameter is invalid.\n");
+ print_usage();
+ goto out;
+ }
+ if ((info->dump_level <= 1) && (argc == optind + 2)) {
+ info->name_sysmap = NULL;
+ info->name_memory = argv[optind];
+ info->name_dumpfile = argv[optind+1];
+ } else {
+ info->name_sysmap = argv[optind];
+ info->name_memory = argv[optind+1];
+ info->name_dumpfile = argv[optind+2];
+ }
}
- if (!open_system_map(info))
- goto out;
- if (!open_dump_memory(info))
- goto out;
-
- if (!open_dump_file(info))
- goto out;
-
- if (!open_dump_bitmap(info))
- goto out;
-
- dwarf_info.vmlinux_fd = open_kernel_file(dwarf_info.vmlinux_name);
- if (dwarf_info.vmlinux_fd == -1)
- goto out;
-
- if (!initial(info))
- goto out;
+ if (info->flag_generate_config) {
+ if (!open_files_for_generating_configfile(info))
+ goto out;
- if (!create_dump_bitmap(info))
- goto out;
+ if (!generate_config(info))
+ goto out;
- if (!write_dump_header(info))
- goto out;
+ if (!close_files_for_generating_configfile(info))
+ goto out;
- if (!write_pages(info))
- goto out;
+ MSG("\n");
+ } else {
+ if (!open_files_for_creating_dumpfile(info))
+ goto out;
- if (!write_dump_bitmap(info))
- goto out;
+ if (!initial(info))
+ goto out;
- close_system_map(info);
+ if (!create_dump_bitmap(info))
+ goto out;
- close_dump_memory(info);
+ if (!write_dump_header(info))
+ goto out;
- close_dump_file(info);
+ if (!write_pages(info))
+ goto out;
- close_dump_bitmap(info);
+ if (!write_dump_bitmap(info))
+ goto out;
- close_kernel_file(dwarf_info.vmlinux_fd);
+ if (!close_files_for_creating_dumpfile(info))
+ goto out;
- MSG("\n");
- MSG("The dumpfile is saved to %s.\n", info->name_dumpfile);
+ MSG("\n");
+ MSG("The dumpfile is saved to %s.\n", info->name_dumpfile);
+ }
MSG("makedumpfile Completed.\n");
- g_free(info->pt_load_segments);
+ if (!info->flag_generate_config)
+ g_free(info->pt_load_segments);
g_free(info->dump_header);
g_free(info);
return COMPLETED;
@@ -1975,5 +2423,8 @@ out:
g_free(info->dump_header);
if (info != NULL)
g_free(info);
- return FAILED;
+ if (info->retcd)
+ return info->retcd;
+ else
+ return FAILED;
}
diff -urp kexec-tools-1.101-orig/makedumpfile/makedumpfile.h kexec-tools-1.101/makedumpfile/makedumpfile.h
--- kexec-tools-1.101-orig/makedumpfile/makedumpfile.h 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/makedumpfile.h 2006-09-07 10:09:39.000000000 -0400
@@ -23,6 +23,7 @@
#include <string.h>
#include <errno.h>
#include <time.h>
+#include <sys/utsname.h>
#include <glib.h>
#include <zlib.h>
#include "diskdump_mod.h"
@@ -34,6 +35,9 @@
*/
#define COMPLETED (0)
#define FAILED (1)
+#define WRONG_RELEASE (2) /* utsname.release does not match. */
+#define ANALYSIS_FAILED (3) /* detected illegal page descriptor. */
+#define OUTPUT_FAILED (4) /* detected an output error. */
/*
* Page flags
@@ -137,6 +141,16 @@ isAnon(unsigned long mapping)
#define VERSION_2_6_15 (15)
#define VERSION_2_6_16 (16)
#define VERSION_2_6_17 (17)
+#define VERSION_2_6_18 (18)
+
+/*
+ * field name of config file
+ */
+#define STR_OSRELEASE "OSRELEASE="
+#define STR_PAGESIZE "PAGESIZE="
+#define STR_SYMBOL(X) "SYMBOL("X")="
+#define STR_SIZE(X) "SIZE("X")="
+#define STR_OFFSET(X) "OFFSET("X")="
/*
* The values of linux 2.6.15.1
@@ -187,6 +201,7 @@ struct cache_data {
};
struct DumpInfo {
+ int retcd; /* return code */
int size_pagedesc; /* size of page descriptor */
int offset_page_flags; /* offset of page.flags */
int offset_page__count; /* offset of page._count */
@@ -201,6 +216,9 @@ struct DumpInfo {
int flag_compress; /* flag of compression */
int flag_elf;
int flag_elf_dumpfile; /* flag of elf dump file */
+ int flag_vmlinux; /* flag of vmlinux */
+ int flag_generate_config;/* flag of generating config file */
+ int flag_read_config; /* flag of reading config file */
size_t page_size; /* size of page */
unsigned int max_mapnr; /* number of page descriptor */
@@ -245,4 +263,13 @@ struct DumpInfo {
*/
int fd_bitmap;
char *name_bitmap;
+
+ /*
+ * config file info:
+ */
+ FILE *file_configfile;
+ char *name_configfile; /* config file */
+ char release[65]; /*Can I define 65 automatically?*/
+ unsigned long sym_mem_map;
+ unsigned long sym_system_utsname;
};
Only in kexec-tools-1.101/makedumpfile: makedumpfile.h.orig
diff -urp kexec-tools-1.101-orig/makedumpfile/Makefile kexec-tools-1.101/makedumpfile/Makefile
--- kexec-tools-1.101-orig/makedumpfile/Makefile 2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/Makefile 2006-09-07 10:09:39.000000000 -0400
@@ -77,4 +77,4 @@ readdwarfinfo: $(SRC_DEBUG) $(OBJ_DEBUG)
$(CC) $(CFLAGS_DEBUG) $(OBJ_DEBUG) -lelf -o $@
install:
- cp ./makedumpfile /usr/sbin
+ cp ./makedumpfile /bin
kexec-tools-1.101-ppc64-64k-pages.patch:
kexec/arch/ppc64/crashdump-ppc64.c | 13 +++++++------
kexec/arch/ppc64/crashdump-ppc64.h | 14 +++++---------
purgatory/arch/ppc64/crashdump_backup.c | 8 +++-----
3 files changed, 15 insertions(+), 20 deletions(-)
--- NEW FILE kexec-tools-1.101-ppc64-64k-pages.patch ---
Signed-off-by: Sachin Sant <sachinp at in.ibm.com>
---
diff -Naurp kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.c kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.c
--- kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.c 2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.c 2006-09-08 07:32:19.000000000 +0530
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <elf.h>
@@ -85,8 +86,8 @@ static int get_crash_memory_ranges(struc
unsigned long long start, end, cstart, cend;
/* create a separate program header for the backup region */
- crash_memory_range[0].start = 0x0000000000000000;
- crash_memory_range[0].end = 0x0000000000008000;
+ crash_memory_range[0].start = BACKUP_START;
+ crash_memory_range[0].end = BACKUP_END;
crash_memory_range[0].type = RANGE_RAM;
memory_ranges++;
@@ -125,8 +126,8 @@ static int get_crash_memory_ranges(struc
break;
start = ((unsigned long long *)buf)[0];
end = start + ((unsigned long long *)buf)[1];
- if (start == 0 && end >= 0x8000)
- start = 0x8000;
+ if (start == 0 && end >= BACKUP_END)
+ start = BACKUP_END;
match = 0;
sort_regions(&exclude_rgns);
@@ -420,8 +421,8 @@ void add_usable_mem_rgns(unsigned long l
unsigned long long end = base + size;
unsigned long long ustart, uend;
- base = _ALIGN_DOWN(base, PAGE_SIZE);
- end = _ALIGN_UP(end, PAGE_SIZE);
+ base = _ALIGN_DOWN(base, getpagesize());
+ end = _ALIGN_UP(end, getpagesize());
for (i=0; i < usablemem_rgns.size; i++) {
ustart = usablemem_rgns.ranges[i].start;
diff -Naurp kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.h kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.h
--- kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.h 2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.h 2006-09-08 07:33:38.000000000 +0530
@@ -6,28 +6,24 @@ int load_crashdump_segments(struct kexec
void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
void add_exclude_rgns(unsigned long long base, unsigned long long size);
-#define PAGE_OFFSET 0xC000000000000000
+#define PAGE_OFFSET 0xC000000000000000
#define KERNELBASE PAGE_OFFSET
#define VMALLOCBASE 0xD000000000000000
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
-
-#define MAXMEM (-KERNELBASE-VMALLOCBASE)
+#define MAXMEM (-KERNELBASE-VMALLOCBASE)
#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 6)
#define COMMAND_LINE_SIZE 512 /* from kernel */
-/* Backup Region, First 32K of System RAM. */
+/* Backup Region, First 64K of System RAM. */
#define BACKUP_START 0x0000
-#define BACKUP_END 0x8000
+#define BACKUP_END 0x10000
#define BACKUP_SIZE (BACKUP_END - BACKUP_START + 1)
-#define KDUMP_BACKUP_LIMIT 0x8000
+#define KDUMP_BACKUP_LIMIT BACKUP_END
#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
extern unsigned long long crash_base;
extern unsigned long long crash_size;
diff -Naurp kexec-tools-rh/purgatory/arch/ppc64/crashdump_backup.c kexec-tools-rh-fix/purgatory/arch/ppc64/crashdump_backup.c
--- kexec-tools-rh/purgatory/arch/ppc64/crashdump_backup.c 2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/purgatory/arch/ppc64/crashdump_backup.c 2006-09-08 08:42:27.000000000 +0530
@@ -21,9 +21,7 @@
#include <stdint.h>
#include <string.h>
-
-#define BACKUP_REGION_SOURCE 0x0
-#define BACKUP_REGION_SIZE 32*1024
+#include "../../../kexec/arch/ppc64/crashdump-ppc64.h"
extern unsigned long backup_start;
@@ -32,10 +30,10 @@ void crashdump_backup_memory(void)
{
void *dest, *src;
- src = (void *)BACKUP_REGION_SOURCE;
+ src = (void *)BACKUP_START;
if (backup_start) {
dest = (void *)(backup_start);
- memcpy(dest, src, BACKUP_REGION_SIZE);
+ memcpy(dest, src, BACKUP_SIZE);
}
}
kexec-tools-1.101-reloc-update.patch:
kexec/Makefile | 1
kexec/arch/i386/kexec-bzImage.c | 2
kexec/arch/i386/kexec-elf-x86.c | 6
kexec/arch/i386/kexec-multiboot-x86.c | 5
kexec/arch/ia64/kexec-elf-ia64.c | 6
kexec/arch/ppc/kexec-elf-ppc.c | 4
kexec/arch/ppc64/kexec-elf-ppc64.c | 6
kexec/arch/x86_64/crashdump-x86_64.c | 190 ++++++++++++++++++++++++++---
kexec/arch/x86_64/kexec-elf-rel-x86_64.c | 2
kexec/arch/x86_64/kexec-elf-x86_64.c | 6
kexec/arch/x86_64/kexec-x86_64.c | 4
kexec/crashdump.h | 2
kexec/kexec-elf-core.c | 29 ++++
kexec/kexec-elf-exec.c | 9 -
kexec/kexec-elf-rel.c | 9 -
kexec/kexec-elf.c | 27 ++--
kexec/kexec-elf.h | 17 +-
kexec/kexec.c | 44 ++++++
kexec/kexec.h | 4
purgatory/arch/i386/entry32-16-debug.S | 20 +--
purgatory/arch/i386/include/arch/debug.h | 2
purgatory/arch/i386/linux-entry16.S | 44 +++---
purgatory/arch/x86_64/include/arch/debug.h | 2
23 files changed, 345 insertions(+), 96 deletions(-)
--- NEW FILE kexec-tools-1.101-reloc-update.patch ---
--- kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S.orig 2004-12-20 05:48:45.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S 2006-12-01 15:05:42.000000000 -0500
@@ -127,10 +127,10 @@
TTYS0_TX_AL
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#else
-#define DEBUG(x)
+#define DEBUG_CHAR(x)
#define DEBUG_TX_HEX32(x)
#endif
@@ -142,15 +142,15 @@
entry16:
.code32
-DEBUG('a')
+DEBUG_CHAR('a')
/* Setup the classic BIOS interrupt table at 0x0 */
lidt idtptr
-DEBUG('b')
+DEBUG_CHAR('b')
/* Provide us with 16bit segments that we can use */
lgdt gdt
-DEBUG('c')
+DEBUG_CHAR('c')
/* Note we don't disable the a20 line, (this shouldn't be required)
* The code to do it is in kexec_test and it is a real pain.
* I will worry about that when I need it.
@@ -164,26 +164,26 @@
movl %eax, %fs
movl %eax, %gs
-DEBUG('d')
+DEBUG_CHAR('d')
/* switch to 16bit mode */
ljmp $0x08, $1f - entry16
1:
.code16
-DEBUG('e')
+DEBUG_CHAR('e')
/* Disable Paging and protected mode */
/* clear the PG & PE bits of CR0 */
movl %cr0,%eax
andl $~((1 << 31)|(1<<0)),%eax
movl %eax,%cr0
-DEBUG('f')
+DEBUG_CHAR('f')
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
ljmp *(realptr - entry16)
3:
-DEBUG('g')
+DEBUG_CHAR('g')
/* we are in real mode now
* set up the real mode segment registers : %ds, $ss, %es
*/
@@ -191,7 +191,7 @@
movw %cs, %ax
movw %ax, %ds
-DEBUG('h')
+DEBUG_CHAR('h')
/* Load the registers */
movl eax - entry16, %eax
movl ebx - entry16, %ebx
@@ -386,10 +386,10 @@
TTYS0_TX_AL
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#else
-#define DEBUG(x)
+#define DEBUG_CHAR(x)
#define DEBUG_TX_HEX32(x)
#endif
@@ -403,7 +403,7 @@
_reloc = .
.balign 16
.code32
-DEBUG('a')
+DEBUG_CHAR('a')
/* Compute where I am running at */
call 1f
1: popl %ebx
@@ -412,13 +412,13 @@
/* Remember where I am running at */
movl %ebx, location - _reloc(%ebx)
-DEBUG('b')
+DEBUG_CHAR('b')
/* Fixup my real mode segment */
movl %ebx, %eax
shrl $4, %eax
movw %ax, 2 + realptr - _reloc(%ebx)
-DEBUG('c')
+DEBUG_CHAR('c')
/* Fixup the gdt */
movl %ebx, %eax
shll $16, %eax
@@ -440,7 +440,7 @@
-DEBUG('d')
+DEBUG_CHAR('d')
/* Setup the classic BIOS interrupt table at 0x0 */
lidt idtptr - _reloc(%ebx)
@@ -465,20 +465,20 @@
ljmp $0x08, $2f - _reloc
2:
.code16
-DEBUG('e')
+DEBUG_CHAR('e')
/* Disable Paging and protected mode */
/* clear the PG & PE bits of CR0 */
movl %cr0,%eax
andl $~((1 << 31)|(1<<0)),%eax
movl %eax,%cr0
-DEBUG('f')
+DEBUG_CHAR('f')
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
ljmp *(realptr - _reloc)
3:
-DEBUG('g')
+DEBUG_CHAR('g')
/* we are in real mode now
* set up the real mode segment registers : %ds, $ss, %es
*/
@@ -486,7 +486,7 @@
movw %cs, %ax
movw %ax, %ds
-DEBUG('h')
+DEBUG_CHAR('h')
/* Load the registers */
movl eax - _reloc, %eax
movl ebx - _reloc, %ebx
@@ -600,7 +600,7 @@
setup16_debug_kernel_pre_protected:
.code16
- DEBUG('i')
+ DEBUG_CHAR('i')
cli # no interrupts allowed !
movb $0x80, %al # disable NMI for bootup
# sequence
@@ -611,7 +611,7 @@
.byte 0xbf /* movl $0x12345678, %edi */
location:
.long 0x12345678
- DEBUG('j')
+ DEBUG_CHAR('j')
.byte 0xb8 /* movl $0x10000, %eax */
setup16_debug_old_code32:
.long 0x10000
--- kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h.orig 2004-12-20 18:03:17.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h 2006-12-01 15:05:42.000000000 -0500
@@ -311,6 +311,6 @@
TTYS0_TX_AL
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
--- kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S.orig 2004-12-20 18:11:43.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S 2006-12-01 15:05:42.000000000 -0500
@@ -55,15 +55,15 @@
orl %ecx, 0x14 + gdt
-DEBUG('a')
+DEBUG_CHAR('a')
/* Setup the classic BIOS interrupt table at 0x0 */
lidt idtptr
-DEBUG('b')
+DEBUG_CHAR('b')
/* Provide us with 16bit segments that we can use */
lgdt gdt
-DEBUG('c')
+DEBUG_CHAR('c')
/* Note we don't disable the a20 line, (this shouldn't be required)
* The code to do it is in kexec_test and it is a real pain.
* I will worry about that when I need it.
@@ -77,26 +77,26 @@
movl %eax, %fs
movl %eax, %gs
-DEBUG('d')
+DEBUG_CHAR('d')
/* switch to 16bit mode */
ljmp $0x08, $1f - entry16_debug
1:
.code16
-DEBUG('e')
+DEBUG_CHAR('e')
/* Disable Paging and protected mode */
/* clear the PG & PE bits of CR0 */
movl %cr0,%eax
andl $~((1 << 31)|(1<<0)),%eax
movl %eax,%cr0
-DEBUG('f')
+DEBUG_CHAR('f')
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
ljmp *(realptr - entry16_debug)
3:
-DEBUG('g')
+DEBUG_CHAR('g')
/* we are in real mode now
* set up the real mode segment registers : %ds, $ss, %es
*/
@@ -104,7 +104,7 @@
movw %cs, %ax
movw %ax, %ds
-DEBUG('h')
+DEBUG_CHAR('h')
/* Load the registers */
movl eax - entry16_debug, %eax
movl ebx - entry16_debug, %ebx
@@ -176,7 +176,7 @@
.text
entry16_debug_pre32:
.code16
-DEBUG('i')
+DEBUG_CHAR('i')
cli # no interrupts allowed !
movb $0x80, %al # disable NMI for bootup
# sequence
@@ -186,7 +186,7 @@
entry16_debug_first32:
.code32
-DEBUG('j')
+DEBUG_CHAR('j')
.byte 0xb8 /* movl $0x10000, %eax */
entry16_debug_old_first32:
.long 0x100000
--- kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h.orig 2004-12-20 18:05:40.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h 2006-12-01 15:05:42.000000000 -0500
@@ -311,7 +311,7 @@
TTYS0_TX_AL
-#define DEBUG(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ; TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
#define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ; TTYS0_TX_CHAR($'\n')
--- kexec-tools-1.101/kexec/kexec.h.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.h 2006-12-01 15:05:42.000000000 -0500
@@ -116,6 +116,9 @@
struct mem_ehdr rhdr;
unsigned long backup_start;
unsigned long kexec_flags;
+ unsigned long kern_vaddr_start;
+ unsigned long kern_paddr_start;
+ unsigned long kern_size;
};
void usage(void);
@@ -177,6 +180,7 @@
extern void *xmalloc(size_t size);
extern void *xrealloc(void *ptr, size_t size);
extern char *slurp_file(const char *filename, off_t *r_size);
+extern char *slurp_file_len(const char *filename, off_t size);
extern char *slurp_decompress_file(const char *filename, off_t *r_size);
extern void add_segment(struct kexec_info *info,
const void *buf, size_t bufsz, unsigned long base, size_t memsz);
--- kexec-tools-1.101/kexec/Makefile.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/Makefile 2006-12-01 15:05:42.000000000 -0500
@@ -13,6 +13,7 @@
KEXEC_C_SRCS+= kexec/ifdown.c
KEXEC_C_SRCS+= kexec/kexec-elf.c
KEXEC_C_SRCS+= kexec/kexec-elf-exec.c
+KEXEC_C_SRCS+= kexec/kexec-elf-core.c
KEXEC_C_SRCS+= kexec/kexec-elf-rel.c
KEXEC_C_SRCS+= kexec/kexec-elf-boot.c
KEXEC_C_SRCS+= kexec/crashdump.c
--- kexec-tools-1.101/kexec/kexec-elf-exec.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-exec.c 2006-12-01 15:05:42.000000000 -0500
@@ -11,11 +11,12 @@
static const int probe_debug = 0;
-int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
{
struct mem_phdr *phdr, *end_phdr;
int result;
- result = build_elf_info(buf, len, ehdr);
+ result = build_elf_info(buf, len, ehdr, flags);
if (result < 0) {
return result;
}
@@ -136,11 +137,11 @@
}
void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
- const char *buf, off_t len)
+ const char *buf, off_t len, uint32_t flags)
{
int result;
/* Parse the Elf file */
- result = build_elf_exec_info(buf, len, ehdr);
+ result = build_elf_exec_info(buf, len, ehdr, flags);
if (result < 0) {
die("ELF exec parse failed\n");
}
--- kexec-tools-1.101/kexec/kexec.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.c 2006-12-01 15:05:42.000000000 -0500
@@ -391,6 +391,50 @@
return buf;
}
+/* This functions reads either specified number of bytes from the file or
+ lesser if EOF is met. */
+
+char *slurp_file_len(const char *filename, off_t size)
+{
+ int fd;
+ char *buf;
+ off_t progress;
+ ssize_t result;
+
+ if (!filename)
+ return 0;
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open %s: %s\n", filename,
+ strerror(errno));
+ return 0;
+ }
+ buf = xmalloc(size);
+ progress = 0;
+ while(progress < size) {
+ result = read(fd, buf + progress, size - progress);
+ if (result < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ fprintf(stderr, "read on %s of %ld bytes failed: %s\n",
+ filename, (size - progress)+ 0UL,
+ strerror(errno));
+ free(buf);
+ return 0;
+ }
+ if (result == 0)
+ /* EOF */
+ break;
+ progress += result;
+ }
+ result = close(fd);
+ if (result < 0) {
+ die("Close of %s failed: %s\n",
+ filename, strerror(errno));
+ }
+ return buf;
+}
+
#if HAVE_ZLIB_H
char *slurp_decompress_file(const char *filename, off_t *r_size)
{
--- kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c 2006-12-01 15:05:42.000000000 -0500
@@ -133,7 +133,7 @@
* it's gdt.
*/
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- 0x3000, 640*1024, -1);
+ 0x3000, 640*1024, -1, 0);
/* The argument/parameter segment */
setup_size = kern16_size + command_line_len;
--- kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c 2006-12-01 15:05:42.000000000 -0500
@@ -209,10 +209,11 @@
/* Load the ELF executable */
- elf_exec_build_load(info, &ehdr, buf, len);
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
/* Load the setup code */
- elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0, ULONG_MAX, 1);
+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0,
+ ULONG_MAX, 1, 0);
/* The first segment will contain the multiboot headers:
* =============
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c 2006-12-01 15:05:42.000000000 -0500
@@ -47,7 +47,7 @@
struct mem_ehdr ehdr;
int result;
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
if (probe_debug) {
fprintf(stderr, "Not an ELF executable\n");
@@ -177,7 +177,7 @@
}
/* Load the ELF executable */
- elf_exec_build_load(info, &ehdr, buf, len);
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
entry = ehdr.e_entry;
max_addr = elf_max_addr(&ehdr);
@@ -186,7 +186,7 @@
if (arg_style != ARG_STYLE_NONE) {
/* Load the setup code */
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- 0, ULONG_MAX, 1);
+ 0, ULONG_MAX, 1, 0);
}
if (arg_style == ARG_STYLE_NONE) {
info->entry = (void *)entry;
--- kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c.orig 2005-01-20 14:10:56.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c 2006-12-01 15:05:42.000000000 -0500
@@ -72,7 +72,7 @@
struct mem_ehdr ehdr;
int result;
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
goto out;
}
@@ -180,7 +180,7 @@
}
/* Parse the Elf file */
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
free_elf_info(&ehdr);
return result;
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c 2006-12-01 15:05:42.000000000 -0500
@@ -64,7 +64,7 @@
continue;
str = line + consumed;
end = end + 1;
-#if 0
+#ifdef DEBUG
printf("%016Lx-%016Lx : %s",
start, end, str);
#endif
@@ -104,7 +104,7 @@
memory_range[memory_ranges].start = start;
memory_range[memory_ranges].end = end;
memory_range[memory_ranges].type = type;
-#if 0
+#ifdef DEBUG
printf("%016Lx-%016Lx : %x\n",
start, end, type);
#endif
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c 2006-12-01 15:05:42.000000000 -0500
@@ -47,7 +47,7 @@
struct mem_ehdr ehdr;
int result;
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
if (probe_debug) {
fprintf(stderr, "Not an ELF executable\n");
@@ -177,7 +177,7 @@
}
/* Load the ELF executable */
- elf_exec_build_load(info, &ehdr, buf, len);
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
entry = ehdr.e_entry;
max_addr = elf_max_addr(&ehdr);
@@ -186,7 +186,7 @@
if (arg_style != ARG_STYLE_NONE) {
/* Load the setup code */
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- 0, ULONG_MAX, 1);
+ 0, ULONG_MAX, 1, 0);
}
if (arg_style == ARG_STYLE_NONE) {
info->entry = (void *)entry;
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c.orig 2004-12-21 12:51:24.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2006-12-01 15:05:42.000000000 -0500
@@ -60,7 +60,7 @@
void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
void *location, unsigned long address, unsigned long value)
{
-#if 0
+#ifdef DEBUG
fprintf(stderr, "%s\n", reloc_name(r_type));
#endif
switch(r_type) {
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c 2006-12-01 15:05:42.000000000 -0500
@@ -24,8 +24,10 @@
#include <errno.h>
#include <limits.h>
#include <elf.h>
+#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <unistd.h>
#include "../../kexec.h"
#include "../../kexec-elf.h"
@@ -40,6 +42,137 @@
/* Forward Declaration. */
static int exclude_crash_reserve_region(int *nr_ranges);
+#define KERN_VADDR_ALIGN 0x200000 /* 2MB */
+
+/* Read kernel physical load addr from /proc/iomem (Kernel Code) and
+ * store in kexec_info */
+static int get_kernel_paddr(struct kexec_info *info)
+{
+ const char iomem[]= "/proc/iomem";
+ char line[MAX_LINE];
+ FILE *fp;
+ unsigned long long start, end;
+
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ char *str;
+ int consumed, count;
+ count = sscanf(line, "%Lx-%Lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+#ifdef DEBUG
+ printf("%016Lx-%016Lx : %s",
+ start, end, str);
+#endif
+ if (memcmp(str, "Kernel code\n", 12) == 0) {
+ info->kern_paddr_start = start;
+
+#ifdef DEBUG
+ printf("kernel load physical addr start = 0x%016Lx\n",
+ start);
+#endif
+ fclose(fp);
+ return 0;
+ }
+ }
+ fprintf(stderr, "Cannot determine kernel physical load addr\n");
+ fclose(fp);
+ return -1;
+}
+
+/* Hardcoding kernel virtual address and size. While writting
+ * this patch vanilla kernel is compiled for addr 2MB. Anybody
+ * using kernel older than that which was compiled for 1MB
+ * physical addr, use older version of kexec-tools. This function
+ * is there just for backward compatibility reasons and we should
+ * get rid of it at some point of time.
+ */
+
+static int hardcode_kernel_vaddr_size(struct kexec_info *info)
+{
+ fprintf(stderr, "Warning: Hardcoding kernel virtual addr and size\n");
+ info->kern_vaddr_start = __START_KERNEL_map + 0x200000;
+ info->kern_size = KERNEL_TEXT_SIZE - 0x200000;
+ fprintf(stderr, "Warning: virtual addr = 0x%lx size = 0x%lx\n",
+ info->kern_vaddr_start, info->kern_size);
+ return 0;
+}
+
+/* Retrieve info regarding virtual address kernel has been compiled for and
+ * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
+ * from kexec-tools fails because of malformed elf notes. A kernel patch has
+ * been submitted. For the folks using older kernels, this function
+ * hard codes the values to remain backward compatible. Once things stablize
+ * we should get rid of backward compatible code. */
+
+static int get_kernel_vaddr_and_size(struct kexec_info *info)
+{
+ int result;
+ const char kcore[] = "/proc/kcore";
+ char *buf;
+ struct mem_ehdr ehdr;
+ struct mem_phdr *phdr, *end_phdr;
+ int align;
+ unsigned long size;
+ uint32_t elf_flags = 0;
+
+ align = getpagesize();
+ size = KCORE_ELF_HEADERS_SIZE;
+ buf = slurp_file_len(kcore, size);
+ if (!buf) {
+ fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
+ return -1;
+ }
+
+ /* Don't perform checks to make sure stated phdrs and shdrs are
+ * actually present in the core file. It is not practical
+ * to read the GB size file into a user space buffer, Given the
+ * fact that we don't use any info from that.
+ */
+ elf_flags |= ELF_SKIP_FILESZ_CHECK;
+ result = build_elf_core_info(buf, size, &ehdr, elf_flags);
+ if (result < 0) {
+ fprintf(stderr, "ELF core (kcore) parse failed\n");
+ hardcode_kernel_vaddr_size(info);
+ return 0;
+ }
+
+ /* Traverse through the Elf headers and find the region where
+ * kernel is mapped. */
+ end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
+ for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
+ if (phdr->p_type == PT_LOAD) {
+ unsigned long saddr = phdr->p_vaddr;
+ unsigned long eaddr = phdr->p_vaddr + phdr->p_memsz;
+ unsigned long size;
+
+ /* Look for kernel text mapping header. */
+ if ((saddr >= __START_KERNEL_map) &&
+ (eaddr <= __START_KERNEL_map + KERNEL_TEXT_SIZE)) {
+ saddr = (saddr) & (~(KERN_VADDR_ALIGN - 1));
+ info->kern_vaddr_start = saddr;
+ size = eaddr - saddr;
+ /* Align size to page size boundary. */
+ size = (size + align - 1) & (~(align - 1));
+ info->kern_size = size;
+#ifdef DEBUG
+ printf("kernel vaddr = 0x%lx size = 0x%lx\n",
+ saddr, size);
+#endif
+ return 0;
+ }
+ }
+ }
+ fprintf(stderr, "Can't find kernel text map area from kcore\n");
+ return -1;
+}
+
/* Stores a sorted list of RAM memory ranges for which to create elf headers.
* A separate program header is created for backup region */
static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
@@ -245,7 +378,7 @@
memmap_p[j+1] = memmap_p[j];
memmap_p[tidx].start = addr;
memmap_p[tidx].end = addr + size - 1;
-#if 0
+#ifdef DEBUG
printf("Memmap after adding segment\n");
for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
mstart = memmap_p[i].start;
@@ -330,7 +463,7 @@
memmap_p[j-1] = memmap_p[j];
memmap_p[j-1].start = memmap_p[j-1].end = 0;
}
-#if 0
+#ifdef DEBUG
printf("Memmap after deleting segment\n");
for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
mstart = memmap_p[i].start;
@@ -404,7 +537,7 @@
die("Command line overflow\n");
strcat(cmdline, str_mmap);
}
-#if 0
+#ifdef DEBUG
printf("Command line after adding memmap\n");
printf("%s\n", cmdline);
#endif
@@ -432,7 +565,7 @@
if (cmdlen > (COMMAND_LINE_SIZE - 1))
die("Command line overflow\n");
strcat(cmdline, str);
-#if 0
+#ifdef DEBUG
printf("Command line after adding elfcorehdr\n");
printf("%s\n", cmdline);
#endif
@@ -465,7 +598,7 @@
die("Command line overflow\n");
strcat(cmdline, str_mmap);
-#if 0
+#ifdef DEBUG
printf("Command line after adding acpi memmap\n");
printf("%s\n", cmdline);
#endif
@@ -536,6 +669,27 @@
(elf->e_phnum)++;
}
+ /* Setup an PT_LOAD type program header for the region where
+ * Kernel is mapped.
+ */
+ phdr = (Elf64_Phdr *) bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_LOAD;
+ phdr->p_flags = PF_R|PF_W|PF_X;
+ phdr->p_offset = phdr->p_paddr = info->kern_paddr_start;
+ phdr->p_vaddr = info->kern_vaddr_start;
+ phdr->p_filesz = phdr->p_memsz = info->kern_size;
+ phdr->p_align = 0;
+ (elf->e_phnum)++;
+#ifdef DEBUG
+ printf("Kernel text Elf header: p_type = %d, p_offset = 0x%lx "
+ "p_paddr = 0x%lx p_vaddr = 0x%lx "
+ "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+ phdr->p_type, phdr->p_offset, phdr->p_paddr,
+ phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
+
+
/* Setup PT_LOAD type program header for every system RAM chunk.
* A seprate program header for Backup Region*/
for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
@@ -555,21 +709,13 @@
else
phdr->p_offset = mstart;
- /* Handle linearly mapped region.*/
+ /* We already prepared the header for kernel text. Map
+ * rest of the memory segments to kernel linearly mapped
+ * memory region.
+ */
- /* Filling the vaddr conditionally as we have two linearly
- * mapped regions here. One is __START_KERNEL_map 0 to 40 MB
- * other one is PAGE_OFFSET */
-
- if ((mend <= (MAXMEM - 1)) && mstart < KERNEL_TEXT_SIZE)
- phdr->p_vaddr = mstart + __START_KERNEL_map;
- else {
- if (mend <= (MAXMEM - 1))
- phdr->p_vaddr = mstart + PAGE_OFFSET;
- else
- phdr->p_vaddr = -1ULL;
- }
phdr->p_paddr = mstart;
+ phdr->p_vaddr = mstart + PAGE_OFFSET;
phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
/* Do we need any alignment of segments? */
phdr->p_align = 0;
@@ -593,6 +739,12 @@
long int nr_cpus = 0;
struct memory_range *mem_range, *memmap_p;
+ if (get_kernel_paddr(info))
+ return -1;
+
+ if (get_kernel_vaddr_and_size(info))
+ return -1;
+
if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
return -1;
@@ -638,7 +790,7 @@
* This is a makeshift solution until it is fixed in kernel.
*/
elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
- max_addr, 1);
+ max_addr, -1);
if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
return -1;
cmdline_add_memmap(mod_cmdline, memmap_p);
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c 2006-12-01 15:05:42.000000000 -0500
@@ -56,7 +56,7 @@
{
struct mem_ehdr ehdr;
int result;
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
if (probe_debug) {
fprintf(stderr, "Not an ELF executable\n");
@@ -163,7 +163,7 @@
}
/* Parse the Elf file */
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
fprintf(stderr, "ELF parse failed\n");
free_elf_info(&ehdr);
@@ -198,7 +198,7 @@
/* Load the setup code */
elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
- 0x0, ULONG_MAX, -1);
+ 0x0, ULONG_MAX, -1, 0);
if (load_crashdump_segments(info, &ehdr, max_addr, 0,
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c 2006-12-01 15:05:42.000000000 -0500
@@ -52,7 +52,7 @@
{
struct mem_ehdr ehdr;
int result;
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
goto out;
}
@@ -163,7 +163,7 @@
}
/* Parse the Elf file */
- result = build_elf_exec_info(buf, len, &ehdr);
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
if (result < 0) {
free_elf_info(&ehdr);
return result;
@@ -213,7 +213,7 @@
memcpy(seg_buf, purgatory, purgatory_size);
seg_size = purgatory_size;
elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
- purgatory_size, 0, max_addr, 1);
+ purgatory_size, 0, max_addr, 1, 0);
/* Add a ram-disk to the current image
* Note: Add the ramdisk after elf_rel_build_load
--- kexec-tools-1.101/kexec/kexec-elf-rel.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-rel.c 2006-12-01 15:05:42.000000000 -0500
@@ -135,10 +135,11 @@
return rela;
}
-int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
{
int result;
- result = build_elf_info(buf, len, ehdr);
+ result = build_elf_info(buf, len, ehdr, flags);
if (result < 0) {
return result;
}
@@ -412,12 +413,12 @@
void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
const char *buf, off_t len, unsigned long min, unsigned long max,
- int end)
+ int end, uint32_t flags)
{
int result;
/* Parse the Elf file */
- result = build_elf_rel_info((char *)purgatory, purgatory_size, ehdr);
+ result = build_elf_rel_info(buf, len, ehdr, flags);
if (result < 0) {
die("ELF rel parse failed\n");
}
--- /dev/null 2006-11-22 10:18:18.589138000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-core.c 2006-12-01 15:05:42.000000000 -0500
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "elf.h"
+#include "kexec-elf.h"
+
+
+int build_elf_core_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
+{
+ int result;
+ result = build_elf_info(buf, len, ehdr, flags);
+ if (result < 0) {
+ return result;
+ }
+ if ((ehdr->e_type != ET_CORE)) {
+ /* not an ELF Core */
+ fprintf(stderr, "Not ELF type ET_CORE\n");
+ return -1;
+ }
+ if (!ehdr->e_phdr) {
+ /* No program header */
+ fprintf(stderr, "No ELF program header\n");
+ return -1;
+ }
+
+ return 0;
+}
--- kexec-tools-1.101/kexec/crashdump.h.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/crashdump.h 2006-12-01 15:05:42.000000000 -0500
@@ -5,5 +5,7 @@
/* Need to find a better way to determine per cpu notes section size. */
#define MAX_NOTE_BYTES 1024
+/* Expecting ELF headers to fit in 4K. Increase it if you need more. */
+#define KCORE_ELF_HEADERS_SIZE 4096
#endif /* CRASHDUMP_H */
--- kexec-tools-1.101/kexec/kexec-elf.c.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf.c 2006-12-01 15:05:42.000000000 -0500
@@ -368,7 +368,8 @@
return 0;
}
-static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
{
size_t phdr_size, mem_phdr_size;
int i;
@@ -418,9 +419,11 @@
/* Check the program headers to be certain
* they are safe to use.
+ * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
*/
phdr = &ehdr->e_phdr[i];
- if ((phdr->p_offset + phdr->p_filesz) > len) {
+ if (!(flags & ELF_SKIP_FILESZ_CHECK)
+ && (phdr->p_offset + phdr->p_filesz) > len) {
/* The segment does not fit in the buffer */
if (probe_debug) {
fprintf(stderr, "ELF segment not in file\n");
@@ -580,7 +583,8 @@
return 0;
}
-static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
{
size_t shdr_size, mem_shdr_size;
int i;
@@ -628,11 +632,12 @@
}
/* Check the section headers to be certain
* they are safe to use.
+ * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
*/
shdr = &ehdr->e_shdr[i];
- if ((shdr->sh_type != SHT_NOBITS) &&
- ((shdr->sh_offset + shdr->sh_size) > len))
- {
+ if (!(flags & ELF_SKIP_FILESZ_CHECK)
+ && (shdr->sh_type != SHT_NOBITS)
+ && (shdr->sh_offset + shdr->sh_size) > len) {
/* The section does not fit in the buffer */
if (probe_debug) {
fprintf(stderr, "ELF section %d not in file\n",
@@ -710,7 +715,8 @@
note_size += (hdr.n_descsz + 3) & ~3;
if ((hdr.n_namesz != 0) && (name[hdr.n_namesz -1] != '\0')) {
- die("Note name is not null termiated");
+ fprintf(stderr, "Note name is not null termiated\n");
+ return -1;
}
ehdr->e_note[i].n_type = hdr.n_type;
ehdr->e_note[i].n_name = (char *)name;
@@ -729,7 +735,8 @@
memset(ehdr, 0, sizeof(*ehdr));
}
-int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags)
{
int result;
result = build_mem_ehdr(buf, len, ehdr);
@@ -737,14 +744,14 @@
return result;
}
if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) {
- result = build_mem_phdrs(buf, len, ehdr);
+ result = build_mem_phdrs(buf, len, ehdr, flags);
if (result < 0) {
free_elf_info(ehdr);
return result;
}
}
if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) {
- result = build_mem_shdrs(buf, len, ehdr);
+ result = build_mem_shdrs(buf, len, ehdr, flags);
if (result < 0) {
free_elf_info(ehdr);
return result;
--- kexec-tools-1.101/kexec/kexec-elf.h.orig 2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf.h 2006-12-01 15:05:42.000000000 -0500
@@ -82,22 +82,29 @@
uint32_t n_type; /* Type of the note. */
} ElfNN_Nhdr;
+/* Misc flags */
+#define ELF_SKIP_FILESZ_CHECK 0x00000001
extern void free_elf_info(struct mem_ehdr *ehdr);
-extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
-extern int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
-extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
+extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags);
+extern int build_elf_exec_info(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, uint32_t flags);
+extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+ uint32_t flags);
+extern int build_elf_core_info(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, uint32_t flags);
extern int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info);
extern int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info,
unsigned long min, unsigned long max, int end);
extern void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
- const char *buf, off_t len);
+ const char *buf, off_t len, uint32_t flags);
extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
const char *buf, off_t len, unsigned long min, unsigned long max,
- int end);
+ int end, uint32_t flags);
extern int elf_rel_find_symbol(struct mem_ehdr *ehdr,
const char *name, struct mem_sym *ret_sym);
kexec-tools-1.101-x86_64-crashdump.patch:
arch/x86_64/crashdump-x86_64.c | 97 ++++++++++++++++++++++++++++++++++++-----
kexec.h | 2
2 files changed, 89 insertions(+), 10 deletions(-)
--- NEW FILE kexec-tools-1.101-x86_64-crashdump.patch ---
--- kexec-tools-1.101/kexec/kexec.h.x86_64fix 2006-08-29 19:09:12.000000000 -0400
+++ kexec-tools-1.101/kexec/kexec.h 2006-08-29 19:11:01.000000000 -0400
@@ -116,6 +116,8 @@ struct kexec_info {
struct mem_ehdr rhdr;
unsigned long backup_start;
unsigned long kexec_flags;
+ unsigned long kern_load_addr_start;
+ unsigned long kern_load_addr_end;
};
void usage(void);
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.x86_64fix 2006-08-29 19:07:51.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c 2006-08-29 19:08:22.000000000 -0400
@@ -47,6 +47,53 @@ static struct memory_range crash_memory_
/* Memory region reserved for storing panic kernel and other data. */
static struct memory_range crash_reserved_mem;
+/* Read kernel physical load addr from /proc/iomem (Kernel Code) and
+ * store in kexec_info */
+static int get_kernel_load_addr(struct kexec_info *info)
+{
+ const char iomem[]= "/proc/iomem";
+ char line[MAX_LINE];
+ FILE *fp;
+ unsigned long long start, end;
+
+ fp = fopen(iomem, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
+ return -1;
+ }
+ while(fgets(line, sizeof(line), fp) != 0) {
+ char *str;
+ int consumed, count;
+ count = sscanf(line, "%Lx-%Lx : %n",
+ &start, &end, &consumed);
+ if (count != 2)
+ continue;
+ str = line + consumed;
+#if 0
+ printf("%016Lx-%016Lx : %s",
+ start, end, str);
+#endif
+ if (memcmp(str, "Kernel code\n", 12) == 0) {
+ info->kern_load_addr_start = start;
+
+ /* Currently hardcoding the kernel end to 40MB
+ * This assumption is broken if kernel is compiled for
+ * and address other than START_KERNEL_map
+ */
+ info->kern_load_addr_end = start + KERNEL_TEXT_SIZE;
+#if 0
+ printf("kernel load addr start = 0x%016Lx end = 0x%016Lx\n",
+ start, (start + KERNEL_TEXT_SIZE));
+#endif
+ fclose(fp);
+ return 0;
+ }
+ }
+ fprintf(stderr, "Cannot determine kernel physical load addr\n");
+ fclose(fp);
+ return -1;
+}
+
/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
* create Elf headers. Keeping it separate from get_memory_ranges() as
* requirements are different in the case of normal kexec and crashdumps.
@@ -58,14 +105,18 @@ static struct memory_range crash_reserve
* to look into down the line. May be something like /proc/kernelmem or may
* be zone data structures exported from kernel.
*/
-static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
+static int get_crash_memory_ranges(struct kexec_info *info,
+ struct memory_range **range, int *ranges)
{
const char iomem[]= "/proc/iomem";
- int memory_ranges = 0;
+ int memory_ranges = 0, rc = 0;
char line[MAX_LINE];
FILE *fp;
unsigned long long start, end;
+ if ((rc = get_kernel_load_addr(info)))
+ die("Error while reading the kernel load address\n");
+
fp = fopen(iomem, "r");
if (!fp) {
fprintf(stderr, "Cannot open %s: %s\n",
@@ -83,6 +134,9 @@ static int get_crash_memory_ranges(struc
while(fgets(line, sizeof(line), fp) != 0) {
char *str;
int type, consumed, count;
+ unsigned long kaddr_start = info->kern_load_addr_start;
+ unsigned long kaddr_end = info->kern_load_addr_end;
+
if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
break;
count = sscanf(line, "%Lx-%Lx : %n",
@@ -126,12 +180,18 @@ static int get_crash_memory_ranges(struc
crash_memory_range[memory_ranges].type = type;
memory_ranges++;
- /* Segregate linearly mapped region. */
- if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) {
- crash_memory_range[memory_ranges-1].end = MAXMEM -1;
-
+ /* Segregate kernel text region. Assuming that kernel
+ * text region is not splitted and is part of single memory
+ * chunk.
+ */
+ if ((start <= kaddr_start) && (end >= kaddr_end)) {
+ if ((kaddr_start - start) > 0) {
+ crash_memory_range[memory_ranges-1].end =
+ kaddr_start - 1;
+ }
/* Add segregated region. */
- crash_memory_range[memory_ranges].start = MAXMEM;
+ crash_memory_range[memory_ranges].start =
+ crash_memory_range[memory_ranges - 1].end + 1;
crash_memory_range[memory_ranges].end = end;
crash_memory_range[memory_ranges].type = type;
memory_ranges++;
@@ -532,6 +592,13 @@ static int prepare_crash_memory_elf64_he
/* Increment number of program headers. */
(elf->e_phnum)++;
+#if 0
+ printf("Elf header: p_type = %d, p_offset = 0x%lx "
+ "p_paddr = 0x%lx p_vaddr = 0x%lx "
+ "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+ phdr->p_type, phdr->p_offset, phdr->p_paddr,
+ phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
}
/* Setup PT_LOAD type program header for every system RAM chunk.
@@ -559,8 +626,11 @@ static int prepare_crash_memory_elf64_he
* mapped regions here. One is __START_KERNEL_map 0 to 40 MB
* other one is PAGE_OFFSET */
- if ((mend <= (MAXMEM - 1)) && mstart < KERNEL_TEXT_SIZE)
- phdr->p_vaddr = mstart + __START_KERNEL_map;
+ /* Kernel text mapping reion. */
+ if (mstart == info->kern_load_addr_start) {
+ phdr->p_vaddr = (mstart + __START_KERNEL_map
+ - info->kern_load_addr_start);
+ }
else {
if (mend <= (MAXMEM - 1))
phdr->p_vaddr = mstart + PAGE_OFFSET;
@@ -574,6 +644,13 @@ static int prepare_crash_memory_elf64_he
/* Increment number of program headers. */
(elf->e_phnum)++;
+#if 0
+ printf("Elf header: p_type = %d, p_offset = 0x%lx "
+ "p_paddr = 0x%lx p_vaddr = 0x%lx "
+ "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+ phdr->p_type, phdr->p_offset, phdr->p_paddr,
+ phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
}
return 0;
}
@@ -591,7 +668,7 @@ int load_crashdump_segments(struct kexec
long int nr_cpus = 0;
struct memory_range *mem_range, *memmap_p;
- if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
+ if (get_crash_memory_ranges(info, &mem_range, &nr_ranges) < 0)
return -1;
/* Memory regions which panic kernel can safely use to boot into */
kexec-tools-1.101-x86_64-exactmap.patch:
crashdump-x86_64.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletion(-)
--- NEW FILE kexec-tools-1.101-x86_64-exactmap.patch ---
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.orig 2006-11-14 12:15:45.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c 2006-11-14 12:16:04.000000000 -0500
@@ -113,6 +113,8 @@
* initializing acpi tables in second kernel.
*/
type = RANGE_ACPI;
+ } else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) {
+ type = RANGE_ACPI_NVS;
} else {
continue;
}
@@ -645,7 +647,8 @@
/* Inform second kernel about the presence of ACPI tables. */
for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
unsigned long start, end;
- if (mem_range[i].type != RANGE_ACPI)
+ if ( !( mem_range[i].type == RANGE_ACPI
+ || mem_range[i].type == RANGE_ACPI_NVS) )
continue;
start = mem_range[i].start;
end = mem_range[i].end;
Index: kdump.conf
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.conf,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- kdump.conf 30 Aug 2006 20:34:16 -0000 1.3
+++ kdump.conf 15 Dec 2006 21:05:01 -0000 1.4
@@ -2,31 +2,67 @@
#
# This file contains a series of commands to perform (in order) when a
# kernel crash has happened and the kdump kernel has been loaded
-#
-# The commands are chained together to allow redundancy in case the
-# primary choice is not available at crash time
+#
+# Currently only one dump target and path may be configured at once
+# if the configured dump target fails, the default action will be preformed
+# the default action may be configured with the default directive below
#
# Basics commands supported are:
-# raw <partition> - will dd /proc/vmcore into <partition>
-# <nfs mount> - will mount fs and copy /proc/vmcore to
-# <mnt>/var/crash/%DATE/ , supports DNS
-# <user at location> - will scp /proc/vmcore to
-# <user at location>:/var/crash/%DATE/, supports DNS
-# <fs type> - will mount -t <fs type> /mnt and copy /proc/vmcore to
-# /mnt/var/crash/%DATE/
-# ifc <interface> - instead of bringing up the interface that is normally associated
-# with the next hop of the ip address you plan to use with scp or nfs
-# activate this interface instead. This is sometimes needed in the event
-# that the kdump kernel assigns your interface a different name, given
-# that it only loads the driver needed for the specific interface you are
-# going to use
-# default reboot - if all of the above fail, then reboot the system
-# and accept the /proc/vmcore is lost, else
-# comment out 'default' to fall through and fix
-# the system (if the disk is available)
+# raw <partition> - Will dd /proc/vmcore into <partition>.
+#
+# net <nfs mount> - Will mount fs and copy /proc/vmcore to
+# <mnt>/var/crash/%HOST-%DATE/, supports DNS.
+#
+# net <user at server> - Will scp /proc/vmcore to
+# <user at server>:/var/crash/%HOST-%DATE/, supports DNS
+# NOTE: make sure user has necessary write
+# permissions on server
+#
+# <fs type> <partition> - Will mount -t <fs type> <partition> /mnt and copy
+# /proc/vmcore to /mnt/var/crash/%DATE/.
+# NOTE: <partition> can be a device node, label or uuid.
+#
+# path <path> - Append path to the filesystem device which you are
+# dumping to. Ignored for raw device dumps.
+# If unset, will default to /var/crash.
+#
+# core_collector makedumpfile <options>
+# This directive allows you to use the dump filtering
+# program makedumpfile to retrieve your core, which on
+# some arches can drastically reduce core file size.
+# See /sbin/makedumpfile --help for a list of options.
+# Note that the -i and -g options are not needed here,
+# as the initrd will automatically be populated with
+# a config file appropriate for the running kernel.
+#
+# link_delay <seconds>
+# Some network cards take a long time to initialize, and
+# some spanning tree enabled networks do not transmit
+# user traffic for long periods after a link state
+# changes. This optional parameter defines a wait
+# period after a link is activated in which the
+# initramfs will wait before attempting to transmit
+# user data.
+# default <reboot | shell>
+# if all of the above fail, do the default action.
+# reboot: If the default action is reboot simply reboot
+# the system and loose the core that you are
+# trying to retrieve.
+# shell: If the default action is shell, then drop to
+# an msh session inside the initramfs from
+# where you can try to record the core manually.
+# Exiting this shell reboots the system.
+# NOTE: If no default action is specified, the initramfs
+# will mount the root file system and run init.
#raw /dev/sda5
#ext3 /dev/sda3
-#my.server.com:/export/tmp
-#user at my.server.com
-#default reboot
+#ext3 LABEL=/boot
+#ext3 UUID=03138356-5e61-4ab3-b58e-27507ac41937
+#net my.server.com:/export/tmp
+#net user at my.server.com
+#path /var/crash
+#core_collector makedumpfile -c
+#link_delay 60
+#default shell
+
Index: kdump.init
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.init,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- kdump.init 28 Sep 2006 16:16:04 -0000 1.11
+++ kdump.init 15 Dec 2006 21:05:01 -0000 1.12
@@ -9,7 +9,7 @@
#
# Copyright 2005 Red Hat, Inc.
#
-# chkconfig: 2345 20 80
+# chkconfig: - 20 80
#
# Author: Jeff Moyer <jmoyer at redhat.com>
@@ -28,7 +28,9 @@
KEXEC_ARGS=""
KDUMP_CONFIG_FILE="/etc/kdump.conf"
-standard_kexec_args="-p --args-linux"
+LOGGER="/usr/bin/logger -p info -t kdump"
+
+standard_kexec_args="-p"
if [ -f /etc/sysconfig/kdump ]; then
. /etc/sysconfig/kdump
@@ -39,7 +41,13 @@
coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
mkdir -p $coredir
- cp /proc/vmcore $coredir/vmcore
+ cp /proc/vmcore $coredir/vmcore-incomplete
+ if [ $? == 0 ]; then
+ mv $coredir/vmcore-incomplete $coredir/vmcore
+ $LOGGER "saved a vmcore to $coredir"
+ else
+ $LOGGER "failed to save a vmcore to $coredir"
+ fi
}
function check_config()
@@ -48,24 +56,29 @@
local running_kernel=`uname -r`
kdump_kver=`echo $running_kernel | sed 's/smp//g'`
- kdump_kver="${kdump_kver}kdump"
else
kdump_kver=$KDUMP_KERNELVER
fi
- kdump_kernel="${BOOTDIR}/vmlinux-${kdump_kver}"
- kdump_initrd="${BOOTDIR}/initrd-${kdump_kver}.img"
+ kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
+ kdump_initrd="${KDUMP_BOOTDIR}/initrd-${kdump_kver}kdump.img"
if [ ! -f $kdump_kernel ]; then
echo -n "No kdump kernel image found."; warning; echo
echo "Tried to locate ${kdump_kernel}"
- exit 0
+ return 0
fi
if [ ! -f $kdump_initrd ]; then
echo -n "No kdump initial ramdisk found."; warning; echo
- echo "Tried to locate ${kdump_initrd}"
- return 1
+ echo "Rebuilding $kdump_initrd"
+ /sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+ if [ $? != 0 ]; then
+ echo "Failed to run mkdumprd"
+ $LOGGER "mkdumprd: failed to make kdump initrd"
+ exit 1
+ fi
+ return 0
fi
#check to see if config file has been modified after
@@ -82,17 +95,52 @@
echo "Detected $KDUMP_CONFIG_FILE or $kdump_kernel change"
echo "Rebuilding $kdump_initrd"
/sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+ if [ $? != 0 ]; then
+ echo "Failed to run mkdumprd"
+ $LOGGER "mkdumprd: failed to make kdump initrd"
+ return 1
+ fi
fi
- #hack until we stop making initrd for kdump during rpm install
- #allow initrd 120 seconds to be created before considering it new
- module_time=`stat -c "%Y" /lib/modules/${kdump_kver}`
- let module_time=module_time+120
- if [ ! "$image_time" -gt "$module_time" ]; then
- echo "Detected initial rpm install"
- echo "Rebuilding $kdump_initrd"
- /sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+}
+
+# This function check iomem and determines if we have more than
+# 4GB of ram available. Returns 1 if we do, 0 if we dont
+function need_64bit_headers()
+{
+
+ MEMSZ=`sed -e's/\(^[0-9]\+.*\)/0x\1/' -e's/\(-\)\(.*\)/ 0x\2/' /proc/iomem | \
+ awk 'BEGIN {
+ totalmem=0;
+ segmentmem=0;
+ }
+ /.*RAM.*/ {
+ start = strtonum($1);
+ end = strtonum($2);
+ segmentmem=end-start;
+ totalmem=totalmem+(segmentmem/1024);
+ if (end >= 4194304) {
+ totalmem=totalmem+4194304;
+ }
+ }
+ END {
+ printf "%d", (totalmem+1);
+ }'`
+
+ #The AWK script above computes the total number of KB
+ #in the RAM areas of /proc/iomem
+ #Note also that we set totalmem to 4GB in the event that
+ #any physical address is larger than 4GB. This lets us
+ #default to 64 bit ELF headers for PAE kernels, which
+ #need then to access those higher addresses.
+
+ #This comparison tells us if the above amount is more than
+ #4GB (4096 KB). I do the funny math to avoid overflow
+ if [ $MEMSZ -ge 4194304 ]
+ then
+ return 1
fi
+ return 0
}
# Load the kdump kerel specified in /etc/sysconfig/kdump
@@ -100,54 +148,215 @@
# as the currently running kernel.
function load_kdump()
{
- if [ -z "$KDUMP_COMMANDLINE" ]; then
+
+ if [ -z "$KDUMP_COMMANDLINE" ]
+ then
KDUMP_COMMANDLINE=`cat /proc/cmdline`
- KDUMP_COMMANDLINE=`echo $KDUMP_COMMANDLINE | sed -e 's/crashkernel=[0-9]\+M@[0-9]\+M//g'`
- KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} irqpoll"
fi
+ ARCH=`uname -m`
+ if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
+ then
+
+ need_64bit_headers
+ if [ $? == 1 ]
+ then
+ FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf32-core-headers`
+ if [ -n "$FOUND_ELF_ARGS" ]
+ then
+ echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
+ warning
+ echo
+ else
+ KEXEC_ARGS="$KEXEC_ARGS --elf64-core-headers"
+ fi
+ else
+ FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf64-core-headers`
+ if [ -z "$FOUND_ELF_ARGS" ]
+ then
+ KEXEC_ARGS="$KEXEC_ARGS --elf32-core-headers"
+ fi
+ fi
+ fi
+
+ KDUMP_COMMANDLINE=`echo $KDUMP_COMMANDLINE | sed -e 's/crashkernel=[0-9]\+M@[0-9]\+M//g'`
+ KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}"
+
$KEXEC $KEXEC_ARGS $standard_kexec_args \
--command-line="$KDUMP_COMMANDLINE" \
- --initrd=$kdump_initrd $kdump_kernel
-
+ --initrd=$kdump_initrd $kdump_kernel 2>/dev/null
if [ $? == 0 ]; then
- touch /var/run/kdump.status
+ $LOGGER "kexec: loaded kdump kernel"
+ return 0
+ else
+ $LOGGER "kexec: failed to load kdump kernel"
+ return 1
+ fi
+}
+
+function propagate_ssh_key()
+{
+ #Check if selinux is on... must flip to permissive mode
+ #for the moment to create key, then flip back...
+ se_enforce=`/usr/sbin/sestatus | grep -c "^Current mode.*enforcing"`
+ if [ "$se_enforce" -ge 1 ]; then
+ /usr/sbin/setenforce 0 2>&1 > /dev/null
+ fi
+
+ #Use dedicated key for kdump
+ if [ ! -d /root/.ssh ]; then
+ mkdir /root/.ssh
+ chmod 700 /root/.ssh
+ fi
+ if [ ! -e /root/.ssh/config ]; then
+ echo "IdentityFile ~/.ssh/kdump_id_rsa" >> /root/.ssh/config
+ elif [ `grep -c kdump_id_rsa /root/.ssh/config` -eq 0 ]; then
+ echo "IdentityFile ~/.ssh/kdump_id_rsa" >> /root/.ssh/config
+ fi
+ local KEYFILE=/root/.ssh/kdump_id_rsa.pub
+ local errmsg="Failed to propagate ssh key"
+
+ #make sure they've configured kdump.conf for ssh dumps
+ local SSH_TARGET=`awk '/^\ *net.*@.*$/ {print $0}' $KDUMP_CONFIG_FILE`
+ if [ -z "$SSH_TARGET" ]; then
+ echo "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate"
+ $LOGGER "$errmsg, no ssh config specified in $KDUMP_CONFIG_FILE"
+ exit 1
+ fi
+
+ #Check to see if we already created key, if not, create it.
+ if [ -f $KEYFILE ]; then
+ echo "Using existing keys..."
+ else
+ echo -n "Generating new ssh keys... "
+ /usr/bin/ssh-keygen -t rsa -f /root/.ssh/kdump_id_rsa -N "" 2>&1 > /dev/null
+ echo "done."
fi
+ #If necessary, flip selinux back to enforcing
+ if [ "$se_enforce" -ge 1 ]; then
+ /usr/sbin/setenforce 1 2>&1 > /dev/null
+ fi
+
+ #now find the target ssh user and server to contact.
+ SSH_USER=`echo $SSH_TARGET | cut -d\ -f2 | cut -d@ -f1`
+ SSH_SERVER=`echo $SSH_TARGET | sed -e's/\(.*@\)\(.*$\)/\2/'`
+
+ #now send the found key to the found server
+ cat $KEYFILE | ssh -x $SSH_USER@$SSH_SERVER "mkdir -p ~$SSH_USER/.ssh; chmod 700 ~$SSH_USER/.ssh; cat >> ~$SSH_USER/.ssh/authorized_keys2"
+ RET=$?
+ if [ $RET == 0 ]; then
+ echo $KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys2 on $SSH_SERVER
+ $LOGGER "propagated ssh key (ssh server: $SSH_SERVER)"
+ return 0
+ else
+ echo $KEYFILE failed in transfer to $SSH_SERVER
+ $LOGGER "$errmsg, unable to transfer $KEYFILE to $SSH_SERVER"
+ exit 1
+ fi
+
+}
+
+function status()
+{
+ if [ ! -e /sys/kernel/kexec_crash_loaded ]
+ then
+ return 2
+ fi
+ rc=`cat /sys/kernel/kexec_crash_loaded`
+ if [ $rc == 1 ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+function start()
+{
+ #TODO check raw partition for core dump image
+ status
+ rc=$?
+ if [ $rc == 2 ]; then
+ echo -n "Kdump is not supported on this kernel"; failure; echo
+ return 1;
+ else
+ if [ $rc == 0 ]; then
+ echo -n "Kdump already running"; success; echo
+ return 0
+ fi
+ fi
+ check_config
+ if [ $? != 0 ]; then
+ echo -n "Starting kdump:"; failure; echo
+ $LOGGER "failed to start up, config file incorrect"
+ return 1
+ fi
+ load_kdump
+ if [ $? != 0 ]; then
+ echo -n "Starting kdump:"; failure; echo
+ $LOGGER "failed to start up"
+ return 1
+ fi
+
+ echo -n "Starting kdump:"; success; echo
+ $LOGGER "started up"
+}
+
+function stop()
+{
+ $KEXEC -p -u 2>/dev/null
+ if [ $? == 0 ]; then
+ $LOGGER "kexec: unloaded kdump kernel"
+ echo -n "Stopping kdump:"; success; echo
+ $LOGGER "stopped"
+ else
+ $LOGGER "kexec: failed to unload kdump kernel"
+ echo -n "Stopping kdump:"; failure; echo
+ $LOGGER "failed to stop"
+ fi
}
case "$1" in
start)
- if [ -f /proc/vmcore ]; then
- save_core
- reboot
- else
- #TODO check raw partition for core dump image
- check_config
- load_kdump
+ if [ -s /proc/vmcore ]; then
+ save_core
+ reboot
+ else
+ start
fi
;;
stop)
- $KEXEC -p -u
- rm -f /var/run/kdump.status
+ stop
;;
status)
- if [ -a /var/run/kdump.status ]; then
+ EXIT_CODE=0
+ status
+ case "$?" in
+ 0)
echo "Kdump is operational"
- else
+ ;;
+ 1)
echo "Kdump is not operational"
- fi
+ EXIT_CODE=1
+ ;;
+ 2)
+ echo "Kdump is unsupported on this kernel"
+ EXIT_CODE=1
+ ;;
+ esac
+ exit $EXIT_CODE
;;
restart)
- $KEXEC -p -u
- rm -f /var/run/kdump.status
- check_config
- load_kdump
+ stop
+ start
;;
condrestart)
;;
+ propagate)
+ propagate_ssh_key
+ ;;
*)
- echo $"Usage: $0 {start|stop|status|restart}"
+ echo $"Usage: $0 {start|stop|status|restart|propagate}"
exit 1
esac
Index: kdump.sysconfig
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.sysconfig,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- kdump.sysconfig 5 Jul 2006 14:57:41 -0000 1.4
+++ kdump.sysconfig 15 Dec 2006 21:05:01 -0000 1.5
@@ -11,6 +11,10 @@
# /proc/cmdline
KDUMP_COMMANDLINE=""
+# This variable lets us append arguments to the current kdump commandline
+# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
+KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"
+
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
kexec-tools-1.101-Makefile.patch:
Makefile | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
Index: kexec-tools-1.101-Makefile.patch
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools-1.101-Makefile.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- kexec-tools-1.101-Makefile.patch 5 Jul 2006 19:54:50 -0000 1.3
+++ kexec-tools-1.101-Makefile.patch 15 Dec 2006 21:05:01 -0000 1.4
@@ -1,8 +1,8 @@
---- kexec-tools-1.101/Makefile.orig 2006-07-05 15:42:41.000000000 -0400
-+++ kexec-tools-1.101/Makefile 2006-07-05 15:43:09.000000000 -0400
-@@ -44,7 +44,7 @@ PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
-
+--- kexec-tools-1.101/Makefile.orig 2006-10-20 13:42:52.000000000 -0400
++++ kexec-tools-1.101/Makefile 2006-10-20 13:43:22.000000000 -0400
+@@ -45,7 +45,7 @@
MAN_PAGES:= kexec/kexec.8
+ MAN_PAGES+= kdump/kdump.8
BINARIES_i386:= $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump
-BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
+BINARIES_x86_64:= $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump
kexec-tools-1.101-ppc64-usage.patch:
kexec-ppc64.c | 4 ++++
1 files changed, 4 insertions(+)
Index: kexec-tools-1.101-ppc64-usage.patch
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools-1.101-ppc64-usage.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- kexec-tools-1.101-ppc64-usage.patch 22 Aug 2006 14:18:04 -0000 1.1
+++ kexec-tools-1.101-ppc64-usage.patch 15 Dec 2006 21:05:01 -0000 1.2
@@ -1,8 +1,6 @@
-Index: kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c
-===================================================================
---- kexec-tools-1.101.orig/kexec/arch/ppc64/kexec-ppc64.c
-+++ kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c
-@@ -552,6 +552,10 @@ int file_types = sizeof(file_type) / siz
+--- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c.orig 2006-10-20 11:10:39.000000000 -0400
++++ kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c 2006-10-20 11:11:22.000000000 -0400
+@@ -577,6 +577,10 @@
void arch_usage(void)
{
Index: kexec-tools.spec
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools.spec,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -r1.64 -r1.65
--- kexec-tools.spec 28 Sep 2006 16:16:04 -0000 1.64
+++ kexec-tools.spec 15 Dec 2006 21:05:01 -0000 1.65
@@ -1,36 +1,55 @@
Name: kexec-tools
Version: 1.101
-Release: 54%{?dist}
+Release: 55%{?dist}
License: GPL
Group: Applications/System
Summary: The kexec/kdump userspace component.
Source0: %{name}-%{version}.tar.gz
Source1: kdump.init
Source2: kdump.sysconfig
-Source3: mkdumprd
-Source4: kdump.conf
-Source5: kcp.c
-Source6: Makefile.kcp
-Source7: makedumpfile.tar.gz
-Source8: kexec-kdump-howto.txt
+Source3: kdump.sysconfig.x86_64
+Source4: kdump.sysconfig.i386
+Source5: kdump.sysconfig.ppc64
+Source6: kdump.sysconfig.ia64
+Source7: mkdumprd
+Source8: kdump.conf
+Source9: makedumpfile-1.0.7.tar.gz
+Source10: kexec-kdump-howto.txt
+Source11: firstboot_kdump.py
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires(pre): coreutils chkconfig sed busybox ethtool
-BuildRequires: zlib-devel elfutils-libelf-devel glib2-devel pkgconfig
+Requires(pre): coreutils chkconfig sed
+Requires: busybox >= 1.2.0
+BuildRequires: zlib-devel elfutils-libelf-devel glib2-devel pkgconfig elfutils-libelf-devel elfutils-devel
+ExcludeArch: ppc
+%ifarch %{ix86} x86_64 ppc64 ia64
+Obsoletes: diskdumputils netdump
+%endif
#
# Patches 0 through 100 are meant for x86 kexec-tools enablement
#
Patch1: kexec-tools-1.101-kdump.patch
+Patch2: kexec-tools-1.101-elf-core-type.patch
#
# Patches 101 through 200 are meant for x86_64 kexec-tools enablement
#
Patch101: kexec-tools-1.101-disable-kdump-x8664.patch
+Patch102: kexec-tools-1.101-x86_64-exactmap.patch
#
# Patches 201 through 300 are meant for ia64 kexec-tools enablement
#
Patch201: kexec-tools-1.101-ia64-fixup.patch
+Patch202: kexec-tools-1.101-ia64-tools.patch
+Patch203: kexec-tools-1.101-ia64-kdump.patch
+Patch204: kexec-tools-1.101-ia64-EFI.patch
+Patch205: kexec-tools-1.101-ia64-icache-align.patch
+Patch206: kexec-tools-1.101-ia64-noio.patch
+Patch207: kexec-tools-1.101-ia64-phdr-malloc.patch
+Patch208: kexec-tools-1.101-ia64-load-offset.patch
+Patch209: kexec-tools-1.101-ia64-noio-eat.patch
+Patch210: kexec-tools-1.101-ia64-dash-l-fix.patch
#
# Patches 301 through 400 are meant for ppc64 kexec-tools enablement
@@ -39,6 +58,7 @@
Patch302: kexec-tools-1.101-ppc64-usage.patch
Patch303: kexec-tools-1.101-ppc64-cliargs.patch
Patch304: kexec-tools-1.101-ppc64-platform-fix.patch
+Patch305: kexec-tools-1.101-ppc64-64k-pages.patch
#
# Patches 401 through 500 are meant for s390 kexec-tools enablement
@@ -54,12 +74,11 @@
# Patches 601 onward are generic patches
#
Patch601: kexec-tools-1.101-Makefile.patch
-Patch602: kexec-tools-1.101-Makefile-kcp.patch
-Patch603: kexec-tools-1.101-et-dyn.patch
-Patch604: kexec-tools-1.101-add-makedumpfile1.patch
-Patch605: kexec-tools-1.101-add-makedumpfile2.patch
-Patch606: kexec-tools-1.101-makedumpfile-archbuild.patch
-Patch607: kexec-tools-1.101-page_h.patch
+Patch602: kexec-tools-1.101-et-dyn.patch
+Patch603: kexec-tools-1.101-page_h.patch
+Patch604: kexec-tools-1.101-elf-format.patch
+Patch605: kexec-tools-1.101-ifdown.patch
+Patch606: kexec-tools-1.101-reloc-update.patch
%description
kexec-tools provides /sbin/kexec binary that facilitates a new
@@ -72,28 +91,36 @@
%setup -q -n %{name}-%{version}
rm -f ../kexec-tools-1.101.spec
%patch1 -p1
+%patch2 -p1
%patch101 -p1
+%patch102 -p1
%patch201 -p1
+%patch202 -p1
+%patch203 -p1
+%patch204 -p1
+%patch205 -p1
+%patch206 -p1
+%patch207 -p1
+%patch208 -p1
+%patch209 -p1
+%patch210 -p1
%patch301 -p1
%patch302 -p1
%patch303 -p1
%patch304 -p1
+%patch305 -p1
%patch401 -p1
%patch501 -p1
%patch601 -p1
%patch602 -p1
-%patch603 -p1
mkdir -p -m755 kcp
-cp %{SOURCE5} kcp/kcp.c
-cp %{SOURCE6} kcp/Makefile
-mkdir makedumpfile
-tar -C makedumpfile -z -x -v -f %{SOURCE7}
+tar -z -x -v -f %{SOURCE9}
+%patch603 -p1
%patch604 -p1
%patch605 -p1
%patch606 -p1
-%patch607 -p1
%build
%configure \
@@ -103,9 +130,9 @@
%endif
--sbindir=/sbin
rm -f kexec-tools.spec.in
-cp %{SOURCE8} .
+cp %{SOURCE10} .
make
-%ifarch %{ix86} x86_64
+%ifarch %{ix86} x86_64 ia64 ppc64
make -C makedumpfile
%endif
@@ -116,21 +143,41 @@
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
mkdir -p -m755 $RPM_BUILD_ROOT%{_localstatedir}/crash
mkdir -p -m755 $RPM_BUILD_ROOT%{_mandir}/man8/
+mkdir -p -m755 $RPM_BUILD_ROOT%{_docdir}
+mkdir -p -m755 $RPM_BUILD_ROOT%{_datadir}/kdump
install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/kdump
-install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
-install -m 755 %{SOURCE3} $RPM_BUILD_ROOT/sbin/mkdumprd
-install -m 755 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf
+if [ -f $RPM_SOURCE_DIR/kdump.sysconfig.%{_target_cpu} ]; then
+ install -m 644 $RPM_SOURCE_DIR/kdump.sysconfig.%{_target_cpu} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
+else
+ install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
+fi
+install -m 755 %{SOURCE7} $RPM_BUILD_ROOT/sbin/mkdumprd
+install -m 755 %{SOURCE8} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf
install -m 644 kexec/kexec.8 $RPM_BUILD_ROOT%{_mandir}/man8/kexec.8
-%ifarch %{ix86} x86_64
+install -m 755 %{SOURCE11} $RPM_BUILD_ROOT%{_datadir}/kdump/firstboot_kdump.py
+%ifarch %{ix86} x86_64 ia64 ppc64
install -m 755 makedumpfile/makedumpfile $RPM_BUILD_ROOT/sbin/makedumpfile
%endif
-
%clean
rm -rf $RPM_BUILD_ROOT
%post
touch /etc/kdump.conf
/sbin/chkconfig --add kdump
+#This portion of the script is temporary. Its only here
+#to fix up broken boxes that require special settings
+#in /etc/sysconfig/kdump. It will be removed when
+#These systems are fixed.
+
+#This is for HP zx1 machines
+#They require machvec=dig on the kernel command line
+if [ -d /proc/bus/mckinley ]
+then
+ sed -e's/\(^KDUMP_COMMANDLINE_APPEND.*\)\("$\)/\1 machvec=dig"/' \
+ /etc/sysconfig/kdump > /etc/sysconfig/kdump.new
+ mv /etc/sysconfig/kdump.new /etc/sysconfig/kdump
+fi
+
%postun
@@ -145,9 +192,20 @@
fi
exit 0
+%triggerin -- firstboot
+if [ ! -e %{_datadir}/firstboot/modules/firstboot_kdump.py ]
+then
+ ln -s %{_datadir}/kdump/firstboot_kdump.py %{_datadir}/firstboot/modules/firstboot_kdump.py
+fi
+
+
+%triggerun -- firstboot
+rm -f %{_datadir}/firstboot/modules/firstboot_kdump.py
+
%files
%defattr(-,root,root,-)
/sbin/*
+%{_datadir}/kdump
%config(noreplace,missingok) %{_sysconfdir}/sysconfig/kdump
%config(noreplace,missingok) %{_sysconfdir}/kdump.conf
%config %{_sysconfdir}/rc.d/init.d/kdump
@@ -162,22 +220,24 @@
%doc kexec-kdump-howto.txt
%changelog
-* Thu Sep 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-54%{dist}
-- update mkdumprd to use busybox ifup/down infrastructure
-- update initscript file to use chkconfig properly
-
-* Fri Sep 22 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
-- rewrote mkdumprd to use busybox
-
-* Tue Sep 19 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
-- added kdump howto documentation
-
-* Thu Aug 31 2006 Neil Horman <nhorman at redhat.com> - 1.101-51%{dist}
-- update mkdumprd to properly do scp and nfs based dumps
-- update docs in kdump.conf to reflect new ifc parameter
+* Fri Dec 15 2006 Neil Horman <nhorman at redhat.com> - 1.101-5%{dist}
+- Wholesale update of RHEL5 revisions 55-147
+
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-54%{dist}
+- integrate default elf format patch
-* Mon Aug 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-50%{dist}
-- updating to build without need for asm/page.h on x86_64
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-53%{dist}
+- Taking Viveks x86_64 crashdump patch (rcv. via email)
+
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
+- Taking ia64 tools patch for bz 181358
+
+* Mon Aug 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-51%{dist}
+- more doc updates
+- added patch to fix build break from kernel headers change
+
+* Thu Aug 24 2006 Neil Horman <nhorman at redhat.com> - 1.101-50%{dist}
+- repo patch to enable support for relocatable kernels.
* Thu Aug 24 2006 Neil Horman <nhorman at redhat.com> - 1.101-49%{dist}
- rewriting kcp to properly do ssh and scp
@@ -251,11 +311,6 @@
- rebuild
* Wed Jul 07 2006 Neil Horman <nhorman at redhat.com> 1.101-27.fc6
-- Modify spec/sysconfig to not autobuild kdump kernel command line
-- Add dist to revision tag
-- Build for all arches
-
-* Wed Jun 28 2006 Karsten Hopp <karsten at redhat.de> 1.101-20
- Buildrequire zlib-devel
* Thu Jun 22 2006 Neil Horman <nhorman at redhat.com> -1.101-19
Index: mkdumprd
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/mkdumprd,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- mkdumprd 28 Sep 2006 16:16:04 -0000 1.10
+++ mkdumprd 15 Dec 2006 21:05:01 -0000 1.11
@@ -25,6 +25,8 @@
# Guillaume Cottenceau <gc at mandrakesoft.com>
# Peter Jones <pjones at redhat.com>
# Neil Horman <nhorman at redhat.com>
+cmdname=`basename $0`
+
umask 0022
export MALLOC_PERTURB_=204
@@ -66,7 +68,8 @@
vg_list=""
net_list=""
-USING_METHOD="raw"
+USING_METHOD="local_fs"
+SAVE_PATH=/var/crash
vecho()
{
@@ -95,14 +98,14 @@
cmd=error
fi
- $cmd "usage: `basename $0` [--version] [--help] [-v] [-d] [-f] [--preload <module>]"
+ $cmd "usage: $cmdname [--version] [--help] [-v] [-d] [-f] [--preload <module>]"
$cmd " [--force-ide-probe] [--force-scsi-probe | --omit-scsi-modules]"
$cmd " [--image-version] [--force-scsi-probe | --omit-raid-modules]"
$cmd " [--with=<module>] [--force-lvm-probe | --omit-lvm-modules]"
$cmd " [--builtin=<module>] [--omit-dmraid]"
$cmd " [--fstab=<fstab>] [--nocompress] <initrd-image> <kernel-version>"
$cmd ""
- $cmd " (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)"
+ $cmd " (ex: $cmdname /boot/initrd-2.2.5-15.img 2.2.5-15)"
if [ "$1" == "-n" ]; then
exit 0
@@ -233,31 +236,6 @@
fi
}
-finddmmods() {
- line=$(/sbin/dmsetup table "$1" 2>/dev/null)
- [ -z "$line" ] && return 1
- type=$(echo "$line" | awk '{ print $3 }')
- [ -z "$type" ] && return 1
- case "$type" in
- mirror)
- findmodule -dm-mirror
- ;;
- emc)
- findmodule -dm-emc
- findmodule -dm-round-robin
- ;;
- multipath)
- findmodule -dm-multipath
- findmodule -dm-round-robin
- ;;
- crypt)
- findmodule -dm-crypt
- ;;
- zero)
- findmodule -dm-zero
- ;;
- esac
-}
inst() {
if [ "$#" != "2" ];then
@@ -320,7 +298,23 @@
continue ;;
*) handleddevices="$handleddevices $device" ;;
esac
- modalias=$(cat /sys/class/net/$device/device/modalias)
+
+ case "$device" in
+ bond*)
+ modalias=bonding
+ ;;
+ eth*.*)
+ modalias=8021q
+ ;;
+ *)
+ if [ -f /sys/class/net/$device/device/modalias ]
+ then
+ modalias=$(cat /sys/class/net/$device/device/modalias)
+ else
+ modalias=$(ethtool -i $device | awk '/^driver:/ { print $2 }')
+ fi
+ ;;
+ esac
for driver in $(modprobe --set-version $kernel --show-depends $modalias 2>/dev/null| awk '{ print gensub(".*/","","g",$2) }') ; do
findmodule ${driver%%.ko}
done
@@ -367,6 +361,9 @@
handlelvordev() {
local vg=`lvs --noheadings -o vg_name $1 2>/dev/null`
+ if [ -z "$vg" ]; then
+ vg=`lvs --noheadings -o vg_name $(echo $1 | sed -e 's#^/dev/mapper/\([^-]*\)-\(.*\)$#/dev/\1/\2#') 2>/dev/null`
+ fi
if [ -n "$vg" ]; then
vg=`echo $vg` # strip whitespace
case " $vg_list " in
@@ -387,29 +384,56 @@
handlenetdev() {
local dev=$1
cp /etc/sysconfig/network-scripts/ifcfg-$dev $MNTIMAGE/etc
+ BOOTPROTO=""
+ VLAN=""
+ MASTER=""
+ SLAVE=""
. $MNTIMAGE/etc/ifcfg-$dev
findnetdriver $dev
- if [ "$MASTER" == "yes" ]
- then
- #put code here to handle subdevs for a bond
- echo "BUS_ID=\"Bonding\"" >> $MNTIMAGE/etc/ifcfg-$dev
- elif [ "$VLAN" == "yes" ]
- then
- #put code to handle vlan devices
- echo "BUS+Id=\"Vlan\"" >> $MNTIMAGE/etc/ifcfg-$dev
- else
- BUS_ID=`/sbin/ethtool -i $dev | grep bus-info`
- echo "BUS_ID=\"$BUS_ID\"" >> $MNTIMAGE/etc/ifcfg-$dev
- fi
if [ "$BOOTPROTO" == "dhcp" ]
then
echo iface $dev inet dhcp >> $MNTIMAGE/etc/network/interfaces
else
- echo iface $dev inet static address $IPADDR netmask $NETMASK >> $MNTIMAGE/etc/network/interfaces
+ echo iface $dev inet static >> $MNTIMAGE/etc/network/interfaces
+ if [ -n "$IPADDR" ]
+ then
+ echo " " address $IPADDR >> $MNTIMAGE/etc/network/interfaces
+ fi
+ if [ -n "$NETMASK" ]
+ then
+ echo " " netmask $NETMASK >> $MNTIMAGE/etc/network/interfaces
+ fi
fi
+
+ #This lets us recursively handle stacked devices
+ case "$dev" in
+ bond*)
+ #This is a bond, pick up its slaves
+ for j in `cat /sys/class/net/$dev/bonding/slaves`
+ do
+ handlenetdev $j
+ done
+ echo "BUS_ID=\"Bonding\"" >> $MNTIMAGE/etc/ifcfg-$dev
+ ;;
+ *)
+
+ if [ "$VLAN" == "yes" ]
+ then
+ #put code to handle vlan devices
+ echo "BUS_ID=\"Vlan\"" >> $MNTIMAGE/etc/ifcfg-$dev
+ #now make sure we pick up the driver to support the
+ #underlying interface
+ BASE_IFC=`echo $dev | cut -d"." -f1`
+ handlenetdev $BASE_IFC
+ else
+ BUS_ID=`ls -l /sys/class/net/$dev/device | sed -e's/\(.*\/\)\(.*$\)/\2/'`
+ echo "BUS_ID=\"$BUS_ID\"" >> $MNTIMAGE/etc/ifcfg-$dev
+ fi
+ ;;
+ esac
}
while [ $# -gt 0 ]; do
@@ -453,7 +477,7 @@
;;
--version)
- echo "mkinitrd: version $VERSION"
+ echo "$cmdname: version $VERSION"
exit 0
;;
@@ -574,7 +598,7 @@
fi
if [ $UID != 0 ]; then
- error "mkinitrd must be run as root."
+ error "$cmdname must be run as root."
exit 1
fi
@@ -759,8 +783,6 @@
findmodule $n
done
-finddmmods
-
vecho "Using modules:$MODULES"
MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX`
@@ -789,7 +811,7 @@
if [ -n "$UUID" ]; then
UUID="--uuid $UUID"
fi
- emit dm create "$1" $UUID $(/sbin/dmsetup table "$1")
+ emit "echo \"$(/sbin/dmsetup table $1)\" | /sbin/dmsetup.static create \"$1\" $UUID"
}
emitdms()
@@ -805,7 +827,7 @@
emitdm "$NAME"
;;
part)
- emit dm partadd "$NAME"
+ emit /sbin/kpartx.static -pp -a \"/dev/mapper/$NAME\"
;;
esac
done
@@ -833,7 +855,7 @@
#find ethernet device used to route to remote host, ie eth0
netdev=`/sbin/ip route get to $rhost 2>&1`
- [ $? != 0 ] && echo "Bad kdump location: $location" && continue
+ [ $? != 0 ] && echo "Bad kdump location: $location" && exit 1
#the field in the ip output changes if we go to another subnet
OFF_SUBNET=`echo $netdev | grep via`
if [ -n "$OFF_SUBNET" ]
@@ -855,12 +877,10 @@
;;
raw)
USING_METHOD="raw"
- ;;
- ifc)
- KDUMP_IFC=$location
- if [ -n "$network" ]; then
- network=`echo $network | sed -e's/\(^.* \)\('$netdev'\)\( .*$\)/\1 '$KDUMP_IFC' \3/'`
+ if (echo $location | egrep -q "^(LABEL|UUID)="); then
+ location=$(findfs $location)
fi
+ handlelvordev $location
;;
core_collector)
if [ -x /sbin/makedumpfile ]; then
@@ -873,8 +893,26 @@
exit 1
fi
;;
+ path)
+ SAVE_PATH=$location
+ ;;
+ link_delay)
+ LINK_DELAY=$location
+ ;;
+ default)
+ DEFAULT_ACTION=$location
+ ;;
*)
- USING_METHOD="local_fs"
+ IS_COMMENT=`echo $type | grep ^#.*$`
+ if [ -n "$IS_COMMENT" -o -z "$location" ]
+ then
+ #don't process comments or blank line
+ continue
+ fi
+ if (echo $location | egrep -q "^(LABEL|UUID)="); then
+ location=$(findfs $location)
+ fi
+ handlelvordev $location
;;
esac
@@ -899,6 +937,7 @@
mkdir -p $MNTIMAGE/dev
mkdir -p $MNTIMAGE/proc
mkdir -p $MNTIMAGE/sys
+mkdir -p $MNTIMAGE/tmp
mkdir -p $MNTIMAGE/sysroot
mkdir -p $MNTIMAGE/modules
mkdir -p $MNTIMAGE/usr/share/udhcpc
@@ -913,7 +952,15 @@
#if we are using makedumpfile here, then generate the config file
if [ -n "$CORE_COLLECTOR" ]; then
RUN_KERN_VER=`uname -r`
- /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config -x /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux /boot/System.map-$RUN_KERN_VER
+ if [ ! -f /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux ]
+ then
+ echo "kernel-debuginfo-$RUN_KERN_VER is not installed. You need this to use makedumpfile!"
+ echo "please install it and restart the kdump service"
+ rm -rf $MNTIMAGE
+ rm -rf $IMAGE
+ exit 1
+ fi
+ /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config -x /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux > /dev/null
if [ $? != 0 ]; then
echo "could not generate makedumpfile configuration. aborting"
rm -rf $MNTIMAGE
@@ -985,7 +1032,41 @@
#NETWORKING SCRIPT DIRECTORIES
cat >> $MNTIMAGE/etc/network/if-pre-up.d/pre-up-script << EOF
#!/bin/msh
-ifconfig \$IFACE up
+PATH=\$PATH:/scriptfns
+. /etc/ifcfg-\$IFACE
+
+LINK_DELAY=$LINK_DELAY
+if [ "\$BUS_ID" != "Vlan" ]
+then
+ ifconfig \$IFACE up
+ if [ -n "\$LINK_DELAY" ]
+ then
+ echo "\$IFACE Link Up. Waiting \$LINK_DELAY Seconds"
+ sleep \$LINK_DELAY
+ echo "Continuing"
+ fi
+fi
+
+if [ "\$BUS_ID" == "Bonding" ]
+then
+ #this is a bond find and bring up the slaves
+ echo searching for slaves
+ find_activate_slaves \$IFACE
+elif [ "\$BUS_ID" == "Vlan" ]
+then
+ #bring up the base interface first
+ BASE_DEV=\`echo \$IFACE | cut -d"." -f1\`
+ VLAN_ID=\`echo \$IFACE | cut -d"." -f2\`
+ ifconfig \$BASE_DEV up
+ if [ -n "\$LINK_DELAY" ]
+ then
+ echo "\$IFACE Link Up. Waiting \$LINK_DELAY Seconds"
+ sleep \$LINK_DELAY
+ echo "Continuing"
+ fi
+ vconfig add \$BASE_DEV \$VLAN_ID
+ ifconfig \$IFACE up
+fi
exit 0
EOF
@@ -996,6 +1077,7 @@
cat >> $MNTIMAGE/etc/network/if-up.d/up-script << EOF
#!/bin/msh
+PATH=\$PATH:/scriptfns
if [ "\$METHOD" != "dhcp" ]
then
. /etc/ifcfg-\$IFACE
@@ -1017,56 +1099,69 @@
SCRIPTDIR=$MNTIMAGE/scriptfns
mkdir -p $SCRIPTDIR
-cat >> $SCRIPTDIR/rename_interfaces << EOF
+cat >> $SCRIPTDIR/map_interface << EOF
#!/bin/msh
-TMPCNT=0
+if [ -e /tmp/tmpcnt ]
+then
+ TMPCNT=\`cat /tmp/tmpcnt\`
+else
+ TMPCNT=0
+fi
#erase previously recorded map
-rm -f /etc/iface_map
-for i in \`ls /etc/ifcfg-*\`
+RENAMED=""
+REAL_DEV=""
+NETDEV=\$1
+. /etc/ifcfg-\$NETDEV
+for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
do
- RENAMED=""
- REAL_DEV=""
- NETDEV=\`echo \$i | cut -d"-" -f2\`
- for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
- do
- . /etc/ifcfg-\$NETDEV
- case "\$BUS_ID" in
- Bonding)
- #do something for bonding
- ;;
- Vlan)
- #do something for vlan
- ;;
- *)
- INFO=\`ethtool -i \$j | grep bus-info\`
- if [ "\$INFO" == "\$BUS_ID" -a -z "\$REAL_DEV" ]
- then
- REAL_DEV=\$j
- RENAMED="yes"
- fi
- ;;
- esac
- done
+ case "\$BUS_ID" in
+ Bonding)
+ REAL_DEV=bond0
+ RENAMED="yes"
+ ;;
+ Vlan)
+ BASE_DEV=\`echo \$NETDEV | cut -d"." -f1\`
+ VLAN_ID=\`echo \$NETDEV | cut -d"." -f2\`
+ REAL_BASE=\`grep "^\$BASE_DEV " /etc/iface_map | cut -d" " -f2\`
+ #Note we add the \ to our vlan values to escape the . for sed-ability
+ #Note we also convert . to _ to avoid problems with busybox ifup
+ REAL_DEV=\$REAL_BASE\\\\.\$VLAN_ID
+ NETDEV=\$BASE_DEV\\\\.\$VLAN_ID
+ RENAMED="yes"
+ ;;
+ *)
+ INFO=\`ls -l /sys/class/net/\$j/device 2>/dev/null | sed -e's/\\(.*\\/\\)\\(.*$\\)/\\2/'\`
+ if [ "\$INFO" == "\$BUS_ID" -a -z "\$REAL_DEV" ]
+ then
+ REAL_DEV=\$j
+ RENAMED="yes"
+ fi
+ ;;
+ esac
+done
- if [ -z "\$RENAMED" ]
- then
- echo "Could not find a mapping for device \$NETDEV"
- exit 1
- fi
+if [ -z "\$RENAMED" ]
+then
+ echo "Could not find a mapping for device \$NETDEV"
+ exit 1
+fi
- #build the interface rename map
- echo \$NETDEV \$REAL_DEV tmp\$TMPCNT>> /etc/iface_map
- TMPCNT=\`echo \$TMPCNT 1 + p | dc\`
- echo mapping \$NETDEV to \$REAL_DEV
-done
+#build the interface rename map
+echo \$NETDEV \$REAL_DEV tmp\$TMPCNT >> /etc/iface_map
+TMPCNT=\`echo \$TMPCNT 1 + p | dc\`
+echo \$TMPCNT > /tmp/tmpcnt
+echo mapping \$NETDEV to \$REAL_DEV
+EOF
+cat >> $SCRIPTDIR/rename_interfaces << EOF
+#!/bin/msh
MAP_COUNT=\`wc -l /etc/iface_map | cut -d" " -f7 \`
#now do all the renaming - first to temp space
for j in \`seq 1 1 \$MAP_COUNT\`
do
- CURRENT=\`awk '{if (RN == ARGV[j]) print \$1}' /etc/iface_map\`
- NEW=\`awk '{if (RN == ARGV[j]) print \$2}' /etc/iface_map\`
- INTERIM=\`awk '{if (RN == ARGV[j]) print \$3}' /etc/iface_map\`
+ CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$1}' /etc/iface_map\`
+ NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\`
+ INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\`
mv /etc/ifcfg-\$CURRENT /etc/ifcfg-\$INTERIM
for i in /etc/ifcfg-\$INTERIM /etc/iface_to_activate /etc/network/interfaces
do
@@ -1079,9 +1174,9 @@
for j in \`seq 1 1 \$MAP_COUNT\`
do
- CURRENT=\`awk '{if (RN == ARGV[j]) print \$1}' /etc/iface_map\`
- NEW=\`awk '{if (RN == ARGV[j]) print \$2}' /etc/iface_map\`
- INTERIM=\`awk '{if (RN == ARGV[j]) print \$3}' /etc/iface_map\`
+ CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$1}' /etc/iface_map\`
+ NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\`
+ INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\`
mv /etc/ifcfg-\$INTERIM /etc/ifcfg-\$NEW
for i in /etc/ifcfg-\$NEW /etc/iface_to_activate /etc/network/interfaces
do
@@ -1094,6 +1189,23 @@
exit 0
EOF
+cat >> $SCRIPTDIR/find_activate_slaves << EOF
+#!/bin/msh
+BOND_MASTER=\$1
+
+for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
+do
+ MASTER=""
+ . /etc/ifcfg-\$j
+ if [ "\$MASTER" == "\$BOND_MASTER" ]
+ then
+ #this is a slave of the rising interface
+ echo enslaving \$j to \$BOND_MASTER
+ echo +\$j > /sys/class/net/\$BOND_MASTER/bonding/slaves
+ fi
+done
+EOF
+
#DONT ADD STUFF to SCRIPTDIR PAST HERE
for i in `ls $SCRIPTDIR/*`
do
@@ -1156,10 +1268,13 @@
#!/bin/msh
export PATH=$PATH:/scriptfns
mount -t proc /proc /proc
-setquiet
echo Mounting proc filesystem
echo Mounting sysfs filesystem
mount -t sysfs /sys /sys
+echo 1 > /proc/sys/vm/dirty_background_ratio
+echo 5 > /proc/sys/vm/dirty_ratio
+echo 10 > /proc/sys/vm/dirty_writeback_centisecs
+echo 50 > /proc/sys/vm/dirty_expire_centisecs
echo Creating /dev
mount -o mode=0755 -t tmpfs /dev /dev
mkdir /dev/pts
@@ -1232,17 +1347,23 @@
emit "for i in \`ls /sys/block\`; do"
emit " MAJOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f1\`"
emit " MINOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f2\`"
+emit " MINOR_RANGE=\`cat /sys/block/\$i/range | cut -d":" -f2\`"
emit " echo Creating block device \$i"
emit " mknod /dev/\$i b \$MAJOR_NUM \$MINOR_NUM"
-emit " MINOR_END=\`echo \$MINOR_NUM 10 + p | dc\`"
-emit " MINOR_START=\`echo \$MINOR_NUM 1 + p | dc\`"
-emit " for j in \`seq \$MINOR_START 1 \$MINOR_END\`"
-emit " do"
-emit " if [ ! -e /dev/\$i\$j ]"
-emit " then"
-emit " mknod /dev/\$i\$j b \$MAJOR_NUM \$j"
-emit " fi"
-emit " done"
+emit " if [ \"\$MINOR_RANGE\" -gt 1 ]"
+emit " then"
+emit " MINOR_END=\`echo \$MINOR_NUM \$MINOR_RANGE + p | dc\`"
+emit " MINOR_START=\`echo \$MINOR_NUM 1 + p | dc\`"
+emit " PART_NUM=1"
+emit " for j in \`seq \$MINOR_START 1 \$MINOR_END\`"
+emit " do"
+emit " if [ ! -e /dev/\$i\$PART_NUM ]"
+emit " then"
+emit " mknod /dev/\$i\$PART_NUM b \$MAJOR_NUM \$j"
+emit " fi"
+emit " PART_NUM=\`expr \$PART_NUM + 1\`"
+emit " done"
+emit " fi"
emit "done"
if [ -n "$vg_list" ]; then
@@ -1286,7 +1407,7 @@
emit " DM_NUM=\`echo \$DM_NUM 1 + p | dc\`"
emit " if [ -z \"\$noresume\" ]"
emit " then"
- emit " /sbin/dmsetup resume /dev/mapper/\$VGRP-\$i"
+ emit " /sbin/dmsetup.static resume /dev/mapper/\$VGRP-\$i"
emit " fi"
emit " fi"
emit "done"
@@ -1298,15 +1419,31 @@
echo "$KDUMP_CONFIG_FILE: $2"
exit 1
}
- emit "DATE=\`date +%Y-%M-%d-%T\`"
if [ -n "$KDUMP_CONFIG_FILE" ]; then
memtotal=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`
#timezone info for date which outputs YYYY-MM-DD-hh:mm
cp /etc/localtime $MNTIMAGE/etc/localtime
- bin="/sbin/dmsetup /usr/bin/scp /usr/bin/ssh /sbin/ethtool /sbin/mdadm"
+ cp /etc/sysconfig/clock $MNTIMAGE/etc
+ emit ". /etc/clock"
+ emit " if [ \"\$UTC\" == "true" ]"
+ emit " then"
+ emit " TIME_FORMAT=-u"
+ emit " else"
+ emit " TIME_FORMAT=-l"
+ emit "fi"
+ emit "hwclock --hctosys \$TIME_FORMAT"
+ emit "DATE=\`date +%Y-%m-%d-%T\`"
+
+ bin="/sbin/dmsetup.static /sbin/kpartx.static"
+
+ if [ -n "$CORE_COLLECTOR" ]; then
+ bin="$bin /sbin/makedumpfile"
+ fi
+
#ssh, scp require libraries that aren't found with ldd
- lib=/lib && [ -d "/lib64" ] && lib=/lib64
+ ARCH=`uname -m`
+ lib=/lib && [ -d "/lib64" -a "$ARCH" != "ppc64" ] && lib=/lib64
k_extras="/$lib/libnss_compat.so.2 /$lib/libnss_files.so.2"
#traverse the config file and setup each dump location
@@ -1327,21 +1464,40 @@
#setup raw case
emit "echo Saving to partition $location"
emit "dd if=/proc/vmcore of=$location"
- emit "cond reboot -h -f"
+ emit "if [ $? == 0 ]"
+ emit "then"
+ emit " reboot -f"
+ emit "fi"
;;
net)
- if [ -n "$CORE_COLLECTOR" ]; then
- bin="$bin /sbin/makedumpfile"
- fi
-
#build an /etc/passwd for scp to work properly
grep "^root" /etc/passwd > $MNTIMAGE/etc/passwd
# bring up the network
+ emit "for i in \`ls /etc/ifcfg-*\`"
+ emit "do"
+ emit " NETDEV=\`echo \$i | cut -d\"-\" -f2\`"
+ emit " map_interface \$NETDEV"
+ emit "done"
emit "rename_interfaces"
emit "IFACE=\`cat /etc/iface_to_activate\`"
emit "ifup \$IFACE"
+ #lets make sure we're up
+ emit "IFADDR=\`ifconfig \$IFACE | awk '/inet addr/ {print \$2}' | cut -d\":\" -f 2\`"
+ emit "if [ -z \"\$IFADDR\" ]"
+ emit "then"
+ emit " echo \"\$IFACE failed to come up\""
+ if [ "$DEFAULT_ACTION" == "shell" ]
+ then
+ emit " echo \"Dropping to shell. exit to reboot\""
+ emit " /bin/msh"
+ emit " reboot -f"
+ elif [ "$DEFAULT_ACTION" == "reboot" ]
+ then
+ emit " reboot -f"
+ fi
+ emit "fi"
#grab remote host and xlate into numbers
rhost=`echo $location | sed 's/.*@//' | cut -d':' -f1`
need_dns=`echo $rhost|grep [a-zA-Z]`
@@ -1349,9 +1505,17 @@
#find the local ip being used as a route to remote ip
netdev=`/sbin/ip route get to $rhost 2>&1`
- [ $? != 0 ] && echo "Bad kdump location: $location" && continue
- lhost=`echo $netdev|awk '{print $5;}'|head -n 1`
-
+ [ $? != 0 ] && echo "Bad kdump location: $location" && exit 1
+ OFF_SUBNET=`echo $netdev | grep via`
+ if [ -n "$OFF_SUBNET" ]
+ then
+ # we are going to a different subnet
+ lhost=`echo $netdev|awk '{print $7}'|head -n 1`
+ else
+ # we are on the same subnet
+ lhost=`echo $netdev|awk '{print $5}'|head -n 1`
+ fi
+
emit "echo Saving to remote location $location"
if [ -z "`echo $location|grep @`" ]; then
#NFS path
@@ -1360,12 +1524,18 @@
tmnt=`mktemp -dq`
kdump_chk "mount -t nfs -o nolock $rlocation $tmnt" \
"Bad NFS mount $location"
- mkdir -p $tmnt/var/crash
- tdir=`mktemp -dqp $tmnt/var/crash`
+ mkdir -p $tmnt/$SAVE_PATH
+ tdir=`mktemp -dqp $tmnt/$SAVE_PATH`
- rc=$? && rm -rf $tdir && umount $tmnt && rm -rf $tmnt
+ rc=$? && rm -rf $tdir
+ umount $tmnt
+ if [ $? != 0 ]; then
+ echo "Cannot unmount the temporary directory"
+ exit 1
+ fi
+ rm -rf $tmnt
if [ $rc != "0" ]; then
- echo "Cannot create directory in $location: var/crash"
+ echo "Cannot create directory in $location: $SAVE_PATH"
exit 1
fi
@@ -1378,26 +1548,31 @@
#setup nfs case
mkdir -p $MNTIMAGE/mnt
emit "mount -t nfs -o nolock $rlocation /mnt"
- emit "mkdir -p /mnt/var/crash/$lhost-\$DATE"
- emit "$CORE_COLLECTOR /proc/vmcore /mnt/var/crash/$lhost-\$DATE/vmcore"
+ emit "mkdir -p /mnt/$SAVE_PATH/$lhost-\$DATE"
+ emit "$CORE_COLLECTOR /proc/vmcore /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete"
emit "if [ \$? == 0 ]"
emit "then"
+ emit " mv /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore"
+ emit " umount /mnt"
emit " reboot -f"
emit "fi"
emit "umount /mnt"
else
#SSH path
#rebuild $location replacing machine name with ip address
+ bin="$bin /usr/bin/ssh /usr/bin/scp"
rlocation=`echo $location|sed 's/@.*/@'"$rhost"'/'`
#test ssh path and directory creation
s_opts="-o BatchMode=yes -o StrictHostKeyChecking=no"
- kdump_chk "ssh -q $s_opts $rlocation mkdir -p /var/crash/ </dev/null" \
- "Could not create $location:/var/crash, check ssh keys"
- tdir=`ssh -q $s_opts $rlocation mktemp -dqp /var/crash </dev/null`
+ kdump_chk "ssh -q $s_opts $rlocation mkdir -p $SAVE_PATH </dev/null" \
+ "Could not create $location:$SAVE_PATH, you probably need to run \"service kdump propagate\""
+ tdir=`ssh -q $s_opts $rlocation mktemp -dqp $SAVE_PATH </dev/null`
if [ $? != "0" ]; then
- echo "$KDUMP_CONFIG_FILE: Could not create temp directory in $location:/var/crash"
+ echo "$KDUMP_CONFIG_FILE: Could not create temp directory in $location:$SAVE_PATH"
exit 1
fi
+ #We do this to remove the temp directory from above
+ ssh -q $s_opts $rlocation rmdir $tdir
#setup ssh case, quick check to see if setup already
if [ ! -r $MNTIMAGE/dev/urandom ]; then
@@ -1408,38 +1583,32 @@
mknod $MNTIMAGE/dev/urandom c 1 9
fi
emit "dd if=/dev/mem of=/dev/urandom count=1 bs=512 skip=100"
- emit "ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mkdir /var/crash/$lhost-\$DATE"
- emit "scp -q -o BatchMode=yes -o StrictHostKeyChecking=no /proc/vmcore $rlocation:/var/crash/$lhost-\$DATE/vmcore"
+ emit "ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mkdir $SAVE_PATH/$lhost-\$DATE"
+ emit "scp -q -o BatchMode=yes -o StrictHostKeyChecking=no /proc/vmcore $rlocation:$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete"
emit "if [ \$? == 0 ]"
emit "then"
+ emit " ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mv $SAVE_PATH/$lhost-\$DATE/vmcore-incomplete $SAVE_PATH/$lhost-\$DATE/vmcore"
emit " reboot -f"
emit "fi"
fi
;;
- ifc)
- ;;
core_collector)
;;
default)
- [ "$location" == "reboot" ] && emit "reboot -f"
- if [ "$location" == "shell" ]
- then
- emit "echo dropping to initramfs shell"
- emit "echo exiting this shell will reboot your system"
- emit "/bin/msh"
- emit "reboot -f"
- fi
- #else load normally on default failure case
+ ;;
+ link_delay)
+ ;;
+ path)
;;
*)
#test filesystem and directory creation
kdump_chk "test -f /sbin/fsck.$type" "Unsupported type $type"
kdump_chk "mount -t $type $location /mnt" "Bad mount point $location"
- mkdir -p /mnt/var/crash
- tdir=`mktemp -dqp /mnt/var/crash/`
+ mkdir -p /mnt/$SAVE_PATH
+ tdir=`mktemp -dqp /mnt/$SAVE_PATH`
rc=$? && rm -rf $tdir && umount /mnt
if [ $rc != "0" ]; then
- echo "Cannot create directory in $location: /var/crash"
+ echo "Cannot create directory in $location: $SAVE_PATH"
exit 1
fi
#TODO check for available size is greater than $memtotal
@@ -1451,14 +1620,23 @@
CORE_COLLECTOR="cp"
fi
emit "echo Saving to the local filesystem $location"
- emit "fsck.$type $location"
- emit "mount -t $type $location /mnt"
+ emit "DUMPDEV=$location"
+ emit "IS_LABEL=\`echo \$DUMPDEV | grep LABEL\`"
+ emit "IS_UUID=\`echo \$DUMPDEV | grep UUID\`"
+ emit "if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] "
+ emit "then"
+ emit " DUMPDEV=\`findfs \$DUMPDEV\`"
+ emit "fi"
+ emit "fsck.$type \$DUMPDEV"
+ emit "mount -t $type \$DUMPDEV /mnt"
emit "if [ \$? == 0 ]"
emit "then"
- emit " mkdir -p /mnt/var/crash/127.0.0.1-\$DATE"
- emit " $CORE_COLLECTOR /proc/vmcore /mnt/var/crash/127.0.0.1-\$DATE/vmcore"
+ emit " mkdir -p /mnt/$SAVE_PATH/127.0.0.1-\$DATE"
+ emit " $CORE_COLLECTOR /proc/vmcore /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore-incomplete"
emit " if [ \$? == 0 ]"
emit " then"
+ emit " mv /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore-incomplete /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore"
+ emit " umount /mnt"
emit " reboot -f"
emit " fi"
emit "fi"
@@ -1467,6 +1645,18 @@
esac
done < $KDUMP_CONFIG_FILE
+ #now handle the default action
+ if [ "$DEFAULT_ACTION" == "shell" ]
+ then
+ emit "echo dropping to initramfs shell"
+ emit "echo exiting this shell will reboot your system"
+ emit "/bin/msh"
+ emit "reboot -f"
+ elif [ "$DEFAULT_ACTION" == "reboot" ]
+ then
+ emit "reboot -f"
+ fi
+
#find the shared libraries. this snippet taken from kboot
kdump_libs=`for n in $bin; do
ldd "$n" 2>/dev/null | tr -s '\011' ' ' |
@@ -1485,7 +1675,13 @@
emit "ROOTDEV=\`cat /proc/cmdline | grep root=\`"
emit "if [ -n \"\$ROOTDEV\" ]"
emit "then"
-emit " ROOTDEV=\`cat /proc/cmdline | cut -d\" \" -f2 | sed -e's/root=//'\`"
+emit " ROOTDEV=\`cat /proc/cmdline | sed 's/^.*root=//' | cut -d\" \" -f1\`"
+emit " IS_LABEL=\`echo \$ROOTDEV | grep LABEL\`"
+emit " IS_UUID=\`echo \$ROOTDEV | grep UUID\`"
+emit " if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] "
+emit " then"
+emit " ROOTDEV=\`findfs \$ROOTDEV\`"
+emit " fi"
emit "else"
emit " #we need to get the root major/minor from real-root-dev"
emit " ROOT_DEV_NR=\`cat /proc/sys/kernel/real-root-dev\`"
Index: sources
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/sources,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- sources 2 Aug 2006 19:25:03 -0000 1.3
+++ sources 15 Dec 2006 21:05:01 -0000 1.4
@@ -1,2 +1,2 @@
b4f7ffcc294d41a6a4c40d6e44b7734d kexec-tools-1.101.tar.gz
-aa738475824ee3d25e5030fc506366bd makedumpfile.tar.gz
+56fcb4d8e58e22795aeb6c28408916b0 makedumpfile-1.0.7.tar.gz
More information about the fedora-cvs-commits
mailing list