diff -uNr linux-2.5.7/Documentation/i386/boot.txt linux-2.5.7.boot3.elf/Documentation/i386/boot.txt
--- linux-2.5.7/Documentation/i386/boot.txt	Sun Mar 10 20:05:16 2002
+++ linux-2.5.7.boot3.elf/Documentation/i386/boot.txt	Wed Apr  3 02:06:43 2002
@@ -127,7 +127,18 @@
 0224/2	2.01+	heap_end_ptr	Free memory after setup end
 0226/2	N/A	pad1		Unused
 0228/4	2.02+	cmd_line_ptr	32-bit pointer to the kernel command line
-022C/4	2.03+	initrd_addr_max	Highest legal initrd address
+022C/4	2.03+	ramdisk_max	Highest legal initrd address
+0230/2	2.04+	entry32_off	offset of 32bit entry point
+0230/2	2.04+	internal_cmdline_off	offset of compiled in command line
+0234/4	2.04+	low_base	0x1000
+0238/4	2.04+	low_memsz	Memory used @ 0x1000
+023C/4	2.04+	low_filesz	Precomputed data for 0x1000
+0240/4	2.04+	real_base	0x90000
+0244/4	2.04+	real_memsz	Memory used @ 0x90000
+0248/4	2.04+	real_filesz	Precomputed data for @ 0x90000
+024C/4	2.04+	high_memsz	Memory used @ 0x100000
+0250/4	2.04+	high_base	0x100000
+0254/4	2.04+	high_filesz	Amount of file used for the compressed kernel
 
 For backwards compatibility, if the setup_sects field contains 0, the
 real value is 4.
@@ -198,7 +209,7 @@
 	The initrd should typically be located as high in memory as
 	possible, as it may otherwise get overwritten by the early
 	kernel initialization sequence.	 However, it must never be
-	located above the address specified in the initrd_addr_max
+	located above the address specified in the ramdisk_max
 	field.	The initrd should be at least 4K page aligned.
 
   cmd_line_ptr:
@@ -219,6 +230,76 @@
 	if your ramdisk is exactly 131072 bytes long and this field is
 	0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
 
+  entry32_off:
+	The offset of the 32bit entry point from the real mode kernel.
+	For boot protocols 2.03 or earlier, this field is not present,
+	and there is no 32bit entry point.
+
+  internal_cmdline_off:
+	The offset of the null terminated compiled in command line
+	from the real mode kernel.   For boot protocols 2.03 or
+	earlier this field is not present, and there is no built in
+	command line.  The memory from internal_cmdline_off to
+	real_filesz is reserved for the compiled in command_line.  An
+	external utility may modify this command line.
+
+	To change the maximum size of the compiled in command line several
+	variables need to be modified.  real_filesz to indicate the
+	new maximum size.  setup_sects to indicate if the number of
+	sectors needed for the realmode kernel changes.  
+
+	A heap is maintained between real_filesz and real_memsz/heap_end_ptr.
+	Increasing the size of the heap is not a problem, decreasing
+	it is.  So when changing the real_filesz, real_memsz and
+	heap_end_ptr should also be changed.  real_memsz and
+	heap_end_ptr should always indicate the same maximum except
+	at runtime when a bootloader may indicate a larger heap is
+	present.
+
+  low_base, low_memsz, low_filesz, 
+  real_base, real_memsz, real_filesz, 
+  high_base, high_memsz, high_filesz:
+	Up to this point building a zImage or a bzImage has been a very lossy
+	process.  The introduction of these six variables attempts to
+	rectify that situation.  They document exactly which pieces
+	of memory, the kernel uses during the boot process, and they
+	indicate exactly how large the various data segments of the
+	kernel are.  It is now possible to create a lossless
+	transformation to and from a static ELF executable.
+
+	For a bzImage the low program segment describes the memory
+	from 4KB - 572KB the kernel decompressors uses as a temorary
+	buffer.  For a zImage the low program segment describes the
+	memory from 4KB - 572KB where the compressed kernel is loaded. 
+
+	For a bzImage the high program segment describes the memory
+	from 1MB on where the compressed kernel is loaded, where
+	decompression takes place, where the kernel initially runs,
+	and where the kernels bss segment is.  For a zImage the high
+	program segment describes the memory from 1MB on where the
+	kernel is decompressed to, where the kernel initial runs, and
+	where the kernels bss segment is located.
+
+	The real program segment describes the memory from 572KB
+	(0x90000) to 640KB (0xa0000) that the real mode kernel uses.
+	This region may be moved lower in memory if the BIOS has
+	reserved region for some other purpose.  When doing so
+	the following considerations should be applied.
+	
+		For a zImage you may move the real mode kernel now
+		lower than low_base + low_memsz.
+
+		For a bzImage if you move real_base below (low_base +
+		low_memsz) the following are the values of the other
+		variables.
+			low_memsz -= (low_base + low_memsz) - real_base
+			high_memsz += (low_base + low_memsz) - real_base
+		
+	
+	With this information it becomes safe to to statically
+	relocate the real mode kernel as well as dynamically relocate
+	it.  real_base should not be > 0x90000.
+
 
 **** THE KERNEL COMMAND LINE
 
@@ -247,6 +328,11 @@
 	The kernel command line *must* be within the memory region
 	covered by setup_move_size, so you may need to adjust this
 	field.
+
+If the protocol version is 2.04 or higher a compiled in command line
+may be present.  If this is the case the passed command line is
+appended onto the tail of the compiled command line.  Assuming
+there is room.
 
 
 **** SAMPLE BOOT CONFIGURATION
diff -uNr linux-2.5.7/Documentation/i386/zero-page.txt linux-2.5.7.boot3.elf/Documentation/i386/zero-page.txt
--- linux-2.5.7/Documentation/i386/zero-page.txt	Mon Aug 30 11:47:02 1999
+++ linux-2.5.7.boot3.elf/Documentation/i386/zero-page.txt	Tue Apr  2 11:41:31 2002
@@ -9,6 +9,8 @@
   arch/i386/boot/video.S
   arch/i386/kernel/head.S
   arch/i386/kernel/setup.c
+
+See include/asm-i386/boot_param.h a structure is kept there with uptodate information.
  
 
 Offset	Type		Description
@@ -65,7 +67,7 @@
 0x21c	unsigned long	INITRD_SIZE, size in bytes of ramdisk image
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
-0x2d0 - 0x600		E820MAP
+0x2d0 - 0x550		E820MAP
 
 0x800	string, 2K max	COMMAND_LINE, the kernel commandline as
 			copied using CL_OFFSET.
diff -uNr linux-2.5.7/Makefile linux-2.5.7.boot3.elf/Makefile
--- linux-2.5.7/Makefile	Wed Mar 20 07:18:30 2002
+++ linux-2.5.7.boot3.elf/Makefile	Tue Apr  2 22:26:28 2002
@@ -93,15 +93,6 @@
 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
 # set SVGA_MODE to whatever number you want.
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
diff -uNr linux-2.5.7/arch/i386/Config.help linux-2.5.7.boot3.elf/arch/i386/Config.help
--- linux-2.5.7/arch/i386/Config.help	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/Config.help	Wed Apr  3 02:07:21 2002
@@ -797,6 +797,28 @@
   a work-around for a number of buggy BIOSes. Switch this option on if
   your computer crashes instead of powering off properly.
 
+LinuxBIOS support
+CONFIG_LINUXBIOS
+  LinuxBIOS is an alternative GPL'd firmware initially for x86
+  compatible machines.  LinuxBIOS attempts to be a simple and as fast
+  as possible, and is initially optimized for linux.  The interface to
+  the OS is a table at the beginning of memory.  Which should make the
+  inevitable firmware bugs easier to work around, as should the source
+  code :)  A goal of this table is to provide enough information so
+  that any OS but especially linux does not need to have motherboard
+  specific knowledge.
+
+  This first release only provides LinuxBIOS detection (by detecting
+  it's table) and memory size detection. 
+
+  For more information on LinuxBIOS see http://www.linuxbios.org
+
+CONFIG_CMDLINE
+  Generally it is best to pass command line parameters via the
+  bootloader but there are times it is convinient not to do this.
+  This allows you to hard code a default kernel command line, whatever
+  the bootloader passes will be appended to it.
+
 CONFIG_TOSHIBA
   This adds a driver to safely access the System Management Mode of
   the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
diff -uNr linux-2.5.7/arch/i386/Makefile linux-2.5.7.boot3.elf/arch/i386/Makefile
--- linux-2.5.7/arch/i386/Makefile	Thu Apr 12 13:20:31 2001
+++ linux-2.5.7.boot3.elf/arch/i386/Makefile	Wed Apr  3 02:08:16 2002
@@ -18,7 +18,7 @@
 
 LD=$(CROSS_COMPILE)ld -m elf_i386
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
-LDFLAGS=-e stext
+LDFLAGS=
 LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
 
 CFLAGS += -pipe
@@ -118,6 +118,12 @@
 
 bzImage: vmlinux
 	@$(MAKEBOOT) bzImage
+
+zElf: vmlinux
+	@$(MAKEBOOT) zElf
+
+bzElf: vmlinux
+	@$(MAKEBOOT) bzElf
 
 compressed: zImage
 
diff -uNr linux-2.5.7/arch/i386/boot/Makefile linux-2.5.7.boot3.elf/arch/i386/boot/Makefile
--- linux-2.5.7/arch/i386/boot/Makefile	Sun Aug  5 14:13:19 2001
+++ linux-2.5.7.boot3.elf/arch/i386/boot/Makefile	Wed Apr  3 02:08:16 2002
@@ -12,13 +12,18 @@
 		$(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
+
+
+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
@@ -39,49 +44,43 @@
 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: 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 -o $@ $^
+
+brealmode: bbootsect.o bsetup.o
+	$(LD) -T realmode.lds -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/arch/i386/boot/bootsect.S linux-2.5.7.boot3.elf/arch/i386/boot/bootsect.S
--- linux-2.5.7/arch/i386/boot/bootsect.S	Sun Mar 10 20:07:02 2002
+++ linux-2.5.7.boot3.elf/arch/i386/boot/bootsect.S	Tue Apr  2 22:26:28 2002
@@ -54,7 +54,7 @@
 #endif
 
 .code16
-.text
+.section ".bootsect", "ax", @progbits
 
 .global _start
 _start:
@@ -71,7 +71,7 @@
 	cld
 	rep
 	movsw
-	ljmp	$INITSEG, $go
+	ljmp	$INITSEG, $go - _start
 
 # bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
 # wouldn't have to worry about this if we checked the top of memory.  Also
@@ -123,12 +123,12 @@
 # can be read, 15 if sector 15 can be read.  Otherwise guess 9.
 # Note that %cx = 0 from rep movsw above.
 
-	movw	$disksizes, %si		# table of sizes to try
+	movw	$disksizes - _start, %si	# table of sizes to try
 probe_loop:
 	lodsb
 	cbtw				# extend to word
-	movw	%ax, sectors
-	cmpw	$disksizes+4, %si
+	movw	%ax, sectors - _start
+	cmpw	$disksizes+4 - _start, %si
 	jae	got_sectors		# If all else fails, try 9
 
 	xchgw	%cx, %ax		# %cx = track and sector
@@ -146,7 +146,7 @@
 	movb	$0x07, %bl		# page 0, attribute 7 (normal)
 					# %bh is set above; int10 doesn't
 					# modify it
-	movw	$msg1, %bp
+	movw	$msg1 - _start, %bp
 	movw	$0x1301, %ax		# write string, move cursor
 	int	$0x10			# tell the user we're loading..
 
@@ -155,25 +155,25 @@
 # cylinder (for 9-sector 360K and 720K floppies).
 
 	movw	$0x0001, %ax		# set sread (sector-to-read) to 1 as
-	movw	$sread, %si		# the boot sector has already been read
+	movw	$sread - _start, %si	# the boot sector has already been read
 	movw	%ax, (%si)
 
 	call	kill_motor		# reset FDC
 	movw	$0x0200, %bx		# address = 512, in INITSEG
 next_step:
-	movb	setup_sects, %al
-	movw	sectors, %cx
+	movb	setup_sects - _start, %al
+	movw	sectors - _start, %cx
 	subw	(%si), %cx		# (%si) = sread
 	cmpb	%cl, %al
 	jbe	no_cyl_crossing
-	movw	sectors, %ax
+	movw	sectors - _start, %ax
 	subw	(%si), %ax		# (%si) = sread
 no_cyl_crossing:
 	call	read_track
 	pushw	%ax			# save it
 	call	set_next		# set %bx properly; it uses %ax,%cx,%dx
 	popw	%ax			# restore
-	subb	%al, setup_sects	# rest - for next step
+	subb	%al, setup_sects-_start	# rest - for next step
 	jnz	next_step
 
 	pushw	$SYSSEG
@@ -190,11 +190,11 @@
 # Segments are as follows: %cs = %ds = %ss = INITSEG,
 #	%es = SYSSEG, %fs = 0, %gs is unused.
 
-	movw	root_dev, %ax
+	movw	root_dev-_start, %ax
 	orw	%ax, %ax
 	jne	root_defined
 
-	movw	sectors, %bx
+	movw	sectors-_start, %bx
 	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb
 	cmpw	$15, %bx
 	je	root_defined
@@ -209,7 +209,7 @@
 
 	movb	$0, %al			# /dev/fd0 - autodetect
 root_defined:
-	movw	%ax, root_dev
+	movw	%ax, root_dev-_start
 
 # After that (everything loaded), we jump to the setup-routine
 # loaded directly after the bootblock:
@@ -242,13 +242,13 @@
 	shr	$4, %cx
 	add	%cx, %ax		# check offset
 #endif
-	cmpw	syssize, %ax		# have we loaded everything yet?
+	cmpw	syssize-_start, %ax	# have we loaded everything yet?
 	jbe	ok1_read
 
 	ret
 
 ok1_read:
-	movw	sectors, %ax
+	movw	sectors-_start, %ax
 	subw	(%si), %ax		# (%si) = sread
 	movw	%ax, %cx
 	shlw	$9, %cx
@@ -297,7 +297,7 @@
 set_next:
 	movw	%ax, %cx
 	addw	(%si), %ax		# (%si) = sread
-	cmp	sectors, %ax
+	cmp	sectors-_start, %ax
 	jne	ok3_set
 	movw	$0x0001, %ax
 	xorw	%ax, 2(%si)		# change head
Binary files linux-2.5.7/arch/i386/boot/bzElf and linux-2.5.7.boot3.elf/arch/i386/boot/bzElf differ
diff -uNr linux-2.5.7/arch/i386/boot/compressed/head.S linux-2.5.7.boot3.elf/arch/i386/boot/compressed/head.S
--- linux-2.5.7/arch/i386/boot/compressed/head.S	Wed Jul  5 13:03:12 2000
+++ linux-2.5.7.boot3.elf/arch/i386/boot/compressed/head.S	Tue Apr  2 11:46:18 2002
@@ -25,24 +25,30 @@
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
+#include <asm/boot.h>
 
 	.globl startup_32
 	
 startup_32:
 	cld
 	cli
-	movl $(__KERNEL_DS),%eax
-	movl %eax,%ds
-	movl %eax,%es
-	movl %eax,%fs
-	movl %eax,%gs
 
-	lss SYMBOL_NAME(stack_start),%esp
-	xorl %eax,%eax
-1:	incl %eax		# check that A20 really IS enabled
-	movl %eax,0x000000	# loop forever if it isn't
-	cmpl %eax,0x100000
-	je 1b
+	/*
+	 * Save the initial registers
+	 */
+	movl %eax, eax
+	movl %ebx, ebx
+	movl %ecx, ecx
+	movl %edx, edx
+	movl %esi, esi
+	movl %edi, edi
+	movl %esp, esp
+	movl %ebp, ebp
+
+	/*
+	 * Setup the stack
+	 */
+	movl SYMBOL_NAME(stack_start), %esp
 
 /*
  * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
@@ -66,16 +72,10 @@
  */
 	subl $16,%esp	# place for structure on the stack
 	movl %esp,%eax
-	pushl %esi	# real mode pointer as second arg
 	pushl %eax	# address of structure as first arg
 	call SYMBOL_NAME(decompress_kernel)
 	orl  %eax,%eax 
-	jnz  3f
-	popl %esi	# discard address
-	popl %esi	# real mode pointer
-	xorl %ebx,%ebx
-	ljmp $(__KERNEL_CS), $0x100000
-
+	jz out
 /*
  * We come here, if we were loaded high.
  * We need to move the move-in-place routine down to 0x1000
@@ -83,8 +83,20 @@
  * which we got from the stack.
  */
 3:
-	movl $move_routine_start,%esi
-	movl $0x1000,%edi
+	/* Relocate the move routine */
+	movl $move_routine_start,%esi	#src
+	movl $MOVE_ROUTINE_BASE,%edi	#dest
+	movl %edi, %eax 
+	subl %esi, %eax			# The relocation factor
+	addl %eax, reloc1
+	addl %eax, reloc2
+	addl %eax, reloc3
+	addl %eax, reloc4
+	addl %eax, reloc5
+	addl %eax, reloc6
+	addl %eax, reloc7
+	addl %eax, reloc8
+	addl %eax, reloc9
 	movl $move_routine_end,%ecx
 	subl %esi,%ecx
 	addl $3,%ecx
@@ -93,19 +105,21 @@
 	rep
 	movsl
 
+	/* Load it's arguments and jump to the move routine */
 	popl %esi	# discard the address
-	popl %ebx	# real mode pointer
 	popl %esi	# low_buffer_start
 	popl %ecx	# lcount
 	popl %edx	# high_buffer_start
 	popl %eax	# hcount
 	movl $0x100000,%edi
 	cli		# make sure we don't get interrupted
-	ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
+	movl $MOVE_ROUTINE_BASE, %ebx	# and jump to the move routine
+	jmpl %ebx
 
 /*
  * Routine (template) for moving the decompressed kernel in place,
- * if we were high loaded. This _must_ PIC-code !
+ * if we were high loaded. This _must_ be PIC-code !
+ * Or it must be anotated with lables so it can be manually relocated.
  */
 move_routine_start:
 	movl %ecx,%ebp
@@ -122,7 +136,34 @@
 	shrl $2,%ecx
 	rep
 	movsl
-	movl %ebx,%esi	# Restore setup pointer
-	xorl %ebx,%ebx
-	ljmp $(__KERNEL_CS), $0x100000
+out:
+	.byte 0xa1		# movl eax,  %eax
+reloc1:	.long eax
+	.byte 0x8b, 0x1d	# movl ebx,  %ebx
+reloc2:	.long ebx
+	.byte 0x8b, 0x0d	# movl ecx,  %ecx
+reloc3:	.long ecx
+	.byte 0x8b, 0x15	# movl edx, %edx
+reloc4:	.long edx
+	.byte 0x8b, 0x35	# movl esi, %esi
+reloc5:	.long esi
+	.byte 0x8b, 0x3d	# movl edi, %edi
+reloc6:	.long edi
+	.byte 0x8b, 0x25	# movl esp, %esp
+reloc7:	.long esp
+	.byte 0x8b, 0x2d	# movl ebp, %ebp
+reloc8:	.long ebp
+	.byte 0xff, 0x25	# jmpl *(kernel_start)
+reloc9:	.long kernel_start
+ENTRY(initial_regs)
+eax:	.long 0x12345678 /* eax */
+ebx:	.long 0x12345678 /* ebx */
+ecx:	.long 0x12345678 /* ecx */
+edx:	.long 0x12345678 /* edx */
+esi:	.long 0x12345678 /* esi */
+edi:	.long 0x12345678 /* edi */
+esp:	.long 0x12345678 /* esp */
+ebp:	.long 0x12345678 /* ebp */
+kernel_start:
+	.long 0x100000
 move_routine_end:
diff -uNr linux-2.5.7/arch/i386/boot/compressed/misc.c linux-2.5.7.boot3.elf/arch/i386/boot/compressed/misc.c
--- linux-2.5.7/arch/i386/boot/compressed/misc.c	Mon Nov 12 10:59:43 2001
+++ linux-2.5.7.boot3.elf/arch/i386/boot/compressed/misc.c	Tue Apr  2 11:46:18 2002
@@ -13,6 +13,10 @@
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
 #include <asm/io.h>
+#include <linux/apm_bios.h>
+#include <asm/e820.h>
+#include <asm/boot_param.h>
+#include <asm/boot.h>
 
 /*
  * gzip declarations
@@ -84,13 +88,9 @@
 /*
  * This is set up by the setup-routine at boot-time
  */
-static unsigned char *real_mode; /* Pointer to real-mode data */
-
-#define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
-#ifndef STANDARD_MEMORY_BIOS_CALL
-#define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
-#endif
-#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+static struct boot_params *real_mode; /* Pointer to real-mode data */
+/* Amount of memory in kilobytes, if it isn't set assume enough */
+static unsigned long mem_k = 0xFFFFFFFF;
 
 extern char input_data[];
 extern int input_len;
@@ -112,10 +112,6 @@
 static long free_mem_ptr = (long)&end;
 static long free_mem_end_ptr;
 
-#define INPLACE_MOVE_ROUTINE  0x1000
-#define LOW_BUFFER_START      0x2000
-#define LOW_BUFFER_MAX       0x90000
-#define HEAP_SIZE             0x3000
 static unsigned int low_buffer_end, low_buffer_size;
 static int high_loaded =0;
 static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
@@ -171,13 +167,17 @@
 		vidmem[i] = ' ';
 }
 
+static int vid_initialized = 0;
 static void puts(const char *s)
 {
 	int x,y,pos;
 	char c;
 
-	x = SCREEN_INFO.orig_x;
-	y = SCREEN_INFO.orig_y;
+	if (!vid_initialized)
+		return;
+
+	x = real_mode->screen.info.orig_x;
+	y = real_mode->screen.info.orig_y;
 
 	while ( ( c = *s++ ) != '\0' ) {
 		if ( c == '\n' ) {
@@ -198,8 +198,8 @@
 		}
 	}
 
-	SCREEN_INFO.orig_x = x;
-	SCREEN_INFO.orig_y = y;
+	real_mode->screen.info.orig_x = x;
+	real_mode->screen.info.orig_y = y;
 
 	pos = (x + cols * y) * 2;	/* Update cursor position */
 	outb_p(14, vidport);
@@ -208,6 +208,21 @@
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
+static void vid_puts_init(void)
+{
+	vid_initialized = 1;
+	if (real_mode->screen.info.orig_video_mode == 7) {
+		vidmem = (char *) 0xb0000;
+		vidport = 0x3b4;
+	} else {
+		vidmem = (char *) 0xb8000;
+		vidport = 0x3d4;
+	}
+	
+	lines = real_mode->screen.info.orig_video_lines;
+	cols = real_mode->screen.info.orig_video_cols;
+}
+
 static void* memset(void* s, int c, size_t n)
 {
 	int i;
@@ -302,16 +317,14 @@
 
 struct {
 	long * a;
-	short b;
-	} stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS };
+	} stack_start = { & user_stack [STACK_SIZE] };
+
+extern struct initial_regs32 initial_regs;
+extern __u32 kernel_start;
 
 static void setup_normal_output_buffer(void)
 {
-#ifdef STANDARD_MEMORY_BIOS_CALL
-	if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
-#else
-	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n");
-#endif
+	if (mem_k < 2048)  error("Less than 2MB of memory.\n");
 	output_data = (char *)0x100000; /* Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
 }
@@ -324,11 +337,7 @@
 static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
 {
 	high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
-#ifdef STANDARD_MEMORY_BIOS_CALL
-	if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
-#else
-	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n");
-#endif	
+	if (mem_k < (4*1024))  error("Less than 4MB of memory.\n");
 	mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
 	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
 	  ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
@@ -341,6 +350,7 @@
 	}
 	else mv->hcount = -1;
 	mv->high_buffer_start = high_buffer_start;
+	if ((ulg)output_data >= low_buffer_end) output_data=high_buffer_start;
 }
 
 static void close_output_buffer_if_we_run_high(struct moveparams *mv)
@@ -356,20 +366,26 @@
 }
 
 
-asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
+asmlinkage int decompress_kernel(struct moveparams *mv)
 {
-	real_mode = rmode;
-
-	if (SCREEN_INFO.orig_video_mode == 7) {
-		vidmem = (char *) 0xb0000;
-		vidport = 0x3b4;
-	} else {
-		vidmem = (char *) 0xb8000;
-		vidport = 0x3d4;
+	/* If we don't know better assume we can't use any
+	 * real mode memory, and we have enough protected mode memory.
+	 */
+	real_mode = 0;
+	if ((initial_regs.ebp == ENTRY16) || (initial_regs.ebp == ENTRY32)) {
+		real_mode = (struct boot_params *)initial_regs.esi;
 	}
+	if (initial_regs.ebp == ENTRY16) {
+		vid_puts_init();
 
-	lines = SCREEN_INFO.orig_video_lines;
-	cols = SCREEN_INFO.orig_video_cols;
+		mem_k = real_mode->screen.overlap.ext_mem_k;
+#ifndef STANDARD_MEMORY_BIOS_CALL
+		if (real_mode->alt_mem_k > mem_k) {
+			mem_k = real_mode->alt_mem_k;
+		}
+#endif
+		mem_k += 1024;
+	}
 
 	if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
 	else setup_output_buffer_if_we_run_high(mv);
diff -uNr linux-2.5.7/arch/i386/boot/realmode.lds linux-2.5.7.boot3.elf/arch/i386/boot/realmode.lds
--- linux-2.5.7/arch/i386/boot/realmode.lds	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot3.elf/arch/i386/boot/realmode.lds	Wed Apr  3 02:06:43 2002
@@ -0,0 +1,20 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+ENTRY(entry32)
+OUTPUT_ARCH(i386)
+SECTIONS
+{
+	. = 0x90000;
+	.bootsect : {
+		*(.bootsect)
+	}
+	. = 0x90200;
+	.setup : {
+		*(.setup)
+	}
+	.setup.heap : {
+		*(.setup.heap)
+	}
+	/DISCARD/ : {
+		*(*)
+	}
+}
diff -uNr linux-2.5.7/arch/i386/boot/setup.S linux-2.5.7.boot3.elf/arch/i386/boot/setup.S
--- linux-2.5.7/arch/i386/boot/setup.S	Sun Mar 10 20:05:20 2002
+++ linux-2.5.7.boot3.elf/arch/i386/boot/setup.S	Wed Apr  3 02:06:43 2002
@@ -42,6 +42,12 @@
  * if CX/DX have been changed in the e801 call and if so use AX/BX .
  * Michael Miller, April 2001 <michaelm@mjmm.org>
  *
+ * Update boot protocol to version 2.04
+ * - Add support for a compiled in command line.
+ * - Add support for a 32bit kernel entry point
+ * - Stop information loss when bzImage is created
+ * Eric Biederman 29 March 2002 <ebiederm@xmission.com>
+ *
  */
 
 #include <linux/config.h>
@@ -56,6 +62,20 @@
 #define SIG1	0xAA55
 #define SIG2	0x5A5A
 
+/* Segments used by setup.S */
+#define __SETUP_CS      0x10
+#define __SETUP_DS      0x18
+#define __SETUP_REAL_CS 0x20
+#define __SETUP_REAL_DS 0x28
+
+#define MIN_HEAP_SIZE 1024
+
+#ifndef __BIG_KERNEL__
+#define KERNEL_START 0x1000		/* zImage */
+#else
+#define KERNEL_START 0x100000 		/* bzImage */
+#endif
+
 INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
 SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
 SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
@@ -64,15 +84,10 @@
 DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
 
 .code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
+.globl _setup, _esetup
 
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
+.section ".setup", "ax", @progbits
+_setup:	
 
 start:
 	jmp	trampoline
@@ -80,14 +95,15 @@
 # This is the setup header, and it must start at %cs:2 (old 0x9020:2)
 
 		.ascii	"HdrS"		# header signature
-		.word	0x0203		# header version number (>= 0x0105)
+		.word	0x0204		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
-start_sys_seg:	.word	SYSSEG
-		.word	kernel_version	# pointing to kernel version string
+start_sys_seg:				# pointing to kernel version string
 					# above section of header is compatible
 					# with loadlin-1.5 (header v1.5). Don't
 					# change it.
+		.word	SYSSEG
+		.word	kernel_version - start
 
 type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
 					#      Bootlin, SYSLX, bootsect...)
@@ -115,13 +131,8 @@
 					# loader knows how much data behind
 					# us also needs to be loaded.
 
-code32_start:				# here loaders can put a different
+code32_start:	.long	KERNEL_START	# here loaders can put a different
 					# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-		.long	0x1000		#   0x1000 = default for zImage
-#else
-		.long	0x100000	# 0x100000 = default for big kernel
-#endif
 
 ramdisk_image:	.long	0		# address of loaded ramdisk image
 					# Here the loader puts the 32-bit
@@ -131,11 +142,12 @@
 ramdisk_size:	.long	0		# its size in bytes
 
 bootsect_kludge:
-		.word  bootsect_helper, SETUPSEG
+		.word	bootsect_helper - start, SETUPSEG
 
-heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
+heap_end_ptr:	.word	_esetup_heap - start
+					# (Header version 0x0201 or later)
 					# space from here (exclusive) down to
-					# end of setup code can be used by setup
+					# heap_start can be used by setup
 					# for local heap purposes.
 
 pad1:		.word	0
@@ -158,8 +170,39 @@
 					# The highest safe address for
 					# the contents of an initrd
 
+entry32_off:	.word	entry32 - start + (DELTA_INITSEG << 4)
+					# offset of the 32bit entry point
+					# relative to the start of
+					# the real mode kernel
+
+internal_cmdline_off:			# offset of compiled in	command line
+		.word	internal_command_line - start + (DELTA_INITSEG << 4)
+
+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_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
+high_memsz:	.long	0x00000000	# Size of high buffer @	0x100000
+high_filesz:	.long	0x00000000	# Datasize of the linux kernel
+# variables private to the kernel (not for bootloaders)
+entry32_used:	.long 0x00000000
+entry32_16_off:	.long protected_to_real - start + (DELTA_INITSEG << 4)
+eax:		.long 0x00000000
+ebx:		.long 0x00000000
+ecx:		.long 0x00000000
+edx:		.long 0x00000000
+esi:		.long 0x00000000
+edi:		.long 0x00000000
+esp:		.long 0x00000000
+ebp:		.long 0x00000000
 trampoline:	call	start_of_setup
-		.space	1024
+		# Don't let the E820 map overlap code
+		. = (0x2d0 - 0x200) + (E820MAX * E820ENTRY_SIZE)
 # End of setup header #####################################################
 
 start_of_setup:
@@ -179,10 +222,10 @@
 	movw	%cs, %ax		# aka SETUPSEG
 	movw	%ax, %ds
 # Check signature at end of setup
-	cmpw	$SIG1, setup_sig1
+	cmpw	$SIG1, setup_sig1 - start
 	jne	bad_sig
 
-	cmpw	$SIG2, setup_sig2
+	cmpw	$SIG2, setup_sig2 - start
 	jne	bad_sig
 
 	jmp	good_sig1
@@ -233,7 +276,7 @@
 	movw	%bx, %cx
 	shrw	$3, %bx				# convert to segment
 	addw	$SYSSEG, %bx
-	movw	%bx, %cs:start_sys_seg
+	movw	%bx, %cs:start_sys_seg - start
 # Move rest of setup code/data to here
 	movw	$2048, %di			# four sectors loaded by LILO
 	subw	%si, %si
@@ -245,16 +288,16 @@
 	movsw
 	movw	%cs, %ax			# aka SETUPSEG
 	movw	%ax, %ds
-	cmpw	$SIG1, setup_sig1
+	cmpw	$SIG1, setup_sig1 - start
 	jne	no_sig
 
-	cmpw	$SIG2, setup_sig2
+	cmpw	$SIG2, setup_sig2 - start
 	jne	no_sig
 
 	jmp	good_sig
 
 no_sig:
-	lea	no_sig_mess, %si
+	lea	no_sig_mess - start, %si
 	call	prtstr
 
 no_sig_loop:
@@ -266,16 +309,16 @@
 	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
 	movw	%ax, %ds
 # Check if an old loader tries to load a big-kernel
-	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
+	testb	$LOADED_HIGH, %cs:loadflags - start	# Do we have a big kernel?
 	jz	loader_ok			# No, no danger for old loaders.
 
-	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
+	cmpb	$0, %cs:type_of_loader - start	# Do we have a loader that
 						# can deal with us?
 	jnz	loader_ok			# Yes, continue.
 
 	pushw	%cs				# No, we have an old loader,
 	popw	%ds				# die. 
-	lea	loader_panic_mess, %si
+	lea	loader_panic_mess - start, %si
 	call	prtstr
 
 	jmp	no_sig_loop
@@ -334,7 +377,7 @@
 
 	incb	(E820NR)
 	movw	%di, %ax
-	addw	$20, %ax
+	addw	$E820ENTRY_SIZE, %ax
 	movw	%ax, %di
 again820:
 	cmpl	$0, %ebx			# check to see if
@@ -541,10 +584,10 @@
 #endif
 
 # Now we want to move to protected mode ...
-	cmpw	$0, %cs:realmode_swtch
+	cmpw	$0, %cs:realmode_swtch - start
 	jz	rmodeswtch_normal
 
-	lcall	*%cs:realmode_swtch
+	lcall	*%cs:realmode_swtch - start
 
 	jmp	rmodeswtch_end
 
@@ -555,12 +598,12 @@
 rmodeswtch_end:
 # we get the code32 start address and modify the below 'jmpi'
 # (loader may have changed it)
-	movl	%cs:code32_start, %eax
-	movl	%eax, %cs:code32
+	movl	%cs:code32_start - start, %eax
+	movl	%eax, %cs:code32 - start
 
 # Now we move the system to its rightful place ... but we check if we have a
 # big-kernel. In that case we *must* not move it ...
-	testb	$LOADED_HIGH, %cs:loadflags
+	testb	$LOADED_HIGH, %cs:loadflags - start
 	jz	do_move0			# .. then we have a normal low
 						# loaded zImage
 						# .. or else we have a high
@@ -571,7 +614,7 @@
 	movw	$0x100, %ax			# start of destination segment
 	movw	%cs, %bp			# aka SETUPSEG
 	subw	$DELTA_INITSEG, %bp		# aka INITSEG
-	movw	%cs:start_sys_seg, %bx		# start of source segment
+	movw	%cs:start_sys_seg - start, %bx	# start of source segment
 	cld
 do_move:
 	movw	%ax, %es			# destination segment
@@ -597,9 +640,9 @@
 	movw	%ax, %ds
 		
 # Check whether we need to be downward compatible with version <=201
-	cmpl	$0, cmd_line_ptr
+	cmpl	$0, cmd_line_ptr - start
 	jne	end_move_self		# loader uses version >=202 features
-	cmpb	$0x20, type_of_loader
+	cmpb	$0x20, type_of_loader - start
 	je	end_move_self		# bootsect loader, we know of it
 
 # Boot loader doesnt support boot protocol version 2.02.
@@ -627,20 +670,20 @@
 	movw	%ax, %ds
 	movw	$INITSEG, %ax			# real INITSEG
 	movw	%ax, %es
-	movw	%cs:setup_move_size, %cx
+	movw	%cs:setup_move_size - start, %cx
 	std					# we have to move up, so we use
 						# direction down because the
 						# areas may overlap
 	movw	%cx, %di
 	decw	%di
 	movw	%di, %si
-	subw	$move_self_here+0x200, %cx
+	subw	$move_self_here+0x200 -start, %cx
 	rep
 	movsb
-	ljmp	$SETUPSEG, $move_self_here
+	ljmp	$SETUPSEG, $move_self_here -start
 
 move_self_here:
-	movw	$move_self_here+0x200, %cx
+	movw	$move_self_here+0x200-start, %cx
 	rep
 	movsb
 	movw	$SETUPSEG, %ax
@@ -716,10 +759,10 @@
 
 	# A20 is still not responding.  Try frobbing it again.
 	# 
-	decb	(a20_tries)
+	decb	(a20_tries - start)
 	jnz	a20_try_loop
 	
-	movw	$a20_err_msg, %si
+	movw	$a20_err_msg - start, %si
 	call	prtstr
 
 a20_die:
@@ -737,13 +780,13 @@
 a20_done:
 
 # set up gdt and idt
-	lidt	idt_48				# load idt with 0,0
+	lidt	idt_48 - start			# load idt with 0,0
 	xorl	%eax, %eax			# Compute gdt_base
 	movw	%ds, %ax			# (Convert %ds:gdt to a linear ptr)
 	shll	$4, %eax
-	addl	$gdt, %eax
-	movl	%eax, (gdt_48+2)
-	lgdt	gdt_48				# load gdt with whatever is
+	addl	$gdt - start, %eax
+	movl	%eax, (gdt_48+2 - start)
+	lgdt	gdt_48 - start			# load gdt with whatever is
 						# appropriate
 
 # make sure any possible coprocessor is properly reset..
@@ -781,13 +824,22 @@
 	jmp	flush_instr
 
 flush_instr:
-	xorw	%bx, %bx			# Flag to indicate a boot
 	xorl	%esi, %esi			# Pointer to real-mode code
 	movw	%cs, %si
 	subw	$DELTA_INITSEG, %si
 	shll	$4, %esi			# Convert to 32-bit pointer
+	movl	$ENTRY16, %ebp			# Magic to indicate 16bit entry
+
+# Setup the data segments
+	movw	$(__SETUP_DS), %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+	movw	%ax, %ss
+
 # NOTE: For high loaded big kernels we need a
-#	jmpi    0x100000,__KERNEL_CS
+#	jmpi    0x100000,__SETUP_CS
 #
 #	but we yet haven't reloaded the CS register, so the default size 
 #	of the target offset still is 16 bit.
@@ -798,7 +850,7 @@
 	.byte 0x66, 0xea			# prefix + jmpi-opcode
 code32:	.long	0x1000				# will be set to 0x100000
 						# for big kernels
-	.word	__KERNEL_CS
+	.word	__SETUP_CS
 
 # Here's a bunch of information about your current kernel..
 kernel_version:	.ascii	UTS_RELEASE
@@ -824,15 +876,15 @@
 # Because there is no place left in the 512 bytes of the boot sector,
 # we must emigrate to code space here.
 bootsect_helper:
-	cmpw	$0, %cs:bootsect_es
+	cmpw	$0, %cs:bootsect_es - start
 	jnz	bootsect_second
 
-	movb	$0x20, %cs:type_of_loader
+	movb	$0x20, %cs:type_of_loader - start
 	movw	%es, %ax
 	shrw	$4, %ax
-	movb	%ah, %cs:bootsect_src_base+2
+	movb	%ah, %cs:bootsect_src_base+2 - start
 	movw	%es, %ax
-	movw	%ax, %cs:bootsect_es
+	movw	%ax, %cs:bootsect_es - start
 	subw	$SYSSEG, %ax
 	lret					# nothing else to do for now
 
@@ -846,15 +898,15 @@
 	movw	$0x8000, %cx			# full 64K, INT15 moves words
 	pushw	%cs
 	popw	%es
-	movw	$bootsect_gdt, %si
+	movw	$bootsect_gdt - start, %si
 	movw	$0x8700, %ax
 	int	$0x15
 	jc	bootsect_panic			# this, if INT15 fails
 
-	movw	%cs:bootsect_es, %es		# we reset %es to always point
-	incb	%cs:bootsect_dst_base+2		# to 0x10000
+	movw	%cs:bootsect_es -start, %es	# we reset %es to always point
+	incb	%cs:bootsect_dst_base+2 -start	# to 0x10000
 bootsect_ex:
-	movb	%cs:bootsect_dst_base+2, %ah
+	movb	%cs:bootsect_dst_base+2 -start, %ah
 	shlb	$4, %ah				# we now have the number of
 						# moved frames in %ax
 	xorb	%al, %al
@@ -892,7 +944,7 @@
 	pushw	%cs
 	popw	%ds
 	cld
-	leaw	bootsect_panic_mess, %si
+	leaw	bootsect_panic_mess -start, %si
 	call	prtstr
 	
 bootsect_panic_loop:
@@ -990,29 +1042,174 @@
 	outb	%al,$0x80
 	ret
 
+	.code32
+	.globl entry32
+entry32:
+	testl	%esp, %esp
+	jnz	1f
+	/* If there isn't a valid stack pointer
+	 * Assume setup.S is loaded at INITSEG,
+	 * and setup a stack pointer just below that.
+	 */
+	movl	%esp, ((INITSEG << 4) - 4)
+	movl	$((INITSEG << 4) - 4), %esp
+	jmp	2f
+1:	pushl	%esp
+2:	pushl	%esi
+	call	3f
+3:	popl	%esi
+	subl	$(3b - start), %esi
+	movl	%eax, eax - start(%esi)
+	movl	%ebx, ebx - start(%esi)
+	movl	%ebx, ebx - start(%esi)
+	movl	%ecx, ecx - start(%esi)
+	movl	%edx, edx - start(%esi)
+	popl	%eax
+	movl	%eax, esi - start(%esi)
+	movl	%edi, edi - start(%esi)
+	movl	%ebp, ebp - start(%esi)
+	popl	%esp
+	movl	%esp, esp - start(%esi)
+
+	/* Magic to indicate 32bit entry */
+	movl	$ENTRY32, %ebp
+	movl	%ebp, entry32_used - start(%esi)
+
+	/* Pointer to real mode code */
+	subl	$(DELTA_INITSEG << 4), %esi
+
+	/* Start address for 32-bit code */
+	movl	$KERNEL_START, %ebx
+	jmpl	*%ebx
+
+protected_to_real:
+	cli
+	/* Get pointer to start */
+	call	1f
+1:	popl	%esi
+	subl	$(1b - start), %esi
+
+	/* Fixup my real mode segment */
+	movl	%esi, %eax
+	shrl	$4, %eax
+	movw	%ax, 2 + realptr - start(%esi)
+
+	/* Compute the gdt fixup */
+	movl	%esi, %eax
+	shll	$16, %eax			# Base low
+
+	movl	%esi, %ebx
+	shrl	$16, %ebx
+	andl	$0xff, %ebx
+
+	movl	%esi, %edx
+	andl	$0xff000000, %edx
+	orl	%edx, %ebx			# Base high
+
+	/* Fixup the gdt */
+	andl	$0x0000ffff, (gdt - start + __SETUP_REAL_CS)(%esi)
+	orl	%eax,        (gdt - start + __SETUP_REAL_CS)(%esi)
+	andl	$0x00ffff00, (gdt - start + __SETUP_REAL_CS + 4)(%esi)
+	orl	%ebx,        (gdt - start + __SETUP_REAL_CS + 4)(%esi)
+	andl	$0x0000ffff, (gdt - start + __SETUP_REAL_DS)(%esi)
+	orl	%eax,        (gdt - start + __SETUP_REAL_DS)(%esi)
+	andl	$0x00ffff00, (gdt - start + __SETUP_REAL_DS + 4)(%esi)
+	orl	%ebx,        (gdt - start + __SETUP_REAL_DS + 4)(%esi)
+
+	/* Fixup gdt_48 */
+	leal	gdt - start(%esi), %eax		# Compute gdt_base
+	movl	%eax, gdt_48 +2 - start(%esi)	# Store gdt_base
+
+	/* Setup the classic BIOS interrupt table at 0x0 */
+	lidt	idt_real - start(%esi)
+	
+	/* Load 16bit segments we can use */
+	lgdt	gdt_48 - start(%esi)
+
+	/* Don't disable the a20 line, (this shouldn't be required) */
+
+	/* Load 16bit data segments, to ensure the segment limits are set */
+	movl	$__SETUP_REAL_DS, %ebx
+	movl	%ebx, %ds
+	movl	%ebx, %es
+	movl	%ebx, %ss
+	movl	%ebx, %fs
+	movl	%ebx, %gs
+
+	/* switch to 16bit mode */
+	ljmp	$__SETUP_REAL_CS, $1f - start
+1:
+	.code16
+	/* Disable Paging and protected mode */
+	/* clear the PG & PE bits of CR0 */
+	movl	%cr0,%eax
+	andl	$~((1 << 31)|(1<<0)),%eax
+	movl	%eax,%cr0
+
+	/* make intersegment jmp to flush the processor pipeline
+	 * and reload %cs:%eip (to clear upper 16 bits of %eip).
+	 */
+	ljmp	*(realptr - start)
+2:
+	/* we are in real mode now
+	 * set up the real mode segment registers : %ds, %ss, %es, %gs, %fs
+	 */
+	movw	%cs, %ax
+	/* Put the data segments in INITSEG */
+	subw	$DELTA_INITSEG, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+	/* Put ss:sp just below INITSEG */
+	subw	$0x800, %ax
+	movw	%ax, %ss
+	movw	$0x8000, %sp
+	jmp	start
+	
+realptr:
+	.word	2b - start
+	.word	0x0000
+
 # Descriptor tables
 gdt:
 	.word	0, 0, 0, 0			# dummy
 	.word	0, 0, 0, 0			# unused
 
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
+	.word	0xFFFF				# 32bit 4GB - (0x100000*0x1000 = 4GB)
 	.word	0				# base address = 0
-	.word	0x9A00				# code read/exec
-	.word	0x00CF				# granularity = 4096, 386
+	.byte	0x00, 0x9B			# code read/exec/accessed
+	.byte	0xCF, 0x00			# granularity = 4096, 386
 						#  (+5th nibble of limit)
 
-	.word	0xFFFF				# 4Gb - (0x100000*0x1000 = 4Gb)
+	.word	0xFFFF				# 32bit 4GB - (0x100000*0x1000 = 4GB)
 	.word	0				# base address = 0
-	.word	0x9200				# data read/write
-	.word	0x00CF				# granularity = 4096, 386
+	.byte	0x00, 0x93			# data read/write/accessed
+	.byte	0xCF, 0x00			# granularity = 4096, 386
 						#  (+5th nibble of limit)
+
+	.word	0xFFFF				# 16bit 64KB - (0x10000*1 = 64KB)
+	.word	0				# base address = SETUPSEG
+	.byte	0x00, 0x9b			# code read/exec/accessed
+	.byte	0x00, 0x00			# granularity = bytes
+
+
+	.word	0xFFFF				# 16bit 64KB - (0x10000*1 = 64KB)
+	.word	0				# base address = SETUPSEG
+	.byte	0x00, 0x93			# data read/write/accessed
+	.byte	0x00, 0x00			# granularity = bytes
+gdt_end:
+	
 idt_48:
 	.word	0				# idt limit = 0
 	.word	0, 0				# idt base = 0L
-gdt_48:
-	.word	0x8000				# gdt limit=2048,
-						#  256 GDT entries
 
+idt_real:
+	.word	0x400 - 1			# idt limit ( 256 entries)
+	.word	0, 0				# idt base = 0L
+	
+gdt_48:
+	.word	gdt_end - gdt - 1		# gdt limit
 	.word	0, 0				# gdt base (filled in later)
 
 # Include video setup & detection code
@@ -1025,12 +1222,10 @@
 
 # After this point, there is some free space which is used by the video mode
 # handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
+internal_command_line:
+	.asciz CONFIG_CMDLINE
+_esetup:
+.section ".setup.heap", "a", @nobits
+_setup_heap:
+. = MIN_HEAP_SIZE
+_esetup_heap:
diff -uNr linux-2.5.7/arch/i386/boot/tools/build.c linux-2.5.7.boot3.elf/arch/i386/boot/tools/build.c
--- linux-2.5.7/arch/i386/boot/tools/build.c	Mon Jul  2 14:56:40 2001
+++ linux-2.5.7.boot3.elf/arch/i386/boot/tools/build.c	Wed Apr  3 02:10:09 2002
@@ -1,19 +1,24 @@
+
 /*
  *  $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
+ *  Copyright (C) 2002 Eric Biederman
+ *
  */
 
 /*
  * 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.
  */
 
@@ -22,32 +27,124 @@
  * 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 these headers */
+#include <linux/version.h>
+#include <linux/compile.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;
+/* Segments of the output file */
+#define SEHDR 0
+#define SREAL 1
+#define SLOW  2
+#define SHIGH 3
+#define SEGS  4
+
+/* 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. */
+
+
+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 +155,544 @@
 	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 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;
+	
+}
+
+static 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;
+}
+
+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 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 file_seg *seg)
+{
+	int i, j;
+	Elf32_Phdr *phdr, *plow, *phigh;
+	size_t phdr_size;
+	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);
+	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;
+		if (least != phdr +i) {
+			Elf32_Phdr tmp;
+			tmp = phdr[i];
+			phdr[i] = *least;
+			*least = tmp;
+		}
 	}
-	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+	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;
+		seg->mem_addr = start;
+		seg->mem_size = end - start;
+		seg->data_size = middle - start;
+	}
+	return phdr;
+	
+}
 
-	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;
+static void get_elf_sizes(char *name, size_t pstart, struct file_seg *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 (sizes->mem_addr != 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 read_elf(char *name, size_t pstart, struct file_seg *seg)
+{
+	int src_fd;
+	Elf32_Ehdr ehdr;
+	Elf32_Phdr *phdr;
+	size_t last_paddr;
+	size_t loc;
+	int i;
+
+	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, 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++) {
+		size_t size;
+		if (phdr[i].p_type != PT_LOAD) {
+			break;
+		}
+		if (last_paddr != phdr[i].p_paddr) {
+			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;
+		checked_lseek(src_fd, phdr[i].p_offset, SEEK_SET, name);
+		checked_read(src_fd, seg->data + loc, size, name);
+		loc += size;
+	}
+	free(phdr);
+	close(src_fd);
+	return;
+}
+
+struct image_info {
+	size_t entry32;
+	size_t setup_sectors;
+	size_t sys_size;
+	size_t root_dev;
+	struct boot_params *param;
+};
+
+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;
+	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->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;
+} __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 = SEHDR +1; i < SEGS; 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 */
+
+	/* 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;
+}
 
-	return 0;					    /* Everything is OK */
+static void usage(void)
+{
+	die("Usage: build [-e] [-b] vmlinux realmode compressed/vmlinux image");
+}
+
+int main(int argc, char **argv)
+{
+	int is_big_kernel, is_elf;
+	char *kernel;
+	char *realmode;
+	char *zkernel;
+	char *image;
+	int image_fd;
+	size_t major_root, minor_root;
+	struct image_info info;
+	struct file_seg kernel_sz;
+	struct file_seg seg[SEGS];
+	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--;
+		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);
+
+	/* Read in the file information */
+	get_elf_sizes(kernel, 0x100000, &kernel_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_addr = HIGH_BASE;
+		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_addr = LOW_BASE;
+		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;
+
+	/* 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;
+	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].mem_addr + info.param->entry32_off;
+	printf("Setup is %d bytes\n", seg[SREAL].data_size);
+
+	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 ((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", (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);
+	}
+
+	/* Write destination file */
+	image_fd = checked_open(image, O_RDWR | O_CREAT | O_TRUNC, 0666);
+	for(i = 0; i < SEGS; i++) {
+		checked_lseek(image_fd, seg[i].file_offset, SEEK_SET, image);
+		checked_write(image_fd, seg[i].data, seg[i].data_size, image);
+	}
+	close(image_fd);
+	return 0;
 }
diff -uNr linux-2.5.7/arch/i386/boot/video.S linux-2.5.7.boot3.elf/arch/i386/boot/video.S
--- linux-2.5.7/arch/i386/boot/video.S	Thu Jul  5 12:28:16 2001
+++ linux-2.5.7.boot3.elf/arch/i386/boot/video.S	Tue Apr  2 11:52:04 2002
@@ -117,6 +117,12 @@
 	xorw	%ax, %ax
 	movw	%ax, %gs	# GS is zero
 	cld
+
+	# Setup the heap
+	movl	real_filesz - start, %eax
+	subl	$(DELTA_INITSEG << 4), %eax
+	movw	%ax, heap_start - start
+	
 	call	basic_detect	# Basic adapter type testing (EGA/VGA/MDA/CGA)
 #ifdef CONFIG_VIDEO_SELECT
 	movw	%fs:(0x01fa), %ax		# User selected video mode
@@ -126,7 +132,7 @@
 	call	mode_set			# Set the mode
 	jc	vid1
 
-	leaw	badmdt, %si			# Invalid mode ID
+	leaw	badmdt - start, %si			# Invalid mode ID
 	call	prtstr
 vid2:	call	mode_menu
 vid1:
@@ -148,14 +154,14 @@
 	cmpb	$0x10, %bl			# No, it's a CGA/MDA/HGA card.
 	je	basret
 
-	incb	adapter
+	incb	adapter - start
 	movw	$0x1a00, %ax			# Check EGA or VGA?
 	int	$0x10
 	cmpb	$0x1a, %al			# 1a means VGA...
 	jne	basret				# anything else is EGA.
 	
 	incb	%fs:(PARAM_HAVE_VGA)		# We've detected a VGA
-	incb	adapter
+	incb	adapter - start
 basret:	ret
 
 # Store the video mode parameters for later usage by the kernel.
@@ -164,7 +170,7 @@
 # because some very obscure BIOSes supply insane values.
 mode_params:
 #ifdef CONFIG_VIDEO_SELECT
-	cmpb	$0, graphic_mode
+	cmpb	$0, graphic_mode - start
 	jnz	mopar_gr
 #endif
 	movb	$0x03, %ah			# Read cursor position
@@ -178,10 +184,10 @@
 	cmpb	$0x7, %al			# MDA/HGA => segment differs
 	jnz	mopar0
 
-	movw	$0xb000, video_segment
+	movw	$0xb000, video_segment - start
 mopar0: movw	%gs:(0x485), %ax		# Font size
 	movw	%ax, %fs:(PARAM_FONT_POINTS)	# (valid only on EGA/VGA)
-	movw	force_size, %ax			# Forced size?
+	movw	force_size - start, %ax		# Forced size?
 	orw	%ax, %ax
 	jz	mopar1
 
@@ -190,7 +196,7 @@
 	ret
 
 mopar1:	movb	$25, %al
-	cmpb	$0, adapter			# If we are on CGA/MDA/HGA, the
+	cmpb	$0, adapter - start		# If we are on CGA/MDA/HGA, the
 	jz	mopar2				# screen must have 25 lines.
 
 	movb	%gs:(0x484), %al		# On EGA/VGA, use the EGA+ BIOS
@@ -201,7 +207,7 @@
 #ifdef CONFIG_VIDEO_SELECT
 # Fetching of VESA frame buffer parameters
 mopar_gr:
-	leaw	modelist+1024, %di
+	movw	heap_start - start, %di
 	movb	$0x23, %fs:(PARAM_HAVE_VGA)
 	movw	16(%di), %ax
 	movw	%ax, %fs:(PARAM_LFB_LINELENGTH)
@@ -223,7 +229,7 @@
 	movl	%eax, %fs:(PARAM_LFB_COLORS+4)
 
 # get video mem size
-	leaw	modelist+1024, %di
+	movw	heap_start - start, %di
 	movw	$0x4f00, %ax
 	int	$0x10
 	xorl	%eax, %eax
@@ -243,7 +249,7 @@
 
 # The video mode menu
 mode_menu:
-	leaw	keymsg, %si			# "Return/Space/Timeout" message
+	leaw	keymsg - start, %si		# "Return/Space/Timeout" message
 	call	prtstr
 	call	flush
 nokey:	call	getkt
@@ -260,31 +266,31 @@
 defmd1:	ret					# No mode chosen? Default 80x25
 
 listm:	call	mode_table			# List mode table
-listm0:	leaw	name_bann, %si			# Print adapter name
+listm0:	leaw	name_bann - start, %si		# Print adapter name
 	call	prtstr
-	movw	card_name, %si
+	movw	card_name - start, %si
 	orw	%si, %si
 	jnz	an2
 
-	movb	adapter, %al
-	leaw	old_name, %si
+	movb	adapter - start, %al
+	leaw	old_name - start, %si
 	orb	%al, %al
 	jz	an1
 
-	leaw	ega_name, %si
+	leaw	ega_name - start, %si
 	decb	%al
 	jz	an1
 
-	leaw	vga_name, %si
+	leaw	vga_name - start, %si
 	jmp	an1
 
 an2:	call	prtstr
-	leaw	svga_name, %si
+	leaw	svga_name - start, %si
 an1:	call	prtstr
-	leaw	listhdr, %si			# Table header
+	leaw	listhdr - start, %si		# Table header
 	call	prtstr
 	movb	$0x30, %dl			# DL holds mode number
-	leaw	modelist, %si
+	movw	modelist - start, %si
 lm1:	cmpw	$ASK_VGA, (%si)			# End?
 	jz	lm2
 
@@ -311,9 +317,9 @@
 	movb	$0x61, %dl
 	jmp	lm1
 
-lm2:	leaw	prompt, %si			# Mode prompt
+lm2:	leaw	prompt - start, %si		# Mode prompt
 	call	prtstr
-	leaw	edit_buf, %di			# Editor buffer
+	leaw	edit_buf - start, %di		# Editor buffer
 lm3:	call	getkey
 	cmpb	$0x0d, %al			# Enter?
 	jz	lment
@@ -324,14 +330,14 @@
 	cmpb	$0x20, %al			# Printable?
 	jc	lm3
 
-	cmpw	$edit_buf+4, %di		# Enough space?
+	cmpw	$edit_buf + 4 - start, %di	# Enough space?
 	jz	lm3
 
 	stosb
 	call	prtchr
 	jmp	lm3
 
-lmbs:	cmpw	$edit_buf, %di			# Backspace
+lmbs:	cmpw	$edit_buf - start, %di		# Backspace
 	jz	lm3
 
 	decw	%di
@@ -343,9 +349,9 @@
 	jmp	lm3
 	
 lment:	movb	$0, (%di)
-	leaw	crlft, %si
+	leaw	crlft - start, %si
 	call	prtstr
-	leaw	edit_buf, %si
+	leaw	edit_buf - start, %si
 	cmpb	$0, (%si)			# Empty string = default mode
 	jz	lmdef
 
@@ -402,14 +408,14 @@
 lmuse:	call	mode_set
 	jc	lmdef
 
-lmbad:	leaw	unknt, %si
+lmbad:	leaw	unknt - start, %si
 	call	prtstr
 	jmp	lm2
-lmscan:	cmpb	$0, adapter			# Scanning only on EGA/VGA
+lmscan:	cmpb	$0, adapter - start		# Scanning only on EGA/VGA
 	jz	lmbad
 
-	movw	$0, mt_end			# Scanning of modes is
-	movb	$1, scanning			# done as new autodetection.
+	movw	$0, mt_end - start		# Scanning of modes is
+	movb	$1, scanning - start		# done as new autodetection.
 	call	mode_table
 	jmp	listm0
 lmdef:	ret
@@ -464,7 +470,7 @@
 	jz	setbios
 
 setbad:	clc
-	movb	$0, do_restore			# The screen needn't be restored
+	movb	$0, do_restore - start		# The screen needn't be restored
 	ret
 
 setvesa:
@@ -496,7 +502,7 @@
 	jnc	setbad
 	
 	addw	%bx, %bx
-	jmp	*spec_inits(%bx)
+	jmp	*spec_inits - start(%bx)
 
 setmenu:
 	orb	%al, %al			# 80x25 is an exception
@@ -529,7 +535,7 @@
 	jmp	_m_s
 
 check_vesa:
-	leaw	modelist+1024, %di
+	movw	heap_start - start, %di
 	subb	$VIDEO_FIRST_VESA>>8, %bh
 	movw	%bx, %cx			# Get mode information structure
 	movw	$0x4f01, %ax
@@ -555,8 +561,8 @@
 	cmpw	$0x004f, %ax			# AL=4f if implemented
 	jnz	_setbad				# AH=0 if OK
 
-	movb	$1, graphic_mode		# flag graphic mode
-	movb	$0, do_restore			# no screen restore
+	movb	$1, graphic_mode - start	# flag graphic mode
+	movb	$0, do_restore - start		# no screen restore
 	stc
 	ret
 
@@ -597,19 +603,19 @@
 
 # Table of routines for setting of the special modes.
 spec_inits:
-	.word	set_80x25
-	.word	set_8pixel
-	.word	set_80x43
-	.word	set_80x28
-	.word	set_current
-	.word	set_80x30
-	.word	set_80x34
-	.word	set_80x60
-	.word	set_gfx
+	.word	set_80x25 - start
+	.word	set_8pixel - start
+	.word	set_80x43 - start
+	.word	set_80x28 - start
+	.word	set_current - start
+	.word	set_80x30 - start
+	.word	set_80x34 - start
+	.word	set_80x60 - start
+	.word	set_gfx - start
 
 # Set the 80x25 mode. If already set, do nothing.
 set_80x25:
-	movw	$0x5019, force_size		# Override possibly broken BIOS
+	movw	$0x5019, force_size - start	# Override possibly broken BIOS
 use_80x25:
 #ifdef CONFIG_VIDEO_400_HACK
 	movw	$0x1202, %ax			# Force 400 scan lines
@@ -624,7 +630,7 @@
 	cmpw	$0x5003, %ax	# Unknown mode, force 80x25 color
 	jnz	force3
 
-st80:	cmpb	$0, adapter	# CGA/MDA/HGA => mode 3/7 is always 80x25
+st80:	cmpb	$0, adapter - start	# CGA/MDA/HGA => mode 3/7 is always 80x25
 	jz	set80
 
 	movb	%gs:(0x0484), %al	# This is EGA+ -- beware of 80x50 etc.
@@ -719,7 +725,7 @@
  	orb	$0xe2, %al			# Set correct sync polarity
  	outb	%al, %dx
 	popw	%dx
-	movw	$0x501e, force_size
+	movw	$0x501e, force_size - start
 	stc					# That's all.
 	ret
 
@@ -728,7 +734,7 @@
 	call	set_80x30			# Set 480 scans
 	call	set14				# And 14-pt font
 	movw	$0xdb12, %ax			# VGA vertical display end
-	movw	$0x5022, force_size
+	movw	$0x5022, force_size - start
 setvde:	call	outidx
 	stc
 	ret
@@ -738,7 +744,7 @@
 	call	set_80x30			# Set 480 scans
 	call	set_8pt				# And 8-pt font
 	movw	$0xdf12, %ax			# VGA vertical display end
-	movw	$0x503c, force_size
+	movw	$0x503c, force_size - start
 	jmp	setvde
 
 # Special hack for ThinkPad graphics
@@ -747,7 +753,7 @@
 	movw	$VIDEO_GFX_BIOS_AX, %ax
 	movw	$VIDEO_GFX_BIOS_BX, %bx
 	int	$0x10
-	movw	$VIDEO_GFX_DUMMY_RESOLUTION, force_size
+	movw	$VIDEO_GFX_DUMMY_RESOLUTION, force_size - start
 	stc
 #endif
 	ret
@@ -756,53 +762,54 @@
 
 # Store screen contents to temporary buffer.
 store_screen:
-	cmpb	$0, do_restore			# Already stored?
+	cmpb	$0, do_restore - start		# Already stored?
 	jnz	stsr
 
-	testb	$CAN_USE_HEAP, loadflags	# Have we space for storing?
+	testb	$CAN_USE_HEAP, loadflags -start	# Have we space for storing?
 	jz	stsr
 	
 	pushw	%ax
 	pushw	%bx
-	pushw	force_size			# Don't force specific size
-	movw	$0, force_size
+	pushw	force_size - start		# Don't force specific size
+	movw	$0, force_size - start
 	call	mode_params			# Obtain params of current mode
-	popw	force_size
+	popw	force_size - start
 	movb	%fs:(PARAM_VIDEO_LINES), %ah
 	movb	%fs:(PARAM_VIDEO_COLS), %al
 	movw	%ax, %bx			# BX=dimensions
 	mulb	%ah
 	movw	%ax, %cx			# CX=number of characters
 	addw	%ax, %ax			# Calculate image size
-	addw	$modelist+1024+4, %ax
-	cmpw	heap_end_ptr, %ax
+	addw	heap_start - start, %ax
+	addw	$4, %ax
+	cmpw	heap_end_ptr - start, %ax
 	jnc	sts1				# Unfortunately, out of memory
 
 	movw	%fs:(PARAM_CURSOR_POS), %ax	# Store mode params
-	leaw	modelist+1024, %di
+	movw	heap_start - start, %di
 	stosw
 	movw	%bx, %ax
 	stosw
 	pushw	%ds				# Store the screen
-	movw	video_segment, %ds
+	movw	video_segment - start, %ds
 	xorw	%si, %si
 	rep
 	movsw
 	popw	%ds
-	incb	do_restore			# Screen will be restored later
+	incb	do_restore - start		# Screen will be restored later
 sts1:	popw	%bx
 	popw	%ax
 stsr:	ret
 
 # Restore screen contents from temporary buffer.
 restore_screen:
-	cmpb	$0, do_restore			# Has the screen been stored?
+	cmpb	$0, do_restore - start		# Has the screen been stored?
 	jz	res1
 
 	call	mode_params			# Get parameters of current mode
 	movb	%fs:(PARAM_VIDEO_LINES), %cl
 	movb	%fs:(PARAM_VIDEO_COLS), %ch
-	leaw	modelist+1024, %si		# Screen buffer
+	movw	heap_start - start, %si	# Screen buffer
 	lodsw					# Set cursor position
 	movw	%ax, %dx
 	cmpb	%cl, %dh
@@ -841,7 +848,7 @@
 	xchgb	%ch, %cl
 	movw	%cx, %bp			# BP=width of dest. line
 	pushw	%es
-	movw	video_segment, %es
+	movw	video_segment - start, %es
 	xorw	%di, %di			# Move the data
 	addw	%bx, %bx			# Convert BX and BP to _bytes_
 	addw	%bp, %bp
@@ -879,14 +886,15 @@
 # Returns address of the end of the table in DI, the end is marked
 # with a ASK_VGA ID.
 mode_table:
-	movw	mt_end, %di			# Already filled?
+	movw	mt_end - start, %di		# Already filled?
 	orw	%di, %di
 	jnz	mtab1x
-	
-	leaw	modelist, %di			# Store standard modes:
+
+	movw	heap_start - start, %di		# Store standard modes:
+	movw	%di, modelist - start
 	movl	$VIDEO_80x25 + 0x50190000, %eax	# The 80x25 mode (ALL)
 	stosl
-	movb	adapter, %al			# CGA/MDA/HGA -- no more modes
+	movb	adapter - start, %al		# CGA/MDA/HGA -- no more modes
 	orb	%al, %al
 	jz	mtabe
 	
@@ -899,12 +907,12 @@
 
 mtab1x:	jmp	mtab1
 
-mtabv:	leaw	vga_modes, %si			# All modes for std VGA
+mtabv:	leaw	vga_modes - start, %si		# All modes for std VGA
 	movw	$vga_modes_end-vga_modes, %cx
 	rep	# I'm unable to use movsw as I don't know how to store a half
 	movsb	# of the expression above to cx without using explicit shr.
 
-	cmpb	$0, scanning			# Mode scan requested?
+	cmpb	$0, scanning - start		# Mode scan requested?
 	jz	mscan1
 	
 	call	mode_scan
@@ -929,13 +937,13 @@
 mtabe:
 
 #ifdef CONFIG_VIDEO_COMPACT
-	leaw	modelist, %si
+	movw	modelist - start, %si
 	movw	%di, %dx
 	movw	%si, %di
 cmt1:	cmpw	%dx, %si			# Scan all modes
 	jz	cmt2
 
-	leaw	modelist, %bx			# Find in previous entries
+	movw	modelist - start, %bx		# Find in previous entries
 	movw	2(%si), %cx
 cmt3:	cmpw	%bx, %si
 	jz	cmt4
@@ -956,8 +964,9 @@
 #endif	/* CONFIG_VIDEO_COMPACT */
 
 	movw	$ASK_VGA, (%di)			# End marker
-	movw	%di, mt_end
-mtab1:	leaw	modelist, %si			# SI=mode list, DI=list end
+	movw	%di, mt_end - start
+	movw	%di, heap_start - start
+mtab1:	movw	modelist - start, %si		# SI=mode list, DI=list end
 ret0:	ret
 
 # Modes usable on all standard VGAs
@@ -984,7 +993,7 @@
 
 #ifdef CONFIG_VIDEO_VESA
 vesa_modes:
-	cmpb	$2, adapter			# VGA only
+	cmpb	$2, adapter - start		# VGA only
 	jnz	ret0
 
 	movw	%di, %bp			# BP=original mode table end
@@ -1001,7 +1010,7 @@
 	cmpw	$0x4153, 0x202(%di)
 	jnz	ret0
 	
-	movw	$vesa_name, card_name		# Set name to "VESA VGA"
+	movw	$vesa_name - start, card_name - start	# Set name to "VESA VGA"
 	pushw	%gs
 	lgsw	0x20e(%di), %si			# GS:SI=mode list
 	movw	$128, %cx			# Iteration limit
@@ -1066,11 +1075,11 @@
 	cmpw	$5, %bx
 	jnc	vesan
 
-	movw	vesa_text_mode_table(%bx), %ax
+	movw	vesa_text_mode_table - start(%bx), %ax
 	movw	%ax, 2(%di)
 vesaok:	addw	$4, %di				# The mode is valid. Store it.
 vesan:	loop	vesa1			# Next mode. Limit exceeded => error
-vesae:	leaw	vesaer, %si
+vesae:	leaw	vesaer - start, %si
 	call	prtstr
 	movw	%bp, %di			# Discard already found modes.
 vesar:	popw	%gs
@@ -1160,7 +1169,7 @@
 	jz	dosvga
 	
 	movw	%bp, %si			# Found, copy the modes
-	movb	svga_prefix, %ah
+	movb	svga_prefix - start, %ah
 cpsvga:	lodsb
 	orb	%al, %al
 	jz	didsv
@@ -1169,7 +1178,7 @@
 	movsw
 	jmp	cpsvga
 
-didsv:	movw	%si, card_name			# Store pointer to card name
+didsv:	movw	%si, card_name - start		# Store pointer to card name
 didsv1:	ret
 
 # Table of all known SVGA cards. For each card, we store a pointer to
@@ -1741,7 +1750,7 @@
 	cmpb	%bh, %al
 	jne	isnot
 	
-	movb	$VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
+	movb	$VIDEO_FIRST_V7>>8, svga_prefix - start	# Use special mode switching
 	ret
 
 video7_md:
@@ -1932,3 +1941,5 @@
 adapter:	.byte	0	# Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
 video_segment:	.word	0xb800	# Video memory segment
 force_size:	.word	0	# Use this size instead of the one in BIOS vars
+modelist:	.word	0	# Start of modelist on the heap
+heap_start:	.word	0	# low heap address
diff -uNr linux-2.5.7/arch/i386/config.in linux-2.5.7.boot3.elf/arch/i386/config.in
--- linux-2.5.7/arch/i386/config.in	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/config.in	Wed Apr  3 02:07:21 2002
@@ -203,6 +203,7 @@
    fi
 fi
 
+bool 'LinuxBIOS support' CONFIG_LINUXBIOS
 endmenu
 
 mainmenu_option next_comment
@@ -279,6 +280,7 @@
    bool '    Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
 fi
 
+string 'Initial kernel command line' CONFIG_CMDLINE ""
 endmenu
 
 source drivers/mtd/Config.in
diff -uNr linux-2.5.7/arch/i386/defconfig linux-2.5.7.boot3.elf/arch/i386/defconfig
--- linux-2.5.7/arch/i386/defconfig	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/defconfig	Wed Apr  3 02:07:21 2002
@@ -119,6 +119,7 @@
 CONFIG_BINFMT_MISC=y
 CONFIG_PM=y
 # CONFIG_APM is not set
+# CONFIG_LINUXBIOS is not set
 
 #
 # Memory Technology Devices (MTD)
diff -uNr linux-2.5.7/arch/i386/kernel/Makefile linux-2.5.7.boot3.elf/arch/i386/kernel/Makefile
--- linux-2.5.7/arch/i386/kernel/Makefile	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/Makefile	Wed Apr  3 02:07:21 2002
@@ -41,6 +41,7 @@
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
+obj-$(CONFIG_LINUXBIOS)		+= linuxbios.o
 ifdef CONFIG_VISWS
 obj-y += setup-visws.o
 obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
diff -uNr linux-2.5.7/arch/i386/kernel/head.S linux-2.5.7.boot3.elf/arch/i386/kernel/head.S
--- linux-2.5.7/arch/i386/kernel/head.S	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/head.S	Tue Apr  2 11:46:18 2002
@@ -16,12 +16,6 @@
 #include <asm/pgtable.h>
 #include <asm/desc.h>
 
-#define OLD_CL_MAGIC_ADDR	0x90020
-#define OLD_CL_MAGIC		0xA33F
-#define OLD_CL_BASE_ADDR	0x90000
-#define OLD_CL_OFFSET		0x90022
-#define NEW_CL_POINTER		0x228	/* Relative to real mode data */
-
 /*
  * References to members of the boot_cpu_data structure.
  */
@@ -39,46 +33,41 @@
 /*
  * swapper_pg_dir is the main page directory, address 0x00101000
  *
- * On entry, %esi points to the real-mode code as a 32-bit pointer.
+ * On entry
+ *   %ds, %es, %ss, %fs, %gs 32bit data segment base=0 mask=0xffffffff
+ *
  */
-startup_32:
+ENTRY(startup_32)
 /*
- * Set segments to known values
+ * Set eflags to a safe state
  */
 	cld
-	movl $(__KERNEL_DS),%eax
+	cli
+/*
+ * Save the initial registers
+ */
+	movl %eax, initial_regs-__PAGE_OFFSET+0
+	movl %ebx, initial_regs-__PAGE_OFFSET+4
+	movl %ecx, initial_regs-__PAGE_OFFSET+8
+	movl %edx, initial_regs-__PAGE_OFFSET+12
+	movl %esi, initial_regs-__PAGE_OFFSET+16
+	movl %edi, initial_regs-__PAGE_OFFSET+20
+	movl %esp, initial_regs-__PAGE_OFFSET+24
+	movl %ebp, initial_regs-__PAGE_OFFSET+28
+
+/*
+ * Set segments to known values
+ */
+	lgdt gdt_48-__PAGE_OFFSET
+	ljmp $__KERNEL_CS,$1f-__PAGE_OFFSET
+1:	movl $__KERNEL_DS,%eax
 	movl %eax,%ds
 	movl %eax,%es
 	movl %eax,%fs
 	movl %eax,%gs
-#ifdef CONFIG_SMP
-	orw %bx,%bx
-	jz 1f
+	movl %eax,%ss
 
 /*
- *	New page tables may be in 4Mbyte page mode and may
- *	be using the global pages. 
- *
- *	NOTE! If we are on a 486 we may have no cr4 at all!
- *	So we do not try to touch it unless we really have
- *	some bits in it to set.  This won't work if the BSP
- *	implements cr4 but this AP does not -- very unlikely
- *	but be warned!  The same applies to the pse feature
- *	if not equally supported. --macro
- *
- *	NOTE! We have to correct for the fact that we're
- *	not yet offset PAGE_OFFSET..
- */
-#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
-	cmpl $0,cr4_bits
-	je 3f
-	movl %cr4,%eax		# Turn on paging options (PSE,PAE,..)
-	orl cr4_bits,%eax
-	movl %eax,%cr4
-	jmp 3f
-1:
-#endif
-/*
  * Initialize page tables
  */
 	movl $pg0-__PAGE_OFFSET,%edi /* initialize page tables */
@@ -106,14 +95,13 @@
 	/* Set up the stack pointer */
 	lss stack_start,%esp
 
-#ifdef CONFIG_SMP
-	orw  %bx,%bx
-	jz  1f				/* Initial CPU cleans BSS */
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
 	pushl $0
 	popfl
-	jmp checkCPUtype
-1:
-#endif CONFIG_SMP
 
 /*
  * Clear BSS first so that there are no surprises...
@@ -131,42 +119,76 @@
  * in 16-bit mode for the "real" operations.
  */
 	call setup_idt
+	
+	call checkCPUtype
+	call SYMBOL_NAME(start_kernel)
+L6:
+	jmp L6			# main should never return here, but
+				# just in case, we know what happens.
+
+
+#ifdef CONFIG_SMP
+ENTRY(secondary_startup_32)
 /*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
+ * Set eflags to a safe state
  */
-	pushl $0
-	popfl
+	cld
+	cli
+
 /*
- * Copy bootup parameters out of the way. First 2kB of
- * _empty_zero_page is for boot parameters, second 2kB
- * is for the command line.
+ * Set segments to known values
+ */
+	movl	$(__KERNEL_DS), %eax
+	movl	%eax,%ds
+	movl	%eax,%es
+	movl	%eax,%fs
+	movl	%eax,%gs
+	movl	%eax,%ss
+
+/*
+ *	New page tables may be in 4Mbyte page mode and may
+ *	be using the global pages. 
+ *
+ *	NOTE! If we are on a 486 we may have no cr4 at all!
+ *	So we do not try to touch it unless we really have
+ *	some bits in it to set.  This won't work if the BSP
+ *	implements cr4 but this AP does not -- very unlikely
+ *	but be warned!  The same applies to the pse feature
+ *	if not equally supported. --macro
  *
- * Note: %esi still has the pointer to the real-mode data.
+ *	NOTE! We have to correct for the fact that we're
+ *	not yet offset PAGE_OFFSET..
  */
-	movl $ SYMBOL_NAME(empty_zero_page),%edi
-	movl $512,%ecx
-	cld
-	rep
-	movsl
-	xorl %eax,%eax
-	movl $512,%ecx
-	rep
-	stosl
-	movl SYMBOL_NAME(empty_zero_page)+NEW_CL_POINTER,%esi
-	andl %esi,%esi
-	jnz 2f			# New command line protocol
-	cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
-	jne 1f
-	movzwl OLD_CL_OFFSET,%esi
-	addl $(OLD_CL_BASE_ADDR),%esi
-2:
-	movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
-	movl $512,%ecx
-	rep
-	movsl
+#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+	cmpl $0,cr4_bits
+	je 3f
+	movl %cr4,%eax		# Turn on paging options (PSE,PAE,..)
+	orl cr4_bits,%eax
+	movl %eax,%cr4
+/*
+ * Enable paging
+ */
+3:
+	movl $swapper_pg_dir-__PAGE_OFFSET,%eax
+	movl %eax,%cr3		/* set the page table pointer.. */
+	movl %cr0,%eax
+	orl $0x80000000,%eax
+	movl %eax,%cr0		/* ..and set paging (PG) bit */
+	jmp 1f			/* flush the prefetch-queue */
 1:
+	movl $1f,%eax
+	jmp *%eax		/* make sure eip is relocated */
+1:
+	/* Set up the stack pointer */
+	lss stack_start,%esp
+	call checkCPUtype
+	call SYMBOL_NAME(initialize_secondary)
+L7:
+	jmp L7			# initialize_secondary should never return here, but
+				# just in case, we know what happens.
+#endif /* CONFIG_SMP */
+
+
 checkCPUtype:
 
 	movl $-1,X86_CPUID		#  -1 for no CPUID initially
@@ -233,47 +255,19 @@
 	orl $0x50022,%eax	# set AM, WP, NE and MP
 	jmp 2f
 
-is386:	pushl %ecx		# restore original EFLAGS
+is386:
+	pushl %ecx		# restore original EFLAGS
 	popfl
 	movl %cr0,%eax		# 386
 	andl $0x80000011,%eax	# Save PG,PE,ET
 	orl $2,%eax		# set MP
 2:	movl %eax,%cr0
 	call check_x87
-	incb ready
-	lgdt gdt_descr
+	/* Now that we know the cpu, setup the idt & ldt */
 	lidt idt_descr
-	ljmp $(__KERNEL_CS),$1f
-1:	movl $(__KERNEL_DS),%eax	# reload all the segment registers
-	movl %eax,%ds		# after changing gdt.
-	movl %eax,%es
-	movl %eax,%fs
-	movl %eax,%gs
-#ifdef CONFIG_SMP
-	movl $(__KERNEL_DS), %eax
-	movl %eax,%ss		# Reload the stack pointer (segment only)
-#else
-	lss stack_start,%esp	# Load processor stack
-#endif
 	xorl %eax,%eax
 	lldt %ax
-	cld			# gcc2 wants the direction flag cleared at all times
-#ifdef CONFIG_SMP
-	movb ready, %cl	
-	cmpb $1,%cl
-	je 1f			# the first CPU calls start_kernel
-				# all other CPUs call initialize_secondary
-	call SYMBOL_NAME(initialize_secondary)
-	jmp L6
-1:
-#endif
-	call SYMBOL_NAME(start_kernel)
-L6:
-	jmp L6			# main should never return here, but
-				# just in case, we know what happens.
-
-ready:	.byte 0
-
+	ret
 /*
  * We depend on ET to be correct. This checks for 287/387.
  */
@@ -372,6 +366,10 @@
 SYMBOL_NAME(gdt):
 	.long SYMBOL_NAME(gdt_table)
 
+	.word 0
+gdt_48:
+	.word GDT_ENTRIES*8-1
+	.long SYMBOL_NAME(gdt_table)-__PAGE_OFFSET
 /*
  * This is initialized to create an identity-mapping at 0-8M (for bootup
  * purposes) and another mapping of the 0-8M area at virtual address
diff -uNr linux-2.5.7/arch/i386/kernel/linuxbios.c linux-2.5.7.boot3.elf/arch/i386/kernel/linuxbios.c
--- linux-2.5.7/arch/i386/kernel/linuxbios.c	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/linuxbios.c	Wed Apr  3 02:07:21 2002
@@ -0,0 +1,103 @@
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <net/checksum.h>
+#include <asm/linuxbios.h>
+#include <asm/e820.h>
+#include "linuxbios_tables.h"
+
+#define for_each_lbrec(head, rec) \
+	for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \
+		(((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes))  && \
+		(rec->size >= 1) && \
+		((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \
+		rec = (struct lb_record *)(((char *)rec) + rec->size)) 
+		
+
+static int __init count_lb_records(struct lb_header *head)
+{
+	struct lb_record *rec;
+	int count;
+	count = 0;
+	for_each_lbrec(head, rec) {
+		count++;
+	}
+	return count;
+}
+
+static struct lb_header * __init __find_lb_table(unsigned long start, unsigned long end)
+{
+	unsigned long addr;
+	/* For now be stupid.... */
+	for(addr = start; addr < end; addr += 16) {
+		struct lb_header *head = phys_to_virt(addr);
+		struct lb_record *recs = phys_to_virt(addr + sizeof(*head));
+		if (memcmp(head->signature, "LBIO", 4) != 0)
+			continue;
+		if (head->header_bytes != sizeof(*head))
+			continue;
+		if (ip_compute_csum((unsigned char *)head, sizeof(*head)) != 0)
+			continue;
+		if (ip_compute_csum((unsigned char *)recs, head->table_bytes) 
+			!= head->table_checksum)
+			continue;
+		if (count_lb_records(head) != head->table_entries)
+			continue;
+		printk(KERN_DEBUG "Found LinuxBIOS table at: %p\n", head);
+		return head;
+	};
+	return 0;
+}
+
+static struct lb_header * __init find_lb_table(void)
+{
+	struct lb_header *head;
+	head = 0;
+	if (!head) {
+		/* First try at address 0 */
+		head = __find_lb_table(0x00000, 0x1000);
+	}
+	if (!head) {
+		/* Then try at address 0xf0000 */
+		head = __find_lb_table(0xf0000, 0x100000);
+	}
+	return head;
+}
+
+void __init read_linuxbios_params(void)
+{
+	struct lb_header *head;
+	struct lb_record *rec;
+	struct lb_memory *mem;
+	int i, entries;
+	head = find_lb_table();
+	if (!head) {
+		return;
+	}
+	mem = 0;
+	for_each_lbrec(head, rec) {
+		if (rec->tag == LB_TAG_MEMORY) {
+			mem = (struct lb_memory *)rec;
+			break;
+		}
+	}
+	if (!mem) {
+		return;
+	}
+	entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+	if (entries == 0)
+		return;
+	e820.nr_map = 0;
+	for(i = 0; i < entries; i++) {
+		unsigned long long start;
+		unsigned long long size;
+		unsigned long type;
+		start = mem->map[i].start;
+		size = mem->map[i].size;
+		type = (mem->map[i].type == LB_MEM_RAM)?E820_RAM: E820_RESERVED;
+		add_memory_region(start, size, type);
+	}
+	print_memory_map("LinuxBIOS");
+	return;
+}
+
diff -uNr linux-2.5.7/arch/i386/kernel/linuxbios_tables.h linux-2.5.7.boot3.elf/arch/i386/kernel/linuxbios_tables.h
--- linux-2.5.7/arch/i386/kernel/linuxbios_tables.h	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/linuxbios_tables.h	Wed Apr  3 02:20:41 2002
@@ -0,0 +1,82 @@
+#ifndef LINUXBIOS_TABLES_H
+#define LINUXBIOS_TABLES_H
+
+#include <linux/types.h>
+
+/* The linuxbios table information is for conveying information
+ * from the firmware to the loaded OS image.  Primarily this
+ * is expected to be information that cannot be discovered by
+ * other means, such as quering the hardware directly.
+ *
+ * All of the information should be Position Independent Data.  
+ * That is it should be safe to relocated any of the information
+ * without it's meaning/correctnes changing.   For table that
+ * can reasonably be used on multiple architectures the data
+ * size should be fixed.  This should ease the transition between
+ * 32 bit and 64 bit architectures etc.
+ *
+ * The completeness test for the information in this table is:
+ * - Can all of the hardware be detected?
+ * - Are the per motherboard constants available?
+ * - Is there enough to allow a kernel to run that was written before
+ *   a particular motherboard is constructed? (Assuming the kernel
+ *   has drivers for all of the hardware but it does not have
+ *   assumptions on how the hardware is connected together).
+ *
+ * With this test it should be straight forward to determine if a
+ * table entry is required or not.  This should remove much of the
+ * long term compatibility burden as table entries which are
+ * irrelevant or have been replaced by better alternatives may be
+ * dropped.  Of course it is polite and expidite to include extra
+ * table entries and be backwards compatible, but it is not required.
+ */
+
+
+struct lb_header
+{
+	uint8_t  signature[4]; /* LBIO */
+	uint32_t header_bytes;
+	uint32_t header_checksum;
+	uint32_t table_bytes;
+	uint32_t table_checksum;
+	uint32_t table_entries;
+};
+
+/* Every entry in the boot enviroment list will correspond to a boot
+ * info record.  Encoding both type and size.  The type is obviously
+ * so you can tell what it is.  The size allows you to skip that
+ * boot enviroment record if you don't know what it easy.  This allows
+ * forward compatibility with records not yet defined.
+ */
+struct lb_record {
+	uint32_t tag;		/* tag ID */
+	uint32_t size;		/* size of record (in bytes) */
+};
+
+#define LB_TAG_UNUSED	0x0000
+
+#define LB_TAG_MEMORY	0x0001
+
+struct lb_memory_range {
+	uint64_t start;
+	uint64_t size;
+	uint32_t type;
+#define LB_MEM_RAM      1
+#define LB_MEM_RESERVED 2
+	
+};
+
+struct lb_memory {
+	uint32_t tag;
+	uint32_t size;
+	struct lb_memory_range map[0];
+};
+
+#define LB_TAG_HWRPB	0x0002
+struct lb_hwrpb {
+	uint32_t tag;
+	uint32_t size;
+	uint64_t hwrpb;
+};
+
+#endif /* LINUXBIOS_TABLES_H */
diff -uNr linux-2.5.7/arch/i386/kernel/setup.c linux-2.5.7.boot3.elf/arch/i386/kernel/setup.c
--- linux-2.5.7/arch/i386/kernel/setup.c	Wed Mar 20 07:18:31 2002
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/setup.c	Wed Apr  3 02:07:21 2002
@@ -101,6 +101,7 @@
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
+#include <linux/smp_lock.h>
 #include <asm/processor.h>
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -114,6 +115,9 @@
 #include <asm/dma.h>
 #include <asm/mpspec.h>
 #include <asm/mmu_context.h>
+#include <asm/boot.h>
+#include <asm/boot_param.h>
+#include <asm/linuxbios.h>
 
 /*
  * Machine setup..
@@ -147,14 +151,9 @@
 /*
  * Setup options
  */
-struct drive_info_struct { char dummy[32]; } drive_info;
+struct drive_info_struct drive_info;
 struct screen_info screen_info;
 struct apm_info apm_info;
-struct sys_desc_table_struct {
-	unsigned short length;
-	unsigned char table[0];
-};
-
 struct e820map e820;
 
 unsigned char aux_device_present;
@@ -169,33 +168,8 @@
 static int disable_x86_serial_nr __initdata = 1;
 static int disable_x86_fxsr __initdata = 0;
 
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM	((unsigned char *)empty_zero_page)
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
-#define E820_MAP_NR (*(char*) (PARAM+E820NR))
-#define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-#define COMMAND_LINE ((char *) (PARAM+2048))
-#define COMMAND_LINE_SIZE 256
-
-#define RAMDISK_IMAGE_START_MASK  	0x07FF
-#define RAMDISK_PROMPT_FLAG		0x8000
-#define RAMDISK_LOAD_FLAG		0x4000	
-
+/* Don't let the initial_regs sit in the BSS */
+struct initial_regs32 initial_regs __initdata = { 0 };
 
 static char command_line[COMMAND_LINE_SIZE];
        char saved_command_line[COMMAND_LINE_SIZE];
@@ -289,7 +263,7 @@
 	}
 }
 
-static void __init add_memory_region(unsigned long long start,
+void __init add_memory_region(unsigned long long start,
                                   unsigned long long size, int type)
 {
 	int x = e820.nr_map;
@@ -307,7 +281,7 @@
 
 #define E820_DEBUG	1
 
-static void __init print_memory_map(char *who)
+void __init print_memory_map(char *who)
 {
 	int i;
 
@@ -554,7 +528,7 @@
  */
 #define LOWMEMSIZE()	(0x9f000)
 
-static void __init setup_memory_region(void)
+static void __init setup_memory_region(struct boot_params *params)
 {
 	char *who = "BIOS-e820";
 
@@ -564,16 +538,16 @@
 	 * Otherwise fake a memory map; one section from 0k->640k,
 	 * the next section from 1mb->appropriate_mem_k
 	 */
-	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+	sanitize_e820_map(params->e820_map, &params->e820_map_nr);
+	if (copy_e820_map(params->e820_map, params->e820_map_nr) < 0) {
 		unsigned long mem_size;
 
 		/* compare results from other methods and take the greater */
-		if (ALT_MEM_K < EXT_MEM_K) {
-			mem_size = EXT_MEM_K;
+		if (params->alt_mem_k < params->screen.overlap.ext_mem_k) {
+			mem_size = params->screen.overlap.ext_mem_k;
 			who = "BIOS-88";
 		} else {
-			mem_size = ALT_MEM_K;
+			mem_size = params->alt_mem_k;
 			who = "BIOS-e801";
 		}
 
@@ -588,13 +562,12 @@
 
 static void __init parse_mem_cmdline (char ** cmdline_p)
 {
-	char c = ' ', *to = command_line, *from = COMMAND_LINE;
+	char c = ' ', *to = command_line, *from = saved_command_line;
 	int len = 0;
 	int usermem = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(saved_command_line, command_line, sizeof(saved_command_line));
 
 	for (;;) {
 		/*
@@ -664,6 +637,145 @@
 	}
 }
 
+static void init_settings(void)
+{
+	ROOT_DEV = to_kdev_t(0x0000);
+	memset(&drive_info, 0, sizeof(drive_info));
+	memset(&screen_info, 0, sizeof(screen_info));
+	memset(&apm_info.bios, 0, sizeof(apm_info.bios));
+	aux_device_present = 0;
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = 0;
+	rd_prompt = 0;
+	rd_doload = 0;
+#endif
+	e820.nr_map = 0;
+	saved_command_line[0] = '\0';
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start = 0;
+	initrd_end = 0;
+#endif
+	/* set default screen information */
+	screen_info.orig_x = 0;
+	screen_info.orig_y = 25;
+	screen_info.orig_video_page = 0;
+	screen_info.orig_video_mode = 0;
+	screen_info.orig_video_cols = 80;
+	screen_info.orig_video_lines = 25;
+	screen_info.orig_video_ega_bx = 0;
+	screen_info.orig_video_isVGA = 1;
+	screen_info.orig_video_points = 16;
+}
+
+static void read_entry32_params(struct boot_params *params)
+{
+	char *cmdline;
+	int cmdline_off;
+	/*
+	 * These values are set a compile time or set by the bootloader
+	 */
+ 	ROOT_DEV = to_kdev_t(params->root_dev);
+
+	if (!params->mount_root_rdonly)
+		root_mountflags &= ~MS_RDONLY;
+
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = params->ramdisk_flags & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((params->ramdisk_flags & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((params->ramdisk_flags & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+	/* The compiled in command line */
+	cmdline = (char *)params;
+	cmdline += params->internal_cmdline_off;
+	strncpy(command_line, cmdline, COMMAND_LINE_SIZE);
+	command_line[COMMAND_LINE_SIZE -1] = '\0';
+
+	/* The bootloader passed command line */
+	cmdline = "";
+	if (params->cmd_line_ptr) {
+		/* New command line protocol */
+		cmdline = (char *)(params->cmd_line_ptr);
+	}
+	else if (*((unsigned short *)OLD_CL_MAGIC_ADDR) == OLD_CL_MAGIC) {
+		cmdline = (char *)OLD_CL_BASE + *((unsigned short *)OLD_CL_OFFSET_ADDR);
+	}
+	cmdline_off = strlen(command_line);
+	memcpy(command_line + cmdline_off, cmdline, COMMAND_LINE_SIZE - cmdline_off);
+	command_line[COMMAND_LINE_SIZE -1] = '\0';
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (params->loader_type && params->initrd_start) {
+		initrd_start = params->initrd_start ?
+			params->initrd_start + PAGE_OFFSET : 0;
+		initrd_end = initrd_start + params->initrd_size;
+	}
+#endif	
+}
+
+static void read_entry16_params(struct boot_params *params)
+{
+	/*
+	 * These values are set up by the setup-routine at boot-time
+	 */
+ 	drive_info = params->drive_info;
+ 	screen_info = params->screen.info;
+	apm_info.bios = params->apm_bios_info;
+	if( params->sys_desc_table.length != 0 ) {
+		MCA_bus = params->sys_desc_table.table[3] &0x2;
+		machine_id = params->sys_desc_table.table[0];
+		machine_submodel_id = params->sys_desc_table.table[1];
+		BIOS_revision = params->sys_desc_table.table[2];
+	}
+	aux_device_present = params->aux_device_info;
+
+	setup_memory_region(params);
+}
+
+static void parse_params(char **cmdline_p)
+{
+	struct boot_params *params;
+	int entry16, entry32;
+	
+	params = (struct boot_params *)initial_regs.esi;
+	entry16 = initial_regs.ebp == ENTRY16;
+	entry32 = (initial_regs.ebp == ENTRY32) && (params->entry32_used);
+
+	init_settings();
+
+	/* Get compiled in and bootloader parameters */
+	if (entry16 || entry32) {
+		read_entry32_params(params);
+	}
+
+	/* Get parameters from the 16bit BIOS */
+	if (entry16) {
+		read_entry16_params(params);
+	}
+
+	/* Attempt to get the LinuxBIOS parameters */
+	read_linuxbios_params();
+
+	/* Read user specified params */
+	parse_mem_cmdline(cmdline_p);
+
+	if ((e820.nr_map == 0) && entry32) {
+		/* If we came in via the 32bit entry point and don't
+		 * have a memory size we need help.
+		 * So go out and come back in the 16bit entry point.
+		 */
+		void (*entry32_16)(void);
+		printk(KERN_INFO "No memory size information so reentering 16bit mode\n");
+		entry32_16 = (void (*)(void))(initial_regs.esi + params->entry32_16_off);
+		unlock_kernel();
+		entry32_16();
+	}
+
+	if (e820.nr_map == 0) {
+		panic("Unknown memory size\n");
+	}
+}
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long bootmap_size, low_mem_size;
@@ -674,27 +786,8 @@
 	visws_get_board_type_and_rev();
 #endif
 
- 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
- 	drive_info = DRIVE_INFO;
- 	screen_info = SCREEN_INFO;
-	apm_info.bios = APM_BIOS_INFO;
-	if( SYS_DESC_TABLE.length != 0 ) {
-		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
-		machine_id = SYS_DESC_TABLE.table[0];
-		machine_submodel_id = SYS_DESC_TABLE.table[1];
-		BIOS_revision = SYS_DESC_TABLE.table[2];
-	}
-	aux_device_present = AUX_DEVICE_INFO;
-
-#ifdef CONFIG_BLK_DEV_RAM
-	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
-	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#endif
-	setup_memory_region();
+	parse_params(cmdline_p);
 
-	if (!MOUNT_ROOT_RDONLY)
-		root_mountflags &= ~MS_RDONLY;
 	init_mm.start_code = (unsigned long) &_text;
 	init_mm.end_code = (unsigned long) &_etext;
 	init_mm.end_data = (unsigned long) &_edata;
@@ -705,8 +798,6 @@
 	data_resource.start = virt_to_phys(&_etext);
 	data_resource.end = virt_to_phys(&_edata)-1;
 
-	parse_mem_cmdline(cmdline_p);
-
 #define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
 #define PFN_PHYS(x)	((x) << PAGE_SHIFT)
@@ -878,18 +969,16 @@
 	find_smp_config();
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (LOADER_TYPE && INITRD_START) {
-		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-			reserve_bootmem(INITRD_START, INITRD_SIZE);
-			initrd_start =
-				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
-			initrd_end = initrd_start+INITRD_SIZE;
+	if (initrd_start) {
+		if ((initrd_end - PAGE_OFFSET) <= (max_low_pfn << PAGE_SHIFT)) {
+			reserve_bootmem(initrd_start - PAGE_OFFSET,
+				initrd_end - initrd_start);
 		}
 		else {
 			printk(KERN_ERR "initrd extends beyond end of memory "
-			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			    INITRD_START + INITRD_SIZE,
-			    max_low_pfn << PAGE_SHIFT);
+				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+				initrd_end - PAGE_OFFSET, 
+				max_low_pfn << PAGE_SHIFT);
 			initrd_start = 0;
 		}
 	}
diff -uNr linux-2.5.7/arch/i386/kernel/trampoline.S linux-2.5.7.boot3.elf/arch/i386/kernel/trampoline.S
--- linux-2.5.7/arch/i386/kernel/trampoline.S	Thu Oct  4 19:42:54 2001
+++ linux-2.5.7.boot3.elf/arch/i386/kernel/trampoline.S	Tue Apr  2 11:46:18 2002
@@ -12,10 +12,6 @@
  *	In fact we don't actually need a stack so we don't
  *	set one up.
  *
- *	We jump into the boot/compressed/head.S code. So you'd
- *	better be running a compressed kernel image or you
- *	won't get very far.
- *
  *	On entry to trampoline_data, the processor is in real mode
  *	with 16-bit addressing and 16-bit data.  CS has some value
  *	and IP is zero.  Thus, data addresses need to be absolute
@@ -23,12 +19,16 @@
  *
  *	If you work on this file, check the object module with objdump
  *	--full-contents --reloc to make sure there are no relocation
- *	entries except for the gdt one..
+ *	entries except for gdt & secondary_startup_32..
  */
 
 #include <linux/linkage.h>
+#include <linux/threads.h>
 #include <asm/segment.h>
 #include <asm/page.h>
+#include <asm/desc.h>
+
+#define GDT_ENTRIES	(__TSS(NR_CPUS))
 
 .data
 
@@ -42,7 +42,6 @@
 	mov	%cs, %ax	# Code and data in the same place
 	mov	%ax, %ds
 
-	mov	$1, %bx		# Flag an SMP trampoline
 	cli			# We should be safe anyway
 
 	movl	$0xA5A5A5A5, trampoline_data - r_base
@@ -56,16 +55,17 @@
 	lmsw	%ax		# into protected mode
 	jmp	flush_instr
 flush_instr:
-	ljmpl	$__KERNEL_CS, $0x00100000
-			# jump to startup_32 in arch/i386/kernel/head.S
+		# jump to secondary_startup_32 in arch/i386/kernel/head.S
+	ljmpl	$__KERNEL_CS, $(SYMBOL_NAME(secondary_startup_32) - __PAGE_OFFSET)
+	
 
 idt_48:
 	.word	0			# idt limit = 0
 	.word	0, 0			# idt base = 0L
 
 gdt_48:
-	.word	0x0800			# gdt limit = 2048, 256 GDT entries
-	.long	gdt_table-__PAGE_OFFSET	# gdt base = gdt (first SMP CPU)
+	.word	GDT_ENTRIES*8-1		# gdt limit
+	.long	SYMBOL_NAME(gdt_table)-__PAGE_OFFSET	# gdt base = gdt (first SMP CPU)
 
 .globl SYMBOL_NAME(trampoline_end)
 SYMBOL_NAME_LABEL(trampoline_end)
diff -uNr linux-2.5.7/arch/i386/vmlinux.lds linux-2.5.7.boot3.elf/arch/i386/vmlinux.lds
--- linux-2.5.7/arch/i386/vmlinux.lds	Sun Mar 10 20:09:08 2002
+++ linux-2.5.7.boot3.elf/arch/i386/vmlinux.lds	Tue Apr  2 11:44:16 2002
@@ -3,7 +3,13 @@
  */
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
-ENTRY(_start)
+physical_startup_32 = startup_32 - 0xC0000000;
+ENTRY(physical_startup_32)
+PHDRS
+{
+	text PT_LOAD AT(0x100000);
+
+}
 SECTIONS
 {
   . = 0xC0000000 + 0x100000;
@@ -12,7 +18,7 @@
 	*(.text)
 	*(.fixup)
 	*(.gnu.warning)
-	} = 0x9090
+	} :text = 0x9090
 
   _etext = .;			/* End of text section */
 
diff -uNr linux-2.5.7/arch/x86_64/boot/Makefile linux-2.5.7.boot3.elf/arch/x86_64/boot/Makefile
--- linux-2.5.7/arch/x86_64/boot/Makefile	Sun Mar 10 20:08:39 2002
+++ linux-2.5.7.boot3.elf/arch/x86_64/boot/Makefile	Tue Apr  2 22:26: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
diff -uNr linux-2.5.7/include/asm-i386/boot.h linux-2.5.7.boot3.elf/include/asm-i386/boot.h
--- linux-2.5.7/include/asm-i386/boot.h	Wed Apr 16 15:15:00 1997
+++ linux-2.5.7.boot3.elf/include/asm-i386/boot.h	Tue Apr  2 11:46:18 2002
@@ -1,10 +1,18 @@
 #ifndef _LINUX_BOOT_H
 #define _LINUX_BOOT_H
 
+/* Address space division during load */
+#define LOW_BASE   0x001000
+#define REAL_BASE  0x090000
+#define HIGH_BASE  0x100000
+#define LOW_MAX    REAL_BASE
+#define REAL_MAX   0x0A0000
+#define HIGH_MAX   __MAXMEM
+
 /* Don't touch these, unless you really know what you're doing. */
-#define DEF_INITSEG	0x9000
+#define DEF_INITSEG	(REAL_BASE >> 4)
+#define DEF_SETUPSEG	((REAL_BASE + 512) >> 4)
 #define DEF_SYSSEG	0x1000
-#define DEF_SETUPSEG	0x9020
 #define DEF_SYSSIZE	0x7F00
 
 /* Internal svga startup constants */
@@ -12,4 +20,27 @@
 #define EXTENDED_VGA	0xfffe		/* 80x50 mode */
 #define ASK_VGA		0xfffd		/* ask for it at bootup */
 
-#endif
+/* Entry point ID constants */
+#define ENTRY16		0x73726468 /* 'hdrs' */
+#define ENTRY32		0x53524448 /* 'HDRS' */
+
+/* Decompressor constants */
+#define MOVE_ROUTINE_BASE LOW_BASE
+#define MOVE_ROUTINE_SIZE 0x001000
+#define LOW_BUFFER_START  (MOVE_ROUTINE_BASE + MOVE_ROUTINE_SIZE)
+#define LOW_BUFFER_MAX    LOW_MAX
+#define HEAP_SIZE         0x003000
+
+/* Maximum command line size */
+#define COMMAND_LINE_SIZE 256
+
+/* Initial page table size 8MB */
+#define INITIAL_PAGE_TABLE_SIZE 0x800000
+
+/* Old command line protocol */
+#define OLD_CL_MAGIC_ADDR  0x90020
+#define OLD_CL_OFFSET_ADDR 0x90022
+#define OLD_CL_BASE 0x90000
+#define OLD_CL_MAGIC 0xA33F
+
+#endif /* _LINUX_BOOT_H */
diff -uNr linux-2.5.7/include/asm-i386/boot_param.h linux-2.5.7.boot3.elf/include/asm-i386/boot_param.h
--- linux-2.5.7/include/asm-i386/boot_param.h	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot3.elf/include/asm-i386/boot_param.h	Wed Apr  3 02:06:43 2002
@@ -0,0 +1,99 @@
+#ifndef __I386_BOOT_PARAM_H
+#define __I386_BOOT_PARAM_H
+
+struct initial_regs32 {
+	const __u32 eax;
+	const __u32 ebx;
+	const __u32 ecx;
+	const __u32 edx;
+	const __u32 esi;
+	const __u32 edi;
+	const __u32 esp;
+	const __u32 ebp;
+}; 
+struct drive_info_struct { __u8 dummy[32]; };
+struct sys_desc_table {
+	__u16 length;
+	__u8 table[318];
+};
+struct screen_info_overlap {
+	__u8  reserved1[2];		/* 0x00 */
+	__u16 ext_mem_k;		/* 0x02 */
+	__u8  reserved2[0x20 - 0x04];	/* 0x04 */
+	__u16 cl_magic;			/* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+	__u16 cl_offset;		/* 0x22 */
+	__u8  reserved3[0x40 - 0x24];	/* 0x24 */
+};
+
+struct boot_params {
+	union {					/* 0x00 */
+		struct screen_info info;
+		struct screen_info_overlap overlap;
+	} screen;
+
+	struct apm_bios_info apm_bios_info;	/* 0x40 */
+	__u8 reserved4[0x80 - 0x54];		/* 0x54 */
+	struct drive_info_struct drive_info;	/* 0x80 */
+	struct sys_desc_table sys_desc_table;	/* 0xa0 */
+	__u32 alt_mem_k;			/* 0x1e0 */
+	__u8  reserved5[4];			/* 0x1e4 */
+	__u8  e820_map_nr;			/* 0x1e8 */
+	__u8  reserved6[8];			/* 0x1e9 */
+	__u8  setup_sects;			/* 0x1f1 */
+	__u16 mount_root_rdonly;		/* 0x1f2 */
+	__u16 syssize;				/* 0x1f4 */
+	__u16 swapdev;				/* 0x1f6 */
+	__u16 ramdisk_flags;			/* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000	
+	__u16 vid_mode;				/* 0x1fa */
+	__u16 root_dev;				/* 0x1fc */
+	__u8  reserved9[1];			/* 0x1fe */
+	__u8  aux_device_info;			/* 0x1ff */
+	/* 2.00+ */
+	__u8  reserved10[2];			/* 0x200 */
+	__u8  header_magic[4];			/* 0x202 */
+	__u16 protocol_version;			/* 0x206 */
+	__u8  reserved11[8];			/* 0x208 */
+	__u8  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
+	__u8  loader_flags;			/* 0x211 */
+	__u8  reserved12[2];			/* 0x212 */
+	__u32 code32_start;			/* 0x214 */
+	__u32 initrd_start;			/* 0x218 */
+	__u32 initrd_size;			/* 0x21c */
+	__u8  reserved13[4];			/* 0x220 */
+	/* 2.01+ */
+	__u16 heap_end_ptr;			/* 0x224 */
+	__u8  reserved14[2];			/* 0x226 */
+	/* 2.02+ */
+	__u32 cmd_line_ptr;			/* 0x228 */
+	/* 2.03+ */
+	__u32 ramdisk_max;			/* 0x22c */
+	/* 2.04+ */
+	__u16 entry32_off;			/* 0x230 */
+	__u16 internal_cmdline_off;		/* 0x232 */
+	__u32 low_base;				/* 0x234 */
+	__u32 low_memsz;			/* 0x238 */
+	__u32 low_filesz;			/* 0x23c */
+	__u32 real_base;			/* 0x240 */
+	__u32 real_memsz;			/* 0x244 */
+	__u32 real_filesz;			/* 0x248 */
+	__u32 high_base;			/* 0x24C */
+	__u32 high_memsz;			/* 0x250 */
+	__u32 high_filesz;			/* 0x254 */
+	/* entry32 values (for internal kernel use only) */
+	__u32 entry32_used;			/* 0x258 */
+	__u32 entry32_16_off;			/* 0x25c */
+	struct initial_regs32 regs;		/* 0x260 */
+	__u8  reserved15[0x2d0 - 0x280];	/* 0x280 */
+	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
+						/* 0x550 */
+} __attribute__((packed));
+#endif /* __I386_BOOT_PARAM_H */
diff -uNr linux-2.5.7/include/asm-i386/e820.h linux-2.5.7.boot3.elf/include/asm-i386/e820.h
--- linux-2.5.7/include/asm-i386/e820.h	Fri Aug 18 10:30:51 2000
+++ linux-2.5.7.boot3.elf/include/asm-i386/e820.h	Wed Apr  3 02:07:21 2002
@@ -15,6 +15,7 @@
 #define E820MAP	0x2d0		/* our map */
 #define E820MAX	32		/* number of entries in E820MAP */
 #define E820NR	0x1e8		/* # entries in E820MAP */
+#define E820ENTRY_SIZE 20	/* size of an E820MAP entry */
 
 #define E820_RAM	1
 #define E820_RESERVED	2
@@ -35,6 +36,9 @@
 };
 
 extern struct e820map e820;
+extern void  add_memory_region(unsigned long long start,
+	unsigned long long size, int type);
+extern void print_memory_map(char *who);
 #endif/*!__ASSEMBLY__*/
 
 #endif/*__E820_HEADER*/
diff -uNr linux-2.5.7/include/asm-i386/linuxbios.h linux-2.5.7.boot3.elf/include/asm-i386/linuxbios.h
--- linux-2.5.7/include/asm-i386/linuxbios.h	Wed Dec 31 17:00:00 1969
+++ linux-2.5.7.boot3.elf/include/asm-i386/linuxbios.h	Wed Apr  3 02:20:20 2002
@@ -0,0 +1,10 @@
+#ifndef __ASMi386_LINUXBIOS_H
+#define __ASMi386_LINUXBIOS_H
+
+#ifdef CONFIG_LINUXBIOS
+void read_linuxbios_params(void);
+#else
+#define read_linuxbios_params()
+#endif /* CONFIG_LINUXBIOS */
+
+#endif
