Date: Thu, 12 Jun 1997 09:35:32 +0200 (MET DST)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Linux/m68k <linux-m68k@phil.uni-sb.de>
Subject: L68K: Bootstrap problem (2.0.x, compressed ramdisks)
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: linux-m68k@phil.uni-sb.de


There's a problem with booting unpadded compressed ramdisks and 2.0.x.

According to bootinfo interface version 1.0 ramdisk sizes must be a multiple of
1024 bytes, so compressed ramdisks had to be padded. This limitation was
removed with the introduction of bootinfo interface version 2.0 (for 2.1.x).

The problem is that the ramdisk image is copied to the end of memory by the
bootstrap. Define the following variables

  - mem_end: end of first memory block
  - rd_size: size of ramdisk in bytes
  - rd_blocks: size of ramdisk in 1K blocks (rounded up)

Then the ramdisk will be copied to mem_end-rd_size. However, the kernel will
think the end of the ramdisk is at mem_end-rd_size+rd_blocks*1024, which is
beyond the end of fysical memory if rd_size != rd_blocks*1024, causing a crash.

So I changed Amiboot to copy the kernel to (mem_end-rd_size)&0xfffffc00 in case
of bootinfo interface version 1.0. Ataboot needs a similar patch.
The other patches are fixes to compile Amiboot and Amiga-Lilo under 2.1.42.

Experimental binaries for Amiboot and Amiga-Lilo are available from

    http://www.cs.kuleuven.ac.be/~geert/bin/amiboot-5.6-exp.gz
    http://www.cs.kuleuven.ac.be/~geert/bin/amiga-lilo-exp.tar.gz

Please test this! Using the programs, I could boot 2.0.28 and 2.1.42 using an
uncompressed ramdisk, a compressed ramdisk and a compressed ramdisk padded to
a multiple of 1K (filesys-ELF-2.0.x-1400K-2).


********************************************************************************

64000 dollar question:

    What if the size of a gzipped ramdisk image is a multiple of 1024 bytes?
    Will gunzip() read beyond the final byte (which always seems to be zero)
    and cause a crash?

********************************************************************************


--- linux-2.1.42/arch/m68k/boot/amiga/linuxboot.h.orig	Sun May 18 23:08:56 1997
+++ linux-2.1.42/arch/m68k/boot/amiga/linuxboot.h	Tue Jun 10 22:26:07 1997
@@ -31,7 +31,7 @@
      *  Amiboot Version
      */
 
-#define AMIBOOT_VERSION		"5.5"
+#define AMIBOOT_VERSION		"5.6"
 
 
     /*
--- linux-2.1.42/arch/m68k/boot/amiga/linuxboot.c.orig	Sun May 18 23:08:56 1997
+++ linux-2.1.42/arch/m68k/boot/amiga/linuxboot.c	Wed Jun 11 23:45:58 1997
@@ -22,9 +22,11 @@
  *  for more details.
  *
  *  History:
+ *	11 Jun 1997 Fix for unpadded gzipped ramdisks with bootinfo interface
+ *		    version 1.0
  *	27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
  *		    interface version 1.0 (Geert)
- *	03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
+ *	 3 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
  *		    code for ataboot)
  *	30 Dec 1996 Reverted the CPU detection to the old scheme
  *		    New boot parameter override scheme (Geert)
@@ -55,7 +57,6 @@
 #include <stddef.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
 
 #include <linux/a.out.h>
 #include <linux/elf.h>
@@ -70,6 +71,10 @@
 #undef custom
 #define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
 
+/* a.out linkage conventions */
+#undef SYMBOL_NAME_STR
+#define SYMBOL_NAME_STR(X) "_"#X
+
 /* temporary stack size */
 #define TEMP_STACKSIZE	(256)
 
@@ -130,10 +135,9 @@
 static int add_bi_string(u_short tag, const u_char *s);
 static int check_bootinfo_version(const char *memptr);
 static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
-			 u_long start_mem, u_long mem_size, u_long rd_size,
-			 u_long kernel_size) __attribute__ ((noreturn));
+			 u_long start_mem, u_long kernel_size, u_long rd_dest,
+			 u_long rd_size) __attribute__ ((noreturn));
 asmlinkage u_long maprommed(void);
-asmlinkage u_long check346(void);
 #ifdef ZKERNEL
 static int load_zkernel(int fd);
 static int KRead(int fd, void *buf, int cnt);
@@ -682,7 +686,7 @@
     if (debugflag) {
 	if (bi.ramdisk.size)
 	    Printf("RAM disk at 0x%08lx, size is %ldK\n",
-		   (u_long)memptr+kernel_size, bi.ramdisk.size>>10);
+		   (u_long)memptr+kernel_size+bi_size, bi.ramdisk.size>>10);
 
 	if (elf_kernel) {
 	    PutChar('\n');
@@ -703,11 +707,11 @@
 	Printf("\nKernel entry is 0x%08lx\n", elf_kernel ? kexec_elf.e_entry :
 							   kexec.a_entry);
 
-	Printf("ramdisk dest top is 0x%08lx\n", start_mem+mem_size);
+	Printf("ramdisk dest is 0x%08lx\n", bi.ramdisk.addr);
 	Printf("ramdisk lower limit is 0x%08lx\n",
-	       (u_long)(memptr+kernel_size));
+	       (u_long)memptr+kernel_size+bi_size);
 	Printf("ramdisk src top is 0x%08lx\n",
-	       (u_long)(memptr+kernel_size)+rd_size);
+	       (u_long)memptr+kernel_size+bi_size+rd_size);
 
 	Puts("\nType a key to continue the Linux/m68k boot...");
 	GetChar();
@@ -743,7 +747,7 @@
 
     /* execute the copy-and-go code (from CHIP RAM) */
     start_kernel(startfunc, (char *)stack+TEMP_STACKSIZE, memptr, start_mem,
-		 mem_size, rd_size, kernel_size);
+		 kernel_size, bi.ramdisk.addr, rd_size);
 
     /* Clean up and exit in case of a failure */
 Fail:
@@ -1065,6 +1069,7 @@
 	compat_bootinfo.memory[i].size = bi.memory[i].size;
     }
     if (bi.ramdisk.size) {
+	bi.ramdisk.addr &= 0xfffffc00;
 	compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
 	compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
     } else {
@@ -1151,14 +1156,14 @@
      */
 
 static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
-			 u_long start_mem, u_long mem_size, u_long rd_size,
-			 u_long kernel_size)
+			 u_long start_mem, u_long kernel_size, u_long rd_dest,
+			 u_long rd_size)
 {
     register void (*a0)() __asm("a0") = startfunc;
     register char *a2 __asm("a2") = stackp;
     register char *a3 __asm("a3") = memptr;
     register u_long a4 __asm("a4") = start_mem;
-    register u_long d0 __asm("d0") = mem_size;
+    register u_long d0 __asm("d0") = rd_dest;
     register u_long d1 __asm("d1") = rd_size;
     register u_long d2 __asm("d2") = kernel_size;
     register u_long d3 __asm("d3") = bi_size;
@@ -1182,7 +1187,7 @@
      *
      *	    a3 = memptr
      *	    a4 = start_mem
-     *	    d0 = mem_size
+     *	    d0 = rd_dest
      *	    d1 = rd_size
      *	    d2 = kernel_size
      *	    d3 = bi_size
@@ -1210,18 +1215,16 @@
 	dbra	d7,1b		|     *dest++ = *src++
 
 				| /* copy the ramdisk to the top of memory */
-				| /* (from back to front) */
-	movel	a4,a1		| dest = (u_long *)(start_mem+mem_size);
-	addl	d0,a1
-	movel	a3,a2		| limit = (u_long *)(memptr+kernel_size +
-	addl	d2,a2		|		     bi_size);
-	addl	d3,a2
-	movel	a2,a0		| src = (u_long *)((u_long)limit+rd_size);
-	addl	d1,a0
+	movel	a3,a0		| src = (u_long *)(memptr+kernel_size+bi_size);
+	addl	d2,a0
+	addl	d3,a0
+	movel	d0,a1		| dest = (u_long *)rd_dest;
+	movel	a0,a2		| limit = (u_long *)(memptr+kernel_size+
+	addl	d1,a2		|		     bi_size+rd_size);
 1:	cmpl	a0,a2
-	beqs	2f		| while (src > limit)
-	moveb	a0@-,a1@-	|     *--dest = *--src;
-	bras	1b
+	jeq	2f		| while (src > limit)
+	moveb	a0@+,a1@+	|     *dest++ = *src++;
+	jra	1b
 2:
 				| /* jump to start of kernel */
 	movel	a4,a0		| jump_to (start_mem);
--- linux-2.1.42/arch/m68k/boot/amiga/bootstrap.c.orig	Sun May 18 23:05:10 1997
+++ linux-2.1.42/arch/m68k/boot/amiga/bootstrap.c	Wed Jun 11 22:37:37 1997
@@ -36,10 +36,12 @@
 #include <stdarg.h>
 #include <string.h>
 #include <sys/file.h>
-#include <sys/types.h>
 #include <unistd.h>
 
 /* required Linux/m68k include files */
+#define __KERNEL_STRICT_NAMES		/* This is ugly, I know */
+#define _LINUX_POSIX_TYPES_H
+#include <asm/posix_types.h>
 #include <linux/a.out.h>
 #include <linux/elf.h>
 #include <asm/amigahw.h>

--- amiga-lilo-2.2/loader.a.c.orig	Thu Jan  2 15:59:31 1997
+++ amiga-lilo-2.2/loader.a.c	Wed Jun 11 23:31:04 1997
@@ -26,6 +26,11 @@
 #include "loader_proto.h"
 
 
+/* a.out linkage conventions */
+#undef SYMBOL_NAME_STR
+#define SYMBOL_NAME_STR(X) "_"#X
+
+
     /*
      *  Program Entry
      *

Greetings,

						Geert

--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/m68k on Amiga          http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

