mtd/docboot README, 1.3, 1.4 doc_bootstub.S, 1.4, 1.5 doc_bootstub.h, 1.3, 1.4 makespl.c, 1.3, 1.4

dbrown at infradead.org dbrown at infradead.org
Tue Mar 29 16:01:57 EST 2005


Update of /home/cvs/mtd/docboot
In directory phoenix.infradead.org:/tmp/cvs-serv25106

Modified Files:
	README doc_bootstub.S doc_bootstub.h makespl.c 
Log Message:
Add support for NFTL-based DOC2000.


Index: README
===================================================================
RCS file: /home/cvs/mtd/docboot/README,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- README	3 Jan 2005 18:31:10 -0000	1.3
+++ README	29 Mar 2005 21:01:54 -0000	1.4
@@ -18,21 +18,25 @@
 
 Like LILO and Grub, DOCBoot is a Linux bootloader.  It dispenses with many of
 the amenities provided by other bootloaders, however.  Command line editing,
-multiple image support, serial port support, fancy prompts and menus, timeouts,
-and all kinds of error checking are not present.  Unlike Grub, DOCBoot does not
-understand filesystems, nor can it load a kernel scattered throughout the
-blocks of a filesystem like LILO.  Instead, DOCBoot reads your kernel directly
-from a contiguous section of the DiskOnChip.
+multiple image support, serial port boot interaction, fancy prompts and menus,
+timeouts, and all kinds of error checking are not present.  Unlike Grub,
+DOCBoot does not understand filesystems, nor can it load a kernel scattered
+throughout the blocks of a filesystem like LILO.  Instead, DOCBoot reads your
+kernel directly from a contiguous section of the DiskOnChip.
 
 DOCBoot supports kernel versions 2.4.0-test3-pre3 or later.  Bad things may
 happen if you try it with an earlier version.
 
-At the moment, DOCBoot supports only the new INFTL-based DiskOnChip 2000 parts,
-sometimes known as Alon or 2000TSOP, and DOC Millennium Plus 16 MB devices.
-It might work on DOC Millenium, but I haven't tested this.
+DOCBoot supports the new INFTL-based DiskOnChip 2000 parts by default.  These
+are sometimes also known as DOC Alon or DOC 2000 TSOP.  Support has also been
+added for DOC Millennium Plus 16 MB devices and for some older (NFTL) DOC 2000
+devices (you'll have to edit a file to build DOCBoot for these other devices).
 
-Support for the older (NFTL) DiskOnChip 2000 parts and DOC Millennium Plus 32 MB
-is planned.
+It might work on DOC Millenium (which behaves similarly to the DOC 2000 TSOP),
+but I haven't tested this.
+
+It does not (at this time) support DOC Millennium Plus 32 MB, or very old DOC
+2000 devices with 256-byte pages.
 
 DOCBoot now supports INITRD image loading.
 
@@ -158,7 +162,13 @@
 
 #define BIOS_EXTENSION: Uncomment this to make a standard PC BIOS extension
                         instead of the SPL image.  This is explained in more
-                        detail below.
+                        detail in the "Bios Extension Support" section below.
+
+#define OLD_DOC2K:	Uncomment this to compile DOCBoot for older (NFTL)
+			DOC 2000 devices.  It doesn't make sense to use this
+			and MILPLUS at the same time; DOCBoot supports only
+			one type of device at a time.  See the "Older (NFTL)
+			DOC 2000 Devices" section for detailed usage info.
 
 
 Keyboard Abort
@@ -211,3 +221,101 @@
 'bios_ext' is a 1024-byte file containing DOCBoot and your commandline info,
 formatted as a standard PC BIOS extension.  Merging this into your BIOS is up
 to you.
+
+
+Older (NFTL) DOC 2000 Devices
+-----------------------------
+
+NFTL-based DOC2000 parts are a bit trickier to use with DOCBoot.  The biggest
+issue is that the NFTL format does not really support partitions, at least not
+in the flexible way used by INFTL.  An INFTL device is organized as follows:
+
+  IPL
+  Media Header
+  Partition 0 (BDK or BDTL)
+  (optional) Partition 1 (BDK or BDTL)
+  . . . up to at most Partition 3
+
+Under Linux, MTD partitions (subdevices) are created for each partition listed
+in the INFTL partition table.  Thus up to five MTD devices will be created:
+
+  /dev/mtd0 is the entire device
+  /dev/mtd1 is Partition 0
+  . . . /dev/mtd4 is Partition 3
+
+No partitions are created for the IPL or Media Header (they are accessible
+through the "whole device" entry, /dev/mtd0).
+
+When using DOCBoot with an INFTL device, we generally write the DOCBoot image to
+partition 0 and create a filesystem such as jffs2 on paritition 1.  This is
+similar to what the M-Systems firmware does: the firware (BDK) goes in
+partition 0, and the INFTL filesystem (BDTL) goes in partition 1.  So far, so
+good.
+
+By contrast, an NFTL device is organized as follows:
+
+  Firmware
+  Media Header
+  BDTL Data
+
+Under Linux, normally two MTD devices will be created:
+
+  /dev/mtd0 is the entire device
+  /dev/mtd1 is the BDTL filesystem
+
+Recall steps 2 and 5 from the "Quick Start" section of this document:
+
+ 2. Ensure that your first BDK partition is large enough to hold your bzImage
+    plus 1k.
+
+ 5. Assuming your first BDK partition is /dev/mtd1:
+      flash_eraseall /dev/mtd1
+      nandwrite -o /dev/mtd1 doc_spl
+
+How do we accomplish these tasks when NFTL doesn't have partitions?
+
+It turns out the M-Systems DOS utility DFORMAT is willing to pretend that the
+Firmware section of the device is a BDK partition.  So the command referred to
+in the Quick Start:
+
+    dformat /win:xxxx /bdkl0:x
+
+Will work for NFTL devices.  Properly used, this will resize the Firmware
+section to be large enough for your DOCBoot image.
+
+However, early versions of the Linux diskonchip driver (prior to April 2005)
+didn't scan the entire device when looking for the Media Header section.  They
+only scanned the first 128K or so.  Thus, older version of the diskonchip
+driver will refuse to work with NFTL devices if the Firmware has been resized
+enough for DOCBoot.  An up-to-date version of the driver will fix this problem.
+
+The other problem is the flash_eraseall command in step 5 of the Quick Start. We
+want to erase just the Firmware section, but our only choices are /dev/mtd0
+(the entire device), or /dev/mtd1 (our filesystem).  To solve this, recent
+versions of the diskonchip driver add a new module parameter, used as follows:
+
+  modprobe diskonchip show_firmware_partition=1
+
+Linux will now create three MTD devices instead of two:
+
+  /dev/mtd0 is the entire device
+  /dev/mtd1 is the Firmware and Media Header sections
+  /dev/mtd2 is the BDTL filesystem
+
+(With INFTL devices, this option will create a new partition for the IPL +
+Media Header section).  This option is safe to use all the time; it is not the
+default because it would unexpectedly break device naming for existing users.
+We can now use:
+
+  flash_eraseall /dev/mtd1
+
+To erase the firmware.  Although the Media Header is part of this device, it is
+write-protected in Linux and will not be destroyed.  When it tries to erase the
+Media Header, flash_eraseall will produce error messages about failure to erase
+"bad blocks", these should be ignored.
+
+One final note: show_firmware_partition=1 is only needed when you want to
+(re)write your DOCBoot image.  It is not needed for DOCBoot to work, nor for
+normal filesystem operations under Linux.  You might choose to leave the
+Firmware section hidden most of the time and only create a partition for it when
+you need to update it.

Index: doc_bootstub.S
===================================================================
RCS file: /home/cvs/mtd/docboot/doc_bootstub.S,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- doc_bootstub.S	3 Jan 2005 18:31:10 -0000	1.4
+++ doc_bootstub.S	29 Mar 2005 21:01:54 -0000	1.5
@@ -117,7 +117,7 @@
 #endif
 
 	xorw	%di, %di
-	movw	$0x20, %dx	/* scan from second eraseblock */
+	xorw	%dx, %dx
 read_setup_sects:
 	call	doc_readpage
 	decw	%cs:low_sects
@@ -268,10 +268,15 @@
 	testb	$0, BX_Mplus_ReadPipeInit
 	testb	$0, BX_Mplus_ReadPipeInit
 #else
-	movb	$CDSN_CTRL_WP + CDSN_CTRL_ALE + CDSN_CTRL_CE, BX_CDSNControl
+	movb	$CDSN_CTRL_BASE + CDSN_CTRL_ALE, BX_CDSNControl
+	DOC_DELAY4
+	SLOWIO_WRITE($0)
 	movb	$0, SI_CDSN_IO
+	SLOWIO_WRITE(%dl)
 	movb	%dl, SI_CDSN_IO
+	SLOWIO_WRITE(%dh)
 	movb	%dh, SI_CDSN_IO
+  #ifndef OLD_DOC2K
 		/* This test is used in the MSYS IPL.  It appears to check
 		   an undocumented bit in the ConfigurationInput register,
 		   presumably to determine if the NAND chip is large enough to
@@ -281,13 +286,16 @@
 	movb	$0, SI_CDSN_IO
 notbigchip:
 	call	doc_wait
-	testb	$0, BX_ReadPipeInit
+	testb	BX_ReadPipeInit, %al
+  #else
+	call	doc_wait
+  #endif
 #endif
 	movw	$0x208, %cx	/* Read page + 8 bytes OOB */
 	pushw	%di
 rploop:
-	lodsb
-	stosb
+	SLOWIO_READ
+	movsb
 	decw	%si
 	loop	rploop
 	incw	%dx
@@ -322,25 +330,25 @@
 	ret
 #else
                 /* Enable CLE line to flash */
-        movb    $CDSN_CTRL_WP + CDSN_CTRL_CLE + CDSN_CTRL_CE, BX_CDSNControl
+	movb	$CDSN_CTRL_BASE + CDSN_CTRL_CLE, BX_CDSNControl
+	DOC_DELAY4
                 /* Write the actual command */
-        movb	%al, SI_CDSN_IO
+	SLOWIO_WRITE(%al)
+  	movb	%al, SI_CDSN_IO
 	/* fall through... */
 
                 /* doc_wait:     Wait for the DiskOnChip to be ready */
 doc_wait:
+  #ifndef OLD_DOC2K
         movb	$0, BX_WritePipeTerm
-	movb	$CDSN_CTRL_WP + CDSN_CTRL_CE, BX_CDSNControl
-	testb	$0x80, BX_NOP
-	testb	$0x80, BX_NOP
-	testb	$0x80, BX_NOP
-	testb	$0x80, BX_NOP
-doc_waitloop:    
+  #endif
+	movb	$CDSN_CTRL_BASE, BX_CDSNControl
+	DOC_DELAY4
+doc_waitloop:
 	testb	$0x80, BX_CDSNControl
-        jz      doc_waitloop
-	testb	$0x80, BX_NOP
-	testb	$0x80, BX_NOP
-        ret
+	jz	doc_waitloop
+	DOC_DELAY2
+	ret
 #endif
                 
 

Index: doc_bootstub.h
===================================================================
RCS file: /home/cvs/mtd/docboot/doc_bootstub.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- doc_bootstub.h	3 Jan 2005 18:31:10 -0000	1.3
+++ doc_bootstub.h	29 Mar 2005 21:01:54 -0000	1.4
@@ -111,15 +111,23 @@
 
 	/* Some macros to make it obvious what we're accessing */
 #define BXREG	DoC_ChipID
+//#define BXREG	DoC_CDSNControl
 
-#define BX_ChipID		(%bx)
-#define BX_DOCControl		2(%bx)
-#define BX_CDSNControl		4(%bx)
-#define BX_ConfigurationInput	28(%bx)
-#define BX_ReadPipeInit		29(%bx)
-#define BX_WritePipeTerm	30(%bx)
-#define BX_LastDataRead		31(%bx)
-#define BX_NOP			32(%bx)
+#define BX_ChipID		(DoC_ChipID-BXREG)(%bx)
+#define BX_DOCControl		(DoC_DOCControl-BXREG)(%bx)
+#define BX_CDSNControl		(DoC_CDSNControl-BXREG)(%bx)
+//#define BX_CDSNControl		(%bx)
+#define BX_SlowIO		(DoC_CDSNSlowIO-BXREG)(%bx)
+#define BX_ConfigurationInput	(DoC_ConfigInput-BXREG)(%bx)
+#define BX_ReadPipeInit		(DoC_ReadPipeInit-BXREG)(%bx)
+#define BX_WritePipeTerm	(DoC_WritePipeTerm-BXREG)(%bx)
+#define BX_LastDataRead		(DoC_LastDataRead-BXREG)(%bx)
+#define BX_NOP			(DoC_NOP-BXREG)(%bx)
+#define BX_DELAY		(%bx)
+//#define BX_DELAY		BX_ChipID
+
+#define DOC_DELAY2 testw BX_DELAY, %ax
+#define DOC_DELAY4 incw BX_DELAY
 
 #define BX_Mplus_NOP		2(%bx)
 #define BX_Mplus_DOCControl	6(%bx)
@@ -131,7 +139,6 @@
 #define BX_Mplus_WritePipeTerm	46(%bx)
 #define BX_Mplus_CtrlConfirm	118(%bx)
 
-#define SIREG DoC_M_CDSN_IO
 #define SI_CDSN_IO		(%si)
 
 			/* Print message string */
@@ -147,3 +154,16 @@
 /* #define DOC_ADDRESS	0xc800 */
 /* #define BIOS_EXTENSION */
 /* #define MILPLUS */
+ #define OLD_DOC2K 
+
+#ifdef OLD_DOC2K
+  #define CDSN_CTRL_BASE CDSN_CTRL_FLASH_IO + CDSN_CTRL_WP + CDSN_CTRL_CE
+  #define SLOWIO_WRITE(x) movb x, BX_SlowIO
+  #define SLOWIO_READ testb BX_SlowIO, %al
+  #define SIREG DoC_2k_CDSN_IO
+#else
+  #define CDSN_CTRL_BASE CDSN_CTRL_WP + CDSN_CTRL_CE
+  #define SLOWIO_WRITE(x) ;
+  #define SLOWIO_READ ;
+  #define SIREG DoC_M_CDSN_IO
+#endif

Index: makespl.c
===================================================================
RCS file: /home/cvs/mtd/docboot/makespl.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- makespl.c	3 Jan 2005 18:31:10 -0000	1.3
+++ makespl.c	29 Mar 2005 21:01:54 -0000	1.4
@@ -8,7 +8,12 @@
 /* The commandline is at the next 256-byte boundary after the parameters. */
 #define CMDLINE_LOCATION ((CHECKSUM_LOCATION+PARAM_BYTES+255)&0xffffff00)
 
+#ifdef OLD_DOC2K
+unsigned char buf[0x4000];
+#else
 unsigned char buf[0x3000];
+#endif
+unsigned char ff_pad[0x100];
 unsigned char spl_sig[16] =
 	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x55, 0x55,
 	  0x84, 0xa8, 0xac, 0xa0, 0x30, 0x30, 0x30, 0x30 };
@@ -31,23 +36,36 @@
 	unsigned long initrd_bytes;
 };
 
-void writeblocks(int outfd, unsigned char *buf, int len, unsigned char *oob) {
+void writeblocks(int outfd, unsigned char *buf, int len, unsigned char *oob,
+		 unsigned int halfblock) {
 	int ret;
+	int bs = halfblock ? 256 : 512;
 
 	while (len) {
-		if (len < 512) {
-			memset(buf + len, 0xff, 512 - len);
-			len = 512;
+		if (len < bs) {
+			memset(buf + len, 0xff, bs - len);
+			len = bs;
 		}
-		ret = write(outfd, buf, 512);
+		ret = write(outfd, buf, bs);
 		if (ret < 0) {
 			perror("write output file");
 			exit(1);
 		}
-		if (ret < 512) {
-			fprintf(stderr, "short write of output file (%d bytes < 512)\n", ret);
+		if (ret < bs) {
+			fprintf(stderr, "short write of output file (%d bytes < %d)\n", ret, bs);
 			exit(1);
 		}
+		if (halfblock) {
+			ret = write(outfd, ff_pad, bs);
+			if (ret < 0) {
+				perror("write output file");
+				exit(1);
+			}
+			if (ret < bs) {
+				fprintf(stderr, "short write of output file (%d bytes < %d)\n", ret, bs);
+				exit(1);
+			}
+		}
 		ret = write(outfd, oob, 16);
 		if (ret < 0) {
 			perror("write output file");
@@ -57,8 +75,8 @@
 			fprintf(stderr, "short write of output file (%d bytes < 16)\n", ret);
 			exit(1);
 		}
-		len -= 512;
-		buf += 512;
+		len -= bs;
+		buf += bs;
 	}
 }
 
@@ -89,6 +107,8 @@
 	int image_sects, setup_sects, kernel_sects, image_start;
 	struct params *params = (struct params *) (buf + CHECKSUM_LOCATION);
 
+	memset(ff_pad, 0xff, sizeof(ff_pad));
+
 	if (sizeof(struct params) != PARAM_BYTES) {
 		fprintf(stderr,
 "Param size mismatch!  Some idiot changed the code wrong!  Aborting.\n");
@@ -126,11 +146,17 @@
 	}
 	stublen = lseek(stubfd, 0, SEEK_END);
 	lseek(stubfd, 0, SEEK_SET);
+#ifdef OLD_DOC2K
+	stub_sects = (stublen + 255) >> 8;
+#else
 	stub_sects = (stublen + 511) >> 9;
+#endif
 	image_start = stub_sects << 9;
 	/* Note:  image_start should be == stublen, because doc_bootstub.S
 	 * should always pad to a 512-byte boundary.  Still, better safe than
-	 * sorry. */
+	 * sorry.
+	 *
+	 * (If OLD_DOC2K is defined, image_start will actually be stublen*2) */
 
 	imgfd = open(argv[optind++], O_RDONLY);
 	if (imgfd < 0) {
@@ -250,8 +276,20 @@
 		/* Set the slack byte to fix the csum */
 		params->checksum = 0 - checksum;
 	} else {
+#ifdef OLD_DOC2K
+		for (i = 0; i < (image_start/2); i++)
+			checksum += buf[i];
+		i = image_start;
+		while (i<sizeof(buf)) {
+			checksum += buf[i];
+			i++;
+			if ((i >> 8) & 1)
+				i += 256;
+		}
+#else
 		for (i = 0; i < sizeof(buf); i++)
 			checksum += buf[i];
+#endif
 
 		/* Set the slack byte to fix the csum */
 		params->checksum = 0x55 - checksum;
@@ -265,14 +303,19 @@
 			exit(1);
 		}
 	} else {
-		/* Write the bootstub page */
-		writeblocks(outfd, buf, 512, spl_sig);
-		/* Write the commandline page */
-		writeblocks(outfd, buf + 512, image_start - 512, stub_sig);
+#ifdef OLD_DOC2K
+		/* Write the bootstub in halfblock mode */
+		writeblocks(outfd, buf, image_start/2, stub_sig, 1);
+#else
+		/* Write the first bootstub page */
+		writeblocks(outfd, buf, 512, spl_sig, 0);
+		/* Write the rest of the bootstub */
+		writeblocks(outfd, buf + 512, image_start - 512, stub_sig, 0);
+#endif
 	}
 	/* Write the rest of the first buffer */
 	writeblocks(outfd, buf + image_start, sizeof(buf) - image_start,
-		    image_sig);
+		    image_sig, 0);
 
 	/* Now chuck out the rest of the kernel */
 
@@ -285,7 +328,7 @@
 		if (len == 0)
 			break;
 		
-		writeblocks(outfd, buf, len, image_sig);
+		writeblocks(outfd, buf, len, image_sig, 0);
 	}
 
 	if (!initrd) return 0;
@@ -301,7 +344,7 @@
 		if (len == 0)
 			break;
 		
-		writeblocks(initrd_outfd, buf, len, image_sig);
+		writeblocks(initrd_outfd, buf, len, image_sig, 0);
 	}
 
 	return 0;





More information about the linux-mtd-cvs mailing list