[PATCH 6/6] ppc64-kdump-purgatory-backup-support.patch

R Sharada sharada at in.ibm.com
Tue Jan 17 02:17:56 EST 2006



This patch implements the purgatory support to take backup
of the first 32KB of the first kernel
- Modified the v2wrap code to make the secondary cpus spin
directly in the v2wrap after pulling them out of kexec_wait
- Use the elf_rel function support to set the various
symbols used in purgatory
- load device-tree as a separate segment
- other miscellaneous compiler warnings cleanup
- add purgatory code support for backup
- build purgatory as relocatable for ppc64

Signed-off-by: R Sharada <sharada at in.ibm.com>
Signed-off-by: Mohan Kumar M <mohan at in.ibm.com>
---


diff -puN kexec/arch/ppc64/fs2dt.c~ppc64-kdump-purgatory-backup-support kexec/arch/ppc64/fs2dt.c
--- kexec-tools-1.101/kexec/arch/ppc64/fs2dt.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/fs2dt.c	2006-01-17 07:23:35.000000000 +0530
@@ -374,7 +374,7 @@ void putnode(void)
 }
 
 int create_flatten_tree(struct kexec_info *info, unsigned char **bufp,
-			 unsigned long *sizep, char *cmdline)
+			unsigned long *sizep, char *cmdline)
 {
 	unsigned long len;
 	unsigned long tlen;
@@ -420,10 +420,10 @@ int create_flatten_tree(struct kexec_inf
 
 	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);
diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~ppc64-kdump-purgatory-backup-support kexec/arch/ppc64/kexec-elf-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-ppc64.c	2006-01-17 07:23:35.000000000 +0530
@@ -4,6 +4,7 @@
  * Copyright (C) 2004  Adam Litke (agl at us.ibm.com)
  * Copyright (C) 2004  IBM Corp.
  * Copyright (C) 2005  R Sharada (sharada at in.ibm.com)
+ * Copyright (C) 2006  Mohan Kumar M (mohan at 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
@@ -45,6 +46,7 @@ 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)
 {
@@ -83,6 +85,10 @@ int elf_ppc64_load(int argc, char **argv
 	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)
@@ -167,7 +173,7 @@ int elf_ppc64_load(int argc, char **argv
 		size = phdr->p_memsz;
 
 	hole_addr = (unsigned long)locate_hole(info, size, 0, 0,
-			0xFFFFFFFFFFFFFFFFUL, 1);
+			max_addr, 1);
 	ehdr.e_phdr[0].p_paddr = hole_addr;
 	result = elf_exec_load(&ehdr, info);
 	if (result < 0) {
@@ -175,24 +181,6 @@ int elf_ppc64_load(int argc, char **argv
 		return result;
 	}
 
-	/* 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.
 	 */
@@ -207,68 +195,136 @@ int elf_ppc64_load(int argc, char **argv
 	}
 
 	/* 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;
-
-	  /* 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;
+		unsigned char *blob_buf = NULL;
+		off_t blob_size = 0;
+
+		/* 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;
+		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;
 }
diff -puN kexec/arch/ppc64/kexec-elf-rel-ppc64.c~ppc64-kdump-purgatory-backup-support kexec/arch/ppc64/kexec-elf-rel-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-rel-ppc64.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-elf-rel-ppc64.c	2006-01-17 07:35:50.000000000 +0530
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <elf.h>
+#include <string.h>
 #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 = (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 -puN kexec/arch/ppc64/kexec-zImage-ppc64.c~ppc64-kdump-purgatory-backup-support kexec/arch/ppc64/kexec-zImage-ppc64.c
--- kexec-tools-1.101/kexec/arch/ppc64/kexec-zImage-ppc64.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/arch/ppc64/kexec-zImage-ppc64.c	2006-01-17 07:23:35.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 -puN purgatory/Makefile~ppc64-kdump-purgatory-backup-support purgatory/Makefile
--- kexec-tools-1.101/purgatory/Makefile~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/Makefile	2006-01-17 07:23:35.000000000 +0530
@@ -21,13 +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/purgatory.c
 PURGATORY_C_SRCS += purgatory/printf.c
 PURGATORY_C_SRCS += purgatory/string.c
-endif
-PURGATORY_S_OBJS:= 
+PURGATORY_S_OBJS:=
 
 include purgatory/arch/$(ARCH)/Makefile
 
@@ -61,12 +59,7 @@ $(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 -puN purgatory/arch/ppc64/Makefile~ppc64-kdump-purgatory-backup-support purgatory/arch/ppc64/Makefile
--- kexec-tools-1.101/purgatory/arch/ppc64/Makefile~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/Makefile	2006-01-17 07:23:35.000000000 +0530
@@ -2,6 +2,7 @@
 # Purgatory ppc
 #
 
-PURGATORY_C_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 -puN /dev/null purgatory/arch/ppc64/console-ppc64.c
--- /dev/null	2004-07-01 07:56:11.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/console-ppc64.c	2006-01-17 07:23:35.000000000 +0530
@@ -0,0 +1,27 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Mohan Kumar M (mohan at 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 <purgatory.h>
+
+void putchar(int c)
+{
+	return;
+}
diff -puN /dev/null purgatory/arch/ppc64/purgatory-ppc64.c
--- /dev/null	2004-07-01 07:56:11.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/purgatory-ppc64.c	2006-01-17 07:23:35.000000000 +0530
@@ -0,0 +1,41 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Mohan Kumar M (mohan at 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 <purgatory.h>
+#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 -puN /dev/null purgatory/arch/ppc64/purgatory-ppc64.h
--- /dev/null	2004-07-01 07:56:11.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/purgatory-ppc64.h	2006-01-17 07:23:35.000000000 +0530
@@ -0,0 +1,6 @@
+#ifndef PURGATORY_PPC64_H
+#define PURGATORY_PPC64_H
+
+void crashdump_backup_memory(void);
+
+#endif /* PURGATORY_PPC64_H */
diff -puN purgatory/arch/ppc64/v2wrap.S~ppc64-kdump-purgatory-backup-support purgatory/arch/ppc64/v2wrap.S
--- kexec-tools-1.101/purgatory/arch/ppc64/v2wrap.S~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/v2wrap.S	2006-01-17 07:23:35.000000000 +0530
@@ -2,6 +2,7 @@
 #  kexec: Linux boots Linux
 #
 #  Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
+#  Copyright (C) 2006, Mohan Kumar M (mohan at 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
@@ -18,14 +19,17 @@
 #
 
 # 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
 #
@@ -34,50 +38,50 @@
 #   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 at 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
-
-	.org 0x60		# ABI: slaves start at 60 with r3=phys
-slave:	ld	4,secondary_hold at l(0);
-	cmpdi	0,4,0
-	beq	slave
-
-	# 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
-	bctr
+	mr      17,3            # save cpu id to r17
+	mr      15,4            # save physical address in reg15
 
-	# ok, now wait for the master to tell is to go back to the new block
-1:	ld	5,copied at l(4)
-	cmpdi	0,5,0
-	beq	1b
-	ba	0x60
+	LOADADDR(6,my_toc)
+	ld      2,0(6)          #setup toc
 
+	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
 
-	.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 at ha
+	lwz     5,spin at 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
@@ -85,7 +89,17 @@ slave:	ld	4,secondary_hold at l(0);
 	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
@@ -103,12 +117,12 @@ slave:	ld	4,secondary_hold at l(0);
 	icbi	0,6
 	sync
 	isync
-	std	6,-16(3)	# send slaves back down
+	lis     6,spin at ha
+	li      0,0
+	stw     0,spin at 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 -puN kexec/kexec-elf.c~ppc64-kdump-purgatory-backup-support kexec/kexec-elf.c
--- kexec-tools-1.101/kexec/kexec-elf.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/kexec-elf.c	2006-01-17 07:29:17.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 -puN kexec/kexec-elf-rel.c~ppc64-kdump-purgatory-backup-support kexec/kexec-elf-rel.c
--- kexec-tools-1.101/kexec/kexec-elf-rel.c~ppc64-kdump-purgatory-backup-support	2006-01-17 07:23:35.000000000 +0530
+++ kexec-tools-1.101-sharada/kexec/kexec-elf-rel.c	2006-01-17 07:23:35.000000000 +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,18 @@ 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);
+			*/
 			}
 			sec_base = 0;
 			if (sym.st_shndx == SHN_COMMON) {
@@ -383,14 +393,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 +409,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 +462,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 +501,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 -puN /dev/null purgatory/arch/ppc64/crashdump_backup.c
--- /dev/null	2004-07-01 07:56:11.000000000 +0530
+++ kexec-tools-1.101-sharada/purgatory/arch/ppc64/crashdump_backup.c	2006-01-17 07:23:35.000000000 +0530
@@ -0,0 +1,41 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Mohan Kumar M (mohan at 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 <stdint.h>
+#include <string.h>
+
+#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);
+	}
+}
_



More information about the Linuxppc64-dev mailing list