Index: u-boot-2006-06-30-2020/common/cmd_nand.c
===================================================================
--- u-boot-2006-06-30-2020.orig/common/cmd_nand.c	2006-09-01 17:07:24.000000000 -0400
+++ u-boot-2006-06-30-2020/common/cmd_nand.c	2006-09-07 14:07:31.561941307 -0400
@@ -129,12 +129,139 @@
 
 }
 
+#ifdef CFG_NAND_WRITE_YAFFS
+
+/*
+ * Write a yaffs filesystem image to NAND.
+ *
+ * If yaffs flag is 1, then the image is assumed to have been
+ * generated by yaffs2/utils/mkyaffsimage.c, and only
+ * 512B block + 16B OOB NAND is supported using the YAFFS1 OOB layout.
+ *
+ * Otherwise, the image is assumed to have been generated by
+ * yaffs2/utils/mkyaffs2image.c with Sergey Kubushyn's patch applied
+ * (see http://aleph1.co.uk/lurker/message/20060211.004601.77b55bf3.en.html)
+ * and supports larger 2KB block + 64B OOB NAND.
+ *
+ * Only MTD generated ECC is supported.
+ *
+ * Loosely based on mtd/util/nandwrite.c.
+ */
+
+static struct nand_oobinfo yaffs1_oobinfo = {
+	.useecc = MTD_NANDECC_PLACE,
+	.eccbytes = 6,
+	.eccpos = { 8, 9, 10, 13, 14, 15 }
+};
+
+static struct nand_oobinfo yaffs2_oobinfo = {
+	.useecc = MTD_NANDECC_AUTOPLACE,
+	.eccbytes = 24,
+	.eccpos = {
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = { {2, 38} }
+};
+
+static int nand_write_yaffs(nand_info_t *nand, ulong off, ulong *size, u_char *image, int yaffs)
+{
+	int imglen, pagelen;
+	u_char *imgptr, *oobptr;
+	int ret;
+	size_t retlen;
+	int i;
+	struct nand_oobinfo old_oobinfo;
+
+	imglen = *size;
+	imgptr = image;
+	*size = 0;
+
+	/* Make sure device page sizes are valid */
+	if ((yaffs == 1 && !(nand->oobsize == 16 && nand->oobblock == 512)) ||
+	    (yaffs == 2 && !(nand->oobsize == 64 && nand->oobblock == 2048))) {
+		printf("Unsupported flash layout\n");
+		return 1;
+	}
+
+	/* update oobinfo for yaffs */
+	old_oobinfo = nand->oobinfo;
+	nand->oobinfo = yaffs == 1 ? yaffs1_oobinfo : yaffs2_oobinfo;
+
+	/* Check, if image is pagealigned */
+	pagelen = nand->oobblock + nand->oobsize;
+	if ((off % nand->erasesize) != 0 || (imglen % pagelen) != 0) {
+		printf ("Input image is not page aligned\n");
+		goto closeall;
+	}
+
+	/* Check, if length fits into device */
+	if ( ((imglen / pagelen) * nand->oobblock) > (nand->size - off)) {
+		printf ("Input image does not fit into device");
+		goto closeall;
+	}
+
+	/* Get data from input and write to the device */
+	while (imglen > 0 && (off < nand->size)) {
+
+		/* if start of eraseblock, check for bad block */
+		if (off % nand->erasesize == 0 && (nand->block_isbad)(nand, off)) {
+			printf ("Bad block at 0x%08lx, will be skipped\n", off);
+
+			off += nand->erasesize;
+			continue;
+		}
+
+		oobptr = imgptr + nand->oobblock;
+
+		/* set the ECC bytes to 0xff so MTD will calculate it */
+		for (i = 0; i < nand->oobinfo.eccbytes; i++)
+			oobptr[nand->oobinfo.eccpos[i]] = 0xff;
+
+		/* Write OOB data first, as ecc will be placed in there */
+		ret = (nand->write_oob)(nand, off, nand->oobsize, &retlen, oobptr);
+		if (ret != 0) {
+			printf("\nNAND OOB write error %d at block 0x%08lx\n", ret, off);
+			goto closeall;
+		}
+
+		/* Write out the Page data */
+		ret = (nand->write)(nand, off, nand->oobblock, &retlen, imgptr);
+		if (ret != 0) {
+			printf("\nNAND write error %d at block 0x%08lx\n", ret, off);
+			goto closeall;
+		}
+
+		imgptr += pagelen;
+		imglen -= pagelen;
+		off += nand->oobblock;
+	}
+
+ closeall:
+	nand->oobinfo = old_oobinfo;
+
+	*size = imgptr - image;
+
+	if (imglen > 0) {
+		printf("Data did not fit into device, due to bad blocks\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+#endif /* CFG_NAND_WRITE_YAFFS */
+
+
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
 	int i, dev, ret;
 	ulong addr, off, size;
 	char *cmd, *s;
 	nand_info_t *nand;
+#ifdef CFG_NAND_WRITE_YAFFS
+	int yaffs = 0;		/* 1 = 512+64 NAND, 2 = 2048+64 NAND */
+#endif
 
 	/* at least two arguments please */
 	if (argc < 2)
@@ -239,6 +366,15 @@
 				clean = CLEAN_JFFS2;
 		}
 */
+#ifdef CFG_NAND_WRITE_YAFFS
+		s = strchr(cmd, '.');
+		if (s != NULL && strncmp(s, ".yaffs", 6) == 0) {
+			if (s[6] == '1')
+				yaffs = 1;
+			else if (s[6] == '2' || s[6] == '\0')
+				yaffs = 2;
+		}
+#endif
 		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
 
 		arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
@@ -251,6 +387,10 @@
 
 		if (i)
 			ret = nand_read(nand, off, &size, (u_char *)addr);
+#ifdef CFG_NAND_WRITE_YAFFS
+		else if(yaffs)
+			ret = nand_write_yaffs(nand, off, &size, (u_char *)addr, yaffs);
+#endif
 		else
 			ret = nand_write(nand, off, &size, (u_char *)addr);
 
@@ -271,6 +411,10 @@
 	"nand read[.jffs2]     - addr off size\n"
 	"nand write[.jffs2]    - addr off size - read/write `size' bytes starting\n"
 	"    at offset `off' to/from memory address `addr'\n"
+#ifdef CFG_NAND_WRITE_YAFFS
+	"nand write[.yaffs[1]] addr off size - read/write `size' bytes starting\n"
+	"    at offset `off' to memory address `addr' [yaffs1 or yaffs2 format]\n"
+#endif
 	"nand erase [clean] [off size] - erase `size' bytes from\n"
 	"    offset `off' (entire device if not specified)\n"
 	"nand bad - show bad blocks\n"
