diff -uNr linux-2.5.7.boot.linuxbios/Makefile linux-2.5.7.boot.elf/Makefile
--- linux-2.5.7.boot.linuxbios/Makefile	Fri Mar 29 23:53:33 2002
+++ linux-2.5.7.boot.elf/Makefile	Sat Mar 30 20:38:02 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 7
-EXTRAVERSION = .boot.linuxbios
+EXTRAVERSION = .boot.elf
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -uNr linux-2.5.7.boot.linuxbios/arch/i386/Makefile linux-2.5.7.boot.elf/arch/i386/Makefile
--- linux-2.5.7.boot.linuxbios/arch/i386/Makefile	Fri Mar 29 09:17:57 2002
+++ linux-2.5.7.boot.elf/arch/i386/Makefile	Sat Mar 30 18:24:20 2002
@@ -119,6 +119,12 @@
 bzImage: vmlinux
 	@$(MAKEBOOT) bzImage
 
+zElf: vmlinux
+	@$(MAKEBOOT) zElf
+
+bzElf: vmlinux
+	@$(MAKEBOOT) bzElf
+
 compressed: zImage
 
 zlilo: vmlinux
diff -uNr linux-2.5.7.boot.linuxbios/arch/i386/boot/Makefile linux-2.5.7.boot.elf/arch/i386/boot/Makefile
--- linux-2.5.7.boot.linuxbios/arch/i386/boot/Makefile	Fri Mar 29 23:48:44 2002
+++ linux-2.5.7.boot.elf/arch/i386/boot/Makefile	Sat Mar 30 21:42:36 2002
@@ -18,6 +18,13 @@
 bzImage: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux brealmode compressed/bvmlinux 
 	tools/build -b $(TOPDIR)/vmlinux brealmode compressed/bvmlinux bzImage
 
+
+zElf: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux realmode compressed/vmlinux 
+	tools/build -e $(TOPDIR)/vmlinux realmode compressed/vmlinux zElf
+
+bzElf: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux brealmode compressed/bvmlinux 
+	tools/build -e -b $(TOPDIR)/vmlinux brealmode compressed/bvmlinux bzElf
+
 compressed/vmlinux: $(TOPDIR)/vmlinux
 	@$(MAKE) -C compressed vmlinux
 
@@ -37,7 +44,7 @@
 install: $(CONFIGURE) $(BOOTIMAGE)
 	sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
-tools/build: tools/build.c
+tools/build: tools/build.c $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h $(TOPDIR)/include/asm-i386/boot.h
 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
 
 bootsect.o: bootsect.s
@@ -65,10 +72,10 @@
 	$(CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
 realmode: bootsect.o setup.o
-	$(LD) -T realmode.lds -s -o $@ $^
+	$(LD) -T realmode.lds  -o $@ $^
 
 brealmode: bbootsect.o bsetup.o
-	$(LD) -T realmode.lds -s -o $@ $^
+	$(LD) -T realmode.lds -o $@ $^
 
 dep:
 
Binary files linux-2.5.7.boot.linuxbios/arch/i386/boot/bzElf and linux-2.5.7.boot.elf/arch/i386/boot/bzElf differ
diff -uNr linux-2.5.7.boot.linuxbios/arch/i386/boot/realmode.lds linux-2.5.7.boot.elf/arch/i386/boot/realmode.lds
--- linux-2.5.7.boot.linuxbios/arch/i386/boot/realmode.lds	Fri Mar 29 23:48:44 2002
+++ linux-2.5.7.boot.elf/arch/i386/boot/realmode.lds	Sat Mar 30 21:08:27 2002
@@ -1,5 +1,5 @@
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-ENTRY(_start)
+ENTRY(entry32)
 OUTPUT_ARCH(i386)
 SECTIONS
 {
@@ -10,6 +10,9 @@
 	. = 0x90200;
 	.setup : {
 		*(.setup)
+	}
+	.setup.heap : {
+		*(.setup.heap)
 	}
 	/DISCARD/ : {
 		*(*)
diff -uNr linux-2.5.7.boot.linuxbios/arch/i386/boot/setup.S linux-2.5.7.boot.elf/arch/i386/boot/setup.S
--- linux-2.5.7.boot.linuxbios/arch/i386/boot/setup.S	Fri Mar 29 23:49:22 2002
+++ linux-2.5.7.boot.elf/arch/i386/boot/setup.S	Sat Mar 30 22:29:55 2002
@@ -86,7 +86,7 @@
 .code16
 .globl _setup, _esetup
 
-.section ".bootsect", "ax", @progbits
+.section ".setup", "ax", @progbits
 _setup:	
 
 start:
@@ -144,7 +144,7 @@
 bootsect_kludge:
 		.word	bootsect_helper - start, SETUPSEG
 
-heap_end_ptr:	.word	_esetup + MIN_HEAP_SIZE  - start
+heap_end_ptr:	.word	_esetup_heap - start
 					# (Header version 0x0201 or later)
 					# space from here (exclusive) down to
 					# heap_start can be used by setup
@@ -183,7 +183,7 @@
 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)
+		.long	(_esetup_heap - 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
@@ -1043,6 +1043,7 @@
 	ret
 
 	.code32
+	.globl entry32
 entry32:
 	testl	%esp, %esp
 	jnz	1f
@@ -1223,6 +1224,8 @@
 # handling code to store the temporary mode table (not used by the kernel).
 internal_command_line:
 	.asciz CONFIG_CMDLINE
-	.balign 512
-
 _esetup:
+.section ".setup.heap", "a", @nobits
+_setup_heap:
+. = MIN_HEAP_SIZE
+_esetup_heap:
diff -uNr linux-2.5.7.boot.linuxbios/arch/i386/boot/tools/build.c linux-2.5.7.boot.elf/arch/i386/boot/tools/build.c
--- linux-2.5.7.boot.linuxbios/arch/i386/boot/tools/build.c	Fri Mar 29 23:48:44 2002
+++ linux-2.5.7.boot.elf/arch/i386/boot/tools/build.c	Sun Mar 31 08:55:21 2002
@@ -10,12 +10,14 @@
 /*
  * This file builds a disk-image from three different files:
  *
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
- * - setup: 8086 machine code, sets up system parm
+ * - vmlinux: kernel before compression
+ * - realmode: composed of:
+ *    - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ *    - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
  *
  * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
+ * just writes the result, removing headers and padding to
  * the right amount. It also writes some system data to stderr.
  */
 
@@ -40,7 +42,9 @@
 #include <inttypes.h>
 #include <errno.h>
 #include <elf.h>
-/* To stay in sync with the kernel we must include <asm/boot.h> */
+/* To stay in sync with the kernel we must include these headers */
+#include <linux/version.h>
+#include <linux/compile.h>
 #include <asm/boot.h>
 
 #define DEFAULT_MAJOR_ROOT 0
@@ -49,6 +53,58 @@
 /* Minimal number of setup sectors (see also bootsect.S) */
 #define SETUP_SECTS 4
 
+/* Segments of the output file */
+#define SEHDR 0
+#define SREAL 1
+#define SLOW  2
+#define SHIGH 3
+
+/* Kernel version */
+#define LINUX_KERNEL_VERSION \
+	UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION
+
+typedef uint16_t Elf_Half;
+typedef uint32_t Elf_Word;
+typedef uint64_t Elf_Xword;
+
+typedef struct 
+{
+	Elf_Word n_namesz;		/* Length of the note's name.  */
+	Elf_Word n_descsz;		/* Length of the note's descriptor.  */
+	Elf_Word n_type;		/* Type of the note.  */
+} Elf_Nhdr;
+
+typedef struct 
+{
+	Elf_Word n_paddr;
+	Elf_Word n_size;
+} Elf_Pdesc;
+
+/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
+
+#define EIN_NOTE_NAME	"ELFBoot"
+#define EIN_PROGRAM_NAME	0x00000001
+/* The program in this ELF file */
+#define EIN_PROGRAM_VERSION	0x00000002
+/* The version of the program in this ELF file */
+#define EIN_PROGRAM_CHECKSUM	0x00000003
+/* ip style checksum of the memory image. */
+
+
+/* Linux image notes for booting... The name for all of these is Linux */
+
+/* 0x00000001 - 0x00000005 are depricated do not use */
+#define LIN_NOTE_NAME	"Linux"
+
+#define LIN_COMMAND_LINE_PTR	0x00000006
+/* Pointer to the command line to pass to the loaded kernel. */
+#define LIN_INITRD_START_PTR	0x00000007
+/* Pointer to the start of the ramdisk in bytes */
+#define LIN_INITRD_SIZE_PTR	0x00000008
+/* Pointer to the size of the ramdisk in bytes */
+#define LIN_VID_MODE_PTR	0x00000009
+/* Pointer to the vid_mode parameter */
+
 struct boot_params {
 	uint8_t  reserved1[0x1f1];			/* 0x000 */
 	uint8_t  setup_sects;			/* 0x1f1 */
@@ -102,6 +158,7 @@
 						/* 0x258 */
 };
 
+
 void die(const char * str, ...)
 {
 	va_list args;
@@ -168,6 +225,95 @@
 	return result;
 }
 
+static void *checked_realloc(void *ptr, size_t size)
+{
+	void *result;
+	result = realloc(ptr, size);
+	if (result == 0) {
+		die("realloc of failed: %s", strerror(errno));
+	}
+	return result;
+}
+
+unsigned long compute_ip_checksum(void *addr, unsigned long length)
+{
+	uint16_t *ptr;
+	unsigned long sum;
+	unsigned long len;
+	unsigned long laddr;
+	/* compute an ip style checksum */
+	laddr = (unsigned long )addr;
+	sum = 0;
+	if (laddr & 1) {
+		uint16_t buffer;
+		unsigned char *ptr;
+		/* copy the first byte into a 2 byte buffer.
+		 * This way automatically handles the endian question
+		 * of which byte (low or high) the last byte goes in.
+		 */
+		buffer = 0;
+		ptr = addr;
+		memcpy(&buffer, ptr, 1);
+		sum += buffer;
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+		length -= 1;
+		addr = ptr +1;
+	}
+	len = length >> 1;
+	ptr = addr;
+	while (len--) {
+		sum += *(ptr++);
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	addr = ptr;
+	if (length & 1) {
+		uint16_t buffer;
+		unsigned char *ptr;
+		/* copy the last byte into a 2 byte buffer.
+		 * This way automatically handles the endian question
+		 * of which byte (low or high) the last byte goes in.
+		 */
+		buffer = 0;
+		ptr = addr;
+		memcpy(&buffer, ptr, 1);
+		sum += buffer;
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	return (~sum) & 0xFFFF;
+	
+}
+
+unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new)
+{
+	unsigned long checksum;
+	sum = ~sum & 0xFFFF;
+	new = ~new & 0xFFFF;
+	if (offset & 1) {
+		/* byte swap the sum if it came from an odd offset 
+		 * since the computation is endian independant this
+		 * works.
+		 */
+		new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
+	}
+	checksum = sum + new;
+	if (checksum > 0xFFFF) {
+		checksum -= 0xFFFF;
+	}
+	return (~checksum) & 0xFFFF;
+}
+
+unsigned long negate_ip_checksum(unsigned long sum)
+{
+	sum = ~sum & 0xFFFF;
+
+	sum = 0xFFFF - sum;
+
+	return ~sum & 0xFFFF;
+}
+
 static void check_ehdr(Elf32_Ehdr *ehdr, char *name)
 {
 	/* Do some basic to ensure it is an ELF image */
@@ -197,20 +343,29 @@
 		die("%s has invalid program header size", name);
 	}
 }
-struct elf_sizes
+
+struct file_seg
 {
+	size_t mem_addr;
 	size_t mem_size;
 	size_t data_size;
+	off_t  file_offset;
+	size_t entry;
+	unsigned char *data;
 };
 
 static Elf32_Phdr *read_sorted_phdr(char *name, int fd, 
-	Elf32_Ehdr *ehdr, struct elf_sizes *sizes)
+	Elf32_Ehdr *ehdr, struct file_seg *seg)
 {
 	int i, j;
 	Elf32_Phdr *phdr, *plow, *phigh;
 	size_t phdr_size;
-	sizes->mem_size = 0;
-	sizes->data_size = 0;
+	seg->mem_addr = 0;
+	seg->mem_size = 0;
+	seg->data_size = 0;
+	seg->file_offset = 0;
+	seg->entry = ehdr->e_entry;
+	seg->data = 0;
 
 	phdr_size = ehdr->e_phnum * sizeof(*phdr);
 	phdr = checked_malloc(phdr_size);
@@ -251,14 +406,15 @@
 		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;
+		seg->mem_addr = start;
+		seg->mem_size = end - start;
+		seg->data_size = middle - start;
 	}
 	return phdr;
 	
 }
 
-static void get_elf_sizes(char *name, size_t pstart, struct elf_sizes *sizes)
+static void get_elf_sizes(char *name, size_t pstart, struct file_seg *sizes)
 {
 	int fd;
 	Elf32_Ehdr ehdr;
@@ -268,7 +424,7 @@
 	check_ehdr(&ehdr, name);
 
 	phdr = read_sorted_phdr(name, fd, &ehdr, sizes);
-	if (phdr->p_paddr != pstart) {
+	if (sizes->mem_addr != pstart) {
 		die("Low PHDR in %s not at 0x%08x", name, pstart);
 	}
 
@@ -277,118 +433,238 @@
 	return;
 }
 
-static void append_elf(char *dest_name, int dest_fd, 
-	char *name, size_t pstart, off_t align, struct elf_sizes *sizes)
+static void read_elf(char *name, size_t pstart, struct file_seg *seg)
 {
 	int src_fd;
 	Elf32_Ehdr ehdr;
 	Elf32_Phdr *phdr;
 	size_t last_paddr;
-	off_t loc;
+	size_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) {
+	phdr = read_sorted_phdr(name, src_fd, &ehdr, seg);
+	if (seg->mem_addr != pstart) {
 		die("Low PHDR in %s not at 0x%08x", name, pstart);
 	}
 	
 	last_paddr = phdr[0].p_paddr;
+	seg->data = checked_malloc(seg->data_size);
+	loc = 0;
 	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);
+			size = phdr[i].p_paddr - last_paddr;
+			memset(seg->data + loc, 0, size);
+			loc += size;
 		}
 		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);
+		checked_read(src_fd, seg->data + loc, size, name);
+		loc += size;
 	}
 	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;
 }
 
-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 entry32;
 	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;
+	struct boot_params *param;
 };
 
-#define OFFSET_OF(X) offsetof(struct boot_params, X)
-static void update_image(char *name, int fd, struct image_info *info)
+static void update_image(struct file_seg *seg, struct image_info *info)
 {
+	struct boot_params *param = info->param;
 	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);
+	param->setup_sects  = info->setup_sectors;
+	param->syssize      = info->sys_size;
+	param->root_dev     = info->root_dev;
+	param->low_memsz    = seg[SLOW].mem_size;
+	param->low_filesz   = seg[SLOW].data_size;
+	param->real_memsz   = seg[SREAL].mem_size;
+	param->heap_end_ptr = seg[SREAL].mem_size - 512;
+	param->real_filesz  = seg[SREAL].data_size;
+	param->high_memsz   = seg[SHIGH].mem_size;
+	param->high_filesz  = seg[SHIGH].data_size;
+}
+
+struct elf_header {
+	Elf32_Ehdr ehdr;
+	Elf32_Phdr phdr[4];
+	Elf_Nhdr   program_name_hdr;
+	uint8_t    program_name_name[8];
+	uint8_t    program_name_desc[8];
+	Elf_Nhdr   program_version_hdr;
+	uint8_t    program_version_name[8];
+	uint8_t    program_version_desc[(sizeof(LINUX_KERNEL_VERSION) + 3) & ~3];
+	Elf_Nhdr   program_checksum_hdr;
+	uint8_t    program_checksum_name[8];
+	uint16_t   program_checksum;
+        uint16_t   program_checksum_pad;
+	Elf_Nhdr   command_line_hdr;
+	uint8_t    command_line_name[8];
+	Elf_Pdesc  command_line_desc;
+	Elf_Nhdr   initrd_start_hdr;
+	uint8_t    initrd_start_name[8];
+	Elf_Pdesc  initrd_start_desc;
+	Elf_Nhdr   initrd_size_hdr;
+	uint8_t    initrd_size_name[8];
+	Elf_Pdesc  initrd_size_desc;
+	Elf_Nhdr   vid_mode_hdr;
+	uint8_t    vid_mode_name[8];
+	Elf_Pdesc  vid_mode_desc;
+} __attribute__((packed));
+
+static void build_elf_header(struct file_seg *seg, struct image_info *info)
+{
+	struct elf_header *hdr;
+	size_t checksum, bytes;
+	int i;
+	hdr = checked_malloc(sizeof(*hdr));
+	memset(hdr, 0, sizeof(*hdr));
+	memcpy(hdr->ehdr.e_ident, ELFMAG, 4);
+	hdr->ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+	hdr->ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+	hdr->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+	hdr->ehdr.e_type = ET_EXEC;
+	hdr->ehdr.e_machine = EM_386;
+	hdr->ehdr.e_version = EV_CURRENT;
+	hdr->ehdr.e_entry = info->entry32;
+	hdr->ehdr.e_phoff = offsetof(struct elf_header, phdr);
+	hdr->ehdr.e_shoff = 0;
+	hdr->ehdr.e_flags = 0;
+	hdr->ehdr.e_ehsize = sizeof(hdr->ehdr);
+	hdr->ehdr.e_phentsize = sizeof(hdr->phdr[0]);
+	hdr->ehdr.e_phnum = 4;
+	hdr->ehdr.e_shentsize = 0;
+	hdr->ehdr.e_shnum = 0;
+	hdr->ehdr.e_shstrndx = 0;
+	hdr->phdr[0].p_type = PT_NOTE;
+	hdr->phdr[0].p_offset = offsetof(struct elf_header, program_name_hdr);
+	hdr->phdr[0].p_vaddr = 0;
+	hdr->phdr[0].p_paddr = 0;
+	hdr->phdr[0].p_filesz = sizeof(*hdr) - offsetof(struct elf_header, program_name_hdr);
+	hdr->phdr[0].p_memsz = hdr->phdr[0].p_filesz;
+	hdr->phdr[0].p_flags = 0;
+	hdr->phdr[0].p_align = 0;
+	
+	for(i = 1; i < 4; i++) {
+		hdr->phdr[i].p_type = PT_LOAD;
+		hdr->phdr[i].p_offset = seg[i].file_offset;
+		hdr->phdr[i].p_vaddr  = seg[i].mem_addr;
+		hdr->phdr[i].p_paddr  = seg[i].mem_addr;
+		hdr->phdr[i].p_filesz = seg[i].data_size;
+		hdr->phdr[i].p_memsz  = seg[i].mem_size;
+		hdr->phdr[i].p_flags  = 0;
+		hdr->phdr[i].p_align  = 0;
+	}
+	
+	hdr->program_name_hdr.n_namesz = strlen(EIN_NOTE_NAME) +1;
+	hdr->program_name_hdr.n_descsz = strlen("Linux") +1;
+	hdr->program_name_hdr.n_type = EIN_PROGRAM_NAME;
+	strcpy(hdr->program_name_name, EIN_NOTE_NAME);
+	strcpy(hdr->program_name_desc, "Linux");
+	
+	hdr->program_version_hdr.n_namesz = strlen(EIN_NOTE_NAME) +1;
+	hdr->program_version_hdr.n_descsz = strlen(LINUX_KERNEL_VERSION)+1;
+	hdr->program_version_hdr.n_type = EIN_PROGRAM_VERSION;
+	strcpy(hdr->program_version_name, EIN_NOTE_NAME);
+	strcpy(hdr->program_version_desc, LINUX_KERNEL_VERSION);
+
+	hdr->program_checksum_hdr.n_namesz = strlen(EIN_NOTE_NAME) +1;
+	hdr->program_checksum_hdr.n_descsz = 2;
+	hdr->program_checksum_hdr.n_type = EIN_PROGRAM_CHECKSUM;
+	strcpy(hdr->program_checksum_name, EIN_NOTE_NAME);
+	hdr->program_checksum = 0; /* This is written later */
+
+	hdr->command_line_hdr.n_namesz = strlen(LIN_NOTE_NAME) +1;
+	hdr->command_line_hdr.n_descsz = sizeof(hdr->command_line_desc);
+	hdr->command_line_hdr.n_type = LIN_COMMAND_LINE_PTR;
+	strcpy(hdr->command_line_name, LIN_NOTE_NAME);
+	hdr->command_line_desc.n_paddr = 
+		seg[SREAL].mem_addr + seg[SREAL].data_size - COMMAND_LINE_SIZE;
+	hdr->command_line_desc.n_size = COMMAND_LINE_SIZE;
+
+	hdr->initrd_start_hdr.n_namesz = strlen(LIN_NOTE_NAME) +1;
+	hdr->initrd_start_hdr.n_descsz = sizeof(hdr->initrd_start_desc);
+	hdr->initrd_start_hdr.n_type = LIN_INITRD_START_PTR;
+	strcpy(hdr->initrd_start_name, LIN_NOTE_NAME);
+	hdr->initrd_start_desc.n_paddr = 
+		seg[SREAL].mem_addr + offsetof(struct boot_params, initrd_start);
+	hdr->initrd_start_desc.n_size = 4;
+
+	hdr->initrd_size_hdr.n_namesz = strlen(LIN_NOTE_NAME) +1;
+	hdr->initrd_size_hdr.n_descsz = sizeof(hdr->initrd_size_desc);
+	hdr->initrd_size_hdr.n_type = LIN_INITRD_SIZE_PTR;
+	strcpy(hdr->initrd_size_name, LIN_NOTE_NAME);
+	hdr->initrd_size_desc.n_paddr = 
+		seg[SREAL].mem_addr + offsetof(struct boot_params, initrd_size);
+	hdr->initrd_size_desc.n_size = 4;
+
+	hdr->vid_mode_hdr.n_namesz = strlen(LIN_NOTE_NAME) +1;
+	hdr->vid_mode_hdr.n_descsz = sizeof(hdr->vid_mode_desc);
+	hdr->vid_mode_hdr.n_type = LIN_VID_MODE_PTR;
+	strcpy(hdr->vid_mode_name, LIN_NOTE_NAME);
+	hdr->vid_mode_desc.n_paddr = 
+		seg[SREAL].mem_addr + offsetof(struct boot_params, vid_mode);
+	hdr->vid_mode_desc.n_size = 2;
+
+	/* Compute the image checksum, this covers everything except the
+	 * ELF notes.
+	 */
+	bytes = sizeof(hdr->ehdr) + sizeof(hdr->phdr);
+	checksum = compute_ip_checksum(hdr, bytes);
+	for(i = 1; i < 4; i++) {
+		checksum = add_ip_checksums(bytes, checksum, 
+			compute_ip_checksum(seg[i].data, seg[i].data_size));
+		bytes += seg[i].mem_size;
+	}
+	hdr->program_checksum = checksum;
+	seg[SEHDR].data = (unsigned char *)hdr;
 }
 
 static void usage(void)
 {
-	die("Usage: build [-b] vmlinux realmode compressed/vmlinux image");
+	die("Usage: build [-e] [-b] vmlinux realmode compressed/vmlinux image");
 }
 
 int main(int argc, char **argv)
 {
-	int is_big_kernel = 0;
+	int is_big_kernel, is_elf;
 	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 file_seg kernel_sz;
+	struct file_seg seg[4];
 	struct stat st;
+	int i;
 
+	memset(seg, 0, sizeof(seg));
+	is_big_kernel = 0;
+	is_elf = 0;
+	if (argc > 2 && (strcmp(argv[1], "-e") == 0)) {
+		is_elf = 1;
+		argc--;
+		argv++;
+	}
 	if (argc > 2 && (strcmp(argv[1], "-b") == 0)) {
 		is_big_kernel = 1;
 		argc--;
@@ -414,61 +690,101 @@
 	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);
+	/* Read in the file information */
 	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);
+	read_elf(realmode, 0x90000, &seg[SREAL]);
+	if (!is_big_kernel) {
+		/* zImage */
+		read_elf(zkernel, LOW_BASE, &seg[SLOW]);
+		seg[SLOW].mem_size += HEAP_SIZE;
+		if ((seg[SLOW].mem_addr + seg[SLOW].mem_size) > LOW_BUFFER_MAX) {
+			seg[SLOW].mem_size = LOW_BUFFER_MAX - seg[SLOW].mem_addr;
+		}
+		seg[SHIGH].mem_size = kernel_sz.mem_size;
+	} else {
+		/* bzImage */
+		size_t data_size = 0;
+		read_elf(zkernel, HIGH_BASE, &seg[SHIGH]);
+		seg[SLOW].mem_size = kernel_sz.mem_size;
+		if (kernel_sz.data_size > (LOW_BUFFER_MAX - LOW_BUFFER_START)) {
+			seg[SLOW].mem_size = LOW_BUFFER_MAX - LOW_BUFFER_START;
+			data_size = kernel_sz.data_size - seg[SLOW].mem_size;
+		}
+		seg[SLOW].mem_size += LOW_BUFFER_START - seg[SLOW].mem_addr;
+		seg[SHIGH].mem_size +=  HEAP_SIZE;
+		if (kernel_sz.mem_size > seg[SHIGH].mem_size) {
+			seg[SHIGH].mem_size = kernel_sz.mem_size;
+		}
+	}
+	info.param = (struct boot_params *)seg[SREAL].data;
 
-	info.setup_sectors = (realmode_sz.data_size - 512 + 511)/512;
+	if (is_elf) {
+		/* Expand the compiled in command line to maximum size */
+		size_t extra_bytes, cmdline_bytes;
+		extra_bytes = 0;
+		cmdline_bytes = seg[SREAL].data_size - info.param->internal_cmdline_off;
+		if (COMMAND_LINE_SIZE > cmdline_bytes) {
+			extra_bytes = COMMAND_LINE_SIZE - cmdline_bytes;
+		}
+		seg[SREAL].data = checked_realloc(seg[SREAL].data, 
+			seg[SREAL].data_size + extra_bytes);
+		memset(seg[SREAL].data + seg[SREAL].data_size, 0, extra_bytes);
+		seg[SREAL].data_size += extra_bytes;
+		seg[SREAL].mem_size += extra_bytes;
+	}
+
+	/* Compute the file offsets */
+	info.setup_sectors = (seg[SREAL].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);
+	if (is_elf) {
+		seg[SEHDR].data_size = sizeof(struct elf_header);
+	}
+	/* Note: for ELF images I don't have to make SREAL
+	 * info.setup_sectors long, but it makes the conversion back
+	 * to a bzImage just a trivial header removal.
+	 */
+	seg[SREAL].file_offset = seg[SEHDR].file_offset + seg[SEHDR].data_size;
+	seg[SLOW].file_offset  = seg[SREAL].file_offset + (info.setup_sectors +1)*512;
+	seg[SHIGH].file_offset = seg[SLOW].file_offset + seg[SLOW].data_size;
+
+	/* Check and print the values to write back. */
+	info.entry32 = seg[SREAL].entry;
+	printf("Setup is %d bytes\n", seg[SREAL].data_size);
 
-	info.sys_size = (zkernel_sz.data_size + 15)/16;
+	info.sys_size = (seg[is_big_kernel?2:0].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) {
+	if ((seg[SHIGH].mem_addr + seg[SHIGH].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;
-		}
+	printf("System is %d KB\n", (info.sys_size*16)/1024);
+	printf("entry32: 0x%x\n", info.entry32);
+	printf("low_memsz= %5d kB  low_filesz= %5d kB\n", 
+		seg[SLOW].mem_size/1024, seg[SLOW].data_size/1024);
+	printf("real_memsz=%5d B   real_filesz=%5d B\n",
+		seg[SREAL].mem_size, seg[SREAL].data_size);
+	printf("high_memsz=%5d kB  high_filesz=%5d KB\n", 
+		seg[SHIGH].mem_size/1024, seg[SHIGH].data_size/1024);
+
+	/* Write the values back */
+	update_image(seg, &info);
+	if (is_elf) {
+		build_elf_header(seg, &info);
+		printf("elf_header_size=%d\n", seg[SEHDR].data_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;
+
+	/* Write destination file */
+	image_fd = checked_open(image, O_RDWR | O_CREAT | O_TRUNC, 0666);
+	for(i = 0; i < 4; i++) {
+		checked_lseek(image_fd, seg[i].file_offset, SEEK_SET, image);
+		checked_write(image_fd, seg[i].data, seg[i].data_size, image);
 	}
-	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;
 }
