From d3c4b95f8a0babc3588f23a250943def7708d332 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 15 Dec 2006 21:05:01 +0000 Subject: [PATCH] Updating fc7 with all RHEL5 work --- firstboot_kdump.py | 367 ++++++ kdump.conf | 82 +- kdump.init | 289 ++++- kdump.sysconfig | 4 + kdump.sysconfig.i386 | 32 + kdump.sysconfig.ia64 | 32 + kdump.sysconfig.ppc64 | 32 + kdump.sysconfig.x86_64 | 32 + kexec-tools-1.101-Makefile.patch | 8 +- kexec-tools-1.101-elf-core-type.patch | 11 + kexec-tools-1.101-elf-format.patch | 22 + kexec-tools-1.101-ia64-EFI.patch | 281 +++++ kexec-tools-1.101-ia64-dash-l-fix.patch | 125 ++ kexec-tools-1.101-ia64-icache-align.patch | 13 + kexec-tools-1.101-ia64-kdump.patch | 1251 +++++++++++++++++++++ kexec-tools-1.101-ia64-load-offset.patch | 11 + kexec-tools-1.101-ia64-noio-eat.patch | 11 + kexec-tools-1.101-ia64-noio.patch | 252 +++++ kexec-tools-1.101-ia64-phdr-malloc.patch | 19 + kexec-tools-1.101-ia64-tools.patch | 808 +++++++++++++ kexec-tools-1.101-ifdown.patch | 33 + kexec-tools-1.101-ppc64-64k-pages.patch | 111 ++ kexec-tools-1.101-ppc64-usage.patch | 8 +- kexec-tools-1.101-reloc-update.patch | 1051 +++++++++++++++++ kexec-tools-1.101-x86_64-exactmap.patch | 21 + kexec-tools.spec | 145 ++- mkdumprd | 504 ++++++--- sources | 2 +- 28 files changed, 5285 insertions(+), 272 deletions(-) create mode 100755 firstboot_kdump.py create mode 100644 kdump.sysconfig.i386 create mode 100644 kdump.sysconfig.ia64 create mode 100644 kdump.sysconfig.ppc64 create mode 100644 kdump.sysconfig.x86_64 create mode 100644 kexec-tools-1.101-elf-core-type.patch create mode 100644 kexec-tools-1.101-elf-format.patch create mode 100644 kexec-tools-1.101-ia64-EFI.patch create mode 100644 kexec-tools-1.101-ia64-dash-l-fix.patch create mode 100644 kexec-tools-1.101-ia64-icache-align.patch create mode 100644 kexec-tools-1.101-ia64-kdump.patch create mode 100644 kexec-tools-1.101-ia64-load-offset.patch create mode 100644 kexec-tools-1.101-ia64-noio-eat.patch create mode 100644 kexec-tools-1.101-ia64-noio.patch create mode 100644 kexec-tools-1.101-ia64-phdr-malloc.patch create mode 100644 kexec-tools-1.101-ia64-tools.patch create mode 100644 kexec-tools-1.101-ifdown.patch create mode 100644 kexec-tools-1.101-ppc64-64k-pages.patch create mode 100644 kexec-tools-1.101-reloc-update.patch create mode 100644 kexec-tools-1.101-x86_64-exactmap.patch diff --git a/firstboot_kdump.py b/firstboot_kdump.py new file mode 100755 index 0000000..e23c6e3 --- /dev/null +++ b/firstboot_kdump.py @@ -0,0 +1,367 @@ +# +# firstboot_kdump.py - kdump configuration page for firstboot +# Copyright 2006 Red Hat, Inc. +# Author: Jarod Wilson +# Contributors: +# Neil Horman +# Dave Lehman +# +# +# 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 diff --git a/kdump.conf b/kdump.conf index a4938c2..19858ce 100644 --- a/kdump.conf +++ b/kdump.conf @@ -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 - will dd /proc/vmcore into -# - will mount fs and copy /proc/vmcore to -# /var/crash/%DATE/ , supports DNS -# - will scp /proc/vmcore to -# :/var/crash/%DATE/, supports DNS -# - will mount -t /mnt and copy /proc/vmcore to -# /mnt/var/crash/%DATE/ -# ifc - 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 - Will dd /proc/vmcore into . +# +# net - Will mount fs and copy /proc/vmcore to +# /var/crash/%HOST-%DATE/, supports DNS. +# +# net - Will scp /proc/vmcore to +# :/var/crash/%HOST-%DATE/, supports DNS +# NOTE: make sure user has necessary write +# permissions on server +# +# - Will mount -t /mnt and copy +# /proc/vmcore to /mnt/var/crash/%DATE/. +# NOTE: can be a device node, label or uuid. +# +# 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 +# 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 +# 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 +# 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@my.server.com -#default reboot +#ext3 LABEL=/boot +#ext3 UUID=03138356-5e61-4ab3-b58e-27507ac41937 +#net my.server.com:/export/tmp +#net user@my.server.com +#path /var/crash +#core_collector makedumpfile -c +#link_delay 60 +#default shell + diff --git a/kdump.init b/kdump.init index dc98f38..32ca8b2 100644 --- a/kdump.init +++ b/kdump.init @@ -9,7 +9,7 @@ # # Copyright 2005 Red Hat, Inc. # -# chkconfig: 2345 20 80 +# chkconfig: - 20 80 # # Author: Jeff Moyer @@ -28,7 +28,9 @@ KDUMP_COMMANDLINE="" 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 @@ function save_core() 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 @@ function check_config() 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 @@ function check_config() 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 @@ function check_config() # 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 diff --git a/kdump.sysconfig b/kdump.sysconfig index 262e70c..8c9f596 100644 --- a/kdump.sysconfig +++ b/kdump.sysconfig @@ -11,6 +11,10 @@ KDUMP_KERNELVER="" # /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 # diff --git a/kdump.sysconfig.i386 b/kdump.sysconfig.i386 new file mode 100644 index 0000000..34b5f16 --- /dev/null +++ b/kdump.sysconfig.i386 @@ -0,0 +1,32 @@ +# 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="" diff --git a/kdump.sysconfig.ia64 b/kdump.sysconfig.ia64 new file mode 100644 index 0000000..c73cf6e --- /dev/null +++ b/kdump.sysconfig.ia64 @@ -0,0 +1,32 @@ +# 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="" diff --git a/kdump.sysconfig.ppc64 b/kdump.sysconfig.ppc64 new file mode 100644 index 0000000..21db4a5 --- /dev/null +++ b/kdump.sysconfig.ppc64 @@ -0,0 +1,32 @@ +# 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" diff --git a/kdump.sysconfig.x86_64 b/kdump.sysconfig.x86_64 new file mode 100644 index 0000000..34b5f16 --- /dev/null +++ b/kdump.sysconfig.x86_64 @@ -0,0 +1,32 @@ +# 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="" diff --git a/kexec-tools-1.101-Makefile.patch b/kexec-tools-1.101-Makefile.patch index 3487c38..a4e5fed 100644 --- a/kexec-tools-1.101-Makefile.patch +++ b/kexec-tools-1.101-Makefile.patch @@ -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 diff --git a/kexec-tools-1.101-elf-core-type.patch b/kexec-tools-1.101-elf-core-type.patch new file mode 100644 index 0000000..0296076 --- /dev/null +++ b/kexec-tools-1.101-elf-core-type.patch @@ -0,0 +1,11 @@ +--- 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) diff --git a/kexec-tools-1.101-elf-format.patch b/kexec-tools-1.101-elf-format.patch new file mode 100644 index 0000000..446080f --- /dev/null +++ b/kexec-tools-1.101-elf-format.patch @@ -0,0 +1,22 @@ +--- 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; diff --git a/kexec-tools-1.101-ia64-EFI.patch b/kexec-tools-1.101-ia64-EFI.patch new file mode 100644 index 0000000..e88c652 --- /dev/null +++ b/kexec-tools-1.101-ia64-EFI.patch @@ -0,0 +1,281 @@ +--- 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); diff --git a/kexec-tools-1.101-ia64-dash-l-fix.patch b/kexec-tools-1.101-ia64-dash-l-fix.patch new file mode 100644 index 0000000..8419113 --- /dev/null +++ b/kexec-tools-1.101-ia64-dash-l-fix.patch @@ -0,0 +1,125 @@ +--- 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 + #include + #include ++#include + #include + #include "../../kexec.h" + #include "../../kexec-syscall.h" ++#include "elf.h" + #include "kexec-ia64.h" + #include + + 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); diff --git a/kexec-tools-1.101-ia64-icache-align.patch b/kexec-tools-1.101-ia64-icache-align.patch new file mode 100644 index 0000000..fed2601 --- /dev/null +++ b/kexec-tools-1.101-ia64-icache-align.patch @@ -0,0 +1,13 @@ +--- 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"); diff --git a/kexec-tools-1.101-ia64-kdump.patch b/kexec-tools-1.101-ia64-kdump.patch new file mode 100644 index 0000000..80cab6f --- /dev/null +++ b/kexec-tools-1.101-ia64-kdump.patch @@ -0,0 +1,1251 @@ +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 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 ++#include ++#include ++#include ++#include ++#include ++#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 + #include + #include "../../kexec.h" ++#include "../../kexec-syscall.h" + #include "../../kexec-elf.h" ++#include "crashdump-ia64.h" + #include + + 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@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 ++#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@intel.com) ++ * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@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@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 + #include + #include + #include "purgatory-ia64.h" + +-#define PAGE_OFFSET 0xe000000000000000 ++#define PAGE_OFFSET 0xe000000000000000UL ++ ++#define EFI_PAGE_SHIFT 12 ++#define EFI_PAGE_SIZE (1UL<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); ++} +_ diff --git a/kexec-tools-1.101-ia64-load-offset.patch b/kexec-tools-1.101-ia64-load-offset.patch new file mode 100644 index 0000000..c381a19 --- /dev/null +++ b/kexec-tools-1.101-ia64-load-offset.patch @@ -0,0 +1,11 @@ +--- 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 */ diff --git a/kexec-tools-1.101-ia64-noio-eat.patch b/kexec-tools-1.101-ia64-noio-eat.patch new file mode 100644 index 0000000..32fd6d7 --- /dev/null +++ b/kexec-tools-1.101-ia64-noio-eat.patch @@ -0,0 +1,11 @@ +--- 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}, + }; + diff --git a/kexec-tools-1.101-ia64-noio.patch b/kexec-tools-1.101-ia64-noio.patch new file mode 100644 index 0000000..45694cc --- /dev/null +++ b/kexec-tools-1.101-ia64-noio.patch @@ -0,0 +1,252 @@ +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 + +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 +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 + +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 + +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 +-/* 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 + diff --git a/kexec-tools-1.101-ia64-phdr-malloc.patch b/kexec-tools-1.101-ia64-phdr-malloc.patch new file mode 100644 index 0000000..c3f1151 --- /dev/null +++ b/kexec-tools-1.101-ia64-phdr-malloc.patch @@ -0,0 +1,19 @@ +--- 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); diff --git a/kexec-tools-1.101-ia64-tools.patch b/kexec-tools-1.101-ia64-tools.patch new file mode 100644 index 0000000..7ff7a44 --- /dev/null +++ b/kexec-tools-1.101-ia64-tools.patch @@ -0,0 +1,808 @@ +--- 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 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\fP and ++.\" \fI\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 , ++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 ++/* 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@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 ++#include ++#include + #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 + #include + #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 + * Copyright (C) 2004 Khalid Aziz Hewlett Packard Co ++ * Copyright (C) 2005 Zou Nan hai 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include "../../kexec.h" + #include "../../kexec-syscall.h" + #include "kexec-ia64.h" + #include + +-#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 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\fP and + .\" \fI\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= ++Specify the lowest memory addres to load code into. ++.TP ++.B \-\-mem\-max= ++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 , ++This manual page was written by Khalid Aziz , + for the Debian project (but may be used by others). diff --git a/kexec-tools-1.101-ifdown.patch b/kexec-tools-1.101-ifdown.patch new file mode 100644 index 0000000..28111aa --- /dev/null +++ b/kexec-tools-1.101-ifdown.patch @@ -0,0 +1,33 @@ +--- 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(); + } diff --git a/kexec-tools-1.101-ppc64-64k-pages.patch b/kexec-tools-1.101-ppc64-64k-pages.patch new file mode 100644 index 0000000..2ffe7ac --- /dev/null +++ b/kexec-tools-1.101-ppc64-64k-pages.patch @@ -0,0 +1,111 @@ +Signed-off-by: Sachin Sant +--- + +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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include +- +-#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); + } + } diff --git a/kexec-tools-1.101-ppc64-usage.patch b/kexec-tools-1.101-ppc64-usage.patch index a80cfd4..57467d1 100644 --- a/kexec-tools-1.101-ppc64-usage.patch +++ b/kexec-tools-1.101-ppc64-usage.patch @@ -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) { diff --git a/kexec-tools-1.101-reloc-update.patch b/kexec-tools-1.101-reloc-update.patch new file mode 100644 index 0000000..39d8095 --- /dev/null +++ b/kexec-tools-1.101-reloc-update.patch @@ -0,0 +1,1051 @@ +--- 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 + #include + #include ++#include + #include + #include ++#include + #include + #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 ++#include ++#include ++#include ++#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); diff --git a/kexec-tools-1.101-x86_64-exactmap.patch b/kexec-tools-1.101-x86_64-exactmap.patch new file mode 100644 index 0000000..13886ad --- /dev/null +++ b/kexec-tools-1.101-x86_64-exactmap.patch @@ -0,0 +1,21 @@ +--- 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; diff --git a/kexec-tools.spec b/kexec-tools.spec index cdc0e77..255c7ca 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -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 @@ Patch301: kexec-tools-1.101-ppc64-ignore-args.patch 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 @@ Patch501: kexec-tools-1.101-ppc-fixup.patch # 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 @@ component of the kernel's kexec feature. %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 @@ tar -C makedumpfile -z -x -v -f %{SOURCE7} %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}/rc.d/init.d 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 @@ if [ "$1" = 0 ]; then 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 @@ exit 0 %doc kexec-kdump-howto.txt %changelog -* Thu Sep 28 2006 Neil Horman - 1.101-54%{dist} -- update mkdumprd to use busybox ifup/down infrastructure -- update initscript file to use chkconfig properly +* Fri Dec 15 2006 Neil Horman - 1.101-5%{dist} +- Wholesale update of RHEL5 revisions 55-147 -* Fri Sep 22 2006 Neil Horman - 1.101-52%{dist} -- rewrote mkdumprd to use busybox +* Tue Aug 29 2006 Neil Horman - 1.101-54%{dist} +- integrate default elf format patch -* Tue Sep 19 2006 Neil Horman - 1.101-52%{dist} -- added kdump howto documentation +* Tue Aug 29 2006 Neil Horman - 1.101-53%{dist} +- Taking Viveks x86_64 crashdump patch (rcv. via email) -* Thu Aug 31 2006 Neil Horman - 1.101-51%{dist} -- update mkdumprd to properly do scp and nfs based dumps -- update docs in kdump.conf to reflect new ifc parameter +* Tue Aug 29 2006 Neil Horman - 1.101-52%{dist} +- Taking ia64 tools patch for bz 181358 -* Mon Aug 28 2006 Neil Horman - 1.101-50%{dist} -- updating to build without need for asm/page.h on x86_64 +* Mon Aug 28 2006 Neil Horman - 1.101-51%{dist} +- more doc updates +- added patch to fix build break from kernel headers change + +* Thu Aug 24 2006 Neil Horman - 1.101-50%{dist} +- repo patch to enable support for relocatable kernels. * Thu Aug 24 2006 Neil Horman - 1.101-49%{dist} - rewriting kcp to properly do ssh and scp @@ -251,11 +311,6 @@ exit 0 - rebuild * Wed Jul 07 2006 Neil Horman 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 1.101-20 - Buildrequire zlib-devel * Thu Jun 22 2006 Neil Horman -1.101-19 diff --git a/mkdumprd b/mkdumprd index 0e1187b..ac51476 100644 --- a/mkdumprd +++ b/mkdumprd @@ -25,6 +25,8 @@ # Guillaume Cottenceau # Peter Jones # Neil Horman +cmdname=`basename $0` + umask 0022 export MALLOC_PERTURB_=204 @@ -66,7 +68,8 @@ fstab="/etc/fstab" vg_list="" net_list="" -USING_METHOD="raw" +USING_METHOD="local_fs" +SAVE_PATH=/var/crash vecho() { @@ -95,14 +98,14 @@ usage () { cmd=error fi - $cmd "usage: `basename $0` [--version] [--help] [-v] [-d] [-f] [--preload ]" + $cmd "usage: $cmdname [--version] [--help] [-v] [-d] [-f] [--preload ]" $cmd " [--force-ide-probe] [--force-scsi-probe | --omit-scsi-modules]" $cmd " [--image-version] [--force-scsi-probe | --omit-raid-modules]" $cmd " [--with=] [--force-lvm-probe | --omit-lvm-modules]" $cmd " [--builtin=] [--omit-dmraid]" $cmd " [--fstab=] [--nocompress] " $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 @@ findmodule() { 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 @@ findnetdriver() { 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 @@ handleraid() { 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 @@ handlelvordev() { 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 @@ while [ $# -gt 0 ]; do ;; --version) - echo "mkinitrd: version $VERSION" + echo "$cmdname: version $VERSION" exit 0 ;; @@ -574,7 +598,7 @@ if [ ! -d /lib/modules/$kernel ]; then 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 @@ for n in $CONFMODS; do findmodule $n done -finddmmods - vecho "Using modules:$MODULES" MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX` @@ -789,7 +811,7 @@ emitdm() 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 @@ emitdms() emitdm "$NAME" ;; part) - emit dm partadd "$NAME" + emit /sbin/kpartx.static -pp -a \"/dev/mapper/$NAME\" ;; esac done @@ -833,7 +855,7 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then #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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then ;; 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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then 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/etc 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 @@ ln -s bin $MNTIMAGE/sbin #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 @@ EOF #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 @@ done 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 @@ chmod 755 $MNTIMAGE/usr/share/udhcpc/default.script 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 - - 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 + 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 + +#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 @@ done 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 @@ done < /etc/iface_map 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 @@ cat >> $MNTIMAGE/init << EOF #!/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 "echo Creating Block Devices" 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 @@ if [ -n "$vg_list" ]; then 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 @@ kdump_chk() 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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then #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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then #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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then 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 @@ if [ -n "$KDUMP_CONFIG_FILE" ]; then #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 | tr -s '\011' ' ' | @@ -1485,7 +1675,13 @@ emit "#check to see if we have root= on the command line" 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\`" diff --git a/sources b/sources index 4c2c03f..7155a78 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ b4f7ffcc294d41a6a4c40d6e44b7734d kexec-tools-1.101.tar.gz -aa738475824ee3d25e5030fc506366bd makedumpfile.tar.gz +56fcb4d8e58e22795aeb6c28408916b0 makedumpfile-1.0.7.tar.gz