Blob Blame History Raw
--- kexec-tools-1.101/include/x86/x86-linux.h.orig	2007-01-05 13:28:08.000000000 -0500
+++ kexec-tools-1.101/include/x86/x86-linux.h	2007-01-05 13:24:49.000000000 -0500
@@ -141,7 +141,10 @@ struct x86_linux_param_header {
 	uint32_t high_filesz;			/* 0x254 */
 	uint8_t  reserved15[0x2d0 - 0x258];	/* 0x258 */
 #else
-	uint8_t  reserved15[0x2d0 - 0x230];	/* 0x230 */
+	/* 2.04+ */
+	uint32_t kernel_alignment;		/* 0x230 */
+	uint8_t  relocatable_kernel;		/* 0x234 */
+	uint8_t  reserved15[0x2d0 - 0x235];	/* 0x230 */
 #endif
 	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
 						/* 0x550 */
@@ -201,12 +204,15 @@ struct x86_linux_header {
 	uint32_t high_filesz;			/* 0x254 */
 	uint32_t tail[32*1024 - 0x258];		/* 0x258 */
 #else
-	uint8_t  tail[32*1024 - 0x230];		/* 0x230 */
+	uint32_t kernel_alignment;		/* 0x230 */
+	uint8_t  relocatable_kernel;		/* 0x234 */
+	uint8_t  tail[32*1024 - 0x235];		/* 0x230 */
 #endif
 } PACKED;
 
 #endif /* ASSEMBLY */
 
 #define DEFAULT_INITRD_ADDR_MAX 0x37FFFFFF
+#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
 
 #endif /* X86_LINUX_H */
--- kexec-tools-1.101/kexec/arch/i386/crashdump-x86.c.orig	2007-01-05 13:28:08.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/crashdump-x86.c	2007-01-05 13:27:53.000000000 -0500
@@ -680,7 +680,9 @@ int load_crashdump_segments(struct kexec
 	tmp = xmalloc(sz);
 	memset(tmp, 0, sz);
 	info->backup_start = add_buffer(info, tmp, sz, sz, align,
-				0, max_addr, 1);
+				0, max_addr, -1);
+	dfprintf(stdout, "Created backup segment at 0x%lx\n",
+				info->backup_start);
 	if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
 		return -1;
 
@@ -719,7 +721,8 @@ int load_crashdump_segments(struct kexec
 	 * This is a makeshift solution until it is fixed in kernel.
 	 */
 	elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
-							max_addr, 1);
+							max_addr, -1);
+	dfprintf(stdout, "Created elf header segment at 0x%lx\n", elfcorehdr);
 	if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
 		return -1;
 	cmdline_add_memmap(mod_cmdline, memmap_p);
--- kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c.orig	2007-01-05 13:28:08.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c	2007-01-05 13:24:49.000000000 -0500
@@ -59,6 +59,7 @@ void setup_linux_bootloader_parameters(
 	initrd_addr_max = DEFAULT_INITRD_ADDR_MAX;
 	if (real_mode->protocol_version >= 0x0203) {
 		initrd_addr_max = real_mode->initrd_addr_max;
+		dfprintf(stdout, "initrd_addr_max is 0x%lx\n", initrd_addr_max);
 	}
 
 	/* Load the initrd if we have one */
@@ -66,6 +67,8 @@ void setup_linux_bootloader_parameters(
 		initrd_base = add_buffer(info,
 			initrd_buf, initrd_size, initrd_size,
 			4096, INITRD_BASE, initrd_addr_max, -1);
+		dfprintf(stdout, "Loaded initrd at 0x%lx size 0x%lx\n",
+					initrd_base, initrd_size);
 	} else {
 		initrd_base = 0;
 		initrd_size = 0;
--- kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c.orig	2007-01-05 13:28:08.000000000 -0500
+++ kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c	2007-01-05 13:27:53.000000000 -0500
@@ -34,8 +34,10 @@
 #include <x86/x86-linux.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
+#include "../../kexec-syscall.h"
 #include "kexec-x86.h"
 #include "x86-linux-setup.h"
+#include "crashdump-x86.h"
 #include <arch/options.h>
 
 static const int probe_debug = 0;
@@ -109,6 +111,9 @@ int do_bzImage_load(struct kexec_info *i
 	unsigned long setup_base, setup_size;
 	struct entry32_regs regs32;
 	struct entry16_regs regs16;
+	unsigned int relocatable_kernel = 0;
+	unsigned long kernel32_load_addr;
+	char *modified_cmdline;
 
 	/*
 	 * Find out about the file I am about to load.
@@ -121,6 +126,7 @@ int do_bzImage_load(struct kexec_info *i
 	if (setup_sects == 0) {
 		setup_sects = 4;
 	}
+
 	kern16_size = (setup_sects +1) *512;
 	kernel_version = ((unsigned char *)&setup_header) + 512 + setup_header.kver_addr;
 	if (kernel_len < kern16_size) {
@@ -128,25 +134,88 @@ int do_bzImage_load(struct kexec_info *i
 		return -1;
 	}
 
+	if (setup_header.protocol_version >= 0x0205) {
+		relocatable_kernel = setup_header.relocatable_kernel;
+		dfprintf(stdout, "bzImage is relocatable\n");
+	}
+
+	/* Can't use bzImage for crash dump purposes with real mode entry */
+	if((info->kexec_flags & KEXEC_ON_CRASH) && real_mode_entry) {
+		fprintf(stderr, "Can't use bzImage for crash dump purposes"
+				" with real mode entry\n");
+		return -1;
+	}
+
+	if((info->kexec_flags & KEXEC_ON_CRASH) && !relocatable_kernel) {
+		fprintf(stderr, "BzImage is not relocatable. Can't be used"
+				" as capture kernel.\n");
+		return -1;
+	}
+
+	/* 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 (command_line) {
+			strncpy(modified_cmdline, command_line,
+					COMMAND_LINE_SIZE);
+			modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+		}
+
+		/* If panic kernel is being loaded, additional segments need
+		 * to be created. load_crashdump_segments will take care of
+		 * loading the segments as high in memory as possible, hence
+		 * in turn as away as possible from kernel to avoid being
+		 * stomped by the kernel.
+		 */
+		if (load_crashdump_segments(info, modified_cmdline, -1, 0) < 0)
+			return -1;
+
+		/* Use new command line buffer */
+		command_line = modified_cmdline;
+		command_line_len = strlen(command_line) +1;
+	}
+
 	/* Load the trampoline.  This must load at a higher address
 	 * the the argument/parameter segment or the kernel will stomp
 	 * it's gdt.
 	 */
-	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
-		0x3000, 640*1024, -1);
+
+	if (!real_mode_entry && relocatable_kernel)
+		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+					0x3000, -1, -1, 0);
+	else
+		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+					0x3000, 640*1024, -1, 0);
+	dfprintf(stdout, "Loaded purgatory at addr 0x%lx\n",
+			info->rhdr.rel_addr);
 
 	/* The argument/parameter segment */
 	setup_size = kern16_size + command_line_len;
 	real_mode = xmalloc(setup_size);
 	memcpy(real_mode, kernel, kern16_size);
-	if (real_mode->protocol_version >= 0x0200) {
+
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+		/* If using bzImage for capture kernel, then we will not be
+		 * executing real mode code. setup segment can be loaded
+		 * anywhere as we will be just reading command line.
+		 */
+		setup_base = add_buffer(info, real_mode, setup_size, setup_size,
+			16, 0x3000, -1, 1);
+	}
+	else if (real_mode->protocol_version >= 0x0200) {
 		/* Careful setup_base must be greater than 8K */
 		setup_base = add_buffer(info, real_mode, setup_size, setup_size,
-			16, 0x3000, 640*1024, -1);
+			16, 0x3000, 640*1024, 1);
 	} else {
 		add_segment(info, real_mode, setup_size, SETUP_BASE, setup_size);
 		setup_base = SETUP_BASE;
 	}
+	dfprintf(stdout, "Loaded real-mode code and command line at 0x%lx\n",
+			setup_base);
+
 	/* Verify purgatory loads higher than the parameters */
 	if (info->rhdr.rel_addr < setup_base) {
 		die("Could not put setup code above the kernel parameters\n");
@@ -154,9 +223,30 @@ int do_bzImage_load(struct kexec_info *i
 	
 	/* The main kernel segment */
 	size = kernel_len - kern16_size;
-	add_segment(info, kernel + kern16_size, size, KERN32_BASE,  size);
 
+	if (real_mode->protocol_version >=0x0205 && relocatable_kernel) {
+		/* Relocatable bzImage */
+		unsigned long kern_align = real_mode->kernel_alignment;
+		unsigned long kernel32_max_addr = DEFAULT_BZIMAGE_ADDR_MAX;
+
+		if (real_mode->protocol_version >= 0x0203) {
+			if (kernel32_max_addr > real_mode->initrd_addr_max)
+				kernel32_max_addr = real_mode->initrd_addr_max;
+		}
+
+		kernel32_load_addr = add_buffer(info, kernel + kern16_size,
+						size, size, kern_align,
+						0x100000, kernel32_max_addr,
+						1);
+	}
+	else {
+		kernel32_load_addr = KERN32_BASE;
+		add_segment(info, kernel + kern16_size, size,
+				kernel32_load_addr, size);
+	}
 		
+	dfprintf(stdout, "Loaded 32bit kernel at 0x%lx\n", kernel32_load_addr);
+
 	/* Tell the kernel what is going on */
 	setup_linux_bootloader_parameters(info, real_mode, setup_base,
 		kern16_size, command_line, command_line_len,
@@ -177,7 +267,7 @@ int do_bzImage_load(struct kexec_info *i
 	regs32.edi = 0; /* unused */
 	regs32.esp = elf_rel_get_addr(&info->rhdr, "stack_end"); /* stack, unused */
 	regs32.ebp = 0; /* unused */
-	regs32.eip = KERN32_BASE; /* kernel entry point */
+	regs32.eip = kernel32_load_addr; /* kernel entry point */
 
 	/*
 	 * Initialize the 16bit start information.
--- kexec-tools-1.101/kexec/kexec.h.orig	2007-01-05 13:28:08.000000000 -0500
+++ kexec-tools-1.101/kexec/kexec.h	2007-01-05 13:24:43.000000000 -0500
@@ -197,4 +197,11 @@ int arch_compat_trampoline(struct kexec_
 void arch_update_purgatory(struct kexec_info *info);
 
 #define MAX_LINE	160
+
+#ifdef DEBUG
+#define dfprintf(args...)	do {fprintf(args);} while(0)
+#else
+#define dfprintf(args...)	do { } while(0)
+#endif
+
 #endif /* KEXEC_H */