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