From lsorense@csclub.uwaterloo.ca Wed May 20 21:24:29 2009
Received: (at 512429) by bugs.debian.org; 20 May 2009 21:24:29 +0000
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
	(2007-08-08) on rietz.debian.org
X-Spam-Level: 
X-Spam-Bayes: score:0.0000 Tokens: new, 540; hammy, 140; neutral, 343; spammy,
	11. spammytokens:1.000-1--HUGE, 0.999-1--583, 0.999-1--addi, 0.999-1--584,
	0.998-1--3613 hammytokens:0.000-+--struct, 0.000-+--initrd,
	0.000-+--overwrite, 0.000-+--cflags, 0.000-+--filesystems
X-Spam-Status: No, score=-3.8 required=4.0 tests=AWL,BAYES_00,FOURLA,
	IMPRONONCABLE_1,IMPRONONCABLE_2,MURPHY_DRUGS_REL8,MURPHY_WRONG_WORD2,
	RCVD_IN_DNSWL_MED autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Return-path: <lsorense@csclub.uwaterloo.ca>
Received: from caffeine.csclub.uwaterloo.ca ([129.97.134.17])
	by rietz.debian.org with esmtp (Exim 4.63)
	(envelope-from <lsorense@csclub.uwaterloo.ca>)
	id 1M6tH3-0004ue-8U
	for 512429@bugs.debian.org; Wed, 20 May 2009 21:24:29 +0000
Received: from caffeine.csclub.uwaterloo.ca (localhost [127.0.0.1])
	by caffeine.csclub.uwaterloo.ca (Postfix) with ESMTP id B410273CC4
	for <512429@bugs.debian.org>; Wed, 20 May 2009 17:24:27 -0400 (EDT)
Received: by caffeine.csclub.uwaterloo.ca (Postfix, from userid 20367)
	id 9635573CDD; Wed, 20 May 2009 17:24:27 -0400 (EDT)
Date: Wed, 20 May 2009 17:24:27 -0400
To: 512429@bugs.debian.org
Subject: Finally a patch to fix this.
Message-ID: <20090520212427.GW21463@csclub.uwaterloo.ca>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.5.18 (2008-05-17)
From: lsorense@csclub.uwaterloo.ca (Lennart Sorensen)
X-Virus-Scanned: ClamAV using ClamSMTP

I finally had time to finish this up along with some cleanup.  I failed
to fix openbios (I can't make sense of it), so I instead did some ugly
hack to work around the bad implementation in openbios by keeping the
struct address the same, and wrapping the code and data of first.b around
that struct, rather than being all before the struct.  It works
wonderfully with qemu 0.10.4 from sid.

So what has been changed:

Build warnings and errors.

Makefile dependancies have been cleaned up so make works without
unnecesary runs of make clean.

Support for initrd+vmlinux bigger than 11MB except on powerpc 601 where
only 16MB is mapped.  64MB is now mapped on 604 and higher.  No idea
how the mapping works on a 601 so I don't know how to fix it.

Support for a larger second.b file.  256KB is currently supported up
from 64KB.  Since e2fslibs has gotten larger, second.b is currently 85KB,
which caused problems building a working quik before.  This is done
through the use of a second.map file.  first.b now only stores the
location of second.map, loads that and then uses the 1024 bytes in that
as the table of blocks for second.b

Switching to a newer e2fslibs means symlinks are now fully supported.
Using ext3 might work, but some unclean shutdowns might make for
an unreadable filesystem and cause boot failures.  I would recommend
sticking with ext2 for /boot.

Version number changed to 3.0 since I think this is a HUGE change in
functionality and behaviour.  You can decide if you like that change
or not.

So here is the patch:

diff -ruN quik-2.1/first/first.S quik-2.1.fixed/first/first.S
--- quik-2.1/first/first.S	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/first/first.S	2009-05-20 15:55:18.000000000 -0400
@@ -38,6 +38,26 @@
 .LC7:	.string	"exit"
 .LC8:	.string	"enter"
 
+/* We need 64bytes for our FIRST_INFO struct reserved so we make some */
+/* data and tell the linker where we want it.                         */
+	.section	".filler"
+.FILL0:	.long	0xdeadbeef
+.FILL1:	.long	0xdeadbeef
+.FILL2:	.long	0xdeadbeef
+.FILL3:	.long	0xdeadbeef
+.FILL4:	.long	0xdeadbeef
+.FILL5:	.long	0xdeadbeef
+.FILL6:	.long	0xdeadbeef
+.FILL7:	.long	0xdeadbeef
+.FILL8:	.long	0xdeadbeef
+.FILL9:	.long	0xdeadbeef
+.FILLA:	.long	0xdeadbeef
+.FILLB:	.long	0xdeadbeef
+.FILLC:	.long	0xdeadbeef
+.FILLD:	.long	0xdeadbeef
+.FILLE:	.long	0xdeadbeef
+.FILLF:	.long	0xdeadbeef
+
 	.section	".text"
 	.align	2
 	.globl	main
@@ -56,7 +76,8 @@
 	sync
 	isync
 
-/* Use the BAT2 & 3 registers to map the 1st 16MB of RAM to 0. */
+/* Use the BAT2 & 3 registers to map the 1st 16MB of RAM to 0 on 601. */
+/* Use the BAT3 register to map the 1st 64MB of RAM to 0 on 604 and later. */
 	mfpvr	9
 	rlwinm	9,9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
 					/* the 604 case now works on G3, and should */
@@ -66,7 +87,7 @@
 	li	7,4			/* set up BAT registers for 601 */
 	li	8,0x7f
 	b	5f
-4:	li	7,0x1ff			/* set up BAT registers for 604 et al */
+4:	li	7,0x7ff			/* set up BAT registers for 604 et al */
 	li	8,2
 	mtdbatl	3,8
 	mtdbatu	3,7
@@ -134,11 +155,33 @@
 	cmplwi	0,0,1
 	ble	out		/*	goto out; */
 
+/* Load second.map.x */
 	addi	26,14,FIRST_INFO@l	/* fp = FIRST_INFO; */
+	li	29,SECOND_MAP_SIZE@l	/* map size should fit in one block */
+	addi	20,26,0x3C-4	/* bp = &fp->blknos[-1]; */
+	lwz	28,20(26)	/* addr = fp->second_map_base; */
+	addi	3,14,.LC5@l	/*	call_prom("seek", 3, bdev, */
+	li	4,3		/*		  0, *++bp * 512); */
+	mr	5,27
+	lwzu	31,4(20)
+	srwi	6,31,23
+	slwi	7,31,9
+	bl	call_prom
+	mr	16,3
+	addi	3,14,.LC6@l	/*	if (call_prom("read", 3, bdev, */
+	li	4,3		/*		      addr, bs) != bs) */
+	mr	5,27
+	mr	6,28
+	mr	7,29
+	bl	call_prom
+	mr	30,3
+	cmpw	0,3,29		/*		goto out; */
+	bne	out
+
+/* Load second.b */
+	addi	20,28,-4	/* bp = &fp->mapbase[-1]; */
 	lwz	28,16(26)	/* addr = fp->second_base; */
 	mr	25,28		/* start = (void *) addr; */
-	lwz	29,12(26)	/* bs = fp->blocksize; */
-	addi	20,26,0x38-4	/* bp = &fp->blknos[-1]; */
 	lwz	21,8(26)	/* i = fp->nblocks; do { */
 3:	addi	3,14,.LC5@l	/*	call_prom("seek", 3, bdev, */
 	li	4,3		/*		  0, *++bp * 512); */
@@ -229,4 +272,18 @@
 .Lfe2:
 	.size	 call_prom,.Lfe2-call_prom
 
-
+	/* This is filler to ensure that the code ends at 0x2c8 where */
+	/* FIRST_INFO starts to line up with the filler data above    */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
diff -ruN quik-2.1/first/ld.script quik-2.1.fixed/first/ld.script
--- quik-2.1/first/ld.script	2000-03-10 15:59:28.000000000 -0500
+++ quik-2.1.fixed/first/ld.script	2009-05-20 15:48:14.000000000 -0400
@@ -31,6 +31,7 @@
   .text      :
   {
     *(.text)
+    *(.filler)
     *(.rodata)
     *(.rodata1)
     *(.got1)
diff -ruN quik-2.1/include/layout.h quik-2.1.fixed/include/layout.h
--- quik-2.1/include/layout.h	2009-05-20 15:13:20.000000000 -0400
+++ quik-2.1.fixed/include/layout.h	2009-05-20 15:21:33.000000000 -0400
@@ -10,20 +10,25 @@
  * (at your option) any later version.
  */
 
-#define VERSION		"2.1"
+#define VERSION		"3.0"
 
 #define FIRST_BASE	0x3f4000 /* dec: 4145152 */
 #define FIRST_SIZE	0x400 /* dec: 1024 */
 
-#define SECOND_BASE	0x3e0000 /* dec: 4063232 */
-#define SECOND_SIZE	0x10000 /* dec: 65536 */
+#define SECOND_BASE	0x3b0000 /* dec: 3866624 */
+#define SECOND_SIZE	0x40000 /* dec: 262144 max size of second.b */
+
+#define SECOND_MAP_BASE 0x3efc00 /* Last 1K of SECOND's memory range,
+					which we can overwrite on last
+					transfer if needed */
+#define SECOND_MAP_SIZE	0x400 /* dec: 1024 */
 
 #define STACK_TOP	0x400000 /* dec: 4194304 */
 
 /* 0x400000 - 0x500000 is one of OF's favourite places to be. */
 
 /* We malloc in low memory now and load kernel at 0x500000 instead, we
- * also map 16Mb with BATs. This is all done to help loading larger
+ * also map 64MB with BATs. This is all done to help loading larger
  * kernels. --BenH.
  */
 #define MALLOC_BASE	0x300000 /* dec: 3145728 */
@@ -31,12 +36,13 @@
 #ifndef __ASSEMBLY__
 struct first_info {
     char	quik_vers[8];
-    int		nblocks;
+    int		nblocks; /* blocks in second.b */
     int		blocksize;
     unsigned	second_base;
+    unsigned	second_map_base; /* load address of second.map */
     int		conf_part;
     char	conf_file[32];
-    unsigned	blknos[64];
+    unsigned	blknos[1]; /* block used for second.map */
 };
 #endif	/* __ASSEMBLY__ */
 
@@ -44,5 +50,10 @@
  * If you change FIRST_SIZE or sizeof(struct first_info),
  * be sure to change the definition of FIRST_INFO_OFF.
  */
-#define FIRST_INFO_OFF	0x2c8	/* == FIRST_SIZE - sizeof(struct first_info) */
+#define FIRST_INFO_OFF	0x2c8	/* was FIRST_SIZE - sizeof(struct first_info) */
+                                /* now it is stuck because openbios           */
+                                /* for qemu hardcoded it rather than just     */
+                                /* booting the bootable partition and I       */
+                                /* don't know how the openbios forth code     */
+                                /* works well enough to fix it.               */
 #define FIRST_INFO	(FIRST_BASE + FIRST_INFO_OFF)
diff -ruN quik-2.1/include/quik_md.h quik-2.1.fixed/include/quik_md.h
--- quik-2.1/include/quik_md.h	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/include/quik_md.h	2009-01-21 17:06:51.000000000 -0500
@@ -93,7 +93,7 @@
   int rlevel;
 } mdev_info_t;
 
-#define BOOTDEV(dev,i) (((dev)->devs[(i)]) ? (dev)->devs[(i)]->bootdev : NULL)
+#define BOOTDEV(dev,i) (((dev)->devs[(i)]) ? (dev)->devs[(i)]->bootdev : "")
 #define SPART(dev,i) (((dev)->devs[(i)]) ? (dev)->devs[(i)]->spart : NULL)
 
 dev_info_t * new_dev_info (void);
@@ -101,6 +101,7 @@
 int md_get_version (int);
 mdev_info_t * md_get_info (const char *);
 mdev_info_t * new_mdev_info (unsigned char);
+void free_mdev_info(mdev_info_t *);
 
 
 #endif
diff -ruN quik-2.1/quik/Makefile quik-2.1.fixed/quik/Makefile
--- quik-2.1/quik/Makefile	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/quik/Makefile	2009-01-21 17:08:00.000000000 -0500
@@ -5,6 +5,9 @@
 
 all: quik
 
+quik.o: quik.c ../include/layout.h ../include/quik_md.h
+quik_md.o: quik.c ../include/layout.h ../include/quik_md.h
+
 quik: $(objects)
 	$(CC) $(CFLAGS) -o quik $(objects)
 
diff -ruN quik-2.1/quik/quik.c quik-2.1.fixed/quik/quik.c
--- quik-2.1/quik/quik.c	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/quik/quik.c	2009-02-09 10:59:27.000000000 -0500
@@ -227,11 +227,13 @@
   }
 }
 
-int get_partition_blocks(char *filename, mdev_info_t * devs)
+int get_partition_blocks(char *filename, mdev_info_t * devs, char *mapfilenamebase)
 {
     int fd;
+    int mapfd;
     int block, i, j;
     struct stat st;
+    char mapfilename[64];
 
     if ((fd = open(filename, O_RDONLY)) == -1)
 	fatal("Cannot find %s", filename);
@@ -240,18 +242,31 @@
     devs->nsect = devs->bs >> 9;
     for (j=0; j<devs->ndevs; j++) {
       if (SPART(devs,j)) {
+        snprintf(mapfilename,64,"%s.%d",mapfilenamebase,j);
+        if ((mapfd = open(mapfilename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
+          fatal("Cannot open %s for write", mapfilename);
 	devs->devs[j]->finfo.blocksize = devs->bs;
 	
 	for (i = 0;; i++) {
 	  block = i;
 	  if (i * devs->bs >= st.st_size || ioctl(fd, FIBMAP, &block) < 0 || !block)
 	    break;
-	  devs->devs[j]->finfo.blknos[i] = block * devs->nsect + devs->devs[j]->doff;
+	  devs->devs[j]->finfo.blknos[0] = block * devs->nsect + devs->devs[j]->doff;
+          write(mapfd,&(devs->devs[j]->finfo.blknos[0]),4);
 	}
 	devs->devs[j]->finfo.nblocks = i;
+        close(mapfd);
+        if ((mapfd = open(mapfilename, O_RDONLY)) == -1)
+          fatal("Cannot find %s", mapfilename);
+        block = 0;
+        if (ioctl(mapfd, FIBMAP, &block) < 0 || !block)
+          fatal("Failed to map block of %s",mapfilename);
+        devs->devs[j]->finfo.blknos[0] = block * devs->nsect + devs->devs[j]->doff;
+        close(mapfd);
       }
     }
     close(fd);
+
     return 0;
 }
 
@@ -284,6 +299,7 @@
 		"QUIK" VERSION, 
 		sizeof(devs->devs[i]->finfo.quik_vers));
 	devs->devs[i]->finfo.second_base = SECOND_BASE;
+	devs->devs[i]->finfo.second_map_base = SECOND_MAP_BASE;
 	devs->devs[i]->finfo.conf_part = devs->devs[i]->cpart;
 	strncpy(devs->devs[i]->finfo.conf_file, 
 		config_file, 
@@ -737,7 +753,7 @@
       install_first_stage(devs->fs_dev, install);
       make_bootable(devs);
     }
-    get_partition_blocks(secondary, devs);
+    get_partition_blocks(secondary, devs, "/boot/second.map");
     write_block_table(devs, config_file);
     
     free_mdev_info(devs);
diff -ruN quik-2.1/README.big.second quik-2.1.fixed/README.big.second
--- quik-2.1/README.big.second	1969-12-31 19:00:00.000000000 -0500
+++ quik-2.1.fixed/README.big.second	2009-05-20 16:47:10.000000000 -0400
@@ -0,0 +1,37 @@
+This version of QUIK has been enhanced to support a map file for loading
+second.b since e2fslibs has gotten to big to fit in the 64KB QUIK was
+originally written for.  This is similar to how lilo has done things
+pretty much forever since lilo only had 480 or so bytes to work in,
+while QUIK has 1024.  Eventually 1024 bytes isn't enough for the block
+map either though.
+
+Adding this support increased the size of first.S's assembly code, which
+causes the location of FIRST_INFO struct to move, although removing the
+second.b block map from the struct reduces the struct size a lot.
+
+Unfortunately, openbios for ppc qemu has hardcoded the location of the
+struct used by QUIK 2.1, rather than implementing generic loading of
+whatever partition is flagged as bootable.  I wish I knew how to fix
+that but I can't understand the forth code they use at all, and have no
+idea how to fix it.  So to stay compatible with openbios's current design,
+I have kept the struct location fixed at 0x2c8 from the start of the
+code and filled it with filler data (currently 64bytes of 0xdeadbeef).
+The code is padded with nop to 0x2c8 and the linker script places the
+filler section right after the code.  This leaves space between the code
+and rodata for the 64byte scruct and leaves the address of the struct
+fixed so that openbios can still find it.  It's ugly, but it works.
+
+The maximum size of second.b is now 256KB rather than 64KB, and could
+be made larger without much effort.  Current size is 85KB.
+
+Moving to a new e2fslibs has made symlinks work, so that's a bonus.
+It may even work with ext3 filesystems, although if you have an unclean
+shutdown, the journal needing a replay could prevent you from booting,
+which is similar to issues grub can have with ext3 filesystems and
+unclean shutdowns.  Maybe it works, maybe it doesn't.  ext2 for /boot
+is still recommended.  Certainly you must have quik load from a filesystem
+where the block numbers fit in 32bit (so no more than 2TB including any
+offsets from the start of the disk).  Probably not an issue for anyone.
+
+-- 
+Len Sorensen
diff -ruN quik-2.1/second/Makefile quik-2.1.fixed/second/Makefile
--- quik-2.1/second/Makefile	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/second/Makefile	2009-02-09 10:58:53.000000000 -0500
@@ -4,7 +4,7 @@
 
 CFLAGS = -I../include -O2 -D__NO_STRING_INLINES -Wall -ffreestanding
 
-LDFLAGS=-N -Ttext 0x3e0000
+LDFLAGS=-N -Ttext 0x3b0000
 
 OBJS =	crt0.o printf.o malloc.o main.o cmdline.o disk.o file.o \
 	cfg.o strtol.o prom.o cache.o string.o setjmp.o ctype.o \
@@ -16,8 +16,8 @@
 	$(LD) $(LDFLAGS) -Bstatic -o second $(OBJS) -lext2fs
 
 crt0.o:        crt0.S
-main.o:        main.c quik.h
-malloc.o:      malloc.c quik.h
+main.o:        main.c quik.h ../include/layout.h
+malloc.o:      malloc.c quik.h ../include/layout.h
 printf.o:      printf.c quik.h
 cmdline.o:     cmdline.c quik.h
 disk.o:	       disk.c quik.h
diff -ruN quik-2.1/second/misc.c quik-2.1.fixed/second/misc.c
--- quik-2.1/second/misc.c	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/second/misc.c	2009-05-20 16:08:24.000000000 -0400
@@ -11,8 +11,6 @@
  */
 #include <linux/kernel.h>
 
-#include <asm/page.h>
-
 #include <sys/types.h>
 #include "setjmp.h"
 #include "gzip.h"
diff -ruN quik-2.1/second/prom.c quik-2.1.fixed/second/prom.c
--- quik-2.1/second/prom.c	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/second/prom.c	2009-02-05 16:31:25.000000000 -0500
@@ -145,29 +145,32 @@
 prom_init(void (*pp)(void *))
 {
     prom_entry = pp;
+    int tmp;
     /* First get a handle for the stdout device */
     prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
     if (prom_chosen == (void *)-1)
 	prom_exit();
-    getpromprop(prom_chosen, "stdout", &prom_stdout, sizeof(prom_stdout));
-    getpromprop(prom_chosen, "stdin", &prom_stdin, sizeof(prom_stdin));
-    getpromprop(prom_chosen, "mmu", &prom_mmu, sizeof(prom_mmu));
+    tmp = getpromprop(prom_chosen, "stdout", &prom_stdout, sizeof(prom_stdout));
+    tmp = getpromprop(prom_chosen, "stdin", &prom_stdin, sizeof(prom_stdin));
+    tmp = getpromprop(prom_chosen, "mmu", &prom_mmu, sizeof(prom_mmu));
     prom_options = call_prom("finddevice", 1, 1, "/options");
 }
 
 void
 prom_get_chosen(char *name, char *buf, int buflen)
 {
+    int tmp;
     buf[0] = 0;
-    getpromprop(prom_chosen, name, buf, buflen);
+    tmp = getpromprop(prom_chosen, name, buf, buflen);
 }
 
 void
 prom_get_options(char *name, char *buf, int buflen)
 {
+    int tmp;
     buf[0] = 0;
     if (prom_options != (void *) -1)
-	getpromprop(prom_options, name, buf, buflen);
+	tmp = getpromprop(prom_options, name, buf, buflen);
 }
 
 int
diff -ruN quik-2.1/second/quik.h quik-2.1.fixed/second/quik.h
--- quik-2.1/second/quik.h	2009-05-20 14:46:01.000000000 -0400
+++ quik-2.1.fixed/second/quik.h	2009-02-05 16:22:29.000000000 -0500
@@ -6,7 +6,7 @@
 #include <stddef.h>
 
 #define IMAGE_BUF       ((unsigned char *) 0x500000)
-#define IMAGE_END       ((unsigned char *) 0x1000000)
+#define IMAGE_END       ((unsigned char *) 0x4000000)
 
 extern char cbuff[];
 extern char bootdevice[];
@@ -58,3 +58,4 @@
 void cmdinit();
 void cmdedit(void (*tabfunc)(void), int c);
 
+int uncompress_kernel(int);




