rpms/kexec-tools/devel firstboot_kdump.py, NONE, 1.1 kdump.sysconfig.i386, NONE, 1.1 kdump.sysconfig.ia64, NONE, 1.1 kdump.sysconfig.ppc64, NONE, 1.1 kdump.sysconfig.x86_64, NONE, 1.1 kexec-tools-1.101-elf-core-type.patch, NONE, 1.1 kexec-tools-1.101-elf-format.patch, NONE, 1.1 kexec-tools-1.101-ia64-EFI.patch, NONE, 1.1 kexec-tools-1.101-ia64-dash-l-fix.patch, NONE, 1.1 kexec-tools-1.101-ia64-icache-align.patch, NONE, 1.1 kexec-tools-1.101-ia64-kdump.patch, NONE, 1.1 kexec-tools-1.101-ia64-load-offset.patch, NONE, 1.1 kexec-tools-1.101-ia64-noio-eat.patch, NONE, 1.1 kexec-tools-1.101-ia64-noio.patch, NONE, 1.1 kexec-tools-1.101-ia64-phdr-malloc.patch, NONE, 1.1 kexec-tools-1.101-ia64-tools.patch, NONE, 1.1 kexec-tools-1.101-ifdown.patch, NONE, 1.1 kexec-tools-1.101-makedumpfile-configfile.patch, NONE, 1.1 kexec-tools-1.101-ppc64-64k-pages.patch, NONE, 1.1 kexec-tools-1.101-reloc-update.patch, NONE, 1.1 kexec-tools-1.101-x86_64-crashdump.patch, NONE, 1.1 kexec-tools-1.101-x86_64-exactmap.patch, NONE, 1.1 kdum! p.conf, 1.3, 1.4 kdump.init, 1.11, 1.12 kdump.sysconfig, 1.4, 1.5 kexec-tools-1.101-Makefile.patch, 1.3, 1.4 kexec-tools-1.101-ppc64-usage.patch, 1.1, 1.2 kexec-tools.spec, 1.64, 1.65 mkdumprd, 1.10, 1.11 sources, 1.3, 1.4

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Fri Dec 15 21:05:04 UTC 2006


Author: nhorman

Update of /cvs/dist/rpms/kexec-tools/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv24284

Modified Files:
	kdump.conf kdump.init kdump.sysconfig 
	kexec-tools-1.101-Makefile.patch 
	kexec-tools-1.101-ppc64-usage.patch kexec-tools.spec mkdumprd 
	sources 
Added Files:
	firstboot_kdump.py kdump.sysconfig.i386 kdump.sysconfig.ia64 
	kdump.sysconfig.ppc64 kdump.sysconfig.x86_64 
	kexec-tools-1.101-elf-core-type.patch 
	kexec-tools-1.101-elf-format.patch 
	kexec-tools-1.101-ia64-EFI.patch 
	kexec-tools-1.101-ia64-dash-l-fix.patch 
	kexec-tools-1.101-ia64-icache-align.patch 
	kexec-tools-1.101-ia64-kdump.patch 
	kexec-tools-1.101-ia64-load-offset.patch 
	kexec-tools-1.101-ia64-noio-eat.patch 
	kexec-tools-1.101-ia64-noio.patch 
	kexec-tools-1.101-ia64-phdr-malloc.patch 
	kexec-tools-1.101-ia64-tools.patch 
	kexec-tools-1.101-ifdown.patch 
	kexec-tools-1.101-makedumpfile-configfile.patch 
	kexec-tools-1.101-ppc64-64k-pages.patch 
	kexec-tools-1.101-reloc-update.patch 
	kexec-tools-1.101-x86_64-crashdump.patch 
	kexec-tools-1.101-x86_64-exactmap.patch 
Log Message:
Updating fc7 with all RHEL5 work


--- NEW FILE firstboot_kdump.py ---
#
# firstboot_kdump.py - kdump configuration page for firstboot
# Copyright 2006 Red Hat, Inc.
# Author: Jarod Wilson <jwilson at redhat.com>
# Contributors:
#     Neil Horman <nhorman at redhat.com>
#     Dave Lehman <dlehman at redhat.com>
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import sys
sys.path.append('/usr/share/system-config-kdump/')

from gtk import *
import string
import os
import os.path
import time
import gtk
import gobject
import functions
import commands
import rhpl.executil as executil
from firstboot import start_process

from rhpl.translate import _, N_
from rhpl import translate
translate.textdomain("firstboot")


class childWindow:
    # runPriority determines the order in which this module runs in firstboot
    runPriority = 70
    moduleName = _("Kdump")
    windowName = moduleName
    needsReboot = False

    # possible bootloaders we'll need to adjust
    #             bootloader : (config file, kdump offset)
    bootloaders = { "grub"   : ("/boot/grub/grub.conf", 16),
                    "yaboot" : ("/boot/etc/yaboot.conf", 32),
                    "elilo"  : ("/boot/efi/EFI/redhat/elilo.conf", 256) }
    bootloader = None
    offset = 0

    # list of architectures without kdump support
    unsupportedArches = [ "ppc", "s390", "s390x", "i386", "i586" ]

    # list of platforms that have a separate kernel-kdump
    kernelKdumpArches = [ "ppc64" ]
    kernelKdumpInstalled = False

    # toggle sensitivity of kdump config bits
    def showHide(self, status):
        self.totalMem.set_sensitive(status)
        self.kdumpMem.set_sensitive(status)
        self.systemUsableMem.set_sensitive(status)
        self.labelTotal.set_sensitive(status)
        self.labelKdump.set_sensitive(status)
        self.labelSys.set_sensitive(status)
        self.kdumpEnabled = status

    def on_enableKdumpCheck_toggled(self, *args):
        showHideStatus = self.enableKdumpCheck.get_active()
        self.showHide(showHideStatus)

    def updateAvail(self, widget, spin):
        self.remMem = self.availMem - spin.get_value_as_int()
        self.systemUsableMem.set_text("%s" % self.remMem)

    def getBootloader(self):
        for (name, (conf, offset)) in self.bootloaders.items():
            if os.access(conf, os.W_OK):
                self.bootloader = name
        return self.bootloader

    def launch(self, doDebug = None):
        self.doDebug = doDebug

        if doDebug:
            print "initializing kdump module"

        # What kernel are we running?
        self.runningKernel = os.popen("/bin/uname -r").read().strip()

        # What arch are we running on?
        self.arch = os.popen("/bin/uname -m").read().strip()

        # Check for a xen kernel, kdump doesn't work w/xen just yet...
        self.xenKernel = self.runningKernel.find("xen")

        # Fedora or RHEL?
        releaseFile = '/etc/redhat-release'
        self.distro = 'rhel'
        lines = open(releaseFile).readlines()
        for line in lines:
            if line.find("Fedora") != -1:
                self.distro = 'fedora'
                kernelKdumpArchesFC = [ "i686", "x86_64" ]
                self.kernelKdumpArches.extend(kernelKdumpArchesFC)
                break

        # If we need kernel-kdump, check to see if its already installed
        if self.arch in self.kernelKdumpArches:
            self.kernelKdump = "/boot/vmlinux-%skdump" % self.runningKernel
            if os.access(self.kernelKdump, os.R_OK):
                self.kernelKdumpInstalled = True

        # Ascertain how much memory is in the system
        memInfo = open("/proc/meminfo").readlines()
        self.availMem = 0
        for line in memInfo:
                if line.startswith("MemTotal:"):
                    self.availMem = int(line.split()[1]) / 1024
                    break

        # Fix up memory calculations if kdump is already on
        cmdLine = open("/proc/cmdline").read()
        self.kdumpMem = 0
        self.kdumpOffset = 0
        self.origCrashKernel = ""
	chkConfigStatus=commands.getoutput('/sbin/chkconfig --list kdump')
        if chkConfigStatus.find("on") > -1:
            self.kdumpEnabled = True
	    self.kdumpMemInitial = 0
	    if cmdLine.find("crashkernel") > -1:
		    crashString = filter(lambda t: t.startswith("crashkernel="),
					 cmdLine.split())[0].split("=")[1]
		    if self.doDebug:
			print "crashString is %s" % crashString
		    (self.kdumpMem, self.kdumpOffset) = [int(m[:-1]) for m in crashString.split("@")]
		    self.availMem += self.kdumpMem
		    self.origCrashKernel = "%dM@%dM" % (self.kdumpMem, self.kdumpOffset)
		    self.kdumpMemInitial = self.kdumpMem
        else:
            self.kdumpEnabled = False
            self.kdumpMemInitial = 0
        self.initialState = self.kdumpEnabled

        # Do some sanity-checking and try to present only sane options.
        #
        # Defaults
        lowerBound = 128
        minUsable = 256
        step = 64
        self.enoughMem = True
        if self.arch == 'ia64':
            # ia64 usually needs at *least* 256M, page-aligned... :(
            lowerBound = 256
            minUsable = 512
            step = 256
        elif self.arch == 'ppc64':
            # ppc64 often fails w/128M lately, and we want at least 1G
            # of RAM for normal use, due to 64k page size... :\
            lowerBound = 256
            minUsable = 1024

        upperBound = (self.availMem - minUsable) - (self.availMem % step)

        if upperBound < lowerBound:
            self.enoughMem = False

        # Set spinner to lowerBound unless already set on kernel command line
        if self.kdumpMem == 0:
            self.kdumpMem = lowerBound
        else:
            # round down to a multiple of step value
            self.kdumpMem = self.kdumpMem - (self.kdumpMem % step)

        # kdump enable/disable checkbox
        self.enableKdumpCheck = gtk.CheckButton("Enable kdump?")
        self.enableKdumpCheck.set_alignment(xalign=0, yalign=0)

        # detected total amount of system memory
        self.totalMem = gtk.Label(_("%s" % self.availMem))
        self.labelTotal = gtk.Label(_("_Total System Memory (MB):"))
        self.labelTotal.set_use_underline(True)
        self.labelTotal.set_mnemonic_widget(self.totalMem)
        self.labelTotal.set_alignment(0.0, 0.5)
        self.labelTotal.set_width_chars(32)

        # how much ram to reserve for kdump
        self.memSpin = gtk.Adjustment(self.kdumpMem, lowerBound, upperBound, step, step, 64)
        self.kdumpMem = gtk.SpinButton(self.memSpin, 0, 0)
        self.kdumpMem.set_update_policy(gtk.UPDATE_IF_VALID)
        self.kdumpMem.set_numeric(True)
        self.memSpin.connect("value_changed", self.updateAvail, self.kdumpMem)
        self.labelKdump = gtk.Label(_("_Kdump Memory (MB):"))
        self.labelKdump.set_use_underline(True)
        self.labelKdump.set_mnemonic_widget(self.kdumpMem)
        self.labelKdump.set_alignment(0.0, 0.5)

        # remaining usable system memory
        self.resMem = eval(string.strip(self.kdumpMem.get_text()))
        self.remMem = self.availMem - self.resMem
        self.systemUsableMem = gtk.Label(_("%s" % self.remMem))
        self.labelSys = gtk.Label(_("_Usable System Memory (MB):"))
        self.labelSys.set_use_underline(True)
        self.labelSys.set_mnemonic_widget(self.systemUsableMem)
        self.labelSys.set_alignment(0.0, 0.5)
        
        self.vbox = gtk.VBox()
        self.vbox.set_size_request(400, 200)

        title_pix = functions.imageFromFile("workstation.png")

        internalVBox = gtk.VBox()
        internalVBox.set_border_width(10)
        internalVBox.set_spacing(10)

        label = gtk.Label(_("Kdump is a kernel crash dumping mechanism. In the event of a "
                            "system crash, kdump will capture information from your system "
                            "that can be invaluable in determining the cause of the crash. "
                            "Note that kdump does require reserving a portion of system "
                            "memory that will be unavailable for other uses."))

        label.set_line_wrap(True)
        label.set_alignment(0.0, 0.5)
        label.set_size_request(500, -1)
        internalVBox.pack_start(label, False, True)

        table = gtk.Table(2, 4)

        table.attach(self.enableKdumpCheck, 0, 2, 0, 1, gtk.FILL, gtk.FILL, 5, 5)

        table.attach(self.labelTotal, 0, 1, 1, 2, gtk.FILL)
        table.attach(self.totalMem, 1, 2, 1, 2, gtk.SHRINK, gtk.FILL, 5, 5)

        table.attach(self.labelKdump, 0, 1, 2, 3, gtk.FILL)
        table.attach(self.kdumpMem, 1, 2, 2, 3, gtk.SHRINK, gtk.FILL, 5, 5)

        table.attach(self.labelSys, 0, 1, 3, 4, gtk.FILL)
        table.attach(self.systemUsableMem, 1, 2, 3, 4, gtk.SHRINK, gtk.FILL, 5, 5)

        # disable until user clicks check box, if not already enabled
        if self.initialState is False:
            self.showHide(False)
        else:
            self.enableKdumpCheck.set_active(True)

        internalVBox.pack_start(table, True, 15)

        # toggle sensitivity of Mem items
        self.enableKdumpCheck.connect("toggled", self.on_enableKdumpCheck_toggled)

        self.vbox.pack_start(internalVBox, False, 15)

        return self.vbox, title_pix, self.moduleName

    def grabFocus(self):
        self.enableKdumpCheck.grab_focus()

    def apply(self, *args):
        if self.kdumpEnabled:
            totalSysMem = self.totalMem.get_text()
            totalSysMem = eval(string.strip(totalSysMem))
            reservedMem = self.kdumpMem.get_value_as_int()
            remainingMem = totalSysMem - reservedMem
        else:
            reservedMem = self.kdumpMemInitial

        if self.doDebug:
            print "Running kernel %s on %s architecture" % (self.runningKernel, self.arch)
            if self.enableKdumpCheck.get_active():
                print "System Mem: %s MB    Kdump Mem: %s MB    Avail Mem: %s MB" % (totalSysMem, reservedMem, remainingMem)
            else:
                print "Kdump will be disabled"

        # If the user simply doesn't have enough memory for kdump to be viable/supportable, tell 'em
        if self.enoughMem is False and self.kdumpEnabled:
            self.showErrorMessage(_("Sorry, your system does not have enough memory for kdump to be viable!"))
            self.enableKdumpCheck.set_active(False)
            self.showHide(False)
            return 0
        # Alert user that we're not going to turn on kdump if they're running a xen kernel
        elif self.xenKernel != -1 and self.kdumpEnabled:
            self.showErrorMessage(_("Sorry, Xen kernels do not support kdump at this time!"))
            self.enableKdumpCheck.set_active(False)
            self.showHide(False)
            return 0
        # If there's no kdump support on this arch, let the user know and don't configure
        elif self.arch in self.unsupportedArches:
            self.showErrorMessage(_("Sorry, the %s architecture does not support kdump at this time!" % self.arch))
            self.enableKdumpCheck.set_active(False)
            self.showHide(False)
            return 0

        # If running on an arch w/a separate kernel-kdump (i.e., non-relocatable kernel), check to
        # see that its installed, otherwise, alert the user they need to install it, and give them
        # the chance to abort configuration.
        if self.arch in self.kernelKdumpArches and self.kernelKdumpInstalled is False:
            kernelKdumpNote = "\n\nNote that the %s architecture does not feature a relocatable kernel at this time, and thus requires a separate kernel-kdump package to be installed for kdump to function. This can be installed via 'yum install kernel-kdump' at your convenience.\n\n" % self.arch
        else:
            kernelKdumpNote = ""

        # Don't alert if nothing has changed
        if self.initialState != self.kdumpEnabled or reservedMem != self.kdumpMemInitial:
            dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
                                    gtk.BUTTONS_YES_NO,
                                    _("Changing Kdump settings requires rebooting the "
                                      "system to reallocate memory accordingly. %sWould you "
                                      "like to continue with this change and reboot the "
                                      "system after firstboot is complete?" % kernelKdumpNote))
            dlg.set_position(gtk.WIN_POS_CENTER)
            dlg.show_all()
            rc = dlg.run()
            dlg.destroy()

            if rc == gtk.RESPONSE_NO:
                self.needsReboot = False
                return None
            else:
                self.needsReboot = True

                # Find bootloader if it exists, and update accordingly
                if self.getBootloader() == None:
                    self.showErrorMessage(_("Error! No bootloader config file found, aborting configuration!"))
                    self.enableKdumpCheck.set_active(False)
                    self.showHide(False)
                    return 0
                else:
                    self.offset = self.bootloaders[self.bootloader][1]

                # Are we adding or removing the crashkernel param?
                if self.kdumpEnabled:
                    grubbyCmd = "/sbin/grubby --%s --update-kernel=/boot/vmlinuz-%s --args=crashkernel=%iM@%iM" \
                                % (self.bootloader, self.runningKernel, reservedMem, self.offset)
                    chkconfigStatus = "on"
                else:
                    grubbyCmd = "/sbin/grubby --%s --update-kernel=/boot/vmlinuz-%s --remove-args=crashkernel=%s" \
                                % (self.bootloader, self.runningKernel, self.origCrashKernel)
                    chkconfigStatus = "off" 

                if self.doDebug:
                    print "Using %s bootloader with %iM offset" % (self.bootloader, self.offset)
                    print "Grubby command would be:\n    %s" % grubbyCmd
                else:
                    os.system(grubbyCmd)
                    os.system("/sbin/chkconfig kdump %s" % chkconfigStatus)
                    if self.bootloader == 'yaboot':
                        os.system('/sbin/ybin')
        else:
            self.needsReboot = False


        return 0

    def showErrorMessage(self, text):
        dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text)
        dlg.set_position(gtk.WIN_POS_CENTER)
        dlg.set_modal(True)
        rc = dlg.run()
        dlg.destroy()
        return None


--- NEW FILE kdump.sysconfig.i386 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel.  This will likely match the contents of the grub kernel
# line.  For example:
#   KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"

# Any additional kexec arguments required.  In most situations, this should
# be left empty
#
# Example:
#   KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=" --args-linux"

#Where to find the boot image
KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension.  Relocatable kernels don't have one
KDUMP_IMG_EXT=""


--- NEW FILE kdump.sysconfig.ia64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel.  This will likely match the contents of the grub kernel
# line.  For example:
#   KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"

# Any additional kexec arguments required.  In most situations, this should
# be left empty
#
# Example:
#   KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
KDUMP_BOOTDIR="/boot/efi/efi/redhat"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension.  Relocatable kernels don't have one
KDUMP_IMG_EXT=""


--- NEW FILE kdump.sysconfig.ppc64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel.  This will likely match the contents of the grub kernel
# line.  For example:
#   KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib"

# Any additional kexec arguments required.  In most situations, this should
# be left empty
#
# Example:
#   KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinux"

#What is the images extension.  Relocatable kernels don't have one
KDUMP_IMG_EXT="kdump"


--- NEW FILE kdump.sysconfig.x86_64 ---
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel.  This will likely match the contents of the grub kernel
# line.  For example:
#   KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"

# Any additional kexec arguments required.  In most situations, this should
# be left empty
#
# Example:
#   KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=" --args-linux"

#Where to find the boot image
KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension.  Relocatable kernels don't have one
KDUMP_IMG_EXT=""

kexec-tools-1.101-elf-core-type.patch:
 kexec-x86.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE kexec-tools-1.101-elf-core-type.patch ---
--- kexec-tools-1.101/kexec/arch/i386/kexec-x86.c.orig	2006-11-15 16:28:04.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-x86.c	2006-11-15 16:28:13.000000000 -0500
@@ -145,7 +145,7 @@
 	.serial_baud = 0,
 	.console_vga = 0,
 	.console_serial = 0,
-	.core_header_type = CORE_TYPE_ELF64,
+	.core_header_type = CORE_TYPE_ELF32,
 };
 
 int arch_process_options(int argc, char **argv)

kexec-tools-1.101-elf-format.patch:
 i386/kexec-elf-x86.c      |    2 +-
 x86_64/kexec-elf-x86_64.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

--- NEW FILE kexec-tools-1.101-elf-format.patch ---
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c.fix	2006-08-29 20:07:34.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c	2006-08-29 20:08:03.000000000 -0400
@@ -120,7 +120,7 @@ int elf_x86_64_load(int argc, char **arg
 	/*
 	 * Parse the command line arguments
 	 */
-	arg_style = ARG_STYLE_ELF;
+	arg_style = ARG_STYLE_LINUX;
 	command_line = 0;
 	modified_cmdline = 0;
 	modified_cmdline_len = 0;
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c.fix	2006-08-29 20:07:14.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c	2006-08-29 20:07:24.000000000 -0400
@@ -121,7 +121,7 @@ int elf_x86_load(int argc, char **argv, 
 	/*
 	 * Parse the command line arguments
 	 */
-	arg_style = ARG_STYLE_ELF;
+	arg_style = ARG_STYLE_LINUX;
 	command_line = 0;
 	modified_cmdline = 0;
 	modified_cmdline_len = 0;

kexec-tools-1.101-ia64-EFI.patch:
 kexec/arch/ia64/kexec-elf-ia64.c     |   10 +++++
 kexec/arch/ia64/kexec-ia64.c         |   40 ++++++++++++++++++++++
 purgatory/arch/ia64/entry.S          |    3 +
 purgatory/arch/ia64/purgatory-ia64.c |   62 ++++++++++++++++++-----------------
 4 files changed, 83 insertions(+), 32 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-EFI.patch ---
--- kexec-tools-1.101/purgatory/arch/ia64/entry.S.orig1	2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/entry.S	2006-10-12 14:48:04.000000000 -0400
@@ -46,6 +46,8 @@
 	br.call.sptk.many b0=ia64_env_setup
 	movl r10=__kernel_entry;;
 	ld8 r14=[r10];;
+	movl r10=__boot_param_base;;
+	ld8 r28=[r10];;
 	mov b6=r14;;
 	mov ar.lc=r0
 	mov ar.ec=r0
@@ -61,6 +63,7 @@
 DECLARE_DATA8(__command_line_len)
 DECLARE_DATA8(__efi_memmap_base)
 DECLARE_DATA8(__efi_memmap_size)
+DECLARE_DATA8(__boot_param_base)
 DECLARE_DATA8(__loaded_segments)
 DECLARE_DATA8(__loaded_segments_num)
 
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig1	2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c	2006-10-12 14:48:04.000000000 -0400
@@ -123,11 +123,12 @@
 	uint64_t command_line_len;
 	uint64_t efi_memmap_base;
 	uint64_t efi_memmap_size;
+	uint64_t boot_param_base;
 	struct loaded_segment *loaded_segments;
 	unsigned long loaded_segments_num;
 };
 
-void
+void 
 setup_arch(void)
 {
 	reset_vga();
@@ -138,11 +139,11 @@
 	return addr - PAGE_OFFSET;
 }
 
-void
-patch_efi_memmap(struct kexec_boot_params *params,
+void 
+patch_efi_memmap(struct kexec_boot_params *params, 
 		struct ia64_boot_param *boot_param)
 {
-	void *dest = (void *)params->efi_memmap_base;
+	void *dest = (void *)params->efi_memmap_base; 
 	void *src  = (void *)boot_param->efi_memmap;
 	unsigned long len = boot_param->efi_memmap_size;
 	unsigned long memdesc_size = boot_param->efi_memdesc_size;
@@ -150,15 +151,15 @@
 	efi_memory_desc_t *md1, *md2;
 	void *p1, *p2, *src_end = src + len;
 	int i;
-	for (p1 = src, p2 = dest; p1 < src_end;
+	for (p1 = src, p2 = dest; p1 < src_end; 
 			p1 += memdesc_size, p2 += memdesc_size) {
 		unsigned long mstart, mend;
 		md1 = p1;
 		md2 = p2;
-		if (md1->num_pages == 0)
+		if (md1->num_pages == 0) 
 			continue;
 		mstart = md1->phys_addr;
-		mend = md1->phys_addr + (md1->num_pages
+		mend = md1->phys_addr + (md1->num_pages 
 				<< EFI_PAGE_SHIFT);
 		switch (md1->type) {
 			case EFI_LOADER_DATA:
@@ -168,7 +169,7 @@
 			default:
 				*md2 = *md1;
 		}
-		// segments are already sorted and aligned to 4K
+		// segments are already sorted and aligned to 4K 
 		orig_type = md2->type;
 		for (i = 0; i < params->loaded_segments_num; i++) {
 			struct loaded_segment *seg;
@@ -177,50 +178,50 @@
 				unsigned long start_pages, mid_pages, end_pages;
 				if (seg->end > mend) {
 					p1 += memdesc_size;
-					for(; p1 < src_end;
+					for(; p1 < src_end; 
 							p1 += memdesc_size) {
 						md1 = p1;
 						/* TODO check contig and attribute here */
-						mend = md1->phys_addr
+						mend = md1->phys_addr 
 							+ (md1->num_pages << EFI_PAGE_SHIFT);
 						if (seg->end < mend)
 							break;
 					}
 				}
-				start_pages = (seg->start - mstart)
+				start_pages = (seg->start - mstart) 
 					>> EFI_PAGE_SHIFT;
 				mid_pages = (seg->end - seg->start)
 					>> EFI_PAGE_SHIFT;
-				end_pages  = (mend - seg->end)
+				end_pages  = (mend - seg->end) 
 					>> EFI_PAGE_SHIFT;
 				if (start_pages) {
 					md2->num_pages = start_pages;
-					p2 += memdesc_size;
+					p2 += memdesc_size; 
 					md2 = p2;
 					*md2 = *md1;
 				}
 				md2->phys_addr = seg->start;
 				md2->num_pages = mid_pages;
-				md2->type = seg->reserved ?
+				md2->type = seg->reserved ? 
 					EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA;
 				if (end_pages) {
-					p2 += memdesc_size;
+					p2 += memdesc_size; 
 					md2 = p2;
 					*md2 = *md1;
 					md2->phys_addr = seg->end;
 					md2->num_pages = end_pages;
 					md2->type = orig_type;
 					mstart = seg->end;
-				} else
+				} else 
 					break;
 			}
 		}
 	}
-
+	
 	boot_param->efi_memmap_size = p2 - dest;
 }
 
-void
+void 
 flush_icache_range(char *start, unsigned long len)
 {
 	unsigned long i;
@@ -233,7 +234,7 @@
 extern char __dummy_efi_function[], __dummy_efi_function_end[];
 
 
-void
+void 
 ia64_env_setup(struct ia64_boot_param *boot_param,
 	struct kexec_boot_params *params)
 {
@@ -243,13 +244,15 @@
 	unsigned long *set_virtual_address_map;
 	char *command_line = (char *)params->command_line;
 	uint64_t command_line_len = params->command_line_len;
-
+	struct ia64_boot_param *new_boot_param = 
+	(struct ia64_boot_param *) params->boot_param_base;
+	memcpy(new_boot_param, boot_param, 4096);
 	// patch efi_runtime->set_virtual_address_map to a
 	// dummy function
 	len = __dummy_efi_function_end - __dummy_efi_function;
-	memcpy(command_line + command_line_len,
+	memcpy(command_line + command_line_len, 
 		__dummy_efi_function, len);
-	systab = (efi_system_table_t *)boot_param->efi_systab;
+	systab = (efi_system_table_t *)new_boot_param->efi_systab;
 	runtime = (efi_runtime_services_t *)PA(systab->runtime);
 	set_virtual_address_map =
 		(unsigned long *)PA(runtime->set_virtual_address_map);
@@ -257,15 +260,14 @@
 		(unsigned long)(command_line + command_line_len);
 	flush_icache_range(command_line + command_line_len, len);
 
-	patch_efi_memmap(params, boot_param);
-
-	boot_param->efi_memmap = params->efi_memmap_base;
+	patch_efi_memmap(params, new_boot_param);
 
-	boot_param->command_line = params->command_line;
-	boot_param->console_info.orig_x = 0;
-	boot_param->console_info.orig_y = 0;
-	boot_param->initrd_start = params->ramdisk_base;
-	boot_param->initrd_size =  params->ramdisk_size;
+	new_boot_param->efi_memmap = params->efi_memmap_base;
+	new_boot_param->command_line = params->command_line;
+	new_boot_param->console_info.orig_x = 0;
+	new_boot_param->console_info.orig_y = 0;
+	new_boot_param->initrd_start = params->ramdisk_base;
+	new_boot_param->initrd_size =  params->ramdisk_size;
 }
 
 /* This function can be used to execute after the SHA256 verification. */
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig1	2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c	2006-10-12 14:47:57.000000000 -0400
@@ -36,6 +36,38 @@
 
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
+/* Reserve range for EFI memmap and Boot parameter */
+static int split_range(int range, unsigned long start, unsigned long end)
+{
+	unsigned long ram_end = memory_range[range - 1].end;
+	unsigned int type = memory_range[range - 1].type;
+	int i;
+	//align end and start to page size of EFI
+	start = start & ~((1UL<<12) - 1);
+	end = (end + (1UL<<12) - 1)& ~((1UL<<12) - 1);
+	for (i = 0; i < range; i++) 
+		if(memory_range[i].start <= start && memory_range[i].end >=end)
+			break;
+	if (i >= range)
+		return range;
+	range = i;
+	if (memory_range[range].start < start) {
+		memory_range[range].end = start;
+		range++;
+	}
+	memory_range[range].start = start;
+	memory_range[range].end = end;
+	memory_range[range].type = RANGE_RESERVED;
+	range++;
+	if (end < ram_end) {
+		memory_range[range].start = end;
+		memory_range[range].end = ram_end;
+		memory_range[range].type = type;
+		range++;
+	}
+	return range;
+}
+
 /* Return a sorted list of available memory ranges. */
 int get_memory_ranges(struct memory_range **range, int *ranges,
 				unsigned long kexec_flags)
@@ -85,6 +117,12 @@
 					mem_max = end;
 			}
 			continue;
+		} else if (memcmp(str, "Boot parameter\n", 14) == 0) {
+			memory_ranges = split_range(memory_ranges, start, end);
+			continue;
+		} else if (memcmp(str, "EFI Memory Map\n", 14) == 0) {
+			memory_ranges = split_range(memory_ranges, start, end);
+			continue;
 		} else
 			continue;
 		/*
@@ -125,7 +163,7 @@
 {
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
-		{ 0, 			0, NULL, 0 },
+		{ 0, 0, NULL, 0 },
 	};
 	static const char short_options[] = KEXEC_ARCH_OPT_STR;
 	int opt;
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig1	2006-10-12 14:25:54.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-10-12 14:48:04.000000000 -0400
@@ -115,9 +115,10 @@
 	unsigned long entry, max_addr, gp_value;
 	unsigned long command_line_base, ramdisk_base;
 	unsigned long efi_memmap_base, efi_memmap_size;
+	unsigned long boot_param_base;
 	int result;
 	int opt;
-	char *efi_memmap_buf;
+	char *efi_memmap_buf, *boot_param;
 #define OPT_APPEND	(OPT_ARCH_MAX+0)
 #define OPT_RAMDISK	(OPT_ARCH_MAX+1)
 	static const struct option options[] = {
@@ -191,6 +192,13 @@
 				&command_line) < 0)
 		return -1;
 
+	// reverve 4k for ia64_boot_param
+	boot_param = xmalloc(4096);
+        boot_param_base = add_buffer(info, boot_param, 4096, 4096, 4096, 0,
+                        max_addr, -1);
+        elf_rel_set_symbol(&info->rhdr, "__boot_param_base",
+                        &boot_param_base, sizeof(long));
+
 	// reserve 8k for efi_memmap
 	efi_memmap_size = 1UL<<14;
 	efi_memmap_buf = xmalloc(efi_memmap_size);

kexec-tools-1.101-ia64-dash-l-fix.patch:
 kexec-elf-ia64.c |   15 +++++++++++----
 kexec-ia64.c     |   44 ++++++++++++++++++++++++++++++++++++++++++--
 kexec-ia64.h     |    4 ++++
 3 files changed, 57 insertions(+), 6 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-dash-l-fix.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h.orig	2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h	2006-12-01 14:49:13.000000000 -0500
@@ -7,6 +7,10 @@
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info);
 void elf_ia64_usage(void);
+int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr);
+void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
+        unsigned long addr);
+
 #define MAX_MEMORY_RANGES 1024
 #define EFI_PAGE_SIZE	  (1UL<<12)
 #define ELF_PAGE_SIZE	  (1UL<<16)
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig	2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c	2006-12-01 14:55:16.000000000 -0500
@@ -28,14 +28,16 @@
 #include <string.h>
 #include <getopt.h>
 #include <sched.h>
+#include <limits.h>
 #include <sys/utsname.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
+#include "elf.h"
 #include "kexec-ia64.h"
 #include <arch/options.h>
 
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
-
+static int memory_ranges;
 /* Reserve range for EFI memmap and Boot parameter */
 static int split_range(int range, unsigned long start, unsigned long end)
 {
@@ -73,7 +75,6 @@
 				unsigned long kexec_flags)
 {
 	const char iomem[]= "/proc/iomem";
-	int memory_ranges = 0;
 	char line[MAX_LINE];
 	FILE *fp;
 	fp = fopen(iomem, "r");
@@ -209,6 +210,45 @@
 	return 0;
 }
 
+int update_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+{
+	int i;
+	struct mem_phdr *phdr;
+	unsigned long start_addr = ULONG_MAX, end_addr = 0;
+	unsigned long align = 1UL<<26; // 64M
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		phdr = &ehdr->e_phdr[i];
+		if (phdr->p_type == PT_LOAD) {
+			if (phdr->p_paddr < start_addr) 
+				start_addr = phdr->p_paddr;
+			if ((phdr->p_paddr + phdr->p_memsz) > end_addr)
+				end_addr = phdr->p_paddr + phdr->p_memsz;
+		}
+
+	}
+	
+	for (i = 0; i < memory_ranges 
+		&& memory_range[i].start <= start_addr; i++) {
+		if (memory_range[i].type == RANGE_RAM &&
+			memory_range[i].end > end_addr)
+		return;
+	}
+
+	for (i = 0; i < memory_ranges; i++) {
+		if (memory_range[i].type == RANGE_RAM) {
+			unsigned long start = 
+				(memory_range[i].start + align - 1)&~(align - 1);
+			unsigned long end = memory_range[i].end;
+			if (end > start && 
+					(end - start) > (end_addr - start_addr)) {
+				move_loaded_segments(info, ehdr, start);
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
 void arch_update_purgatory(struct kexec_info *info)
 {
 }
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig	2006-12-01 14:36:39.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-12-01 14:59:29.000000000 -0500
@@ -84,7 +84,8 @@
 
 /* Move the crash kerenl physical offset to reserved region
  */
-static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr, 
+	unsigned long addr)
 {
 	int i;
 	long offset;
@@ -92,7 +93,7 @@
 	for(i = 0; i < ehdr->e_phnum; i++) {
 		phdr = &ehdr->e_phdr[i];
 		if (phdr->p_type == PT_LOAD) {
-			offset = mem_min - phdr->p_paddr;
+			offset = addr - phdr->p_paddr;
 			break;
 		}
 	}
@@ -174,8 +175,14 @@
 			fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n");
 		return -1;
 		}
-		move_loaded_segments(info, &ehdr);
-	}
+		move_loaded_segments(info, &ehdr, mem_min);
+	} else {
+		if (update_loaded_segments(info, &ehdr)) {
+			fprintf(stderr, "Failed to place kernel\n");
+			return -1;
+		}
+        }
+
 
 	entry = ehdr.e_entry;
 	max_addr = elf_max_addr(&ehdr);

kexec-tools-1.101-ia64-icache-align.patch:
 purgatory-ia64.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletion(-)

--- NEW FILE kexec-tools-1.101-ia64-icache-align.patch ---
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig	2006-10-20 13:45:49.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c	2006-10-20 13:46:56.000000000 -0400
@@ -224,7 +224,9 @@
 void 
 flush_icache_range(char *start, unsigned long len)
 {
-	unsigned long i;
+	unsigned long i,addr;
+	addr = (unsigned long)start & ~31UL;
+	len += (unsigned long)start - addr;
 	for (i = 0;i < len; i += 32)
 	  asm volatile("fc.i %0"::"r"(start + i):"memory");
 	asm volatile (";;sync.i;;":::"memory");

kexec-tools-1.101-ia64-kdump.patch:
 kexec/arch/ia64/Makefile             |    2 
 kexec/arch/ia64/crashdump-ia64.c     |  351 +++++++++++++++++++++++++++++++++++
 kexec/arch/ia64/crashdump-ia64.h     |   13 +
 kexec/arch/ia64/kexec-elf-ia64.c     |   80 +++++++
 kexec/arch/ia64/kexec-elf-rel-ia64.c |   37 +++
 kexec/arch/ia64/kexec-ia64.h         |    4 
 kexec/kexec-sha256.h                 |    2 
 kexec/kexec.c                        |    3 
 purgatory/arch/ia64/Makefile         |    2 
 purgatory/arch/ia64/console-ia64.c   |   44 ++++
 purgatory/arch/ia64/entry.S          |   54 +----
 purgatory/arch/ia64/io.h             |   94 +++++++++
 purgatory/arch/ia64/purgatory-ia64.c |  188 +++++++++++++++++-
 purgatory/arch/ia64/purgatory-ia64.h |    3 
 purgatory/arch/ia64/vga.c            |  143 ++++++++++++++
 15 files changed, 955 insertions(+), 65 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-kdump.patch ---
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.c
--- /dev/null	2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.c	2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,351 @@
+/*
+ * kexec: crashdum support
+ * Copyright (C) 2005-2006 Zou Nan hai <nanhai.zou at intel.com> Intel Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
+#include "kexec-ia64.h"
+#include "crashdump-ia64.h"
+
+int memory_ranges = 0;
+#define LOAD_OFFSET 	(0xa000000000000000UL + 0x100000000UL - (1UL<<26))
+#define MAX_LINE        160
+/* Stores a sorted list of RAM memory ranges for which to create elf headers.
+ * A separate program header is created for backup region */
+static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+/* Memory region reserved for storing panic kernel and other data. */
+static struct memory_range crash_reserved_mem;
+unsigned long elfcorehdr;
+static unsigned long kernel_code_start;
+struct loaded_segment {
+        unsigned long start;
+        unsigned long end;
+	unsigned long reserved;
+};
+
+#define MAX_LOAD_SEGMENTS	128
+struct loaded_segment loaded_segments[MAX_LOAD_SEGMENTS];
+
+unsigned long loaded_segments_num, loaded_segments_base;
+static int seg_comp(const void *a, const void *b)
+{
+        const struct loaded_segment *x = a, *y = b;
+        /* avoid overflow */
+        if (x->start > y->start) return 1;
+	if (x->start < y->start) return -1;
+	return 0;
+}
+
+/* purgatory code need this info to patch the EFI memmap
+ */
+static void add_loaded_segments_info(struct kexec_info *info,
+	struct mem_ehdr *ehdr, unsigned long max_addr)
+{
+	 int i;
+         for(i = 0; i < ehdr->e_phnum; i++) {
+                unsigned long start, end;
+                struct mem_phdr *phdr;
+                phdr = &ehdr->e_phdr[i];
+                if (phdr->p_type != PT_LOAD)
+                        continue;
+                start = phdr->p_paddr;
+                end = phdr->p_paddr + phdr->p_memsz;
+
+		loaded_segments[loaded_segments_num].start =
+                        start&~(ELF_PAGE_SIZE-1);
+                loaded_segments[loaded_segments_num].end =
+                        (end + ELF_PAGE_SIZE - 1)&~(ELF_PAGE_SIZE - 1);
+		loaded_segments[loaded_segments_num].reserved = 0;
+		loaded_segments_num++;
+	}
+}
+
+static int get_crash_notes_section_addr(unsigned long *addr, int cpu)
+{
+        char crash_notes[128];
+        char line[MAX_LINE];
+        FILE *fp;
+	sprintf(crash_notes, "/sys/devices/system/cpu/cpu%d/crash_notes", cpu);
+        fp = fopen(crash_notes, "r");
+        if (!fp) {
+                fprintf(stderr, "Cannot open %s: %s\n",
+                        crash_notes, strerror(errno));
+                fprintf(stderr, "Try mounting sysfs\n");
+                return -1;
+        }
+	if (fscanf(fp, "%lx", addr) != 1) {
+		*addr = 0;
+		return -1;
+	}
+        return 0;
+}
+
+/* Removes crash reserve region from list of memory chunks for whom elf program
+ * headers have to be created. Assuming crash reserve region to be a single
+ * continuous area fully contained inside one of the memory chunks */
+static int exclude_crash_reserve_region(int *nr_ranges)
+{
+	int i, j, tidx = -1;
+	unsigned long cstart, cend;
+	struct memory_range temp_region;
+
+	/* Crash reserved region. */
+	cstart = crash_reserved_mem.start;
+	cend = crash_reserved_mem.end;
+
+	for (i = 0; i < (*nr_ranges); i++) {
+		unsigned long mstart, mend;
+		mstart = crash_memory_range[i].start;
+		mend = crash_memory_range[i].end;
+		if (cstart < mend && cend > mstart) {
+			if (cstart != mstart && cend != mend) {
+				/* Split memory region */
+				crash_memory_range[i].end = cstart - 1;
+				temp_region.start = cend + 1;
+				temp_region.end = mend;
+				temp_region.type = RANGE_RAM;
+				tidx = i+1;
+			} else if (cstart != mstart)
+				crash_memory_range[i].end = cstart - 1;
+			else
+				crash_memory_range[i].start = cend + 1;
+		}
+	}
+	/* Insert split memory region, if any. */
+	if (tidx >= 0) {
+		if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
+			/* No space to insert another element. */
+			fprintf(stderr, "Error: Number of crash memory ranges"
+					" excedeed the max limit\n");
+			return -1;
+		}
+		for (j = (*nr_ranges - 1); j >= tidx; j--)
+			crash_memory_range[j+1] = crash_memory_range[j];
+		crash_memory_range[tidx].start = temp_region.start;
+		crash_memory_range[tidx].end = temp_region.end;
+		crash_memory_range[tidx].type = temp_region.type;
+		(*nr_ranges)++;
+	}
+	return 0;
+}
+
+static int prepare_crash_memory_elf64_headers(struct kexec_info *info,
+                                                void *buf, unsigned long size)
+{
+	Elf64_Ehdr *elf;
+	Elf64_Phdr *phdr;
+	int i;
+	long int nr_cpus = 0;
+	char *bufp = buf;
+	unsigned long notes_addr, notes_offset;
+
+	/* Setup ELF Header*/
+	elf = (Elf64_Ehdr *) bufp;
+	bufp += sizeof(Elf64_Ehdr);
+	memcpy(elf->e_ident, ELFMAG, SELFMAG);
+	elf->e_ident[EI_CLASS]  = ELFCLASS64;
+	elf->e_ident[EI_DATA]   = ELFDATA2LSB;
+	elf->e_ident[EI_VERSION]= EV_CURRENT;
+	elf->e_ident[EI_OSABI] = ELFOSABI_NONE;
+	memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+	elf->e_type     = ET_CORE;
+	elf->e_machine  = EM_IA_64;
+	elf->e_version  = EV_CURRENT;
+	elf->e_entry    = 0;
+	elf->e_phoff    = sizeof(Elf64_Ehdr);
+	elf->e_shoff    = 0;
+	elf->e_flags    = 0;
+	elf->e_ehsize   = sizeof(Elf64_Ehdr);
+	elf->e_phentsize= sizeof(Elf64_Phdr);
+	elf->e_phnum    = 0;
+	elf->e_shentsize= 0;
+	elf->e_shnum    = 0;
+	elf->e_shstrndx = 0;
+
+	/* PT_NOTE program headers. One per cpu*/
+	nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+	if (nr_cpus < 0) {
+		return -1;
+	}
+
+        /* Need to find a better way to determine per cpu notes section size. */
+#define MAX_NOTE_BYTES  1024
+
+        for (i = 0; i < nr_cpus; i++) {
+        	if (get_crash_notes_section_addr (&notes_addr, i) < 0)
+                	break;
+		notes_offset = notes_addr;
+		phdr = (Elf64_Phdr *) bufp;
+                bufp += sizeof(Elf64_Phdr);
+                phdr->p_type    = PT_NOTE;
+                phdr->p_flags   = 0;
+                phdr->p_offset  = notes_offset;
+                phdr->p_vaddr   = phdr->p_paddr = notes_offset;
+                phdr->p_filesz  = phdr->p_memsz = MAX_NOTE_BYTES;
+                /* Do we need any alignment of segments? */
+                phdr->p_align   = 0;
+
+                /* Increment number of program headers. */
+                (elf->e_phnum)++;
+        }
+
+	for (i = 0; i < memory_ranges; i++) {
+		unsigned long mstart, mend;
+		mstart = crash_memory_range[i].start;
+		mend = crash_memory_range[i].end;
+		if (!mstart && !mend)
+			break;
+		phdr = (Elf64_Phdr *) bufp;
+		bufp += sizeof(Elf64_Phdr);
+		phdr->p_type    = PT_LOAD;
+		phdr->p_flags   = PF_R|PF_W|PF_X;
+		phdr->p_offset  = mstart;
+		/*add region 5 mapping for kernel*/
+		if (kernel_code_start >= mstart && kernel_code_start < mend) {
+			phdr->p_vaddr = mstart + LOAD_OFFSET;
+			phdr->p_paddr = mstart;
+			phdr->p_filesz  = phdr->p_memsz = mend - mstart + 1;
+			phdr->p_align   = 0;
+			(elf->e_phnum)++;
+
+			phdr = (Elf64_Phdr *) bufp;
+			bufp += sizeof(Elf64_Phdr);
+			phdr->p_type    = PT_LOAD;
+			phdr->p_flags   = PF_R|PF_W|PF_X;
+			phdr->p_offset  = mstart;
+		}
+		phdr->p_vaddr = mstart + PAGE_OFFSET;
+		phdr->p_paddr = mstart;
+		phdr->p_filesz  = phdr->p_memsz = mend - mstart + 1;
+		phdr->p_align   = 0;
+		(elf->e_phnum)++;
+	}
+	return 0;
+}
+
+static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
+{
+	const char iomem[]= "/proc/iomem";
+        char line[MAX_LINE];
+        FILE *fp;
+        unsigned long start, end;
+
+        fp = fopen(iomem, "r");
+        if (!fp) {
+                fprintf(stderr, "Cannot open %s: %s\n",
+                        iomem, strerror(errno));
+                return -1;
+        }
+	while(fgets(line, sizeof(line), fp) != 0) {
+		char *str;
+		int type, consumed, count;
+		if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
+			break;
+		count = sscanf(line, "%lx-%lx : %n",
+				&start, &end, &consumed);
+		str = line + consumed;
+		if (count != 2)
+			continue;
+
+		if (memcmp(str, "System RAM\n", 11) == 0) {
+			type = RANGE_RAM;
+		} else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+			/* Reserved memory region. New kernel can
+			 * use this region to boot into. */
+			crash_reserved_mem.start = start;
+			crash_reserved_mem.end = end;
+			crash_reserved_mem.type = RANGE_RAM;
+			continue;
+		}
+		else if (memcmp(str, "Kernel code\n", 12) == 0) {
+			kernel_code_start = start;
+			continue;
+		}else
+			continue;
+		crash_memory_range[memory_ranges].start = start;
+		crash_memory_range[memory_ranges].end = end;
+		crash_memory_range[memory_ranges].type = type;
+		memory_ranges++;
+	}
+        fclose(fp);
+	if (exclude_crash_reserve_region(&memory_ranges) < 0)
+		return -1;
+	*ranges = memory_ranges;
+	return 0;
+}
+
+static void
+cmdline_add_elfcorehdr(char **cmdline, unsigned long addr)
+{
+	char *str = *cmdline;
+	char buf[64];
+	size_t len;
+	sprintf(buf, " elfcorehdr=%ldK", addr/1024);
+	len = strlen(str) + strlen(buf) + 1;
+	str = xmalloc(len);
+	sprintf(str, "%s%s", *cmdline, buf);
+	*cmdline = str;
+}
+
+int load_crashdump_segments(struct kexec_info *info, struct mem_ehdr *ehdr,
+                            unsigned long max_addr, unsigned long min_base,
+			    char **cmdline)
+{
+	//struct memory_range *mem_range, *memmap_p;
+	struct memory_range *mem_range;
+	int nr_ranges;
+	size_t size;
+	void *tmp;
+	if (info->kexec_flags & KEXEC_ON_CRASH ) {
+		if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) {
+			size =  sizeof(Elf64_Ehdr) +
+				(nr_ranges + 1) * sizeof(Elf64_Phdr);
+			size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1);
+			tmp = xmalloc(size);
+			memset(tmp, 0, size);
+			if (prepare_crash_memory_elf64_headers(info, tmp, size) < 0)
+				return -1;
+			elfcorehdr = add_buffer(info, tmp, size, size, EFI_PAGE_SIZE, min_base,
+					max_addr, -1);
+			loaded_segments[loaded_segments_num].start = elfcorehdr;
+			loaded_segments[loaded_segments_num].end = elfcorehdr + size;
+			loaded_segments[loaded_segments_num].reserved = 1;
+			loaded_segments_num++;
+			cmdline_add_elfcorehdr(cmdline, elfcorehdr);
+		}
+	}
+	add_loaded_segments_info(info, ehdr, max_addr);
+	size = sizeof(struct loaded_segment) * loaded_segments_num;
+	qsort(loaded_segments, loaded_segments_num,
+                        sizeof(struct loaded_segment), seg_comp);
+        loaded_segments_base = add_buffer(info, loaded_segments,
+                        size, size, 16, 0, max_addr, -1);
+
+        elf_rel_set_symbol(&info->rhdr, "__loaded_segments",
+                        &loaded_segments_base, sizeof(long));
+        elf_rel_set_symbol(&info->rhdr, "__loaded_segments_num",
+                         &loaded_segments_num, sizeof(long));
+	return 0;
+}
+
+
diff -puN /dev/null kexec/arch/ia64/crashdump-ia64.h
--- /dev/null	2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/crashdump-ia64.h	2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,13 @@
+#ifndef CRASHDUMP_IA64_H
+#define CRASHDUMP_IA64_H
+
+#define PAGE_OFFSET             0xe000000000000000UL
+#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
+extern int load_crashdump_segments(struct kexec_info *info,
+		struct mem_ehdr *ehdr, unsigned long max_addr,
+		unsigned long min_base, char **cmdline);
+
+#define CRASH_MAX_MEMMAP_NR     (KEXEC_MAX_SEGMENTS + 1)
+#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
+
+#endif
diff -puN kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-ia64.c
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-ia64.c~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-ia64.c	2006-07-13 14:42:05.000000000 +0530
@@ -40,7 +40,9 @@
 #include <boot/elf_boot.h>
 #include <ip_checksum.h>
 #include "../../kexec.h"
+#include "../../kexec-syscall.h"
 #include "../../kexec-elf.h"
+#include "crashdump-ia64.h"
 #include <arch/options.h>
 
 static const int probe_debug = 0;
@@ -80,6 +82,28 @@ void elf_ia64_usage(void)
 		"    --initrd=FILE       Use FILE as the kernel's initial ramdisk.\n");
 }
 
+/* Move the crash kerenl physical offset to reserved region
+ */
+static void move_loaded_segments(struct kexec_info *info, struct mem_ehdr *ehdr)
+{
+	int i;
+	long offset;
+	struct mem_phdr *phdr;
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		phdr = &ehdr->e_phdr[i];
+		if (phdr->p_type == PT_LOAD) {
+			offset = mem_min - phdr->p_paddr;
+			break;
+		}
+	}
+	ehdr->e_entry += offset;
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		phdr = &ehdr->e_phdr[i];
+		if (phdr->p_type == PT_LOAD)
+			phdr->p_paddr += offset;
+	}
+}
+
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
@@ -89,9 +113,11 @@ int elf_ia64_load(int argc, char **argv,
 	off_t ramdisk_size = 0;
 	unsigned long command_line_len;
 	unsigned long entry, max_addr, gp_value;
-	unsigned command_line_base, ramdisk_base;
+	unsigned long command_line_base, ramdisk_base;
+	unsigned long efi_memmap_base, efi_memmap_size;
 	int result;
 	int opt;
+	char *efi_memmap_buf;
 #define OPT_APPEND	(OPT_ARCH_MAX+0)
 #define OPT_RAMDISK	(OPT_ARCH_MAX+1)
 	static const struct option options[] = {
@@ -135,6 +161,15 @@ int elf_ia64_load(int argc, char **argv,
 		free_elf_info(&ehdr);
 		return result;
 	}
+
+	if (info->kexec_flags & KEXEC_ON_CRASH ) {
+		if ((mem_min == 0x00) && (mem_max = ULONG_MAX)) {
+			fprintf(stderr, "Failed to find crash kernel region in /proc/iomem\n");
+		return -1;
+		}
+		move_loaded_segments(info, &ehdr);
+	}
+
 	entry = ehdr.e_entry;
 	max_addr = elf_max_addr(&ehdr);
 
@@ -149,17 +184,48 @@ int elf_ia64_load(int argc, char **argv,
 
 	/* Load the setup code */
 	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-			0x80000, ULONG_MAX, 1);
+			0x0, ULONG_MAX, -1);
 
-	if (command_line_len) {
+
+	if (load_crashdump_segments(info, &ehdr, max_addr, 0,
+				&command_line) < 0)
+		return -1;
+
+	// reserve 8k for efi_memmap
+	efi_memmap_size = 1UL<<14;
+	efi_memmap_buf = xmalloc(efi_memmap_size);
+	efi_memmap_base = add_buffer(info, efi_memmap_buf,
+			efi_memmap_size, efi_memmap_size, 4096, 0,
+			max_addr, -1);
+
+	elf_rel_set_symbol(&info->rhdr, "__efi_memmap_base",
+			&efi_memmap_base, sizeof(long));
+
+	elf_rel_set_symbol(&info->rhdr, "__efi_memmap_size",
+			&efi_memmap_size, sizeof(long));
+	if (command_line) {
+		command_line_len = strlen(command_line) + 1;
+	}
+	if (command_line_len || (info->kexec_flags & KEXEC_ON_CRASH )) {
 		char *cmdline = xmalloc(command_line_len);
 		strcpy(cmdline, command_line);
+
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+			char buf[128];
+			sprintf(buf," max_addr=%lluM min_addr=%lluM",
+					mem_max>>20, mem_min>>20);
+			command_line_len = strlen(cmdline) + strlen(buf) + 1;
+			cmdline = xrealloc(cmdline, command_line_len);
+			strcat(cmdline, buf);
+		}
+
 		command_line_len = (command_line_len + 15)&(~15);
+		command_line_base = add_buffer(info, cmdline,
+				command_line_len, command_line_len,
+				getpagesize(), 0UL,
+				max_addr, -1);
 		elf_rel_set_symbol(&info->rhdr, "__command_line_len",
 				&command_line_len, sizeof(long));
-		command_line_base = add_buffer(info, cmdline,
-					command_line_len, command_line_len,
-					16, 0, max_addr, 1);
 		elf_rel_set_symbol(&info->rhdr, "__command_line",
 				&command_line_base, sizeof(long));
 	}
@@ -168,7 +234,7 @@ int elf_ia64_load(int argc, char **argv,
 		ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
 		ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
 				ramdisk_size,
-				getpagesize(), 0, max_addr, 1);
+				getpagesize(), 0, max_addr, -1);
 		elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
 				&ramdisk_base, sizeof(long));
 		elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
diff -puN kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64 kexec/arch/ia64/kexec-elf-rel-ia64.c
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-elf-rel-ia64.c~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-elf-rel-ia64.c	2006-07-13 14:42:05.000000000 +0530
@@ -1,3 +1,26 @@
+/*
+ * Copyright (C) 2005-2006  Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  pugatory relocation code
+ *  Most of the code in this file is
+ *  based on arch/ia64/kernel/module.c in Linux kernel
+ */
+
+
 /*  Most of the code in this file is
  *  based on arch/ia64/kernel/module.c in Linux kernel
  */
@@ -43,6 +66,15 @@ ia64_patch (uint64_t insn_addr, uint64_t
         b[1] = (b1 & ~m1) | (v1 & m1);
 }
 
+static void
+put_unaligned64(unsigned long val, unsigned char *location)
+{
+	unsigned char *src = (unsigned char *)&val;
+	int i;
+	for (i = 0; i < sizeof(long); i++)
+		*location++ = *src++;
+}
+
 static inline uint64_t
 bundle (const uint64_t insn)
 {
@@ -102,6 +134,11 @@ void machine_apply_elf_rel(struct mem_eh
 				 | ((value & 0x0fffffUL) << 13) /* bit  0 -> 13 */));
 		}
 		break;
+	case R_IA64_PCREL64LSB: {
+		value = value - address;
+		put_unaligned64(value, location);
+	} break;
+	case R_IA64_GPREL22:
 	case R_IA64_LTOFF22X:
 		if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
 			die("value out of gp relative range");
diff -puN kexec/arch/ia64/kexec-ia64.h~kdump-ia64 kexec/arch/ia64/kexec-ia64.h
--- kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.h~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/kexec-ia64.h	2006-07-13 14:42:05.000000000 +0530
@@ -7,5 +7,7 @@ int elf_ia64_probe(const char *buf, off_
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info);
 void elf_ia64_usage(void);
-
+#define MAX_MEMORY_RANGES 1024
+#define EFI_PAGE_SIZE	  (1UL<<12)
+#define ELF_PAGE_SIZE	  (1UL<<16)
 #endif /* KEXEC_IA64_H */
diff -puN kexec/arch/ia64/Makefile~kdump-ia64 kexec/arch/ia64/Makefile
--- kexec-tools-1.101-kdump/kexec/arch/ia64/Makefile~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/arch/ia64/Makefile	2006-07-13 14:42:05.000000000 +0530
@@ -4,3 +4,5 @@
 KEXEC_C_SRCS+= kexec/arch/ia64/kexec-ia64.c 
 KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-ia64.c 
 KEXEC_C_SRCS+= kexec/arch/ia64/kexec-elf-rel-ia64.c
+KEXEC_C_SRCS+= kexec/arch/ia64/crashdump-ia64.c
+
diff -puN kexec/kexec.c~kdump-ia64 kexec/kexec.c
--- kexec-tools-1.101-kdump/kexec/kexec.c~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec.c	2006-07-13 14:42:05.000000000 +0530
@@ -96,6 +96,9 @@ int valid_memory_range(unsigned long sst
 			continue;
 		mstart = memory_range[i].start;
 		mend = memory_range[i].end;
+		if (i < memory_ranges - 1 && mend == memory_range[i+1].start)
+			mend = memory_range[i+1].end;
+
 		/* Check to see if we are fully contained */
 		if ((mstart <= sstart) && (mend >= send)) {
 			return 1;
diff -puN kexec/kexec-sha256.h~kdump-ia64 kexec/kexec-sha256.h
--- kexec-tools-1.101-kdump/kexec/kexec-sha256.h~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/kexec/kexec-sha256.h	2006-07-13 14:42:05.000000000 +0530
@@ -6,6 +6,6 @@ struct sha256_region {
 	unsigned long len;
 };
 
-#define SHA256_REGIONS 8
+#define SHA256_REGIONS 16
 
 #endif /* KEXEC_SHA256_H */
diff -puN purgatory/arch/ia64/console-ia64.c~kdump-ia64 purgatory/arch/ia64/console-ia64.c
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/console-ia64.c~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/console-ia64.c	2006-07-13 14:42:05.000000000 +0530
@@ -1,5 +1,47 @@
 #include <purgatory.h>
+#include "io.h"
+
+#define VGABASE         UNCACHED(0xb8000)
+
+/* code based on i386 console code
+ * TODO add serial support
+ */
+#define MAX_YPOS        25
+#define MAX_XPOS        80
+
+unsigned long current_ypos = 1, current_xpos = 0;
+
+static void putchar_vga(int ch)
+{
+	int  i, k, j;
+
+	if (current_ypos >= MAX_YPOS) {
+		/* scroll 1 line up */
+		for (k = 1, j = 0; k < MAX_YPOS; k++, j++) {
+			for (i = 0; i < MAX_XPOS; i++) {
+				writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
+						VGABASE + 2*(MAX_XPOS*j + i));
+			}
+		}
+		for (i = 0; i < MAX_XPOS; i++)
+			writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
+		current_ypos = MAX_YPOS-1;
+	}
+	if (ch == '\n') {
+		current_xpos = 0;
+		current_ypos++;
+	} else if (ch != '\r')  {
+		writew(((0x7 << 8) | (unsigned short) ch),
+				VGABASE + 2*(MAX_XPOS*current_ypos +
+					current_xpos++));
+		if (current_xpos >= MAX_XPOS) {
+			current_xpos = 0;
+			current_ypos++;
+		}
+	}
+}
+
 void putchar(int ch)
 {
-	/* Nothing for now */
+	putchar_vga(ch);
 }
diff -puN purgatory/arch/ia64/entry.S~kdump-ia64 purgatory/arch/ia64/entry.S
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/entry.S~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/entry.S	2006-07-13 14:42:05.000000000 +0530
@@ -1,7 +1,7 @@
 /*
  * purgatory:  setup code
  *
- * Copyright (C) 2005  Zou Nan hai (nanhai.zou at intel.com)
+ * Copyright (C) 2005-2006  Zou Nan hai (nanhai.zou at intel.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,6 +16,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#define DECLARE_DATA8(name)	\
+.global name;	\
+.size	name, 8;	\
+name:	data8 0x0
 
 .global __dummy_efi_function
 .align  32
@@ -35,18 +39,10 @@ purgatory_start:
 	ld8 gp=[r2];;
 	br.call.sptk.many b0=purgatory
 	;;
-	alloc r2 = ar.pfs, 0, 0, 5, 0
+	alloc r2 = ar.pfs, 0, 0, 2, 0
 	;;
 	mov out0=r28
-
-	movl r2=__command_line;;
-	ld8 out1=[r2];;
-	movl r2=__command_line_len;;
-	ld8 out2=[r2];;
-	movl r2=__ramdisk_base;;
-	ld8 out3=[r2];;
-	movl r2=__ramdisk_size;;
-	ld8 out4=[r2];;
+	movl out1=__ramdisk_base;;
 	br.call.sptk.many b0=ia64_env_setup
 	movl r10=__kernel_entry;;
 	ld8 r14=[r10];;
@@ -58,28 +54,14 @@ purgatory_start:
 	br.call.sptk.many  b0=b6
 .endp   purgatory_start
 
-.align  32
-.global __kernel_entry
-.size	__kernel_entry, 8
-__kernel_entry:
-        data8 0x0
-.global __command_line
-.size	__command_line, 8
-__command_line:
-        data8 0x0
-.global __command_line_len
-.size	__command_line_len, 8
-__command_line_len:
-        data8 0x0
-.global __ramdisk_base
-.size	__ramdisk_base, 8
-__ramdisk_base:
-        data8 0x0
-.global __ramdisk_size
-.size	__ramdisk_size, 8
-__ramdisk_size:
-        data8 0x0
-.global __gp_value
-.size	__gp_value, 8
-__gp_value:
-        data8 0x0
+DECLARE_DATA8(__kernel_entry)
+DECLARE_DATA8(__ramdisk_base)
+DECLARE_DATA8(__ramdisk_size)
+DECLARE_DATA8(__command_line)
+DECLARE_DATA8(__command_line_len)
+DECLARE_DATA8(__efi_memmap_base)
+DECLARE_DATA8(__efi_memmap_size)
+DECLARE_DATA8(__loaded_segments)
+DECLARE_DATA8(__loaded_segments_num)
+
+DECLARE_DATA8(__gp_value)
diff -puN /dev/null purgatory/arch/ia64/io.h
--- /dev/null	2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/io.h	2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,94 @@
+#ifndef IO_H
+#define IO_H
+#define UNCACHED(x) (void *)((x)|(1UL<<63))
+#define MF()	asm volatile ("mf.a" ::: "memory")
+#define IO_SPACE_ENCODING(p)     ((((p) >> 2) << 12) | (p & 0xfff))
+
+static inline void *io_addr (unsigned long port)
+{
+        unsigned long offset;
+	unsigned long io_base;
+	asm volatile ("mov %0=ar.k0":"=r"(io_base));
+	offset = IO_SPACE_ENCODING(port);
+        return UNCACHED(io_base | offset);
+}
+
+static inline unsigned int inb (unsigned long port)
+{
+        volatile unsigned char *addr = io_addr(port);
+        unsigned char ret;
+        ret = *addr;
+        MF();
+        return ret;
+}
+
+static inline unsigned int inw (unsigned long port)
+{
+        volatile unsigned short *addr = io_addr(port);
+        unsigned short ret;
+
+        ret = *addr;
+	MF();
+        return ret;
+}
+
+static inline unsigned int ia64_inl (unsigned long port)
+{
+        volatile unsigned int *addr = __ia64_mk_io_addr(port);
+        unsigned int ret;
+        ret = *addr;
+	MF();
+        return ret;
+}
+
+static inline void outb (unsigned char val, unsigned long port)
+{
+        volatile unsigned char *addr = io_addr(port);
+
+        *addr = val;
+	MF();
+}
+
+static inline void outw (unsigned short val, unsigned long port)
+{
+        volatile unsigned short *addr = io_addr(port);
+
+        *addr = val;
+	MF();
+}
+
+static inline void outl (unsigned int val, unsigned long port)
+{
+        volatile unsigned int *addr = io_addr(port);
+
+        *addr = val;
+	MF();
+}
+
+
+static inline unsigned char readb(const volatile void  *addr)
+{
+        return *(volatile unsigned char *) addr;
+}
+static inline unsigned short readw(const volatile void  *addr)
+{
+        return *(volatile unsigned short *) addr;
+}
+static inline unsigned int readl(const volatile void  *addr)
+{
+        return *(volatile unsigned int *) addr;
+}
+
+static inline void writeb(unsigned char b, volatile void  *addr)
+{
+        *(volatile unsigned char *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void  *addr)
+{
+        *(volatile unsigned short *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void  *addr)
+{
+        *(volatile unsigned int *) addr = b;
+}
+#endif
diff -puN purgatory/arch/ia64/Makefile~kdump-ia64 purgatory/arch/ia64/Makefile
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/Makefile~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/Makefile	2006-07-13 14:42:05.000000000 +0530
@@ -5,5 +5,5 @@ PCFLAGS		+= -ffixed-r28
 PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
 PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
 PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
-PURGATORY_C_SRCS+=
+PURGATORY_C_SRCS+= purgatory/arch/ia64/vga.c
 
diff -puN purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.c
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.c	2006-07-13 14:42:05.000000000 +0530
@@ -1,9 +1,47 @@
+/*
+ * purgatory:  setup code
+ *
+ * Copyright (C) 2005-2006  Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 #include <purgatory.h>
 #include <stdint.h>
 #include <string.h>
 #include "purgatory-ia64.h"
 
-#define PAGE_OFFSET             0xe000000000000000
+#define PAGE_OFFSET             0xe000000000000000UL
+
+#define EFI_PAGE_SHIFT          12
+#define EFI_PAGE_SIZE		(1UL<<EFI_PAGE_SHIFT)
+#define EFI_PAGE_ALIGN(x)	((x + EFI_PAGE_SIZE - 1)&~(EFI_PAGE_SIZE-1))
+/* Memory types: */
+#define EFI_RESERVED_TYPE                0
+#define EFI_LOADER_CODE                  1
+#define EFI_LOADER_DATA                  2
+#define EFI_BOOT_SERVICES_CODE           3
+#define EFI_BOOT_SERVICES_DATA           4
+#define EFI_RUNTIME_SERVICES_CODE        5
+#define EFI_RUNTIME_SERVICES_DATA        6
+#define EFI_CONVENTIONAL_MEMORY          7
+#define EFI_UNUSABLE_MEMORY              8
+#define EFI_ACPI_RECLAIM_MEMORY          9
+#define EFI_ACPI_MEMORY_NVS             10
+#define EFI_MEMORY_MAPPED_IO            11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE                    13
+#define EFI_MAX_MEMORY_TYPE             14
 
 typedef struct {
         uint64_t signature;
@@ -63,53 +101,171 @@ struct ia64_boot_param {
         uint64_t initrd_size;
 };
 
-void setup_arch(void)
+typedef struct {
+        uint32_t type;
+        uint32_t pad;
+        uint64_t phys_addr;
+        uint64_t virt_addr;
+        uint64_t num_pages;
+        uint64_t attribute;
+} efi_memory_desc_t;
+
+struct loaded_segment {
+        unsigned long start;
+        unsigned long end;
+        unsigned long reserved;
+};
+
+struct kexec_boot_params {
+	uint64_t ramdisk_base;
+	uint64_t ramdisk_size;
+	uint64_t command_line;
+	uint64_t command_line_len;
+	uint64_t efi_memmap_base;
+	uint64_t efi_memmap_size;
+	struct loaded_segment *loaded_segments;
+	unsigned long loaded_segments_num;
+};
+
+void
+setup_arch(void)
 {
-	/* Nothing for now */
+	reset_vga();
 }
+
 inline unsigned long PA(unsigned long addr)
 {
 	return addr - PAGE_OFFSET;
 }
 
-void flush_icache_range(char *start, unsigned long len)
+void
+patch_efi_memmap(struct kexec_boot_params *params,
+		struct ia64_boot_param *boot_param)
+{
+	void *dest = (void *)params->efi_memmap_base;
+	void *src  = (void *)boot_param->efi_memmap;
+	unsigned long len = boot_param->efi_memmap_size;
+	unsigned long memdesc_size = boot_param->efi_memdesc_size;
+	uint64_t orig_type;
+	efi_memory_desc_t *md1, *md2;
+	void *p1, *p2, *src_end = src + len;
+	int i;
+	for (p1 = src, p2 = dest; p1 < src_end;
+			p1 += memdesc_size, p2 += memdesc_size) {
+		unsigned long mstart, mend;
+		md1 = p1;
+		md2 = p2;
+		if (md1->num_pages == 0)
+			continue;
+		mstart = md1->phys_addr;
+		mend = md1->phys_addr + (md1->num_pages
+				<< EFI_PAGE_SHIFT);
+		switch (md1->type) {
+			case EFI_LOADER_DATA:
+				*md2 = *md1;
+				md2->type = EFI_CONVENTIONAL_MEMORY;
+				break;
+			default:
+				*md2 = *md1;
+		}
+		// segments are already sorted and aligned to 4K
+		orig_type = md2->type;
+		for (i = 0; i < params->loaded_segments_num; i++) {
+			struct loaded_segment *seg;
+			seg = &params->loaded_segments[i];
+			if (seg->start >= mstart && seg->start < mend) {
+				unsigned long start_pages, mid_pages, end_pages;
+				if (seg->end > mend) {
+					p1 += memdesc_size;
+					for(; p1 < src_end;
+							p1 += memdesc_size) {
+						md1 = p1;
+						/* TODO check contig and attribute here */
+						mend = md1->phys_addr
+							+ (md1->num_pages << EFI_PAGE_SHIFT);
+						if (seg->end < mend)
+							break;
+					}
+				}
+				start_pages = (seg->start - mstart)
+					>> EFI_PAGE_SHIFT;
+				mid_pages = (seg->end - seg->start)
+					>> EFI_PAGE_SHIFT;
+				end_pages  = (mend - seg->end)
+					>> EFI_PAGE_SHIFT;
+				if (start_pages) {
+					md2->num_pages = start_pages;
+					p2 += memdesc_size;
+					md2 = p2;
+					*md2 = *md1;
+				}
+				md2->phys_addr = seg->start;
+				md2->num_pages = mid_pages;
+				md2->type = seg->reserved ?
+					EFI_UNUSABLE_MEMORY:EFI_LOADER_DATA;
+				if (end_pages) {
+					p2 += memdesc_size;
+					md2 = p2;
+					*md2 = *md1;
+					md2->phys_addr = seg->end;
+					md2->num_pages = end_pages;
+					md2->type = orig_type;
+					mstart = seg->end;
+				} else
+					break;
+			}
+		}
+	}
+
+	boot_param->efi_memmap_size = p2 - dest;
+}
+
+void
+flush_icache_range(char *start, unsigned long len)
 {
 	unsigned long i;
 	for (i = 0;i < len; i += 32)
-	  asm volatile("fc.i %0"::"r"(start+i):"memory");
+	  asm volatile("fc.i %0"::"r"(start + i):"memory");
 	asm volatile (";;sync.i;;":::"memory");
 	asm volatile ("srlz.i":::"memory");
 }
 
 extern char __dummy_efi_function[], __dummy_efi_function_end[];
 
-void ia64_env_setup(struct ia64_boot_param *boot_param,
-	uint64_t command_line, uint64_t command_line_len,
-	uint64_t ramdisk_base, uint64_t ramdisk_size)
+
+void
+ia64_env_setup(struct ia64_boot_param *boot_param,
+	struct kexec_boot_params *params)
 {
 	unsigned long len;
         efi_system_table_t *systab;
         efi_runtime_services_t *runtime;
 	unsigned long *set_virtual_address_map;
+	char *command_line = (char *)params->command_line;
+	uint64_t command_line_len = params->command_line_len;
 
 	// patch efi_runtime->set_virtual_address_map to a
 	// dummy function
 	len = __dummy_efi_function_end - __dummy_efi_function;
-	memcpy((char *)command_line + command_line_len, __dummy_efi_function,
-	len);
+	memcpy(command_line + command_line_len,
+		__dummy_efi_function, len);
 	systab = (efi_system_table_t *)boot_param->efi_systab;
 	runtime = (efi_runtime_services_t *)PA(systab->runtime);
 	set_virtual_address_map =
 		(unsigned long *)PA(runtime->set_virtual_address_map);
-	*(set_virtual_address_map)=
-		(unsigned long)((char *)command_line + command_line_len);
-	flush_icache_range((char *)command_line+command_line_len, len);
+	*(set_virtual_address_map) =
+		(unsigned long)(command_line + command_line_len);
+	flush_icache_range(command_line + command_line_len, len);
+
+	patch_efi_memmap(params, boot_param);
+
+	boot_param->efi_memmap = params->efi_memmap_base;
 
-	boot_param->command_line = command_line;
+	boot_param->command_line = params->command_line;
 	boot_param->console_info.orig_x = 0;
 	boot_param->console_info.orig_y = 0;
-	boot_param->initrd_start = ramdisk_base;
-	boot_param->initrd_size =  ramdisk_size;
+	boot_param->initrd_start = params->ramdisk_base;
+	boot_param->initrd_size =  params->ramdisk_size;
 }
 
 /* This function can be used to execute after the SHA256 verification. */
diff -puN purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64 purgatory/arch/ia64/purgatory-ia64.h
--- kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.h~kdump-ia64	2006-07-13 14:42:05.000000000 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/purgatory-ia64.h	2006-07-13 14:42:05.000000000 +0530
@@ -1,6 +1,5 @@
 #ifndef PURGATORY_IA64_H
 #define PURGATORY_IA64_H
 
-/* nothing yet */
-
+void reset_vga(void);
 #endif /* PURGATORY_IA64_H */
diff -puN /dev/null purgatory/arch/ia64/vga.c
--- /dev/null	2006-07-13 05:14:41.629277080 +0530
+++ kexec-tools-1.101-kdump-maneesh/purgatory/arch/ia64/vga.c	2006-07-13 14:42:05.000000000 +0530
@@ -0,0 +1,143 @@
+#include "io.h"
+void reset_vga(void)
+{
+	/* Hello */
+	inb(0x3da);
+	outb(0, 0x3c0);
+
+	/* Sequencer registers */
+	outw(0x0300, 0x3c4);
+	outw(0x0001, 0x3c4);
+	outw(0x0302, 0x3c4);
+	outw(0x0003, 0x3c4);
+	outw(0x0204, 0x3c4);
+
+	/* Ensure CRTC regs 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+	outw(0x0e11, 0x3d4);
+	/* CRTC registers */
+	outw(0x5f00, 0x3d4);
+	outw(0x4f01, 0x3d4);
+	outw(0x5002, 0x3d4);
+	outw(0x8203, 0x3d4);
+	outw(0x5504, 0x3d4);
+	outw(0x8105, 0x3d4);
+	outw(0xbf06, 0x3d4);
+	outw(0x1f07, 0x3d4);
+	outw(0x0008, 0x3d4);
+	outw(0x4f09, 0x3d4);
+	outw(0x200a, 0x3d4);
+	outw(0x0e0b, 0x3d4);
+	outw(0x000c, 0x3d4);
+	outw(0x000d, 0x3d4);
+	outw(0x010e, 0x3d4);
+	outw(0xe00f, 0x3d4);
+	outw(0x9c10, 0x3d4);
+	outw(0x8e11, 0x3d4);
+	outw(0x8f12, 0x3d4);
+	outw(0x2813, 0x3d4);
+	outw(0x1f14, 0x3d4);
+	outw(0x9615, 0x3d4);
+	outw(0xb916, 0x3d4);
+	outw(0xa317, 0x3d4);
+	outw(0xff18, 0x3d4);
+
+	/* Graphic registers */
+	outw(0x0000, 0x3ce);
+	outw(0x0001, 0x3ce);
+	outw(0x0002, 0x3ce);
+	outw(0x0003, 0x3ce);
+	outw(0x0004, 0x3ce);
+	outw(0x1005, 0x3ce);
+	outw(0x0e06, 0x3ce);
+	outw(0x0007, 0x3ce);
+	outw(0xff08, 0x3ce);
+
+	/* Attribute registers */
+	inb(0x3da);
+	outb(0x00, 0x3c0);
+	outb(0x00, 0x3c0);
+
+	inb(0x3da);
+	outb(0x01, 0x3c0);
+	outb(0x01, 0x3c0);
+
+	inb(0x3da);
+	outb(0x02, 0x3c0);
+	outb(0x02, 0x3c0);
+
+	inb(0x3da);
+	outb(0x03, 0x3c0);
+	outb(0x03, 0x3c0);
+
+	inb(0x3da);
+	outb(0x04, 0x3c0);
+	outb(0x04, 0x3c0);
+
+	inb(0x3da);
+	outb(0x05, 0x3c0);
+	outb(0x05, 0x3c0);
+
+	inb(0x3da);
+	outb(0x06, 0x3c0);
+	outb(0x14, 0x3c0);
+
+	inb(0x3da);
+	outb(0x07, 0x3c0);
+	outb(0x07, 0x3c0);
+
+	inb(0x3da);
+	outb(0x08, 0x3c0);
+	outb(0x38, 0x3c0);
+
+	inb(0x3da);
+	outb(0x09, 0x3c0);
+	outb(0x39, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0a, 0x3c0);
+	outb(0x3a, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0b, 0x3c0);
+	outb(0x3b, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0c, 0x3c0);
+	outb(0x3c, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0d, 0x3c0);
+	outb(0x3d, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0e, 0x3c0);
+	outb(0x3e, 0x3c0);
+
+	inb(0x3da);
+	outb(0x0f, 0x3c0);
+	outb(0x3f, 0x3c0);
+
+	inb(0x3da);
+	outb(0x10, 0x3c0);
+	outb(0x0c, 0x3c0);
+
+	inb(0x3da);
+	outb(0x11, 0x3c0);
+	outb(0x00, 0x3c0);
+
+	inb(0x3da);
+	outb(0x12, 0x3c0);
+	outb(0x0f, 0x3c0);
+
+	inb(0x3da);
+	outb(0x13, 0x3c0);
+	outb(0x08, 0x3c0);
+
+	inb(0x3da);
+	outb(0x14, 0x3c0);
+	outb(0x00, 0x3c0);
+
+	/* Goodbye */
+	inb(0x3da);
+	outb(0x20, 0x3c0);
+}
_

kexec-tools-1.101-ia64-load-offset.patch:
 crashdump-ia64.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE kexec-tools-1.101-ia64-load-offset.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c.orig	2006-12-01 14:16:07.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c	2006-12-01 14:18:34.000000000 -0500
@@ -28,7 +28,7 @@
 #include "crashdump-ia64.h"
 
 int memory_ranges = 0;
-#define LOAD_OFFSET 	(0xa000000000000000UL + 0x100000000UL - (1UL<<26))
+#define LOAD_OFFSET 	(0xa000000000000000UL + 0x100000000UL - kernel_code_start)
 #define MAX_LINE        160
 /* Stores a sorted list of RAM memory ranges for which to create elf headers.
  * A separate program header is created for backup region */

kexec-tools-1.101-ia64-noio-eat.patch:
 kexec-elf-ia64.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

--- NEW FILE kexec-tools-1.101-ia64-noio-eat.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig	2006-12-01 14:30:59.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-12-01 14:31:04.000000000 -0500
@@ -128,7 +128,7 @@
 		{"command-line", 1, 0, OPT_APPEND},
 		{"append",       1, 0, OPT_APPEND},
 		{"initrd",       1, 0, OPT_RAMDISK},
-		{"noio",         1, 0, OPT_NOIO},
+		{"noio",         0, 0, OPT_NOIO},
 		{0, 0, 0, 0},
 	};
 

kexec-tools-1.101-ia64-noio.patch:
 kexec/arch/ia64/kexec-elf-ia64.c      |   10 +++++
 purgatory/arch/ia64/entry.S           |    1 
 purgatory/arch/ia64/include/arch/io.h |   25 -------------
 purgatory/arch/ia64/io.h              |   64 ++++++++++++++++++++--------------
 4 files changed, 50 insertions(+), 50 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-noio.patch ---
On Thu, Sep 21, 2006 at 01:06:08PM +0800, Zou Nan hai wrote:
> SN platform support PIO in a different way to generic IA64 platform. It
> does not support most of the legacy I/O ports.
> 
> Give an --noio option to kexec-tools to disable I/O in purgatory code.
> 
> This patch also removed an unused io.h in kexec-tools.
> 
> Signed-off-by: Zou Nan hai <nanhai.zou at intel.com>

I have merged the following into kexec-tools-test.

-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/

From: Zou Nan hai <nanhai.zou at intel.com>
Date: 21 Sep 2006 13:06:08 +0800
Subject: kexec-tools: --noio option to disable I/O in purgatory	code.

SN platform support PIO in a different way to generic IA64 platform. It
does not support most of the legacy I/O ports.

Give an --noio option to kexec-tools to disable I/O in purgatory code.

This patch also removed an unused io.h in kexec-tools.

Signed-off-by: Zou Nan hai <nanhai.zou at intel.com>

Edited to consistently use tabs instead of spaces for intentation,
remove one instance of trailing whitespace, and fix indentation
of noio line in options[].

Signed-off-by: Simon Horman <horms at verge.net.au>

diff -Nraup kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c
kexec-tools-1.101-fix/kexec/arch/ia64/kexec-elf-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-09-20 15:30:40.000000000 +0800
+++ kexec-tools-1.101-fix/kexec/arch/ia64/kexec-elf-ia64.c	2006-09-21 15:12:20.000000000 +0800
@@ -116,16 +116,19 @@ int elf_ia64_load(int argc, char **argv,
 	unsigned long command_line_base, ramdisk_base;
 	unsigned long efi_memmap_base, efi_memmap_size;
 	unsigned long boot_param_base;
+	unsigned long noio=0;
 	int result;
 	int opt;
 	char *efi_memmap_buf, *boot_param;
 #define OPT_APPEND	(OPT_ARCH_MAX+0)
 #define OPT_RAMDISK	(OPT_ARCH_MAX+1)
+#define OPT_NOIO	(OPT_ARCH_MAX+2)
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
 		{"command-line", 1, 0, OPT_APPEND},
 		{"append",       1, 0, OPT_APPEND},
 		{"initrd",       1, 0, OPT_RAMDISK},
+		{"noio",         1, 0, OPT_NOIO},
 		{0, 0, 0, 0},
 	};
 
@@ -148,6 +151,9 @@ int elf_ia64_load(int argc, char **argv,
 		case OPT_RAMDISK:
 			ramdisk = optarg;
 			break;
+		case OPT_NOIO:	/* disable PIO and MMIO in purgatory code*/
+			noio = 1;
+			break;
 		}
 	}
 	command_line_len = 0;
@@ -196,6 +202,10 @@ int elf_ia64_load(int argc, char **argv,
 	boot_param = xmalloc(4096);
         boot_param_base = add_buffer(info, boot_param, 4096, 4096, 4096, 0,
                         max_addr, -1);
+
+	elf_rel_set_symbol(&info->rhdr, "__noio",
+			   &noio, sizeof(long));
+
         elf_rel_set_symbol(&info->rhdr, "__boot_param_base",
                         &boot_param_base, sizeof(long));
 
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/entry.S
kexec-tools-1.101-fix/purgatory/arch/ia64/entry.S
--- kexec-tools-1.101/purgatory/arch/ia64/entry.S	2006-09-20 15:30:40.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/entry.S	2006-09-21 15:11:36.000000000 +0800
@@ -68,3 +68,4 @@ DECLARE_DATA8(__loaded_segments)
 DECLARE_DATA8(__loaded_segments_num)
 
 DECLARE_DATA8(__gp_value)
+DECLARE_DATA8(__noio)
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h
kexec-tools-1.101-fix/purgatory/arch/ia64/include/arch/io.h
--- kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h	2006-09-20 15:29:29.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/include/arch/io.h	1970-01-01 08:00:00.000000000 +0800
@@ -1,25 +0,0 @@
-#ifndef ARCH_IO_H
-#define ARCH_IO_H
-
-#include <stdint.h>
-/* Helper functions for directly doing I/O */
-
-extern inline uint8_t inb(void *port)
-{
-	volatile unsigned char *addr = (unsigned char *)port;
-	uint8_t result;
-
-	result = *addr;
-	asm volatile ("mf.a"::: "memory");
-	return result;
-}
-
-extern inline void outb (uint8_t value, void *port)
-{
-	volatile unsigned char *addr = (unsigned char *)port;
-
-	*addr = value;
-	asm volatile ("mf.a"::: "memory");
-}
-
-#endif /* ARCH_IO_H */
diff -Nraup kexec-tools-1.101/purgatory/arch/ia64/io.h
kexec-tools-1.101-fix/purgatory/arch/ia64/io.h
--- kexec-tools-1.101/purgatory/arch/ia64/io.h	2006-09-20 15:29:29.000000000 +0800
+++ kexec-tools-1.101-fix/purgatory/arch/ia64/io.h	2006-09-21 15:11:19.000000000 +0800
@@ -3,7 +3,7 @@
 #define UNCACHED(x) (void *)((x)|(1UL<<63))
 #define MF()	asm volatile ("mf.a" ::: "memory")
 #define IO_SPACE_ENCODING(p)     ((((p) >> 2) << 12) | (p & 0xfff))
-
+extern long __noio;
 static inline void *io_addr (unsigned long port)
 {
         unsigned long offset;
@@ -16,28 +16,34 @@ static inline void *io_addr (unsigned lo
 static inline unsigned int inb (unsigned long port)
 {
         volatile unsigned char *addr = io_addr(port);
-        unsigned char ret;
-        ret = *addr;
-        MF();
+	unsigned char ret = 0;
+	if (!__noio) {
+		ret = *addr;
+		MF();
+	}
         return ret;
 }
 
 static inline unsigned int inw (unsigned long port)
 {
         volatile unsigned short *addr = io_addr(port);
-        unsigned short ret;
+	unsigned short ret = 0;
 
-        ret = *addr;
-	MF();
+	if (!__noio) {
+		ret = *addr;
+		MF();
+	}
         return ret;
 }
 
-static inline unsigned int ia64_inl (unsigned long port)
+static inline unsigned int inl (unsigned long port)
 {
-        volatile unsigned int *addr = __ia64_mk_io_addr(port);
-        unsigned int ret;
-        ret = *addr;
-	MF();
+	volatile unsigned int *addr = io_addr(port);
+	unsigned int ret ;
+	if (!__noio) {
+		ret = *addr;
+		MF();
+	}
         return ret;
 }
 
@@ -45,50 +51,58 @@ static inline void outb (unsigned char v
 {
         volatile unsigned char *addr = io_addr(port);
 
-        *addr = val;
-	MF();
+	if (!__noio) {
+		*addr = val;
+		MF();
+	}
 }
 
 static inline void outw (unsigned short val, unsigned long port)
 {
         volatile unsigned short *addr = io_addr(port);
 
-        *addr = val;
-	MF();
+	if (!__noio) {
+		*addr = val;
+		MF();
+	}
 }
 
 static inline void outl (unsigned int val, unsigned long port)
 {
         volatile unsigned int *addr = io_addr(port);
 
-        *addr = val;
-	MF();
+	if (!__noio) {
+		*addr = val;
+		MF();
+	}
 }
 
-
 static inline unsigned char readb(const volatile void  *addr)
 {
-        return *(volatile unsigned char *) addr;
+	return __noio ? 0 :*(volatile unsigned char *) addr;
 }
 static inline unsigned short readw(const volatile void  *addr)
 {
-        return *(volatile unsigned short *) addr;
+	return __noio ? 0 :*(volatile unsigned short *) addr;
 }
 static inline unsigned int readl(const volatile void  *addr)
 {
-        return *(volatile unsigned int *) addr;
+	return __noio ? 0 :*(volatile unsigned int *) addr;
 }
 
 static inline void writeb(unsigned char b, volatile void  *addr)
 {
-        *(volatile unsigned char *) addr = b;
+	if (!__noio)
+		*(volatile unsigned char *) addr = b;
 }
 static inline void writew(unsigned short b, volatile void  *addr)
 {
-        *(volatile unsigned short *) addr = b;
+	if (!__noio)
+		*(volatile unsigned short *) addr = b;
 }
 static inline void writel(unsigned int b, volatile void  *addr)
 {
-        *(volatile unsigned int *) addr = b;
+	if (!__noio)
+		*(volatile unsigned int *) addr = b;
 }
 #endif


kexec-tools-1.101-ia64-phdr-malloc.patch:
 crashdump-ia64.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-phdr-malloc.patch ---
--- kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c.orig	2006-11-14 13:38:45.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/crashdump-ia64.c	2006-11-14 14:52:34.000000000 -0500
@@ -316,10 +316,14 @@
 	int nr_ranges;
 	size_t size;
 	void *tmp;
+	long int nr_cpus;
+	if ((nr_cpus = sysconf(_SC_NPROCESSORS_CONF)) < 0)
+		return -1;
 	if (info->kexec_flags & KEXEC_ON_CRASH ) {
 		if (get_crash_memory_ranges(&mem_range, &nr_ranges) == 0) {
-			size =  sizeof(Elf64_Ehdr) +
-				(nr_ranges + 1) * sizeof(Elf64_Phdr);
+			size =  (sizeof(Elf64_Ehdr) +
+				((nr_cpus +1) * sizeof(Elf64_Phdr)) +
+				((nr_ranges + 1) * sizeof(Elf64_Phdr)));
 			size = (size + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1);
 			tmp = xmalloc(size);
 			memset(tmp, 0, size);

kexec-tools-1.101-ia64-tools.patch:
 Makefile                              |    1 
 kdump/kdump.8                         |   39 ++++++++++++
 kexec/Makefile                        |    4 +
 kexec/arch/ia64/kexec-elf-ia64.c      |   60 ++++++++++++++++---
 kexec/arch/ia64/kexec-elf-rel-ia64.c  |   96 ++++++++++++++++++++++++++++--
 kexec/arch/ia64/kexec-ia64.c          |  107 ++++++++++++++++++++++++----------
 kexec/arch/ia64/kexec-ia64.h          |    2 
 kexec/kexec.8                         |   46 ++++++++++++--
 purgatory/arch/ia64/Makefile          |    4 -
 purgatory/arch/ia64/entry.S           |   85 +++++++++++++++++++++++++++
 purgatory/arch/ia64/include/arch/io.h |   25 +++++++
 purgatory/arch/ia64/purgatory-ia64.c  |  106 +++++++++++++++++++++++++++++++++
 12 files changed, 521 insertions(+), 54 deletions(-)

--- NEW FILE kexec-tools-1.101-ia64-tools.patch ---
--- kexec-tools-1.101/Makefile.orig	2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/Makefile	2006-10-20 13:39:08.000000000 -0400
@@ -43,6 +43,7 @@
 PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
 
 MAN_PAGES:= kexec/kexec.8
+MAN_PAGES+= kdump/kdump.8
 BINARIES_i386:=  $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump
 BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
 BINARIES:=$(SBINDIR)/kexec $(BINARIES_$(ARCH)) 
--- /dev/null	2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/kdump/kdump.8	2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,39 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH KDUMP 8 "Jul 27, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+kdump \- This is just a placeholder until real man page has been written
+.SH SYNOPSIS
+.B kdump
+.RI [ options ] " start_address" ...
+.SH DESCRIPTION
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBkdump\fP does not have a man page yet.
+.SH OPTIONS
+.\"These programs follow the usual GNU command line syntax, with long
+.\"options starting with two dashes (`-').
+.\"A summary of options is included below.
+.\"For a complete description, see the Info files.
+.SH SEE ALSO
+.SH AUTHOR
+kdump was written by Eric Biederman.
+.PP
+This manual page was written by Khalid Aziz <khalid.aziz at hp.com>,
+for the Debian project (but may be used by others).
--- kexec-tools-1.101/purgatory/arch/ia64/Makefile.orig	2004-12-20 17:44:22.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/ia64/Makefile	2006-10-20 13:39:08.000000000 -0400
@@ -1,8 +1,8 @@
 #
 # Purgatory ia64
 #
-
-PURGATORY_S_SRCS+=
+PCFLAGS		+= -ffixed-r28
+PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
 PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
 PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
 PURGATORY_C_SRCS+=
--- /dev/null	2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h	2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,25 @@
+#ifndef ARCH_IO_H
+#define ARCH_IO_H
+
+#include <stdint.h>
+/* Helper functions for directly doing I/O */
+
+extern inline uint8_t inb(void *port)
+{
+	volatile unsigned char *addr = (unsigned char *)port;
+	uint8_t result;
+
+	result = *addr;
+	asm volatile ("mf.a"::: "memory");
+	return result;
+}
+
+extern inline void outb (uint8_t value, void *port)
+{
+	volatile unsigned char *addr = (unsigned char *)port;
+
+	*addr = value;
+	asm volatile ("mf.a"::: "memory");
+}
+
+#endif /* ARCH_IO_H */
--- /dev/null	2006-10-19 09:27:39.770809345 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/entry.S	2006-10-20 13:39:08.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * purgatory:  setup code
+ *
+ * Copyright (C) 2005  Zou Nan hai (nanhai.zou at intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+.global __dummy_efi_function
+.align  32
+.proc  __dummy_efi_function
+__dummy_efi_function:
+	mov r8=r0;;
+	br.ret.sptk.many rp;;
+.global __dummy_efi_function_end
+__dummy_efi_function_end:
+.endp 	__dummy_efi_function
+
+.global purgatory_start
+.align  32
+.proc   purgatory_start
+purgatory_start:
+	movl r2=__gp_value;;
+	ld8 gp=[r2];;
+	br.call.sptk.many b0=purgatory
+	;;
+	alloc r2 = ar.pfs, 0, 0, 5, 0
+	;;
+	mov out0=r28
+
+	movl r2=__command_line;;
+	ld8 out1=[r2];;
+	movl r2=__command_line_len;;
+	ld8 out2=[r2];;
+	movl r2=__ramdisk_base;;
+	ld8 out3=[r2];;
+	movl r2=__ramdisk_size;;
+	ld8 out4=[r2];;
+	br.call.sptk.many b0=ia64_env_setup
+	movl r10=__kernel_entry;;
+	ld8 r14=[r10];;
+	mov b6=r14;;
+	mov ar.lc=r0
+	mov ar.ec=r0
+	cover;;
+	invala;;
+	br.call.sptk.many  b0=b6
+.endp   purgatory_start
+
+.align  32
+.global __kernel_entry
+.size	__kernel_entry, 8
+__kernel_entry:
+        data8 0x0
+.global __command_line
+.size	__command_line, 8
+__command_line:
+        data8 0x0
+.global __command_line_len
+.size	__command_line_len, 8
+__command_line_len:
+        data8 0x0
+.global __ramdisk_base
+.size	__ramdisk_base, 8
+__ramdisk_base:
+        data8 0x0
+.global __ramdisk_size
+.size	__ramdisk_size, 8
+__ramdisk_size:
+        data8 0x0
+.global __gp_value
+.size	__gp_value, 8
+__gp_value:
+        data8 0x0
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c.orig	2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c	2006-10-20 13:39:08.000000000 -0400
@@ -1,10 +1,116 @@
 #include <purgatory.h>
+#include <stdint.h>
+#include <string.h>
 #include "purgatory-ia64.h"
 
+#define PAGE_OFFSET             0xe000000000000000
+
+typedef struct {
+        uint64_t signature;
+        uint32_t revision;
+        uint32_t headersize;
+        uint32_t crc32;
+        uint32_t reserved;
+} efi_table_hdr_t;
+
+typedef struct {
+        efi_table_hdr_t hdr;
+        unsigned long get_time;
+        unsigned long set_time;
+        unsigned long get_wakeup_time;
+        unsigned long set_wakeup_time;
+        unsigned long set_virtual_address_map;
+        unsigned long convert_pointer;
+        unsigned long get_variable;
+        unsigned long get_next_variable;
+        unsigned long set_variable;
+        unsigned long get_next_high_mono_count;
+        unsigned long reset_system;
+} efi_runtime_services_t;
+
+typedef struct {
+        efi_table_hdr_t hdr;
+        unsigned long fw_vendor;        /* physical addr of CHAR16 vendor string
+ */
+        uint32_t fw_revision;
+        unsigned long con_in_handle;
+        unsigned long con_in;
+        unsigned long con_out_handle;
+        unsigned long con_out;
+        unsigned long stderr_handle;
+        unsigned long stderr;
+        unsigned long runtime;
+        unsigned long boottime;
+        unsigned long nr_tables;
+        unsigned long tables;
+} efi_system_table_t;
+
+struct ia64_boot_param {
+        uint64_t command_line;             /* physical address of command line arguments */
+        uint64_t efi_systab;               /* physical address of EFI system table */
+        uint64_t efi_memmap;               /* physical address of EFI memory map */
+        uint64_t efi_memmap_size;          /* size of EFI memory map */
+        uint64_t efi_memdesc_size;         /* size of an EFI memory map descriptor */
+        uint32_t efi_memdesc_version;      /* memory descriptor version */
+        struct {
+                uint16_t num_cols; /* number of columns on console output device */
+                uint16_t num_rows; /* number of rows on console output device */
+                uint16_t orig_x;   /* cursor's x position */
+                uint16_t orig_y;   /* cursor's y position */
+        } console_info;
+        uint64_t fpswa;            /* physical address of the fpswa interface */
+        uint64_t initrd_start;
+        uint64_t initrd_size;
+};
+
 void setup_arch(void)
 {
 	/* Nothing for now */
 }
+inline unsigned long PA(unsigned long addr)
+{
+	return addr - PAGE_OFFSET;
+}
+
+void flush_icache_range(char *start, unsigned long len)
+{
+	unsigned long i;
+	for (i = 0;i < len; i += 32)
+	  asm volatile("fc.i %0"::"r"(start+i):"memory");
+	asm volatile (";;sync.i;;":::"memory");
+	asm volatile ("srlz.i":::"memory");
+}
+
+extern char __dummy_efi_function[], __dummy_efi_function_end[];
+
+void ia64_env_setup(struct ia64_boot_param *boot_param,
+	uint64_t command_line, uint64_t command_line_len,
+	uint64_t ramdisk_base, uint64_t ramdisk_size)
+{
+	unsigned long len;
+        efi_system_table_t *systab;
+        efi_runtime_services_t *runtime;
+	unsigned long *set_virtual_address_map;
+
+	// patch efi_runtime->set_virtual_address_map to a
+	// dummy function
+	len = __dummy_efi_function_end - __dummy_efi_function;
+	memcpy((char *)command_line + command_line_len, __dummy_efi_function,
+	len);
+	systab = (efi_system_table_t *)boot_param->efi_systab;
+	runtime = (efi_runtime_services_t *)PA(systab->runtime);
+	set_virtual_address_map =
+		(unsigned long *)PA(runtime->set_virtual_address_map);
+	*(set_virtual_address_map)=
+		(unsigned long)((char *)command_line + command_line_len);
+	flush_icache_range((char *)command_line+command_line_len, len);
+
+	boot_param->command_line = command_line;
+	boot_param->console_info.orig_x = 0;
+	boot_param->console_info.orig_y = 0;
+	boot_param->initrd_start = ramdisk_base;
+	boot_param->initrd_size =  ramdisk_size;
+}
 
 /* This function can be used to execute after the SHA256 verification. */
 void post_verification_setup_arch(void)
--- kexec-tools-1.101/kexec/Makefile.orig	2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/kexec/Makefile	2006-10-20 13:39:08.000000000 -0400
@@ -28,6 +28,7 @@
 KEXEC_OBJS:= $(KEXEC_C_OBJS) $(KEXEC_S_OBJS)
 KEXEC_DEPS:= $(KEXEC_C_DEPS) $(KEXEC_S_DEPS)
 KEXEC:= $(SBINDIR)/kexec
+KEXEC_MANPAGE:= $(MANDIR)/man8/kexec.8
 
 include $(KEXEC_DEPS)
 
@@ -51,6 +52,9 @@
 	mkdir -p $(@D)
 	$(CC) $(KCFLAGS) -o $@ $(KEXEC_OBJS) $(UTIL_LIB) $(LIBS)
 
+$(KEXEC_MANPAGE): kexec/kexec.8
+	 $(MKDIR) -p     $(MANDIR)/man8
+	cp kexec/kexec.8 $(KEXEC_MANPAGE)
 echo::
 	@echo "KEXEC_C_SRCS $(KEXEC_C_SRCS)"
 	@echo "KEXEC_C_DEPS $(KEXEC_C_DEPS)"
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h.orig	2004-12-19 18:52:38.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h	2006-10-20 13:39:08.000000000 -0400
@@ -1,6 +1,8 @@
 #ifndef KEXEC_IA64_H
 #define KEXEC_IA64_H
 
+#define MAX_MEMORY_RANGES 1024
+
 int elf_ia64_probe(const char *buf, off_t len);
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info);
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c.orig	2004-12-20 17:43:23.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c	2006-10-20 13:39:08.000000000 -0400
@@ -1,8 +1,14 @@
+/*  Most of the code in this file is
+ *  based on arch/ia64/kernel/module.c in Linux kernel
+ */
+
 #include <stdio.h>
 #include <elf.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+#define MAX_LTOFF       ((uint64_t) (1 << 22))
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
@@ -17,12 +23,40 @@
 	return 1;
 }
 
+static void
+ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
+{
+        uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
+#       define insn_mask ((1UL << 41) - 1)
+        unsigned long shift;
+
+        b0 = b[0]; b1 = b[1];
+        shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+        if (shift >= 64) {
+                m1 = mask << (shift - 64);
+                v1 = val << (shift - 64);
+        } else {
+                m0 = mask << shift; m1 = mask >> (64 - shift);
+                v0 = val  << shift; v1 = val >> (64 - shift);
+                b[0] = (b0 & ~m0) | (v0 & m0);
+        }
+        b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static inline uint64_t
+bundle (const uint64_t insn)
+{
+        return insn & ~0xfUL;
+}
+
 void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
 	void *location, unsigned long address, unsigned long value)
 {
+	uint64_t gp_value = ehdr->rel_addr + 0x200000;
 	switch(r_type) {
 	case R_IA64_NONE:
 		break;
+	case R_IA64_SEGREL64LSB:
 	case R_IA64_DIR64LSB:
 		*((uint64_t *)location) = value;
 		break;
@@ -31,15 +65,67 @@
 		if (value != *((uint32_t *)location))
 			goto overflow;
 		break;
-	case R_IA64_PCREL21B:
+	case R_IA64_IMM64:
+		ia64_patch((uint64_t)location, 0x01fffefe000UL,
+				/* bit 63 -> 36 */
+				(((value & 0x8000000000000000UL) >> 27)
+				/* bit 21 -> 21 */
+				  | ((value & 0x0000000000200000UL) <<  0)
+				/* bit 16 -> 22 */
+				  | ((value & 0x00000000001f0000UL) <<  6)
+				/* bit 7 -> 27 */
+				  | ((value & 0x000000000000ff80UL) << 20)
+				/* bit 0 -> 13 */
+				  | ((value & 0x000000000000007fUL) << 13)));
+		ia64_patch((uint64_t)location - 1, 0x1ffffffffffUL, value>>22);
+		break;
+	case R_IA64_IMM22:
+		if (value + (1 << 21) >= (1 << 22))
+                	die("value out of IMM22 range\n");
+		ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+				/* bit 21 -> 36 */
+				(((value & 0x200000UL) << 15)
+				/* bit 16 -> 22 */
+				 | ((value & 0x1f0000UL) <<  6)
+				/* bit  7 -> 27 */
+				 | ((value & 0x00ff80UL) << 20)
+				/* bit  0 -> 13 */
+				 | ((value & 0x00007fUL) << 13) ));
+		break;
+	case R_IA64_PCREL21B: {
+		uint64_t delta = ((int64_t)value - (int64_t)address)/16;
+		if (delta + (1 << 20) >= (1 << 21))
+			die("value out of IMM21B range\n");
+		value = ((int64_t)(value - bundle(address)))/16;
+		ia64_patch((uint64_t)location, 0x11ffffe000UL,
+				(((value & 0x100000UL) << 16) /* bit 20 -> 36 */
+				 | ((value & 0x0fffffUL) << 13) /* bit  0 -> 13 */));
+		}
+		break;
+	case R_IA64_LTOFF22X:
+		if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+			die("value out of gp relative range");
+		value -= gp_value;
+		ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+				(((value & 0x200000UL) << 15) /* bit 21 -> 36 */
+				   |((value & 0x1f0000UL) <<  6) /* bit 16 -> 22 */
+				   |((value & 0x00ff80UL) << 20) /* bit  7 -> 27 */
+				   |((value & 0x00007fUL) << 13) /* bit  0 -> 13 */));
+		break;
+	case R_IA64_LDXMOV:
+		if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+			die("value out of gp relative range");
+		ia64_patch((uint64_t)location, 0x1fff80fe000UL, 0x10000000000UL);
+	        break;
 	case R_IA64_LTOFF22:
-	case R_IA64_SEGREL64LSB:
+
 	default:
-		die("Unknown rela relocation: %lu\n", r_type);
+		die("Unknown rela relocation: 0x%lx 0x%lx\n",
+				r_type, address);
 		break;
 	}
 	return;
- overflow:
+overflow:
 	die("overflow in relocation type %lu val %Lx\n", 
-		r_type, value);
+			r_type, value);
 }
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig	2004-12-21 15:01:37.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-10-20 13:39:08.000000000 -0400
@@ -6,6 +6,7 @@
  * Copyright (C) 2004 Silicon Graphics, Inc.
  *   Jesse Barnes <jbarnes at sgi.com>
  * Copyright (C) 2004 Khalid Aziz <khalid.aziz at hp.com> Hewlett Packard Co
+ * Copyright (C) 2005 Zou Nan hai <nanhai.zou at intel.com> Intel Corp
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <limits.h>
 #include <elf.h>
 #include <boot/elf_boot.h>
 #include <ip_checksum.h>
@@ -74,23 +76,29 @@
 {
 	printf(
 		"    --command-line=STRING Set the kernel command line to STRING.\n"
-		"    --append=STRING       Set the kernel command line to STRING.\n");
+		"    --append=STRING       Set the kernel command line to STRING.\n"
+		"    --initrd=FILE       Use FILE as the kernel's initial ramdisk.\n");
 }
 
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line;
-	int command_line_len;
-	unsigned long entry, max_addr;
+	const char *command_line, *ramdisk=0;
+	char *ramdisk_buf = NULL;
+	off_t ramdisk_size = 0;
+	unsigned long command_line_len;
+	unsigned long entry, max_addr, gp_value;
+	unsigned command_line_base, ramdisk_base;
 	int result;
 	int opt;
 #define OPT_APPEND	(OPT_ARCH_MAX+0)
+#define OPT_RAMDISK	(OPT_ARCH_MAX+1)
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
 		{"command-line", 1, 0, OPT_APPEND},
 		{"append",       1, 0, OPT_APPEND},
+		{"initrd",       1, 0, OPT_RAMDISK},
 		{0, 0, 0, 0},
 	};
 
@@ -110,11 +118,14 @@
 		case OPT_APPEND:
 			command_line = optarg;
 			break;
+		case OPT_RAMDISK:
+			ramdisk = optarg;
+			break;
 		}
 	}
 	command_line_len = 0;
 	if (command_line) {
-		command_line_len = strlen(command_line) + 1;
+		command_line_len = strlen(command_line) + 16;
 	}
 
 	/* Parse the Elf file */
@@ -129,13 +140,46 @@
 
 	/* Load the Elf data */
 	result = elf_exec_load(&ehdr, info);
-	free_elf_info(&ehdr);
 	if (result < 0) {
 		fprintf(stderr, "ELF load failed\n");
+		free_elf_info(&ehdr);
 		return result;
 	}
+
+
+	/* Load the setup code */
+	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+			0x80000, ULONG_MAX, 1);
+
+	if (command_line_len) {
+		char *cmdline = xmalloc(command_line_len);
+		strcpy(cmdline, command_line);
+		command_line_len = (command_line_len + 15)&(~15);
+		elf_rel_set_symbol(&info->rhdr, "__command_line_len",
+				&command_line_len, sizeof(long));
+		command_line_base = add_buffer(info, cmdline,
+					command_line_len, command_line_len,
+					16, 0, max_addr, 1);
+		elf_rel_set_symbol(&info->rhdr, "__command_line",
+				&command_line_base, sizeof(long));
+	}
 	
-	/* For now we don't have arguments to pass :( */
-	info->entry = (void *)entry;
+	if (ramdisk) {
+		ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
+		ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
+				ramdisk_size,
+				getpagesize(), 0, max_addr, 1);
+		elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
+				&ramdisk_base, sizeof(long));
+		elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
+				&ramdisk_size, sizeof(long));
+	}
+
+	gp_value = info->rhdr.rel_addr + 0x200000;
+        elf_rel_set_symbol(&info->rhdr, "__gp_value", &gp_value,
+                        sizeof(gp_value));
+
+	elf_rel_set_symbol(&info->rhdr, "__kernel_entry", &entry, sizeof(entry));
+	free_elf_info(&ehdr);
 	return 0;
 }
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c.orig	2006-10-20 13:38:53.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c	2006-10-20 13:39:08.000000000 -0400
@@ -27,42 +27,87 @@
 #include <stdint.h>
 #include <string.h>
 #include <getopt.h>
+#include <sched.h>
 #include <sys/utsname.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
 #include "kexec-ia64.h"
 #include <arch/options.h>
 
-#define MAX_MEMORY_RANGES 64
 static struct memory_range memory_range[MAX_MEMORY_RANGES];
 
 /* Return a sorted list of available memory ranges. */
 int get_memory_ranges(struct memory_range **range, int *ranges,
 				unsigned long kexec_flags)
 {
-	int memory_ranges;
-	/*
-	 * /proc/iomem on ia64 does not show where all memory is. If
-	 * that is fixed up, we can make use of that to validate
-	 * the memory range kernel will be loade din. Until then.....
-	 * -- Khalid Aziz
-	 */
-	
-	/* Note that the ia64 architecture mandates all systems will
-	 * have at least 64MB at 0-64M.  The SGI altix does not follow
-	 * that restriction, but a reasonable guess is better than nothing
-	 * at all.
-	 * -- Eric Biederman
-	 */
-	fprintf(stderr, "Warning assuming memory at 0-64MB is present\n");
-	memory_ranges = 0;
-	memory_range[memory_ranges].start = 0x00010000;
-	memory_range[memory_ranges].end   = 0x10000000;
-	memory_range[memory_ranges].type  = RANGE_RAM;
-	memory_ranges++;
-	*range = memory_range;
-	*ranges = memory_ranges;
-	return 0;
+	const char iomem[]= "/proc/iomem";
+	int memory_ranges = 0;
+	char line[MAX_LINE];
+	FILE *fp;
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n",
+			iomem, strerror(errno));
+		return -1;
+	}
+
+	while(fgets(line, sizeof(line), fp) != 0) {
+		unsigned long start, end;
+		char *str;
+		int type;
+		int consumed;
+		int count;
+		if (memory_ranges >= MAX_MEMORY_RANGES)
+			break;
+		count = sscanf(line, "%lx-%lx : %n",
+				&start, &end, &consumed);
+		if (count != 2)
+			continue;
+		str = line + consumed;
+		end = end + 1;
+		if (memcmp(str, "System RAM\n", 11) == 0) {
+			type = RANGE_RAM;
+		}
+		else if (memcmp(str, "reserved\n", 9) == 0) {
+			type = RANGE_RESERVED;
+		}
+		else if (memcmp(str, "Crash kernel\n", 13) == 0) {
+			/* Redefine the memory region boundaries if kernel
+			 * exports the limits and if it is panic kernel.
+			 * Override user values only if kernel exported
+			 * values are subset of user defined values.
+			 */
+
+			if (kexec_flags & KEXEC_ON_CRASH) {
+				if (start > mem_min)
+					mem_min = start;
+				if (end < mem_max)
+					mem_max = end;
+			}
+			continue;
+		} else
+			continue;
+		/*
+		 * Check if this memory range can be coalesced with
+		 * the previous range
+		 */
+		if ((memory_ranges > 0) &&
+			(start == memory_range[memory_ranges-1].end) &&
+			(type == memory_range[memory_ranges-1].type)) {
+			memory_range[memory_ranges-1].end = end;
+		}
+		else {
+			memory_range[memory_ranges].start = start;
+			memory_range[memory_ranges].end = end;
+			memory_range[memory_ranges].type = type;
+			memory_ranges++;
+		}
+	}
+	fclose(fp);
+ 	*range = memory_range;
+ 	*ranges = memory_ranges;
+
+ 	return 0;
 }
 
 /* Supported file types and callbacks */
@@ -76,9 +121,6 @@
 {
 }
 
-static struct {
-} arch_options = {
-};
 int arch_process_options(int argc, char **argv)
 {
 	static const struct option options[] = {
@@ -88,6 +130,12 @@
 	static const char short_options[] = KEXEC_ARCH_OPT_STR;
 	int opt;
 
+	/* execute from monarch processor */
+	cpu_set_t affinity;
+	CPU_ZERO(&affinity);
+	CPU_SET(0, &affinity);
+	sched_setaffinity(0, sizeof(affinity), &affinity);
+
 	opterr = 0; /* Don't complain about unrecognized options here */
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch(opt) {
@@ -113,10 +161,7 @@
 	}
 	if (strcmp(utsname.machine, "ia64") == 0)
 	{
-		/* For compatibility with older patches 
-		 * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here.
-		 */
-		info->kexec_flags |= KEXEC_ARCH_DEFAULT;
+		info->kexec_flags |= KEXEC_ARCH_IA_64;
 	}
 	else {
 		fprintf(stderr, "Unsupported machine type: %s\n",
--- kexec-tools-1.101/kexec/kexec.8.orig	2004-12-19 17:27:31.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.8	2006-10-20 13:39:08.000000000 -0400
@@ -2,7 +2,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH KEXEC-TOOLS 8 "October 13, 2004"
+.TH KEXEC 8 "October 13, 2004"
 .\" Please adjust this date whenever revising the manpage.
 .\"
 .\" Some roff macros, for reference:
@@ -16,30 +16,60 @@
 .\" .sp <n>    insert n+1 empty lines
 .\" for manpage-specific macros, see man(7)
 .SH NAME
-kexec-tools \- Tool to load a kernel for warm reboot and initiate a warm reboot
+kexec \- Tool to load a kernel for warm reboot and initiate a warm reboot
 .SH SYNOPSIS
-.B kexec-tools
+.B kexec
 .RI [ options ] " files" ...
 .SH DESCRIPTION
 .PP
 .\" TeX users may be more comfortable with the \fB<whatever>\fP and
 .\" \fI<whatever>\fP escape sequences to invode bold face and italics, 
 .\" respectively.
-\fBkexec-tools\fP does not have a man page yet. Please use "kexec -h" for help.
+\fBkexec\fP allows one to load another kernel from the currently running
+Linux kernel. Normally one would load a kernel, and possibly an initial
+ramdisk, into the currently running kernel using kexec and then initiate
+a warm reboot by executing kexec again with appropriate option.
 .SH OPTIONS
 These programs follow the usual GNU command line syntax, with long
 options starting with two dashes (`-').
 A summary of options is included below.
-For a complete description, see the Info files.
 .TP
 .B \-h, \-\-help
 Show summary of options.
 .TP
 .B \-v, \-\-version
 Show version of program.
-.SH SEE ALSO
+.TP
+.B \-f, \-\-force
+Force an immediate kexec without calling shutdown.
+.TP
+.B \-x, \-\-no-ifdown
+Don't bring down network interfaces. (if used, must be last option specified)
+.TP
+.B \-l, \-\-load
+Load the new kernel into the current kernel.
+.TP
+.B \-p, \-\-load-panic
+Load the new kernel for use on panic.
+.TP
+.B \-u, \-\-unload
+Unload the current kexec target kernel.
+.TP
+.B \-e, \-\-exec
+Execute a currently loaded kernel.
+.TP
+.B \-t, \-\-type=TYPE
+Specify the new kernel is of this type.
+.TP
+.B \-\-mem\-min=<addr>
+Specify the lowest memory addres to load code into.
+.TP
+.B \-\-mem\-max=<addr>
+Specify the highest memory addres to load code into.
+.TP
+There may be additional options supported on individual architectures.  Use --help option to see those options.
 .SH AUTHOR
-kexec-tools was written by Eric Biederman.
+kexec was written by Eric Biederman.
 .PP
-This manual page was written by Khalid Aziz <khalid_aziz at hp.com>,
+This manual page was written by Khalid Aziz <khalid.aziz at hp.com>,
 for the Debian project (but may be used by others).

kexec-tools-1.101-ifdown.patch:
 kexec.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+)

--- NEW FILE kexec-tools-1.101-ifdown.patch ---
--- kexec-tools-1.101/kexec/kexec.c.orig1	2006-10-13 14:01:39.000000000 -0400
+++ kexec-tools-1.101/kexec/kexec.c	2006-10-13 14:10:28.000000000 -0400
@@ -698,6 +698,19 @@ void usage(void)
 	printf("\n");
 }
 
+static int kexec_loaded(void)
+{
+	int ret;
+	FILE *fp;
+
+	fp = fopen("/sys/kernel/kexec_loaded", "r");
+	if (fp == NULL)
+		return -1;
+	fscanf(fp, "%d", &ret);
+	fclose(fp);
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	int do_load = 1;
@@ -801,6 +814,10 @@ int main(int argc, char *argv[])
 	if (do_load && (result == 0)) {
 		result = my_load(type, fileind, argc, argv, kexec_flags);
 	}
+	/* Don't shutdown unless there is something to reboot to! */
+	if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded()) {
+		die("Nothing has been loaded!\n");
+	}
 	if ((result == 0) && do_shutdown) {
 		result = my_shutdown();
 	}

kexec-tools-1.101-makedumpfile-configfile.patch:
 Makefile               |    2 
 dwarfinfo/dwarf_incl.h |   11 
 dwarfinfo/dwarfdump.c  |    8 
 dwarfinfo/print_die.c  |   20 +
 makedumpfile.c         |  767 ++++++++++++++++++++++++++++++++++++++-----------
 makedumpfile.h         |   27 +
 makedumpfile.h.orig    |only
 7 files changed, 663 insertions(+), 172 deletions(-)

--- NEW FILE kexec-tools-1.101-makedumpfile-configfile.patch ---
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarfdump.c kexec-tools-1.101/makedumpfile/dwarfinfo/dwarfdump.c
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarfdump.c	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/dwarfdump.c	2006-09-07 10:09:25.000000000 -0400
@@ -107,18 +107,18 @@ main(int argc, char *argv[])
 	dwarf_info.no_of_member = 3;
 	dwarf_info.cur_member = DWARF_INFO_MAX;
 	dwarf_info.member[0].name = "flags";
-	dwarf_info.member[0].offset = 0;
+	dwarf_info.member[0].offset = -1;
 	dwarf_info.member[1].name = "_count";
-	dwarf_info.member[1].offset = 0;
+	dwarf_info.member[1].offset = -1;
 
 	if (argc >= 3 && !strcmp(argv[2], "15")) {
 		dwarf_info.location_member = DWARF_INFO_MAX;
 		dwarf_info.member[2].name = "mapping";
-		dwarf_info.member[2].offset = 0;
+		dwarf_info.member[2].offset = -1;
 	} else {
 		dwarf_info.location_member = 2;
 		dwarf_info.member[2].name = NULL; /* has no name */
-		dwarf_info.member[2].offset = 0;
+		dwarf_info.member[2].offset = -1;
 	}
 
 	dwarfinfo();
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarf_incl.h kexec-tools-1.101/makedumpfile/dwarfinfo/dwarf_incl.h
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/dwarf_incl.h	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/dwarf_incl.h	2006-09-07 10:09:25.000000000 -0400
@@ -64,13 +64,14 @@
 #define	DWARF_INFO_TAG_MEMBER		0x0002
 #define	DWARF_INFO_DONE			0x0004
 #define DWARF_INFO_FILE_NAME_MATCH	0x0008
-#define DWARF_INFO_STRUCT_SIZE_DONE	0x0010
-#define DWARF_INFO_NAME_FOUND		0x0020
-#define DWARF_INFO_NAME_MATCH		0x0040
-#define	DWARF_INFO_OFFSET_DONE		0x0080
+#define DWARF_INFO_STRUCT_NAME_MATCH	0x0010
+#define DWARF_INFO_STRUCT_SIZE_DONE	0x0020
+#define DWARF_INFO_NAME_FOUND		0x0040
+#define DWARF_INFO_NAME_MATCH		0x0080
+#define	DWARF_INFO_OFFSET_DONE		0x0100
 #define DWARF_INFO_MEMBER_DONE		0x1000
 #define DWARF_INFO_STATUS_SHIFT		4
-#define DWARF_INFO_MAX			3
+#define DWARF_INFO_MAX			5
 
 struct dwarf_info {
 	unsigned long	status;		/* TEMP */
diff -urp kexec-tools-1.101-orig/makedumpfile/dwarfinfo/print_die.c kexec-tools-1.101/makedumpfile/dwarfinfo/print_die.c
--- kexec-tools-1.101-orig/makedumpfile/dwarfinfo/print_die.c	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/dwarfinfo/print_die.c	2006-09-07 10:09:25.000000000 -0400
@@ -171,6 +171,12 @@ print_one_die(Dwarf_Debug dbg, Dwarf_Die
     tres = dwarf_tag(die, &tag, &err);
     dwarf_info.tmp_status = 0;
     if (tag == DW_TAG_structure_type) {
+	if ((dwarf_info.status &
+	    (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE))
+	    == (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE)) {
+	    dwarf_info.status |= DWARF_INFO_DONE;
+	    return;
+	}
         dwarf_info.status = DWARF_INFO_TAG_STRUCT;
 #ifdef DEBUG
 	fprintf(stderr, "DWARF_INFO_TAG_STRUCT set 1\n"); /* debug */
@@ -181,6 +187,12 @@ print_one_die(Dwarf_Debug dbg, Dwarf_Die
 	fprintf(stderr, "DWARF_INFO_TAG_MEMBER set 1\n"); /* debug */
 #endif
     } else {
+	if ((dwarf_info.status &
+	    (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE))
+	    == (DWARF_INFO_STRUCT_NAME_MATCH | DWARF_INFO_STRUCT_SIZE_DONE)) {
+	    dwarf_info.status |= DWARF_INFO_DONE;
+	    return;
+	}
         dwarf_info.status = 0;
         return;
     }
@@ -834,8 +846,11 @@ get_attr_value(Dwarf_Debug dbg, Dwarf_Ha
 		if (attr == DW_AT_name) {
 		    if (dwarf_info.status & DWARF_INFO_TAG_STRUCT) {
 			if (!(dwarf_info.status & DWARF_INFO_TAG_MEMBER)) {
-			    if (strcmp(temps, dwarf_info.struct_name)) {
+			    if (!strcmp(temps, dwarf_info.struct_name)) {
+				dwarf_info.status |= DWARF_INFO_STRUCT_NAME_MATCH;
+			    } else {
 				dwarf_info.status &= ~DWARF_INFO_TAG_STRUCT;
+				dwarf_info.status &= ~DWARF_INFO_STRUCT_NAME_MATCH;
 #ifdef DEBUG
 	fprintf(stderr, "DWARF_INFO_TAG_STRUCT reset 4\n"); /* debug */
 #endif
@@ -846,9 +861,6 @@ get_attr_value(Dwarf_Debug dbg, Dwarf_Ha
 				if (dwarf_info.member[i].name == NULL) {
 				    continue;
 				}
-#ifdef DEBUG
-	fprintf(stderr, "&dwarf_info.member[ %d ].name = %p\n", i, &dwarf_info.member[i].name[0]); /* debug */
-#endif
 				if (strcmp(temps, dwarf_info.member[i].name) == 0) {
 				    dwarf_info.cur_member = i;
 				    dwarf_info.tmp_status |= DWARF_INFO_NAME_MATCH;
diff -urp kexec-tools-1.101-orig/makedumpfile/makedumpfile.c kexec-tools-1.101/makedumpfile/makedumpfile.c
--- kexec-tools-1.101-orig/makedumpfile/makedumpfile.c	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/makedumpfile.c	2006-09-07 10:09:39.000000000 -0400
@@ -193,7 +193,7 @@ vaddr_to_fileoffset(struct DumpInfo *inf
  * Get the number of the page descriptors from the ELF info.
  */
 unsigned int
-num_page_descriptor(struct DumpInfo *info)
+get_max_mapnr(struct DumpInfo *info)
 {
 	int i;
 	off_t max_paddr;
@@ -234,22 +234,101 @@ readmem(struct DumpInfo *info, unsigned 
 	return size;
 }
 
+int
+get_kernel_version(char *release)
+{
+	if (!strncmp(release, "2.6.15", strlen("2.6.15"))) {
+		return VERSION_2_6_15;
+	} else if (!strncmp(release, "2.6.16", strlen("2.6.16"))) {
+		return VERSION_2_6_16;
+	} else if (!strncmp(release, "2.6.17", strlen("2.6.17"))) {
+		return VERSION_2_6_17;
+	} else if (!strncmp(release, "2.6.18", strlen("2.6.18"))) {
+		return VERSION_2_6_18;
+	} else {
+		ERRMSG("Can't get kernel version from system_utsname.\n");
+		return FALSE;
+	}
+}
+
+int
+is_page_size(unsigned long page_size)
+{
+	unsigned long bitbuf = page_size;
+	unsigned int i, sum = 0;
+
+	/* Only 1 bit is set because of page size. */
+	for (i = 0; i < sizeof(bitbuf) * 8; i++) {
+		sum += bitbuf & 1;
+		bitbuf = bitbuf >> 1;
+	}
+	if (sum != 1) {
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int
+check_release(struct DumpInfo *info)
+{
+	unsigned long sym_system_utsname;
+	struct utsname system_utsname;
+
+	sym_system_utsname = info->sym_system_utsname;
+	/*
+	 * Get the kernel version from the symbol "system_utsname".
+	 */
+	if (!sym_system_utsname) {
+		ERRMSG("Can't get the symbol of system_utsname.\n");
+		return FALSE;
+	}
+	if (!readmem(info, sym_system_utsname, &system_utsname, sizeof(struct utsname))) {
+		ERRMSG("Can't get the address of system_utsname.\n");
+		return FALSE;
+	}
+
+	if (info->flag_read_config) {
+		if (strcmp(system_utsname.release, info->release)) {
+			ERRMSG("%s doesn't suit the dump_mem.\n", info->name_configfile);
+			info->retcd = WRONG_RELEASE;
+			return FALSE;
+		}
+	}
+
+	info->kernel_version = get_kernel_version(system_utsname.release);
+	if (info->kernel_version == FALSE)
+		return FALSE;
+
+	return TRUE;
+}
+
 void
 print_usage()
 {
 	MSG("\n");
 	MSG("Usage:\n");
-	MSG("  makedumpfile [-c|-E] [-d dump_level] [-x vmlinux] [map_file] dump_mem dump_file\n");
+	MSG("  makedumpfile [-c|-E] [-d dump_level] [-g config_file]|[-i config_file]\n");
+	MSG("  [-x vmlinux] [map_file] dump_mem dump_file\n");
+	MSG("\n");
+	MSG("  Making dump_file with vmlinux and map_file:\n");
+	MSG("    makedumpfile [-c|-E] [-d dump_level] -x vmlinux map_file dump_mem dump_file\n");
+	MSG("\n");
+	MSG("  Making dump_file with config_file:\n");
+	MSG("    makedumpfile [-c|-E] [-d dump_level] -i config_file dump_mem dump_file\n");
+	MSG("\n");
+	MSG("  Generating config_file:\n");
+	MSG("    makedumpfile -g config_file -x vmlinux map_file\n");
 	MSG("\n");
 	MSG("Available options:\n");
 	MSG("  [-c]:\n");
 	MSG("      This option enables the compression function of each page.\n");
-	MSG("      This is only for crash.\n");
+	MSG("      You can not specify this opiton with [-E].\n");
+	MSG("      This is only for crash. [dump_mem] and [dump_file] must be specified.\n");
 	MSG("\n");
 	MSG("  [-E]:\n");
 	MSG("      Create the ELF dump file.\n");
 	MSG("      You can not specify this opiton with [-c].\n");
-	MSG("      This is only for gdb.\n");
+	MSG("      This is only for gdb. [dump_mem] and [dump_file] must be specified.\n");
 	MSG("\n");
 	MSG("  [-d dump_level]:\n");
 	MSG("      This is specification of the skipped pages. \n");
@@ -275,14 +354,40 @@ print_usage()
 //	MSG("        14  |         X       X        X\n");
 	MSG("        15  |  X      X       X        X\n");
 	MSG("\n");
+	MSG("      [-i config_file] or ([-x vmlinux] and [map_file]) must be specified,\n");
+	MSG("      when dump_level is two or more.\n");
+	MSG("      [dump_mem] and [dump_file] must be specified.\n");
+	MSG("\n");
+	MSG("  [-g config_file]:\n");
+	MSG("      Generate the configuration file. Debugging information\n");
+	MSG("      necessary for executing a partial dump is output to this file. A partial\n");
+	MSG("      dump can be executed even if the output this file is read by -i option,\n");
+	MSG("      and there is no kernel file with debugging information. When this option\n");
+	MSG("      is specified, the dump is not output. [-x vmlinux] and [map_file] must\n");
+	MSG("      be specified.\n");
+	MSG("\n");
+	MSG("  [-i config_file]:\n");
+	MSG("      Read the configuration file. This file is the one\n");
+	MSG("      output beforehand by specifying -g option, and debugging information\n");
+	MSG("      necessary for executing a partial dump is contained. A partial dump can\n");
+	MSG("      be executed even if this file is read, and there is no kernel file with\n");
+	MSG("      debugging information. When this option is specified, -g option,\n");
+	MSG("      [-x vmlinux], and [map_file] cannot be specified.\n");
+	MSG("      Note:\n");
+	MSG("      When this file is not specified, this command uses the page size of\n");
+	MSG("      the system under operation(Capture kernel) as the one of dump_mem\n");
+	MSG("      (First-kernel).\n");
+	MSG("\n");
 	MSG("  [-x vmlinux]:\n");
-	MSG("      This is a pathname to a vmlinux file compiled with -g option\n");
-	MSG("      for first-kernel.\n");
-	MSG("      This is necessary when dump_level is 2 or more.\n");
+	MSG("      This is a pathname to the first-kernel's vmlinux file compiled with\n");
+	MSG("      -g option.\n");
+	MSG("      This is necessary when dump_level is 2 or more and [-i config_file] is\n");
+	MSG("      not specified.\n");
 	MSG("\n");
 	MSG("  [map_file]:\n");
-	MSG("      This is a pathname to a system.map file of first-kernel.\n");
-	MSG("      This is necessary when dump_level is 2 or more.\n");
+	MSG("      This is a pathname to a System.map file of first-kernel.\n");
+	MSG("      This is necessary when dump_level is 2 or more and [-i config_file]\n");
+	MSG("      is not specified. [-x vmlinux] must be specified.\n");
 	MSG("\n");
 	MSG("  dump_mem:\n");
 	MSG("      This is a pathname to a first-kernel memory core image.\n");
@@ -312,6 +417,20 @@ open_system_map(struct DumpInfo *info)
 }
 
 int
+open_config_file(struct DumpInfo *info, char *mode)
+{
+	FILE *file_configfile;
+
+	if ((file_configfile = fopen(info->name_configfile, mode)) == NULL) {
+		ERRMSG("Can't open the config file(%s). %s\n",
+		info->name_configfile, strerror(errno));
+		return FALSE;
+	}
+	info->file_configfile = file_configfile;
+	return TRUE;
+}
+
+int
 open_dump_memory(struct DumpInfo *info)
 {
 	int fd;
@@ -322,7 +441,6 @@ open_dump_memory(struct DumpInfo *info)
 		return FALSE;
 	}
 	info->fd_memory = fd;
-
 	return TRUE;
 }
 
@@ -364,6 +482,65 @@ open_dump_bitmap(struct DumpInfo *info)
 	return TRUE;
 }
 
+/*
+ * Open the following files when it generates the configuration file.
+ * - vmlinux
+ * - system.map
+ * - configuration file
+ */
+int
+open_files_for_generating_configfile(struct DumpInfo *info)
+{
+	if ((dwarf_info.vmlinux_fd
+	    = open_kernel_file(dwarf_info.vmlinux_name)) == -1)
+		return FALSE;
+
+	if (!open_system_map(info))
+		return FALSE;
+
+	if (!open_config_file(info, "w"))
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * Open the following files when it creates the dump file.
+ * - dump mem
+ * - dump file
+ * - bit map
+ * if it reads the configuration file
+ *   - configuration file
+ * else
+ *   - vmlinux
+ *   - system.map
+ */
+int
+open_files_for_creating_dumpfile(struct DumpInfo *info)
+{
+	if (info->flag_read_config) {
+		if (!open_config_file(info, "r"))
+			return FALSE;
+	} else if (info->dump_level >= 2) {
+		if ((dwarf_info.vmlinux_fd
+		    = open_kernel_file(dwarf_info.vmlinux_name)) == -1)
+			return FALSE;
+
+		if (!open_system_map(info))
+			return FALSE;
+	}
+	if (!open_dump_memory(info))
+		return FALSE;
+
+	if (!open_dump_file(info))
+		return FALSE;
+
+	if (!open_dump_bitmap(info))
+		return FALSE;
+
+	return TRUE;
+}
+
 int
 dump_Elf32_pt_load(struct DumpInfo *info, Elf32_Phdr *prog, int num_load)
 {
@@ -380,7 +557,6 @@ dump_Elf32_pt_load(struct DumpInfo *info
 	pls->virt_start  = prog->p_vaddr;
 	pls->virt_end    = pls->virt_start + prog->p_filesz;
 	pls->file_offset = prog->p_offset;
-
 	return TRUE;
 }
 
@@ -407,6 +583,7 @@ int
 get_elf_info(struct DumpInfo *info)
 {
 	int i;
+	unsigned long tmp;
 	const off_t failed = (off_t)-1;
 
 	Elf32_Ehdr *elf32;
@@ -436,7 +613,6 @@ get_elf_info(struct DumpInfo *info)
 		       &header[sizeof(Elf32_Ehdr)+sizeof(Elf32_Phdr)];
 		info->num_load_memory    = elf32->e_phnum - 1;
 		info->offset_load_memory = (Elf32_Off)load32->p_offset;
-		info->page_size = (uint32_t)load32->p_align;
 	} else if (STRNEQ(elf64->e_ident, ELFMAG)
 	    && (elf64->e_ident[EI_CLASS] == ELFCLASS64)) {
 		info->flag_elf = ELF64;
@@ -444,7 +620,6 @@ get_elf_info(struct DumpInfo *info)
 		       &header[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
 		info->num_load_memory    = elf64->e_phnum - 1;
 		info->offset_load_memory = (Elf64_Off)load64->p_offset;
-		info->page_size = (uint64_t)load64->p_align;
 	} else {
 		ERRMSG("%s isn't the dump memory.\n", info->name_memory);
 		goto out;
@@ -455,11 +630,8 @@ get_elf_info(struct DumpInfo *info)
 	 *   If the page_size of 1st-kernel is different from the one of
 	 *   capture(2nd)-kernel, the problem will happen.
 	 */
-	if (!info->page_size)
-		info->page_size = (size_t)sysconf(_SC_PAGE_SIZE);
 	if (!info->page_size) {
-		ERRMSG("Can't get the size of page.\n");
-		goto out;
+		info->page_size = sysconf(_SC_PAGE_SIZE);
 	}
 	if (!info->num_load_memory) {
 		ERRMSG("Can't get the number of PT_LOAD.\n");
@@ -517,6 +689,11 @@ get_elf_info(struct DumpInfo *info)
 			if(!dump_Elf64_pt_load(info, load64 + i, i))
 				goto out;
 	}
+	info->max_mapnr = get_max_mapnr(info);
+	tmp = 2*divideup(info->max_mapnr, BITPERBYTE);
+	tmp = divideup(tmp, info->page_size);
+	info->len_bitmap = tmp*info->page_size;
+
 	g_free(tmp_elf_header);
 	return TRUE;
 out:
@@ -528,21 +705,16 @@ out:
 int
 get_symbol_info(struct DumpInfo *info)
 {
-	unsigned int max_mapnr;
-	unsigned long sym_mem_map = 0, sym_num_physpages = 0;
+	unsigned long sym_mem_map = 0;
 	unsigned long sym_system_utsname = 0;
-	unsigned long addr_mem_map;
-	struct new_utsname system_utsname;
 	char buf[BUFSIZE_FGETS], *mapitems[MAXARGS], *endp;
 
 	if (info->name_sysmap == NULL) {
-		info->max_mapnr = num_page_descriptor(info);
-		info->len_bitmap = 2*divideup(info->max_mapnr, BITPERBYTE);
 		return TRUE;
 	}
 
 	/*
-	 * Get a symbol info from the System.map.
+	 * Get symbol info from the System.map.
 	 */
 	while (fgets(buf, BUFSIZE_FGETS, info->map)) {
 		if (parse_line(buf, mapitems) != 3)
@@ -557,16 +729,6 @@ get_symbol_info(struct DumpInfo *info)
 				return FALSE;
 			}
 		}
-		if (strcmp(mapitems[2], "num_physpages") == 0) {
-			sym_num_physpages = strtoul(mapitems[0], &endp, 16);
-        		if ((!sym_num_physpages
-			    || sym_num_physpages == ULONG_MAX)
-			    || strlen(endp) != 0) {
-				ERRMSG("The map file has invalid address of %s",
-				    mapitems[2]);
-				return FALSE;
-			}
-		}
 		if (strcmp(mapitems[2], "system_utsname") == 0) {
 			sym_system_utsname = strtoul(mapitems[0], &endp, 16);
         		if ((!sym_system_utsname
@@ -577,69 +739,11 @@ get_symbol_info(struct DumpInfo *info)
 				return FALSE;
 			}
 		}
-		if ((sym_mem_map != 0)
-		    && (sym_num_physpages != 0)
-		    && (sym_system_utsname != 0))
+		if (sym_mem_map != 0 && sym_system_utsname != 0)
 			break;
 	}
-
-	/*
-	 * Get the address of the symbol "mem_map".
-	 * FIXME
-	 *   If this command get the feature of analysing a struct,
-	 *   the info of the memory management will be gotten from "pgdat_list".
-	 */
-	if (!sym_mem_map) {
-		ERRMSG("Can't get the symbol of mem_map.\n");
-		return FALSE;
-	}
-	if (!readmem(info, sym_mem_map, &addr_mem_map, sizeof addr_mem_map)) {
-		ERRMSG("Can't get the address of mem_map.\n");
-		return FALSE;
-	}
-
-	if (!addr_mem_map) {
-		ERRMSG("Can't get the address of mem_map.\n");
-		return FALSE;
-	}
-	info->addr_mem_map = addr_mem_map;
-
-	/*
-	 * Get the number of the page descriptors.
-	 */
-	if (!sym_num_physpages || !readmem(info, sym_num_physpages, &max_mapnr,
-	     sizeof max_mapnr) || !max_mapnr)
-			max_mapnr = num_page_descriptor(info);
-
-	if (!max_mapnr) {
-		ERRMSG("Can't get the number of the page descriptors.\n");
-		return FALSE;
-	}
-	info->max_mapnr = max_mapnr;
-	info->len_bitmap = 2*divideup(info->max_mapnr, BITPERBYTE);
-
-	/*
-	 * Get the kernel version from the symbol "system_utsname".
-	 */
-	if (!sym_system_utsname) {
-		ERRMSG("Can't get the symbol of system_utsname.\n");
-		return FALSE;
-	}
-	if (!readmem(info, sym_system_utsname, &system_utsname, sizeof(struct new_utsname))) {
-		ERRMSG("Can't get the address of system_utsname.\n");
-		return FALSE;
-	}
-
-	if (!strncmp(system_utsname.release, "2.6.15", strlen("2.6.15"))) {
-		info->kernel_version = VERSION_2_6_15;
-	} else if (!strncmp(system_utsname.release, "2.6.16", strlen("2.6.16"))) {
-		info->kernel_version = VERSION_2_6_16;
-	} else if (!strncmp(system_utsname.release, "2.6.17", strlen("2.6.17"))) {
-		info->kernel_version = VERSION_2_6_17;
-	} else {
-		ERRMSG("Can't get kernel version from system_utsname.\n");
-		return FALSE;
-	}
+	info->sym_mem_map = sym_mem_map;
+	info->sym_system_utsname = sym_system_utsname;
 
 	return TRUE;
 }
@@ -647,9 +751,10 @@ get_symbol_info(struct DumpInfo *info)
 int
 get_pagedesc_offset(struct DumpInfo *info)
 {
+	int i;
 
 	/*
-	 * Get a offset of the page_discriptor's member.
+	 * Get offsets of the page_discriptor's members.
 	 */
 
 	dwarf_info.status = 0;
@@ -659,20 +764,23 @@ get_pagedesc_offset(struct DumpInfo *inf
 	dwarf_info.no_of_member = 3;
 	dwarf_info.cur_member = DWARF_INFO_MAX;
 	dwarf_info.member[0].name = "flags";
-	dwarf_info.member[0].offset = 0;
+	dwarf_info.member[0].offset = -1;
 	dwarf_info.member[1].name = "_count";
-	dwarf_info.member[1].offset = 0;
+	dwarf_info.member[1].offset = -1;
 	if (info->kernel_version == VERSION_2_6_15) { /* linux-2.6.15 */
 		dwarf_info.location_member = DWARF_INFO_MAX;
 		dwarf_info.member[2].name = "mapping";
-		dwarf_info.member[2].offset = 0;
+		dwarf_info.member[2].offset = -1;
 	} else {
 		dwarf_info.location_member = 2;
 		dwarf_info.member[2].name = NULL; /* has no name */
-		dwarf_info.member[2].offset = 0;
+		dwarf_info.member[2].offset = -1;
 	}
 	if (dwarfinfo())
 		return FALSE;
+	for (i = 0; i < dwarf_info.no_of_member; i++)
+		if (dwarf_info.member[i].offset == -1)
+			return FALSE;
 
 	info->size_pagedesc = dwarf_info.struct_size;
 	info->offset_page_flags  = dwarf_info.member[0].offset;
@@ -690,16 +798,248 @@ get_pagedesc_offset(struct DumpInfo *inf
 }
 
 int
-initial(struct DumpInfo *info)
+generate_config(struct DumpInfo *info)
 {
-	if (!get_elf_info(info))
+	struct utsname utsname_buf;
+	long tmp_long;
+
+	/*
+	 * write 1st kernel's OSRELEASE
+	 */
+	if (uname(&utsname_buf)) {
+		ERRMSG("Can't get uname. %s\n", strerror(errno));
 		return FALSE;
+	}
+	fprintf(info->file_configfile, "%s%s\n", STR_OSRELEASE,
+	    utsname_buf.release);
 
+	/*
+	 * write 1st kernel's PAGESIZE
+	 */
+	if (!info->page_size) {
+		tmp_long = sysconf(_SC_PAGE_SIZE);
+		if (tmp_long == -1) {
+			ERRMSG("Can't get the size of page.\n");
+			return FALSE;
+		}
+		info->page_size = (size_t)tmp_long;
+	}
+	fprintf(info->file_configfile, "%s%d\n", STR_PAGESIZE,
+	    (int)info->page_size);
+
+	/*
+	 * write 1st kernel's address of SYMBOL(mem_map)
+	 */
 	if (!get_symbol_info(info))
 		return FALSE;
+	if (!info->sym_mem_map || !info->sym_system_utsname) {
+		ERRMSG("Can't get the symbol of mem_map.\n");
+		return FALSE;
+	}
+	fprintf(info->file_configfile, "%s%lx\n", STR_SYMBOL("mem_map"),
+	    info->sym_mem_map);
+
+	/*
+	 * write 1st kernel's address of SYMBOL(system_utsname)
+	 */
+	fprintf(info->file_configfile, "%s%lx\n", STR_SYMBOL("system_utsname"),
+	    info->sym_system_utsname);
+
+	/*
+	 * get 1st kernel's version
+	 */
+	info->kernel_version = get_kernel_version(utsname_buf.release);
+	if (info->kernel_version == FALSE)
+		return FALSE;
 
+	/*
+	 * write 1st kernel's size of struct page
+	 */
 	if (!get_pagedesc_offset(info))
 		return FALSE;
+	fprintf(info->file_configfile, "%s%d\n", STR_SIZE("page"),
+	    info->size_pagedesc);
+
+	/*
+	 * write 1st kernel's offset of page.flags
+	 */
+	fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page.flags"),
+	    info->offset_page_flags);
+
+	/*
+	 * write 1st kernel's offset of page._count
+	 */
+	fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page._count"),
+	    info->offset_page__count);
+
+	/*
+	 * write 1st kernel's offset of page.mapping
+	 */
+	fprintf(info->file_configfile, "%s%d\n", STR_OFFSET("page.mapping"),
+	    info->offset_page_mapping);
+
+	return TRUE;
+}
+
+int
+read_config(struct DumpInfo *info)
+{
+	unsigned long tmp_ulong;
+	char buf[BUFSIZE_FGETS], *endp;
+	unsigned int ok_flag = 0, i;
+
+	while (fgets(buf, BUFSIZE_FGETS, info->file_configfile)) {
+		i = strlen(buf);
+		if (buf[i - 1] == '\n')
+			buf[i - 1] = '\0';
+		if (strncmp(buf, STR_OSRELEASE, strlen(STR_OSRELEASE)) == 0) {
+			strcpy(info->release, buf + strlen(STR_OSRELEASE));
+			ok_flag = 1;
+		}
+		if (strncmp(buf, STR_PAGESIZE, strlen(STR_PAGESIZE)) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_PAGESIZE), &endp, 10);
+	       		if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			if (!is_page_size(tmp_ulong)) {
+				ERRMSG("Invalid data in %s: %s",
+				info->name_configfile, buf);
+				return FALSE;
+			}
+			info->page_size = tmp_ulong;
+		}
+		if (strncmp(buf, STR_SYMBOL("mem_map"), strlen(STR_SYMBOL("mem_map"))) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_SYMBOL("mem_map")),
+				&endp, 16);
+	       		if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->sym_mem_map = tmp_ulong;
+		}
+		if (strncmp(buf, STR_SYMBOL("system_utsname"), strlen(STR_SYMBOL("system_utsname"))) == 0) {
+			tmp_ulong = strtoul(buf
+				+ strlen(STR_SYMBOL("system_utsname")), &endp, 16);
+        		if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->sym_system_utsname = tmp_ulong;
+		}
+		if (strncmp(buf, STR_SIZE("page"), strlen(STR_SIZE("page"))) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_SIZE("page")), &endp, 10);
+	       		if ((!tmp_ulong || tmp_ulong == ULONG_MAX)
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->size_pagedesc = tmp_ulong;
+		}
+		if (strncmp(buf, STR_OFFSET("page.flags"), strlen(STR_OFFSET("page.flags"))) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page.flags")),
+				&endp, 10);
+	       		if (tmp_ulong == ULONG_MAX
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->offset_page_flags = tmp_ulong;
+		}
+		if (strncmp(buf, STR_OFFSET("page._count"), strlen(STR_OFFSET("page._count"))) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page._count")),
+				&endp, 10);
+	       		if (tmp_ulong == ULONG_MAX
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->offset_page__count = tmp_ulong;
+		}
+		if (strncmp(buf, STR_OFFSET("page.mapping"), strlen(STR_OFFSET("page.mapping"))) == 0) {
+			tmp_ulong = strtoul(buf + strlen(STR_OFFSET("page.mapping")),
+				&endp, 10);
+	       		if (tmp_ulong == ULONG_MAX
+			    || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+					info->name_configfile, buf);
+				return FALSE;
+			}
+			info->offset_page_mapping = tmp_ulong;
+		}
+	}
+	if (!ok_flag || !info->page_size) {
+		ERRMSG("Invalid format in %s", info->name_configfile);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+int
+get_mem_map(struct DumpInfo *info)
+{
+	unsigned long sym_mem_map = info->sym_mem_map;
+	unsigned long addr_mem_map;
+
+	/*
+	 * Get the address of the symbol "mem_map".
+	 * FIXME
+	 *   If this command get the feature of analysing a struct,
+	 *   the info of the memory management will be gotten from "pgdat_list".
+	 */
+	if (!sym_mem_map) {
+		ERRMSG("Can't get the symbol of mem_map.\n");
+		return FALSE;
+	}
+	if (!readmem(info, sym_mem_map, &addr_mem_map, sizeof addr_mem_map)) {
+		ERRMSG("Can't get the address of mem_map.\n");
+		return FALSE;
+	}
+	if (!addr_mem_map) {
+		ERRMSG("Can't get the address of mem_map.\n");
+		return FALSE;
+	}
+	info->addr_mem_map = addr_mem_map;
+
+	return TRUE;
+}
+
+int
+initial(struct DumpInfo *info)
+{
+	if (!get_elf_info(info))
+		return FALSE;
+
+	if (!info->flag_read_config) {
+		if (info->dump_level <= 1)
+			return TRUE;
+		if (!get_symbol_info(info))
+			return FALSE;
+		if (!check_release(info))
+			return FALSE;
+		if (!get_pagedesc_offset(info))
+			return FALSE;
+	} else {
+		if (!read_config(info))
+			return FALSE;
+		if (!info->sym_mem_map || !info->sym_system_utsname) {
+			ERRMSG("Invalid format in %s", info->name_configfile);
+			return FALSE;
+		}
+		if (!check_release(info))
+			return FALSE;
+	}
+	if (!get_mem_map(info))
+		return FALSE;
 
 	return TRUE;
 }
@@ -997,7 +1337,8 @@ create_dump_bitmap(struct DumpInfo *info
 		    strerror(errno));
 		goto out;
 	}
-	if ((page_cache = g_malloc(info->size_pagedesc*PGMM_CACHED)) == NULL) {
+	if (info->dump_level > DL_EXCLUDE_ZERO &&
+	    (page_cache = g_malloc(info->size_pagedesc*PGMM_CACHED)) == NULL) {
 		ERRMSG("Can't allocate memory for the pagedesc cache. %s\n",
 		    strerror(errno));
 		goto out;
@@ -1135,7 +1476,8 @@ create_dump_bitmap(struct DumpInfo *info
 	if (info->flag_elf_dumpfile && !create_contig_bitmap(info))
 		goto out;
 
-	g_free(page_cache);
+	if (page_cache != NULL)
+		g_free(page_cache);
 	g_free(buf);
 	g_free(bm1.buf);
 	g_free(bm2.buf);
@@ -1625,6 +1967,8 @@ write_pages(struct DumpInfo *info)
 				if (!write_cache_bufsz(&bm2))
 					goto out;
 			}
+			if (info->len_bitmap - bm2.offset < BUFSIZE_BITMAP)
+				bm2.cache_size = info->len_bitmap - bm2.offset;
 			if (!read_cache(&bm2))
 				goto out;
 			flag_change_bitmap = 0;
@@ -1751,7 +2095,7 @@ out:
 int write_dump_bitmap(struct DumpInfo *info)
 {
 	struct cache_data bm;
-	unsigned long buf_size;
+	long buf_size;
 	const off_t failed = (off_t)-1;
 
 	if (info->flag_elf_dumpfile)
@@ -1812,6 +2156,14 @@ close_system_map(struct DumpInfo *info)
 }
 
 void
+close_config_file(struct DumpInfo *info)
+{
+	if(fclose(info->file_configfile) < 0)
+		ERRMSG("Can't close the config file(%s). %s\n",
+		info->name_configfile, strerror(errno));
+}
+
+void
 close_dump_memory(struct DumpInfo *info)
 {
 	if (close(info->fd_memory) < 0)
@@ -1844,6 +2196,54 @@ close_kernel_file(int fd)
 			dwarf_info.vmlinux_name, strerror(errno));
 }
 
+/*
+ * Close the following files when it generates the configuration file.
+ * - vmlinux
+ * - system.map
+ * - configuration file
+ */
+int
+close_files_for_generating_configfile(struct DumpInfo *info)
+{
+	close_kernel_file(dwarf_info.vmlinux_fd);
+
+	close_system_map(info);
+
+	close_config_file(info);
+
+	return TRUE;
+}
+
+/*
+ * Close the following files when it creates the dump file.
+ * - dump mem
+ * - dump file
+ * - bit map
+ * if it reads the configuration file
+ *   - configuration file
+ * else
+ *   - vmlinux
+ *   - system.map
+ */
+int
+close_files_for_creating_dumpfile(struct DumpInfo *info)
+{
+	if (info->flag_read_config) {
+		close_config_file(info);
+	} else if (info->dump_level >= 2) {
+		close_kernel_file(dwarf_info.vmlinux_fd);
+
+		close_system_map(info);
+	}
+	close_dump_memory(info);
+
+	close_dump_file(info);
+
+	close_dump_bitmap(info);
+
+	return TRUE;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -1862,7 +2262,7 @@ main(int argc, char *argv[])
 		goto out;
 	}
 
-	while ((opt = getopt(argc, argv, "b:cd:Ex:")) != -1) {
+	while ((opt = getopt(argc, argv, "b:cd:Eg:i:x:")) != -1) {
 		switch (opt) {
 		case 'b':
 			info->block_order = atoi(optarg);
@@ -1876,7 +2276,16 @@ main(int argc, char *argv[])
 		case 'E':
 			info->flag_elf_dumpfile = 1;
 			break;
+		case 'g':
+			info->flag_generate_config = 1;
+			info->name_configfile = optarg;
+			break;
+		case 'i':
+			info->flag_read_config = 1;
+			info->name_configfile = optarg;
+			break;
 		case 'x':
+			info->flag_vmlinux = 1;
 			dwarf_info.vmlinux_name = optarg;
 			break;
 		case '?':
@@ -1885,75 +2294,114 @@ main(int argc, char *argv[])
 			goto out;
 		}
 	}
-	if ((info->dump_level < MIN_DUMP_LEVEL)
-	    || (MAX_DUMP_LEVEL < info->dump_level)) {
-		ERRMSG("Dump_level is invalid.\n");
-		print_usage();
-		goto out;
-	}
-	if ((optind + 3 < argc) 
-	    || ((info->dump_level <= 1) && (argc  < optind + 2))
-	    || ((info->dump_level >= 2) && (argc != optind + 3))
-	    || ((info->flag_compress == 1) && (info->flag_elf_dumpfile == 1))) {
-		ERRMSG("Commandline parameter is invalid.\n");
-		print_usage();
-		goto out;
-	}
-	if ((info->dump_level <= 1) && (argc == optind + 2)) {
+
+	if (info->flag_generate_config) {
+		/*
+		 * generate the configuration file
+		 */
+		if (argc != optind + 1) {
+			ERRMSG("Commandline parameter is invalid.\n");
+			print_usage();
+			goto out;
+		}
+		if (info->flag_compress || info->dump_level ||
+			info->flag_elf_dumpfile || info->flag_read_config ||
+			!info->flag_vmlinux) {
+			ERRMSG("Commandline parameter is invalid.\n");
+			print_usage();
+			goto out;
+		}
+		info->name_sysmap   = argv[optind];
+	} else if (info->flag_read_config) {
+		/*
+		 * check parameters to read the configuration file
+		 */
+		if ((info->dump_level < MIN_DUMP_LEVEL)
+		    || (MAX_DUMP_LEVEL < info->dump_level)) {
+			ERRMSG("Dump_level is invalid.\n");
+			print_usage();
+			goto out;
+		}
+		if ((argc != optind + 2)
+		    || ((info->flag_compress == 1)
+			&& (info->flag_elf_dumpfile == 1))
+			/* || info->flag_generate_config */
+			|| info->flag_vmlinux) {
+			ERRMSG("Commandline parameter is invalid.\n");
+			print_usage();
+			goto out;
+		}
 		info->name_sysmap   = NULL;
 		info->name_memory   = argv[optind];
 		info->name_dumpfile = argv[optind+1];
 	} else {
-		info->name_sysmap   = argv[optind];
-		info->name_memory   = argv[optind+1];
-		info->name_dumpfile = argv[optind+2];
+		if ((info->dump_level < MIN_DUMP_LEVEL)
+		    || (MAX_DUMP_LEVEL < info->dump_level)) {
+			ERRMSG("Dump_level is invalid.\n");
+			print_usage();
+			goto out;
+		}
+		if ((optind + 3 < argc)
+		    || ((info->dump_level <= 1) && (argc  < optind + 2))
+		    || ((info->dump_level >= 2) && (argc != optind + 3))
+		    || ((info->dump_level >= 2) && (!info->flag_vmlinux))
+		    || ((info->flag_compress == 1)
+			&& (info->flag_elf_dumpfile == 1))) {
+			ERRMSG("Commandline parameter is invalid.\n");
+			print_usage();
+			goto out;
+		}
+		if ((info->dump_level <= 1) && (argc == optind + 2)) {
+			info->name_sysmap   = NULL;
+			info->name_memory   = argv[optind];
+			info->name_dumpfile = argv[optind+1];
+		} else {
+			info->name_sysmap   = argv[optind];
+			info->name_memory   = argv[optind+1];
+			info->name_dumpfile = argv[optind+2];
+		}
 	}
 
-	if (!open_system_map(info))
-		goto out;
 
-	if (!open_dump_memory(info))
-		goto out;
-
-	if (!open_dump_file(info))
-		goto out;
-
-	if (!open_dump_bitmap(info))
-		goto out;
-
-	dwarf_info.vmlinux_fd = open_kernel_file(dwarf_info.vmlinux_name);
-	if (dwarf_info.vmlinux_fd == -1)
-		goto out;
-
-	if (!initial(info))
-		goto out;
+	if (info->flag_generate_config) {
+		if (!open_files_for_generating_configfile(info))
+			goto out;
 
-	if (!create_dump_bitmap(info))
-		goto out;
+		if (!generate_config(info))
+			goto out;
 
-	if (!write_dump_header(info))
-		goto out;
+		if (!close_files_for_generating_configfile(info))
+			goto out;
 
-	if (!write_pages(info))
-		goto out;
+		MSG("\n");
+	} else {
+		if (!open_files_for_creating_dumpfile(info))
+			goto out;
 
-	if (!write_dump_bitmap(info))
-		goto out;
+		if (!initial(info))
+			goto out;
 
-	close_system_map(info);
+		if (!create_dump_bitmap(info))
+			goto out;
 
-	close_dump_memory(info);
+		if (!write_dump_header(info))
+			goto out;
 
-	close_dump_file(info);
+		if (!write_pages(info))
+			goto out;
 
-	close_dump_bitmap(info);
+		if (!write_dump_bitmap(info))
+			goto out;
 
-	close_kernel_file(dwarf_info.vmlinux_fd);
+		if (!close_files_for_creating_dumpfile(info))
+			goto out;
 
-	MSG("\n");
-	MSG("The dumpfile is saved to %s.\n", info->name_dumpfile);
+		MSG("\n");
+		MSG("The dumpfile is saved to %s.\n", info->name_dumpfile);
+	}
 	MSG("makedumpfile Completed.\n");
-	g_free(info->pt_load_segments);
+	if (!info->flag_generate_config)
+		g_free(info->pt_load_segments);
 	g_free(info->dump_header);
 	g_free(info);
 	return COMPLETED;
@@ -1975,5 +2423,8 @@ out:
 		g_free(info->dump_header);
 	if (info != NULL)
 		g_free(info);
-	return FAILED;
+	if (info->retcd)
+		return info->retcd;
+	else
+		return FAILED;
 }
diff -urp kexec-tools-1.101-orig/makedumpfile/makedumpfile.h kexec-tools-1.101/makedumpfile/makedumpfile.h
--- kexec-tools-1.101-orig/makedumpfile/makedumpfile.h	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/makedumpfile.h	2006-09-07 10:09:39.000000000 -0400
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <errno.h>
 #include <time.h>
+#include <sys/utsname.h>
 #include <glib.h>
 #include <zlib.h>
 #include "diskdump_mod.h"
@@ -34,6 +35,9 @@
  */
 #define COMPLETED	(0)
 #define FAILED		(1)
+#define WRONG_RELEASE	(2)	/* utsname.release does not match. */
+#define ANALYSIS_FAILED	(3)	/* detected illegal page descriptor. */
+#define OUTPUT_FAILED	(4)	/* detected an output error. */
 
 /*
  * Page flags
@@ -137,6 +141,16 @@ isAnon(unsigned long mapping)
 #define VERSION_2_6_15		(15)
 #define VERSION_2_6_16		(16)
 #define VERSION_2_6_17		(17)
+#define VERSION_2_6_18		(18)
+
+/*
+ * field name of config file
+ */
+#define STR_OSRELEASE	"OSRELEASE="
+#define STR_PAGESIZE	"PAGESIZE="
+#define STR_SYMBOL(X)	"SYMBOL("X")="
+#define STR_SIZE(X)	"SIZE("X")="
+#define STR_OFFSET(X)	"OFFSET("X")="
 
 /*
  * The values of linux 2.6.15.1
@@ -187,6 +201,7 @@ struct cache_data {
 };
 
 struct DumpInfo {
+	int		retcd;		     /* return code */
 	int		size_pagedesc;       /* size of page descriptor */
 	int		offset_page_flags;   /* offset of page.flags */
 	int		offset_page__count;  /* offset of page._count */
@@ -201,6 +216,9 @@ struct DumpInfo {
 	int		flag_compress;       /* flag of compression */
 	int		flag_elf;
 	int		flag_elf_dumpfile;   /* flag of elf dump file */
+	int		flag_vmlinux;	     /* flag of vmlinux */
+	int		flag_generate_config;/* flag of generating config file */
+	int		flag_read_config;    /* flag of reading config file */
 	size_t		page_size;           /* size of page */
 	unsigned int	max_mapnr;           /* number of page descriptor */
 
@@ -245,4 +263,13 @@ struct DumpInfo {
 	 */
 	int			fd_bitmap;
 	char			*name_bitmap;
+
+	/*
+	 * config file info:
+	 */
+	FILE			*file_configfile;
+	char			*name_configfile;	     /* config file */
+	char			release[65]; /*Can I define 65 automatically?*/
+	unsigned long		sym_mem_map;
+	unsigned long		sym_system_utsname;
 };
Only in kexec-tools-1.101/makedumpfile: makedumpfile.h.orig
diff -urp kexec-tools-1.101-orig/makedumpfile/Makefile kexec-tools-1.101/makedumpfile/Makefile
--- kexec-tools-1.101-orig/makedumpfile/Makefile	2006-09-07 10:08:51.000000000 -0400
+++ kexec-tools-1.101/makedumpfile/Makefile	2006-09-07 10:09:39.000000000 -0400
@@ -77,4 +77,4 @@ readdwarfinfo: $(SRC_DEBUG) $(OBJ_DEBUG)
 	$(CC) $(CFLAGS_DEBUG) $(OBJ_DEBUG) -lelf -o $@
 
 install:
-	cp ./makedumpfile /usr/sbin
+	cp ./makedumpfile /bin

kexec-tools-1.101-ppc64-64k-pages.patch:
 kexec/arch/ppc64/crashdump-ppc64.c      |   13 +++++++------
 kexec/arch/ppc64/crashdump-ppc64.h      |   14 +++++---------
 purgatory/arch/ppc64/crashdump_backup.c |    8 +++-----
 3 files changed, 15 insertions(+), 20 deletions(-)

--- NEW FILE kexec-tools-1.101-ppc64-64k-pages.patch ---
Signed-off-by: Sachin Sant <sachinp at in.ibm.com>
---

diff -Naurp kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.c kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.c
--- kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.c	2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.c	2006-09-08 07:32:19.000000000 +0530
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>   
 #include <errno.h>
 #include <limits.h>
 #include <elf.h>
@@ -85,8 +86,8 @@ static int get_crash_memory_ranges(struc
 	unsigned long long start, end, cstart, cend;
 
 	/* create a separate program header for the backup region */
-	crash_memory_range[0].start = 0x0000000000000000;
-	crash_memory_range[0].end = 0x0000000000008000;
+	crash_memory_range[0].start = BACKUP_START;
+	crash_memory_range[0].end = BACKUP_END;
 	crash_memory_range[0].type = RANGE_RAM;
 	memory_ranges++;
 
@@ -125,8 +126,8 @@ static int get_crash_memory_ranges(struc
 				break;
 			start = ((unsigned long long *)buf)[0];
 			end = start + ((unsigned long long *)buf)[1];
-			if (start == 0 && end >= 0x8000)
-				start = 0x8000;
+			if (start == 0 && end >= BACKUP_END)
+				start = BACKUP_END;
 			match = 0;
 			sort_regions(&exclude_rgns);
 
@@ -420,8 +421,8 @@ void add_usable_mem_rgns(unsigned long l
 	unsigned long long end = base + size;
 	unsigned long long ustart, uend;
 
-	base = _ALIGN_DOWN(base, PAGE_SIZE);
-	end = _ALIGN_UP(end, PAGE_SIZE);
+	base = _ALIGN_DOWN(base, getpagesize());
+	end = _ALIGN_UP(end, getpagesize());
 
 	for (i=0; i < usablemem_rgns.size; i++) {
 		ustart = usablemem_rgns.ranges[i].start;
diff -Naurp kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.h kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.h
--- kexec-tools-rh/kexec/arch/ppc64/crashdump-ppc64.h	2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/kexec/arch/ppc64/crashdump-ppc64.h	2006-09-08 07:33:38.000000000 +0530
@@ -6,28 +6,24 @@ int load_crashdump_segments(struct kexec
 void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
 void add_exclude_rgns(unsigned long long base, unsigned long long size);
 
-#define PAGE_OFFSET      0xC000000000000000
+#define PAGE_OFFSET     0xC000000000000000
 #define KERNELBASE      PAGE_OFFSET
 #define VMALLOCBASE     0xD000000000000000
 
 #define __pa(x)         ((unsigned long)(x)-PAGE_OFFSET)
-
-#define MAXMEM                  (-KERNELBASE-VMALLOCBASE)
+#define MAXMEM          (-KERNELBASE-VMALLOCBASE)
 
 #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 6)
 
 #define COMMAND_LINE_SIZE       512 /* from kernel */
-/* Backup Region, First 32K of System RAM. */
+/* Backup Region, First 64K of System RAM. */
 #define BACKUP_START    0x0000
-#define BACKUP_END      0x8000
+#define BACKUP_END      0x10000
 #define BACKUP_SIZE     (BACKUP_END - BACKUP_START + 1)
 
-#define KDUMP_BACKUP_LIMIT      0x8000
+#define KDUMP_BACKUP_LIMIT       BACKUP_END
 #define _ALIGN_UP(addr,size)     (((addr)+((size)-1))&(~((size)-1)))
 #define _ALIGN_DOWN(addr,size)   ((addr)&(~((size)-1)))
-#ifndef PAGE_SIZE
-#define PAGE_SIZE      4096
-#endif
 
 extern unsigned long long crash_base;
 extern unsigned long long crash_size;
diff -Naurp kexec-tools-rh/purgatory/arch/ppc64/crashdump_backup.c kexec-tools-rh-fix/purgatory/arch/ppc64/crashdump_backup.c
--- kexec-tools-rh/purgatory/arch/ppc64/crashdump_backup.c	2006-09-08 07:29:52.000000000 +0530
+++ kexec-tools-rh-fix/purgatory/arch/ppc64/crashdump_backup.c	2006-09-08 08:42:27.000000000 +0530
@@ -21,9 +21,7 @@
 
 #include <stdint.h>
 #include <string.h>
-
-#define BACKUP_REGION_SOURCE 0x0
-#define BACKUP_REGION_SIZE 32*1024
+#include "../../../kexec/arch/ppc64/crashdump-ppc64.h"
 
 extern unsigned long backup_start;
 
@@ -32,10 +30,10 @@ void crashdump_backup_memory(void)
 {
 	void *dest, *src;
 
-	src = (void *)BACKUP_REGION_SOURCE;
+	src = (void *)BACKUP_START;
 
 	if (backup_start) {
 		dest = (void *)(backup_start);
-		memcpy(dest, src, BACKUP_REGION_SIZE);
+		memcpy(dest, src, BACKUP_SIZE);
 	}
 }

kexec-tools-1.101-reloc-update.patch:
 kexec/Makefile                             |    1 
 kexec/arch/i386/kexec-bzImage.c            |    2 
 kexec/arch/i386/kexec-elf-x86.c            |    6 
 kexec/arch/i386/kexec-multiboot-x86.c      |    5 
 kexec/arch/ia64/kexec-elf-ia64.c           |    6 
 kexec/arch/ppc/kexec-elf-ppc.c             |    4 
 kexec/arch/ppc64/kexec-elf-ppc64.c         |    6 
 kexec/arch/x86_64/crashdump-x86_64.c       |  190 ++++++++++++++++++++++++++---
 kexec/arch/x86_64/kexec-elf-rel-x86_64.c   |    2 
 kexec/arch/x86_64/kexec-elf-x86_64.c       |    6 
 kexec/arch/x86_64/kexec-x86_64.c           |    4 
 kexec/crashdump.h                          |    2 
 kexec/kexec-elf-core.c                     |   29 ++++
 kexec/kexec-elf-exec.c                     |    9 -
 kexec/kexec-elf-rel.c                      |    9 -
 kexec/kexec-elf.c                          |   27 ++--
 kexec/kexec-elf.h                          |   17 +-
 kexec/kexec.c                              |   44 ++++++
 kexec/kexec.h                              |    4 
 purgatory/arch/i386/entry32-16-debug.S     |   20 +--
 purgatory/arch/i386/include/arch/debug.h   |    2 
 purgatory/arch/i386/linux-entry16.S        |   44 +++---
 purgatory/arch/x86_64/include/arch/debug.h |    2 
 23 files changed, 345 insertions(+), 96 deletions(-)

--- NEW FILE kexec-tools-1.101-reloc-update.patch ---
--- kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S.orig	2004-12-20 05:48:45.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/linux-entry16.S	2006-12-01 15:05:42.000000000 -0500
@@ -127,10 +127,10 @@
 	TTYS0_TX_AL
 
 
-#define DEBUG(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #else
-#define DEBUG(x)
+#define DEBUG_CHAR(x)
 #define DEBUG_TX_HEX32(x)
 #endif
 	
@@ -142,15 +142,15 @@
 entry16:
 	.code32
 
-DEBUG('a')	
+DEBUG_CHAR('a')
 	/* Setup the classic BIOS interrupt table at 0x0 */
 	lidt	idtptr
 
-DEBUG('b')		
+DEBUG_CHAR('b')
 	/* Provide us with 16bit segments that we can use */
 	lgdt	gdt
 
-DEBUG('c')	
+DEBUG_CHAR('c')
 	/* Note we don't disable the a20 line, (this shouldn't be required)
 	 * The code to do it is in kexec_test and it is a real pain.
 	 * I will worry about that when I need it.
@@ -164,26 +164,26 @@
 	movl	%eax, %fs
 	movl	%eax, %gs
 
-DEBUG('d')
+DEBUG_CHAR('d')
 
 	/* switch to 16bit mode */
 	ljmp	$0x08, $1f - entry16
 1:
 	.code16
-DEBUG('e')	
+DEBUG_CHAR('e')
 	/* Disable Paging and protected mode */
 	/* clear the PG & PE bits of CR0 */
 	movl	%cr0,%eax
 	andl	$~((1 << 31)|(1<<0)),%eax
 	movl	%eax,%cr0
 
-DEBUG('f')
+DEBUG_CHAR('f')
 	/* make intersegment jmp to flush the processor pipeline
 	 * and reload %cs:%eip (to clear upper 16 bits of %eip).
 	 */
 	ljmp	*(realptr - entry16)
 3:
-DEBUG('g')
+DEBUG_CHAR('g')
 	/* we are in real mode now
 	 * set up the real mode segment registers : %ds, $ss, %es
 	 */
@@ -191,7 +191,7 @@
 	movw	%cs, %ax
 	movw	%ax, %ds
 
-DEBUG('h')
+DEBUG_CHAR('h')
 	/* Load the registers */
 	movl	eax - entry16, %eax
 	movl	ebx - entry16, %ebx
@@ -386,10 +386,10 @@
 	TTYS0_TX_AL
 
 
-#define DEBUG(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #else
-#define DEBUG(x)
+#define DEBUG_CHAR(x)
 #define DEBUG_TX_HEX32(x)
 #endif
 
@@ -403,7 +403,7 @@
 _reloc = .
 	.balign 16
 	.code32
-DEBUG('a')
+DEBUG_CHAR('a')
 	/* Compute where I am running at */
 	call	1f
 1:	popl	%ebx
@@ -412,13 +412,13 @@
 	/* Remember where I am running at */
 	movl	%ebx, location - _reloc(%ebx)
 	
-DEBUG('b')
+DEBUG_CHAR('b')
 	/* Fixup my real mode segment */
 	movl	%ebx, %eax
 	shrl	$4, %eax
 	movw	%ax, 2 + realptr - _reloc(%ebx)
 
-DEBUG('c')
+DEBUG_CHAR('c')
 	/* Fixup the gdt */
 	movl	%ebx, %eax
 	shll	$16, %eax
@@ -440,7 +440,7 @@
 
 
 	
-DEBUG('d')
+DEBUG_CHAR('d')
 	/* Setup the classic BIOS interrupt table at 0x0 */
 	lidt	idtptr - _reloc(%ebx)
 	
@@ -465,20 +465,20 @@
 	ljmp	$0x08, $2f - _reloc
 2:
 	.code16
-DEBUG('e')
+DEBUG_CHAR('e')
 	/* Disable Paging and protected mode */
 	/* clear the PG & PE bits of CR0 */
 	movl	%cr0,%eax
 	andl	$~((1 << 31)|(1<<0)),%eax
 	movl	%eax,%cr0
 
-DEBUG('f')
+DEBUG_CHAR('f')
 	/* make intersegment jmp to flush the processor pipeline
 	 * and reload %cs:%eip (to clear upper 16 bits of %eip).
 	 */
 	ljmp	*(realptr - _reloc)
 3:
-DEBUG('g')
+DEBUG_CHAR('g')
 	/* we are in real mode now
 	 * set up the real mode segment registers : %ds, $ss, %es
 	 */
@@ -486,7 +486,7 @@
 	movw	%cs, %ax
 	movw	%ax, %ds
 
-DEBUG('h')
+DEBUG_CHAR('h')
 	/* Load the registers */
 	movl	eax - _reloc, %eax
 	movl	ebx - _reloc, %ebx
@@ -600,7 +600,7 @@
 		
 setup16_debug_kernel_pre_protected:
 	.code16
-	DEBUG('i')
+	DEBUG_CHAR('i')
 	cli					# no interrupts allowed !
 	movb	$0x80, %al			# disable NMI for bootup
 						# sequence
@@ -611,7 +611,7 @@
 	.byte	0xbf	/* movl $0x12345678, %edi */
 location:
 	.long	0x12345678
-	DEBUG('j')
+	DEBUG_CHAR('j')
 	.byte	0xb8	/* movl $0x10000, %eax */
 setup16_debug_old_code32:
 	.long	0x10000
--- kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h.orig	2004-12-20 18:03:17.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/include/arch/debug.h	2006-12-01 15:05:42.000000000 -0500
@@ -311,6 +311,6 @@
 	TTYS0_TX_AL
 	
 
-#define DEBUG(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
--- kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S.orig	2004-12-20 18:11:43.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/i386/entry32-16-debug.S	2006-12-01 15:05:42.000000000 -0500
@@ -55,15 +55,15 @@
 	orl	%ecx, 0x14 + gdt	
 	
 	
-DEBUG('a')	
+DEBUG_CHAR('a')
 	/* Setup the classic BIOS interrupt table at 0x0 */
 	lidt	idtptr
 
-DEBUG('b')		
+DEBUG_CHAR('b')
 	/* Provide us with 16bit segments that we can use */
 	lgdt	gdt
 
-DEBUG('c')	
+DEBUG_CHAR('c')
 	/* Note we don't disable the a20 line, (this shouldn't be required)
 	 * The code to do it is in kexec_test and it is a real pain.
 	 * I will worry about that when I need it.
@@ -77,26 +77,26 @@
 	movl	%eax, %fs
 	movl	%eax, %gs
 
-DEBUG('d')
+DEBUG_CHAR('d')
 
 	/* switch to 16bit mode */
 	ljmp	$0x08, $1f - entry16_debug
 1:
 	.code16
-DEBUG('e')	
+DEBUG_CHAR('e')
 	/* Disable Paging and protected mode */
 	/* clear the PG & PE bits of CR0 */
 	movl	%cr0,%eax
 	andl	$~((1 << 31)|(1<<0)),%eax
 	movl	%eax,%cr0
 
-DEBUG('f')
+DEBUG_CHAR('f')
 	/* make intersegment jmp to flush the processor pipeline
 	 * and reload %cs:%eip (to clear upper 16 bits of %eip).
 	 */
 	ljmp	*(realptr - entry16_debug)
 3:
-DEBUG('g')
+DEBUG_CHAR('g')
 	/* we are in real mode now
 	 * set up the real mode segment registers : %ds, $ss, %es
 	 */
@@ -104,7 +104,7 @@
 	movw	%cs, %ax
 	movw	%ax, %ds
 
-DEBUG('h')
+DEBUG_CHAR('h')
 	/* Load the registers */
 	movl	eax - entry16_debug, %eax
 	movl	ebx - entry16_debug, %ebx
@@ -176,7 +176,7 @@
 	.text	
 entry16_debug_pre32:
 	.code16
-DEBUG('i')
+DEBUG_CHAR('i')
 	cli					# no interrupts allowed !
 	movb	$0x80, %al			# disable NMI for bootup
 						# sequence
@@ -186,7 +186,7 @@
 	
 entry16_debug_first32:
 	.code32
-DEBUG('j')
+DEBUG_CHAR('j')
 	.byte	0xb8	/* movl $0x10000, %eax */
 entry16_debug_old_first32:
 	.long 0x100000
--- kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h.orig	2004-12-20 18:05:40.000000000 -0500
+++ kexec-tools-1.101/purgatory/arch/x86_64/include/arch/debug.h	2006-12-01 15:05:42.000000000 -0500
@@ -311,7 +311,7 @@
 	TTYS0_TX_AL
 	
 
-#define DEBUG(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
+#define DEBUG_CHAR(x) TTYS0_TX_CHAR($x) ;  TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX32(x) TTYS0_TX_HEX32(x); TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 #define DEBUG_TX_HEX64(x) TTYS0_TX_HEX64(x); TTYS0_TX_CHAR($'\r') ;  TTYS0_TX_CHAR($'\n')
 
--- kexec-tools-1.101/kexec/kexec.h.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.h	2006-12-01 15:05:42.000000000 -0500
@@ -116,6 +116,9 @@
 	struct mem_ehdr rhdr;
 	unsigned long backup_start;
 	unsigned long kexec_flags;
+	unsigned long kern_vaddr_start;
+	unsigned long kern_paddr_start;
+	unsigned long kern_size;
 };
 
 void usage(void);
@@ -177,6 +180,7 @@
 extern void *xmalloc(size_t size);
 extern void *xrealloc(void *ptr, size_t size);
 extern char *slurp_file(const char *filename, off_t *r_size);
+extern char *slurp_file_len(const char *filename, off_t size);
 extern char *slurp_decompress_file(const char *filename, off_t *r_size);
 extern void add_segment(struct kexec_info *info,
 	const void *buf, size_t bufsz, unsigned long base, size_t memsz);
--- kexec-tools-1.101/kexec/Makefile.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/Makefile	2006-12-01 15:05:42.000000000 -0500
@@ -13,6 +13,7 @@
 KEXEC_C_SRCS+= kexec/ifdown.c
 KEXEC_C_SRCS+= kexec/kexec-elf.c 
 KEXEC_C_SRCS+= kexec/kexec-elf-exec.c 
+KEXEC_C_SRCS+= kexec/kexec-elf-core.c
 KEXEC_C_SRCS+= kexec/kexec-elf-rel.c 
 KEXEC_C_SRCS+= kexec/kexec-elf-boot.c 
 KEXEC_C_SRCS+= kexec/crashdump.c
--- kexec-tools-1.101/kexec/kexec-elf-exec.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-exec.c	2006-12-01 15:05:42.000000000 -0500
@@ -11,11 +11,12 @@
 
 static const int probe_debug = 0;
 
-int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
 {
 	struct mem_phdr *phdr, *end_phdr;
 	int result;
-	result = build_elf_info(buf, len, ehdr);
+	result = build_elf_info(buf, len, ehdr, flags);
 	if (result < 0) {
 		return result;
 	}
@@ -136,11 +137,11 @@
 }
 
 void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, 
-	const char *buf, off_t len)
+	const char *buf, off_t len, uint32_t flags)
 {
 	int result;
 	/* Parse the Elf file */
-	result = build_elf_exec_info(buf, len, ehdr);
+	result = build_elf_exec_info(buf, len, ehdr, flags);
 	if (result < 0) {
 		die("ELF exec parse failed\n");
 	}
--- kexec-tools-1.101/kexec/kexec.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.c	2006-12-01 15:05:42.000000000 -0500
@@ -391,6 +391,50 @@
 	return buf;
 }
 
+/* This functions reads either specified number of bytes from the file or
+   lesser if EOF is met. */
+
+char *slurp_file_len(const char *filename, off_t size)
+{
+	int fd;
+	char *buf;
+	off_t progress;
+	ssize_t result;
+
+	if (!filename)
+		return 0;
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "Cannot open %s: %s\n", filename,
+				strerror(errno));
+		return 0;
+	}
+	buf = xmalloc(size);
+	progress = 0;
+	while(progress < size) {
+		result = read(fd, buf + progress, size - progress);
+		if (result < 0) {
+			if ((errno == EINTR) ||	(errno == EAGAIN))
+				continue;
+			fprintf(stderr, "read on %s of %ld bytes failed: %s\n",
+					filename, (size - progress)+ 0UL,
+					strerror(errno));
+			free(buf);
+			return 0;
+		}
+		if (result == 0)
+			/* EOF */
+			break;
+		progress += result;
+	}
+	result = close(fd);
+	if (result < 0) {
+		die("Close of %s failed: %s\n",
+			filename, strerror(errno));
+	}
+	return buf;
+}
+
 #if HAVE_ZLIB_H
 char *slurp_decompress_file(const char *filename, off_t *r_size)
 {
--- kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c	2006-12-01 15:05:42.000000000 -0500
@@ -133,7 +133,7 @@
 	 * it's gdt.
 	 */
 	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-		0x3000, 640*1024, -1);
+		0x3000, 640*1024, -1, 0);
 
 	/* The argument/parameter segment */
 	setup_size = kern16_size + command_line_len;
--- kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c	2006-12-01 15:05:42.000000000 -0500
@@ -209,10 +209,11 @@
 
 	
 	/* Load the ELF executable */
-	elf_exec_build_load(info, &ehdr, buf, len);
+	elf_exec_build_load(info, &ehdr, buf, len, 0);
 
 	/* Load the setup code */
-	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0, ULONG_MAX, 1);
+	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, 0,
+				ULONG_MAX, 1, 0);
 	
 	/* The first segment will contain the multiboot headers:
 	 * =============
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c	2006-12-01 15:05:42.000000000 -0500
@@ -47,7 +47,7 @@
 	
 	struct mem_ehdr ehdr;
 	int result;
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		if (probe_debug) {
 			fprintf(stderr, "Not an ELF executable\n");
@@ -177,7 +177,7 @@
 	}
 
 	/* Load the ELF executable */
-	elf_exec_build_load(info, &ehdr, buf, len);
+	elf_exec_build_load(info, &ehdr, buf, len, 0);
 
 	entry = ehdr.e_entry;
 	max_addr = elf_max_addr(&ehdr);
@@ -186,7 +186,7 @@
 	if (arg_style != ARG_STYLE_NONE) {
 		/* Load the setup code */
 		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-			0, ULONG_MAX, 1);
+			0, ULONG_MAX, 1, 0);
 	}
 	if (arg_style == ARG_STYLE_NONE) {
 		info->entry = (void *)entry;
--- kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c.orig	2005-01-20 14:10:56.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c	2006-12-01 15:05:42.000000000 -0500
@@ -72,7 +72,7 @@
 
 	struct mem_ehdr ehdr;
 	int result;
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		goto out;
 	}
@@ -180,7 +180,7 @@
 	}
 
 	/* Parse the Elf file */
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		free_elf_info(&ehdr);
 		return result;
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c	2006-12-01 15:05:42.000000000 -0500
@@ -64,7 +64,7 @@
 			continue;
 		str = line + consumed;
 		end = end + 1;
-#if 0
+#ifdef DEBUG
 		printf("%016Lx-%016Lx : %s",
 			start, end, str);
 #endif
@@ -104,7 +104,7 @@
 		memory_range[memory_ranges].start = start;
 		memory_range[memory_ranges].end = end;
 		memory_range[memory_ranges].type = type;
-#if 0
+#ifdef DEBUG
 		printf("%016Lx-%016Lx : %x\n",
 			start, end, type);
 #endif
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c	2006-12-01 15:05:42.000000000 -0500
@@ -47,7 +47,7 @@
 	
 	struct mem_ehdr ehdr;
 	int result;
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		if (probe_debug) {
 			fprintf(stderr, "Not an ELF executable\n");
@@ -177,7 +177,7 @@
 	}
 
 	/* Load the ELF executable */
-	elf_exec_build_load(info, &ehdr, buf, len);
+	elf_exec_build_load(info, &ehdr, buf, len, 0);
 
 	entry = ehdr.e_entry;
 	max_addr = elf_max_addr(&ehdr);
@@ -186,7 +186,7 @@
 	if (arg_style != ARG_STYLE_NONE) {
 		/* Load the setup code */
 		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-			0, ULONG_MAX, 1);
+			0, ULONG_MAX, 1, 0);
 	}
 	if (arg_style == ARG_STYLE_NONE) {
 		info->entry = (void *)entry;
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c.orig	2004-12-21 12:51:24.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-rel-x86_64.c	2006-12-01 15:05:42.000000000 -0500
@@ -60,7 +60,7 @@
 void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, 
 	void *location, unsigned long address, unsigned long value)
 {
-#if 0
+#ifdef DEBUG
 	fprintf(stderr, "%s\n", reloc_name(r_type));
 #endif
 	switch(r_type) {
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c	2006-12-01 15:05:42.000000000 -0500
@@ -24,8 +24,10 @@
 #include <errno.h>
 #include <limits.h>
 #include <elf.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <unistd.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
@@ -40,6 +42,137 @@
 /* Forward Declaration. */
 static int exclude_crash_reserve_region(int *nr_ranges);
 
+#define KERN_VADDR_ALIGN	0x200000	/* 2MB */
+
+/* Read kernel physical load addr from /proc/iomem (Kernel Code) and
+ * store in kexec_info */
+static int get_kernel_paddr(struct kexec_info *info)
+{
+	const char iomem[]= "/proc/iomem";
+	char line[MAX_LINE];
+	FILE *fp;
+	unsigned long long start, end;
+
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
+		return -1;
+	}
+	while(fgets(line, sizeof(line), fp) != 0) {
+		char *str;
+		int consumed, count;
+		count = sscanf(line, "%Lx-%Lx : %n",
+			&start, &end, &consumed);
+		if (count != 2)
+			continue;
+		str = line + consumed;
+#ifdef DEBUG
+		printf("%016Lx-%016Lx : %s",
+			start, end, str);
+#endif
+		if (memcmp(str, "Kernel code\n", 12) == 0) {
+			info->kern_paddr_start = start;
+
+#ifdef DEBUG
+			printf("kernel load physical addr start = 0x%016Lx\n",
+					start);
+#endif
+			fclose(fp);
+			return 0;
+		}
+	}
+	fprintf(stderr, "Cannot determine kernel physical load addr\n");
+	fclose(fp);
+	return -1;
+}
+
+/* Hardcoding kernel virtual address and size. While writting
+ * this patch vanilla kernel is compiled for addr 2MB. Anybody
+ * using kernel older than that which was compiled for 1MB
+ * physical addr, use older version of kexec-tools. This function
+ * is there just for backward compatibility reasons and we should
+ * get rid of it at some point of time.
+ */
+
+static int hardcode_kernel_vaddr_size(struct kexec_info *info)
+{
+	fprintf(stderr, "Warning: Hardcoding kernel virtual addr and size\n");
+	info->kern_vaddr_start = __START_KERNEL_map + 0x200000;
+	info->kern_size = KERNEL_TEXT_SIZE - 0x200000;
+	fprintf(stderr, "Warning: virtual addr = 0x%lx size = 0x%lx\n",
+		info->kern_vaddr_start, info->kern_size);
+	return 0;
+}
+
+/* Retrieve info regarding virtual address kernel has been compiled for and
+ * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
+ * from kexec-tools fails because of malformed elf notes. A kernel patch has
+ * been submitted. For the folks using older kernels, this function
+ * hard codes the values to remain backward compatible. Once things stablize
+ * we should get rid of backward compatible code. */
+
+static int get_kernel_vaddr_and_size(struct kexec_info *info)
+{
+	int result;
+	const char kcore[] = "/proc/kcore";
+	char *buf;
+	struct mem_ehdr ehdr;
+	struct mem_phdr *phdr, *end_phdr;
+	int align;
+	unsigned long size;
+	uint32_t elf_flags = 0;
+
+	align = getpagesize();
+	size = KCORE_ELF_HEADERS_SIZE;
+	buf = slurp_file_len(kcore, size);
+	if (!buf) {
+		fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
+		return -1;
+	}
+
+	/* Don't perform checks to make sure stated phdrs and shdrs are
+	 * actually present in the core file. It is not practical
+	 * to read the GB size file into a user space buffer, Given the
+	 * fact that we don't use any info from that.
+	 */
+	elf_flags |= ELF_SKIP_FILESZ_CHECK;
+	result = build_elf_core_info(buf, size, &ehdr, elf_flags);
+	if (result < 0) {
+		fprintf(stderr, "ELF core (kcore) parse failed\n");
+		hardcode_kernel_vaddr_size(info);
+		return 0;
+	}
+
+	/* Traverse through the Elf headers and find the region where
+	 * kernel is mapped. */
+	end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
+	for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
+		if (phdr->p_type == PT_LOAD) {
+			unsigned long saddr = phdr->p_vaddr;
+			unsigned long eaddr = phdr->p_vaddr + phdr->p_memsz;
+			unsigned long size;
+
+			/* Look for kernel text mapping header. */
+			if ((saddr >= __START_KERNEL_map) &&
+			    (eaddr <= __START_KERNEL_map + KERNEL_TEXT_SIZE)) {
+				saddr = (saddr) & (~(KERN_VADDR_ALIGN - 1));
+				info->kern_vaddr_start = saddr;
+				size = eaddr - saddr;
+				/* Align size to page size boundary. */
+				size = (size + align - 1) & (~(align - 1));
+				info->kern_size = size;
+#ifdef DEBUG
+			printf("kernel vaddr = 0x%lx size = 0x%lx\n",
+					saddr, size);
+#endif
+				return 0;
+			}
+		}
+	}
+	fprintf(stderr, "Can't find kernel text map area from kcore\n");
+	return -1;
+}
+
 /* Stores a sorted list of RAM memory ranges for which to create elf headers.
  * A separate program header is created for backup region */
 static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
@@ -245,7 +378,7 @@
 			memmap_p[j+1] = memmap_p[j];
 		memmap_p[tidx].start = addr;
 		memmap_p[tidx].end = addr + size - 1;
-#if 0
+#ifdef DEBUG
 	printf("Memmap after adding segment\n");
 	for (i = 0; i < CRASH_MAX_MEMMAP_NR;  i++) {
 		mstart = memmap_p[i].start;
@@ -330,7 +463,7 @@
 			memmap_p[j-1] = memmap_p[j];
 		memmap_p[j-1].start = memmap_p[j-1].end = 0;
 	}
-#if 0
+#ifdef DEBUG
 	printf("Memmap after deleting segment\n");
 	for (i = 0; i < CRASH_MAX_MEMMAP_NR;  i++) {
 		mstart = memmap_p[i].start;
@@ -404,7 +537,7 @@
 			die("Command line overflow\n");
 		strcat(cmdline, str_mmap);
 	}
-#if 0
+#ifdef DEBUG
 		printf("Command line after adding memmap\n");
 		printf("%s\n", cmdline);
 #endif
@@ -432,7 +565,7 @@
 	if (cmdlen > (COMMAND_LINE_SIZE - 1))
 		die("Command line overflow\n");
 	strcat(cmdline, str);
-#if 0
+#ifdef DEBUG
 		printf("Command line after adding elfcorehdr\n");
 		printf("%s\n", cmdline);
 #endif
@@ -465,7 +598,7 @@
 		die("Command line overflow\n");
 	strcat(cmdline, str_mmap);
 
-#if 0
+#ifdef DEBUG
 		printf("Command line after adding acpi memmap\n");
 		printf("%s\n", cmdline);
 #endif
@@ -536,6 +669,27 @@
 		(elf->e_phnum)++;
 	}
 
+	/* Setup an PT_LOAD type program header for the region where
+	 * Kernel is mapped.
+	 */
+	phdr = (Elf64_Phdr *) bufp;
+	bufp += sizeof(Elf64_Phdr);
+	phdr->p_type    = PT_LOAD;
+	phdr->p_flags   = PF_R|PF_W|PF_X;
+	phdr->p_offset  = phdr->p_paddr = info->kern_paddr_start;
+	phdr->p_vaddr   = info->kern_vaddr_start;
+	phdr->p_filesz  = phdr->p_memsz = info->kern_size;
+	phdr->p_align   = 0;
+	(elf->e_phnum)++;
+#ifdef DEBUG
+	printf("Kernel text Elf header: p_type = %d, p_offset = 0x%lx "
+		"p_paddr = 0x%lx p_vaddr = 0x%lx "
+		"p_filesz = 0x%lx p_memsz = 0x%lx\n",
+		phdr->p_type, phdr->p_offset, phdr->p_paddr,
+		phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
+ 
+
 	/* Setup PT_LOAD type program header for every system RAM chunk.
 	 * A seprate program header for Backup Region*/
 	for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
@@ -555,21 +709,13 @@
 		else
 			phdr->p_offset	= mstart;
 
-		/* Handle linearly mapped region.*/
+		/* We already prepared the header for kernel text. Map
+		 * rest of the memory segments to kernel linearly mapped
+		 * memory region.
+		 */
 
-		/* Filling the vaddr conditionally as we have two linearly
-		 * mapped regions here. One is __START_KERNEL_map 0 to 40 MB
-		 * other one is PAGE_OFFSET */
-
-		if ((mend <= (MAXMEM - 1)) && mstart < KERNEL_TEXT_SIZE)
-			phdr->p_vaddr = mstart + __START_KERNEL_map;
-		else {
-			if (mend <= (MAXMEM - 1))
-				phdr->p_vaddr = mstart + PAGE_OFFSET;
-			else
-				phdr->p_vaddr = -1ULL;
-		}
 		phdr->p_paddr = mstart;
+		phdr->p_vaddr = mstart + PAGE_OFFSET;
 		phdr->p_filesz	= phdr->p_memsz	= mend - mstart + 1;
 		/* Do we need any alignment of segments? */
 		phdr->p_align	= 0;
@@ -593,6 +739,12 @@
 	long int nr_cpus = 0;
 	struct memory_range *mem_range, *memmap_p;
 
+	if (get_kernel_paddr(info))
+		return -1;
+
+	if (get_kernel_vaddr_and_size(info))
+		return -1;
+
 	if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
 		return -1;
 
@@ -638,7 +790,7 @@
 	 * This is a makeshift solution until it is fixed in kernel.
 	 */
 	elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
-							max_addr, 1);
+							max_addr, -1);
 	if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
 		return -1;
 	cmdline_add_memmap(mod_cmdline, memmap_p);
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2006-12-01 15:05:42.000000000 -0500
@@ -56,7 +56,7 @@
 {
 	struct mem_ehdr ehdr;
 	int result;
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		if (probe_debug) {
 			fprintf(stderr, "Not an ELF executable\n");
@@ -163,7 +163,7 @@
 	}
 
 	/* Parse the Elf file */
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		fprintf(stderr, "ELF parse failed\n");
 		free_elf_info(&ehdr);
@@ -198,7 +198,7 @@
 
 	/* Load the setup code */
 	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-			0x0, ULONG_MAX, -1);
+			0x0, ULONG_MAX, -1, 0);
 
 
 	if (load_crashdump_segments(info, &ehdr, max_addr, 0,
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c	2006-12-01 15:05:42.000000000 -0500
@@ -52,7 +52,7 @@
 {
 	struct mem_ehdr ehdr;
 	int result;
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		goto out;
 	}
@@ -163,7 +163,7 @@
 	}
 
 	/* Parse the Elf file */
-	result = build_elf_exec_info(buf, len, &ehdr);
+	result = build_elf_exec_info(buf, len, &ehdr, 0);
 	if (result < 0) {
 		free_elf_info(&ehdr);
 		return result;
@@ -213,7 +213,7 @@
 	memcpy(seg_buf, purgatory, purgatory_size);
 	seg_size = purgatory_size;
 	elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
-				purgatory_size, 0, max_addr, 1);
+				purgatory_size, 0, max_addr, 1, 0);
 
 	/* Add a ram-disk to the current image
 	 * Note: Add the ramdisk after elf_rel_build_load
--- kexec-tools-1.101/kexec/kexec-elf-rel.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-rel.c	2006-12-01 15:05:42.000000000 -0500
@@ -135,10 +135,11 @@
 	return rela;
 }
 
-int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
 {
 	int result;
-	result = build_elf_info(buf, len, ehdr);
+	result = build_elf_info(buf, len, ehdr, flags);
 	if (result < 0) {
 		return result;
 	}
@@ -412,12 +413,12 @@
 
 void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
 	const char *buf, off_t len, unsigned long min, unsigned long max,
-	int end)
+	int end, uint32_t flags)
 {
 	int result;
 
 	/* Parse the Elf file */
-	result = build_elf_rel_info((char *)purgatory, purgatory_size, ehdr);
+	result = build_elf_rel_info(buf, len, ehdr, flags);
 	if (result < 0) {
 		die("ELF rel parse failed\n");
 	}
--- /dev/null	2006-11-22 10:18:18.589138000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf-core.c	2006-12-01 15:05:42.000000000 -0500
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "elf.h"
+#include "kexec-elf.h"
+
+
+int build_elf_core_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
+{
+	int result;
+	result = build_elf_info(buf, len, ehdr, flags);
+	if (result < 0) {
+		return result;
+	}
+	if ((ehdr->e_type != ET_CORE)) {
+		/* not an ELF Core */
+		fprintf(stderr, "Not ELF type ET_CORE\n");
+		return -1;
+	}
+	if (!ehdr->e_phdr) {
+		/* No program header */
+		fprintf(stderr, "No ELF program header\n");
+		return -1;
+	}
+
+	return 0;
+}
--- kexec-tools-1.101/kexec/crashdump.h.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/crashdump.h	2006-12-01 15:05:42.000000000 -0500
@@ -5,5 +5,7 @@
 
 /* Need to find a better way to determine per cpu notes section size. */
 #define MAX_NOTE_BYTES		1024
+/* Expecting ELF headers to fit in 4K. Increase it if you need more. */
+#define KCORE_ELF_HEADERS_SIZE  4096
 
 #endif /* CRASHDUMP_H */
--- kexec-tools-1.101/kexec/kexec-elf.c.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf.c	2006-12-01 15:05:42.000000000 -0500
@@ -368,7 +368,8 @@
 	return 0;
 }
 
-static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
 {
 	size_t phdr_size, mem_phdr_size;
 	int i;
@@ -418,9 +419,11 @@
 
 		/* Check the program headers to be certain
 		 * they are safe to use.
+		 * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
 		 */
 		phdr = &ehdr->e_phdr[i];
-		if ((phdr->p_offset + phdr->p_filesz) > len) {
+		if (!(flags & ELF_SKIP_FILESZ_CHECK)
+			&& (phdr->p_offset + phdr->p_filesz) > len) {
 			/* The segment does not fit in the buffer */
 			if (probe_debug) {
 				fprintf(stderr, "ELF segment not in file\n");
@@ -580,7 +583,8 @@
 	return 0;
 }
 
-static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr)
+static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags)
 {
 	size_t shdr_size, mem_shdr_size;
 	int i;
@@ -628,11 +632,12 @@
 		}
 		/* Check the section headers to be certain
 		 * they are safe to use.
+		 * Skip the check if ELF_SKIP_FILESZ_CHECK is set.
 		 */
 		shdr = &ehdr->e_shdr[i];
-		if ((shdr->sh_type != SHT_NOBITS) &&
-			((shdr->sh_offset + shdr->sh_size) > len))
-		{
+		if (!(flags & ELF_SKIP_FILESZ_CHECK)
+			&& (shdr->sh_type != SHT_NOBITS)
+			&& (shdr->sh_offset + shdr->sh_size) > len) {
 			/* The section does not fit in the buffer */
 			if (probe_debug) {
 				fprintf(stderr, "ELF section %d not in file\n",
@@ -710,7 +715,8 @@
 		note_size += (hdr.n_descsz + 3) & ~3;
 
 		if ((hdr.n_namesz != 0) && (name[hdr.n_namesz -1] != '\0')) {
-			die("Note name is not null termiated");
+			fprintf(stderr, "Note name is not null termiated\n");
+			return -1;
 		}
 		ehdr->e_note[i].n_type = hdr.n_type;
 		ehdr->e_note[i].n_name = (char *)name;
@@ -729,7 +735,8 @@
 	memset(ehdr, 0, sizeof(*ehdr));
 }
 
-int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr)
+int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+			uint32_t flags)
 {
 	int result;
 	result = build_mem_ehdr(buf, len, ehdr);
@@ -737,14 +744,14 @@
 		return result;
 	}
 	if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) {
-		result = build_mem_phdrs(buf, len, ehdr);
+		result = build_mem_phdrs(buf, len, ehdr, flags);
 		if (result < 0) {
 			free_elf_info(ehdr);
 			return result;
 		}
 	}
 	if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) {
-		result = build_mem_shdrs(buf, len, ehdr);
+		result = build_mem_shdrs(buf, len, ehdr, flags);
 		if (result < 0) {
 			free_elf_info(ehdr);
 			return result;
--- kexec-tools-1.101/kexec/kexec-elf.h.orig	2006-12-01 15:05:05.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec-elf.h	2006-12-01 15:05:42.000000000 -0500
@@ -82,22 +82,29 @@
 	uint32_t n_type;		/* Type of the note.  */
 } ElfNN_Nhdr;
 
+/* Misc flags */
 
+#define ELF_SKIP_FILESZ_CHECK		0x00000001
 
 extern void free_elf_info(struct mem_ehdr *ehdr);
-extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
-extern int build_elf_exec_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
-extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr);
+extern int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags);
+extern int build_elf_exec_info(const char *buf, off_t len,
+				struct mem_ehdr *ehdr, uint32_t flags);
+extern int build_elf_rel_info(const char *buf, off_t len, struct mem_ehdr *ehdr,
+				uint32_t flags);
 
+extern int build_elf_core_info(const char *buf, off_t len,
+					struct mem_ehdr *ehdr, uint32_t flags);
 extern int elf_exec_load(struct mem_ehdr *ehdr, struct kexec_info *info);
 extern int elf_rel_load(struct mem_ehdr *ehdr, struct kexec_info *info,
 	unsigned long min, unsigned long max, int end);
 
 extern void elf_exec_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, 
-	const char *buf, off_t len);
+				const char *buf, off_t len, uint32_t flags);
 extern void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr, 
 	const char *buf, off_t len, unsigned long min, unsigned long max, 
-	int end);
+	int end, uint32_t flags);
 
 extern int elf_rel_find_symbol(struct mem_ehdr *ehdr,
 	const char *name, struct mem_sym *ret_sym);

kexec-tools-1.101-x86_64-crashdump.patch:
 arch/x86_64/crashdump-x86_64.c |   97 ++++++++++++++++++++++++++++++++++++-----
 kexec.h                        |    2 
 2 files changed, 89 insertions(+), 10 deletions(-)

--- NEW FILE kexec-tools-1.101-x86_64-crashdump.patch ---
--- kexec-tools-1.101/kexec/kexec.h.x86_64fix	2006-08-29 19:09:12.000000000 -0400
+++ kexec-tools-1.101/kexec/kexec.h	2006-08-29 19:11:01.000000000 -0400
@@ -116,6 +116,8 @@ struct kexec_info {
 	struct mem_ehdr rhdr;
 	unsigned long backup_start;
 	unsigned long kexec_flags;
+	unsigned long kern_load_addr_start;
+	unsigned long kern_load_addr_end;
 };
 
 void usage(void);
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.x86_64fix	2006-08-29 19:07:51.000000000 -0400
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c	2006-08-29 19:08:22.000000000 -0400
@@ -47,6 +47,53 @@ static struct memory_range crash_memory_
 /* Memory region reserved for storing panic kernel and other data. */
 static struct memory_range crash_reserved_mem;
 
+/* Read kernel physical load addr from /proc/iomem (Kernel Code) and
+ * store in kexec_info */
+static int get_kernel_load_addr(struct kexec_info *info)
+{
+	const char iomem[]= "/proc/iomem";
+	char line[MAX_LINE];
+	FILE *fp;
+	unsigned long long start, end;
+
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
+		return -1;
+	}
+	while(fgets(line, sizeof(line), fp) != 0) {
+		char *str;
+		int consumed, count;
+		count = sscanf(line, "%Lx-%Lx : %n",
+			&start, &end, &consumed);
+		if (count != 2)
+			continue;
+		str = line + consumed;
+#if 0
+		printf("%016Lx-%016Lx : %s",
+			start, end, str);
+#endif
+		if (memcmp(str, "Kernel code\n", 12) == 0) {
+			info->kern_load_addr_start = start;
+
+		/* Currently hardcoding the kernel end to 40MB
+		 * This assumption is broken if kernel is compiled for
+		 * and address other than START_KERNEL_map
+		 */
+			info->kern_load_addr_end = start + KERNEL_TEXT_SIZE;
+#if 0
+		printf("kernel load addr start = 0x%016Lx end = 0x%016Lx\n",
+					start, (start + KERNEL_TEXT_SIZE));
+#endif
+			fclose(fp);
+			return 0;
+		}
+	}
+	fprintf(stderr, "Cannot determine kernel physical load addr\n");
+	fclose(fp);
+	return -1;
+}
+
 /* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
  * create Elf headers. Keeping it separate from get_memory_ranges() as
  * requirements are different in the case of normal kexec and crashdumps.
@@ -58,14 +105,18 @@ static struct memory_range crash_reserve
  * to look into down the line. May be something like /proc/kernelmem or may
  * be zone data structures exported from kernel.
  */
-static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
+static int get_crash_memory_ranges(struct kexec_info *info,
+				struct memory_range **range, int *ranges)
 {
 	const char iomem[]= "/proc/iomem";
-	int memory_ranges = 0;
+	int memory_ranges = 0, rc = 0;
 	char line[MAX_LINE];
 	FILE *fp;
 	unsigned long long start, end;
 
+	if ((rc = get_kernel_load_addr(info)))
+		die("Error while reading the kernel load address\n");
+
 	fp = fopen(iomem, "r");
 	if (!fp) {
 		fprintf(stderr, "Cannot open %s: %s\n",
@@ -83,6 +134,9 @@ static int get_crash_memory_ranges(struc
 	while(fgets(line, sizeof(line), fp) != 0) {
 		char *str;
 		int type, consumed, count;
+		unsigned long kaddr_start = info->kern_load_addr_start;
+		unsigned long kaddr_end = info->kern_load_addr_end;
+
 		if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
 			break;
 		count = sscanf(line, "%Lx-%Lx : %n",
@@ -126,12 +180,18 @@ static int get_crash_memory_ranges(struc
 		crash_memory_range[memory_ranges].type = type;
 		memory_ranges++;
 
-		/* Segregate linearly mapped region. */
-		if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) {
-			crash_memory_range[memory_ranges-1].end = MAXMEM -1;
-
+		/* Segregate kernel text region. Assuming that kernel
+		 * text region is not splitted and is part of single memory
+		 * chunk.
+		 */
+		if ((start <= kaddr_start) && (end >= kaddr_end)) {
+			if ((kaddr_start - start) > 0) {
+				crash_memory_range[memory_ranges-1].end =
+								kaddr_start - 1;
+			}
 			/* Add segregated region. */
-			crash_memory_range[memory_ranges].start = MAXMEM;
+			crash_memory_range[memory_ranges].start =
+				crash_memory_range[memory_ranges - 1].end + 1;
 			crash_memory_range[memory_ranges].end = end;
 			crash_memory_range[memory_ranges].type = type;
 			memory_ranges++;
@@ -532,6 +592,13 @@ static int prepare_crash_memory_elf64_he
 
 		/* Increment number of program headers. */
 		(elf->e_phnum)++;
+#if 0
+		printf("Elf header: p_type = %d, p_offset = 0x%lx "
+			"p_paddr = 0x%lx p_vaddr = 0x%lx "
+			"p_filesz = 0x%lx p_memsz = 0x%lx\n",
+			phdr->p_type, phdr->p_offset, phdr->p_paddr,
+			phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
 	}
 
 	/* Setup PT_LOAD type program header for every system RAM chunk.
@@ -559,8 +626,11 @@ static int prepare_crash_memory_elf64_he
 		 * mapped regions here. One is __START_KERNEL_map 0 to 40 MB
 		 * other one is PAGE_OFFSET */
 
-		if ((mend <= (MAXMEM - 1)) && mstart < KERNEL_TEXT_SIZE)
-			phdr->p_vaddr = mstart + __START_KERNEL_map;
+		/* Kernel text mapping reion. */
+		if (mstart == info->kern_load_addr_start) {
+			phdr->p_vaddr = (mstart + __START_KERNEL_map
+						- info->kern_load_addr_start);
+		}
 		else {
 			if (mend <= (MAXMEM - 1))
 				phdr->p_vaddr = mstart + PAGE_OFFSET;
@@ -574,6 +644,13 @@ static int prepare_crash_memory_elf64_he
 
 		/* Increment number of program headers. */
 		(elf->e_phnum)++;
+#if 0
+		printf("Elf header: p_type = %d, p_offset = 0x%lx "
+			"p_paddr = 0x%lx p_vaddr = 0x%lx "
+			"p_filesz = 0x%lx p_memsz = 0x%lx\n",
+			phdr->p_type, phdr->p_offset, phdr->p_paddr,
+			phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
 	}
 	return 0;
 }
@@ -591,7 +668,7 @@ int load_crashdump_segments(struct kexec
 	long int nr_cpus = 0;
 	struct memory_range *mem_range, *memmap_p;
 
-	if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
+	if (get_crash_memory_ranges(info, &mem_range, &nr_ranges) < 0)
 		return -1;
 
 	/* Memory regions which panic kernel can safely use to boot into */

kexec-tools-1.101-x86_64-exactmap.patch:
 crashdump-x86_64.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletion(-)

--- NEW FILE kexec-tools-1.101-x86_64-exactmap.patch ---
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c.orig	2006-11-14 12:15:45.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c	2006-11-14 12:16:04.000000000 -0500
@@ -113,6 +113,8 @@
 			 * initializing acpi tables in second kernel.
 			 */
 			type = RANGE_ACPI;
+		} else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) {
+			type = RANGE_ACPI_NVS;
 		} else {
 			continue;
 		}
@@ -645,7 +647,8 @@
 	/* Inform second kernel about the presence of ACPI tables. */
 	for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
 		unsigned long start, end;
-		if (mem_range[i].type != RANGE_ACPI)
+		if ( !( mem_range[i].type == RANGE_ACPI
+			|| mem_range[i].type == RANGE_ACPI_NVS) )
 			continue;
 		start = mem_range[i].start;
 		end = mem_range[i].end;


Index: kdump.conf
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.conf,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- kdump.conf	30 Aug 2006 20:34:16 -0000	1.3
+++ kdump.conf	15 Dec 2006 21:05:01 -0000	1.4
@@ -2,31 +2,67 @@
 #
 # This file contains a series of commands to perform (in order) when a
 # kernel crash has happened and the kdump kernel has been loaded
-# 
-# The commands are chained together to allow redundancy in case the 
-# primary choice is not available at crash time
+#
+# Currently only one dump target and path may be configured at once
+# if the configured dump target fails, the default action will be preformed
+# the default action may be configured with the default directive below
 #
 # Basics commands supported are:
-# raw <partition> - will dd /proc/vmcore into <partition>
-# <nfs mount>     - will mount fs and copy /proc/vmcore to 
-#			<mnt>/var/crash/%DATE/ , supports DNS
-# <user at location> - will scp /proc/vmcore to 
-#			<user at location>:/var/crash/%DATE/, supports DNS
-# <fs type> - will mount -t <fs type> /mnt and copy /proc/vmcore to 
-#			/mnt/var/crash/%DATE/
-# ifc <interface> - instead of bringing up the interface that is normally associated
-#                   with the next hop of the ip address you plan to use with scp or nfs
-#                   activate this interface instead.  This is sometimes needed in the event
-#                   that the kdump kernel assigns your interface a different name, given
-#                   that it only loads the driver needed for the specific interface you are
-#                   going to use
-# default reboot - if all of the above fail, then reboot the system 
-#			and accept the /proc/vmcore is lost, else 
-#			comment out 'default' to fall through and fix 
-#			the system (if the disk is available)
+# raw <partition>	- Will dd /proc/vmcore into <partition>.
+#
+# net <nfs mount>	- Will mount fs and copy /proc/vmcore to
+#			  <mnt>/var/crash/%HOST-%DATE/, supports DNS.
+#
+# net <user at server>	- Will scp /proc/vmcore to
+#			  <user at server>:/var/crash/%HOST-%DATE/, supports DNS
+#			  NOTE: make sure user has necessary write
+#			  permissions on server
+#
+# <fs type> <partition> - Will mount -t <fs type> <partition> /mnt and copy
+#		 	  /proc/vmcore to /mnt/var/crash/%DATE/.
+#			  NOTE: <partition> can be a device node, label or uuid.
+#
+# path <path> 		- Append path to the filesystem device which you are
+#			  dumping to.  Ignored for raw device dumps.
+#		 	  If unset, will default to /var/crash.
+#
+# core_collector makedumpfile <options>
+#			  This directive allows you to use the dump filtering
+#			  program makedumpfile to retrieve your core, which on
+#			  some arches can drastically reduce core file size.
+#			  See /sbin/makedumpfile --help for a list of options.
+#			  Note that the -i and -g options are not needed here,
+#			  as the initrd will automatically be populated with
+#			  a config file appropriate for the running kernel.
+#
+# link_delay <seconds>
+#			  Some network cards take a long time to initialize, and
+#			  some spanning tree enabled networks do not transmit
+#			  user traffic for long periods after a link state
+#			  changes.  This optional parameter defines a wait
+#			  period after a link is activated in which the
+#			  initramfs will wait before attempting to transmit
+#			  user data.
+# default <reboot | shell>
+#			  if all of the above fail, do the default action.
+#			  reboot: If the default action is reboot simply reboot
+#				  the system and loose the core that you are
+#				  trying to retrieve.
+#			  shell:  If the default action is shell, then drop to
+#				  an msh session inside the initramfs from
+#				  where you can try to record the core manually.
+#				  Exiting this shell reboots the system.
+#			  NOTE: If no default action is specified, the initramfs
+#				will mount the root file system and run init.
 
 #raw /dev/sda5
 #ext3 /dev/sda3
-#my.server.com:/export/tmp
-#user at my.server.com
-#default reboot
+#ext3 LABEL=/boot
+#ext3 UUID=03138356-5e61-4ab3-b58e-27507ac41937
+#net my.server.com:/export/tmp
+#net user at my.server.com
+#path /var/crash
+#core_collector makedumpfile -c
+#link_delay 60
+#default shell
+


Index: kdump.init
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.init,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- kdump.init	28 Sep 2006 16:16:04 -0000	1.11
+++ kdump.init	15 Dec 2006 21:05:01 -0000	1.12
@@ -9,7 +9,7 @@
 #
 #  Copyright 2005 Red Hat, Inc.
 #
-#  chkconfig: 2345 20 80
+#  chkconfig: - 20 80
 #
 #  Author:  Jeff Moyer <jmoyer at redhat.com>
 
@@ -28,7 +28,9 @@
 KEXEC_ARGS=""
 KDUMP_CONFIG_FILE="/etc/kdump.conf"
 
-standard_kexec_args="-p --args-linux"
+LOGGER="/usr/bin/logger -p info -t kdump"
+
+standard_kexec_args="-p"
 
 if [ -f /etc/sysconfig/kdump ]; then
 	. /etc/sysconfig/kdump
@@ -39,7 +41,13 @@
 	coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
 
 	mkdir -p $coredir
-	cp /proc/vmcore $coredir/vmcore
+	cp /proc/vmcore $coredir/vmcore-incomplete
+	if [ $? == 0 ]; then
+		mv $coredir/vmcore-incomplete $coredir/vmcore
+		$LOGGER "saved a vmcore to $coredir"
+	else
+		$LOGGER "failed to save a vmcore to $coredir"
+	fi
 }
 
 function check_config()
@@ -48,24 +56,29 @@
 		local running_kernel=`uname -r`
 
 		kdump_kver=`echo $running_kernel | sed 's/smp//g'`
-		kdump_kver="${kdump_kver}kdump"
 	else
 		kdump_kver=$KDUMP_KERNELVER
 	fi
 
-	kdump_kernel="${BOOTDIR}/vmlinux-${kdump_kver}"
-	kdump_initrd="${BOOTDIR}/initrd-${kdump_kver}.img"
+	kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
+	kdump_initrd="${KDUMP_BOOTDIR}/initrd-${kdump_kver}kdump.img"
 
 	if [ ! -f $kdump_kernel ]; then
 		echo -n "No kdump kernel image found."; warning; echo
 		echo "Tried to locate ${kdump_kernel}"
-		exit 0
+		return 0
 	fi
 
 	if [ ! -f $kdump_initrd ]; then
 		echo  -n "No kdump initial ramdisk found."; warning; echo
-		echo "Tried to locate ${kdump_initrd}"
-		return 1
+		echo "Rebuilding $kdump_initrd"
+		/sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+		if [ $? != 0 ]; then
+			echo "Failed to run mkdumprd"
+			$LOGGER "mkdumprd: failed to make kdump initrd"
+			exit 1
+		fi
+		return 0
 	fi
 
 	#check to see if config file has been modified after
@@ -82,17 +95,52 @@
 		echo "Detected $KDUMP_CONFIG_FILE or $kdump_kernel change"
 		echo "Rebuilding $kdump_initrd"
 		/sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+		if [ $? != 0 ]; then
+			echo "Failed to run mkdumprd"
+			$LOGGER "mkdumprd: failed to make kdump initrd"
+			return 1
+		fi
 	fi
 
-	#hack until we stop making initrd for kdump during rpm install
-	#allow initrd 120 seconds to be created before considering it new
-	module_time=`stat -c "%Y" /lib/modules/${kdump_kver}`
-	let module_time=module_time+120
-	if [ ! "$image_time" -gt "$module_time" ]; then
-		echo "Detected initial rpm install"
-		echo "Rebuilding $kdump_initrd"
-		/sbin/mkdumprd -d -f $kdump_initrd $kdump_kver
+}
+
+# This function check iomem and determines if we have more than
+# 4GB of ram available. Returns 1 if we do, 0 if we dont
+function need_64bit_headers()
+{
+
+	MEMSZ=`sed -e's/\(^[0-9]\+.*\)/0x\1/' -e's/\(-\)\(.*\)/ 0x\2/' /proc/iomem | \
+	awk 'BEGIN {
+		totalmem=0;
+		segmentmem=0;
+	     }
+	     /.*RAM.*/ {
+		start = strtonum($1);
+		end = strtonum($2);
+		segmentmem=end-start;
+		totalmem=totalmem+(segmentmem/1024);
+		if (end >= 4194304) {
+			totalmem=totalmem+4194304;
+		}
+	     }
+	     END {
+		printf "%d", (totalmem+1);
+	     }'`
+
+	#The AWK script above computes the total number of KB 
+	#in the RAM areas of /proc/iomem
+	#Note also that we set totalmem to 4GB in the event that
+	#any physical address is larger than 4GB.  This lets us
+	#default to 64 bit ELF headers for PAE kernels, which 
+	#need then to access those higher addresses.
+
+	#This comparison tells us if the above amount is more than 
+	#4GB (4096 KB).  I do the funny math to avoid overflow
+	if [ $MEMSZ -ge 4194304 ]
+	then
+		return 1
 	fi
+	return 0
 }
 
 # Load the kdump kerel specified in /etc/sysconfig/kdump
@@ -100,54 +148,215 @@
 # as the currently running kernel.
 function load_kdump()
 {
-	if [ -z "$KDUMP_COMMANDLINE" ]; then
+
+	if [ -z "$KDUMP_COMMANDLINE" ]
+	then
 		KDUMP_COMMANDLINE=`cat /proc/cmdline`
-		KDUMP_COMMANDLINE=`echo $KDUMP_COMMANDLINE | sed -e 's/crashkernel=[0-9]\+M@[0-9]\+M//g'`
-		KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} irqpoll"
 	fi
 
+	ARCH=`uname -m`
+	if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
+	then
+
+		need_64bit_headers
+		if [ $? == 1 ]
+		then
+			FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf32-core-headers`
+			if [ -n "$FOUND_ELF_ARGS" ]
+			then
+				echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
+				warning
+				echo
+			else	
+				KEXEC_ARGS="$KEXEC_ARGS --elf64-core-headers"
+			fi
+		else
+			FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf64-core-headers`
+			if [ -z "$FOUND_ELF_ARGS" ]
+			then
+				KEXEC_ARGS="$KEXEC_ARGS --elf32-core-headers"
+			fi
+		fi
+	fi
+
+	KDUMP_COMMANDLINE=`echo $KDUMP_COMMANDLINE | sed -e 's/crashkernel=[0-9]\+M@[0-9]\+M//g'`
+	KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}"
+
 	$KEXEC $KEXEC_ARGS $standard_kexec_args \
 		--command-line="$KDUMP_COMMANDLINE" \
-		--initrd=$kdump_initrd $kdump_kernel
-
+		--initrd=$kdump_initrd $kdump_kernel 2>/dev/null
 	if [ $? == 0 ]; then
-		touch /var/run/kdump.status
+		$LOGGER "kexec: loaded kdump kernel"
+		return 0
+	else
+		$LOGGER "kexec: failed to load kdump kernel"
+		return 1
+	fi
+}
+
+function propagate_ssh_key()
+{
+	#Check if selinux is on... must flip to permissive mode
+	#for the moment to create key, then flip back...
+	se_enforce=`/usr/sbin/sestatus | grep -c "^Current mode.*enforcing"`
+	if [ "$se_enforce" -ge 1 ]; then
+		/usr/sbin/setenforce 0 2>&1 > /dev/null
+	fi
+
+	#Use dedicated key for kdump
+	if [ ! -d /root/.ssh ]; then
+		mkdir /root/.ssh
+		chmod 700 /root/.ssh
+	fi
+	if [ ! -e /root/.ssh/config ]; then
+		echo "IdentityFile ~/.ssh/kdump_id_rsa" >> /root/.ssh/config
+	elif [ `grep -c kdump_id_rsa /root/.ssh/config` -eq 0 ]; then
+		echo "IdentityFile ~/.ssh/kdump_id_rsa" >> /root/.ssh/config
+	fi
+	local KEYFILE=/root/.ssh/kdump_id_rsa.pub
+	local errmsg="Failed to propagate ssh key"
+
+	#make sure they've configured kdump.conf for ssh dumps
+	local SSH_TARGET=`awk '/^\ *net.*@.*$/ {print $0}' $KDUMP_CONFIG_FILE`
+	if [ -z "$SSH_TARGET" ]; then
+		echo "No ssh config specified in $KDUMP_CONFIG_FILE.  Can't propagate"
+		$LOGGER "$errmsg, no ssh config specified in $KDUMP_CONFIG_FILE"
+		exit 1
+	fi
+
+	#Check to see if we already created key, if not, create it.
+	if [ -f $KEYFILE ]; then
+		echo "Using existing keys..."
+	else
+		echo -n "Generating new ssh keys... "
+		/usr/bin/ssh-keygen -t rsa -f /root/.ssh/kdump_id_rsa -N "" 2>&1 > /dev/null
+		echo "done."
 	fi
 
+	#If necessary, flip selinux back to enforcing
+	if [ "$se_enforce" -ge 1 ]; then
+		/usr/sbin/setenforce 1 2>&1 > /dev/null
+	fi
+	
+	#now find the target ssh user and server to contact.
+	SSH_USER=`echo $SSH_TARGET | cut -d\  -f2 | cut -d@ -f1`
+	SSH_SERVER=`echo $SSH_TARGET | sed -e's/\(.*@\)\(.*$\)/\2/'`
+ 
+	#now send the found key to the found server
+	cat $KEYFILE | ssh -x $SSH_USER@$SSH_SERVER "mkdir -p ~$SSH_USER/.ssh; chmod 700 ~$SSH_USER/.ssh;  cat >> ~$SSH_USER/.ssh/authorized_keys2"
+	RET=$?
+	if [ $RET == 0 ]; then
+		echo $KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys2 on $SSH_SERVER
+		$LOGGER "propagated ssh key (ssh server: $SSH_SERVER)"
+		return 0
+	else
+		echo $KEYFILE failed in transfer to $SSH_SERVER
+		$LOGGER "$errmsg, unable to transfer $KEYFILE to $SSH_SERVER"
+		exit 1
+	fi
+		
+}
+
+function status()
+{
+	if [ ! -e /sys/kernel/kexec_crash_loaded ]
+	then
+		return 2 
+	fi
+	rc=`cat /sys/kernel/kexec_crash_loaded`
+	if [ $rc == 1 ]; then
+		return 0
+	else
+		return 1
+	fi
+}
+
+function start()
+{
+	#TODO check raw partition for core dump image
+	status 
+	rc=$?
+	if [ $rc == 2 ]; then
+		echo -n "Kdump is not supported on this kernel"; failure; echo
+		return 1;
+	else
+		if [ $rc == 0 ]; then
+			echo -n "Kdump already running"; success; echo
+			return 0
+		fi
+	fi
+	check_config
+	if [ $? != 0 ]; then
+		echo -n "Starting kdump:"; failure; echo
+		$LOGGER "failed to start up, config file incorrect"
+		return 1
+	fi
+	load_kdump
+	if [ $? != 0 ]; then
+		echo -n "Starting kdump:"; failure; echo
+		$LOGGER "failed to start up"
+		return 1
+	fi
+
+	echo -n "Starting kdump:"; success; echo
+	$LOGGER "started up"
+}
+
+function stop()
+{
+	$KEXEC -p -u 2>/dev/null
+	if [ $? == 0 ]; then
+		$LOGGER "kexec: unloaded kdump kernel"
+		echo -n "Stopping kdump:"; success; echo
+		$LOGGER "stopped"
+	else
+		$LOGGER "kexec: failed to unload kdump kernel"
+		echo -n "Stopping kdump:"; failure; echo
+		$LOGGER "failed to stop"
+	fi
 }
 
 case "$1" in
   start)
-	if [ -f /proc/vmcore ]; then
-	    save_core
-	    reboot
-        else
-	    #TODO check raw partition for core dump image
-	    check_config
-	    load_kdump
+	if [ -s /proc/vmcore ]; then
+		save_core
+		reboot
+	else
+		start
 	fi
 	;;
   stop)
-	$KEXEC -p -u
-	rm -f /var/run/kdump.status
+	stop
 	;;
   status)
-	if [ -a /var/run/kdump.status ]; then
+	EXIT_CODE=0
+	status
+	case "$?" in
+	0)
 		echo "Kdump is operational"
-	else
+		;;
+	1)
 		echo "Kdump is not operational"
-	fi 
+		EXIT_CODE=1
+		;;
+	2)
+		echo "Kdump is unsupported on this kernel"
+		EXIT_CODE=1
+		;;
+	esac
+	exit $EXIT_CODE
 	;;
   restart)
-	$KEXEC -p -u
-	rm -f /var/run/kdump.status
-	check_config
-	load_kdump
+	stop
+	start
 	;;
   condrestart)
 	;;
+  propagate)
+	propagate_ssh_key
+	;;
   *)
-	echo $"Usage: $0 {start|stop|status|restart}"
+	echo $"Usage: $0 {start|stop|status|restart|propagate}"
 	exit 1
 esac
 


Index: kdump.sysconfig
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kdump.sysconfig,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- kdump.sysconfig	5 Jul 2006 14:57:41 -0000	1.4
+++ kdump.sysconfig	15 Dec 2006 21:05:01 -0000	1.5
@@ -11,6 +11,10 @@
 # /proc/cmdline
 KDUMP_COMMANDLINE=""
 
+# This variable lets us append arguments to the current kdump commandline
+# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
+KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1"
+
 # Any additional kexec arguments required.  In most situations, this should
 # be left empty
 #

kexec-tools-1.101-Makefile.patch:
 Makefile |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

Index: kexec-tools-1.101-Makefile.patch
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools-1.101-Makefile.patch,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- kexec-tools-1.101-Makefile.patch	5 Jul 2006 19:54:50 -0000	1.3
+++ kexec-tools-1.101-Makefile.patch	15 Dec 2006 21:05:01 -0000	1.4
@@ -1,8 +1,8 @@
---- kexec-tools-1.101/Makefile.orig	2006-07-05 15:42:41.000000000 -0400
-+++ kexec-tools-1.101/Makefile	2006-07-05 15:43:09.000000000 -0400
-@@ -44,7 +44,7 @@ PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
- 
+--- kexec-tools-1.101/Makefile.orig	2006-10-20 13:42:52.000000000 -0400
++++ kexec-tools-1.101/Makefile	2006-10-20 13:43:22.000000000 -0400
+@@ -45,7 +45,7 @@
  MAN_PAGES:= kexec/kexec.8
+ MAN_PAGES+= kdump/kdump.8
  BINARIES_i386:=  $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump
 -BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
 +BINARIES_x86_64:=  $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test $(SBINDIR)/kdump

kexec-tools-1.101-ppc64-usage.patch:
 kexec-ppc64.c |    4 ++++
 1 files changed, 4 insertions(+)

Index: kexec-tools-1.101-ppc64-usage.patch
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools-1.101-ppc64-usage.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- kexec-tools-1.101-ppc64-usage.patch	22 Aug 2006 14:18:04 -0000	1.1
+++ kexec-tools-1.101-ppc64-usage.patch	15 Dec 2006 21:05:01 -0000	1.2
@@ -1,8 +1,6 @@
-Index: kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c
-===================================================================
---- kexec-tools-1.101.orig/kexec/arch/ppc64/kexec-ppc64.c
-+++ kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c
-@@ -552,6 +552,10 @@ int file_types = sizeof(file_type) / siz
+--- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c.orig	2006-10-20 11:10:39.000000000 -0400
++++ kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c	2006-10-20 11:11:22.000000000 -0400
+@@ -577,6 +577,10 @@
  
  void arch_usage(void)
  {


Index: kexec-tools.spec
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/kexec-tools.spec,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -r1.64 -r1.65
--- kexec-tools.spec	28 Sep 2006 16:16:04 -0000	1.64
+++ kexec-tools.spec	15 Dec 2006 21:05:01 -0000	1.65
@@ -1,36 +1,55 @@
 Name: kexec-tools
 Version: 1.101
-Release: 54%{?dist}
+Release: 55%{?dist}
 License: GPL
 Group: Applications/System
 Summary: The kexec/kdump userspace component.
 Source0: %{name}-%{version}.tar.gz
 Source1: kdump.init
 Source2: kdump.sysconfig
-Source3: mkdumprd
-Source4: kdump.conf
-Source5: kcp.c
-Source6: Makefile.kcp
-Source7: makedumpfile.tar.gz
-Source8: kexec-kdump-howto.txt
+Source3: kdump.sysconfig.x86_64
+Source4: kdump.sysconfig.i386
+Source5: kdump.sysconfig.ppc64
+Source6: kdump.sysconfig.ia64
+Source7: mkdumprd
+Source8: kdump.conf
+Source9: makedumpfile-1.0.7.tar.gz
+Source10: kexec-kdump-howto.txt
+Source11: firstboot_kdump.py
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Requires(pre): coreutils chkconfig sed busybox ethtool
-BuildRequires: zlib-devel elfutils-libelf-devel glib2-devel pkgconfig
+Requires(pre): coreutils chkconfig sed 
+Requires: busybox >= 1.2.0
+BuildRequires: zlib-devel elfutils-libelf-devel glib2-devel pkgconfig elfutils-libelf-devel elfutils-devel
+ExcludeArch: ppc
+%ifarch %{ix86} x86_64 ppc64 ia64
+Obsoletes: diskdumputils netdump
+%endif
 
 #
 # Patches 0 through 100 are meant for x86 kexec-tools enablement
 #
 Patch1: kexec-tools-1.101-kdump.patch
+Patch2: kexec-tools-1.101-elf-core-type.patch
 
 #
 # Patches 101 through 200 are meant for x86_64 kexec-tools enablement
 #
 Patch101: kexec-tools-1.101-disable-kdump-x8664.patch
+Patch102: kexec-tools-1.101-x86_64-exactmap.patch
 
 #
 # Patches 201 through 300 are meant for ia64 kexec-tools enablement
 #
 Patch201: kexec-tools-1.101-ia64-fixup.patch
+Patch202: kexec-tools-1.101-ia64-tools.patch
+Patch203: kexec-tools-1.101-ia64-kdump.patch
+Patch204: kexec-tools-1.101-ia64-EFI.patch
+Patch205: kexec-tools-1.101-ia64-icache-align.patch
+Patch206: kexec-tools-1.101-ia64-noio.patch
+Patch207: kexec-tools-1.101-ia64-phdr-malloc.patch
+Patch208: kexec-tools-1.101-ia64-load-offset.patch
+Patch209: kexec-tools-1.101-ia64-noio-eat.patch
+Patch210: kexec-tools-1.101-ia64-dash-l-fix.patch
 
 #
 # Patches 301 through 400 are meant for ppc64 kexec-tools enablement
@@ -39,6 +58,7 @@
 Patch302: kexec-tools-1.101-ppc64-usage.patch
 Patch303: kexec-tools-1.101-ppc64-cliargs.patch
 Patch304: kexec-tools-1.101-ppc64-platform-fix.patch
+Patch305: kexec-tools-1.101-ppc64-64k-pages.patch
 
 #
 # Patches 401 through 500 are meant for s390 kexec-tools enablement
@@ -54,12 +74,11 @@
 # Patches 601 onward are generic patches
 #
 Patch601: kexec-tools-1.101-Makefile.patch
-Patch602: kexec-tools-1.101-Makefile-kcp.patch
-Patch603: kexec-tools-1.101-et-dyn.patch
-Patch604: kexec-tools-1.101-add-makedumpfile1.patch
-Patch605: kexec-tools-1.101-add-makedumpfile2.patch
-Patch606: kexec-tools-1.101-makedumpfile-archbuild.patch
-Patch607: kexec-tools-1.101-page_h.patch
+Patch602: kexec-tools-1.101-et-dyn.patch
+Patch603: kexec-tools-1.101-page_h.patch
+Patch604: kexec-tools-1.101-elf-format.patch
+Patch605: kexec-tools-1.101-ifdown.patch
+Patch606: kexec-tools-1.101-reloc-update.patch
 
 %description
 kexec-tools provides /sbin/kexec binary that facilitates a new
@@ -72,28 +91,36 @@
 %setup -q -n %{name}-%{version}
 rm -f ../kexec-tools-1.101.spec
 %patch1 -p1
+%patch2 -p1
 %patch101 -p1
+%patch102 -p1
 %patch201 -p1
+%patch202 -p1
+%patch203 -p1
+%patch204 -p1
+%patch205 -p1
+%patch206 -p1
+%patch207 -p1
+%patch208 -p1
+%patch209 -p1
+%patch210 -p1
 %patch301 -p1
 %patch302 -p1
 %patch303 -p1
 %patch304 -p1
+%patch305 -p1
 %patch401 -p1
 %patch501 -p1
 %patch601 -p1
 %patch602 -p1
-%patch603 -p1
 
 mkdir -p -m755 kcp
-cp %{SOURCE5} kcp/kcp.c
-cp %{SOURCE6} kcp/Makefile
-mkdir makedumpfile 
-tar -C makedumpfile -z -x -v -f %{SOURCE7}
+tar -z -x -v -f %{SOURCE9}
 
+%patch603 -p1
 %patch604 -p1
 %patch605 -p1
 %patch606 -p1
-%patch607 -p1
 
 %build
 %configure \
@@ -103,9 +130,9 @@
 %endif
     --sbindir=/sbin
 rm -f kexec-tools.spec.in
-cp %{SOURCE8} .
+cp %{SOURCE10} . 
 make
-%ifarch %{ix86} x86_64
+%ifarch %{ix86} x86_64 ia64 ppc64
 make -C makedumpfile
 %endif
 
@@ -116,21 +143,41 @@
 mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
 mkdir -p -m755 $RPM_BUILD_ROOT%{_localstatedir}/crash
 mkdir -p -m755 $RPM_BUILD_ROOT%{_mandir}/man8/
+mkdir -p -m755 $RPM_BUILD_ROOT%{_docdir}
+mkdir -p -m755 $RPM_BUILD_ROOT%{_datadir}/kdump
 install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/kdump
-install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
-install -m 755 %{SOURCE3} $RPM_BUILD_ROOT/sbin/mkdumprd
-install -m 755 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf
+if [ -f $RPM_SOURCE_DIR/kdump.sysconfig.%{_target_cpu} ]; then
+	install -m 644 $RPM_SOURCE_DIR/kdump.sysconfig.%{_target_cpu} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
+else
+	install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/kdump
+fi
+install -m 755 %{SOURCE7} $RPM_BUILD_ROOT/sbin/mkdumprd
+install -m 755 %{SOURCE8} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf
 install -m 644 kexec/kexec.8 $RPM_BUILD_ROOT%{_mandir}/man8/kexec.8
-%ifarch %{ix86} x86_64
+install -m 755 %{SOURCE11} $RPM_BUILD_ROOT%{_datadir}/kdump/firstboot_kdump.py
+%ifarch %{ix86} x86_64 ia64 ppc64
 install -m 755 makedumpfile/makedumpfile $RPM_BUILD_ROOT/sbin/makedumpfile
 %endif
-
 %clean
 rm -rf $RPM_BUILD_ROOT
 
 %post
 touch /etc/kdump.conf
 /sbin/chkconfig --add kdump
+#This portion of the script is temporary.  Its only here
+#to fix up broken boxes that require special settings 
+#in /etc/sysconfig/kdump.  It will be removed when 
+#These systems are fixed.
+
+#This is for HP zx1 machines
+#They require machvec=dig on the kernel command line
+if [ -d /proc/bus/mckinley ]
+then
+	sed -e's/\(^KDUMP_COMMANDLINE_APPEND.*\)\("$\)/\1 machvec=dig"/' \
+	/etc/sysconfig/kdump > /etc/sysconfig/kdump.new
+	mv /etc/sysconfig/kdump.new /etc/sysconfig/kdump
+fi
+
 
 %postun
 
@@ -145,9 +192,20 @@
 fi
 exit 0
 
+%triggerin -- firstboot
+if [ ! -e %{_datadir}/firstboot/modules/firstboot_kdump.py ]
+then
+	ln -s %{_datadir}/kdump/firstboot_kdump.py %{_datadir}/firstboot/modules/firstboot_kdump.py
+fi
+
+
+%triggerun -- firstboot
+rm -f %{_datadir}/firstboot/modules/firstboot_kdump.py
+
 %files
 %defattr(-,root,root,-)
 /sbin/*
+%{_datadir}/kdump
 %config(noreplace,missingok) %{_sysconfdir}/sysconfig/kdump
 %config(noreplace,missingok) %{_sysconfdir}/kdump.conf
 %config %{_sysconfdir}/rc.d/init.d/kdump
@@ -162,22 +220,24 @@
 %doc kexec-kdump-howto.txt
 
 %changelog
-* Thu Sep 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-54%{dist}
-- update mkdumprd to use busybox ifup/down infrastructure
-- update initscript file to use chkconfig properly
-
-* Fri Sep 22 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
-- rewrote mkdumprd to use busybox
-
-* Tue Sep 19 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
-- added kdump howto documentation
-
-* Thu Aug 31 2006 Neil Horman <nhorman at redhat.com> - 1.101-51%{dist}
-- update mkdumprd to properly do scp and nfs based dumps
-- update docs in kdump.conf to reflect new ifc parameter
+* Fri Dec 15 2006 Neil Horman <nhorman at redhat.com> - 1.101-5%{dist}
+- Wholesale update of RHEL5 revisions 55-147
+
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-54%{dist}
+- integrate default elf format patch
 
-* Mon Aug 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-50%{dist}
-- updating to build without need for asm/page.h on x86_64
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-53%{dist}
+- Taking Viveks x86_64 crashdump patch (rcv. via email)
+
+* Tue Aug 29 2006 Neil Horman <nhorman at redhat.com> - 1.101-52%{dist}
+- Taking ia64 tools patch for bz 181358
+
+* Mon Aug 28 2006 Neil Horman <nhorman at redhat.com> - 1.101-51%{dist}
+- more doc updates
+- added patch to fix build break from kernel headers change
+
+* Thu Aug 24 2006 Neil Horman <nhorman at redhat.com> - 1.101-50%{dist}
+- repo patch to enable support for relocatable kernels.
 
 * Thu Aug 24 2006 Neil Horman <nhorman at redhat.com> - 1.101-49%{dist}
 - rewriting kcp to properly do ssh and scp
@@ -251,11 +311,6 @@
 - rebuild
 
 * Wed Jul 07 2006 Neil Horman <nhorman at redhat.com> 1.101-27.fc6
-- Modify spec/sysconfig to not autobuild kdump kernel command line
-- Add dist to revision tag
-- Build for all arches
-
-* Wed Jun 28 2006 Karsten Hopp <karsten at redhat.de> 1.101-20
 - Buildrequire zlib-devel
 
 * Thu Jun 22 2006 Neil Horman <nhorman at redhat.com> -1.101-19


Index: mkdumprd
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/mkdumprd,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- mkdumprd	28 Sep 2006 16:16:04 -0000	1.10
+++ mkdumprd	15 Dec 2006 21:05:01 -0000	1.11
@@ -25,6 +25,8 @@
 #       Guillaume Cottenceau <gc at mandrakesoft.com>
 #	Peter Jones <pjones at redhat.com>
 #       Neil Horman <nhorman at redhat.com>
+cmdname=`basename $0`
+
 umask 0022
 
 export MALLOC_PERTURB_=204
@@ -66,7 +68,8 @@
 
 vg_list=""
 net_list=""
-USING_METHOD="raw"
+USING_METHOD="local_fs"
+SAVE_PATH=/var/crash
 
 vecho()
 {
@@ -95,14 +98,14 @@
         cmd=error
     fi
 
-    $cmd "usage: `basename $0` [--version] [--help] [-v] [-d] [-f] [--preload <module>]"
+    $cmd "usage: $cmdname [--version] [--help] [-v] [-d] [-f] [--preload <module>]"
     $cmd "       [--force-ide-probe] [--force-scsi-probe | --omit-scsi-modules]"
     $cmd "       [--image-version] [--force-scsi-probe | --omit-raid-modules]"
     $cmd "       [--with=<module>] [--force-lvm-probe | --omit-lvm-modules]"
     $cmd "       [--builtin=<module>] [--omit-dmraid]"
     $cmd "       [--fstab=<fstab>] [--nocompress] <initrd-image> <kernel-version>"
     $cmd ""
-    $cmd "       (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)"
+    $cmd "       (ex: $cmdname /boot/initrd-2.2.5-15.img 2.2.5-15)"
 
     if [ "$1" == "-n" ]; then
         exit 0
@@ -233,31 +236,6 @@
     fi
 }
 
-finddmmods() {
-    line=$(/sbin/dmsetup table "$1" 2>/dev/null)
-    [ -z "$line" ] && return 1
-    type=$(echo "$line" | awk '{ print $3 }')
-    [ -z "$type" ] && return 1
-    case "$type" in
-    mirror)
-        findmodule -dm-mirror
-        ;;
-    emc)
-        findmodule -dm-emc
-        findmodule -dm-round-robin
-        ;;
-    multipath)
-        findmodule -dm-multipath
-        findmodule -dm-round-robin
-        ;;
-    crypt)
-        findmodule -dm-crypt
-        ;;
-    zero)
-        findmodule -dm-zero
-        ;;
-    esac
-}
 
 inst() {
     if [ "$#" != "2" ];then
@@ -320,7 +298,23 @@
                 continue ;;
             *) handleddevices="$handleddevices $device" ;;
         esac
-        modalias=$(cat /sys/class/net/$device/device/modalias)
+
+        case "$device" in
+        bond*)
+            modalias=bonding
+            ;;
+        eth*.*)
+            modalias=8021q
+            ;;
+        *)
+            if [ -f /sys/class/net/$device/device/modalias ]
+            then 
+                modalias=$(cat /sys/class/net/$device/device/modalias)
+            else
+                modalias=$(ethtool -i $device | awk '/^driver:/ { print $2 }')
+            fi
+            ;;
+        esac
         for driver in $(modprobe --set-version $kernel --show-depends $modalias 2>/dev/null| awk '{ print gensub(".*/","","g",$2) }') ; do
             findmodule ${driver%%.ko}
         done
@@ -367,6 +361,9 @@
 
 handlelvordev() {
     local vg=`lvs --noheadings -o vg_name $1 2>/dev/null`
+    if [ -z "$vg" ]; then
+        vg=`lvs --noheadings -o vg_name $(echo $1 | sed -e 's#^/dev/mapper/\([^-]*\)-\(.*\)$#/dev/\1/\2#') 2>/dev/null`
+    fi
     if [ -n "$vg" ]; then
         vg=`echo $vg` # strip whitespace
         case " $vg_list " in
@@ -387,29 +384,56 @@
 handlenetdev() {
     local dev=$1
     cp /etc/sysconfig/network-scripts/ifcfg-$dev $MNTIMAGE/etc
+    BOOTPROTO=""
+    VLAN=""
+    MASTER=""
+    SLAVE=""
     . $MNTIMAGE/etc/ifcfg-$dev
 
     findnetdriver $dev
 
-    if [ "$MASTER" == "yes" ]
-    then
-        #put code here to handle subdevs for a bond
-        echo "BUS_ID=\"Bonding\"" >> $MNTIMAGE/etc/ifcfg-$dev
-    elif [ "$VLAN" == "yes" ] 
-    then
-        #put code to handle vlan devices
-        echo "BUS+Id=\"Vlan\"" >> $MNTIMAGE/etc/ifcfg-$dev
-    else
-        BUS_ID=`/sbin/ethtool -i $dev | grep bus-info`
-        echo "BUS_ID=\"$BUS_ID\"" >> $MNTIMAGE/etc/ifcfg-$dev
-    fi
 
     if [ "$BOOTPROTO" == "dhcp" ]
     then
         echo iface $dev inet dhcp >> $MNTIMAGE/etc/network/interfaces
     else    
-        echo iface $dev inet static address $IPADDR netmask $NETMASK >> $MNTIMAGE/etc/network/interfaces
+        echo iface $dev inet static >> $MNTIMAGE/etc/network/interfaces
+        if [ -n "$IPADDR" ]
+        then
+            echo "  " address $IPADDR >> $MNTIMAGE/etc/network/interfaces
+        fi
+        if [ -n "$NETMASK" ]
+        then
+            echo "  " netmask $NETMASK >> $MNTIMAGE/etc/network/interfaces
+        fi
     fi
+
+    #This lets us recursively handle stacked devices
+    case "$dev" in
+        bond*)
+            #This is a bond, pick up its slaves
+            for j in `cat /sys/class/net/$dev/bonding/slaves`
+            do
+                handlenetdev $j
+            done
+            echo "BUS_ID=\"Bonding\"" >> $MNTIMAGE/etc/ifcfg-$dev
+            ;;
+        *)
+
+            if [ "$VLAN" == "yes" ] 
+            then
+                #put code to handle vlan devices
+                echo "BUS_ID=\"Vlan\"" >> $MNTIMAGE/etc/ifcfg-$dev
+                #now make sure we pick up the driver to support the 
+                #underlying interface
+                BASE_IFC=`echo $dev | cut -d"." -f1`
+                handlenetdev $BASE_IFC
+            else
+                BUS_ID=`ls -l /sys/class/net/$dev/device | sed -e's/\(.*\/\)\(.*$\)/\2/'`
+                echo "BUS_ID=\"$BUS_ID\"" >> $MNTIMAGE/etc/ifcfg-$dev
+            fi
+            ;;
+    esac
 }
 
 while [ $# -gt 0 ]; do
@@ -453,7 +477,7 @@
 	    ;;
 
 	--version)
-	    echo "mkinitrd: version $VERSION"
+	    echo "$cmdname: version $VERSION"
 	    exit 0
 	    ;;
 
@@ -574,7 +598,7 @@
 fi
 
 if [ $UID != 0 ]; then
-    error "mkinitrd must be run as root."
+    error "$cmdname must be run as root."
     exit 1
 fi
 
@@ -759,8 +783,6 @@
     findmodule $n
 done
 
-finddmmods
-
 vecho "Using modules:$MODULES"
 
 MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX`
@@ -789,7 +811,7 @@
     if [ -n "$UUID" ]; then
         UUID="--uuid $UUID"
     fi
-    emit dm create "$1" $UUID $(/sbin/dmsetup table "$1")
+    emit "echo \"$(/sbin/dmsetup table $1)\" | /sbin/dmsetup.static create \"$1\" $UUID"
 }
 
 emitdms()
@@ -805,7 +827,7 @@
             emitdm "$NAME"
             ;;
         part)
-            emit dm partadd "$NAME"
+            emit /sbin/kpartx.static -pp -a \"/dev/mapper/$NAME\"
             ;;
         esac
     done
@@ -833,7 +855,7 @@
 
             #find ethernet device used to route to remote host, ie eth0
             netdev=`/sbin/ip route get to $rhost 2>&1`
-            [ $? != 0 ] && echo "Bad kdump location: $location" && continue
+            [ $? != 0 ] && echo "Bad kdump location: $location" && exit 1 
             #the field in the ip output changes if we go to another subnet
             OFF_SUBNET=`echo $netdev | grep via`
             if [ -n "$OFF_SUBNET" ]
@@ -855,12 +877,10 @@
             ;;
         raw)
             USING_METHOD="raw"
-            ;;
-        ifc)
-            KDUMP_IFC=$location
-            if [ -n "$network" ]; then
-                network=`echo $network | sed -e's/\(^.* \)\('$netdev'\)\( .*$\)/\1 '$KDUMP_IFC' \3/'`
+            if (echo $location | egrep -q "^(LABEL|UUID)="); then
+                location=$(findfs $location)
             fi
+            handlelvordev $location
             ;;
         core_collector)
             if [ -x /sbin/makedumpfile ]; then
@@ -873,8 +893,26 @@
                 exit 1
             fi
             ;;
+        path)
+            SAVE_PATH=$location
+            ;;
+        link_delay)
+            LINK_DELAY=$location
+            ;;
+        default)
+            DEFAULT_ACTION=$location
+            ;;
         *)
-            USING_METHOD="local_fs"
+            IS_COMMENT=`echo $type | grep ^#.*$`
+            if [ -n "$IS_COMMENT" -o -z "$location" ]
+            then
+                     #don't process comments or blank line
+                     continue
+            fi
+            if (echo $location | egrep -q "^(LABEL|UUID)="); then
+                location=$(findfs $location)
+            fi
+            handlelvordev $location
             ;;
         esac
 
@@ -899,6 +937,7 @@
 mkdir -p $MNTIMAGE/dev
 mkdir -p $MNTIMAGE/proc
 mkdir -p $MNTIMAGE/sys
+mkdir -p $MNTIMAGE/tmp
 mkdir -p $MNTIMAGE/sysroot
 mkdir -p $MNTIMAGE/modules
 mkdir -p $MNTIMAGE/usr/share/udhcpc
@@ -913,7 +952,15 @@
 #if we are using makedumpfile here, then generate the config file
 if [ -n "$CORE_COLLECTOR" ]; then
     RUN_KERN_VER=`uname -r`
-    /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config -x /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux /boot/System.map-$RUN_KERN_VER 
+    if [ ! -f /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux ]
+    then
+        echo "kernel-debuginfo-$RUN_KERN_VER is not installed.  You need this to use makedumpfile!"
+        echo "please install it and restart the kdump service"
+        rm -rf $MNTIMAGE
+        rm -rf $IMAGE
+        exit 1
+    fi
+    /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config -x /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux > /dev/null
     if [ $? != 0 ]; then
         echo "could not generate makedumpfile configuration.  aborting"
         rm -rf $MNTIMAGE
@@ -985,7 +1032,41 @@
 #NETWORKING SCRIPT DIRECTORIES
 cat >> $MNTIMAGE/etc/network/if-pre-up.d/pre-up-script << EOF
 #!/bin/msh
-ifconfig \$IFACE up
+PATH=\$PATH:/scriptfns
+. /etc/ifcfg-\$IFACE
+
+LINK_DELAY=$LINK_DELAY
+if [ "\$BUS_ID" != "Vlan" ]
+then
+    ifconfig \$IFACE up
+    if [ -n "\$LINK_DELAY" ]
+    then
+        echo "\$IFACE Link Up.  Waiting \$LINK_DELAY Seconds"
+        sleep \$LINK_DELAY
+        echo "Continuing"
+    fi
+fi
+
+if [ "\$BUS_ID" == "Bonding" ]
+then
+    #this is a bond find and bring up the slaves
+    echo searching for slaves
+    find_activate_slaves \$IFACE
+elif [ "\$BUS_ID" == "Vlan" ]
+then
+    #bring up the base interface first
+    BASE_DEV=\`echo \$IFACE | cut -d"." -f1\`
+    VLAN_ID=\`echo \$IFACE | cut -d"." -f2\`
+    ifconfig \$BASE_DEV up
+    if [ -n "\$LINK_DELAY" ]
+    then
+        echo "\$IFACE Link Up.  Waiting \$LINK_DELAY Seconds"
+        sleep \$LINK_DELAY
+        echo "Continuing"
+    fi  
+    vconfig add \$BASE_DEV \$VLAN_ID
+    ifconfig \$IFACE up
+fi
 exit 0
 EOF
 
@@ -996,6 +1077,7 @@
 
 cat >> $MNTIMAGE/etc/network/if-up.d/up-script << EOF
 #!/bin/msh
+PATH=\$PATH:/scriptfns
 if [ "\$METHOD" != "dhcp" ]
 then
     . /etc/ifcfg-\$IFACE
@@ -1017,56 +1099,69 @@
 SCRIPTDIR=$MNTIMAGE/scriptfns
 mkdir -p $SCRIPTDIR
 
-cat >> $SCRIPTDIR/rename_interfaces << EOF
+cat >> $SCRIPTDIR/map_interface << EOF
 #!/bin/msh
-TMPCNT=0
+if [ -e /tmp/tmpcnt ]
+then
+    TMPCNT=\`cat /tmp/tmpcnt\`
+else
+    TMPCNT=0
+fi
 #erase previously recorded map
-rm -f /etc/iface_map
-for i in \`ls /etc/ifcfg-*\`
+RENAMED=""
+REAL_DEV=""
+NETDEV=\$1
+. /etc/ifcfg-\$NETDEV
+for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
 do
-    RENAMED=""
-    REAL_DEV=""
-    NETDEV=\`echo \$i | cut -d"-" -f2\`
-    for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
-    do
-        . /etc/ifcfg-\$NETDEV
-        case "\$BUS_ID" in
-        Bonding)
-            #do something for bonding
-            ;;
-        Vlan)
-            #do something for vlan
-            ;;
-        *)
-            INFO=\`ethtool -i \$j | grep bus-info\`
-            if [ "\$INFO" == "\$BUS_ID" -a -z "\$REAL_DEV" ]
-            then
-                REAL_DEV=\$j
-                RENAMED="yes"
-            fi
-            ;;
-        esac
-    done
+    case "\$BUS_ID" in
+    Bonding)
+        REAL_DEV=bond0
+        RENAMED="yes"
+        ;;
+    Vlan)
+        BASE_DEV=\`echo \$NETDEV | cut -d"." -f1\`
+        VLAN_ID=\`echo \$NETDEV | cut -d"." -f2\`
+        REAL_BASE=\`grep "^\$BASE_DEV " /etc/iface_map | cut -d" " -f2\` 
+        #Note we add the \ to our vlan values to escape the . for sed-ability
+        #Note we also convert . to _ to avoid problems with busybox ifup
+        REAL_DEV=\$REAL_BASE\\\\.\$VLAN_ID
+        NETDEV=\$BASE_DEV\\\\.\$VLAN_ID
+        RENAMED="yes"
+        ;;
+    *)
+        INFO=\`ls -l /sys/class/net/\$j/device 2>/dev/null |  sed -e's/\\(.*\\/\\)\\(.*$\\)/\\2/'\`
+        if [ "\$INFO" == "\$BUS_ID" -a -z "\$REAL_DEV" ]
+        then
+            REAL_DEV=\$j
+            RENAMED="yes"
+        fi
+        ;;
+    esac
+done
 
-    if [ -z "\$RENAMED" ]
-    then
-        echo "Could not find a mapping for device \$NETDEV"
-        exit 1
-    fi
+if [ -z "\$RENAMED" ]
+then
+    echo "Could not find a mapping for device \$NETDEV"
+    exit 1
+fi
 
-    #build the interface rename map
-    echo \$NETDEV \$REAL_DEV tmp\$TMPCNT>> /etc/iface_map
-    TMPCNT=\`echo \$TMPCNT 1 + p | dc\`
-    echo mapping \$NETDEV to \$REAL_DEV
-done
+#build the interface rename map
+echo \$NETDEV \$REAL_DEV tmp\$TMPCNT >> /etc/iface_map
+TMPCNT=\`echo \$TMPCNT 1 + p | dc\`
+echo \$TMPCNT > /tmp/tmpcnt
+echo mapping \$NETDEV to \$REAL_DEV
+EOF
 
+cat >> $SCRIPTDIR/rename_interfaces << EOF
+#!/bin/msh
 MAP_COUNT=\`wc -l /etc/iface_map | cut -d" " -f7 \`
 #now do all the renaming - first to temp space
 for j in \`seq 1 1 \$MAP_COUNT\`
 do
-    CURRENT=\`awk '{if (RN == ARGV[j]) print \$1}' /etc/iface_map\`
-    NEW=\`awk '{if (RN == ARGV[j]) print \$2}' /etc/iface_map\`
-    INTERIM=\`awk '{if (RN == ARGV[j]) print \$3}' /etc/iface_map\`
+    CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$1}' /etc/iface_map\`
+    NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\`
+    INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\`
     mv /etc/ifcfg-\$CURRENT /etc/ifcfg-\$INTERIM
     for i in /etc/ifcfg-\$INTERIM /etc/iface_to_activate /etc/network/interfaces
     do
@@ -1079,9 +1174,9 @@
 
 for j in \`seq 1 1 \$MAP_COUNT\`
 do
-    CURRENT=\`awk '{if (RN == ARGV[j])  print \$1}' /etc/iface_map\`
-    NEW=\`awk '{if (RN == ARGV[j]) print \$2}' /etc/iface_map\`
-    INTERIM=\`awk '{if (RN == ARGV[j]) print \$3}' /etc/iface_map\`
+    CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH)  print \$1}' /etc/iface_map\`
+    NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\`
+    INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\`
     mv /etc/ifcfg-\$INTERIM /etc/ifcfg-\$NEW
     for i in /etc/ifcfg-\$NEW /etc/iface_to_activate /etc/network/interfaces
     do
@@ -1094,6 +1189,23 @@
 exit 0
 EOF
 
+cat >> $SCRIPTDIR/find_activate_slaves << EOF
+#!/bin/msh
+BOND_MASTER=\$1
+
+for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\`
+do
+    MASTER=""
+    . /etc/ifcfg-\$j
+    if [ "\$MASTER" == "\$BOND_MASTER" ]
+    then
+        #this is a slave of the rising interface
+        echo enslaving \$j to \$BOND_MASTER
+        echo +\$j > /sys/class/net/\$BOND_MASTER/bonding/slaves
+    fi
+done
+EOF
+
 #DONT ADD STUFF to SCRIPTDIR PAST HERE
 for i in `ls $SCRIPTDIR/*`
 do
@@ -1156,10 +1268,13 @@
 #!/bin/msh
 export PATH=$PATH:/scriptfns
 mount -t proc /proc /proc
-setquiet
 echo Mounting proc filesystem
 echo Mounting sysfs filesystem
 mount -t sysfs /sys /sys
+echo 1 > /proc/sys/vm/dirty_background_ratio
+echo 5 > /proc/sys/vm/dirty_ratio
+echo 10 > /proc/sys/vm/dirty_writeback_centisecs
+echo 50 > /proc/sys/vm/dirty_expire_centisecs
 echo Creating /dev
 mount -o mode=0755 -t tmpfs /dev /dev
 mkdir /dev/pts
@@ -1232,17 +1347,23 @@
 emit "for i in \`ls /sys/block\`; do"
 emit "  MAJOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f1\`"
 emit "  MINOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f2\`"
+emit "  MINOR_RANGE=\`cat /sys/block/\$i/range | cut -d":" -f2\`"
 emit "  echo Creating block device \$i"
 emit "  mknod /dev/\$i b \$MAJOR_NUM \$MINOR_NUM"
-emit "  MINOR_END=\`echo \$MINOR_NUM 10 + p | dc\`"
-emit "  MINOR_START=\`echo \$MINOR_NUM 1 + p | dc\`"
-emit "  for j in \`seq \$MINOR_START 1 \$MINOR_END\`"
-emit "  do"
-emit "     if [ ! -e /dev/\$i\$j ]"
-emit "     then"
-emit "          mknod /dev/\$i\$j b \$MAJOR_NUM \$j"
-emit "     fi"
-emit "  done"
+emit "  if [ \"\$MINOR_RANGE\" -gt 1 ]"
+emit "  then"
+emit "    MINOR_END=\`echo \$MINOR_NUM \$MINOR_RANGE + p | dc\`"
+emit "    MINOR_START=\`echo \$MINOR_NUM 1 + p | dc\`"
+emit "    PART_NUM=1"
+emit "    for j in \`seq \$MINOR_START 1 \$MINOR_END\`"
+emit "    do"
+emit "       if [ ! -e /dev/\$i\$PART_NUM ]"
+emit "       then"
+emit "            mknod /dev/\$i\$PART_NUM b \$MAJOR_NUM \$j"
+emit "       fi"
+emit "       PART_NUM=\`expr \$PART_NUM + 1\`"
+emit "    done"
+emit "  fi"
 emit "done"
 
 if [ -n "$vg_list" ]; then
@@ -1286,7 +1407,7 @@
     emit "      DM_NUM=\`echo \$DM_NUM 1 + p | dc\`"
     emit "      if [ -z \"\$noresume\" ]"
     emit "      then"
-    emit "        /sbin/dmsetup resume /dev/mapper/\$VGRP-\$i"
+    emit "        /sbin/dmsetup.static resume /dev/mapper/\$VGRP-\$i"
     emit "      fi"
     emit "   fi"
     emit "done"
@@ -1298,15 +1419,31 @@
     echo "$KDUMP_CONFIG_FILE: $2"
     exit 1
 }
-    emit "DATE=\`date +%Y-%M-%d-%T\`"
 if [ -n "$KDUMP_CONFIG_FILE" ]; then
     memtotal=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`
     
     #timezone info for date which outputs YYYY-MM-DD-hh:mm
     cp /etc/localtime $MNTIMAGE/etc/localtime
-    bin="/sbin/dmsetup /usr/bin/scp /usr/bin/ssh /sbin/ethtool /sbin/mdadm" 
+    cp /etc/sysconfig/clock $MNTIMAGE/etc
+    emit ". /etc/clock"
+    emit " if [ \"\$UTC\" == "true" ]"
+    emit " then"
+    emit "    TIME_FORMAT=-u"
+    emit " else"
+    emit "    TIME_FORMAT=-l"
+    emit "fi"
+    emit "hwclock --hctosys \$TIME_FORMAT"
+    emit "DATE=\`date +%Y-%m-%d-%T\`"
+
+    bin="/sbin/dmsetup.static /sbin/kpartx.static" 
+
+    if [ -n "$CORE_COLLECTOR" ]; then
+        bin="$bin /sbin/makedumpfile"
+    fi
+
     #ssh, scp require libraries that aren't found with ldd
-    lib=/lib && [ -d "/lib64" ] && lib=/lib64
+    ARCH=`uname -m`
+    lib=/lib && [ -d "/lib64" -a "$ARCH" != "ppc64" ] && lib=/lib64
     k_extras="/$lib/libnss_compat.so.2 /$lib/libnss_files.so.2"
 
     #traverse the config file and setup each dump location
@@ -1327,21 +1464,40 @@
                     #setup raw case
                     emit "echo Saving to partition $location"
                     emit "dd if=/proc/vmcore of=$location"
-                    emit "cond reboot -h -f"
+                    emit "if [ $? == 0 ]"
+                    emit "then"
+                    emit "  reboot -f"
+                    emit "fi"
                     ;;
 
                 net)
-                    if [ -n "$CORE_COLLECTOR" ]; then
-                        bin="$bin /sbin/makedumpfile"
-                    fi
-
                     #build an /etc/passwd for scp to work properly
                     grep "^root" /etc/passwd > $MNTIMAGE/etc/passwd
 
                     # bring up the network
+                    emit "for i in \`ls /etc/ifcfg-*\`"
+                    emit "do"
+                    emit "   NETDEV=\`echo \$i | cut -d\"-\" -f2\`"
+                    emit "   map_interface \$NETDEV"
+                    emit "done"
                     emit "rename_interfaces"
                     emit "IFACE=\`cat /etc/iface_to_activate\`"
                     emit "ifup \$IFACE"
+                    #lets make sure we're up
+                    emit "IFADDR=\`ifconfig \$IFACE | awk '/inet addr/ {print \$2}' | cut -d\":\" -f 2\`"
+                    emit "if [ -z \"\$IFADDR\" ]"
+                    emit "then"
+                    emit "  echo \"\$IFACE failed to come up\""
+                    if [ "$DEFAULT_ACTION" == "shell" ]
+                    then
+                        emit "  echo \"Dropping to shell. exit to reboot\""
+                        emit "  /bin/msh"
+                        emit "  reboot -f"
+                    elif [ "$DEFAULT_ACTION" == "reboot" ]
+                    then
+                        emit "  reboot -f"
+                    fi 
+                    emit "fi"
                     #grab remote host and xlate into numbers
                     rhost=`echo $location | sed 's/.*@//' | cut -d':' -f1`
                     need_dns=`echo $rhost|grep [a-zA-Z]`
@@ -1349,9 +1505,17 @@
 
                     #find the local ip being used as a route to remote ip
                     netdev=`/sbin/ip route get to $rhost 2>&1`
-                    [ $? != 0 ] && echo "Bad kdump location: $location" && continue
-                    lhost=`echo $netdev|awk '{print $5;}'|head -n 1`
-           
+                    [ $? != 0 ] && echo "Bad kdump location: $location" && exit 1 
+                    OFF_SUBNET=`echo $netdev | grep via`
+                    if [ -n "$OFF_SUBNET" ]
+                    then
+                        # we are going to a different subnet
+                        lhost=`echo $netdev|awk '{print $7}'|head -n 1`
+                    else
+                        # we are on the same subnet
+                        lhost=`echo $netdev|awk '{print $5}'|head -n 1`
+                    fi
+ 
                     emit "echo Saving to remote location $location"
                     if [ -z "`echo $location|grep @`" ]; then
                         #NFS path
@@ -1360,12 +1524,18 @@
                         tmnt=`mktemp -dq`
                         kdump_chk "mount -t nfs -o nolock $rlocation $tmnt" \
                                    "Bad NFS mount $location"
-                        mkdir -p $tmnt/var/crash
-                        tdir=`mktemp -dqp $tmnt/var/crash`
+                        mkdir -p $tmnt/$SAVE_PATH
+                        tdir=`mktemp -dqp $tmnt/$SAVE_PATH`
 
-                        rc=$? && rm -rf $tdir && umount $tmnt && rm -rf $tmnt
+                        rc=$? && rm -rf $tdir 
+                        umount $tmnt
+                        if [ $? != 0 ]; then
+                            echo "Cannot unmount the temporary directory"
+                            exit 1
+                        fi
+                        rm -rf $tmnt
                         if [ $rc != "0" ]; then 
-                            echo "Cannot create directory in $location: var/crash"
+                            echo "Cannot create directory in $location: $SAVE_PATH"
                             exit 1 
                         fi
 
@@ -1378,26 +1548,31 @@
                         #setup nfs case
                         mkdir -p $MNTIMAGE/mnt
                         emit "mount -t nfs -o nolock $rlocation /mnt"
-                        emit "mkdir -p /mnt/var/crash/$lhost-\$DATE"
-                        emit "$CORE_COLLECTOR /proc/vmcore /mnt/var/crash/$lhost-\$DATE/vmcore"
+                        emit "mkdir -p /mnt/$SAVE_PATH/$lhost-\$DATE"
+                        emit "$CORE_COLLECTOR /proc/vmcore /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete"
                         emit "if [ \$? == 0 ]"
                         emit "then"
+                        emit "  mv /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete /mnt/$SAVE_PATH/$lhost-\$DATE/vmcore"
+                        emit "  umount /mnt"
                         emit "  reboot -f"
                         emit "fi"
                         emit "umount /mnt"
                     else
                         #SSH path
                         #rebuild $location replacing machine name with ip address
+                        bin="$bin /usr/bin/ssh /usr/bin/scp"
                         rlocation=`echo $location|sed 's/@.*/@'"$rhost"'/'`
                         #test ssh path and directory creation
                         s_opts="-o BatchMode=yes -o StrictHostKeyChecking=no"
-                        kdump_chk "ssh -q $s_opts $rlocation mkdir -p /var/crash/ </dev/null" \
-                                   "Could not create $location:/var/crash, check ssh keys"
-                        tdir=`ssh -q $s_opts $rlocation mktemp -dqp /var/crash </dev/null`
+                        kdump_chk "ssh -q $s_opts $rlocation mkdir -p $SAVE_PATH </dev/null" \
+                                "Could not create $location:$SAVE_PATH, you probably need to run \"service kdump propagate\""
+                        tdir=`ssh -q $s_opts $rlocation mktemp -dqp $SAVE_PATH </dev/null`
                         if [ $? != "0" ]; then
-                            echo "$KDUMP_CONFIG_FILE: Could not create temp directory in $location:/var/crash"
+                            echo "$KDUMP_CONFIG_FILE: Could not create temp directory in $location:$SAVE_PATH"
                             exit 1
                         fi
+                        #We do this to remove the temp directory from above
+                        ssh -q $s_opts $rlocation rmdir $tdir
 
                         #setup ssh case, quick check to see if setup already
                         if [ ! -r $MNTIMAGE/dev/urandom ]; then
@@ -1408,38 +1583,32 @@
                             mknod $MNTIMAGE/dev/urandom c 1 9
                         fi
                         emit "dd if=/dev/mem of=/dev/urandom count=1 bs=512 skip=100" 
-                        emit "ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mkdir /var/crash/$lhost-\$DATE"
-                        emit "scp -q -o BatchMode=yes -o StrictHostKeyChecking=no /proc/vmcore $rlocation:/var/crash/$lhost-\$DATE/vmcore"
+                        emit "ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mkdir $SAVE_PATH/$lhost-\$DATE"
+                        emit "scp -q -o BatchMode=yes -o StrictHostKeyChecking=no /proc/vmcore $rlocation:$SAVE_PATH/$lhost-\$DATE/vmcore-incomplete"
                         emit "if [ \$? == 0 ]"
                         emit "then"
+                        emit "  ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mv $SAVE_PATH/$lhost-\$DATE/vmcore-incomplete $SAVE_PATH/$lhost-\$DATE/vmcore"
                         emit "  reboot -f"
                         emit "fi"
                     fi
                     ;;
-                ifc)
-                    ;;
                 core_collector)
                     ;;
                 default)
-                    [ "$location" == "reboot" ] && emit "reboot -f"
-                    if [ "$location" == "shell" ]
-                    then
-                        emit "echo dropping to initramfs shell"
-                        emit "echo exiting this shell will reboot your system"
-                        emit "/bin/msh"
-                        emit "reboot -f"
-                    fi
-                    #else load normally on default failure case
+                    ;;
+                link_delay)
+                    ;;
+                path)
                     ;;
                 *)
                     #test filesystem and directory creation
                     kdump_chk "test -f /sbin/fsck.$type" "Unsupported type $type"
                     kdump_chk "mount -t $type $location /mnt" "Bad mount point $location"
-                    mkdir -p /mnt/var/crash
-                    tdir=`mktemp -dqp /mnt/var/crash/`
+                    mkdir -p /mnt/$SAVE_PATH
+                    tdir=`mktemp -dqp /mnt/$SAVE_PATH`
                     rc=$? && rm -rf $tdir && umount /mnt
                     if [ $rc != "0" ]; then 
-                        echo "Cannot create directory in $location: /var/crash"
+                        echo "Cannot create directory in $location: $SAVE_PATH"
                         exit 1
                     fi
                     #TODO check for available size is greater than $memtotal
@@ -1451,14 +1620,23 @@
                         CORE_COLLECTOR="cp"
                     fi
                     emit "echo Saving to the local filesystem $location"
-                    emit "fsck.$type $location"
-                    emit "mount -t $type $location /mnt"
+                    emit "DUMPDEV=$location"
+                    emit "IS_LABEL=\`echo \$DUMPDEV | grep LABEL\`"
+                    emit "IS_UUID=\`echo \$DUMPDEV | grep UUID\`"
+                    emit "if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] "
+                    emit "then"
+                    emit "  DUMPDEV=\`findfs \$DUMPDEV\`"
+                    emit "fi"
+                    emit "fsck.$type \$DUMPDEV"
+                    emit "mount -t $type \$DUMPDEV /mnt"
                     emit "if [ \$? == 0 ]"
                     emit "then"
-                    emit "  mkdir -p /mnt/var/crash/127.0.0.1-\$DATE"
-                    emit "  $CORE_COLLECTOR /proc/vmcore /mnt/var/crash/127.0.0.1-\$DATE/vmcore"
+                    emit "  mkdir -p /mnt/$SAVE_PATH/127.0.0.1-\$DATE"
+                    emit "  $CORE_COLLECTOR /proc/vmcore /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore-incomplete"
                     emit "  if [ \$? == 0 ]"
                     emit "  then"
+                    emit "      mv /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore-incomplete /mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore"
+                    emit "      umount /mnt"
                     emit "      reboot -f"
                     emit "  fi"
                     emit "fi"
@@ -1467,6 +1645,18 @@
             esac
     done < $KDUMP_CONFIG_FILE
 
+    #now handle the default action
+    if [ "$DEFAULT_ACTION" == "shell" ]
+    then
+        emit "echo dropping to initramfs shell"
+        emit "echo exiting this shell will reboot your system"
+        emit "/bin/msh"
+        emit "reboot -f"
+    elif [ "$DEFAULT_ACTION" == "reboot" ]
+    then
+        emit "reboot -f"
+    fi
+                    
     #find the shared libraries.  this snippet taken from kboot
     kdump_libs=`for n in $bin; do 
         ldd "$n" 2>/dev/null | tr -s '\011' ' ' | 
@@ -1485,7 +1675,13 @@
 emit "ROOTDEV=\`cat /proc/cmdline | grep root=\`"
 emit "if [ -n \"\$ROOTDEV\" ]"
 emit "then"
-emit "   ROOTDEV=\`cat /proc/cmdline | cut -d\" \" -f2 | sed -e's/root=//'\`"
+emit "   ROOTDEV=\`cat /proc/cmdline | sed 's/^.*root=//' | cut -d\" \" -f1\`"
+emit "   IS_LABEL=\`echo \$ROOTDEV | grep LABEL\`"
+emit "   IS_UUID=\`echo \$ROOTDEV | grep UUID\`"
+emit "   if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] "
+emit "   then"
+emit "      ROOTDEV=\`findfs \$ROOTDEV\`"
+emit "   fi"
 emit "else"
 emit "   #we need to get the root major/minor from real-root-dev"
 emit "   ROOT_DEV_NR=\`cat /proc/sys/kernel/real-root-dev\`"


Index: sources
===================================================================
RCS file: /cvs/dist/rpms/kexec-tools/devel/sources,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- sources	2 Aug 2006 19:25:03 -0000	1.3
+++ sources	15 Dec 2006 21:05:01 -0000	1.4
@@ -1,2 +1,2 @@
 b4f7ffcc294d41a6a4c40d6e44b7734d  kexec-tools-1.101.tar.gz
-aa738475824ee3d25e5030fc506366bd  makedumpfile.tar.gz
+56fcb4d8e58e22795aeb6c28408916b0  makedumpfile-1.0.7.tar.gz




More information about the fedora-cvs-commits mailing list