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