diff -rNu kexec-tools-1.8/kexec/Makefile kexec-tools/kexec/Makefile
--- kexec-tools-1.8/kexec/Makefile	2002-11-17 20:10:08.000000000 +0000
+++ kexec-tools/kexec/Makefile	2003-03-11 16:12:24.000000000 +0000
@@ -4,8 +4,10 @@
 KEXEC_C_SRCS:= kexec/kexec.c kexec/kexec-syscall.c 
 KEXEC_S_SRCS:= 
 KEXEC_C_SRCS+= kexec/kexec-x86.c kexec/kexec-elf32-x86.c kexec/kexec-bzImage.c
+KEXEC_C_SRCS+= kexec/kexec-multiboot-x86.c
 KEXEC_C_SRCS+= kexec/ifdown.c
-KEXEC_S_SRCS+= kexec/x86-setup-32.S kexec/x86-setup-16.S kexec/x86-setup-16-debug.S
+KEXEC_S_SRCS+= kexec/x86-setup-32.S kexec/x86-setup-16.S 
+KEXEC_S_SRCS+= kexec/x86-setup-16-debug.S kexec/x86-reset-vga.S
 KEXEC_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(KEXEC_C_SRCS))
 KEXEC_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(KEXEC_C_SRCS))
 KEXEC_S_OBJS:= $(patsubst %.S, $(OBJDIR)/%.o, $(KEXEC_S_SRCS))
diff -rNu kexec-tools-1.8/kexec/kexec-multiboot-x86.c kexec-tools/kexec/kexec-multiboot-x86.c
--- kexec-tools-1.8/kexec/kexec-multiboot-x86.c	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools/kexec/kexec-multiboot-x86.c	2003-03-11 16:23:57.000000000 +0000
@@ -0,0 +1,570 @@
+/*
+ *  kexec-multiboot-x86.c
+ *
+ *  (partial) multiboot support for kexec.  Only supports ELF32 
+ *  kernels, and a subset of the multiboot info page options 
+ *  (i.e. enough to boot the Xen hypervisor).
+ * 
+ *  TODO:  
+ *    - smarter allocation of new segments
+ *    - proper support for the MULTIBOOT_VIDEO_MODE bit
+ *    - support for the MULTIBOOT_AOUT_KLUDGE bit
+ *
+ *
+ *  Copyright (C) 2003  Tim Deegan (tjd21@cl.cam.ac.uk)
+ * 
+ *  Parts based on GNU GRUB, Copyright (C) 2000  Free Software Foundation, Inc
+ *  Parts copied from kexec-elf32-x86.c, written by Eric Biederman
+ *
+ *  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; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA
+ *  02111-1307, USA.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <elf.h>
+#include <boot/elf_boot.h>
+#include <asm/page.h>
+#include <ip_checksum.h>
+#include "kexec.h"
+#include "kexec-x86.h"
+
+/* From GNU GRUB */
+#include "mb_header.h"
+#include "mb_info.h"
+
+/* Static storage */
+static char headerbuf[MULTIBOOT_SEARCH];
+static struct multiboot_header *mbh = NULL;
+
+/* Magic for resetting VGA cards to text mode 3 */
+extern unsigned char x86_reset_vga[];
+extern unsigned char x86_reset_vga_end[];
+
+#define BOOTLOADER "kexec"
+#define BOOTLOADER_VERSION VERSION
+#define VGA_RESET_SIZE (x86_reset_vga_end - x86_reset_vga)
+#define SETUP_SPACE ((VGA_RESET_SIZE + setup32_size + 3) & ~3)
+#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
+
+
+int multiboot_x86_probe(FILE *file)
+/* Is it a good idea to try booting this file? */
+{
+	int i, len;
+	/* First of all, check that this is an ELF file */
+	if ((i=elf32_x86_probe(file)) <= 0) {
+		return i;
+	}
+	/* Now look for a multiboot header in the first 8KB */
+	if (fseek(file, 0, SEEK_SET) < 0) {
+		fprintf(stderr, "seek error: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	if ((len = fread(headerbuf, 1, MULTIBOOT_SEARCH, file))
+	    < MULTIBOOT_SEARCH)
+	{
+		if (feof(file))   /* Short file */
+		{
+			if (len < 12)  return 0; 
+		} else {
+			fprintf(stderr, "read error: %s\n",
+				strerror(errno));
+			return -1;
+		}
+        }
+	for (i = 0; i <= (len - 12); i += 4)
+	{
+		/* Search for a multiboot header */
+		mbh = (struct multiboot_header *)(headerbuf + i);
+		if (mbh->magic != MULTIBOOT_MAGIC 
+		    || ((mbh->magic+mbh->flags+mbh->checksum) & 0xffffffff))
+		{
+			/* Not a multiboot header */
+			continue;
+		}
+		if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) {
+			/* Requires options we don't support */
+			fprintf(stderr, 
+				"Found a multiboot header, but it uses "
+				"a non-ELF header layout,\n"
+				"and I can't do that (yet).  Sorry.\n");
+			return -1;
+		} 
+		if (mbh->flags & MULTIBOOT_UNSUPPORTED) {
+			/* Requires options we don't support */
+			fprintf(stderr, 
+				"Found a multiboot header, but it "
+				"requires multiboot options that I\n"
+				"don't understand.  Sorry.\n");
+			return -1;
+		} 
+		if (mbh->flags & MULTIBOOT_VIDEO_MODE) { 
+			/* Asked for screen mode information */
+			/* XXX carry on regardless */
+			fprintf(stderr, 
+				"BEWARE!  Found a multiboot header which asks "
+				"for screen mode information.\n"
+				"BEWARE!  I am NOT supplying screen mode "
+                                "information, but loading it regardless.\n");
+			
+		}
+		/* Bootable */
+		return 1;
+	}
+	/* Not multiboot */
+	return 0;
+}
+
+
+void multiboot_x86_usage(void)
+/* Multiboot-specific options */
+{
+	printf("    --command-line=STRING        Set the kernel command line to STRING.\n");
+	printf("    --module=\"MOD arg1 arg2...\"  Load module MOD with command-line \"arg1...\"\n");
+	printf("                                 (can be used multiple times).\n");
+	printf("    --reset-vga                  Include code to set VGA text mode 3.\n");
+	printf("                                 (use this flag at load time).\n");
+}
+
+
+static unsigned long locate_seg(struct kexec_segment *segment, 
+				int nr_segments,
+				size_t size,
+				unsigned long align_mask)
+/* Find somewhere to put this segment 
+ * Only call this if you know the highest segment is last in the list */
+{
+	struct kexec_segment s;
+
+	s.mem = segment[nr_segments-1].mem + segment[nr_segments-1].memsz;
+	s.mem = (void *)(((unsigned long)s.mem + align_mask) & ~align_mask);
+	s.memsz = size;
+	if (valid_memory_range(&s)) {
+		fprintf(stderr, "Bad place for a segment: %#lx + %#lx\n", 
+			(unsigned long) s.mem, (unsigned long) s.memsz);
+		return 0;
+	} else {
+		return (unsigned long)s.mem;
+	}
+}
+
+
+int multiboot_x86_load(FILE *file, int argc, char **argv,
+			void **ret_entry, struct kexec_segment **ret_segments,
+			int *ret_nr_segments)
+/* Marshal up a multiboot-style kernel */
+{
+	struct multiboot_info *mbi;
+	void   *mbi_buf;
+	struct mod_list *modp;
+	struct kexec_segment *segment;
+	int nr_segments;
+	unsigned long freespace;
+	unsigned long long mem_lower = 0, mem_upper = 0;
+	Elf32_Ehdr *ehdr;
+	Elf32_Phdr *phdr;
+	size_t mbi_bytes, mbi_offset;
+	const char *command_line=NULL;
+	char *imagename, *cp;
+	struct memory_range *range;
+	int ranges;
+	struct AddrRangeDesc *mmap;
+	int command_line_len;
+	int i;
+	int opt;
+	int modules, mod_command_line_space;
+	int extras;
+	int frob_vga;
+#define OPT_CL  	OPT_MAX+0
+#define OPT_MOD 	OPT_MAX+1
+#define OPT_VGA 	OPT_MAX+2
+	static const struct option options[] = {
+		KEXEC_OPTIONS
+		{ "command-line",		1, 0, OPT_CL },
+		{ "append",			1, 0, OPT_CL },
+		{ "module",			1, 0, OPT_MOD },
+		{ "reset-vga",			0, 0, OPT_VGA },
+		{ 0, 				0, 0, 0 },
+	};
+	static const char short_options[] = KEXEC_OPT_STR "";
+	
+	/* Probe for the MB header if it's not already found */
+	if (mbh == NULL && multiboot_x86_probe(file) != 1) 
+	{
+		fprintf(stderr, "Cannot find a loadable multiboot header.\n");
+		return -1;
+	}
+
+	
+	/* Parse the command line */
+	command_line = "";
+	command_line_len = 0;
+	modules = 0;
+	mod_command_line_space = 0;
+	frob_vga = 0;
+	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1)
+	{
+		switch(opt) {
+		default:
+			/* Ignore core options */
+			if (opt < OPT_MAX) {
+				break;
+			}
+		case '?':
+			usage();
+			return -1;
+		case OPT_CL:
+			command_line = optarg;
+			break;
+		case OPT_MOD:
+			modules++;
+			mod_command_line_space += strlen(optarg) + 1;
+			break;
+		case OPT_VGA:
+		        frob_vga = 1;
+			break;
+		}
+	}
+	imagename = argv[optind];
+	command_line_len = strlen(command_line) + strlen(imagename) + 2;
+	
+	/* Find the ELF headers at the start of the file */
+	ehdr = (Elf32_Ehdr *)headerbuf;
+	phdr = (Elf32_Phdr *)(headerbuf + ehdr->e_phoff);
+	if (ehdr->e_phoff + ehdr->e_phnum*sizeof(*phdr) > sizeof(headerbuf)) {
+		/* Don't expect this will happen with sane kernels */
+		fprintf(stderr, "too much ELF for me. \n");
+		return -1;		
+	}
+
+	/* We'll need segments for the kernel, modules and other bits */
+	extras = 1; 
+	/* if (mbh->flags & MULTIBOOT_VIDEO_MODE) extras++;  */
+	if (mbh->flags & MULTIBOOT_MEMORY_INFO) extras++; 
+	segment = malloc(sizeof(*segment)*(ehdr->e_phnum + modules + extras));
+	if (segment == 0) {
+		fprintf(stderr, "malloc failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	/* The first segment will contain the multiboot headers:
+	 * =============
+	 * VGA reset code 
+	 * -------------
+	 * 32-bit CPU setup code
+	 * -------------
+	 * multiboot information (mbi)
+	 * -------------
+	 * kernel command line
+	 * -------------
+	 * bootloader name
+	 * -------------
+	 * module information entries
+	 * -------------
+	 * module command lines
+	 * ==============
+	 */
+	mbi_bytes = (SETUP_SPACE + sizeof(*mbi) + command_line_len 
+		     + strlen (BOOTLOADER " " BOOTLOADER_VERSION) + 1
+		     + 3) & ~3;
+	mbi_buf = malloc(mbi_bytes);
+	if (mbi_buf == NULL) {
+		fprintf(stderr, "malloc failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	mbi = mbi_buf + SETUP_SPACE;
+	memset(mbi, 0, sizeof(*mbi));
+	sprintf(((char *)mbi) + sizeof(*mbi), "%s %s",
+		imagename, command_line);
+	sprintf(((char *)mbi) + sizeof(*mbi) + command_line_len, "%s",
+		BOOTLOADER " " BOOTLOADER_VERSION);
+	mbi->flags = MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME;
+	/* We'll relocate these to absolute addresses later. For now,
+	 * all addresses within the first segment are relative to the
+	 * start of the MBI. */
+	mbi->cmdline = sizeof(*mbi); 
+	mbi->boot_loader_name = sizeof(*mbi) + command_line_len; 
+	/* Sort these out later when we know where it's going */
+	segment[0].buf = 0;
+	segment[0].bufsz = 0;
+	segment[0].mem = 0; 
+	segment[0].memsz = 0;
+	nr_segments=1;
+
+
+	/* Load all the rest of the kernel segments (using the ELF headers) */
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		char *buf;
+		size_t size;
+		size = phdr[i].p_filesz;
+		if (size > phdr[i].p_memsz) {
+			size = phdr[i].p_memsz;
+		}
+		buf = malloc(size);
+		if (buf == 0) {
+			fprintf(stderr, "malloc failed: %s\n",
+				strerror(errno));
+			return -1;
+		}
+		segment[nr_segments].buf = buf;
+		segment[nr_segments].bufsz = size;
+		segment[nr_segments].mem = (void *)phdr[i].p_paddr;
+		segment[nr_segments].memsz = phdr[i].p_memsz;
+		if (valid_memory_range(segment + nr_segments) < 0) {
+			fprintf(stderr, "Invalid memory segment %p - %p\n",
+				segment[nr_segments].mem,
+				((char*)segment[nr_segments].mem) + segment[nr_segments].memsz);
+			return -1;
+		}
+		nr_segments++;
+		if (size == 0 || phdr[i].p_type != PT_LOAD) {
+			/* Don't do file I/O if there is nothing in the file */
+			continue;
+		}
+		if (fseek(file, phdr[i].p_offset, SEEK_SET) != 0) {
+			fprintf(stderr, "seek failed: %s\n",
+				strerror(errno));
+			return -1;
+		}
+		if (fread(buf, size, 1, file) != 1) {
+			fprintf(stderr, "Read failed: %s\n",
+				strerror(errno));
+			return -1;
+		}
+	}
+	
+	/* Make it easy to find space for the next segment */
+	if (sort_segments(segment, nr_segments) < 0) {
+		return -1;
+	}
+
+
+	/* Memory map */
+	if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
+		fprintf(stderr, "Cannot get memory information\n");
+		return -1;
+	}
+	if ((mmap = malloc(ranges * sizeof(*mmap))) == NULL) {
+		fprintf(stderr, "malloc failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+	for (i=0; i<ranges; i++) {
+		/* Translate bzImage mmap to multiboot-speak */
+		mmap[i].size = sizeof(mmap[i]) - 4;
+		mmap[i].BaseAddr = range[i].start;
+		mmap[i].Length = range[i].end - range[i].start;
+		if (range[i].type == RANGE_RAM) {
+			mmap[i].Type = 1; /* RAM */
+			/* Is this the "low" memory? */
+			if ((range[i].start == 0)
+			    && (range[i].end > mem_lower))
+				mem_lower = range[i].end;
+			/* Is this the "high" memory? */
+			if ((range[i].start <= 0x100000)
+			    && (range[i].end > mem_upper + 0x100000))
+				mem_upper = range[i].end - 0x100000;
+		}
+		else
+		mmap[i].Type = 0xbad;  /* Not RAM */
+	}
+
+
+	if (mbh->flags & MULTIBOOT_MEMORY_INFO) { 
+		/* Provide a copy of the memory map to the kernel */
+
+		mbi->flags |= MB_INFO_MEMORY | MB_INFO_MEM_MAP;
+		freespace = locate_seg(segment, nr_segments, 
+				       ranges * sizeof(*mmap), 3);
+		if (!freespace) {
+			fprintf(stderr, "Cannot find space for new segment\n");
+			return -1;
+		}
+
+		segment[nr_segments].buf   = mmap;
+		segment[nr_segments].bufsz = ranges * sizeof(*mmap);
+		segment[nr_segments].mem   = (void *)freespace;
+		segment[nr_segments].memsz = ranges * sizeof(*mmap);
+		mbi->mmap_addr   = freespace;
+		mbi->mmap_length = ranges * sizeof(*mmap);
+
+		/* For kernels that care naught for fancy memory maps
+		 * and just want the size of low and high memory */
+		mbi->mem_lower = MIN(mem_lower>>10, 0xffffffff);
+		mbi->mem_upper = MIN(mem_upper>>10, 0xffffffff);
+			
+		/* done */
+		nr_segments++;
+	}
+
+
+	/* Load modules */
+	if (modules) {
+		char *mod_filename, *mod_command_line, *mod_clp, *buf;
+		FILE *mod_file;
+		struct stat sb;
+
+		/* We'll relocate this to an absolute address later */
+		mbi->mods_addr = (mbi_bytes - SETUP_SPACE);
+		mbi->mods_count = 0;
+		mbi->flags |= MB_INFO_MODS;
+		
+		/* Add room for the module descriptors to the MBI buffer */
+		mbi_bytes += (sizeof(*modp) * modules)
+			+ mod_command_line_space;
+		if ((mbi_buf = realloc(mbi_buf, mbi_bytes)) == NULL) {
+			fprintf(stderr, "realloc failed: %s\n",
+				strerror(errno));
+			return -1;
+		}
+
+		/* mbi might have moved */
+		mbi = mbi_buf + SETUP_SPACE;
+		/* module descriptors go in the newly added space */
+		modp = ((void *)mbi) + mbi->mods_addr; 
+		/* module command lines go after the descriptors */
+		mod_clp = ((void *)modp) + (sizeof(*modp) * modules);
+		
+		/* Go back and parse the module command lines */
+		optind = opterr = 1;
+		while((opt = getopt_long(argc, argv, 
+					 short_options, options, 0)) != -1)
+		{
+			if (opt != OPT_MOD) continue;
+
+			/* Split module filename from command line */
+			mod_command_line = mod_filename = optarg;
+			if ((cp = strchr(mod_filename, ' ')) != NULL) {
+				/* See as I discard the 'const' modifier */
+				*cp = '\0';
+			}
+
+			/* Load the module */
+			if (stat(mod_filename, &sb) != 0) {
+				fprintf(stderr, "Cannot stat %s: %s\n",
+					mod_filename, strerror(errno));
+				return -1;
+			}
+			if ((buf = malloc(sb.st_size)) == NULL) {
+				fprintf(stderr, "malloc failed: %s\n",
+			        strerror(errno));
+				return -1;
+			}
+			if ((mod_file = fopen(mod_filename, "rb")) == NULL) {
+				fprintf(stderr, "Cannot open %s: %s\n",
+					mod_filename, strerror(errno));
+				return -1;
+			}
+			if ((fread(buf, sb.st_size, 1, mod_file)) != 1) { 
+				fprintf(stderr, "Cannot read %s: %s\n",
+					mod_filename, strerror(errno));
+				return -1;
+			}
+			fclose(mod_file);
+			
+			if (cp != NULL) *cp = ' ';
+
+			/* Pick the next aligned spot to load it in */
+			freespace = locate_seg(segment, 
+					       nr_segments,sb.st_size, 
+					       (PAGE_SIZE-1));
+			/* XXX That should be 
+			 * (mbh->flags&MULTIBOOT_PAGE_ALIGN)?(PAGE_SIZE-1):3)
+			 * but for now, forcing page-align makes Xen boot... */
+			        
+			if (!freespace) {
+				fprintf(stderr, 
+					"Cannot find space for new segment\n");
+				return -1;
+			}
+
+			/* Add the module command line */
+			sprintf(mod_clp, "%s", mod_command_line);
+
+			/* Record the module location */
+			segment[nr_segments].buf   = buf;
+			segment[nr_segments].bufsz = sb.st_size;
+			segment[nr_segments].mem   = (void *)freespace;
+			segment[nr_segments].memsz = sb.st_size;
+			modp->mod_start = freespace;
+			modp->mod_end   = freespace + sb.st_size;
+			modp->cmdline   = (void *)mod_clp - (void *)mbi;
+			modp->pad       = 0;
+
+			/* Done */
+			nr_segments++;
+			mbi->mods_count++;
+			mod_clp += strlen(mod_clp) + 1;
+			modp++;
+		}
+		
+	}
+
+
+	/* Find a place for the MBI to live */
+	if (sort_segments(segment, nr_segments) < 0) {
+                return -1;
+        }
+	segment[0].buf = mbi_buf;
+	segment[0].bufsz = mbi_bytes;
+	segment[0].mem = 0;
+	segment[0].memsz = mbi_bytes;
+	if (locate_arguments(segment, nr_segments, 4, 0xFFFFFFFFUL) < 0) {
+		return -1;
+	}
+
+	/* Relocate offsets in the MBI to absolute addresses */
+	mbi_offset = (unsigned long)segment[0].mem + SETUP_SPACE;
+	modp = ((void *)mbi) + mbi->mods_addr;
+	for (i=0; i<mbi->mods_count; i++) {
+		modp[i].cmdline += mbi_offset;
+	}
+	mbi->mods_addr += mbi_offset;
+	mbi->cmdline += mbi_offset;
+	mbi->boot_loader_name += mbi_offset;
+
+	/* Specify the initial CPU state and copy the setup code */
+	memset(&setup32_regs, 0, sizeof(setup32_regs));
+	setup32_regs.eax = 0x2BADB002;
+	setup32_regs.ebx = mbi_offset;
+	setup32_regs.eip = ehdr->e_entry;
+	memcpy(mbi_buf, x86_reset_vga, VGA_RESET_SIZE);
+	memcpy(mbi_buf + VGA_RESET_SIZE, setup32_start, setup32_size);
+
+	/* Done */
+	*ret_entry = frob_vga ? segment[0].mem : segment[0].mem+VGA_RESET_SIZE;
+	*ret_segments = segment;
+	*ret_nr_segments = nr_segments;
+	return 0;
+}
+
+/*
+ *  EOF (kexec-multiboot-x86.c)
+ */
+
diff -rNu kexec-tools-1.8/kexec/kexec-x86.c kexec-tools/kexec/kexec-x86.c
--- kexec-tools-1.8/kexec/kexec-x86.c	2002-12-02 03:49:30.000000000 +0000
+++ kexec-tools/kexec/kexec-x86.c	2003-03-02 20:22:21.000000000 +0000
@@ -72,6 +72,8 @@
 }
 
 struct file_type file_type[] = {
+	{ "multiboot-x86", multiboot_x86_probe, multiboot_x86_load, 
+	  multiboot_x86_usage },
 	{ "elf32-x86", elf32_x86_probe, elf32_x86_load, elf32_x86_usage },
 	{ "bzImage", bzImage_probe, bzImage_load, bzImage_usage },
 };
diff -rNu kexec-tools-1.8/kexec/kexec-x86.h kexec-tools/kexec/kexec-x86.h
--- kexec-tools-1.8/kexec/kexec-x86.h	2002-12-02 02:45:36.000000000 +0000
+++ kexec-tools/kexec/kexec-x86.h	2003-03-02 20:22:07.000000000 +0000
@@ -39,6 +39,12 @@
 	uint16_t cs;
 } setup16_regs, setup16_debug_regs;
 
+
+int multiboot_x86_probe(FILE *file);
+int multiboot_x86_load(FILE *file, int argc, char **argv,
+	void **ret_entry, struct kexec_segment **ret_segments, int *ret_nr_segments);
+void multiboot_x86_usage(void);
+
 int elf32_x86_probe(FILE *file);
 int elf32_x86_load(FILE *file, int argc, char **argv,
 	void **ret_entry, struct kexec_segment **ret_segments, int *ret_nr_segments);
diff -rNu kexec-tools-1.8/kexec/kexec.c kexec-tools/kexec/kexec.c
--- kexec-tools-1.8/kexec/kexec.c	2002-12-02 03:40:08.000000000 +0000
+++ kexec-tools/kexec/kexec.c	2003-03-11 16:03:59.000000000 +0000
@@ -7,6 +7,9 @@
 #include <getopt.h>
 #include "kexec.h"
 
+#ifndef MAX
+#define MAX(_x,_y) (((_x)>=(_y))?(_x):(_y))
+#endif
 
 /* local variables */
 static struct memory_range *memory_range;
@@ -72,6 +75,7 @@
 	int i, j;
 	struct memory_range *mem_range;
 	int max_mem_ranges, mem_ranges;
+	unsigned long start = 0, size;
 
 	/* Compute the free memory ranges */
 	max_mem_ranges = memory_ranges + (segments -1);
@@ -107,8 +111,7 @@
 	}
 	/* Now find the first memory_range I can use */
 	for(i = 0; i < mem_ranges; i++) {
-		unsigned long start, size;
-		start = (mem_range[i].start + align -1) & ~(align -1);
+		start = (MAX(mem_range[i].start,0x100) +align-1) & ~(align-1);
 		size = mem_range[i].end - start;
 		if (size >= segment[0].memsz) {
 			break;
@@ -123,7 +126,7 @@
 			max);
 		return -1;
 	}
-	segment[0].mem = (void *)(unsigned long)((mem_range[i].start + align - 1) & ~(align -1));
+	segment[0].mem = (void *)start;
 	return 0;
 }
 
@@ -134,7 +137,7 @@
 {
 	char *kernel;
 	FILE *fp_kernel;
-	int i;
+	int i, ft;
 	int result;
 	struct kexec_segment *segments;
 	int nr_segments;
@@ -157,20 +160,24 @@
 		fprintf(stderr, "Could not get memory layout\n");
 		return -1;
 	}
-	for(i = 0; i < file_types; i++) {
-		if (type && (strcmp(type, file_type[i].name) != 0)) {
+	for(ft = 0; ft < file_types; ft++) {
+		if (type && (strcmp(type, file_type[ft].name) == 0)) {
 			break;
 		}
-		if (file_type[i].probe(fp_kernel) > 0) {
-			break;
+		if (!type) {
+		        result = file_type[ft].probe(fp_kernel);
+		        if (result < 0) 
+				return result;
+			if (result > 0)
+				break;			
 		}
 	}
-	if (i == file_types) {
+	if (ft == file_types) {
 		fprintf(stderr, "Can not determine the file type of %s\n",
 			kernel);
 		return -1;
 	}
-	if (file_type[i].load(fp_kernel, argc, argv,
+	if (file_type[ft].load(fp_kernel, argc, argv,
 		    &entry, &segments, &nr_segments) < 0) {
 		fprintf(stderr, "Can not load %s\n", kernel);
 		return -1;
@@ -193,14 +200,17 @@
 		/* The load failed, print some debugging information */
 		fprintf(stderr, "kexec_load failed: %s\n",
 			strerror(errno));
-		fprintf(stderr, "entry       = %p\n", entry);
-		fprintf(stderr, "nr_segments = %d\n", nr_segments);
-		for(i = 0; i < nr_segments; i++) {
-			fprintf(stderr, "segment[%d].buf   = %p\n", i, segments[i].buf);
-			fprintf(stderr, "segment[%d].bufsz = %x\n", i, segments[i].bufsz);
-			fprintf(stderr, "segment[%d].mem   = %p\n", i, segments[i].mem);
-			fprintf(stderr, "segment[%d].memsz = %x\n", i, segments[i].memsz);
-		}
+	} else {
+		fprintf(stderr, "kexec_load succeeded (%s)\n",
+			file_type[ft].name);
+	}
+	fprintf(stderr, "entry       = %p\n", entry);
+	fprintf(stderr, "nr_segments = %d\n", nr_segments);
+	for(i = 0; i < nr_segments; i++) {
+	    fprintf(stderr, "segment[%d].buf   = %p\n", i, segments[i].buf);
+	    fprintf(stderr, "segment[%d].bufsz = %x\n", i, segments[i].bufsz);
+	    fprintf(stderr, "segment[%d].mem   = %p\n", i, segments[i].mem);
+	    fprintf(stderr, "segment[%d].memsz = %x\n", i, segments[i].memsz);
 	}
 	return result;
 }
diff -rNu kexec-tools-1.8/kexec/mb_header.h kexec-tools/kexec/mb_header.h
--- kexec-tools-1.8/kexec/mb_header.h	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools/kexec/mb_header.h	2003-03-02 15:44:13.000000000 +0000
@@ -0,0 +1,90 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000   Free Software Foundation, Inc.
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ */
+
+/*
+ *  MultiBoot Header description
+ */
+
+struct multiboot_header
+{
+  /* Must be MULTIBOOT_MAGIC - see below.  */
+  unsigned magic;
+  
+  /* Feature flags - see below.  */
+  unsigned flags;
+  
+  /*
+   * Checksum
+   *
+   * The above fields plus this one must equal 0 mod 2^32.
+   */
+  unsigned checksum;
+  
+  /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set.  */
+  unsigned header_addr;
+  unsigned load_addr;
+  unsigned load_end_addr;
+  unsigned bss_end_addr;
+  unsigned entry_addr;
+
+  /* These are only valid if MULTIBOOT_VIDEO_MODE is set.  */
+  unsigned mode_type;
+  unsigned width;
+  unsigned height;
+  unsigned depth;
+};
+
+/*
+ * The entire multiboot_header must be contained
+ * within the first MULTIBOOT_SEARCH bytes of the kernel image.
+ */
+#define MULTIBOOT_SEARCH		8192
+#define MULTIBOOT_FOUND(addr, len) \
+  (! ((addr) & 0x3) \
+   && (len) >= 12 \
+   && *((int *) (addr)) == MULTIBOOT_MAGIC \
+   && ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \
+	 + *((unsigned *) (addr + 8))) \
+   && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \
+   && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48))
+
+/* Magic value identifying the multiboot_header.  */
+#define MULTIBOOT_MAGIC			0x1BADB002
+
+/*
+ * Features flags for 'flags'.
+ * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set
+ * and it doesn't understand it, it must fail.
+ */
+#define MULTIBOOT_MUSTKNOW		0x0000FFFF
+
+/* currently unsupported flags...  this is a kind of version number.  */
+#define MULTIBOOT_UNSUPPORTED		0x0000FFF8
+
+/* Align all boot modules on i386 page (4KB) boundaries.  */
+#define MULTIBOOT_PAGE_ALIGN		0x00000001
+
+/* Must pass memory information to OS.  */
+#define MULTIBOOT_MEMORY_INFO		0x00000002
+
+/* Must pass video information to OS.  */
+#define MULTIBOOT_VIDEO_MODE		0x00000004
+
+/* This flag indicates the use of the address fields in the header.  */
+#define MULTIBOOT_AOUT_KLUDGE		0x00010000
diff -rNu kexec-tools-1.8/kexec/mb_info.h kexec-tools/kexec/mb_info.h
--- kexec-tools-1.8/kexec/mb_info.h	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools/kexec/mb_info.h	2003-03-02 16:40:30.000000000 +0000
@@ -0,0 +1,217 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000  Free Software Foundation, Inc.
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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.
+ */
+
+/*
+ *  The structure type "mod_list" is used by the "multiboot_info" structure.
+ */
+
+struct mod_list
+{
+  /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+  unsigned long mod_start;
+  unsigned long mod_end;
+  
+  /* Module command line */
+  unsigned long cmdline;
+  
+  /* padding to take it to 16 bytes (must be zero) */
+  unsigned long pad;
+};
+
+
+/*
+ *  INT-15, AX=E820 style "AddressRangeDescriptor"
+ *  ...with a "size" parameter on the front which is the structure size - 4,
+ *  pointing to the next one, up until the full buffer length of the memory
+ *  map has been reached.
+ */
+
+struct AddrRangeDesc
+{
+  unsigned long size;
+  unsigned long long BaseAddr;
+  unsigned long long Length;
+  unsigned long Type;
+  
+  /* unspecified optional padding... */
+};
+
+/* usable memory "Type", all others are reserved.  */
+#define MB_ARD_MEMORY		1
+
+
+/* Drive Info structure.  */
+struct drive_info
+{
+  /* The size of this structure.  */
+  unsigned long size;
+
+  /* The BIOS drive number.  */
+  unsigned char drive_number;
+
+  /* The access mode (see below).  */
+  unsigned char drive_mode;
+
+  /* The BIOS geometry.  */
+  unsigned short drive_cylinders;
+  unsigned char drive_heads;
+  unsigned char drive_sectors;
+
+  /* The array of I/O ports used for the drive.  */
+  unsigned short drive_ports[0];
+};
+
+/* Drive Mode.  */
+#define MB_DI_CHS_MODE		0
+#define MB_DI_LBA_MODE		1
+
+
+/* APM BIOS info.  */
+struct apm_info
+{
+  unsigned short version;
+  unsigned short cseg;
+  unsigned long offset;
+  unsigned short cseg_16;
+  unsigned short dseg_16;
+  unsigned short cseg_len;
+  unsigned short cseg_16_len;
+  unsigned short dseg_16_len;
+};
+
+
+/*
+ *  MultiBoot Info description
+ *
+ *  This is the struct passed to the boot image.  This is done by placing
+ *  its address in the EAX register.
+ */
+
+struct multiboot_info
+{
+  /* MultiBoot info version number */
+  unsigned long flags;
+  
+  /* Available memory from BIOS */
+  unsigned long mem_lower;
+  unsigned long mem_upper;
+  
+  /* "root" partition */
+  unsigned long boot_device;
+  
+  /* Kernel command line */
+  unsigned long cmdline;
+  
+  /* Boot-Module list */
+  unsigned long mods_count;
+  unsigned long mods_addr;
+  
+  union
+  {
+    struct
+    {
+      /* (a.out) Kernel symbol table info */
+      unsigned long tabsize;
+      unsigned long strsize;
+      unsigned long addr;
+      unsigned long pad;
+    }
+    a;
+    
+    struct
+    {
+      /* (ELF) Kernel section header table */
+      unsigned long num;
+      unsigned long size;
+      unsigned long addr;
+      unsigned long shndx;
+    }
+    e;
+  }
+  syms;
+  
+  /* Memory Mapping buffer */
+  unsigned long mmap_length;
+  unsigned long mmap_addr;
+  
+  /* Drive Info buffer */
+  unsigned long drives_length;
+  unsigned long drives_addr;
+  
+  /* ROM configuration table */
+  unsigned long config_table;
+  
+  /* Boot Loader Name */
+  unsigned long boot_loader_name;
+
+  /* APM table */
+  unsigned long apm_table;
+
+  /* Video */
+  unsigned long vbe_control_info;
+  unsigned long vbe_mode_info;
+  unsigned short vbe_mode;
+  unsigned short vbe_interface_seg;
+  unsigned short vbe_interface_off;
+  unsigned short vbe_interface_len;
+};
+
+/*
+ *  Flags to be set in the 'flags' parameter above
+ */
+
+/* is there basic lower/upper memory information? */
+#define MB_INFO_MEMORY			0x00000001
+/* is there a boot device set? */
+#define MB_INFO_BOOTDEV			0x00000002
+/* is the command-line defined? */
+#define MB_INFO_CMDLINE			0x00000004
+/* are there modules to do something with? */
+#define MB_INFO_MODS			0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MB_INFO_AOUT_SYMS		0x00000010
+/* is there an ELF section header table? */
+#define MB_INFO_ELF_SHDR		0x00000020
+
+/* is there a full memory map? */
+#define MB_INFO_MEM_MAP			0x00000040
+
+/* Is there drive info?  */
+#define MB_INFO_DRIVE_INFO		0x00000080
+
+/* Is there a config table?  */
+#define MB_INFO_CONFIG_TABLE		0x00000100
+
+/* Is there a boot loader name?  */
+#define MB_INFO_BOOT_LOADER_NAME	0x00000200
+
+/* Is there a APM table?  */
+#define MB_INFO_APM_TABLE		0x00000400
+
+/* Is there video information?  */
+#define MB_INFO_VIDEO_INFO		0x00000800
+
+/*
+ *  The following value must be present in the EAX register.
+ */
+
+#define MULTIBOOT_VALID			0x2BADB002
diff -rNu kexec-tools-1.8/kexec/x86-reset-vga.S kexec-tools/kexec/x86-reset-vga.S
--- kexec-tools-1.8/kexec/x86-reset-vga.S	1970-01-01 00:00:00.000000000 +0000
+++ kexec-tools/kexec/x86-reset-vga.S	2003-03-12 11:42:53.000000000 +0000
@@ -0,0 +1,260 @@
+/* Crudely reset a VGA card to text mode 3, by writing plausible default    */
+/* values into its registers.                                               */
+/* Tim Deegan (tjd21@cl.cam.ac.uk), March 2003                              */
+/* Based on Keir Fraser's start-of-day reset code from the Xen hypervisor   */
+	.code32
+	.globl x86_reset_vga, x86_reset_vga_end
+x86_reset_vga:
+	push %eax
+	push %edx
+	/* Hello */
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x00, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	/* Sequencer registers */
+	movw $0x3c4, %dx
+	movw $0x0300, %ax
+	outw %ax, %dx
+	movw $0x0001, %ax
+	outw %ax, %dx
+	movw $0x0302, %ax
+	outw %ax, %dx
+	movw $0x0003, %ax
+	outw %ax, %dx
+	movw $0x0204, %ax
+	outw %ax, %dx
+	/* Ensure CRTC regs 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+	movw $0x3d4, %dx
+	movw $0x0e11, %ax
+	outw %ax, %dx
+	/* CRTC registers */
+	movw $0x5f00, %ax
+	outw %ax, %dx
+	movw $0x4f01, %ax
+	outw %ax, %dx
+	movw $0x5002, %ax
+	outw %ax, %dx
+	movw $0x8203, %ax
+	outw %ax, %dx
+	movw $0x5504, %ax
+	outw %ax, %dx
+	movw $0x8105, %ax
+	outw %ax, %dx
+	movw $0xbf06, %ax
+	outw %ax, %dx
+	movw $0x1f07, %ax
+	outw %ax, %dx
+	movw $0x0008, %ax
+	outw %ax, %dx
+	movw $0x4f09, %ax
+	outw %ax, %dx
+	movw $0x200a, %ax
+	outw %ax, %dx
+	movw $0x0e0b, %ax
+	outw %ax, %dx
+	movw $0x000c, %ax
+	outw %ax, %dx
+	movw $0x000d, %ax
+	outw %ax, %dx
+	movw $0x010e, %ax
+	outw %ax, %dx
+	movw $0xe00f, %ax
+	outw %ax, %dx
+	movw $0x9c10, %ax
+	outw %ax, %dx
+	movw $0x8e11, %ax
+	outw %ax, %dx
+	movw $0x8f12, %ax
+	outw %ax, %dx
+	movw $0x2813, %ax
+	outw %ax, %dx
+	movw $0x1f14, %ax
+	outw %ax, %dx
+	movw $0x9615, %ax
+	outw %ax, %dx
+	movw $0xb916, %ax
+	outw %ax, %dx
+	movw $0xa317, %ax
+	outw %ax, %dx
+	movw $0xff18, %ax
+	outw %ax, %dx
+	/* Graphic registers */
+	movw $0x3ce, %dx
+	movw $0x0000, %ax
+	outw %ax, %dx
+	movw $0x0001, %ax
+	outw %ax, %dx
+	movw $0x0002, %ax
+	outw %ax, %dx
+	movw $0x0003, %ax
+	outw %ax, %dx
+	movw $0x0004, %ax
+	outw %ax, %dx
+	movw $0x1005, %ax
+	outw %ax, %dx
+	movw $0x0e06, %ax
+	outw %ax, %dx
+	movw $0x0007, %ax
+	outw %ax, %dx
+	movw $0xff08, %ax
+	outw %ax, %dx
+	/* Attribute registers */
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x00, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x00, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x01, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x01, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x02, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x02, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x03, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x03, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x04, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x04, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x05, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x05, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x06, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x14, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x07, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x07, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x08, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x38, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x09, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x39, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0a, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3a, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0b, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3b, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0c, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3c, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0d, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3d, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0e, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3e, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x0f, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x3f, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x10, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x0c, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x11, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x00, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x12, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x0f, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x13, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x08, %al
+	outb %al, %dx 
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x14, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	movb $0x00, %al
+	outb %al, %dx 
+	/* Goodbye */
+	movw $0x3da, %dx
+	inb %dx, %al
+	movb $0x20, %al
+	movw $0x3c0, %dx
+	outb %al, %dx
+	pop %edx
+	pop %eax
+	nop
+x86_reset_vga_end:	
