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