Index: kexec-tools-1.101/kexec/arch/arm/include/arch/options.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/include/arch/options.h	2006-02-06 18:28:37.027097280 +0100
@@ -0,0 +1,11 @@
+#ifndef KEXEC_ARCH_ARM_OPTIONS_H
+#define KEXEC_ARCH_ARM_OPTIONS_H
+
+#define OPT_ARCH_MAX   (OPT_MAX+0)
+
+#define KEXEC_ARCH_OPTIONS \
+	KEXEC_OPTIONS \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
+
+#endif /* KEXEC_ARCH_ARM_OPTIONS_H */
Index: kexec-tools-1.101/kexec/arch/arm/kexec-arm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/kexec-arm.c	2006-02-06 18:28:37.027097280 +0100
@@ -0,0 +1,138 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * modified from kexec-ppc.c
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/utsname.h>
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-arm.h"
+#include <arch/options.h>
+
+#define MAX_MEMORY_RANGES 64
+#define MAX_LINE 160
+static struct memory_range memory_range[MAX_MEMORY_RANGES];
+
+/* Return a sorted list of available memory ranges. */
+int get_memory_ranges(struct memory_range **range, int *ranges)
+{
+	const char iomem[]= "/proc/iomem";
+	int memory_ranges = 0;
+	char line[MAX_LINE];
+	FILE *fp;
+	fp = fopen(iomem, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s: %s\n", 
+			iomem, strerror(errno));
+		return -1;
+	}
+
+	while(fgets(line, sizeof(line), fp) != 0) {
+		unsigned long long start, end;
+		char *str;
+		int type;
+		int consumed;
+		int count;
+		if (memory_ranges >= MAX_MEMORY_RANGES)
+			break;
+		count = sscanf(line, "%Lx-%Lx : %n",
+			&start, &end, &consumed);
+		if (count != 2) 
+			continue;
+		str = line + consumed;
+		end = end + 1;
+
+		if (memcmp(str, "System RAM\n", 11) == 0) {
+			type = RANGE_RAM;
+		} 
+		else if (memcmp(str, "reserved\n", 9) == 0) {
+			type = RANGE_RESERVED;
+		}
+		else {
+			continue;
+		}
+
+		memory_range[memory_ranges].start = start;
+		memory_range[memory_ranges].end = end;
+		memory_range[memory_ranges].type = type;
+		memory_ranges++;
+	}
+	fclose(fp);
+	*range = memory_range;
+	*ranges = memory_ranges;
+	return 0;
+}
+
+/* Supported file types and callbacks */
+struct file_type file_type[] = {
+	{"zImage", zImage_arm_probe, zImage_arm_load, zImage_arm_usage},
+};
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+
+void arch_usage(void)
+{
+}
+
+static struct {
+} arch_options = {
+};
+int arch_process_options(int argc, char **argv)
+{
+	static const struct option options[] = {
+		KEXEC_ARCH_OPTIONS
+		{ 0, 			0, NULL, 0 },
+	};
+	static const char short_options[] = KEXEC_ARCH_OPT_STR;
+	int opt;
+	unsigned long value;
+	char *end;
+
+	opterr = 0; /* Don't complain about unrecognized options here */
+	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
+		switch(opt) {
+		default:
+			break;
+		}
+	}
+	/* Reset getopt for the next pass; called in other source modules */
+	opterr = 1;
+	optind = 1;
+	return 0;
+}
+
+int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags)
+{
+	int result;
+	struct utsname utsname;
+	result = uname(&utsname);
+	if (result < 0) {
+		fprintf(stderr, "uname failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	if (strncmp(utsname.machine, "arm",3) == 0)
+	{
+		*flags |= KEXEC_ARCH_ARM;
+	}
+	else {
+		fprintf(stderr, "Unsupported machine type: %s\n",
+			utsname.machine);
+		return -1;
+	}
+	return 0;
+}
+
+void arch_update_purgatory(struct kexec_info *info)
+{
+}
+
Index: kexec-tools-1.101/kexec/arch/arm/kexec-arm.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/kexec-arm.h	2006-02-06 18:28:37.028097128 +0100
@@ -0,0 +1,9 @@
+#ifndef KEXEC_ARM_H
+#define KEXEC_ARM_H
+
+int zImage_arm_probe(const char *buf, off_t len);
+int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
+		        struct kexec_info *info);
+void zImage_arm_usage(void);
+
+#endif /* KEXEC_ARM_H */
Index: kexec-tools-1.101/kexec/arch/arm/kexec-elf-rel-arm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/kexec-elf-rel-arm.c	2006-02-06 18:28:37.028097128 +0100
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <elf.h>
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+	if (ehdr->ei_data != ELFDATA2MSB) {
+		return 0;
+	}
+	if (ehdr->ei_class != ELFCLASS32) {
+		return 0;
+	}
+	if (ehdr->e_machine != EM_ARM) 
+	{
+		return 0;
+	}
+	return 1;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+	void *location, unsigned long address, unsigned long value)
+{
+	switch(r_type) {
+	case R_ARM_ABS32:
+		*((uint32_t *)location) += value;
+		break;
+	case R_ARM_REL32:
+		*((uint32_t *)location) += value - address;
+		break;
+	default:
+		die("Unknown rel relocation: %lu\n", r_type);
+		break;
+	}
+}
Index: kexec-tools-1.101/kexec/arch/arm/kexec-zImage-arm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/kexec-zImage-arm.c	2006-02-06 18:28:37.028097128 +0100
@@ -0,0 +1,34 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include "../../kexec.h"
+
+int zImage_arm_probe(const char *buf, off_t len)
+{
+	/* 
+	 * Only zImage loading is supported. Do not check if
+	 * the buffer is valid kernel image
+	 */	
+	return 0;
+}
+void zImage_arm_usage(void)
+{
+}
+int zImage_arm_load(int argc, char **argv, const char *buf, off_t len, 
+	struct kexec_info *info)
+{
+	unsigned long base;
+	unsigned int offset = 0x8000; /* 32k offset from memory start */
+	base = locate_hole(info,len+offset,0,0,ULONG_MAX,INT_MAX);
+	if (base == ULONG_MAX)
+	{
+		return -1;
+	}
+	base += offset;
+	add_segment(info,buf,len,base,len);
+	info->entry = (void*)base;
+	return 0;
+}
Index: kexec-tools-1.101/kexec/arch/arm/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/kexec/arch/arm/Makefile	2006-02-06 18:28:37.028097128 +0100
@@ -0,0 +1,8 @@
+#
+# kexec arm (linux booting linux)
+#
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-elf-rel-arm.c
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-zImage-arm.c 
+KEXEC_C_SRCS+= kexec/arch/arm/kexec-arm.c 
+
+KEXEC_S_SRCS+=
Index: kexec-tools-1.101/kexec/kexec.c
===================================================================
--- kexec-tools-1.101.orig/kexec/kexec.c	2005-01-13 14:24:29.000000000 +0100
+++ kexec-tools-1.101/kexec/kexec.c	2006-02-06 18:28:37.029096976 +0100
@@ -187,7 +187,7 @@
 	}
 
 	/* 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;
 		
Index: kexec-tools-1.101/kexec/kexec-syscall.h
===================================================================
--- kexec-tools-1.101.orig/kexec/kexec-syscall.h	2005-01-06 07:59:50.000000000 +0100
+++ kexec-tools-1.101/kexec/kexec-syscall.h	2006-02-06 18:28:37.029096976 +0100
@@ -37,6 +37,9 @@
 #ifdef __x86_64__
 #define __NR_kexec_load		246
 #endif
+#ifdef __arm__
+#define __NR_kexec_load		__NR_SYSCALL_BASE + 347  
+#endif
 #ifndef __NR_kexec_load
 #error Unknown processor architecture.  Needs a kexec_load syscall number.
 #endif
@@ -67,6 +70,7 @@
 #define KEXEC_ARCH_PPC     (20 << 16)
 #define KEXEC_ARCH_PPC64   (21 << 16)
 #define KEXEC_ARCH_IA_64   (50 << 16)
+#define KEXEC_ARCH_ARM     (40 << 16)
 
 #define KEXEC_MAX_SEGMENTS 8
 
Index: kexec-tools-1.101/purgatory/arch/arm/include/limits.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/purgatory/arch/arm/include/limits.h	2006-02-06 18:28:37.031096672 +0100
@@ -0,0 +1,58 @@
+#ifndef LIMITS_H
+#define LIMITS_H	1
+
+
+/* Number of bits in a `char' */
+#define CHAR_BIT	8
+
+/* Minimum and maximum values a `signed char' can hold */
+#define SCHAR_MIN	(-128)
+#define SCHAR_MAX	127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
+#define UCHAR_MAX	255
+
+/* Minimum and maximum values a `char' can hold */
+#define CHAR_MIN	SCHAR_MIN
+#define CHAR_MAX	SCHAR_MAX
+
+/* Minimum and maximum values a `signed short int' can hold */
+#define SHRT_MIN	(-32768)
+#define SHRT_MAX	32767
+
+/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */
+#define USHRT_MAX	65535
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN		(-INT_MAX - 1)
+#define INT_MAX		2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX	4294967295U
+
+
+/* Minimum and maximum values a `signed int' can hold */
+#define INT_MIN		(-INT_MAX - 1)
+#define INT_MAX		2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
+#define UINT_MAX	4294967295U
+
+/* Minimum and maximum values a `signed long' can hold */
+#define LONG_MAX	2147483647L
+#define LONG_MIN	(-LONG_MAX - 1L)
+
+/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */
+#define ULONG_MAX	4294967295UL
+
+/* Minimum and maximum values a `signed long long' can hold */
+#define LLONG_MAX	9223372036854775807LL
+#define LLONG_MIN	(-LONG_MAX - 1LL)
+
+
+/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */
+#define ULLONG_MAX	18446744073709551615ULL
+
+
+#endif /* LIMITS_H */
Index: kexec-tools-1.101/purgatory/arch/arm/include/stdint.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/purgatory/arch/arm/include/stdint.h	2006-02-06 18:28:37.031096672 +0100
@@ -0,0 +1,16 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long      size_t;
+
+typedef unsigned char      uint8_t;
+typedef unsigned short     uint16_t;
+typedef unsigned int       uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char        int8_t;
+typedef signed short       int16_t;
+typedef signed int         int32_t;
+typedef signed long long   int64_t;
+
+#endif /* STDINT_H */
Index: kexec-tools-1.101/purgatory/arch/arm/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools-1.101/purgatory/arch/arm/Makefile	2006-02-06 18:28:37.031096672 +0100
@@ -0,0 +1,7 @@
+#
+# Purgatory arm
+#
+
+PURGATORY_S_SRCS += 
+PURGATORY_C_SRCS += 
+
Index: kexec-tools-1.101/configure.ac
===================================================================
--- kexec-tools-1.101.orig/configure.ac	2005-01-09 02:36:57.000000000 +0100
+++ kexec-tools-1.101/configure.ac	2006-02-06 18:30:19.274553304 +0100
@@ -25,12 +25,15 @@
 	powerpc )
 		host_cpu="ppc"
 		;;
+	arm* )
+		host_cpu="arm"
+		;;
 	* ) 
 		host_cpu="$host_cpu"
 		;;
 esac
 case $host_cpu in
-	i386|ppc|x86_64|alpha|ppc64|ia64)
+	i386|ppc|x86_64|alpha|ppc64|ia64|arm)
 		;;
 	* )
 		AC_MSG_ERROR([ unsupported architecture $host_cpu])
