diff --git a/kexec-tools-1.101-kdump.patch b/kexec-tools-1.101-kdump.patch
index ced9cf5..f1c0942 100644
--- a/kexec-tools-1.101-kdump.patch
+++ b/kexec-tools-1.101-kdump.patch
@@ -1,6 +1,6 @@
diff -urNp -X dontdiff kexec-tools-1.101/configure kexec-tools-1.101-kdump/configure
--- kexec-tools-1.101/configure 2005-02-16 18:07:44.000000000 +0530
-+++ kexec-tools-1.101-kdump/configure 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/configure 2006-02-01 14:28:15.497259392 +0530
@@ -1384,12 +1384,18 @@ case $host_cpu in
powerpc )
host_cpu="ppc"
@@ -21,20 +21,65 @@ diff -urNp -X dontdiff kexec-tools-1.101/configure kexec-tools-1.101-kdump/confi
;;
* )
{ { echo "$as_me:$LINENO: error: unsupported architecture $host_cpu" >&5
-@@ -1421,6 +1427,10 @@ if test "${with_gamecube+set}" = set; th
- EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1"
- fi;
+@@ -1406,6 +1412,11 @@ if test "${host_alias}" ; then
+ fi
+ EXTRA_CFLAGS=""
+# Check whether ppc64. Add -m64 for building 64-bit binary
+if test "$ARCH" = ppc64; then
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -m64"
+fi;
++
+ # Check whether --with-objdir or --without-objdir was given.
+ if test "${with_objdir+set}" = set; then
+ withval="$with_objdir"
+@@ -1421,7 +1432,6 @@ if test "${with_gamecube+set}" = set; th
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -DCONFIG_GAMECUBE=1"
+ fi;
+-
# Check whether --with-zlib or --without-zlib was given.
if test "${with_zlib+set}" = set; then
+ withval="$with_zlib"
+diff -urNp -X dontdiff kexec-tools-1.101/configure.ac kexec-tools-1.101-kdump/configure.ac
+--- kexec-tools-1.101/configure.ac 2005-01-09 07:06:57.000000000 +0530
++++ kexec-tools-1.101-kdump/configure.ac 2006-02-01 14:28:15.498259240 +0530
+@@ -25,12 +25,18 @@ case $host_cpu in
+ powerpc )
+ host_cpu="ppc"
+ ;;
++ powerpc64 )
++ host_cpu="ppc64"
++ ;;
++ s390x )
++ host_cpu="s390"
++ ;;
+ * )
+ host_cpu="$host_cpu"
+ ;;
+ esac
+ case $host_cpu in
+- i386|ppc|x86_64|alpha|ppc64|ia64)
++ i386|ppc|x86_64|alpha|ppc64|ia64|s390)
+ ;;
+ * )
+ AC_MSG_ERROR([ unsupported architecture $host_cpu])
+@@ -45,6 +51,12 @@ if test "${host_alias}" ; then
+ OBJDIR="$OBJDIR-${host_alias}"
+ fi
+ EXTRA_CFLAGS=""
++
++# Check whether ppc64. Add -m64 for building 64-bit binary
++if test "$ARCH" = ppc64; then
++ EXTRA_CFLAGS="$EXTRA_CFLAGS -m64"
++fi;
++
+ AC_ARG_WITH([objdir], AC_HELP_STRING([--with-objdir=
],[select directory for object files]),
+ [ OBJDIR="$withval" ], [ OBJDIR="$OBJDIR" ])
+
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/crashdump-x86.c kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.c
--- kexec-tools-1.101/kexec/arch/i386/crashdump-x86.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.c 2005-12-15 16:51:43.720392560 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.c 2006-01-19 18:19:07.000000000 +0530
@@ -0,0 +1,724 @@
+/*
+ * kexec: Linux boots Linux
@@ -762,7 +807,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/crashdump-x86.c kexec-t
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/crashdump-x86.h kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.h
--- kexec-tools-1.101/kexec/arch/i386/crashdump-x86.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.h 2005-12-14 15:57:17.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/crashdump-x86.h 2006-01-19 11:41:30.000000000 +0530
@@ -0,0 +1,21 @@
+#ifndef CRASHDUMP_X86_H
+#define CRASHDUMP_X86_H
@@ -787,7 +832,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/crashdump-x86.h kexec-t
+#endif /* CRASHDUMP_X86_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/include/arch/options.h kexec-tools-1.101-kdump/kexec/arch/i386/include/arch/options.h
--- kexec-tools-1.101/kexec/arch/i386/include/arch/options.h 2004-12-22 02:23:37.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/include/arch/options.h 2005-12-14 16:00:38.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/include/arch/options.h 2006-01-19 11:41:36.000000000 +0530
@@ -6,7 +6,9 @@
#define OPT_SERIAL_BAUD (OPT_MAX+2)
#define OPT_CONSOLE_VGA (OPT_MAX+3)
@@ -810,7 +855,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/include/arch/options.h
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c kexec-tools-1.101-kdump/kexec/arch/i386/kexec-bzImage.c
--- kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c 2005-01-13 19:02:01.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-bzImage.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-bzImage.c 2006-01-19 11:41:27.000000000 +0530
@@ -214,7 +214,7 @@ int do_bzImage_load(struct kexec_info *i
/* Fill in the information BIOS calls would normally provide. */
@@ -822,7 +867,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c kexec-t
return 0;
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c kexec-tools-1.101-kdump/kexec/arch/i386/kexec-elf-x86.c
--- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c 2005-01-13 19:29:19.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-elf-x86.c 2005-12-14 15:57:18.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-elf-x86.c 2006-01-19 11:41:32.000000000 +0530
@@ -32,10 +32,12 @@
#include
#include
@@ -931,7 +976,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c kexec-t
elf_rel_get_symbol(&info->rhdr, "entry32_regs", ®s, sizeof(regs));
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c kexec-tools-1.101-kdump/kexec/arch/i386/kexec-multiboot-x86.c
--- kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c 2005-01-25 01:28:04.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-multiboot-x86.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-multiboot-x86.c 2006-01-19 11:41:27.000000000 +0530
@@ -246,7 +246,8 @@ int multiboot_x86_load(int argc, char **
mbi->boot_loader_name = sizeof(*mbi) + command_line_len;
@@ -944,7 +989,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c k
}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-x86.c kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.c
--- kexec-tools-1.101/kexec/arch/i386/kexec-x86.c 2005-02-06 04:54:35.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.c 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.c 2006-01-19 18:19:07.000000000 +0530
@@ -30,14 +30,14 @@
#include "../../kexec-elf.h"
#include "../../kexec-syscall.h"
@@ -1069,7 +1114,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-x86.c kexec-tools
}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-x86.h kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.h
--- kexec-tools-1.101/kexec/arch/i386/kexec-x86.h 2005-02-06 04:41:32.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.h 2005-12-14 15:57:16.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/kexec-x86.h 2006-01-19 11:41:29.000000000 +0530
@@ -1,6 +1,10 @@
#ifndef KEXEC_X86_H
#define KEXEC_X86_H
@@ -1099,7 +1144,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/kexec-x86.h kexec-tools
struct kexec_info *info);
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/Makefile kexec-tools-1.101-kdump/kexec/arch/i386/Makefile
--- kexec-tools-1.101/kexec/arch/i386/Makefile 2005-02-06 04:53:58.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/Makefile 2005-12-14 15:57:16.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/Makefile 2006-01-19 11:41:29.000000000 +0530
@@ -9,3 +9,4 @@ KEXEC_C_SRCS+= kexec/arch/i386/kexec-mul
KEXEC_C_SRCS+= kexec/arch/i386/kexec-beoboot-x86.c
KEXEC_C_SRCS+= kexec/arch/i386/kexec-nbi.c
@@ -1107,7 +1152,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/Makefile kexec-tools-1.
+KEXEC_C_SRCS+= kexec/arch/i386/crashdump-x86.c
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.c
--- kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c 2005-01-13 18:40:01.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.c 2006-02-01 14:41:09.489594672 +0530
@@ -94,7 +94,8 @@ void setup_linux_bootloader_parameters(
cmdline_ptr[cmdline_len - 1] = '\0';
}
@@ -1127,9 +1172,18 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c kexec
die("Cannot get memory information\n");
}
if (ranges > E820MAX) {
+@@ -164,7 +165,7 @@ void setup_linux_system_parameters(struc
+ if (range[i].type != RANGE_RAM)
+ continue;
+ if ((range[i].start <= 0x100000) && range[i].end > 0x100000) {
+- unsigned long long mem_k = (range[i].end >> 10) - 0x100000;
++ unsigned long long mem_k = (range[i].end >> 10) - 0x400;
+ real_mode->ext_mem_k = mem_k;
+ real_mode->alt_mem_k = mem_k;
+ if (mem_k > 0xfc00) {
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.h kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.h
--- kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.h 2004-12-20 17:50:22.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.h 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/i386/x86-linux-setup.h 2006-01-19 11:41:27.000000000 +0530
@@ -7,7 +7,8 @@ void setup_linux_bootloader_parameters(
unsigned long real_mode_base, unsigned long cmdline_offset,
const char *cmdline, off_t cmdline_len,
@@ -1142,7 +1196,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.h kexec
#define SETUP_BASE 0x90000
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c 2005-01-11 11:58:36.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.c 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ia64/kexec-ia64.c 2006-01-19 18:19:07.000000000 +0530
@@ -34,11 +34,11 @@
#include
@@ -1195,7 +1249,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c kexec-tool
fprintf(stderr, "Unsupported machine type: %s\n",
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.c kexec-tools-1.101-kdump/kexec/arch/ppc/kexec-ppc.c
--- kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.c 2005-01-11 11:58:03.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc/kexec-ppc.c 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ppc/kexec-ppc.c 2006-01-19 18:19:07.000000000 +0530
@@ -19,11 +19,11 @@
#include
@@ -1228,10 +1282,562 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.c kexec-tools-
}
else {
fprintf(stderr, "Unsupported machine type: %s\n",
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/crashdump-ppc64.c kexec-tools-1.101-kdump/kexec/arch/ppc64/crashdump-ppc64.c
+--- kexec-tools-1.101/kexec/arch/ppc64/crashdump-ppc64.c 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/crashdump-ppc64.c 2006-01-19 18:20:07.000000000 +0530
+@@ -0,0 +1,511 @@
++/*
++ * kexec: Linux boots Linux
++ *
++ * Created by: R Sharada (sharada@in.ibm.com)
++ * Copyright (C) IBM Corporation, 2005. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation (version 2 of the License).
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include "../../kexec.h"
++#include "../../kexec-elf.h"
++#include "../../kexec-syscall.h"
++#include "../../crashdump.h"
++#include "kexec-ppc64.h"
++#include "crashdump-ppc64.h"
++
++extern struct arch_options_t arch_options;
++
++/* 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];
++
++/*
++ * Used to save various memory ranges/regions needed for the captured
++ * kernel to boot. (lime memmap= option in other archs)
++ */
++mem_rgns_t usablemem_rgns = {0, };
++
++/* array to store memory regions to be excluded from elf header creation */
++mem_rgns_t exclude_rgns = {0, };
++
++/*
++ * To store the memory size of the first kernel and this value will be
++ * passed to the second kernel as command line (savemaxmem=xM).
++ * The second kernel will be calculated saved_max_pfn based on this
++ * variable.
++ * Since we are creating/using usable-memory property, there is no way
++ * we can determine the RAM size unless parsing the device-tree/memoy@/reg
++ * property in the kernel.
++ */
++unsigned long saved_max_mem = 0;
++
++static int sort_regions(mem_rgns_t *rgn);
++
++/* 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.
++ *
++ * Normal kexec needs to look at all of available physical memory irrespective
++ * of the fact how much of it is being used by currently running kernel.
++ * Crashdumps need to have access to memory regions actually being used by
++ * running kernel. Expecting a different file/data structure than /proc/iomem
++ * 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)
++{
++
++ int memory_ranges = 0;
++ char device_tree[256] = "/proc/device-tree/";
++ char fname[256];
++ char buf[MAXBYTES-1];
++ DIR *dir, *dmem;
++ FILE *file;
++ struct dirent *dentry, *mentry;
++ int i, n, match;
++ 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].type = RANGE_RAM;
++ memory_ranges++;
++
++ if ((dir = opendir(device_tree)) == NULL) {
++ perror(device_tree);
++ return -1;
++ }
++ while ((dentry = readdir(dir)) != NULL) {
++ if (strncmp(dentry->d_name, "memory@", 7))
++ continue;
++ strcpy(fname, device_tree);
++ strcat(fname, dentry->d_name);
++ if ((dmem = opendir(fname)) == NULL) {
++ perror(fname);
++ closedir(dir);
++ return -1;
++ }
++ while ((mentry = readdir(dmem)) != NULL) {
++ if (strcmp(mentry->d_name, "reg"))
++ continue;
++ strcat(fname, "/reg");
++ if ((file = fopen(fname, "r")) == NULL) {
++ perror(fname);
++ closedir(dmem);
++ closedir(dir);
++ return -1;
++ }
++ if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
++ perror(fname);
++ fclose(file);
++ closedir(dmem);
++ closedir(dir);
++ return -1;
++ }
++ if (memory_ranges >= MAX_MEMORY_RANGES)
++ break;
++ start = ((unsigned long long *)buf)[0];
++ end = start + ((unsigned long long *)buf)[1];
++ if (start == 0 && end >= 0x8000)
++ start = 0x8000;
++ match = 0;
++ sort_regions(&exclude_rgns);
++
++ /* exclude crash reserved regions */
++ for (i = 0; i < exclude_rgns.size; i++) {
++ cstart = exclude_rgns.ranges[i].start;
++ cend = exclude_rgns.ranges[i].end;
++ if (cstart < end && cend > start) {
++ if ((cstart == start) && (cend == end)) {
++ match = 1;
++ continue;
++ }
++ if (start < cstart && end > cend) {
++ match = 1;
++ crash_memory_range[memory_ranges].start = start;
++ crash_memory_range[memory_ranges].end = cstart - 1;
++ crash_memory_range[memory_ranges].type = RANGE_RAM;
++ memory_ranges++;
++ crash_memory_range[memory_ranges].start = cend + 1;
++ crash_memory_range[memory_ranges].end = end;
++ crash_memory_range[memory_ranges].type = RANGE_RAM;
++ memory_ranges++;
++ break;
++ } else if (start < cstart) {
++ match = 1;
++ crash_memory_range[memory_ranges].start = start;
++ crash_memory_range[memory_ranges].end = cstart - 1;
++ crash_memory_range[memory_ranges].type = RANGE_RAM;
++ memory_ranges++;
++ end = cstart - 1;
++ continue;
++ } else if (end > cend){
++ match = 1;
++ crash_memory_range[memory_ranges].start = cend + 1;
++ crash_memory_range[memory_ranges].end = end;
++ crash_memory_range[memory_ranges].type = RANGE_RAM;
++ memory_ranges++;
++ start = cend + 1;
++ continue;
++ }
++ }
++
++ } /* end of for loop */
++ if (!match) {
++ crash_memory_range[memory_ranges].start = start;
++ crash_memory_range[memory_ranges].end = end;
++ crash_memory_range[memory_ranges].type = RANGE_RAM;
++ memory_ranges++;
++ }
++
++ fclose(file);
++ }
++ closedir(dmem);
++ }
++ closedir(dir);
++
++ /*
++ * Can not trust the memory regions order that we read from
++ * device-tree. Hence, get the MAX end value.
++ */
++ for (i = 0; i < memory_ranges; i++)
++ if (saved_max_mem < crash_memory_range[i].end)
++ saved_max_mem = crash_memory_range[i].end;
++
++ *range = crash_memory_range;
++ *ranges = memory_ranges;
++#if DEBUG
++ int i;
++ printf("CRASH MEMORY RANGES\n");
++ for(i = 0; i < *ranges; i++) {
++ start = crash_memory_range[i].start;
++ end = crash_memory_range[i].end;
++ fprintf(stderr, "%016Lx-%016Lx\n", start, end);
++ }
++#endif
++ return 0;
++}
++
++/* Converts unsigned long to ascii string. */
++static void ultoa(unsigned long i, char *str)
++{
++ int j = 0, k;
++ char tmp;
++
++ do {
++ str[j++] = i % 10 + '0';
++ } while ((i /=10) > 0);
++ str[j] = '\0';
++
++ /* Reverse the string. */
++ for (j = 0, k = strlen(str) - 1; j < k; j++, k--) {
++ tmp = str[k];
++ str[k] = str[j];
++ str[j] = tmp;
++ }
++}
++
++static int add_cmdline_param(char *cmdline, unsigned long addr,
++ char *cmdstr, char *byte)
++{
++ int cmdlen, len, align = 1024;
++ char str[COMMAND_LINE_SIZE], *ptr;
++
++ /* Passing in =xxxK / =xxxM format. Saves space required in cmdline.*/
++ switch (byte[0]) {
++ case 'K':
++ if (addr%align)
++ return -1;
++ addr = addr/align;
++ break;
++ case 'M':
++ addr = addr/(align *align);
++ break;
++ }
++ ptr = str;
++ strcpy(str, cmdstr);
++ ptr += strlen(str);
++ ultoa(addr, ptr);
++ strcat(str, byte);
++ len = strlen(str);
++ cmdlen = strlen(cmdline) + len;
++ if (cmdlen > (COMMAND_LINE_SIZE - 1))
++ die("Command line overflow\n");
++ strcat(cmdline, str);
++#if DEBUG
++ fprintf(stderr, "Command line after adding elfcorehdr: %s\n", cmdline);
++#endif
++ return 0;
++}
++
++/* Prepares the crash memory elf64 headers and stores in supplied buffer. */
++static int prepare_crash_memory_elf64_headers(struct kexec_info *info,
++ void *buf, unsigned long size)
++{
++ Elf64_Ehdr *elf;
++ Elf64_Phdr *phdr;
++ int i;
++ char *bufp;
++ long int nr_cpus = 0;
++ unsigned long notes_addr;
++
++ bufp = (char*) buf;
++
++ /* 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] = ELFDATA2MSB;
++ 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_PPC64;
++ 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_per_cpu(i, ¬es_addr) < 0) {
++ /* This cpu is not present. Skip it. */
++ continue;
++ }
++ phdr = (Elf64_Phdr *) bufp;
++ bufp += sizeof(Elf64_Phdr);
++ phdr->p_type = PT_NOTE;
++ phdr->p_flags = 0;
++ phdr->p_offset = phdr->p_paddr = notes_addr;
++ phdr->p_vaddr = 0;
++ 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)++;
++ }
++
++ /* 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++) {
++ unsigned long 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;
++ if (mstart == BACKUP_START && mend == BACKUP_END)
++ phdr->p_offset = info->backup_start;
++ else
++ phdr->p_offset = mstart;
++ /* Handle linearly mapped region.*/
++ if (mend <= (MAXMEM - 1))
++ phdr->p_vaddr = mstart + PAGE_OFFSET;
++ else
++ phdr->p_vaddr = -1ULL;
++ phdr->p_paddr = mstart;
++ phdr->p_filesz = phdr->p_memsz = mend - mstart;
++ /* Do we need any alignment of segments? */
++ phdr->p_align = 0;
++
++ /* Increment number of program headers. */
++ (elf->e_phnum)++;
++ }
++ return 0;
++}
++
++/* Loads additional segments in case of a panic kernel is being loaded.
++ * One segment for backup region, another segment for storing elf headers
++ * for crash memory image.
++ */
++int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
++ unsigned long max_addr, unsigned long min_base)
++{
++ void *tmp;
++ unsigned long sz, elfcorehdr;
++ int nr_ranges, align = 1024;
++ long int nr_cpus = 0;
++ struct memory_range *mem_range;
++
++ if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
++ return -1;
++
++ /* Create a backup region segment to store backup data*/
++ sz = (BACKUP_SIZE + align - 1) & ~(align - 1);
++ tmp = xmalloc(sz);
++ memset(tmp, 0, sz);
++ info->backup_start = add_buffer(info, tmp, sz, sz, align,
++ 0, max_addr, 1);
++ reserve(info->backup_start, sz);
++ /* Create elf header segment and store crash image data. */
++ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
++ if (nr_cpus < 0) {
++ fprintf(stderr,"kexec_load (elf header segment)"
++ " failed: %s\n", strerror(errno));
++ return -1;
++ }
++ if (arch_options.core_header_type == CORE_TYPE_ELF64) {
++ sz = sizeof(Elf64_Ehdr) +
++ nr_cpus * sizeof(Elf64_Phdr) +
++ nr_ranges * sizeof(Elf64_Phdr);
++ } else {
++ sz = sizeof(Elf32_Ehdr) +
++ nr_cpus * sizeof(Elf32_Phdr) +
++ nr_ranges * sizeof(Elf32_Phdr);
++ }
++ sz = (sz + align - 1) & ~(align -1);
++ tmp = xmalloc(sz);
++ memset(tmp, 0, sz);
++ if (arch_options.core_header_type == CORE_TYPE_ELF64) {
++ if (prepare_crash_memory_elf64_headers(info, tmp, sz) < 0)
++ return -1;
++ }
++
++ elfcorehdr = add_buffer(info, tmp, sz, sz, align, min_base,
++ max_addr, 1);
++ reserve(elfcorehdr, sz);
++ /* modify and store the cmdline in a global array. This is later
++ * read by flatten_device_tree and modified if required
++ */
++ add_cmdline_param(mod_cmdline, elfcorehdr, " elfcorehdr=", "K");
++ add_cmdline_param(mod_cmdline, saved_max_mem, " savemaxmem=", "M");
++ return 0;
++}
++
++/*
++ * Used to save various memory regions needed for the captured kernel.
++ */
++
++void add_usable_mem_rgns(unsigned long long base, unsigned long long size)
++{
++ int i;
++ unsigned long long end = base + size;
++ unsigned long long ustart, uend;
++
++ base = _ALIGN_DOWN(base, PAGE_SIZE);
++ end = _ALIGN_UP(end, PAGE_SIZE);
++
++ for (i=0; i < usablemem_rgns.size; i++) {
++ ustart = usablemem_rgns.ranges[i].start;
++ uend = usablemem_rgns.ranges[i].end;
++ if (base < uend && end > ustart) {
++ if ((base >= ustart) && (end <= uend))
++ return;
++ if (base < ustart && end > uend) {
++ usablemem_rgns.ranges[i].start = base;
++ usablemem_rgns.ranges[i].end = end;
++ return;
++ } else if (base < ustart) {
++ usablemem_rgns.ranges[i].start = base;
++ return;
++ } else if (end > uend){
++ usablemem_rgns.ranges[i].end = end;
++ return;
++ }
++ }
++ }
++ usablemem_rgns.ranges[usablemem_rgns.size].start = base;
++ usablemem_rgns.ranges[usablemem_rgns.size++].end = end;
++
++#ifdef DEBUG
++ fprintf(stderr, "usable memory rgns size:%d base:%lx size:%lx\n", usablemem_rgns.size, base, size);
++#endif
++}
++
++/*
++ * Used to exclude various memory regions that do not need elf hdr generation
++ */
++
++void add_exclude_rgns(unsigned long long base, unsigned long long size)
++{
++ int i;
++ unsigned long long end = base + size;
++ unsigned long long xstart, xend;
++
++ for (i=0; i < exclude_rgns.size; i++) {
++ xstart = exclude_rgns.ranges[i].start;
++ xend = exclude_rgns.ranges[i].end;
++ if (base < xend && end > xstart) {
++ if ((base >= xstart) && (end <= xend))
++ return;
++ if (base < xstart && end > xend) {
++ exclude_rgns.ranges[i].start = base;
++ exclude_rgns.ranges[i].end = end;
++ return;
++ } else if (base < xstart) {
++ exclude_rgns.ranges[i].start = base;
++ exclude_rgns.ranges[i].end = xend;
++ return;
++ } else if (end > xend){
++ exclude_rgns.ranges[i].start = xstart;
++ exclude_rgns.ranges[i].end = end;
++ return;
++ }
++ }
++ }
++ exclude_rgns.ranges[exclude_rgns.size].start = base;
++ exclude_rgns.ranges[exclude_rgns.size++].end = end;
++
++#ifdef DEBUG
++ fprintf(stderr, "exclude rgns size:%d base:%lx end:%lx size:%lx\n", exclude_rgns.size, base, end, size);
++#endif
++}
++
++static int sort_regions(mem_rgns_t *rgn)
++{
++ int i, j;
++ unsigned long long tstart, tend;
++ for (i = 0; i < rgn->size; i++) {
++ for (j = 0; j < rgn->size - i - 1; j++) {
++ if (rgn->ranges[j].start > rgn->ranges[j+1].start) {
++ tstart = rgn->ranges[j].start;
++ tend = rgn->ranges[j].end;
++ rgn->ranges[j].start = rgn->ranges[j+1].start;
++ rgn->ranges[j].end = rgn->ranges[j+1].end;
++ rgn->ranges[j+1].start = tstart;
++ rgn->ranges[j+1].end = tend;
++ }
++ }
++ }
++ return 0;
++
++}
++
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/crashdump-ppc64.h kexec-tools-1.101-kdump/kexec/arch/ppc64/crashdump-ppc64.h
+--- kexec-tools-1.101/kexec/arch/ppc64/crashdump-ppc64.h 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/crashdump-ppc64.h 2006-01-19 18:20:04.000000000 +0530
+@@ -0,0 +1,33 @@
++#ifndef CRASHDUMP_PPC64_H
++#define CRASHDUMP_PPC64_H
++
++int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
++ unsigned long max_addr, unsigned long min_base);
++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 KERNELBASE PAGE_OFFSET
++#define VMALLOCBASE 0xD000000000000000
++
++#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
++
++#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. */
++#define BACKUP_START 0x0000
++#define BACKUP_END 0x8000
++#define BACKUP_SIZE (BACKUP_END - BACKUP_START + 1)
++
++#define KDUMP_BACKUP_LIMIT 0x8000
++#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
++#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
++#define PAGE_SIZE 4096
++
++extern unsigned long long crash_base;
++extern unsigned long long crash_size;
++
++#endif /* CRASHDUMP_PPC64_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.101-kdump/kexec/arch/ppc64/fs2dt.c
--- kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/fs2dt.c 2005-12-14 15:57:18.000000000 +0530
-@@ -0,0 +1,340 @@
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/fs2dt.c 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,435 @@
+/*
+ * fs2dt: creates a flattened device-tree
+ *
@@ -1262,7 +1868,9 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+#include
+#include
+#include
++#include "../../kexec.h"
+#include "kexec-ppc64.h"
++#include "crashdump-ppc64.h"
+
+#define MAXPATH 1024 /* max path name length */
+#define NAMESPACE 16384 /* max bytes for property names */
@@ -1296,9 +1904,12 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+dvt dtstruct[TREEWORDS], *dt;
+unsigned long long mem_rsrv[2*MEMRESERVE];
+
-+extern unsigned long initrd_base;
-+extern unsigned long initrd_size;
+static int initrd_found = 0;
++static int crash_param = 0;
++char local_cmdline[COMMAND_LINE_SIZE] = { "" };
++dvt *dt_len; /* changed len of modified cmdline in flat device-tree */
++extern mem_rgns_t usablemem_rgns;
++struct bootblock bb[1];
+
+void reserve(unsigned long long where, unsigned long long length)
+{
@@ -1322,26 +1933,12 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ err((void *)data, ERR_RESERVE);
+ else if (!strcmp(name, "linux,rtas-base"))
+ base = *data;
-+ else if (!strcmp(name, "linux,initrd-start")) {
-+ if (initrd_base)
-+ *(unsigned long long *) data = initrd_base;
-+ base = *(unsigned long long *)data;
-+ initrd_found = 1;
-+ }
+ else if (!strcmp(name, "linux,tce-base"))
+ base = *(unsigned long long *) data;
+ else if (!strcmp(name, "rtas-size") ||
+ !strcmp(name, "linux,tce-size"))
+ size = *data;
-+ else if (!strcmp(name, "linux,initrd-end")) {
-+ if (initrd_size) {
-+ *(unsigned long long *) data = initrd_base +
-+ initrd_size;
-+ size = initrd_size;
-+ } else
-+ end = *(unsigned long long *)data;
-+ initrd_found = 1;
-+ }
++
+ if (size && end)
+ err(name, ERR_RESERVE);
+ if (base && size) {
@@ -1373,6 +1970,67 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ return offset;
+}
+
++void add_usable_mem_property(int fd, int len)
++{
++ char fname[MAXPATH], *bname;
++ char buf[MAXBYTES +1];
++ unsigned long ranges[2*MAX_MEMORY_RANGES];
++ unsigned long long base, end, loc_base, loc_end;
++ int range, rlen = 0;
++
++ strcpy(fname, pathname);
++ bname = strrchr(fname,'/');
++ bname[0] = '\0';
++ bname = strrchr(fname,'/');
++ if (strncmp(bname, "/memory@", 8))
++ return;
++
++ lseek(fd, 0, SEEK_SET);
++ if (read(fd, buf, len) != len)
++ err(pathname, ERR_READ);
++
++ base = ((unsigned long long *)buf)[0];
++ end = base + ((unsigned long long *)buf)[1];
++
++ for (range = 0; range < usablemem_rgns.size; range++) {
++ loc_base = usablemem_rgns.ranges[range].start;
++ loc_end = usablemem_rgns.ranges[range].end;
++ if (loc_base >= base && loc_end <= end) {
++ ranges[rlen++] = loc_base;
++ ranges[rlen++] = loc_end - loc_base;
++ } else if (base < loc_end && end > loc_base) {
++ if (loc_base < base)
++ loc_base = base;
++ if (loc_end > end)
++ loc_end = end;
++ ranges[rlen++] = loc_base;
++ ranges[rlen++] = loc_end - loc_base;
++ }
++ }
++
++ if (!rlen) {
++ /*
++ * User did not pass any ranges for thsi region. Hence, write
++ * (0,0) duple in linux,usable-memory property such that
++ * this region will be ignored.
++ */
++ ranges[rlen++] = 0;
++ ranges[rlen++] = 0;
++ }
++
++ rlen = rlen * sizeof(unsigned long);
++ /*
++ * No add linux,usable-memory property.
++ */
++ *dt++ = 3;
++ *dt++ = rlen;
++ *dt++ = propnum("linux,usable-memory");
++ if ((rlen >= 8) && ((unsigned long)dt & 0x4))
++ dt++;
++ memcpy(dt,&ranges,rlen);
++ dt += (rlen + 3)/4;
++}
++
+/* put all properties (files) in the property structure */
+void putprops(char *fn, DIR *dir)
+{
@@ -1384,11 +2042,10 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ if (lstat(pathname, statbuf))
+ err(pathname, ERR_STAT);
+
-+ /* skip initrd entries if 2nd kernel does not need them */
-+ if (!initrd_base && !strcmp(fn,"linux,initrd-end"))
++ if (!crash_param && !strcmp(fn,"linux,crashkernel-base"))
+ continue;
+
-+ if (!initrd_base && !strcmp(fn,"linux,initrd-start"))
++ if (!crash_param && !strcmp(fn,"linux,crashkernel-size"))
+ continue;
+
+ /*
@@ -1396,15 +2053,23 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ * boot. So, ignore it.
+ */
+ if (!strcmp(dp->d_name, "linux,pci-domain") ||
-+ !strcmp(dp->d_name, "htab_base") ||
-+ !strcmp(dp->d_name, "htab_size") ||
-+ !strcmp(dp->d_name, "kernel_end"))
-+ continue;
++ !strcmp(dp->d_name, "linux,htab-base") ||
++ !strcmp(dp->d_name, "linux,htab-size") ||
++ !strcmp(dp->d_name, "linux,kernel-end"))
++ continue;
++
++ /* This property will be created/modified later in putnode()
++ * So ignore it.
++ */
++ if (!strcmp(dp->d_name, "linux,initrd-start") ||
++ !strcmp(dp->d_name, "linux,initrd-end"))
++ continue;
+
+ if (S_ISREG(statbuf[0].st_mode)) {
+ int fd, len = statbuf[0].st_size;
+
+ *dt++ = 3;
++ dt_len = dt;
+ *dt++ = len;
+ *dt++ = propnum(fn);
+
@@ -1416,11 +2081,45 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ err(pathname, ERR_OPEN);
+ if (read(fd, dt, len) != len)
+ err(pathname, ERR_READ);
-+ close(fd);
+
+ checkprop(fn, dt);
+
++ /* Get the cmdline from the device-tree and modify it */
++ if (!strcmp(dp->d_name, "bootargs")) {
++ int cmd_len;
++ char temp_cmdline[COMMAND_LINE_SIZE] = { "" };
++ char *param = NULL;
++ cmd_len = strlen(local_cmdline);
++ if (cmd_len != 0) {
++ param = strstr(local_cmdline,
++ "crashkernel=");
++ if (param)
++ crash_param = 1;
++ param = NULL;
++ param = strstr(local_cmdline, "root=");
++ }
++ if (!param) {
++ char *old_param;
++ memcpy(temp_cmdline, dt, len);
++ param = strstr(temp_cmdline, "root=");
++ old_param = strtok(param, " ");
++ if (cmd_len != 0)
++ strcat(local_cmdline, " ");
++ strcat(local_cmdline, old_param);
++ }
++ strcat(local_cmdline, " ");
++ cmd_len = strlen(local_cmdline);
++ cmd_len = cmd_len + 1;
++ memcpy(dt,local_cmdline,cmd_len);
++ len = cmd_len;
++ *dt_len = cmd_len;
++ fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
++ }
++
+ dt += (len + 3)/4;
++ if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
++ add_usable_mem_property(fd, len);
++ close(fd);
+ }
+ }
+ fn[0] = '\0';
@@ -1486,7 +2185,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ if ((len >= 8) && ((unsigned long)dt & 0x4))
+ dt++;
+
-+ memcpy(dt,&initrd_end,8);
++ memcpy(dt,&initrd_end,len);
+ dt += (len + 3)/4;
+
+ reserve(initrd_base, initrd_size);
@@ -1514,9 +2213,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ dn[-1] = '\0';
+}
+
-+struct bootblock bb[1];
-+
-+int create_flatten_tree(struct kexec_info *info, unsigned char **bufp, unsigned long *sizep)
++int create_flatten_tree(struct kexec_info *info, unsigned char **bufp,
++ unsigned long *sizep, char *cmdline)
+{
+ unsigned long len;
+ unsigned long tlen;
@@ -1530,6 +2228,9 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ pathstart = pathname + strlen(pathname);
+ dt = dtstruct;
+
++ if (cmdline)
++ strcpy(local_cmdline, cmdline);
++
+ putnode();
+ *dt++ = 9;
+
@@ -1559,10 +2260,10 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+
+ reserve(me, bb->totalsize); /* patched later in kexec_load */
+
-+ buf = (unsigned char *) realloc(*bufp, *sizep + bb->totalsize);
++ buf = (unsigned char *) malloc(bb->totalsize);
+ *bufp = buf;
-+ memcpy(buf+(*sizep), bb, bb->off_mem_rsvmap);
-+ tlen = *sizep + bb->off_mem_rsvmap;
++ memcpy(buf, bb, bb->off_mem_rsvmap);
++ tlen = bb->off_mem_rsvmap;
+ memcpy(buf+tlen, mem_rsrv, bb->off_dt_struct - bb->off_mem_rsvmap);
+ tlen = tlen + (bb->off_dt_struct - bb->off_mem_rsvmap);
+ memcpy(buf+tlen, dtstruct, bb->off_dt_strings - bb->off_dt_struct);
@@ -1572,26 +2273,45 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c kexec-tools-1.
+ *sizep = tlen;
+ return 0;
+}
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/include/arch/options.h kexec-tools-1.101-kdump/kexec/arch/ppc64/include/arch/options.h
+--- kexec-tools-1.101/kexec/arch/ppc64/include/arch/options.h 2004-12-22 01:56:00.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/include/arch/options.h 2006-01-19 18:20:07.000000000 +0530
+@@ -2,9 +2,11 @@
+ #define KEXEC_ARCH_PPC64_OPTIONS_H
+
+ #define OPT_ARCH_MAX (OPT_MAX+0)
++#define OPT_ELF64_CORE (OPT_MAX+1)
+
+ #define KEXEC_ARCH_OPTIONS \
+ KEXEC_OPTIONS \
++ { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \
+
+ #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c 2004-12-17 15:02:04.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-ppc64.c 2005-12-14 16:00:37.000000000 +0530
-@@ -3,6 +3,7 @@
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-ppc64.c 2006-01-19 18:20:08.000000000 +0530
+@@ -3,6 +3,8 @@
*
* Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
* Copyright (C) 2004 IBM Corp.
+ * Copyright (C) 2005 R Sharada (sharada@in.ibm.com)
++ * Copyright (C) 2006 Mohan Kumar M (mohan@in.ibm.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
-@@ -33,45 +34,15 @@
+@@ -32,46 +34,19 @@
+ #include
#include "../../kexec.h"
#include "../../kexec-elf.h"
++#include "../../kexec-syscall.h"
#include "kexec-ppc64.h"
++#include "crashdump-ppc64.h"
+#include
#define BOOTLOADER "kexec"
#define BOOTLOADER_VERSION VERSION
- #define MAX_COMMAND_LINE 256
+-#define MAX_COMMAND_LINE 256
-#define UPSZ(X) ((sizeof(X) + 3) & ~3)
-static struct boot_notes {
@@ -1627,35 +2347,48 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c kexe
- .n_type = EBN_COMMAND_LINE,
- },
-};
-+int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *);
-+int parse_options(char *);
-+int setup_memory_ranges(void);
++unsigned long initrd_base, initrd_size;
++
++int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
++ char *);
++int my_r2(struct mem_ehdr *ehdr);
int elf_ppc64_probe(const char *buf, off_t len)
{
-@@ -94,12 +65,69 @@ int elf_ppc64_probe(const char *buf, off
+@@ -94,12 +69,91 @@ int elf_ppc64_probe(const char *buf, off
return result;
}
-int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
+- struct kexec_info *info)
+int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
- struct kexec_info *info)
++ struct kexec_info *info)
{
struct mem_ehdr ehdr;
-+ const char *command_line;
-+ const char *input_options;
-+ int command_line_len;
-+ const char *ramdisk;
-+ const char *devicetreeblob;
-+ unsigned long *lp;
-+ int result;
-+ int opt;
++ char *cmdline, *modified_cmdline;
++ const char *ramdisk, *devicetreeblob;
++ int cmdline_len, modified_cmdline_len;
++ unsigned long long max_addr, hole_addr;
++ unsigned char *seg_buf = NULL;
++ off_t seg_size = 0;
++ struct mem_phdr *phdr;
++ size_t size;
++ unsigned long long *rsvmap_ptr;
++ struct bootblock *bb_ptr;
++ unsigned int nr_segments, i;
++ int result, opt;
++ unsigned long my_kernel, my_dt_offset;
++ unsigned int my_panic_kernel;
++ unsigned long my_stack, my_backup_start;
++ unsigned long toc_addr;
++
+#define OPT_APPEND (OPT_ARCH_MAX+0)
+#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_DEVICETREEBLOB (OPT_ARCH_MAX+2)
+
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
++ { "command-line", 1, NULL, OPT_APPEND },
+ { "append", 1, NULL, OPT_APPEND },
+ { "ramdisk", 1, NULL, OPT_RAMDISK },
+ { "devicetreeblob", 1, NULL, OPT_DEVICETREEBLOB },
@@ -1667,23 +2400,24 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c kexe
/* Parse command line arguments */
+ initrd_base = 0;
+ initrd_size = 0;
-+ command_line = 0;
-+ input_options = 0;
++ cmdline = 0;
+ ramdisk = 0;
+ devicetreeblob = 0;
++ max_addr = 0xFFFFFFFFFFFFFFFFUL;
++ hole_addr = 0;
+
-+ while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
++ while ((opt = getopt_long(argc, argv, short_options,
++ options, 0)) != -1) {
+ switch (opt) {
+ default:
+ /* Ignore core options */
-+ if (opt < OPT_ARCH_MAX) {
++ if (opt < OPT_ARCH_MAX)
+ break;
-+ }
+ case '?':
+ usage();
+ return -1;
+ case OPT_APPEND:
-+ input_options = optarg;
++ cmdline = optarg;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
@@ -1694,38 +2428,45 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c kexe
+ }
+ }
+
-+ command_line_len = 0;
-+ if (command_line) {
-+ command_line_len = strlen(command_line) + 1;
-+ }
++ cmdline_len = 0;
++ if (cmdline)
++ cmdline_len = strlen(cmdline) + 1;
+
-+ if (input_options)
-+ parse_options(input_options);
++ setup_memory_ranges(info->kexec_flags);
++
++ /* Need to append some command line parameters internally in case of
++ * taking crash dumps.
++ */
++ if (info->kexec_flags & KEXEC_ON_CRASH) {
++ modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
++ memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
++ if (cmdline) {
++ strncpy(modified_cmdline, cmdline, COMMAND_LINE_SIZE);
++ modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
++ }
++ modified_cmdline_len = strlen(modified_cmdline);
++ }
/* Parse the Elf file */
result = build_elf_exec_info(buf, len, &ehdr);
-@@ -109,15 +137,180 @@ int elf_ppc64_load(int argc, char **argv
+@@ -108,13 +162,171 @@ int elf_ppc64_load(int argc, char **argv
+ return result;
}
- /* Load the Elf data */
-+ setup_memory_ranges();
+- /* Load the Elf data */
+ /* Load the Elf data. Physical load addresses in elf64 header do not
+ * show up correctly. Use user supplied address for now to patch the
+ * elf header
+ */
-+ unsigned long long base_addr;
-+ struct mem_phdr *phdr;
-+ size_t size;
+
+ phdr = &ehdr.e_phdr[0];
+ size = phdr->p_filesz;
-+ if (size > phdr->p_memsz) {
++ if (size > phdr->p_memsz)
+ size = phdr->p_memsz;
-+ }
+
-+ base_addr = (unsigned long)locate_hole(info, size, 0, 0,
-+ 0xFFFFFFFFFFFFFFFFUL, 1);
-+ ehdr.e_phdr[0].p_paddr = base_addr;
++ hole_addr = (unsigned long)locate_hole(info, size, 0, 0,
++ max_addr, 1);
++ ehdr.e_phdr[0].p_paddr = hole_addr;
result = elf_exec_load(&ehdr, info);
if (result < 0) {
free_elf_info(&ehdr);
@@ -1733,175 +2474,244 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c kexe
}
- return 1;
+
-+ /* Add a ram-disk to the current image */
-+ if (ramdisk) {
-+ if (devicetreeblob) {
-+ fprintf(stderr, "Can't use ramdisk with device tree blob input\n");
-+ return -1;
-+ }
-+ unsigned char *ramdisk_buf = NULL;
-+ off_t ramdisk_size = 0;
-+ unsigned long long ramdisk_addr;
-+
-+ ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
-+ add_buffer(info, ramdisk_buf, ramdisk_size, ramdisk_size, 0, 0,
-+ 0xFFFFFFFFFFFFFFFFUL, 1);
-+ ramdisk_addr = (unsigned long long)info->segment[info->nr_segments-1].mem;
-+ initrd_base = ramdisk_addr;
-+ initrd_size = ramdisk_size;
++ /* If panic kernel is being loaded, additional segments need
++ * to be created.
++ */
++ if (info->kexec_flags & KEXEC_ON_CRASH) {
++ result = load_crashdump_segments(info, modified_cmdline,
++ max_addr, 0);
++ if (result < 0)
++ return -1;
++ /* Use new command line. */
++ cmdline = modified_cmdline;
++ cmdline_len = strlen(modified_cmdline) + 1;
+ }
+
+ /* Add v2wrap to the current image */
-+ unsigned char *v2wrap_buf = NULL;
-+ off_t v2wrap_size = 0;
-+ unsigned long long *rsvmap_ptr;
-+ struct bootblock *bb_ptr;
-+ unsigned int devtree_size;
++ seg_buf = NULL;
++ seg_size = 0;
+
-+ v2wrap_buf = (char *) malloc(purgatory_size);
-+ if (v2wrap_buf == NULL) {
++ seg_buf = (char *) malloc(purgatory_size);
++ if (seg_buf == NULL) {
+ free_elf_info(&ehdr);
+ return -1;
+ }
-+ memcpy(v2wrap_buf, purgatory, purgatory_size);
-+ v2wrap_size = purgatory_size;
++ memcpy(seg_buf, purgatory, purgatory_size);
++ seg_size = purgatory_size;
++ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
++ 0, max_addr, 1);
++
++ /* Add a ram-disk to the current image
++ * Note: Add the ramdisk after elf_rel_build_load
++ */
++ if (ramdisk) {
++ if (devicetreeblob) {
++ fprintf(stderr,
++ "Can't use ramdisk with device tree blob input\n");
++ return -1;
++ }
++ seg_buf = slurp_file(ramdisk, &seg_size);
++ add_buffer(info, seg_buf, seg_size, seg_size, 0, 0, max_addr, 1);
++ hole_addr = (unsigned long long)
++ info->segment[info->nr_segments-1].mem;
++ initrd_base = hole_addr;
++ initrd_size = (unsigned long long)
++ info->segment[info->nr_segments-1].memsz;
++ } /* ramdisk */
++
+ if (devicetreeblob) {
-+ unsigned char *blob_buf = NULL;
-+ off_t blob_size = 0;
-+ unsigned char *tmp_buf = NULL;
++ unsigned char *blob_buf = NULL;
++ off_t blob_size = 0;
+
-+ /* Grab device tree from buffer */
-+ blob_buf = slurp_file(devicetreeblob, &blob_size);
-+
-+ /* Append to purgatory */
-+ tmp_buf = (unsigned char *) realloc(v2wrap_buf, v2wrap_size + blob_size);
-+ v2wrap_buf = tmp_buf;
-+ memcpy(v2wrap_buf+v2wrap_size, blob_buf, blob_size);
-+ v2wrap_size += blob_size;
++ /* Grab device tree from buffer */
++ blob_buf = slurp_file(devicetreeblob, &blob_size);
++ add_buffer(info, blob_buf, blob_size, blob_size, 0, 0,
++ max_addr, -1);
+
+ } else {
-+ /* create from fs2dt */
-+ create_flatten_tree(info, &v2wrap_buf, &v2wrap_size);
++ /* create from fs2dt */
++ seg_buf = NULL;
++ seg_size = 0;
++ create_flatten_tree(info, &seg_buf, &seg_size, cmdline);
++ add_buffer(info, seg_buf, seg_size, seg_size,
++ 0, 0, max_addr, -1);
+ }
-+ add_buffer(info, v2wrap_buf, v2wrap_size, v2wrap_size, 0, 0,
-+ 0xFFFFFFFFFFFFFFFFUL, -1);
+
+ /* patch reserve map address for flattened device-tree
-+ find last entry (both 0) in the reserve mem list. Assume DT
-+ entry is before this one */
++ * find last entry (both 0) in the reserve mem list. Assume DT
++ * entry is before this one
++ */
+ bb_ptr = (struct bootblock *)(
-+ (unsigned char *)info->segment[(info->nr_segments)-1].buf +
-+ 0x100);
++ (unsigned char *)info->segment[(info->nr_segments)-1].buf);
+ rsvmap_ptr = (long long *)(
+ (unsigned char *)info->segment[(info->nr_segments)-1].buf +
-+ bb_ptr->off_mem_rsvmap + 0x100);
-+ while (*rsvmap_ptr || *(rsvmap_ptr+1)){
++ bb_ptr->off_mem_rsvmap);
++ while (*rsvmap_ptr || *(rsvmap_ptr+1))
+ rsvmap_ptr += 2;
-+ }
+ rsvmap_ptr -= 2;
-+ *rsvmap_ptr = (unsigned long long)(
-+ info->segment[(info->nr_segments)-1].mem + 0x100);
-+ rsvmap_ptr++;
-+ *rsvmap_ptr = (unsigned long long)bb_ptr->totalsize;
++ *rsvmap_ptr = (unsigned long long)(
++ info->segment[(info->nr_segments)-1].mem);
++ rsvmap_ptr++;
++ *rsvmap_ptr = (unsigned long long)bb_ptr->totalsize;
+
-+ unsigned int nr_segments;
+ nr_segments = info->nr_segments;
-+ lp = info->segment[nr_segments-1].buf + 0x100;
-+ lp--;
-+ *lp = info->segment[0].mem;
-+ info->entry = info->segment[nr_segments-1].mem;
+
-+ unsigned int i;
++ /* Set kernel */
++ my_kernel = (unsigned long )info->segment[0].mem;
++ elf_rel_set_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
++
++ /* Set dt_offset */
++ my_dt_offset = (unsigned long )info->segment[nr_segments-1].mem;
++ elf_rel_set_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
++ sizeof(my_dt_offset));
++
++ if (info->kexec_flags & KEXEC_ON_CRASH) {
++ my_panic_kernel = 1;
++ /* Set panic flag */
++ elf_rel_set_symbol(&info->rhdr, "panic_kernel",
++ &my_panic_kernel, sizeof(my_panic_kernel));
++
++ /* Set backup address */
++ my_backup_start = info->backup_start;
++ elf_rel_set_symbol(&info->rhdr, "backup_start",
++ &my_backup_start, sizeof(my_backup_start));
++ }
++
++ /* Set stack address */
++ my_stack = locate_hole(info, 16*1024, 0, 0, max_addr, 1);
++ my_stack += 16*1024;
++ elf_rel_set_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
++
++ /* Set toc */
++ toc_addr = (unsigned long) my_r2(&info->rhdr);
++ elf_rel_set_symbol(&info->rhdr, "my_toc", &toc_addr, sizeof(toc_addr));
++
++#ifdef DEBUG
++ my_kernel = 0;
++ my_dt_offset = 0;
++ my_panic_kernel = 0;
++ my_backup_start = 0;
++ my_stack = 0;
++ toc_addr = 0;
++
++ elf_rel_get_symbol(&info->rhdr, "kernel", &my_kernel, sizeof(my_kernel));
++ elf_rel_get_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
++ sizeof(my_dt_offset));
++ elf_rel_get_symbol(&info->rhdr, "panic_kernel", &my_panic_kernel,
++ sizeof(my_panic_kernel));
++ elf_rel_get_symbol(&info->rhdr, "backup_start", &my_backup_start,
++ sizeof(my_backup_start));
++ elf_rel_get_symbol(&info->rhdr, "stack", &my_stack, sizeof(my_stack));
++ elf_rel_get_symbol(&info->rhdr, "my_toc", &toc_addr,
++ sizeof(toc_addr));
++
++ fprintf(stderr, "info->entry is %p\n", info->entry);
++ fprintf(stderr, "kernel is %Lx\n", my_kernel);
++ fprintf(stderr, "dt_offset is %Lx\n", my_dt_offset);
++ fprintf(stderr, "panic_kernel is %x\n", my_panic_kernel);
++ fprintf(stderr, "backup_start is %Lx\n", my_backup_start);
++ fprintf(stderr, "stack is %Lx\n", my_stack);
++ fprintf(stderr, "toc_addr is %Lx\n", toc_addr);
++ fprintf(stderr, "purgatory size is %d\n", purgatory_size);
++#endif
++
+ for (i = 0; i < nr_segments; i++)
-+ printf("segment[i].mem:%lx\n", info->segment[i].mem);
++ fprintf(stderr, "segment[%d].mem:%p memsz:%ld\n", i,
++ info->segment[i].mem, info->segment[i].memsz);
+
+ return 0;
}
void elf_ppc64_usage(void)
- {
- fprintf(stderr, "elf support is still broken\n");
- }
-+
-+struct param_struct {
-+ const char *name;
-+ void *val;
-+};
-+struct param_struct params;
-+
-+static char *next_arg(char *args, char **param, char **val)
-+{
-+ unsigned int i, equals = 0;
-+ char *next;
-+
-+ /* Chew any extra spaces */
-+ while (*args == ' ') args++;
-+ for (i = 0; args[i]; i++) {
-+ if (args[i] == ' ')
-+ break;
-+ if (equals == 0) {
-+ if (args[i] == '=')
-+ equals = i;
-+ }
-+ }
-+ *param = args;
-+ if (!equals)
-+ *val = NULL;
-+ else {
-+ args[equals] = '\0';
-+ *val = args + equals + 1;
-+ }
-+
-+ if (args[i]) {
-+ args[i] = '\0';
-+ next = args + i + 1;
-+ } else
-+ next = args + i;
-+ return next;
-+}
-+
-+static int add_arg(char *param, char*val)
-+{
-+ int ret = 0;
-+ if (strcmp(param, "initrd-base")==0)
-+ initrd_base=strtoul(val, NULL, 0);
-+ else if (strcmp(param, "initrd-size")==0)
-+ initrd_size=strtoul(val, NULL, 0);
-+ else {
-+ printf("invalid option\n");
-+ ret = 1;
-+ }
-+ return ret;
-+}
-+
-+int parse_options(char *options)
-+{
-+ char *param, *val;
-+ /* initrd-addr , initrd-size */
-+ while (*options) {
-+ int ret;
-+ options = next_arg(options, ¶m, &val);
-+ ret = add_arg(param, val);
-+ }
-+ /* All parsed OK */
-+ return 0;
-+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-rel-ppc64.c kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-rel-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2004-12-20 07:36:04.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2005-12-14 15:57:19.000000000 +0530
-@@ -22,7 +22,7 @@ static struct mem_shdr *toc_section(cons
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2006-01-19 18:20:08.000000000 +0530
+@@ -1,5 +1,6 @@
+ #include
+ #include
++#include
+ #include "../../kexec.h"
+ #include "../../kexec-elf.h"
+
+@@ -21,20 +22,19 @@ static struct mem_shdr *toc_section(cons
+ {
struct mem_shdr *shdr, *shdr_end;
unsigned char *strtab;
- strtab = ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
+- strtab = ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
- shdr_end = &ehdr->e_shdr[ehdr->shnum];
+- for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+- if (strcmp(shdr->sh_name, ".toc") == 0) {
++ strtab = (unsigned char *)ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
+ shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
- for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
- if (strcmp(shdr->sh_name, ".toc") == 0) {
++ for(shdr = ehdr->e_shdr; shdr != shdr_end; shdr++)
++ if ( shdr->sh_size &&
++ strcmp(&strtab[shdr->sh_name], ".toc") == 0)
return shdr;
+- }
+- }
+ return NULL;
+ }
+
+ /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
+ gives the value maximum span in an instruction which uses a signed
+ offset) */
+-static unsigned long my_r2(const struct mem_ehdr *ehdr)
++unsigned long my_r2(const struct mem_ehdr *ehdr)
+ {
+ struct mem_shdr *shdr;
+ shdr = toc_section(ehdr);
+@@ -53,7 +53,7 @@ void machine_apply_elf_rel(struct mem_eh
+ /* Simply set it */
+ *(uint32_t *)location = value;
+ break;
+-
++
+ case R_PPC64_ADDR64:
+ /* Simply set it */
+ *(uint64_t *)location = value;
+@@ -78,15 +78,34 @@ void machine_apply_elf_rel(struct mem_eh
+ /* Convert value to relative */
+ value -= address;
+ if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
+- die("REL24 %li out of range!\n",
++ die("REL24 %li out of range!\n",
+ (long int)value);
+ }
+
+ /* Only replace bits 2 through 26 */
+- *(uint32_t *)location
+- = (*(uint32_t *)location & ~0x03fffffc)
+- | (value & 0x03fffffc);
++ *(uint32_t *)location = (*(uint32_t *)location & ~0x03fffffc)
++ | (value & 0x03fffffc);
++ break;
++
++ case R_PPC64_ADDR16_LO:
++ *(uint16_t *)location = value & 0xffff;
++ break;
++
++ case R_PPC64_ADDR16_HI:
++ *(uint16_t *)location = (value>>16) & 0xffff;
+ break;
++
++ case R_PPC64_ADDR16_HA:
++ *(uint16_t *)location = ((value>>16) & 0xffff);
++ break;
++
++ case R_PPC64_ADDR16_HIGHEST:
++ *(uint16_t *)location = ((value>>48) & 0xffff);
++ break;
++ case R_PPC64_ADDR16_HIGHER:
++ *(uint16_t *)location = ((value>>32) & 0xffff);
++ break;
++
+ default:
+ die("Unknown rela relocation: %lu\n", r_type);
+ break;
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.c 2005-12-14 16:00:37.000000000 +0530
-@@ -0,0 +1,527 @@
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.c 2006-01-19 18:20:07.000000000 +0530
+@@ -0,0 +1,640 @@
+/*
+ * kexec: Linux boots Linux
+ *
@@ -1935,27 +2745,23 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-ppc64.h"
++#include "crashdump-ppc64.h"
+#include
+
-+#define MAX_MEMORY_RANGES 64
-+#define MAX_LINE 160
-+#define MAXBYTES 128
+/* Platforms supported by kexec on PPC64 */
+#define PLATFORM_PSERIES 0x0100
+#define PLATFORM_PSERIES_LPAR 0x0101
+
-+struct exclude_range {
-+ unsigned long long start, end;
-+};
+static struct exclude_range exclude_range[MAX_MEMORY_RANGES];
-+
+static unsigned long long rmo_top;
+static unsigned int platform;
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+static struct memory_range base_memory_range[MAX_MEMORY_RANGES];
+unsigned long long memory_max = 0;
-+static int nr_memory_ranges;
-+static int nr_exclude_ranges;
++static int nr_memory_ranges, nr_exclude_ranges;
++unsigned long long crash_base, crash_size;
++
++static int sort_base_ranges();
+
+/* Get base memory ranges */
+static int get_base_ranges()
@@ -1968,7 +2774,6 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ FILE *file;
+ struct dirent *dentry, *mentry;
+ int n;
-+ unsigned long long start, end;
+
+ if ((dir = opendir(device_tree)) == NULL) {
+ perror(device_tree);
@@ -2010,17 +2815,44 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ ((unsigned long long *)buf)[1];
+ base_memory_range[local_memory_ranges].type = RANGE_RAM;
+ local_memory_ranges++;
-+#if 0
++#ifdef DEBUG
+ fprintf(stderr, "%016Lx-%016Lx : %x\n", memory_range[local_memory_ranges-1].start, memory_range[local_memory_ranges-1].end, memory_range[local_memory_ranges].type);
+#endif
+ fclose(file);
+ }
-+ memory_max = base_memory_range[local_memory_ranges - 1].end;
+ closedir(dmem);
+ }
+ closedir(dir);
+ nr_memory_ranges = local_memory_ranges;
++ sort_base_ranges();
++ memory_max = base_memory_range[nr_memory_ranges - 1].end;
++#ifdef DEBUG
+ fprintf(stderr, "get base memory ranges:%d\n", nr_memory_ranges);
++#endif
++ return 0;
++}
++
++/* Sort the base ranges in memory - this is useful for ensuring that our
++ * ranges are in ascending order, even if device-tree read of memory nodes
++ * is done differently. Also, could be used for other range coalescing later
++ */
++static int sort_base_ranges()
++{
++ int i, j;
++ unsigned long long tstart, tend;
++
++ for (i = 0; i < nr_memory_ranges - 1; i++) {
++ for (j = 0; j < nr_memory_ranges - i - 1; j++) {
++ if (base_memory_range[j].start > base_memory_range[j+1].start) {
++ tstart = base_memory_range[j].start;
++ tend = base_memory_range[j].end;
++ base_memory_range[j].start = base_memory_range[j+1].start;
++ base_memory_range[j].end = base_memory_range[j+1].end;
++ base_memory_range[j+1].start = tstart;
++ base_memory_range[j+1].end = tend;
++ }
++ }
++ }
+ return 0;
+}
+
@@ -2044,12 +2876,17 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ return 0;
+}
+
-+/* Get devtree details and create exclude_range array */
-+static int get_devtree_details()
++/* Get devtree details and create exclude_range array
++ * Also create usablemem_ranges for KEXEC_ON_CRASH
++ */
++static int get_devtree_details(unsigned long kexec_flags)
+{
+ unsigned long long rmo_base;
+ unsigned long long tce_base;
+ unsigned int tce_size;
++ unsigned int rtas_base, rtas_size;
++ unsigned long long htab_base, htab_size;
++ unsigned long long kernel_end;
+ char buf[MAXBYTES-1];
+ char device_tree[256] = "/proc/device-tree/";
+ char fname[256];
@@ -2094,17 +2931,17 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ return -1;
+ }
+ fclose(file);
++
+ memset(fname, 0, sizeof(fname));
+ strcpy(fname, device_tree);
+ strcat(fname, dentry->d_name);
-+ strcat(fname, "/kernel_end");
++ strcat(fname, "/linux,kernel-end");
+ if ((file = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ closedir(cdir);
+ closedir(dir);
+ return -1;
+ }
-+ unsigned long long kernel_end;
+ if (fread(&kernel_end, sizeof(unsigned long), 1, file) != 1) {
+ perror(fname);
+ fclose(file);
@@ -2112,10 +2949,62 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ closedir(dir);
+ return -1;
+ }
++ fclose(file);
++
+ /* Add kernel memory to exclude_range */
+ exclude_range[i].start = 0x0UL;
+ exclude_range[i].end = kernel_end;
+ i++;
++
++ if (kexec_flags & KEXEC_ON_CRASH) {
++ memset(fname, 0, sizeof(fname));
++ strcpy(fname, device_tree);
++ strcat(fname, dentry->d_name);
++ strcat(fname, "/linux,crashkernel-base");
++ if ((file = fopen(fname, "r")) == NULL) {
++ perror(fname);
++ closedir(cdir);
++ closedir(dir);
++ return -1;
++ }
++ if (fread(&crash_base, sizeof(unsigned long), 1,
++ file) != 1) {
++ perror(fname);
++ fclose(file);
++ closedir(cdir);
++ closedir(dir);
++ return -1;
++ }
++ fclose(file);
++
++ memset(fname, 0, sizeof(fname));
++ strcpy(fname, device_tree);
++ strcat(fname, dentry->d_name);
++ strcat(fname, "/linux,crashkernel-size");
++ if ((file = fopen(fname, "r")) == NULL) {
++ perror(fname);
++ closedir(cdir);
++ closedir(dir);
++ return -1;
++ }
++ if (fread(&crash_size, sizeof(unsigned long), 1,
++ file) != 1) {
++ perror(fname);
++ fclose(file);
++ closedir(cdir);
++ closedir(dir);
++ return -1;
++ }
++
++ if (crash_base > mem_min)
++ mem_min = crash_base;
++ if (crash_base + crash_size < mem_max)
++ mem_max = crash_base + crash_size;
++
++ add_usable_mem_rgns(0, crash_base + crash_size);
++ reserve(KDUMP_BACKUP_LIMIT, crash_base-KDUMP_BACKUP_LIMIT);
++ }
++
+ /* if LPAR, no need to read any more from /chosen */
+ if (platform != PLATFORM_PSERIES) {
+ closedir(cdir);
@@ -2124,14 +3013,13 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ memset(fname, 0, sizeof(fname));
+ strcpy(fname, device_tree);
+ strcat(fname, dentry->d_name);
-+ strcat(fname, "/htab_base");
++ strcat(fname, "/linux,htab-base");
+ if ((file = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ closedir(cdir);
+ closedir(dir);
+ return -1;
+ }
-+ unsigned long long htab_base, htab_size;
+ if (fread(&htab_base, sizeof(unsigned long), 1, file) != 1) {
+ perror(fname);
+ fclose(file);
@@ -2142,7 +3030,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ memset(fname, 0, sizeof(fname));
+ strcpy(fname, device_tree);
+ strcat(fname, dentry->d_name);
-+ strcat(fname, "/htab_size");
++ strcat(fname, "/linux,htab-size");
+ if ((file = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ closedir(cdir);
@@ -2170,7 +3058,6 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ closedir(dir);
+ return -1;
+ }
-+ unsigned int rtas_base, rtas_size;
+ if (fread(&rtas_base, sizeof(unsigned int), 1, file) != 1) {
+ perror(fname);
+ fclose(file);
@@ -2200,6 +3087,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ exclude_range[i].start = rtas_base;
+ exclude_range[i].end = rtas_base + rtas_size;
+ i++;
++ if (kexec_flags & KEXEC_ON_CRASH)
++ add_usable_mem_rgns(rtas_base, rtas_size);
+ } /* rtas */
+
+ if (strncmp(dentry->d_name, "memory@0", 8) == 0) {
@@ -2219,8 +3108,10 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ }
+ rmo_base = ((unsigned long long *)buf)[0];
+ rmo_top = rmo_base + ((unsigned long long *)buf)[1];
-+ if (platform == PLATFORM_PSERIES)
-+ if (memory_max > 0x40000000UL? (rmo_top = 0x40000000UL) : (rmo_top = memory_max));
++ if (platform == PLATFORM_PSERIES) {
++ if (rmo_top > 0x30000000UL)
++ rmo_top = 0x30000000UL;
++ }
+ fclose(file);
+ closedir(cdir);
+ } /* memory */
@@ -2265,6 +3156,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ exclude_range[i].start = tce_base;
+ exclude_range[i].end = tce_base + tce_size;
+ i++;
++ if (kexec_flags & KEXEC_ON_CRASH)
++ add_usable_mem_rgns(tce_base, tce_size);
+ closedir(cdir);
+ } /* pci */
+ }
@@ -2273,7 +3166,31 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ nr_exclude_ranges = i;
+
+ sort_ranges();
-+#if 0
++
++ /* add crash_region and remove rtas range from exclude regions if it
++ * lies within crash region
++ */
++ if (kexec_flags & KEXEC_ON_CRASH) {
++ unsigned long new_crash_size;
++ if (crash_base < rtas_base &&
++ ((crash_base + crash_size) > (rtas_base + rtas_size))){
++ new_crash_size = rtas_base - crash_base;
++ add_exclude_rgns(crash_base, new_crash_size);
++ new_crash_size = (crash_base + crash_size) - (rtas_base + rtas_size);
++ add_exclude_rgns(rtas_base + rtas_size, new_crash_size);
++ } else if (crash_base < rtas_base &&
++ ((rtas_base + rtas_size) > (crash_base + crash_size))){
++ new_crash_size = rtas_base - crash_base;
++ add_exclude_rgns(crash_base, new_crash_size);
++ } else if (crash_base > rtas_base &&
++ ((rtas_base + rtas_size) < (crash_base + crash_size))){
++ new_crash_size = (crash_base + crash_size) - (rtas_base + rtas_size);
++ add_exclude_rgns(rtas_base + rtas_size, new_crash_size);
++ } else
++ add_exclude_rgns(crash_base, crash_size);
++ }
++
++#ifdef DEBUG
+ int k;
+ for (k = 0; k < i; k++)
+ fprintf(stderr, "exclude_range sorted exclude_range[%d] start:%lx, end:%lx\n", k, exclude_range[k].start, exclude_range[k].end);
@@ -2282,7 +3199,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+}
+
+/* Setup a sorted list of memory ranges. */
-+int setup_memory_ranges(void)
++int setup_memory_ranges(unsigned long kexec_flags)
+{
+ int i, j = 0;
+
@@ -2291,7 +3208,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ */
+
+ get_base_ranges();
-+ get_devtree_details();
++ get_devtree_details(kexec_flags);
+
+ for (i = 0; i < nr_exclude_ranges; i++) {
+ /* If first exclude range does not start with 0, include the
@@ -2340,25 +3257,27 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ j--;
+ break;
+ }
-+ if ((memory_range[j-1].start < rmo_top) && (memory_range[j-1].end >= rmo_top)) {
++ if ((memory_range[j-1].start < rmo_top) &&
++ (memory_range[j-1].end >= rmo_top)) {
+ memory_range[j-1].end = rmo_top;
+ break;
+ }
+ }
+ nr_memory_ranges = j;
+
-+#if 0
++#ifdef DEBUG
+ int k;
+ for (k = 0; k < j; k++)
-+ fprintf(stderr, "seup_memory_ranges memory_range[%d] start:%lx, end:%lx\n", k, memory_range[k].start, memory_range[k].end);
++ fprintf(stderr, "setup_memory_ranges memory_range[%d] start:%lx, end:%lx\n", k, memory_range[k].start, memory_range[k].end);
+#endif
+ return 0;
+}
+
+/* Return a list of valid memory ranges */
-+int get_memory_ranges(struct memory_range **range, int *ranges)
++int get_memory_ranges(struct memory_range **range, int *ranges,
++ unsigned long kexec_flags)
+{
-+ setup_memory_ranges();
++ setup_memory_ranges(kexec_flags);
+ *range = memory_range;
+ *ranges = nr_memory_ranges;
+ fprintf(stderr, "get memory ranges:%d\n", nr_memory_ranges);
@@ -2373,17 +3292,18 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+void arch_usage(void)
+{
+ fprintf(stderr, " --devicetreeblob= Specify device tree blob file.\n");
++ fprintf(stderr, " --elf64-core-headers Prepare core headers in ELF64 format\n");
+}
+
-+static struct {
-+} arch_options = {
++struct arch_options_t arch_options = {
++ .core_header_type = CORE_TYPE_ELF64,
+};
+
+int arch_process_options(int argc, char **argv)
+{
+ 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;
@@ -2393,6 +3313,9 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ switch(opt) {
+ default:
+ break;
++ case OPT_ELF64_CORE:
++ arch_options.core_header_type = CORE_TYPE_ELF64;
++ break;
+ }
+ }
+ /* Reset getopt for the next pass; called in other source modules */
@@ -2401,7 +3324,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ return 0;
+}
+
-+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
++int arch_compat_trampoline(struct kexec_info *info)
+{
+ int result;
+ struct utsname utsname;
@@ -2416,7 +3339,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+ /* We are running a 32-bit kexec-tools on 64-bit ppc64.
+ * So pass KEXEC_ARCH_PPC64 here
+ */
-+ *flags |= KEXEC_ARCH_PPC64;
++ info->kexec_flags |= KEXEC_ARCH_PPC64;
+ }
+ else {
+ fprintf(stderr, "Unsupported machine type: %s\n",
@@ -2431,14 +3354,26 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.c kexec-to
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.h
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h 2004-12-17 12:14:42.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.h 2005-12-14 15:57:19.000000000 +0530
-@@ -6,4 +6,17 @@ int elf_ppc64_load(int argc, char **argv
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-ppc64.h 2006-01-19 18:20:07.000000000 +0530
+@@ -1,9 +1,44 @@
+ #ifndef KEXEC_PPC64_H
+ #define KEXEC_PPC64_H
+
++#define MAX_MEMORY_RANGES 256 /* TO FIX - needs to be dynamically set */
++#define MAXBYTES 128
++#define MAX_LINE 160
++#define CORE_TYPE_ELF32 1
++#define CORE_TYPE_ELF64 2
++
++int setup_memory_ranges(unsigned long kexec_flags);
++
+ int elf_ppc64_probe(const char *buf, off_t len);
+ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
struct kexec_info *info);
void elf_ppc64_usage(void);
-
--#endif /* KEXEC_PPC_H */
-+unsigned long initrd_base;
-+unsigned long initrd_size;
++void reserve(unsigned long long where, unsigned long long length);
++
++extern unsigned long initrd_base, initrd_size;
+/* boot block version 2 as defined by the linux kernel */
+struct bootblock {
+ unsigned magic,
@@ -2450,11 +3385,39 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h kexec-to
+ last_comp_version,
+ boot_physid;
+};
++
++struct arch_options_t {
++ int core_header_type;
++};
++
++struct exclude_range {
++ unsigned long long start, end;
++};
++
++typedef struct mem_rgns {
++ unsigned int size;
++ struct exclude_range ranges[MAX_MEMORY_RANGES];
++} mem_rgns_t;
+
+-#endif /* KEXEC_PPC_H */
+#endif /* KEXEC_PPC64_H */
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/kexec-zImage-ppc64.c kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-zImage-ppc64.c
+--- kexec-tools-1.101/kexec/arch/ppc64/kexec-zImage-ppc64.c 2004-12-16 17:47:51.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/kexec-zImage-ppc64.c 2006-01-19 18:20:08.000000000 +0530
+@@ -153,7 +153,8 @@ int zImage_ppc64_load(FILE *file, int ar
+ return -1;
+ }
+ mem_offset = p->p_vaddr - load_loc;
+- if (fread(segment->buf+mem_offset, p->p_filesz, 1, file) != 1) {
++ if (fread((void *)segment->buf+mem_offset, p->p_filesz, 1,
++ file) != 1) {
+ perror("read error: ");
+ return -1;
+ }
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/Makefile kexec-tools-1.101-kdump/kexec/arch/ppc64/Makefile
--- kexec-tools-1.101/kexec/arch/ppc64/Makefile 2004-12-17 12:05:30.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/ppc64/Makefile 2005-12-14 15:57:18.000000000 +0530
-@@ -2,6 +2,9 @@
++++ kexec-tools-1.101-kdump/kexec/arch/ppc64/Makefile 2006-01-19 18:20:06.000000000 +0530
+@@ -2,6 +2,10 @@
# kexec ppc64 (linux booting linux)
#
KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-rel-ppc64.c
@@ -2463,11 +3426,12 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/ppc64/Makefile kexec-tools-1
+KEXEC_C_SRCS+= kexec/arch/ppc64/fs2dt.c
+KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-elf-ppc64.c
+KEXEC_C_SRCS+= kexec/arch/ppc64/kexec-ppc64.c
++KEXEC_C_SRCS+= kexec/arch/ppc64/crashdump-ppc64.c
KEXEC_S_SRCS+=
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/include/arch/options.h kexec-tools-1.101-kdump/kexec/arch/s390/include/arch/options.h
--- kexec-tools-1.101/kexec/arch/s390/include/arch/options.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/include/arch/options.h 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/include/arch/options.h 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_S390_OPTIONS_H
+#define KEXEC_ARCH_S390_OPTIONS_H
@@ -2482,7 +3446,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/include/arch/options.h
+#endif /* KEXEC_ARCH_S390_OPTIONS_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-elf-rel-s390.c kexec-tools-1.101-kdump/kexec/arch/s390/kexec-elf-rel-s390.c
--- kexec-tools-1.101/kexec/arch/s390/kexec-elf-rel-s390.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-elf-rel-s390.c 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-elf-rel-s390.c 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,23 @@
+/*
+ * kexec/arch/s390/kexec-elf-rel-s390.c
@@ -2509,7 +3473,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-elf-rel-s390.c ke
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-image.c kexec-tools-1.101-kdump/kexec/arch/s390/kexec-image.c
--- kexec-tools-1.101/kexec/arch/s390/kexec-image.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-image.c 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-image.c 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,137 @@
+/*
+ * kexec/arch/s390/kexec-image.c
@@ -2650,7 +3614,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-image.c kexec-too
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-s390.c kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.c
--- kexec-tools-1.101/kexec/arch/s390/kexec-s390.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.c 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.c 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,104 @@
+/*
+ * kexec/arch/s390/kexec-s390.c
@@ -2758,7 +3722,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-s390.c kexec-tool
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-s390.h kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.h
--- kexec-tools-1.101/kexec/arch/s390/kexec-s390.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.h 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/kexec-s390.h 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,25 @@
+/*
+ * kexec/arch/s390/kexec-s390.h
@@ -2787,7 +3751,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/kexec-s390.h kexec-tool
+#endif /* KEXEC_IA64_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/Makefile kexec-tools-1.101-kdump/kexec/arch/s390/Makefile
--- kexec-tools-1.101/kexec/arch/s390/Makefile 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/s390/Makefile 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/s390/Makefile 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,6 @@
+#
+# kexec s390 (linux booting linux)
@@ -2797,8 +3761,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/s390/Makefile kexec-tools-1.
+KEXEC_C_SRCS+= kexec/arch/s390/kexec-elf-rel-s390.c
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.c
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.c 2005-12-15 16:57:30.415686864 +0530
-@@ -0,0 +1,766 @@
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.c 2006-02-01 14:33:42.949479088 +0530
+@@ -0,0 +1,770 @@
+/*
+ * kexec: Linux boots Linux
+ *
@@ -3343,6 +4307,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c ke
+ mend = crash_memory_range[i].end;
+ if (!mstart && !mend)
+ break;
++ if (crash_memory_range[i].type != RANGE_RAM)
++ break;
+ phdr = (Elf64_Phdr *) bufp;
+ bufp += sizeof(Elf64_Phdr);
+ phdr->p_type = PT_LOAD;
@@ -3448,6 +4414,8 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c ke
+ mend = crash_memory_range[i].end;
+ if (!mstart && !mend)
+ break;
++ if (crash_memory_range[i].type != RANGE_RAM)
++ break;
+ phdr = (Elf32_Phdr *) bufp;
+ bufp += sizeof(Elf32_Phdr);
+ phdr->p_type = PT_LOAD;
@@ -3567,7 +4535,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.c ke
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.h kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.h
--- kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.h 2005-12-14 16:00:44.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/crashdump-x86_64.h 2006-01-19 11:41:40.000000000 +0530
@@ -0,0 +1,24 @@
+#ifndef CRASHDUMP_X86_64_H
+#define CRASHDUMP_X86_64_H
@@ -3595,7 +4563,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/crashdump-x86_64.h ke
+#endif /* CRASHDUMP_X86_64_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/include/arch/options.h kexec-tools-1.101-kdump/kexec/arch/x86_64/include/arch/options.h
--- kexec-tools-1.101/kexec/arch/x86_64/include/arch/options.h 2004-12-22 02:24:02.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/include/arch/options.h 2005-12-14 16:00:44.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/include/arch/options.h 2006-01-19 11:41:40.000000000 +0530
@@ -6,7 +6,9 @@
#define OPT_SERIAL_BAUD (OPT_MAX+2)
#define OPT_CONSOLE_VGA (OPT_MAX+3)
@@ -3618,7 +4586,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/include/arch/options.
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-elf-x86_64.c
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c 2005-01-13 18:40:54.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-elf-x86_64.c 2005-12-14 16:00:58.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-elf-x86_64.c 2006-01-19 11:41:42.000000000 +0530
@@ -32,10 +32,12 @@
#include
#include
@@ -3713,7 +4681,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c ke
elf_rel_get_symbol(&info->rhdr, "entry64_regs", ®s, sizeof(regs));
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-x86_64.c
--- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c 2005-02-06 04:55:01.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-x86_64.c 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/kexec-x86_64.c 2006-01-19 18:19:07.000000000 +0530
@@ -30,14 +30,15 @@
#include "../../kexec-elf.h"
#include "../../kexec-syscall.h"
@@ -3835,7 +4803,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c kexec-
}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/Makefile kexec-tools-1.101-kdump/kexec/arch/x86_64/Makefile
--- kexec-tools-1.101/kexec/arch/x86_64/Makefile 2005-02-06 04:55:19.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/arch/x86_64/Makefile 2005-12-14 16:00:44.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/arch/x86_64/Makefile 2006-01-19 11:41:40.000000000 +0530
@@ -7,6 +7,7 @@ KEXEC_C_SRCS+= kexec/arch/i386/kexec-mul
KEXEC_C_SRCS+= kexec/arch/i386/kexec-beoboot-x86.c
KEXEC_C_SRCS+= kexec/arch/i386/kexec-nbi.c
@@ -3846,7 +4814,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/arch/x86_64/Makefile kexec-tools-
KEXEC_C_SRCS+= kexec/arch/x86_64/kexec-elf-rel-x86_64.c
diff -urNp -X dontdiff kexec-tools-1.101/kexec/crashdump.c kexec-tools-1.101-kdump/kexec/crashdump.c
--- kexec-tools-1.101/kexec/crashdump.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/crashdump.c 2005-12-15 16:56:46.389379880 +0530
++++ kexec-tools-1.101-kdump/kexec/crashdump.c 2006-01-19 18:19:07.000000000 +0530
@@ -0,0 +1,65 @@
+/*
+ * crashdump.c: Architecture independent code for crashdump support.
@@ -3915,7 +4883,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/crashdump.c kexec-tools-1.101-kdu
+}
diff -urNp -X dontdiff kexec-tools-1.101/kexec/crashdump.h kexec-tools-1.101-kdump/kexec/crashdump.h
--- kexec-tools-1.101/kexec/crashdump.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/crashdump.h 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/crashdump.h 2006-01-19 18:19:07.000000000 +0530
@@ -0,0 +1,9 @@
+#ifndef CRASHDUMP_H
+#define CRASHDUMP_H
@@ -3928,7 +4896,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/crashdump.h kexec-tools-1.101-kdu
+#endif /* CRASHDUMP_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec.c kexec-tools-1.101-kdump/kexec/kexec.c
--- kexec-tools-1.101/kexec/kexec.c 2005-01-13 18:54:29.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/kexec.c 2005-12-14 15:57:17.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/kexec.c 2006-02-01 14:41:52.281089376 +0530
@@ -38,8 +38,8 @@
#include "kexec-elf.h"
#include "kexec-sha256.h"
@@ -3940,6 +4908,15 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec.c kexec-tools-1.101-kdump/k
void die(char *fmt, ...)
{
+@@ -187,7 +187,7 @@ unsigned long locate_hole(struct kexec_i
+ }
+
+ /* Compute the free memory ranges */
+- max_mem_ranges = memory_ranges + (info->nr_segments -1);
++ max_mem_ranges = memory_ranges + info->nr_segments;
+ mem_range = malloc(max_mem_ranges *sizeof(struct memory_range));
+ mem_ranges = 0;
+
@@ -323,12 +323,17 @@ unsigned long add_buffer(struct kexec_in
{
unsigned long base;
@@ -4007,9 +4984,385 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec.c kexec-tools-1.101-kdump/k
print_segments(stderr, &info);
}
return result;
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec-elf.c kexec-tools-1.101-kdump/kexec/kexec-elf.c
+--- kexec-tools-1.101/kexec/kexec-elf.c 2004-12-20 14:58:30.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/kexec-elf.c 2006-01-19 18:20:08.000000000 +0530
+@@ -113,21 +113,21 @@ static int build_mem_elf32_ehdr(const ch
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_entry) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_entry) > UINT32_MAX) {
+ /* entry is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_entry to large\n");
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_phoff) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_phoff) > UINT32_MAX) {
+ /* phoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_phoff to large\n");
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_shoff) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_shoff) > UINT32_MAX) {
+ /* shoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_shoff to large\n");
+@@ -146,7 +146,7 @@ static int build_mem_elf32_ehdr(const ch
+ ehdr->e_shstrndx = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+ if ((ehdr->e_phnum > 0) &&
+- (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf32_Phdr)))
++ (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf32_Phdr)))
+ {
+ /* Invalid program header size */
+ if (probe_debug) {
+@@ -185,21 +185,21 @@ static int build_mem_elf64_ehdr(const ch
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_entry) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_entry) > UINT32_MAX) {
+ /* entry is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_entry to large\n");
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_phoff) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_phoff) > UINT32_MAX) {
+ /* phoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_phoff to large\n");
+ }
+ return -1;
+ }
+- if (elf32_to_cpu(ehdr, lehdr.e_shoff) > ULONG_MAX) {
++ if (elf32_to_cpu(ehdr, lehdr.e_shoff) > UINT32_MAX) {
+ /* shoff is to large */
+ if (probe_debug) {
+ fprintf(stderr, "ELF e_shoff to large\n");
+@@ -218,7 +218,7 @@ static int build_mem_elf64_ehdr(const ch
+ ehdr->e_shstrndx = elf16_to_cpu(ehdr, lehdr.e_shstrndx);
+
+ if ((ehdr->e_phnum > 0) &&
+- (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf64_Phdr)))
++ (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf64_Phdr)))
+ {
+ /* Invalid program header size */
+ if (probe_debug) {
+@@ -302,7 +302,7 @@ static int build_mem_ehdr(const char *bu
+ return 0;
+ }
+
+-static int build_mem_elf32_phdr(const char *buf, off_t len,
++static int build_mem_elf32_phdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+ {
+ struct mem_phdr *phdr;
+@@ -312,12 +312,12 @@ static int build_mem_elf32_phdr(const ch
+ phdr = &ehdr->e_phdr[idx];
+ memcpy(&lphdr, pbuf, sizeof(lphdr));
+
+- if ( (elf32_to_cpu(ehdr, lphdr.p_filesz) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lphdr.p_memsz) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lphdr.p_offset) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lphdr.p_paddr) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lphdr.p_vaddr) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lphdr.p_align) > ULONG_MAX))
++ if ( (elf32_to_cpu(ehdr, lphdr.p_filesz) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lphdr.p_memsz) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lphdr.p_offset) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lphdr.p_paddr) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lphdr.p_vaddr) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lphdr.p_align) > UINT32_MAX))
+ {
+ fprintf(stderr, "Program segment size out of range\n");
+ return -1;
+@@ -345,12 +345,12 @@ static int build_mem_elf64_phdr(const ch
+ phdr = &ehdr->e_phdr[idx];
+ memcpy(&lphdr, pbuf, sizeof(lphdr));
+
+- if ( (elf64_to_cpu(ehdr, lphdr.p_filesz) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lphdr.p_memsz) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lphdr.p_offset) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lphdr.p_paddr) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lphdr.p_vaddr) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lphdr.p_align) > ULONG_MAX))
++ if ( (elf64_to_cpu(ehdr, lphdr.p_filesz) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lphdr.p_memsz) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lphdr.p_offset) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lphdr.p_paddr) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lphdr.p_vaddr) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lphdr.p_align) > UINT64_MAX))
+ {
+ fprintf(stderr, "Program segment size out of range\n");
+ return -1;
+@@ -388,7 +388,7 @@ static int build_mem_phdrs(const char *b
+ fprintf(stderr, "Invalid ei_class?\n");
+ return -1;
+ }
+- phdr_size *= ehdr->e_phnum;
++ phdr_size *= ehdr->e_phnum;
+ if (ehdr->e_phoff + phdr_size > len) {
+ /* The program header did not fit in the file buffer */
+ if (probe_debug) {
+@@ -396,7 +396,7 @@ static int build_mem_phdrs(const char *b
+ }
+ return -1;
+ }
+-
++
+ /* Allocate the e_phdr array */
+ mem_phdr_size = sizeof(ehdr->e_phdr[0]) * ehdr->e_phnum;
+ ehdr->e_phdr = xmalloc(mem_phdr_size);
+@@ -440,7 +440,7 @@ static int build_mem_phdrs(const char *b
+ return 0;
+ }
+
+-static int build_mem_elf32_shdr(const char *buf, off_t len,
++static int build_mem_elf32_shdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+ {
+ struct mem_shdr *shdr;
+@@ -451,12 +451,12 @@ static int build_mem_elf32_shdr(const ch
+ shdr = &ehdr->e_shdr[idx];
+ memcpy(&lshdr, sbuf, sizeof(lshdr));
+
+- if ( (elf32_to_cpu(ehdr, lshdr.sh_flags) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lshdr.sh_addr) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lshdr.sh_offset) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lshdr.sh_size) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lshdr.sh_addralign) > ULONG_MAX) ||
+- (elf32_to_cpu(ehdr, lshdr.sh_entsize) > ULONG_MAX))
++ if ( (elf32_to_cpu(ehdr, lshdr.sh_flags) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lshdr.sh_addr) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lshdr.sh_offset) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lshdr.sh_size) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lshdr.sh_addralign) > UINT32_MAX) ||
++ (elf32_to_cpu(ehdr, lshdr.sh_entsize) > UINT32_MAX))
+ {
+ fprintf(stderr, "Program section size out of range\n");
+ return -1;
+@@ -510,7 +510,7 @@ static int build_mem_elf32_shdr(const ch
+ return 0;
+ }
+
+-static int build_mem_elf64_shdr(const char *buf, off_t len,
++static int build_mem_elf64_shdr(const char *buf, off_t len,
+ struct mem_ehdr *ehdr, int idx)
+ {
+ struct mem_shdr *shdr;
+@@ -521,12 +521,12 @@ static int build_mem_elf64_shdr(const ch
+ shdr = &ehdr->e_shdr[idx];
+ memcpy(&lshdr, sbuf, sizeof(lshdr));
+
+- if ( (elf64_to_cpu(ehdr, lshdr.sh_flags) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lshdr.sh_addr) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lshdr.sh_offset) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lshdr.sh_size) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lshdr.sh_addralign) > ULONG_MAX) ||
+- (elf64_to_cpu(ehdr, lshdr.sh_entsize) > ULONG_MAX))
++ if ( (elf64_to_cpu(ehdr, lshdr.sh_flags) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lshdr.sh_addr) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lshdr.sh_offset) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lshdr.sh_size) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lshdr.sh_addralign) > UINT64_MAX) ||
++ (elf64_to_cpu(ehdr, lshdr.sh_entsize) > UINT64_MAX))
+ {
+ fprintf(stderr, "Program section size out of range\n");
+ return -1;
+@@ -608,7 +608,7 @@ static int build_mem_shdrs(const char *b
+ }
+ return -1;
+ }
+-
++
+ /* Allocate the e_shdr array */
+ mem_shdr_size = sizeof(ehdr->e_shdr[0]) * ehdr->e_shnum;
+ ehdr->e_shdr = xmalloc(mem_shdr_size);
+@@ -635,7 +635,7 @@ static int build_mem_shdrs(const char *b
+ {
+ /* The section does not fit in the buffer */
+ if (probe_debug) {
+- fprintf(stderr, "ELF section %d not in file\n",
++ fprintf(stderr, "ELF section %d not in file\n",
+ i);
+ }
+ return -1;
+@@ -653,14 +653,14 @@ static int build_mem_shdrs(const char *b
+ return 0;
+ }
+
+-static void read_nhdr(const struct mem_ehdr *ehdr,
++static void read_nhdr(const struct mem_ehdr *ehdr,
+ ElfNN_Nhdr *hdr, const unsigned char *note)
+ {
+ memcpy(hdr, note, sizeof(*hdr));
+ hdr->n_namesz = elf32_to_cpu(ehdr, hdr->n_namesz);
+ hdr->n_descsz = elf32_to_cpu(ehdr, hdr->n_descsz);
+ hdr->n_type = elf32_to_cpu(ehdr, hdr->n_type);
+-
++
+ }
+ static int build_mem_notes(const char *buf, off_t len, struct mem_ehdr *ehdr)
+ {
+@@ -686,7 +686,7 @@ static int build_mem_notes(const char *b
+ if (!note_start) {
+ return 0;
+ }
+-
++
+ /* Walk through and count the notes */
+ ehdr->e_notenum = 0;
+ for(note = note_start; note < note_end; note+= note_size) {
+@@ -708,7 +708,7 @@ static int build_mem_notes(const char *b
+ note_size += (hdr.n_namesz + 3) & ~3;
+ desc = note + note_size;
+ 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");
+ }
+@@ -716,7 +716,7 @@ static int build_mem_notes(const char *b
+ ehdr->e_note[i].n_name = name;
+ ehdr->e_note[i].n_desc = desc;
+ ehdr->e_note[i].n_descsz = hdr.n_descsz;
+-
++
+ }
+ return 0;
+ }
+diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec-elf-rel.c kexec-tools-1.101-kdump/kexec/kexec-elf-rel.c
+--- kexec-tools-1.101/kexec/kexec-elf-rel.c 2005-01-13 18:34:21.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/kexec-elf-rel.c 2006-02-01 16:41:33.288410328 +0530
+@@ -155,7 +155,7 @@ int build_elf_rel_info(const char *buf,
+ if (probe_debug) {
+ fprintf(stderr, "No ELF section headers\n");
+ }
+- return -1;
++ return -1;
+ }
+ if (!machine_verify_elf_rel(ehdr)) {
+ /* It does not meant the native architecture constraints */
+@@ -251,7 +251,7 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+
+ /* Allocate where we will put the relocated object */
+ buf = xmalloc(bufsz);
+- buf_addr = add_buffer(info, buf, bufsz, bufsz + bss_pad + bsssz,
++ buf_addr = add_buffer(info, buf, bufsz, bufsz + bss_pad + bsssz,
+ buf_align, min, max, end);
+ ehdr->rel_addr = buf_addr;
+ ehdr->rel_size = bufsz + bss_pad + bsssz;
+@@ -269,7 +269,7 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+ unsigned long off;
+ /* Adjust the address */
+ data_addr = (data_addr + (align - 1)) & ~(align -1);
+-
++
+ /* Update the section */
+ off = data_addr - buf_addr;
+ memcpy(buf + off, shdr->sh_data, shdr->sh_size);
+@@ -306,7 +306,7 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+ continue;
+ }
+ if ((shdr->sh_info > ehdr->e_shnum) ||
+- (shdr->sh_link > ehdr->e_shnum))
++ (shdr->sh_link > ehdr->e_shnum))
+ {
+ die("Invalid section number\n");
+ }
+@@ -350,12 +350,12 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+
+ /* The final address of that location */
+ address = section->sh_addr + rel.r_offset;
+-
++
+ /* The relevant symbol */
+ sym = elf_sym(ehdr, symtab->sh_data + (rel.r_sym * elf_sym_size(ehdr)));
+-#if 0
++#ifdef DEBUG
+ fprintf(stderr, "sym: %10s info: %02x other: %02x shndx: %lx value: %lx size: %lx\n",
+- strtab + sym.st_name,
++ strtab + sym.st_name,
+ sym.st_info,
+ sym.st_other,
+ sym.st_shndx,
+@@ -364,8 +364,19 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+
+ #endif
+ if (sym.st_shndx == STN_UNDEF) {
+- die("Undefined symbol: %s\n",
++ /*
++ * NOTE: ppc64 elf .ro shows up a UNDEF section.
++ * From Elf 1.2 Spec:
++ * Relocation Entries: If the index is STN_UNDEF,
++ * the undefined symbol index, the relocation uses 0
++ * as the "symbol value".
++ * So, is this really an error condition to flag die?
++ */
++ /*
++ die("Undefined symbol: %s\n",
+ strtab + sym.st_name);
++ */
++ continue;
+ }
+ sec_base = 0;
+ if (sym.st_shndx == SHN_COMMON) {
+@@ -383,14 +394,14 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+ else {
+ sec_base = ehdr->e_shdr[sym.st_shndx].sh_addr;
+ }
+-#if 0
++#ifdef DEBUG
+ fprintf(stderr, "sym: %s value: %lx addr: %lx\n",
+ strtab + sym.st_name, value, address);
+ #endif
+ value = sym.st_value;
+ value += sec_base;
+ value += rel.r_addend;
+- machine_apply_elf_rel(ehdr, rel.r_type,
++ machine_apply_elf_rel(ehdr, rel.r_type,
+ (void *)location, address, value);
+ }
+ }
+@@ -399,7 +410,7 @@ int elf_rel_load(struct mem_ehdr *ehdr,
+ return result;
+ }
+
+-void elf_rel_build_load(struct kexec_info *info, struct mem_ehdr *ehdr,
++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)
+ {
+@@ -452,8 +463,8 @@ int elf_rel_find_symbol(struct mem_ehdr
+ if (strcmp(strtab + sym.st_name, name) != 0) {
+ continue;
+ }
+- if ((sym.st_shndx == STN_UNDEF) ||
+- (sym.st_shndx > ehdr->e_shnum))
++ if ((sym.st_shndx == STN_UNDEF) ||
++ (sym.st_shndx > ehdr->e_shnum))
+ {
+ die("Symbol: %s has Bad section index %d\n",
+ name, sym.st_shndx);
+@@ -491,7 +502,7 @@ void elf_rel_set_symbol(struct mem_ehdr
+
+ result = elf_rel_find_symbol(ehdr, name, &sym);
+ if (result < 0) {
+- die("Symbol: %s not found cannot set\n",
++ die("Symbol: %s not found cannot set\n",
+ name);
+ }
+ if (sym.st_size != size) {
diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec.h kexec-tools-1.101-kdump/kexec/kexec.h
--- kexec-tools-1.101/kexec/kexec.h 2005-01-13 18:33:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/kexec.h 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/kexec.h 2006-01-19 18:19:07.000000000 +0530
@@ -91,6 +91,8 @@ do { \
} while(0)
#endif
@@ -4046,7 +5399,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec.h kexec-tools-1.101-kdump/k
#endif /* KEXEC_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec-syscall.h kexec-tools-1.101-kdump/kexec/kexec-syscall.h
--- kexec-tools-1.101/kexec/kexec-syscall.h 2005-01-06 12:29:50.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/kexec-syscall.h 2005-12-15 11:09:09.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/kexec-syscall.h 2006-01-19 11:41:43.000000000 +0530
@@ -37,6 +37,12 @@
#ifdef __x86_64__
#define __NR_kexec_load 246
@@ -4072,7 +5425,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/kexec-syscall.h kexec-tools-1.101
#endif /* KEXEC_SYSCALL_H */
diff -urNp -X dontdiff kexec-tools-1.101/kexec/Makefile kexec-tools-1.101-kdump/kexec/Makefile
--- kexec-tools-1.101/kexec/Makefile 2004-12-22 01:06:39.000000000 +0530
-+++ kexec-tools-1.101-kdump/kexec/Makefile 2005-12-15 11:55:22.000000000 +0530
++++ kexec-tools-1.101-kdump/kexec/Makefile 2006-01-19 18:19:07.000000000 +0530
@@ -15,6 +15,7 @@ KEXEC_C_SRCS+= kexec/kexec-elf.c
KEXEC_C_SRCS+= kexec/kexec-elf-exec.c
KEXEC_C_SRCS+= kexec/kexec-elf-rel.c
@@ -4083,7 +5436,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/kexec/Makefile kexec-tools-1.101-kdump/
include kexec/arch/$(ARCH)/Makefile
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/crashdump_backup.c kexec-tools-1.101-kdump/purgatory/arch/i386/crashdump_backup.c
--- kexec-tools-1.101/purgatory/arch/i386/crashdump_backup.c 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/i386/crashdump_backup.c 2005-12-14 16:00:56.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/i386/crashdump_backup.c 2006-01-19 11:41:41.000000000 +0530
@@ -0,0 +1,46 @@
+/*
+ * kexec: Linux boots Linux
@@ -4133,7 +5486,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/crashdump_backup.c
+}
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/Makefile kexec-tools-1.101-kdump/purgatory/arch/i386/Makefile
--- kexec-tools-1.101/purgatory/arch/i386/Makefile 2005-01-11 06:37:58.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/i386/Makefile 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/i386/Makefile 2006-01-19 11:41:27.000000000 +0530
@@ -12,3 +12,4 @@ PURGATORY_C_SRCS+= purgatory/arch/i386/p
PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
@@ -4141,7 +5494,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/Makefile kexec-tool
+PURGATORY_C_SRCS+= purgatory/arch/i386/crashdump_backup.c
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.c kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.c
--- kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.c 2004-12-21 21:59:48.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.c 2006-01-19 11:41:27.000000000 +0530
@@ -30,6 +30,7 @@ void x86_setup_cpu(void)
uint8_t reset_vga = 0;
uint8_t legacy_timer = 0;
@@ -4162,7 +5515,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.c kex
+}
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.h kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.h
--- kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.h 2004-12-20 17:52:26.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.h 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/i386/purgatory-x86.h 2006-01-19 11:41:27.000000000 +0530
@@ -4,5 +4,6 @@
void x86_reset_vga(void);
void x86_setup_legacy_pic(void);
@@ -4172,7 +5525,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.h kex
#endif /* PURGATORY_X86_H */
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c 2004-12-21 04:15:21.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ia64/purgatory-ia64.c 2006-01-19 11:41:27.000000000 +0530
@@ -5,3 +5,9 @@ void setup_arch(void)
{
/* Nothing for now */
@@ -4185,7 +5538,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c ke
+}
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc/purgatory-ppc.c kexec-tools-1.101-kdump/purgatory/arch/ppc/purgatory-ppc.c
--- kexec-tools-1.101/purgatory/arch/ppc/purgatory-ppc.c 2004-12-21 04:17:43.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/ppc/purgatory-ppc.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc/purgatory-ppc.c 2006-01-19 11:41:27.000000000 +0530
@@ -5,3 +5,9 @@ void setup_arch(void)
{
/* Nothing for now */
@@ -4196,24 +5549,160 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc/purgatory-ppc.c kexe
+{
+ /* Nothing for now */
+}
+diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/console-ppc64.c kexec-tools-1.101-kdump/purgatory/arch/ppc64/console-ppc64.c
+--- kexec-tools-1.101/purgatory/arch/ppc64/console-ppc64.c 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/console-ppc64.c 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,27 @@
++/*
++ * kexec: Linux boots Linux
++ *
++ * Created by: Mohan Kumar M (mohan@in.ibm.com)
++ *
++ * Copyright (C) IBM Corporation, 2005. All rights reserved
++ *
++ * 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
++
++void putchar(int c)
++{
++ return;
++}
+diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/crashdump_backup.c kexec-tools-1.101-kdump/purgatory/arch/ppc64/crashdump_backup.c
+--- kexec-tools-1.101/purgatory/arch/ppc64/crashdump_backup.c 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/crashdump_backup.c 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,41 @@
++/*
++ * kexec: Linux boots Linux
++ *
++ * Created by: Mohan Kumar M (mohan@in.ibm.com)
++ *
++ * Copyright (C) IBM Corporation, 2005. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation (version 2 of the License).
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include
++#include
++
++#define BACKUP_REGION_SOURCE 0x0
++#define BACKUP_REGION_SIZE 32*1024
++
++extern unsigned long backup_start;
++
++/* Backup first 32KB of memory to backup region reserved by kexec */
++void crashdump_backup_memory(void)
++{
++ void *dest, *src;
++
++ src = (void *)BACKUP_REGION_SOURCE;
++
++ if (backup_start) {
++ dest = (void *)(backup_start);
++ memcpy(dest, src, BACKUP_REGION_SIZE);
++ }
++}
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/Makefile kexec-tools-1.101-kdump/purgatory/arch/ppc64/Makefile
--- kexec-tools-1.101/purgatory/arch/ppc64/Makefile 2004-12-17 11:00:20.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/Makefile 2005-12-14 15:57:19.000000000 +0530
-@@ -3,5 +3,5 @@
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/Makefile 2006-01-19 18:20:08.000000000 +0530
+@@ -2,6 +2,7 @@
+ # Purgatory ppc
#
- PURGATORY_C_SRCS+=
+-PURGATORY_C_SRCS+=
-PURGATORY_S_SRCS+=
+-
+PURGATORY_S_SRCS+= purgatory/arch/ppc64/v2wrap.S
-
++PURGATORY_C_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c
++PURGATORY_C_SRCS += purgatory/arch/ppc64/console-ppc64.c
++PURGATORY_C_SRCS += purgatory/arch/ppc64/crashdump_backup.c
+diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/purgatory-ppc64.c kexec-tools-1.101-kdump/purgatory/arch/ppc64/purgatory-ppc64.c
+--- kexec-tools-1.101/purgatory/arch/ppc64/purgatory-ppc64.c 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/purgatory-ppc64.c 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,41 @@
++/*
++ * kexec: Linux boots Linux
++ *
++ * Created by: Mohan Kumar M (mohan@in.ibm.com)
++ *
++ * Copyright (C) IBM Corporation, 2005. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation (version 2 of the License).
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include
++#include "purgatory-ppc64.h"
++
++unsigned int panic_kernel = 0;
++unsigned long backup_start = 0;
++unsigned long stack = 0;
++unsigned long dt_offset = 0;
++unsigned long my_toc = 0;
++unsigned long kernel = 0;
++
++void setup_arch(void)
++{
++ return;
++}
++
++void post_verification_setup_arch(void)
++{
++ if (panic_kernel)
++ crashdump_backup_memory();
++}
+diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/purgatory-ppc64.h kexec-tools-1.101-kdump/purgatory/arch/ppc64/purgatory-ppc64.h
+--- kexec-tools-1.101/purgatory/arch/ppc64/purgatory-ppc64.h 1970-01-01 05:30:00.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/purgatory-ppc64.h 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,6 @@
++#ifndef PURGATORY_PPC64_H
++#define PURGATORY_PPC64_H
++
++void crashdump_backup_memory(void);
++
++#endif /* PURGATORY_PPC64_H */
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S kexec-tools-1.101-kdump/purgatory/arch/ppc64/v2wrap.S
--- kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/v2wrap.S 2005-12-14 15:57:19.000000000 +0530
-@@ -0,0 +1,114 @@
++++ kexec-tools-1.101-kdump/purgatory/arch/ppc64/v2wrap.S 2006-01-19 18:20:08.000000000 +0530
+@@ -0,0 +1,128 @@
+#
+# kexec: Linux boots Linux
+#
+# Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
++# Copyright (C) 2006, Mohan Kumar M (mohan@in.ibm.com), IBM Corporation
+#
+# 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
@@ -4230,14 +5719,17 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S kexec-too
+#
+
+# v2wrap.S
-+# a wrapper to place in front of a v2 device tree
-+# to call a ppc64 kernel with the expected arguments
++# a wrapper to call purgatory code to backup first
++# 32kB of first kernel into the backup region
++# reserved by kexec-tools.
++# Invokes ppc64 kernel with the expected arguments
+# of kernel(device-tree, phys-offset, 0)
++
+#
+# calling convention:
+# r3 = physical number of this cpu (all cpus)
+# r4 = address of this chunk (master only)
-+# master enters at start (aka first byte of this chunk)
++# master enters at purgatory_start (aka first byte of this chunk)
+# slaves (additional cpus), if any, enter a copy of the
+# first 0x100 bytes of this code relocated to 0x0
+#
@@ -4246,50 +5738,50 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S kexec-too
+# and the slaves are sent to address 0x60
+# with r3 = their physical cpu number.
+
++#define LOADADDR(rn,name) \
++ lis rn,name##@highest; \
++ ori rn,rn,name##@higher; \
++ rldicr rn,rn,32,31; \
++ oris rn,rn,name##@h; \
++ ori rn,rn,name##@l
+
+# look a bit like a Linux kernel here ...
+ .machine ppc64
-+ .org 0
-+start: b master
++ .globl purgatory_start
++purgatory_start: b master
+ tweq 0,0
-+secondary_hold:
-+ .llong 0
-+
-+ .org 0x20 # need a bit more space than after slave,
+master:
-+ std 4,secondary_hold@l(0) # bring slaves up here to this copy
-+ sync # try to get the slaves to see this
+ or 1,1,1 # low priority to let other thread catchup
+ isync
-+ mr 5,3 # save cpu id to r5
-+ addi 3,4,0x100 # r3 = boot param block
-+ lwz 6,20(3) # fetch version number
-+ cmpwi 0,6,2 # v2 ?
-+ blt 80f
-+ stw 5,28(3) # save my cpu number as boot_cpu_phys
-+80: b 81f
++ mr 17,3 # save cpu id to r17
++ mr 15,4 # save physical address in reg15
+
-+ .org 0x60 # ABI: slaves start at 60 with r3=phys
-+slave: ld 4,secondary_hold@l(0);
-+ cmpdi 0,4,0
-+ beq slave
++ LOADADDR(6,my_toc)
++ ld 2,0(6) #setup toc
+
-+ # ahh, master told us where he is running from
-+ # jump into our copy of the code up there so this code can change
-+ addi 5,4,1f-start
-+ mtctr 5
++ LOADADDR(6,stack)
++ ld 1,0(6) #setup stack
++
++ subi 1,1,112
++ bl .purgatory
++ nop
++
++ b 81f
++ .org purgatory_start + 0x60 # ABI: slaves start at 60 with r3=phys
++slave:
++ # load slave spin code address and branch into that
++ LOADADDR(6,slave_spin)
++ ld 4,0(6)
++ mtctr 4
+ bctr
+
-+ # ok, now wait for the master to tell is to go back to the new block
-+1: ld 5,copied@l(4)
-+ cmpdi 0,5,0
-+ beq 1b
-+ ba 0x60
-+
-+
-+
-+ .long 0 # just an eye-catcher, delete if space needed
-+ .long 0 # just an eye-catcher, delete if space needed
++spin: .long 1
++slave_spin_code:
++ lis 5,spin@ha
++ lwz 5,spin@l(5)
++ cmpwi 0,5,0
++ bne slave_spin_code
++ ba 0x60
+
+81: # master continues here
+ or 3,3,3 # ok back to high, lets boot
@@ -4297,7 +5789,17 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S kexec-too
+ mtctr 6 # delay a bit for slaves to catch up
+83: bdnz 83b # before we overwrite 0-100 again
+
-+ ld 4,-8(3) # kernel pointer is at -8(bb) by loader
++ LOADADDR(16, dt_offset)
++ ld 3,0(16) # load device-tree address
++ mr 16,3 # save dt address in reg16
++ lwz 6,20(3) # fetch version number
++ cmpwi 0,6,2 # v2 ?
++ blt 80f
++ stw 17,28(3) # save my cpu number as boot_cpu_phys
++80:
++ LOADADDR(6,kernel)
++ ld 4,0(6) # load the kernel address
++
+ addi 5,4,-8 # prepare copy with update form instructions
+ li 6,0x100/8
+ mtctr 6
@@ -4315,18 +5817,18 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S kexec-too
+ icbi 0,6
+ sync
+ isync
-+ std 6,-16(3) # send slaves back down
++ lis 6,spin@ha
++ li 0,0
++ stw 0,spin@l(6)
++ mr 3,16 # restore dt address
++
+ bctr # start kernel
+
-+ .org 0xf0
-+copied: .llong 0
-+kernel: .llong 0
-+ .org 0x100
-+__end_stub:
-+ .equ boot_block, . - start
++slave_spin: .llong slave_spin_code
++
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/include/limits.h kexec-tools-1.101-kdump/purgatory/arch/s390/include/limits.h
--- kexec-tools-1.101/purgatory/arch/s390/include/limits.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/s390/include/limits.h 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/s390/include/limits.h 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,54 @@
+#ifndef _LIMITS_H_
+#define _LIMITS_H_
@@ -4384,7 +5886,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/include/limits.h ke
+#endif /* !_LIMITS_H_ */
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/include/stdint.h kexec-tools-1.101-kdump/purgatory/arch/s390/include/stdint.h
--- kexec-tools-1.101/purgatory/arch/s390/include/stdint.h 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/s390/include/stdint.h 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/s390/include/stdint.h 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,24 @@
+#ifndef _STDINT_H
+#define _STDINT_H
@@ -4412,7 +5914,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/include/stdint.h ke
+#endif
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/Makefile kexec-tools-1.101-kdump/purgatory/arch/s390/Makefile
--- kexec-tools-1.101/purgatory/arch/s390/Makefile 1970-01-01 05:30:00.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/s390/Makefile 2005-12-14 16:00:40.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/s390/Makefile 2006-01-19 11:41:37.000000000 +0530
@@ -0,0 +1,7 @@
+#
+# Purgatory s390
@@ -4423,7 +5925,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/s390/Makefile kexec-tool
+
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/x86_64/Makefile kexec-tools-1.101-kdump/purgatory/arch/x86_64/Makefile
--- kexec-tools-1.101/purgatory/arch/x86_64/Makefile 2004-12-21 12:43:53.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/x86_64/Makefile 2005-12-14 16:00:56.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/x86_64/Makefile 2006-01-19 11:41:41.000000000 +0530
@@ -9,6 +9,7 @@ PURGATORY_S_SRCS+= purgatory/arch/x86_64
PURGATORY_S_SRCS+= purgatory/arch/x86_64/setup-x86_64.S
PURGATORY_S_SRCS+= purgatory/arch/x86_64/stack.S
@@ -4434,7 +5936,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/x86_64/Makefile kexec-to
PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/x86_64/purgatory-x86_64.c kexec-tools-1.101-kdump/purgatory/arch/x86_64/purgatory-x86_64.c
--- kexec-tools-1.101/purgatory/arch/x86_64/purgatory-x86_64.c 2004-12-21 22:07:41.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/arch/x86_64/purgatory-x86_64.c 2005-12-14 16:00:56.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/arch/x86_64/purgatory-x86_64.c 2006-01-19 11:41:41.000000000 +0530
@@ -4,9 +4,16 @@
uint8_t reset_vga = 0;
@@ -4454,7 +5956,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/arch/x86_64/purgatory-x86_64.
+}
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/include/purgatory.h kexec-tools-1.101-kdump/purgatory/include/purgatory.h
--- kexec-tools-1.101/purgatory/include/purgatory.h 2004-12-18 18:42:15.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/include/purgatory.h 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/include/purgatory.h 2006-01-19 11:41:27.000000000 +0530
@@ -4,5 +4,6 @@
void putchar(int ch);
void printf(const char *fmt, ...);
@@ -4464,7 +5966,7 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/include/purgatory.h kexec-too
#endif /* PURGATORY_H */
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/Makefile kexec-tools-1.101-kdump/purgatory/Makefile
--- kexec-tools-1.101/purgatory/Makefile 2005-01-09 04:06:32.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/Makefile 2005-12-14 15:57:19.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/Makefile 2006-01-19 18:20:08.000000000 +0530
@@ -6,6 +6,11 @@
# There is probably a cleaner way to do this but for now this
# should keep us from accidentially include unsafe library functions
@@ -4477,34 +5979,23 @@ diff -urNp -X dontdiff kexec-tools-1.101/purgatory/Makefile kexec-tools-1.101-kd
PCFLAGS:=-Wall -Os \
-I$(shell $(CC) -print-file-name=include) \
-Ipurgatory/include -Ipurgatory/arch/$(ARCH)/include \
-@@ -17,9 +22,11 @@ PCFLAGS += $(call cc-option, -fnostdinc)
+@@ -16,11 +21,11 @@ PCFLAGS += $(call cc-option, -fnobuiltin
+ PCFLAGS += $(call cc-option, -fnostdinc)
PCFLAGS += $(call cc-option, -fno-zero-initialized-in-bss)
- PURGATORY_C_SRCS:=
-+ifneq ($(ARCH),ppc64)
+-PURGATORY_C_SRCS:=
++PURGATORY_C_SRCS:=
PURGATORY_C_SRCS += purgatory/purgatory.c
PURGATORY_C_SRCS += purgatory/printf.c
PURGATORY_C_SRCS += purgatory/string.c
-+endif
- PURGATORY_S_OBJS:=
+-PURGATORY_S_OBJS:=
++PURGATORY_S_OBJS:=
include purgatory/arch/$(ARCH)/Makefile
-@@ -54,7 +61,12 @@ $(PURGATORY_S_OBJS): $(OBJDIR)/%.o: %.S
- $(PURGATORY): $(PURGATORY_OBJS) $(UTIL_LIB)
- $(MKDIR) -p $(@D)
-+ifneq ($(ARCH),ppc64)
- $(LD) $(LDFLAGS) --no-undefined -e purgatory_start -r -o $@ $(PURGATORY_OBJS) $(UTIL_LIB)
-+else
-+ $(LD) -Ttext=0 -e 0 -o $(OBJDIR)/purgatory/v2wrap.elf $(PURGATORY_OBJS)
-+ objcopy -O binary $(OBJDIR)/purgatory/v2wrap.elf $@
-+endif
-
- echo::
- @echo "PURGATORY_C_SRCS $(PURGATORY_C_SRCS)"
diff -urNp -X dontdiff kexec-tools-1.101/purgatory/purgatory.c kexec-tools-1.101-kdump/purgatory/purgatory.c
--- kexec-tools-1.101/purgatory/purgatory.c 2004-12-22 00:21:03.000000000 +0530
-+++ kexec-tools-1.101-kdump/purgatory/purgatory.c 2005-12-14 15:57:15.000000000 +0530
++++ kexec-tools-1.101-kdump/purgatory/purgatory.c 2006-01-19 11:41:27.000000000 +0530
@@ -44,4 +44,5 @@ void purgatory(void)
printf("I'm in purgatory\n");
setup_arch();
diff --git a/kexec-tools.spec b/kexec-tools.spec
index 566b433..ee198c9 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -1,6 +1,6 @@
Name: kexec-tools
Version: 1.101
-Release: 6
+Release: 7
License: GPL
Group: Applications/System
Summary: The kexec/kdump userspace component.
@@ -10,13 +10,6 @@ Source1: kdump.init
Source2: kdump.sysconfig
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
-%define kdump 0
-
-%ifarch %{ix86}
-%define kdump 1
-%endif
-
-
#
# Patches 0 through 100 are meant for x86 kexec-tools enablement
#
@@ -48,10 +41,8 @@ rm -f ../kexec-tools-1.101.spec
%patch1 -p1
%patch101 -p1
-%if %{kdump}
cp $RPM_SOURCE_DIR/kdump.init .
cp $RPM_SOURCE_DIR/kdump.sysconfig .
-%endif
%build
%configure
@@ -63,18 +54,14 @@ rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
mkdir -p -m755 $RPM_BUILD_ROOT/etc/rc.d/init.d
mkdir -p -m755 $RPM_BUILD_ROOT/etc/sysconfig
-%if %{kdump}
install -m 644 kdump.sysconfig $RPM_BUILD_ROOT/etc/sysconfig/kdump
install -m 755 kdump.init $RPM_BUILD_ROOT/etc/rc.d/init.d/kdump
-%endif
%clean
rm -rf $RPM_BUILD_ROOT
%post
-%if %{kdump}
chkconfig --add kdump
-%endif
%postun
@@ -92,11 +79,9 @@ exit 0
%files
%defattr(-,root,root,-)
%{_sbindir}/kexec
-%if %{kdump}
%{_sbindir}/kdump
%config(noreplace,missingok) /etc/sysconfig/kdump
%config /etc/rc.d/init.d/kdump
-%endif
%{_libdir}/kexec-tools/kexec_test
%doc News
@@ -104,6 +89,9 @@ exit 0
%doc TODO
%changelog
+* Wed Feb 01 2006 Thomas Graf
+- New kdump patch to support s390 arch + various fixes
+- Include kdump in x86_64 builds
* Mon Jan 30 2006 Thomas Graf
- New kdump patch to support x86_64 userspace