diff -uNr linux-2.5.7.boot.heap/Makefile linux-2.5.7.boot.build/Makefile
--- linux-2.5.7.boot.heap/Makefile	Fri Mar 29 11:14:12 2002
+++ linux-2.5.7.boot.build/Makefile	Fri Mar 29 11:50:17 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 7
-EXTRAVERSION = .boot.heap
+EXTRAVERSION = .boot.build
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -91,15 +91,6 @@
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
 	  -fomit-frame-pointer -fno-strict-aliasing -fno-common
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
-
-#
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-# This is i386 specific.
-#
-
-export ROOT_DEV = CURRENT
 
 #
 # If you want to preset the SVGA mode, uncomment the next line and
diff -uNr linux-2.5.7.boot.heap/arch/i386/boot/Makefile linux-2.5.7.boot.build/arch/i386/boot/Makefile
--- linux-2.5.7.boot.heap/arch/i386/boot/Makefile	Sun Aug  5 14:13:19 2001
+++ linux-2.5.7.boot.build/arch/i386/boot/Makefile	Fri Mar 29 11:53:02 2002
@@ -12,13 +12,11 @@
 		$(TOPDIR)/include/linux/autoconf.h \
 		$(TOPDIR)/include/asm/boot.h
 
-zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
-	$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
-	tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage
-
-bzImage: $(CONFIGURE) bbootsect bsetup compressed/bvmlinux tools/build
-	$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out
-	tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
+zImage: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux realmode compressed/vmlinux 
+	tools/build $(TOPDIR)/vmlinux realmode compressed/vmlinux zImage
+
+bzImage: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux brealmode compressed/bvmlinux 
+	tools/build -b $(TOPDIR)/vmlinux brealmode compressed/bvmlinux bzImage
 
 compressed/vmlinux: $(TOPDIR)/vmlinux
 	@$(MAKE) -C compressed vmlinux
@@ -42,46 +40,40 @@
 tools/build: tools/build.c
 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
 
-bootsect: bootsect.o
-	$(LD) -Ttext 0x0 -s --oformat binary -o $@ $<
-
 bootsect.o: bootsect.s
 	$(AS) -o $@ $<
 
 bootsect.s: bootsect.S Makefile $(BOOT_INCL)
 	$(CPP) $(CPPFLAGS) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
-bbootsect: bbootsect.o
-	$(LD) -Ttext 0x0 -s --oformat binary $< -o $@
-
 bbootsect.o: bbootsect.s
 	$(AS) -o $@ $<
 
 bbootsect.s: bootsect.S Makefile $(BOOT_INCL)
 	$(CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
-setup: setup.o
-	$(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $<
-
 setup.o: setup.s
 	$(AS) -o $@ $<
 
 setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
 	$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
-bsetup: bsetup.o
-	$(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $<
-
 bsetup.o: bsetup.s
 	$(AS) -o $@ $<
 
 bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
 	$(CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
+realmode: bootsect.o setup.o
+	$(LD) -T realmode.lds -s -o $@ $^
+
+brealmode: bbootsect.o bsetup.o
+	$(LD) -T realmode.lds -s -o $@ $^
+
 dep:
 
 clean:
 	rm -f tools/build
-	rm -f setup bootsect zImage compressed/vmlinux.out
-	rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
+	rm -f realmode zImage
+	rm -f brealmode bzImage
 	@$(MAKE) -C compressed clean
diff -uNr linux-2.5.7.boot.heap/arch/i386/boot/bootsect.S linux-2.5.7.boot.build/arch/i386/boot/bootsect.S
--- linux-2.5.7.boot.heap/arch/i386/boot/bootsect.S	Fri Mar 29 10:39:38 2002
+++ linux-2.5.7.boot.build/arch/i386/boot/bootsect.S	Fri Mar 29 12:00:42 2002
@@ -54,7 +54,7 @@
 #endif
 
 .code16
-.text
+.section ".bootsect", "ax", @progbits
 
 .global _start
 _start:
diff -uNr linux-2.5.7.boot.heap/arch/i386/boot/realmode.lds linux-2.5.7.boot.build/arch/i386/boot/realmode.lds
--- linux-2.5.7.boot.heap/arch/i386/boot/realmode.lds	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot.build/arch/i386/boot/realmode.lds	Fri Mar 29 11:54:36 2002
@@ -0,0 +1,17 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+ENTRY(_start)
+OUTPUT_ARCH(i386)
+SECTIONS
+{
+	. = 0x90000;
+	.bootsect : {
+		*(.bootsect)
+	}
+	. = 0x90200;
+	.setup : {
+		*(.setup)
+	}
+	/DISCARD/ : {
+		*(*)
+	}
+}
diff -uNr linux-2.5.7.boot.heap/arch/i386/boot/setup.S linux-2.5.7.boot.build/arch/i386/boot/setup.S
--- linux-2.5.7.boot.heap/arch/i386/boot/setup.S	Fri Mar 29 11:40:13 2002
+++ linux-2.5.7.boot.build/arch/i386/boot/setup.S	Fri Mar 29 12:00:25 2002
@@ -80,7 +80,7 @@
 .code16
 .globl _setup, _esetup
 
-.text
+.section ".bootsect", "ax", @progbits
 _setup:	
 
 start:
@@ -165,7 +165,18 @@
 					# the contents of an initrd
 
 # variables private to setup.S (not for bootloaders)
-real_filesz:	.long (_esetup - start) + (DELTA_INITSEG << 4)
+pad2:		.long 0
+low_base:	.long	LOW_BASE	# low buffer base 0x1000
+low_memsz:	.long	0x00000000	# Size of low buffer  @ 0x1000
+low_filesz:	.long	0x00000000	# Size of precomputed data @ 0x1000
+real_base:	.long	REAL_BASE	# Location of real mode kernel
+real_memsz:				# Memory usage of real mode kernel @ 0x90000
+		.long	(_esetup + MIN_HEAP_SIZE - start) + (DELTA_INITSEG << 4)
+real_filesz:				# Datasize of real mode kernel @ 0x90000
+		.long	(_esetup - start) + (DELTA_INITSEG << 4)
+high_base:	.long	HIGH_BASE	# high buffer base 0x100000
+high_memsz:	.long	0x00000000	# Size of high buffer @	0x100000
+high_filesz:	.long	0x00000000	# Datasize of the linux kernel
 trampoline:	call	start_of_setup
 		# Don't let the E820 map overlap code
 		. = (0x2d0 - 0x200) + (E820MAX * E820ENTRY_SIZE)
diff -uNr linux-2.5.7.boot.heap/arch/i386/boot/tools/build.c linux-2.5.7.boot.build/arch/i386/boot/tools/build.c
--- linux-2.5.7.boot.heap/arch/i386/boot/tools/build.c	Mon Jul  2 14:56:40 2001
+++ linux-2.5.7.boot.build/arch/i386/boot/tools/build.c	Fri Mar 29 12:02:55 2002
@@ -3,6 +3,8 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
+ *  Copyright (C) 2002 Eric Biederman
+ *
  */
 
 /*
@@ -22,32 +24,83 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  * Cross compiling fixes by Gertjan van Wingerde, July 1996
  * Rewritten by Martin Mares, April 1997
+ * Rewriten by Eric Biederman to remove the need for objcopy and
+ *   to stop losing information. 29 Mary 2002
  */
 
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/sysmacros.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <elf.h>
+/* To stay in sync with the kernel we must include <asm/boot.h> */
 #include <asm/boot.h>
 
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
-
 #define DEFAULT_MAJOR_ROOT 0
 #define DEFAULT_MINOR_ROOT 0
 
 /* Minimal number of setup sectors (see also bootsect.S) */
 #define SETUP_SECTS 4
 
-byte buf[1024];
-int fd;
-int is_big_kernel;
+struct boot_params {
+	uint8_t  reserved1[0x1f1];			/* 0x000 */
+	uint8_t  setup_sects;			/* 0x1f1 */
+	uint16_t mount_root_rdonly;		/* 0x1f2 */
+	uint16_t syssize;				/* 0x1f4 */
+	uint16_t swapdev;				/* 0x1f6 */
+	uint16_t ramdisk_flags;			/* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000	
+	uint16_t vid_mode;				/* 0x1fa */
+	uint16_t root_dev;				/* 0x1fc */
+	uint8_t  reserved9[1];			/* 0x1fe */
+	uint8_t  aux_device_info;			/* 0x1ff */
+	/* 2.00+ */
+	uint8_t  reserved10[2];			/* 0x200 */
+	uint8_t  header_magic[4];			/* 0x202 */
+	uint16_t protocol_version;			/* 0x206 */
+	uint8_t  reserved11[8];			/* 0x208 */
+	uint8_t  loader_type;			/* 0x210 */
+#define LOADER_TYPE_LOADLIN         1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX        3
+#define LOADER_TYPE_ETHERBOOT       4
+#define LOADER_TYPE_UNKNOWN         0xFF
+	uint8_t  loader_flags;			/* 0x211 */
+	uint8_t  reserved12[2];			/* 0x212 */
+	uint32_t code32_start;			/* 0x214 */
+	uint32_t initrd_start;			/* 0x218 */
+	uint32_t initrd_size;			/* 0x21c */
+	uint8_t  reserved13[4];			/* 0x220 */
+	/* 2.01+ */
+	uint16_t heap_end_ptr;			/* 0x224 */
+	uint8_t  reserved14[2];			/* 0x226 */
+	/* 2.02+ */
+	uint32_t cmd_line_ptr;			/* 0x228 */
+	/* 2.03+ */
+	uint32_t ramdisk_max;			/* 0x22c */
+	/* 2.04+ */
+	uint16_t entry32_off;			/* 0x230 */
+	uint16_t internal_cmdline_off;		/* 0x232 */
+	uint32_t low_base;			/* 0x234 */
+	uint32_t low_memsz;			/* 0x238 */
+	uint32_t low_filesz;			/* 0x23c */
+	uint32_t real_base;			/* 0x240 */
+	uint32_t real_memsz;			/* 0x244 */
+	uint32_t real_filesz;			/* 0x248 */
+	uint32_t high_base;			/* 0x24C */
+	uint32_t high_memsz;			/* 0x250 */
+	uint32_t high_filesz;			/* 0x254 */
+						/* 0x258 */
+};
 
 void die(const char * str, ...)
 {
@@ -58,132 +111,364 @@
 	exit(1);
 }
 
-void file_open(const char *name)
+int checked_open(const char *pathname, int flags, mode_t mode)
+{
+	int result;
+	result = open(pathname, flags, mode);
+	if (result < 0) {
+		die("Cannot open %s : %s", 
+			pathname,
+			strerror(errno));
+	}
+	return result;
+}
+void checked_read(int fd, void *buf, size_t count, const char *pathname)
 {
-	if ((fd = open(name, O_RDONLY, 0)) < 0)
-		die("Unable to open `%s': %m", name);
+	ssize_t result;
+	result = read(fd, buf, count);
+	if (result != count) {
+		die("Cannot read %d bytes from %s: %s",
+			count, 
+			pathname,
+			strerror(errno));
+	}
 }
 
-void usage(void)
+void checked_write(int fd, void *buf, size_t count, const char *pathname)
 {
-	die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+	ssize_t result;
+	result = write(fd, buf, count);
+	if (result != count) {
+		die("Cannot write %d bytes from %s: %s",
+			count, 
+			pathname,
+			strerror(errno));
+	}
 }
 
-int main(int argc, char ** argv)
+off_t checked_lseek(int fd, off_t offset, int whence, const char *pathname)
 {
-	unsigned int i, c, sz, setup_sectors;
-	u32 sys_size;
-	byte major_root, minor_root;
-	struct stat sb;
+	off_t result;
+	result = lseek(fd, offset, whence);
+	if (result == (off_t)-1) {
+		die("lseek failed on %s: %s",
+			pathname, strerror(errno));
+	}
+	return result;
+}
 
-	if (argc > 2 && !strcmp(argv[1], "-b"))
-	  {
-	    is_big_kernel = 1;
-	    argc--, argv++;
-	  }
-	if ((argc < 4) || (argc > 5))
-		usage();
-	if (argc > 4) {
-		if (!strcmp(argv[4], "CURRENT")) {
-			if (stat("/", &sb)) {
-				perror("/");
-				die("Couldn't stat /");
+static void *checked_malloc(size_t size)
+{
+	void *result;
+	result = malloc(size);
+	if (result == 0) {
+		die("malloc of %d bytes failed: %s",
+			size, strerror(errno));
+	}
+	return result;
+}
+
+static void check_ehdr(Elf32_Ehdr *ehdr, char *name)
+{
+	/* Do some basic to ensure it is an ELF image */
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+		die("%s is not an ELF binary", name);
+	}
+	if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
+		die("%s is not a 32bit ELF object", name);
+	}
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
+		die("%s does not have little endian data", name);
+	}
+	if ((ehdr->e_ident[EI_VERSION] != EV_CURRENT) ||
+		ehdr->e_version != EV_CURRENT) {
+		die("%s has invalid ELF version", name);
+	}
+	if (ehdr->e_type != ET_EXEC) {
+		die("%s is not an ELF executable", name);
+	}
+	if (ehdr->e_machine != EM_386) {
+		die("%s is not for x86", name);
+	}
+	if ((ehdr->e_phoff == 0) || (ehdr->e_phnum == 0)) {
+		die("%s has no program header", name);
+	}
+	if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) {
+		die("%s has invalid program header size", name);
+	}
+}
+struct elf_sizes
+{
+	size_t mem_size;
+	size_t data_size;
+};
+
+static Elf32_Phdr *read_sorted_phdr(char *name, int fd, 
+	Elf32_Ehdr *ehdr, struct elf_sizes *sizes)
+{
+	int i, j;
+	Elf32_Phdr *phdr, *plow, *phigh;
+	size_t phdr_size;
+	sizes->mem_size = 0;
+	sizes->data_size = 0;
+
+	phdr_size = ehdr->e_phnum * sizeof(*phdr);
+	phdr = checked_malloc(phdr_size);
+	checked_lseek(fd, ehdr->e_phoff, SEEK_SET, name);
+	checked_read(fd, phdr, phdr_size, name);
+
+	plow = 0;
+	phigh = 0;
+	/* Do an insertion sort on the program headers */
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		Elf32_Phdr *least;
+		least = phdr +i;
+		for(j = i+1; j < ehdr->e_phnum; j++) {
+			if (phdr[j].p_type != PT_LOAD) {
+				continue;
 			}
-			major_root = major(sb.st_dev);
-			minor_root = minor(sb.st_dev);
-		} else if (strcmp(argv[4], "FLOPPY")) {
-			if (stat(argv[4], &sb)) {
-				perror(argv[4]);
-				die("Couldn't stat root device.");
+			if ((least->p_type != PT_LOAD) || 
+				(phdr[j].p_paddr < least->p_paddr)) {
+				least = phdr + j;
 			}
-			major_root = major(sb.st_rdev);
-			minor_root = minor(sb.st_rdev);
-		} else {
-			major_root = 0;
-			minor_root = 0;
-		}
-	} else {
-		major_root = DEFAULT_MAJOR_ROOT;
-		minor_root = DEFAULT_MINOR_ROOT;
-	}
-	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-
-	file_open(argv[1]);
-	i = read(fd, buf, sizeof(buf));
-	fprintf(stderr,"Boot sector %d bytes.\n",i);
-	if (i != 512)
-		die("Boot block must be exactly 512 bytes");
-	if (buf[510] != 0x55 || buf[511] != 0xaa)
-		die("Boot block hasn't got boot flag (0xAA55)");
-	buf[508] = minor_root;
-	buf[509] = major_root;
-	if (write(1, buf, 512) != 512)
-		die("Write call failed");
-	close (fd);
-
-	file_open(argv[2]);				    /* Copy the setup code */
-	for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-	if (c != 0)
-		die("read-error on `setup'");
-	close (fd);
-
-	setup_sectors = (i + 511) / 512;	/* Pad unused space with zeros */
-	/* for compatibility with ancient versions of LILO. */
-	if (setup_sectors < SETUP_SECTS)
-		setup_sectors = SETUP_SECTS;
-	fprintf(stderr, "Setup is %d bytes.\n", i);
-	memset(buf, 0, sizeof(buf));
-	while (i < setup_sectors * 512) {
-		c = setup_sectors * 512 - i;
-		if (c > sizeof(buf))
-			c = sizeof(buf);
-		if (write(1, buf, c) != c)
-			die("Write call failed");
-		i += c;
-	}
-
-	file_open(argv[3]);
-	if (fstat (fd, &sb))
-		die("Unable to stat `%s': %m", argv[3]);
-	sz = sb.st_size;
-	fprintf (stderr, "System is %d kB\n", sz/1024);
-	sys_size = (sz + 15) / 16;
-	/* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
-	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
-		die("System is too big. Try using %smodules.",
-			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xefff)
-		fprintf(stderr,"warning: kernel is too big for standalone boot "
-		    "from floppy\n");
-	while (sz > 0) {
-		int l, n;
-
-		l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
-		if ((n=read(fd, buf, l)) != l) {
-			if (n < 0)
-				die("Error reading %s: %m", argv[3]);
-			else
-				die("%s: Unexpected EOF", argv[3]);
-		}
-		if (write(1, buf, l) != l)
-			die("Write failed");
-		sz -= l;
+		}
+		if (least != phdr +i) {
+			Elf32_Phdr tmp;
+			tmp = phdr[i];
+			phdr[i] = *least;
+			*least = tmp;
+		}
+	}
+	plow = phdr;
+	phigh = 0;
+	for(i = 0; i < ehdr->e_phnum; i++) {
+		if (phdr[i].p_type != PT_LOAD)
+			break;
+		phigh = phdr +i;
+	}
+	if (phigh) {
+		size_t start, middle, end;
+		start = plow->p_paddr;
+		middle = phigh->p_paddr + phigh->p_filesz;
+		end = phigh->p_paddr + phigh->p_memsz;
+		sizes->mem_size = end - start;
+		sizes->data_size = middle - start;
 	}
+	return phdr;
+	
+}
+
+static void get_elf_sizes(char *name, size_t pstart, struct elf_sizes *sizes)
+{
+	int fd;
+	Elf32_Ehdr ehdr;
+	Elf32_Phdr *phdr;
+	fd = checked_open(name, O_RDONLY, 0);
+	checked_read(fd, &ehdr, sizeof(ehdr), name);
+	check_ehdr(&ehdr, name);
+
+	phdr = read_sorted_phdr(name, fd, &ehdr, sizes);
+	if (phdr->p_paddr != pstart) {
+		die("Low PHDR in %s not at 0x%08x", name, pstart);
+	}
+
+	free(phdr);
 	close(fd);
+	return;
+}
 
-	if (lseek(1, 497, SEEK_SET) != 497)		    /* Write sizes to the bootsector */
-		die("Output: seek failed");
-	buf[0] = setup_sectors;
-	if (write(1, buf, 1) != 1)
-		die("Write of setup sector count failed");
-	if (lseek(1, 500, SEEK_SET) != 500)
-		die("Output: seek failed");
-	buf[0] = (sys_size & 0xff);
-	buf[1] = ((sys_size >> 8) & 0xff);
-	if (write(1, buf, 2) != 2)
-		die("Write of image length failed");
+static void append_elf(char *dest_name, int dest_fd, 
+	char *name, size_t pstart, off_t align, struct elf_sizes *sizes)
+{
+	int src_fd;
+	Elf32_Ehdr ehdr;
+	Elf32_Phdr *phdr;
+	size_t last_paddr;
+	off_t loc;
+	int i;
+	if (align == 0) {
+		align = 1;
+	}
+
+	src_fd = checked_open(name, O_RDONLY, 0);
+	checked_read(src_fd, &ehdr, sizeof(ehdr), name);
+	check_ehdr(&ehdr, name);
+
+	phdr = read_sorted_phdr(name, src_fd, &ehdr, sizes);
+	if (phdr->p_paddr != pstart) {
+		die("Low PHDR in %s not at 0x%08x", name, pstart);
+	}
+	
+	last_paddr = phdr[0].p_paddr;
+	for(i = 0; i < ehdr.e_phnum; i++) {
+		char *buf;
+		size_t size;
+		if (phdr[i].p_type != PT_LOAD) {
+			break;
+		}
+		if (last_paddr != phdr[i].p_paddr) {
+			checked_lseek(dest_fd, phdr[i].p_paddr - last_paddr, 
+				SEEK_CUR, dest_name);
+		}
+		last_paddr = phdr[i].p_paddr + phdr[i].p_filesz;
+
+		size = phdr[i].p_filesz;
+		buf = checked_malloc(size);
+		checked_lseek(src_fd, phdr[i].p_offset, SEEK_SET, name);
+		checked_read(src_fd, buf, size, name);
+		checked_write(dest_fd, buf, size, dest_name);
+		free(buf);
+	}
+	free(phdr);
+	close(src_fd);
+
+	/* Align the output */
+	loc = checked_lseek(dest_fd, 0, SEEK_CUR, dest_name);
+	loc = (loc + align -1) & ~(align -1);
+	checked_lseek(dest_fd, loc, SEEK_SET, dest_name);
+	return;
+}
 
-	return 0;					    /* Everything is OK */
+static void write_uint8(int fd, off_t offset, uint8_t value, const char *name)
+{
+	checked_lseek(fd, offset, SEEK_SET, name);
+	checked_write(fd, &value, sizeof(value), name);
+}
+static void write_uint16(int fd, off_t offset, uint16_t value, const char *name)
+{
+	checked_lseek(fd, offset, SEEK_SET, name);
+	checked_write(fd, &value, sizeof(value), name);
+}
+static void write_uint32(int fd, off_t offset, uint32_t value, const char *name)
+{
+	checked_lseek(fd, offset, SEEK_SET, name);
+	checked_write(fd, &value, sizeof(value), name);
+}
+
+struct image_info {
+	size_t setup_sectors;
+	size_t sys_size;
+	size_t root_dev;
+	size_t low_memsz;
+	size_t low_filesz;
+	size_t high_memsz;
+	size_t high_filesz;
+};
+
+#define OFFSET_OF(X) offsetof(struct boot_params, X)
+static void update_image(char *name, int fd, struct image_info *info)
+{
+	info->setup_sectors &= 0xff;
+	info->sys_size &= 0xffff;
+	info->root_dev &= 0xffff;
+	write_uint8 (fd, OFFSET_OF(setup_sects), info->setup_sectors, name);
+	write_uint16(fd, OFFSET_OF(syssize),     info->sys_size,      name);
+	write_uint16(fd, OFFSET_OF(root_dev),    info->root_dev,      name);
+	write_uint32(fd, OFFSET_OF(low_memsz),   info->low_memsz,     name);
+	write_uint32(fd, OFFSET_OF(low_filesz),  info->low_filesz,    name);
+	write_uint32(fd, OFFSET_OF(high_memsz),  info->high_memsz,    name);
+	write_uint32(fd, OFFSET_OF(high_filesz), info->high_filesz,   name);
+}
+
+static void usage(void)
+{
+	die("Usage: build [-b] vmlinux realmode compressed/vmlinux image");
+}
+
+int main(int argc, char **argv)
+{
+	int is_big_kernel = 0;
+	char *kernel;
+	char *realmode;
+	char *zkernel;
+	char *image;
+	int image_fd;
+	size_t major_root, minor_root;
+	size_t zkernel_base;
+	struct image_info info;
+	struct elf_sizes kernel_sz, zkernel_sz, realmode_sz;
+	struct stat st;
+
+	if (argc > 2 && (strcmp(argv[1], "-b") == 0)) {
+		is_big_kernel = 1;
+		argc--;
+		argv++;
+	}
+	if (argc != 5) {
+		usage();
+	}
+	kernel = argv[1];
+	realmode = argv[2];
+	zkernel = argv[3];
+	image = argv[4];
+
+	/* Compute the current root device */
+	major_root = DEFAULT_MAJOR_ROOT;
+	minor_root = DEFAULT_MINOR_ROOT;
+	if (stat("/", &st) == 0) {
+		major_root = major(st.st_dev);
+		minor_root = minor(st.st_dev);
+	}
+	major_root &= 0xff;
+	minor_root &= 0xff;
+	info.root_dev = (major_root << 8) | minor_root;
+	printf("Root device is (%d, %d)\n", major_root, minor_root);
+
+	zkernel_base = is_big_kernel? HIGH_BASE: LOW_BASE;
+
+	image_fd = checked_open(image, O_RDWR | O_CREAT | O_TRUNC, 0666);
+	get_elf_sizes(kernel, 0x100000, &kernel_sz);
+	append_elf(image, image_fd, realmode, 0x90000, 512, &realmode_sz);
+	append_elf(image, image_fd, zkernel, zkernel_base, 1, &zkernel_sz);
+
+	info.setup_sectors = (realmode_sz.data_size - 512 + 511)/512;
+	if (info.setup_sectors < SETUP_SECTS)
+		info.setup_sectors = SETUP_SECTS;
+	printf("Setup is %d bytes\n", realmode_sz.data_size);
+
+	info.sys_size = (zkernel_sz.data_size + 15)/16;
+	if (!is_big_kernel && (info.sys_size > DEF_SYSSIZE)) {
+		die("System is to big. Try using bzImage or modules.");
+	}
+	if (kernel_sz.mem_size >= INITIAL_PAGE_TABLE_SIZE) {
+		die("System is to big.  Try using modules.");
+	}
+	if (info.sys_size > 0xefff) {
+		fprintf(stderr, "warning: kernel is too big for standalone boot " 
+			"from floppy\n");
+	}
+	printf("System is %d KB\n", zkernel_sz.data_size/1024);
+	info.low_filesz = 0;
+	info.high_filesz = 0;
+	if (is_big_kernel) {
+		/* bzImage */
+		size_t data_size = 0;
+		info.high_filesz = zkernel_sz.data_size;
+		info.low_memsz = kernel_sz.data_size;
+		if (kernel_sz.data_size > (LOW_BUFFER_MAX - LOW_BUFFER_START)) {
+			info.low_memsz = LOW_BUFFER_MAX - LOW_BUFFER_START;
+			data_size = kernel_sz.data_size - info.low_memsz;
+		}
+		info.high_memsz = zkernel_sz.mem_size + HEAP_SIZE + data_size;
+		if (kernel_sz.mem_size > info.high_memsz) {
+			info.high_memsz = kernel_sz.mem_size;
+		}
+	}
+	else  {
+		/* zImage */
+		info.low_filesz = zkernel_sz.data_size;
+		info.low_memsz = zkernel_sz.mem_size + HEAP_SIZE;
+		if (info.low_memsz + LOW_BUFFER_START > LOW_BUFFER_MAX) {
+			info.low_memsz = LOW_BUFFER_MAX - LOW_BUFFER_START;
+		}
+		info.high_memsz = kernel_sz.mem_size;
+	}
+	info.low_memsz += LOW_BUFFER_START - LOW_BASE;
+	update_image(image, image_fd, &info);
+	printf(" low_memsz=%5dkB  low_filesz=%5dkB\n", 
+		info.low_memsz/1024, info.low_filesz/1024);
+	printf( "high_memsz=%5dkB high_filesz=%5dKB\n", 
+		info.high_memsz/1024, info.high_filesz/1024);
+	close(image_fd);
+	return 0;
 }
diff -uNr linux-2.5.7.boot.heap/arch/x86_64/boot/Makefile linux-2.5.7.boot.build/arch/x86_64/boot/Makefile
--- linux-2.5.7.boot.heap/arch/x86_64/boot/Makefile	Sun Mar 10 20:08:39 2002
+++ linux-2.5.7.boot.build/arch/x86_64/boot/Makefile	Fri Mar 29 11:51:28 2002
@@ -14,11 +14,11 @@
 
 zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
 	$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
-	tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage
+	tools/build bootsect setup compressed/vmlinux.out CURRENT > zImage
 
 bzImage: $(CONFIGURE) bbootsect bsetup compressed/bvmlinux tools/build
 	$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out
-	tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
+	tools/build -b bbootsect bsetup compressed/bvmlinux.out CURRENT > bzImage
 
 bzImage-padded: bzImage
 	dd if=/dev/zero bs=1k count=70 >> bzImage
