[PATCH] ia64 support for kexec-tools

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for kexec-tools on ia64. This patch applies on
top of -kdump7 patch from <http://lse.sourceforge.net/kdump/>.

Signed-off-by: Khalid Aziz <khalid.aziz@xxxxxx>
---

diff -urNp kexec-tools-1.101/kdump/kdump.8 kexec-tools-1.101-ia64/kdump/kdump.8
--- kexec-tools-1.101/kdump/kdump.8	1969-12-31 17:00:00.000000000 -0700
+++ kexec-tools-1.101-ia64/kdump/kdump.8	2006-04-06 12:54:59.000000000 -0600
@@ -0,0 +1,39 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH KDUMP 8 "Jul 27, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+kdump \- This is just a placeholder until real man page has been written
+.SH SYNOPSIS
+.B kdump
+.RI [ options ] " start_address" ...
+.SH DESCRIPTION
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics, 
+.\" respectively.
+\fBkdump\fP does not have a man page yet. 
+.SH OPTIONS
+.\"These programs follow the usual GNU command line syntax, with long
+.\"options starting with two dashes (`-').
+.\"A summary of options is included below.
+.\"For a complete description, see the Info files.
+.SH SEE ALSO
+.SH AUTHOR
+kdump was written by Eric Biederman.
+.PP
+This manual page was written by Khalid Aziz <khalid.aziz@xxxxxx>,
+for the Debian project (but may be used by others).
diff -urNp kexec-tools-1.101/kdump/Makefile kexec-tools-1.101-ia64/kdump/Makefile
--- kexec-tools-1.101/kdump/Makefile	2005-02-05 18:40:36.000000000 -0700
+++ kexec-tools-1.101-ia64/kdump/Makefile	2006-04-06 12:54:59.000000000 -0600
@@ -10,6 +10,7 @@ KDUMP_SRCS:= $(KDUMP_C_SRCS)
 KDUMP_OBJS:= $(KDUMP_C_OBJS)
 KDUMP_DEPS:= $(KDUMP_C_DEPS)
 KDUMP:= $(SBINDIR)/kdump
+KDUMP_MANPAGE:= $(MANDIR)/man8/kdump.8
 
 include $(KDUMP_DEPS)
 
@@ -25,6 +26,9 @@ $(KDUMP): $(KDUMP_OBJS)
 	mkdir -p $(@D)
 	$(CC) $(CFLAGS) -o $@ $(KDUMP_OBJS)
 
+$(KDUMP_MANPAGE): kdump/kdump.8
+	$(MKDIR) -p     $(MANDIR)/man8
+	cp kdump/kdump.8 $(KDUMP_MANPAGE)
 echo::
 	@echo "KDUMP_C_SRCS $(KDUMP_C_SRCS)"
 	@echo "KDUMP_C_DEPS $(KDUMP_C_DEPS)"
diff -urNp kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-elf-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c	2004-12-21 13:01:37.000000000 -0700
+++ kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-elf-ia64.c	2006-04-06 12:54:59.000000000 -0600
@@ -6,6 +6,7 @@
  * Copyright (C) 2004 Silicon Graphics, Inc.
  *   Jesse Barnes <jbarnes@xxxxxxx>
  * Copyright (C) 2004 Khalid Aziz <khalid.aziz@xxxxxx> Hewlett Packard Co
+ * Copyright (C) 2005 Zou Nan hai <nanhai.zou@xxxxxxxxx> Intel Corp
  *
  * 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
@@ -34,6 +35,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <limits.h>
 #include <elf.h>
 #include <boot/elf_boot.h>
 #include <ip_checksum.h>
@@ -74,23 +76,29 @@ void elf_ia64_usage(void)
 {
 	printf(
 		"    --command-line=STRING Set the kernel command line to STRING.\n"
-		"    --append=STRING       Set the kernel command line to STRING.\n");
+		"    --append=STRING       Set the kernel command line to STRING.\n"
+		"    --initrd=FILE       Use FILE as the kernel's initial ramdisk.\n");
 }
 
 int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line;
-	int command_line_len;
-	unsigned long entry, max_addr;
+	const char *command_line, *ramdisk=0;
+	char *ramdisk_buf = NULL;
+	off_t ramdisk_size = 0;
+	unsigned long command_line_len;
+	unsigned long entry, max_addr, gp_value;
+	unsigned command_line_base, ramdisk_base;
 	int result;
 	int opt;
 #define OPT_APPEND	(OPT_ARCH_MAX+0)
+#define OPT_RAMDISK	(OPT_ARCH_MAX+1)
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
 		{"command-line", 1, 0, OPT_APPEND},
 		{"append",       1, 0, OPT_APPEND},
+		{"initrd",       1, 0, OPT_RAMDISK},
 		{0, 0, 0, 0},
 	};
 
@@ -110,11 +118,14 @@ int elf_ia64_load(int argc, char **argv,
 		case OPT_APPEND:
 			command_line = optarg;
 			break;
+		case OPT_RAMDISK:
+			ramdisk = optarg;
+			break;
 		}
 	}
 	command_line_len = 0;
 	if (command_line) {
-		command_line_len = strlen(command_line) + 1;
+		command_line_len = strlen(command_line) + 16;
 	}
 
 	/* Parse the Elf file */
@@ -129,13 +140,46 @@ int elf_ia64_load(int argc, char **argv,
 
 	/* Load the Elf data */
 	result = elf_exec_load(&ehdr, info);
-	free_elf_info(&ehdr);
 	if (result < 0) {
 		fprintf(stderr, "ELF load failed\n");
+		free_elf_info(&ehdr);
 		return result;
 	}
+
+
+	/* Load the setup code */
+	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+			0x80000, ULONG_MAX, 1);
+
+	if (command_line_len) {
+		char *cmdline = xmalloc(command_line_len);
+		strcpy(cmdline, command_line);
+		command_line_len = (command_line_len + 15)&(~15);
+		elf_rel_set_symbol(&info->rhdr, "__command_line_len",
+				&command_line_len, sizeof(long));
+		command_line_base = add_buffer(info, cmdline,
+					command_line_len, command_line_len,
+					16, 0, max_addr, 1);
+		elf_rel_set_symbol(&info->rhdr, "__command_line",
+				&command_line_base, sizeof(long));
+	}
 	
-	/* For now we don't have arguments to pass :( */
-	info->entry = (void *)entry;
+	if (ramdisk) {
+		ramdisk_buf = slurp_file(ramdisk, &ramdisk_size);
+		ramdisk_base = add_buffer(info, ramdisk_buf, ramdisk_size,
+				ramdisk_size,
+				getpagesize(), 0, max_addr, 1);
+		elf_rel_set_symbol(&info->rhdr, "__ramdisk_base",
+				&ramdisk_base, sizeof(long));
+		elf_rel_set_symbol(&info->rhdr, "__ramdisk_size",
+				&ramdisk_size, sizeof(long));
+	}
+
+	gp_value = info->rhdr.rel_addr + 0x200000;
+        elf_rel_set_symbol(&info->rhdr, "__gp_value", &gp_value,
+                        sizeof(gp_value));
+
+	elf_rel_set_symbol(&info->rhdr, "__kernel_entry", &entry, sizeof(entry));
+	free_elf_info(&ehdr);
 	return 0;
 }
diff -urNp kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-elf-rel-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-rel-ia64.c	2004-12-20 15:43:23.000000000 -0700
+++ kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-elf-rel-ia64.c	2006-04-06 12:54:59.000000000 -0600
@@ -1,8 +1,14 @@
+/*  Most of the code in this file is
+ *  based on arch/ia64/kernel/module.c in Linux kernel
+ */
+
 #include <stdio.h>
 #include <elf.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 
+#define MAX_LTOFF       ((uint64_t) (1 << 22))
+
 int machine_verify_elf_rel(struct mem_ehdr *ehdr)
 {
 	if (ehdr->ei_data != ELFDATA2LSB) {
@@ -17,12 +23,40 @@ int machine_verify_elf_rel(struct mem_eh
 	return 1;
 }
 
+static void
+ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
+{
+        uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
+#       define insn_mask ((1UL << 41) - 1)
+        unsigned long shift;
+
+        b0 = b[0]; b1 = b[1];
+        shift = 5 + 41 * (insn_addr % 16); /* 5 bits of template, then 3 x 41-bit instructions */
+        if (shift >= 64) {
+                m1 = mask << (shift - 64);
+                v1 = val << (shift - 64);
+        } else {
+                m0 = mask << shift; m1 = mask >> (64 - shift);
+                v0 = val  << shift; v1 = val >> (64 - shift);
+                b[0] = (b0 & ~m0) | (v0 & m0);
+        }
+        b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+static inline uint64_t
+bundle (const uint64_t insn)
+{
+        return insn & ~0xfUL;
+}
+
 void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
 	void *location, unsigned long address, unsigned long value)
 {
+	uint64_t gp_value = ehdr->rel_addr + 0x200000;
 	switch(r_type) {
 	case R_IA64_NONE:
 		break;
+	case R_IA64_SEGREL64LSB:
 	case R_IA64_DIR64LSB:
 		*((uint64_t *)location) = value;
 		break;
@@ -31,15 +65,67 @@ void machine_apply_elf_rel(struct mem_eh
 		if (value != *((uint32_t *)location))
 			goto overflow;
 		break;
-	case R_IA64_PCREL21B:
+	case R_IA64_IMM64:
+		ia64_patch((uint64_t)location, 0x01fffefe000UL, 
+				/* bit 63 -> 36 */
+				(((value & 0x8000000000000000UL) >> 27) 
+				/* bit 21 -> 21 */
+				  | ((value & 0x0000000000200000UL) <<  0) 
+				/* bit 16 -> 22 */
+				  | ((value & 0x00000000001f0000UL) <<  6) 
+				/* bit 7 -> 27 */
+				  | ((value & 0x000000000000ff80UL) << 20) 
+				/* bit 0 -> 13 */
+				  | ((value & 0x000000000000007fUL) << 13)));
+		ia64_patch((uint64_t)location - 1, 0x1ffffffffffUL, value>>22);
+		break;
+	case R_IA64_IMM22:
+		if (value + (1 << 21) >= (1 << 22))
+                	die("value out of IMM22 range\n");
+		ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+				/* bit 21 -> 36 */
+				(((value & 0x200000UL) << 15)
+				/* bit 16 -> 22 */
+				 | ((value & 0x1f0000UL) <<  6)
+				/* bit  7 -> 27 */
+				 | ((value & 0x00ff80UL) << 20)
+				/* bit  0 -> 13 */
+				 | ((value & 0x00007fUL) << 13) ));
+		break;
+	case R_IA64_PCREL21B: {
+		uint64_t delta = ((int64_t)value - (int64_t)address)/16;
+		if (delta + (1 << 20) >= (1 << 21))
+			die("value out of IMM21B range\n");
+		value = ((int64_t)(value - bundle(address)))/16;
+		ia64_patch((uint64_t)location, 0x11ffffe000UL,
+				(((value & 0x100000UL) << 16) /* bit 20 -> 36 */
+				 | ((value & 0x0fffffUL) << 13) /* bit  0 -> 13 */));
+		}
+		break;
+	case R_IA64_LTOFF22X:
+		if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+			die("value out of gp relative range");
+		value -= gp_value;
+		ia64_patch((uint64_t)location, 0x01fffcfe000UL,
+				(((value & 0x200000UL) << 15) /* bit 21 -> 36 */
+				   |((value & 0x1f0000UL) <<  6) /* bit 16 -> 22 */
+				   |((value & 0x00ff80UL) << 20) /* bit  7 -> 27 */
+				   |((value & 0x00007fUL) << 13) /* bit  0 -> 13 */));
+		break;
+	case R_IA64_LDXMOV:
+		if (value - gp_value + MAX_LTOFF/2 >= MAX_LTOFF)
+			die("value out of gp relative range");
+		ia64_patch((uint64_t)location, 0x1fff80fe000UL, 0x10000000000UL);
+	        break;
 	case R_IA64_LTOFF22:
-	case R_IA64_SEGREL64LSB:
+
 	default:
-		die("Unknown rela relocation: %lu\n", r_type);
+		die("Unknown rela relocation: 0x%lx 0x%lx\n",
+				r_type, address);
 		break;
 	}
 	return;
- overflow:
+overflow:
 	die("overflow in relocation type %lu val %Lx\n", 
-		r_type, value);
+			r_type, value);
 }
diff -urNp kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-ia64.c
--- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c	2006-04-06 14:07:58.000000000 -0600
+++ kexec-tools-1.101-ia64/kexec/arch/ia64/kexec-ia64.c	2006-04-06 12:59:28.000000000 -0600
@@ -27,6 +27,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <getopt.h>
+#include <sched.h>
 #include <sys/utsname.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
@@ -56,7 +57,7 @@ int get_memory_ranges(struct memory_rang
 	 */
 	fprintf(stderr, "Warning assuming memory at 0-64MB is present\n");
 	memory_ranges = 0;
-	memory_range[memory_ranges].start = 0x00010000;
+	memory_range[memory_ranges].start = 0x00100000;
 	memory_range[memory_ranges].end   = 0x10000000;
 	memory_range[memory_ranges].type  = RANGE_RAM;
 	memory_ranges++;
@@ -76,9 +77,6 @@ void arch_usage(void)
 {
 }
 
-static struct {
-} arch_options = {
-};
 int arch_process_options(int argc, char **argv)
 {
 	static const struct option options[] = {
@@ -87,8 +85,12 @@ int arch_process_options(int argc, char 
 	};
 	static const char short_options[] = KEXEC_ARCH_OPT_STR;
 	int opt;
-	unsigned long value;
-	char *end;
+
+	/* execute from monarch processor */
+        cpu_set_t affinity;
+	CPU_ZERO(&affinity);
+	CPU_SET(0, &affinity);
+        sched_setaffinity(0, sizeof(affinity), &affinity);
 
 	opterr = 0; /* Don't complain about unrecognized options here */
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
@@ -115,32 +117,7 @@ int arch_compat_trampoline(struct kexec_
 	}
 	if (strcmp(utsname.machine, "ia64") == 0)
 	{
-		info->kexec_flags |= KEXEC_ARCH_X86_64;
-	}
-	else {
-		fprintf(stderr, "Unsupported machine type: %s\n",
-			utsname.machine);
-		return -1;
-	}
-	return 0;
-}
-
-int arch_compat_trampoline(struct kexec_info *info)
-{
-	int result;
-	struct utsname utsname;
-	result = uname(&utsname);
-	if (result < 0) {
-		fprintf(stderr, "uname failed: %s\n",
-			strerror(errno));
-		return -1;
-	}
-	if (strcmp(utsname.machine, "ia64") == 0)
-	{
-		/* For compatibility with older patches 
-		 * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_IA64 here.
-		 */
-		info->kexec_flags |= KEXEC_ARCH_DEFAULT;
+		info->kexec_flags |= KEXEC_ARCH_IA_64;
 	}
 	else {
 		fprintf(stderr, "Unsupported machine type: %s\n",
diff -urNp kexec-tools-1.101/kexec/kexec.8 kexec-tools-1.101-ia64/kexec/kexec.8
--- kexec-tools-1.101/kexec/kexec.8	2004-12-19 15:27:31.000000000 -0700
+++ kexec-tools-1.101-ia64/kexec/kexec.8	2006-04-06 12:54:59.000000000 -0600
@@ -2,7 +2,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH KEXEC-TOOLS 8 "October 13, 2004"
+.TH KEXEC 8 "October 13, 2004"
 .\" Please adjust this date whenever revising the manpage.
 .\"
 .\" Some roff macros, for reference:
@@ -16,30 +16,60 @@
 .\" .sp <n>    insert n+1 empty lines
 .\" for manpage-specific macros, see man(7)
 .SH NAME
-kexec-tools \- Tool to load a kernel for warm reboot and initiate a warm reboot
+kexec \- Tool to load a kernel for warm reboot and initiate a warm reboot
 .SH SYNOPSIS
-.B kexec-tools
+.B kexec
 .RI [ options ] " files" ...
 .SH DESCRIPTION
 .PP
 .\" TeX users may be more comfortable with the \fB<whatever>\fP and
 .\" \fI<whatever>\fP escape sequences to invode bold face and italics, 
 .\" respectively.
-\fBkexec-tools\fP does not have a man page yet. Please use "kexec -h" for help.
+\fBkexec\fP allows one to load another kernel from the currently running 
+Linux kernel. Normally one would load a kernel, and possibly an initial 
+ramdisk, into the currently running kernel using kexec and then initiate
+a warm reboot by executing kexec again with appropriate option.
 .SH OPTIONS
 These programs follow the usual GNU command line syntax, with long
 options starting with two dashes (`-').
 A summary of options is included below.
-For a complete description, see the Info files.
 .TP
 .B \-h, \-\-help
 Show summary of options.
 .TP
 .B \-v, \-\-version
 Show version of program.
-.SH SEE ALSO
+.TP
+.B \-f, \-\-force
+Force an immediate kexec without calling shutdown.
+.TP
+.B \-x, \-\-no-ifdown
+Don't bring down network interfaces. (if used, must be last option specified)
+.TP
+.B \-l, \-\-load
+Load the new kernel into the current kernel.
+.TP
+.B \-p, \-\-load-panic
+Load the new kernel for use on panic.
+.TP
+.B \-u, \-\-unload
+Unload the current kexec target kernel.
+.TP
+.B \-e, \-\-exec
+Execute a currently loaded kernel.
+.TP
+.B \-t, \-\-type=TYPE
+Specify the new kernel is of this type.
+.TP
+.B \-\-mem\-min=<addr>
+Specify the lowest memory addres to load code into.
+.TP
+.B \-\-mem\-max=<addr>
+Specify the highest memory addres to load code into.
+.TP
+There may be additional options supported on individual architectures.  Use --help option to see those options.
 .SH AUTHOR
-kexec-tools was written by Eric Biederman.
+kexec was written by Eric Biederman.
 .PP
-This manual page was written by Khalid Aziz <khalid_aziz@xxxxxx>,
+This manual page was written by Khalid Aziz <khalid.aziz@xxxxxx>,
 for the Debian project (but may be used by others).
diff -urNp kexec-tools-1.101/kexec/Makefile kexec-tools-1.101-ia64/kexec/Makefile
--- kexec-tools-1.101/kexec/Makefile	2006-04-06 14:07:58.000000000 -0600
+++ kexec-tools-1.101-ia64/kexec/Makefile	2006-04-06 12:55:01.000000000 -0600
@@ -28,6 +28,7 @@ KEXEC_SRCS:= $(KEXEC_C_SRCS) $(KEXEC_S_S
 KEXEC_OBJS:= $(KEXEC_C_OBJS) $(KEXEC_S_OBJS)
 KEXEC_DEPS:= $(KEXEC_C_DEPS) $(KEXEC_S_DEPS)
 KEXEC:= $(SBINDIR)/kexec
+KEXEC_MANPAGE:= $(MANDIR)/man8/kexec.8
 
 include $(KEXEC_DEPS)
 
@@ -51,6 +52,9 @@ $(KEXEC): $(KEXEC_OBJS) $(UTIL_LIB)
 	mkdir -p $(@D)
 	$(CC) $(KCFLAGS) -o $@ $(KEXEC_OBJS) $(UTIL_LIB) $(LIBS)
 
+$(KEXEC_MANPAGE): kexec/kexec.8
+	 $(MKDIR) -p     $(MANDIR)/man8
+	cp kexec/kexec.8 $(KEXEC_MANPAGE)
 echo::
 	@echo "KEXEC_C_SRCS $(KEXEC_C_SRCS)"
 	@echo "KEXEC_C_DEPS $(KEXEC_C_DEPS)"
diff -urNp kexec-tools-1.101/Makefile kexec-tools-1.101-ia64/Makefile
--- kexec-tools-1.101/Makefile	2005-02-18 05:26:09.000000000 -0700
+++ kexec-tools-1.101-ia64/Makefile	2006-04-06 12:55:01.000000000 -0600
@@ -43,6 +43,7 @@ PKGLIBDIR=$(LIBDIR)/$(PACKAGE)
 PKGINCLUDEIR=$(INCLUDEDIR)/$(PACKAGE)
 
 MAN_PAGES:= kexec/kexec.8
+MAN_PAGES+= kdump/kdump.8
 BINARIES_i386:=  $(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
 BINARIES_x86_64:=$(SBINDIR)/kexec $(PKGLIBDIR)/kexec_test
 BINARIES:=$(SBINDIR)/kexec $(SBINDIR)/kdump $(BINARIES_$(ARCH)) 
diff -urNp kexec-tools-1.101/purgatory/arch/ia64/entry.S kexec-tools-1.101-ia64/purgatory/arch/ia64/entry.S
--- kexec-tools-1.101/purgatory/arch/ia64/entry.S	1969-12-31 17:00:00.000000000 -0700
+++ kexec-tools-1.101-ia64/purgatory/arch/ia64/entry.S	2006-04-06 12:55:01.000000000 -0600
@@ -0,0 +1,85 @@
+/*
+ * purgatory:  setup code
+ *
+ * Copyright (C) 2005  Zou Nan hai (nanhai.zou@xxxxxxxxx)
+ *
+ * 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.
+ */
+
+.global __dummy_efi_function
+.align  32
+.proc  __dummy_efi_function
+__dummy_efi_function:
+	mov r8=r0;;
+	br.ret.sptk.many rp;;
+.global __dummy_efi_function_end
+__dummy_efi_function_end:
+.endp 	__dummy_efi_function
+
+.global purgatory_start
+.align  32
+.proc   purgatory_start
+purgatory_start:
+	movl r2=__gp_value;;
+	ld8 gp=[r2];;
+	br.call.sptk.many b0=purgatory
+	;;
+	alloc r2 = ar.pfs, 0, 0, 5, 0
+	;;
+	mov out0=r28
+
+	movl r2=__command_line;;
+	ld8 out1=[r2];;
+	movl r2=__command_line_len;;
+	ld8 out2=[r2];;
+	movl r2=__ramdisk_base;;
+	ld8 out3=[r2];;
+	movl r2=__ramdisk_size;;
+	ld8 out4=[r2];;
+	br.call.sptk.many b0=ia64_env_setup
+	movl r10=__kernel_entry;;
+	ld8 r14=[r10];;
+	mov b6=r14;;
+	mov ar.lc=r0
+	mov ar.ec=r0
+	cover;;
+	invala;;
+	br.call.sptk.many  b0=b6
+.endp   purgatory_start
+
+.align  32
+.global __kernel_entry
+.size	__kernel_entry, 8
+__kernel_entry:
+        data8 0x0
+.global __command_line
+.size	__command_line, 8
+__command_line:
+        data8 0x0
+.global __command_line_len
+.size	__command_line_len, 8
+__command_line_len:
+        data8 0x0
+.global __ramdisk_base
+.size	__ramdisk_base, 8
+__ramdisk_base:
+        data8 0x0
+.global __ramdisk_size
+.size	__ramdisk_size, 8
+__ramdisk_size:
+        data8 0x0
+.global __gp_value
+.size	__gp_value, 8
+__gp_value:
+        data8 0x0
diff -urNp kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h kexec-tools-1.101-ia64/purgatory/arch/ia64/include/arch/io.h
--- kexec-tools-1.101/purgatory/arch/ia64/include/arch/io.h	1969-12-31 17:00:00.000000000 -0700
+++ kexec-tools-1.101-ia64/purgatory/arch/ia64/include/arch/io.h	2006-04-06 12:55:01.000000000 -0600
@@ -0,0 +1,25 @@
+#ifndef ARCH_IO_H
+#define ARCH_IO_H
+
+#include <stdint.h>
+/* Helper functions for directly doing I/O */
+
+extern inline uint8_t inb(void *port)
+{
+	volatile unsigned char *addr = (unsigned char *)port;
+	uint8_t result;
+
+	result = *addr;
+	asm volatile ("mf.a"::: "memory");
+	return result;
+}
+
+extern inline void outb (uint8_t value, void *port)
+{
+	volatile unsigned char *addr = (unsigned char *)port;
+
+	*addr = value;
+	asm volatile ("mf.a"::: "memory");
+}
+
+#endif /* ARCH_IO_H */
diff -urNp kexec-tools-1.101/purgatory/arch/ia64/Makefile kexec-tools-1.101-ia64/purgatory/arch/ia64/Makefile
--- kexec-tools-1.101/purgatory/arch/ia64/Makefile	2004-12-20 15:44:22.000000000 -0700
+++ kexec-tools-1.101-ia64/purgatory/arch/ia64/Makefile	2006-04-06 12:55:01.000000000 -0600
@@ -1,8 +1,8 @@
 #
 # Purgatory ia64
 #
-
-PURGATORY_S_SRCS+=
+PCFLAGS		+= -ffixed-r28
+PURGATORY_S_SRCS+= purgatory/arch/ia64/entry.S
 PURGATORY_C_SRCS+= purgatory/arch/ia64/purgatory-ia64.c
 PURGATORY_C_SRCS+= purgatory/arch/ia64/console-ia64.c
 PURGATORY_C_SRCS+=
diff -urNp kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c kexec-tools-1.101-ia64/purgatory/arch/ia64/purgatory-ia64.c
--- kexec-tools-1.101/purgatory/arch/ia64/purgatory-ia64.c	2006-04-06 14:07:58.000000000 -0600
+++ kexec-tools-1.101-ia64/purgatory/arch/ia64/purgatory-ia64.c	2006-04-06 12:55:01.000000000 -0600
@@ -1,10 +1,116 @@
 #include <purgatory.h>
+#include <stdint.h>
+#include <string.h>
 #include "purgatory-ia64.h"
 
+#define PAGE_OFFSET             0xe000000000000000
+
+typedef struct {
+        uint64_t signature;
+        uint32_t revision;
+        uint32_t headersize;
+        uint32_t crc32;
+        uint32_t reserved;
+} efi_table_hdr_t;
+
+typedef struct {
+        efi_table_hdr_t hdr;
+        unsigned long get_time;
+        unsigned long set_time;
+        unsigned long get_wakeup_time;
+        unsigned long set_wakeup_time;
+        unsigned long set_virtual_address_map;
+        unsigned long convert_pointer;
+        unsigned long get_variable;
+        unsigned long get_next_variable;
+        unsigned long set_variable;
+        unsigned long get_next_high_mono_count;
+        unsigned long reset_system;
+} efi_runtime_services_t;
+
+typedef struct {
+        efi_table_hdr_t hdr;
+        unsigned long fw_vendor;        /* physical addr of CHAR16 vendor string
+ */
+        uint32_t fw_revision;
+        unsigned long con_in_handle;
+        unsigned long con_in;
+        unsigned long con_out_handle;
+        unsigned long con_out;
+        unsigned long stderr_handle;
+        unsigned long stderr;
+        unsigned long runtime;
+        unsigned long boottime;
+        unsigned long nr_tables;
+        unsigned long tables;
+} efi_system_table_t;
+
+struct ia64_boot_param {
+        uint64_t command_line;             /* physical address of command line arguments */
+        uint64_t efi_systab;               /* physical address of EFI system table */
+        uint64_t efi_memmap;               /* physical address of EFI memory map */
+        uint64_t efi_memmap_size;          /* size of EFI memory map */
+        uint64_t efi_memdesc_size;         /* size of an EFI memory map descriptor */
+        uint32_t efi_memdesc_version;      /* memory descriptor version */
+        struct {
+                uint16_t num_cols; /* number of columns on console output device */
+                uint16_t num_rows; /* number of rows on console output device */
+                uint16_t orig_x;   /* cursor's x position */
+                uint16_t orig_y;   /* cursor's y position */
+        } console_info;
+        uint64_t fpswa;            /* physical address of the fpswa interface */
+        uint64_t initrd_start;
+        uint64_t initrd_size;
+};
+
 void setup_arch(void)
 {
 	/* Nothing for now */
 }
+inline unsigned long PA(unsigned long addr)
+{
+	return addr - PAGE_OFFSET;
+}
+
+void flush_icache_range(char *start, unsigned long len)
+{
+	unsigned long i;
+	for (i = 0;i < len; i += 32)
+	  asm volatile("fc.i %0"::"r"(start+i):"memory");
+	asm volatile (";;sync.i;;":::"memory");
+	asm volatile ("srlz.i":::"memory");
+}
+
+extern char __dummy_efi_function[], __dummy_efi_function_end[];
+
+void ia64_env_setup(struct ia64_boot_param *boot_param,
+	uint64_t command_line, uint64_t command_line_len,
+	uint64_t ramdisk_base, uint64_t ramdisk_size)
+{
+	unsigned long len;
+        efi_system_table_t *systab;
+        efi_runtime_services_t *runtime;
+	unsigned long *set_virtual_address_map;
+
+	// patch efi_runtime->set_virtual_address_map to a
+	// dummy function
+	len = __dummy_efi_function_end - __dummy_efi_function;
+	memcpy((char *)command_line + command_line_len, __dummy_efi_function,
+	len);
+	systab = (efi_system_table_t *)boot_param->efi_systab;
+	runtime = (efi_runtime_services_t *)PA(systab->runtime);
+	set_virtual_address_map =
+		(unsigned long *)PA(runtime->set_virtual_address_map);
+	*(set_virtual_address_map)=
+		(unsigned long)((char *)command_line + command_line_len);
+	flush_icache_range((char *)command_line+command_line_len, len);
+
+	boot_param->command_line = command_line;
+	boot_param->console_info.orig_x = 0;
+	boot_param->console_info.orig_y = 0;
+	boot_param->initrd_start = ramdisk_base;
+	boot_param->initrd_size =  ramdisk_size;
+}
 
 /* This function can be used to execute after the SHA256 verification. */
 void post_verification_setup_arch(void)



[Index of Archives]     [Netdev]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]     [Linux Media]

  Powered by Linux