Bläddra i källkod

implement cfgfs for devices with NAND flash like rb532

Waldemar Brodkorb 14 år sedan
förälder
incheckning
41f61a4fe1

+ 1 - 2
TODO

@@ -1,5 +1,4 @@
-- do a make bulk for all targets
-- implement update for MTD devices (foxboard,rb532,ag241)
+- implement update for MTD devices (rb532,ag241)
 - network scripts for wireless client and acess point
 - add tcsh and describe new package creation procedure in wiki
 - add toolchain only support for generic toolchains (mips/ppc/..)

+ 4 - 3
package/cfgfs/Makefile

@@ -4,16 +4,17 @@
 include ${TOPDIR}/rules.mk
 
 PKG_NAME:=		cfgfs
-PKG_VERSION:=		1.0.6
-PKG_RELEASE:=		5
+PKG_VERSION:=		1.0.7
+PKG_RELEASE:=		1
 PKG_DESCR:=		compressed config filesystem
 PKG_SECTION:=		base
+
 PKG_TARGET_DEPENDS:=	alix wrap foxboard ag241 rb532
 
 WRKDIST=		${WRKDIR}/${PKG_NAME}-${PKG_VERSION}
 NO_DISTFILES:=		1
 
-CFLINE_CFGFS:= 		select BUSYBOX_COMM\n\tselect BUSYBOX_MD5SUM\n\tselect BUSYBOX_XARGS\n\tselect BUSYBOX_FEATURE_SORT_BIG\n\tdepends on !ADK_TARGET_ROOTFS_NFSROOT\n\tdepends on !ADK_TARGET_ROOTFS_YAFFS
+CFLINE_CFGFS:= 		select BUSYBOX_COMM\n\tselect BUSYBOX_MD5SUM\n\tselect BUSYBOX_XARGS\n\tselect BUSYBOX_FEATURE_SORT_BIG\n\tdepends on !ADK_TARGET_ROOTFS_NFSROOT
 
 include ${TOPDIR}/mk/package.mk
 

+ 17 - 8
package/cfgfs/src/fwcf.sh

@@ -1,7 +1,7 @@
 #!/bin/sh
 # Copyright (c) 2006, 2007
 #	Thorsten Glaser <tg@mirbsd.de>
-# Copyright (c) 2009
+# Copyright (c) 2009, 2010
 #	Waldemar Brodkorb <wbx@openadk.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
@@ -21,7 +21,7 @@
 # Possible return values:
 # 0 - everything ok
 # 1 - syntax error
-# 1 - no 'cfgfs' mtd/cf partition found
+# 1 - no 'cfgfs' mtd/cf/nand partition found
 # 1 - cfgfs erase: failed
 # 1 - cfgfs setup: already run
 # 3 - cfgfs setup: mount --bind problems
@@ -42,7 +42,7 @@
 export PATH=/bin:/sbin:/usr/bin:/usr/sbin
 wd=$(pwd)
 cd /
-what='Configuration Filesystem Utility (cfgfs), Version 1.06'
+what='Configuration Filesystem Utility (cfgfs), Version 1.07'
 
 who=$(id -u)
 if [ $who -ne 0 ]; then
@@ -113,8 +113,17 @@ EOF
 	exit 1 ;;
 esac
 
-# find backend device, first try to find partition with ID 88
 mtd=0
+
+if [ -x /sbin/nand ];then
+	mtdtool=/sbin/nand
+fi
+
+if [ -x /sbin/mtd ];then
+	mtdtool=/sbin/mtd
+fi
+
+# find backend device, first try to find partition with ID 88
 part=$(fdisk -l|awk '$5 == 88 { print $1 }')
 if [ -z $part ]; then
 	# otherwise search for MTD device with name cfgfs
@@ -130,7 +139,7 @@ fi
 if test $1 = erase; then
 	dd if="$part" 2>&1 | md5sum 2>&1 >/dev/urandom
 	if [ $mtd -eq 1 ]; then
-		cfgfs.helper -Me | mtd -F write - cfgfs
+		cfgfs.helper -Me | eval $mtdtool -F write - cfgfs
 	else
 		cfgfs.helper -Me | cat > $part
 	fi
@@ -161,7 +170,7 @@ if test $1 = setup; then
 		x=$(dd if="$part" bs=4 count=1 2>/dev/null)
 		[[ "$x" = "FWCF" ]] || \
 			if [ $mtd -eq 1 ]; then
-				cfgfs.helper -Me | mtd -F write - cfgfs
+				cfgfs.helper -Me | eval $mtdtool -F write - cfgfs
 			else
 				cfgfs.helper -Me | cat > $part
 			fi
@@ -258,7 +267,7 @@ if test $1 = commit; then
 	done
 	rv=0
 	if [ $mtd -eq 1 ]; then
-		if ! ( cfgfs.helper -M /tmp/.cfgfs/temp | mtd -F write - cfgfs ); then
+		if ! ( cfgfs.helper -M /tmp/.cfgfs/temp | eval $mtdtool -F write - cfgfs ); then
 			echo 'cfgfs: error: cannot write to $part!'
 			rv=6
 		fi
@@ -387,7 +396,7 @@ if test $1 = restore; then
 		exit 12
 	fi
 	if [ $mtd -eq 1 ]; then
-		if ! ( cfgfs.helper -MD dump | mtd -F write - cfgfs ); then
+		if ! ( cfgfs.helper -MD dump | eval $mtdtool -F write - cfgfs ); then
 			echo 'cfgfs: error: cannot write to $part!'
 			exit 6
 		fi

+ 4 - 8
package/nand/Makefile

@@ -5,7 +5,7 @@ include ${TOPDIR}/rules.mk
 
 PKG_NAME:=		nand
 PKG_VERSION:=		1.0
-PKG_RELEASE:=		1
+PKG_RELEASE:=		3
 PKG_DESCR:=		NAND utility
 PKG_SECTION:=		base
 
@@ -25,15 +25,11 @@ INSTALL_STYLE:=		manual
 
 do-build:
 	mkdir -p ${WRKBUILD}
-	${CP} ./src/* ${WRKBUILD}
-	${TARGET_CC} ${TCPPFLAGS} ${TCFLAGS} -o ${WRKBUILD}/nandwrite \
-		${WRKBUILD}/nandwrite.c
-	${TARGET_CC} ${TCPPFLAGS} ${TCFLAGS} -o ${WRKBUILD}/nanddump \
-		${WRKBUILD}/nanddump.c
+	${TARGET_CC} -Wall ${TCPPFLAGS} ${TCFLAGS} -o ${WRKBUILD}/nand \
+		./src/nand.c
 
 do-install:
 	${INSTALL_DIR} ${IDIR_NAND}/sbin
-	${INSTALL_BIN} ${WRKBUILD}/nandwrite ${IDIR_NAND}/sbin
-	${INSTALL_BIN} ${WRKBUILD}/nanddump ${IDIR_NAND}/sbin
+	${INSTALL_BIN} ${WRKBUILD}/nand ${IDIR_NAND}/sbin
 
 include ${TOPDIR}/mk/pkg-bottom.mk

+ 581 - 0
package/nand/src/nand.c

@@ -0,0 +1,581 @@
+/*
+ * nand - simple nand memory technology device manipulation tool
+ *
+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The code is based on the mtd-utils nandwrite and flash_erase_all.
+ */
+
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <errno.h>
+#include <error.h>
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <getopt.h>
+
+#include "mtd/mtd-user.h"
+#include <linux/reboot.h>
+
+int nand_open(const char *, int);
+int nand_erase(const char *);
+int nand_info(const char *);
+int nand_write(const char*, const char *, int);
+void usage(void) __attribute__((noreturn));
+
+#define MAX_PAGE_SIZE	4096
+#define MAX_OOB_SIZE	128
+
+static unsigned char writebuf[MAX_PAGE_SIZE];
+static unsigned char oobbuf[MAX_OOB_SIZE];
+static unsigned char oobreadbuf[MAX_OOB_SIZE];
+
+static struct nand_oobinfo autoplace_oobinfo = {
+	.useecc = MTD_NANDECC_AUTOPLACE
+};
+
+static void erase_buffer(void *buffer, size_t size)
+{
+	const uint8_t kEraseByte = 0xff;
+
+	if (buffer != NULL && size > 0) {
+		memset(buffer, kEraseByte, size);
+	}
+}
+
+int nand_open(const char *nand, int flags) {
+
+	FILE *fp;
+	char dev[PATH_MAX];
+	int i;
+
+	if ((fp = fopen("/proc/mtd", "r"))) {
+		while (fgets(dev, sizeof(dev), fp)) {
+			if (sscanf(dev, "mtd%d:", &i) && strstr(dev, nand)) {
+				snprintf(dev, sizeof(dev), "/dev/mtd%d", i);
+				fclose(fp);
+				return open(dev, flags);
+			}
+		}
+		fclose(fp);
+	}
+
+	return open(nand, flags);
+}
+
+int nand_info(const char *nand) {
+
+	int fd, ret;
+	mtd_info_t nandinfo;
+	struct nand_oobinfo oobinfo;
+	loff_t offset;
+
+	if ((fd = nand_open(nand, O_RDONLY)) < 0) {
+		fprintf(stderr, "nand: unable to open MTD device %s\n", nand);
+		return 1;
+	}
+
+	if (ioctl(fd, MEMGETINFO, &nandinfo) != 0) {
+		fprintf(stderr, "nand: unable to get MTD device info from %s\n", nand);
+		return 1;
+	}
+
+	if (nandinfo.type == MTD_NANDFLASH) {
+		fprintf(stdout, "MTD devise is NAND\n");
+	} else {
+		fprintf(stdout, "MTD devise is NOT NAND\n");
+		return 1;
+	}
+
+	fprintf(stdout, "NAND block/erase size is: %u\n", nandinfo.erasesize); 
+	fprintf(stdout, "NAND page size is: %u\n", nandinfo.writesize); 
+	fprintf(stdout, "NAND OOB size is: %u\n", nandinfo.oobsize); 
+	fprintf(stdout, "NAND partition size is: %u\n", nandinfo.size); 
+
+	for (offset = 0; offset < nandinfo.size; offset += nandinfo.erasesize) {
+		ret = ioctl(fd, MEMGETBADBLOCK, &offset);
+		if (ret > 0) {
+			printf("\nSkipping bad block at %llu\n", offset);
+			continue;
+		} else if (ret < 0) {
+			if (errno == EOPNOTSUPP) {
+				fprintf(stderr, "Bad block check not available\n");
+				return 1;
+			}
+		}
+	}
+	
+	if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
+		fprintf(stderr, "Unable to get NAND oobinfo\n");
+		return 1;
+	}
+
+	if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
+		fprintf(stdout, "NAND device/driver supports autoplacement of OOB\n");
+	}
+
+	return 0;
+}
+
+int nand_erase(const char *nand) {
+
+	mtd_info_t meminfo;
+	struct nand_oobinfo oobinfo;
+	int fd, clmpos, clmlen;
+	erase_info_t erase;
+
+	clmpos = 0;
+	clmlen = 8;
+
+	erase_buffer(oobbuf, sizeof(oobbuf));
+
+	if ((fd = nand_open(nand, O_RDWR)) < 0) {
+		fprintf(stderr, "nand: %s: unable to open MTD device\n", nand);
+		return 1;
+	}
+
+	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
+		fprintf(stderr, "nand: %s: unable to get MTD device info\n", nand);
+		return 1;
+	}
+
+	erase.length = meminfo.erasesize;
+
+	for (erase.start = 0; erase.start < meminfo.size; erase.start += meminfo.erasesize) {
+		if (ioctl(fd, MEMERASE, &erase) != 0) {
+			fprintf(stderr, "\nnand: %s: MTD Erase failure: %s\n", nand, strerror(errno));
+			continue;
+		}
+
+		struct mtd_oob_buf oob;
+
+		if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0) {
+			fprintf(stderr, "Unable to get NAND oobinfo\n");
+			return 1;
+		}
+
+		if (oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
+			fprintf(stderr, "NAND device/driver does not support autoplacement of OOB\n");
+			return 1;
+		}
+
+		if (!oobinfo.oobfree[0][1]) {
+			fprintf(stderr, "Autoplacement selected and no empty space in oob\n");
+			return 1;
+		}
+		clmpos = oobinfo.oobfree[0][0];
+		clmlen = oobinfo.oobfree[0][1];
+		if (clmlen > 8)
+			clmlen = 8;
+
+		//fprintf(stdout, "Using clmlen: %d clmpos: %d\n", clmlen, clmpos); 
+
+		oob.ptr = oobbuf;
+		oob.start = erase.start + clmpos;
+		oob.length = clmlen;
+		if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
+			fprintf(stderr, "\nnand: %s: MTD writeoob failure: %s\n", nand, strerror(errno));
+			continue;
+		}
+	}
+	return 0;
+}
+
+int nand_write(const char *img, const char *nand, int quiet) {
+
+	static bool pad = true;
+	static const char *standard_input = "-";
+	static bool autoplace = true;
+	static bool markbad = true;
+	static int mtdoffset = 0;
+	int cnt = 0;
+	int fd = -1;
+	int ifd = -1;
+	int imglen = 0, pagelen;
+	bool baderaseblock = false;
+	int blockstart = -1;
+	struct mtd_info_user meminfo;
+	struct mtd_oob_buf oob;
+	loff_t offs;
+	int ret, readlen;
+	int oobinfochanged = 0;
+	struct nand_oobinfo old_oobinfo;
+
+	erase_buffer(oobbuf, sizeof(oobbuf));
+
+	/* Open the device */
+	if ((fd = nand_open(nand, O_RDWR | O_SYNC)) == -1) {
+		perror(nand);
+		exit (EXIT_FAILURE);
+	}
+
+	/* Fill in MTD device capability structure */
+	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
+		perror("MEMGETINFO");
+		close(fd);
+		exit (EXIT_FAILURE);
+	}
+
+	/* Make sure device page sizes are valid */
+	if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
+			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
+			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
+			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
+		fprintf(stderr, "Unknown flash (not normal NAND)\n");
+		close(fd);
+		exit (EXIT_FAILURE);
+	}
+
+	if (autoplace) {
+		/* Read the current oob info */
+		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
+			perror ("MEMGETOOBSEL");
+			close (fd);
+			exit (EXIT_FAILURE);
+		}
+
+		// autoplace ECC ?
+		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
+
+			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
+				perror ("MEMSETOOBSEL");
+				close (fd);
+				exit (EXIT_FAILURE);
+			}
+			oobinfochanged = 1;
+		}
+	}
+
+	oob.length = meminfo.oobsize;
+	oob.ptr = oobbuf;
+
+	/* Determine if we are reading from standard input or from a file. */
+	if (strcmp(img, standard_input) == 0) {
+		ifd = STDIN_FILENO;
+	} else {
+		ifd = open(img, O_RDONLY);
+	}
+
+	if (ifd == -1) {
+		perror(img);
+		goto restoreoob;
+	}
+
+	pagelen = meminfo.writesize;
+
+	/*
+	 * For the standard input case, the input size is merely an
+	 * invariant placeholder and is set to the write page
+	 * size. Otherwise, just use the input file size.
+	 */
+
+	if (ifd == STDIN_FILENO) {
+	    imglen = pagelen;
+	} else {
+	    imglen = lseek(ifd, 0, SEEK_END);
+	    lseek (ifd, 0, SEEK_SET);
+	}
+
+	// Check, if file is page-aligned
+	if ((!pad) && ((imglen % pagelen) != 0)) {
+		fprintf (stderr, "Input file is not page-aligned. Use the padding "
+				 "option.\n");
+		goto closeall;
+	}
+
+	// Check, if length fits into device
+	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
+		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
+				imglen, pagelen, meminfo.writesize, meminfo.size);
+		perror ("Input file does not fit into device");
+		goto closeall;
+	}
+
+	/*
+	 * Get data from input and write to the device while there is
+	 * still input to read and we are still within the device
+	 * bounds. Note that in the case of standard input, the input
+	 * length is simply a quasi-boolean flag whose values are page
+	 * length or zero.
+	 */
+	while (imglen && (mtdoffset < meminfo.size)) {
+		// new eraseblock , check for bad block(s)
+		// Stay in the loop to be sure if the mtdoffset changes because
+		// of a bad block, that the next block that will be written to
+		// is also checked. Thus avoiding errors if the block(s) after the
+		// skipped block(s) is also bad
+		while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) {
+			blockstart = mtdoffset & (~meminfo.erasesize + 1);
+			offs = blockstart;
+			baderaseblock = false;
+			if (quiet < 2)
+				fprintf (stdout, "Writing data to block %d at offset 0x%x\n",
+						 blockstart / meminfo.erasesize, blockstart);
+
+			/* Check all the blocks in an erase block for bad blocks */
+			do {
+				if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
+					perror("ioctl(MEMGETBADBLOCK)");
+					goto closeall;
+				}
+				if (ret == 1) {
+					baderaseblock = true;
+					if (!quiet)
+						fprintf (stderr, "Bad block at %x "
+								"from %x will be skipped\n",
+								(int) offs, blockstart);
+				}
+
+				if (baderaseblock) {
+					mtdoffset = blockstart + meminfo.erasesize;
+				}
+				offs +=  meminfo.erasesize;
+			} while ( offs < blockstart + meminfo.erasesize );
+
+		}
+
+		readlen = meminfo.writesize;
+
+		if (ifd != STDIN_FILENO) {
+			int tinycnt = 0;
+
+			if (pad && (imglen < readlen))
+			{
+				readlen = imglen;
+				erase_buffer(writebuf + readlen, meminfo.writesize - readlen);
+			}
+
+			/* Read Page Data from input file */
+			while(tinycnt < readlen) {
+				cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
+				if (cnt == 0) { // EOF
+					break;
+				} else if (cnt < 0) {
+					perror ("File I/O error on input file");
+					goto closeall;
+				}
+				tinycnt += cnt;
+			}
+		} else {
+			int tinycnt = 0;
+
+			while(tinycnt < readlen) {
+				cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
+				if (cnt == 0) { // EOF
+					break;
+				} else if (cnt < 0) {
+					perror ("File I/O error on stdin");
+					goto closeall;
+				}
+				tinycnt += cnt;
+			}
+
+			/* No padding needed - we are done */
+			if (tinycnt == 0) {
+				imglen = 0;
+				break;
+			}
+
+			/* No more bytes - we are done after writing the remaining bytes */
+			if (cnt == 0) {
+				imglen = 0;
+			}
+
+			/* Padding */
+			if (pad && (tinycnt < readlen)) {
+				erase_buffer(writebuf + tinycnt, meminfo.writesize - tinycnt);
+			}
+		}
+
+		/* Write out the Page data */
+		if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) {
+			int rewind_blocks;
+			off_t rewind_bytes;
+			erase_info_t erase;
+
+			perror ("pwrite");
+			/* Must rewind to blockstart if we can */
+			rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */
+			rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen;
+			if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) {
+				perror("lseek");
+				fprintf(stderr, "Failed to seek backwards to recover from write error\n");
+				goto closeall;
+			}
+			erase.start = blockstart;
+			erase.length = meminfo.erasesize;
+			fprintf(stderr, "Erasing failed write from %08lx-%08lx\n",
+				(long)erase.start, (long)erase.start+erase.length-1);
+			if (ioctl(fd, MEMERASE, &erase) != 0) {
+				perror("MEMERASE");
+				goto closeall;
+			}
+
+			if (markbad) {
+				loff_t bad_addr = mtdoffset & (~(meminfo.erasesize) + 1);
+				fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr);
+				if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
+					perror("MEMSETBADBLOCK");
+					/* But continue anyway */
+				}
+			}
+			mtdoffset = blockstart + meminfo.erasesize;
+			imglen += rewind_blocks * meminfo.writesize;
+
+			continue;
+		}
+		if (ifd != STDIN_FILENO) {
+			imglen -= readlen;
+		}
+		mtdoffset += meminfo.writesize;
+	}
+
+closeall:
+	close(ifd);
+
+restoreoob:
+	if (oobinfochanged == 1) {
+		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
+			perror ("MEMSETOOBSEL");
+			close (fd);
+			exit (EXIT_FAILURE);
+		}
+	}
+
+	close(fd);
+
+	if ((ifd != STDIN_FILENO) && (imglen > 0)) {
+		perror ("Data was only partially written due to error\n");
+		exit (EXIT_FAILURE);
+	}
+
+	/* Return happy */
+	return EXIT_SUCCESS;
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "Usage: nand [<options> ...] <command> [<arguments> ...] <device>\n\n"
+	"The device is in the format of mtdX (eg: mtd4) or its label.\n"
+	"nand recognises these commands:\n"
+	"        erase                   erase all data on device\n"
+	"        info                    print information about device\n"
+	"        write <imagefile>|-     write <imagefile> (use - for stdin) to device\n"
+	"Following options are available:\n"
+	"        -q                      quiet mode\n"
+	"        -r                      reboot after successful command\n"
+	"Example: To write linux.img to mtd partition labeled as linux\n"
+	"         mtd write linux.img linux\n\n");
+	exit(1);
+}
+
+int main(int argc, char **argv) {
+
+	int ch, quiet, boot;
+	char *device;
+	enum {
+		CMD_INFO,
+		CMD_ERASE,
+		CMD_WRITE,
+	} cmd;
+
+	boot = 0;
+	quiet = 0;
+
+	while ((ch = getopt(argc, argv, "Fqr:")) != -1)
+		switch (ch) {
+			case 'F':
+				quiet = 1;
+				/* FALLTHROUGH */
+			case 'q':
+				quiet++;
+				break;
+			case 'r':
+				boot = 1;
+				break;
+			case '?':
+			default:
+				usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc < 2)
+		usage();
+
+	if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
+		cmd = CMD_ERASE;
+		device = argv[1];
+	} else if ((strcmp(argv[0], "info") == 0) && (argc == 2)) {
+		cmd = CMD_INFO;
+		device = argv[1];
+	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
+		cmd = CMD_WRITE;
+		device = argv[2];
+	} else {
+		usage();
+	}
+
+	sync();
+
+	switch (cmd) {
+		case CMD_INFO:
+			if (quiet < 2)
+				fprintf(stderr, "Info about %s ...\n", device);
+			nand_info(device);
+			break;
+		case CMD_ERASE:
+			if (quiet < 2)
+				fprintf(stderr, "Erasing %s ...\n", device);
+			nand_erase(device);
+			break;
+		case CMD_WRITE:
+			if (quiet < 2)
+				fprintf(stderr, "Writing from %s to %s ... ", argv[1], device);
+			nand_erase(device);
+			nand_write(argv[1], device, quiet);
+			if (quiet < 2)
+				fprintf(stderr, "\n");
+			break;
+	}
+	
+	sync();
+
+	if (boot) {
+		fprintf(stderr, "\nRebooting ... ");
+		fflush(stdout);
+		fflush(stderr);
+		syscall(SYS_reboot,LINUX_REBOOT_MAGIC1,LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART,NULL);
+	}	
+
+	return 0;
+}

+ 0 - 421
package/nand/src/nanddump.c

@@ -1,421 +0,0 @@
-/*
- *  nanddump.c
- *
- *  Copyright (C) 2000 David Woodhouse (dwmw2@infradead.org)
- *                     Steven J. Hill (sjhill@realitydiluted.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Overview:
- *   This utility dumps the contents of raw NAND chips or NAND
- *   chips contained in DoC devices.
- */
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <asm/types.h>
-#include <mtd/mtd-user.h>
-
-#define PROGRAM "nanddump"
-#define VERSION "$Revision: 1.29 $"
-
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static void display_help (void)
-{
-	printf(
-"Usage: nanddump [OPTIONS] MTD-device\n"
-"Dumps the contents of a nand mtd partition.\n"
-"\n"
-"           --help               Display this help and exit\n"
-"           --version            Output version information and exit\n"
-"-f file    --file=file          Dump to file\n"
-"-i         --ignoreerrors       Ignore errors\n"
-"-l length  --length=length      Length\n"
-"-n         --noecc              Read without error correction\n"
-"-o         --omitoob            Omit oob data\n"
-"-b         --omitbad            Omit bad blocks from the dump\n"
-"-p         --prettyprint        Print nice (hexdump)\n"
-"-q         --quiet              Don't display progress and status messages\n"
-"-s addr    --startaddress=addr  Start address\n"
-	);
-	exit(EXIT_SUCCESS);
-}
-
-static void display_version (void)
-{
-	printf(PROGRAM " " VERSION "\n"
-			"\n"
-			PROGRAM " comes with NO WARRANTY\n"
-			"to the extent permitted by law.\n"
-			"\n"
-			"You may redistribute copies of " PROGRAM "\n"
-			"under the terms of the GNU General Public Licence.\n"
-			"See the file `COPYING' for more information.\n");
-	exit(EXIT_SUCCESS);
-}
-
-// Option variables
-
-static bool		ignoreerrors = false;	// ignore errors
-static bool		pretty_print = false;	// print nice in ascii
-static bool		noecc = false;		// don't error correct
-static bool		omitoob = false;	// omit oob data
-static unsigned long	start_addr;		// start address
-static unsigned long	length;			// dump length
-static const char	*mtddev;		// mtd device name
-static const char	*dumpfile;		// dump file name
-static bool		omitbad = false;
-static bool		quiet = false;		// suppress diagnostic output
-
-static void process_options (int argc, char * const argv[])
-{
-	int error = 0;
-
-	for (;;) {
-		int option_index = 0;
-		static const char *short_options = "bs:f:il:opqn";
-		static const struct option long_options[] = {
-			{"help", no_argument, 0, 0},
-			{"version", no_argument, 0, 0},
-			{"file", required_argument, 0, 'f'},
-			{"ignoreerrors", no_argument, 0, 'i'},
-			{"prettyprint", no_argument, 0, 'p'},
-			{"omitoob", no_argument, 0, 'o'},
-			{"omitbad", no_argument, 0, 'b'},
-			{"startaddress", required_argument, 0, 's'},
-			{"length", required_argument, 0, 'l'},
-			{"noecc", no_argument, 0, 'n'},
-			{"quiet", no_argument, 0, 'q'},
-			{0, 0, 0, 0},
-		};
-
-		int c = getopt_long(argc, argv, short_options,
-				long_options, &option_index);
-		if (c == EOF) {
-			break;
-		}
-
-		switch (c) {
-			case 0:
-				switch (option_index) {
-					case 0:
-						display_help();
-						break;
-					case 1:
-						display_version();
-						break;
-				}
-				break;
-			case 'b':
-				omitbad = true;
-				break;
-			case 's':
-				start_addr = strtol(optarg, NULL, 0);
-				break;
-			case 'f':
-				if (!(dumpfile = strdup(optarg))) {
-					perror("stddup");
-					exit(EXIT_FAILURE);
-				}
-				break;
-			case 'i':
-				ignoreerrors = true;
-				break;
-			case 'l':
-				length = strtol(optarg, NULL, 0);
-				break;
-			case 'o':
-				omitoob = true;
-				break;
-			case 'p':
-				pretty_print = true;
-				break;
-			case 'q':
-				quiet = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
-			case '?':
-				error++;
-				break;
-		}
-	}
-
-	if (quiet && pretty_print) {
-		fprintf(stderr, "The quiet and pretty print options are mutually-\n"
-				"exclusive. Choose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if ((argc - optind) != 1 || error)
-		display_help ();
-
-	mtddev = argv[optind];
-}
-
-/*
- * Buffers for reading data from flash
- */
-static unsigned char readbuf[4096];
-static unsigned char oobbuf[128];
-
-/*
- * Main program
- */
-int main(int argc, char * const argv[])
-{
-	unsigned long ofs, end_addr = 0;
-	unsigned long long blockstart = 1;
-	int ret, i, fd, ofd, bs, badblock = 0;
-	struct mtd_oob_buf oob = {0, 16, oobbuf};
-	mtd_info_t meminfo;
-	char pretty_buf[80];
-	int oobinfochanged = 0 ;
-	struct nand_oobinfo old_oobinfo;
-	struct mtd_ecc_stats stat1, stat2;
-	bool eccstats = false;
-
-	process_options(argc, argv);
-
-	/* Open MTD device */
-	if ((fd = open(mtddev, O_RDONLY)) == -1) {
-		perror(mtddev);
-		exit (EXIT_FAILURE);
-	}
-
-	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
-		close(fd);
-		exit (EXIT_FAILURE);
-	}
-
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 32 && meminfo.writesize == 1024) &&
-			!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
-	/* Read the real oob length */
-	oob.length = meminfo.oobsize;
-
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	} else {
-
-		/* check if we can read ecc stats */
-		if (!ioctl(fd, ECCGETSTATS, &stat1)) {
-			eccstats = true;
-			if (!quiet) {
-				fprintf(stderr, "ECC failed: %d\n", stat1.failed);
-				fprintf(stderr, "ECC corrected: %d\n", stat1.corrected);    
-				fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks);    
-				fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks);    
-			}
-		} else
-			perror("No ECC status information available");
-	}
-
-	/* Open output file for writing. If file name is "-", write to standard
-	 * output. */
-	if (!dumpfile) {
-		ofd = STDOUT_FILENO;
-	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
-		perror (dumpfile);
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
-
-	/* Initialize start/end addresses and block size */
-	if (length)
-		end_addr = start_addr + length;
-	if (!length || end_addr > meminfo.size)
-		end_addr = meminfo.size;
-
-	bs = meminfo.writesize;
-
-	/* Print informative message */
-
-	if (!quiet) {
-		fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
-				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
-		fprintf(stderr,
-				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
-				(unsigned int) start_addr, (unsigned int) end_addr);
-	}
-	/* Dump the flash contents */
-	for (ofs = start_addr; ofs < end_addr ; ofs+=bs) {
-
-		// new eraseblock , check for bad block
-		if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
-			blockstart = ofs & (~meminfo.erasesize + 1);
-			if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
-				perror("ioctl(MEMGETBADBLOCK)");
-				goto closeall;
-			}
-		}
-
-		if (badblock) {
-			if (omitbad)
-				continue;
-			memset (readbuf, 0xff, bs);
-		} else {
-			/* Read page data and exit on failure */
-			if (pread(fd, readbuf, bs, ofs) != bs) {
-				perror("pread");
-				goto closeall;
-			}
-		}
-
-		/* ECC stats available ? */
-		if (eccstats) {
-			if (ioctl(fd, ECCGETSTATS, &stat2)) {
-				perror("ioctl(ECCGETSTATS)");
-				goto closeall;
-			}
-			if (stat1.failed != stat2.failed)
-				fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
-						" at offset 0x%08lx\n",
-						stat2.failed - stat1.failed, ofs);
-			if (stat1.corrected != stat2.corrected)
-				fprintf(stderr, "ECC: %d corrected bitflip(s) at"
-						" offset 0x%08lx\n",
-						stat2.corrected - stat1.corrected, ofs);
-			stat1 = stat2;
-		}
-
-		/* Write out page data */
-		if (pretty_print) {
-			for (i = 0; i < bs; i += 16) {
-				sprintf(pretty_buf,
-						"0x%08x: %02x %02x %02x %02x %02x %02x %02x "
-						"%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-						(unsigned int) (ofs + i),  readbuf[i],
-						readbuf[i+1], readbuf[i+2],
-						readbuf[i+3], readbuf[i+4],
-						readbuf[i+5], readbuf[i+6],
-						readbuf[i+7], readbuf[i+8],
-						readbuf[i+9], readbuf[i+10],
-						readbuf[i+11], readbuf[i+12],
-						readbuf[i+13], readbuf[i+14],
-						readbuf[i+15]);
-				write(ofd, pretty_buf, 60);
-			}
-		} else
-			write(ofd, readbuf, bs);
-
-
-
-		if (omitoob)
-			continue;
-
-		if (badblock) {
-			memset (readbuf, 0xff, meminfo.oobsize);
-		} else {
-			/* Read OOB data and exit on failure */
-			oob.start = ofs;
-			if (ioctl(fd, MEMREADOOB, &oob) != 0) {
-				perror("ioctl(MEMREADOOB)");
-				goto closeall;
-			}
-		}
-
-		/* Write out OOB data */
-		if (pretty_print) {
-			if (meminfo.oobsize < 16) {
-				sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
-						"%02x %02x\n",
-						oobbuf[0], oobbuf[1], oobbuf[2],
-						oobbuf[3], oobbuf[4], oobbuf[5],
-						oobbuf[6], oobbuf[7]);
-				write(ofd, pretty_buf, 48);
-				continue;
-			}
-
-			for (i = 0; i < meminfo.oobsize; i += 16) {
-				sprintf(pretty_buf, "  OOB Data: %02x %02x %02x %02x %02x %02x "
-						"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-						oobbuf[i], oobbuf[i+1], oobbuf[i+2],
-						oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
-						oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
-						oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
-						oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
-						oobbuf[i+15]);
-				write(ofd, pretty_buf, 60);
-			}
-		} else
-			write(ofd, oobbuf, meminfo.oobsize);
-	}
-
-	/* reset oobinfo */
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close(fd);
-			close(ofd);
-			return EXIT_FAILURE;
-		}
-	}
-	/* Close the output file and MTD device */
-	close(fd);
-	close(ofd);
-
-	/* Exit happy */
-	return EXIT_SUCCESS;
-
-closeall:
-	/* The new mode change is per file descriptor ! */
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0)  {
-			perror ("MEMSETOOBSEL");
-		}
-	}
-	close(fd);
-	close(ofd);
-	exit(EXIT_FAILURE);
-}

+ 0 - 647
package/nand/src/nandwrite.c

@@ -1,647 +0,0 @@
-/*
- *  nandwrite.c
- *
- *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *		  2003 Thomas Gleixner (tglx@linutronix.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Overview:
- *   This utility writes a binary image directly to a NAND flash
- *   chip or NAND chips contained in DoC devices. This is the
- *   "inverse operation" of nanddump.
- *
- * tglx: Major rewrite to handle bad blocks, write data with or without ECC
- *	 write oob data only on request
- *
- * Bug/ToDo:
- */
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <getopt.h>
-
-#include <asm/types.h>
-#include "mtd/mtd-user.h"
-
-#define PROGRAM "nandwrite"
-#define VERSION "$Revision: 1.32 $"
-
-#define MAX_PAGE_SIZE	4096
-#define MAX_OOB_SIZE	128
-
-/*
- * Buffer array used for writing data
- */
-static unsigned char writebuf[MAX_PAGE_SIZE];
-static unsigned char oobbuf[MAX_OOB_SIZE];
-static unsigned char oobreadbuf[MAX_OOB_SIZE];
-
-// oob layouts to pass into the kernel as default
-static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
-
-static void display_help (void)
-{
-	printf(
-"Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
-"Writes to the specified MTD device.\n"
-"\n"
-"  -a, --autoplace         Use auto oob layout\n"
-"  -j, --jffs2             Force jffs2 oob layout (legacy support)\n"
-"  -y, --yaffs             Force yaffs oob layout (legacy support)\n"
-"  -f, --forcelegacy       Force legacy support on autoplacement-enabled mtd\n"
-"                          device\n"
-"  -m, --markbad           Mark blocks bad if write fails\n"
-"  -n, --noecc             Write without ecc\n"
-"  -o, --oob               Image contains oob data\n"
-"  -s addr, --start=addr   Set start address (default is 0)\n"
-"  -p, --pad               Pad to page size\n"
-"  -b, --blockalign=1|2|4  Set multiple of eraseblocks to align to\n"
-"  -q, --quiet             Don't display progress messages\n"
-"      --help              Display this help and exit\n"
-"      --version           Output version information and exit\n"
-	);
-	exit (EXIT_SUCCESS);
-}
-
-static void display_version (void)
-{
-	printf(PROGRAM " " VERSION "\n"
-			"\n"
-			"Copyright (C) 2003 Thomas Gleixner \n"
-			"\n"
-			PROGRAM " comes with NO WARRANTY\n"
-			"to the extent permitted by law.\n"
-			"\n"
-			"You may redistribute copies of " PROGRAM "\n"
-			"under the terms of the GNU General Public Licence.\n"
-			"See the file `COPYING' for more information.\n");
-	exit (EXIT_SUCCESS);
-}
-
-static const char	*standard_input = "-";
-static const char	*mtd_device, *img;
-static int		mtdoffset = 0;
-static bool		quiet = false;
-static bool		writeoob = false;
-static bool		autoplace = false;
-static bool		markbad = false;
-static bool		forcejffs2 = false;
-static bool		forceyaffs = false;
-static bool		forcelegacy = false;
-static bool		noecc = false;
-static bool		pad = false;
-static int		blockalign = 1; /*default to using 16K block size */
-
-static void process_options (int argc, char * const argv[])
-{
-	int error = 0;
-
-	for (;;) {
-		int option_index = 0;
-		static const char *short_options = "ab:fjmnopqs:y";
-		static const struct option long_options[] = {
-			{"help", no_argument, 0, 0},
-			{"version", no_argument, 0, 0},
-			{"autoplace", no_argument, 0, 'a'},
-			{"blockalign", required_argument, 0, 'b'},
-			{"forcelegacy", no_argument, 0, 'f'},
-			{"jffs2", no_argument, 0, 'j'},
-			{"markbad", no_argument, 0, 'm'},
-			{"noecc", no_argument, 0, 'n'},
-			{"oob", no_argument, 0, 'o'},
-			{"pad", no_argument, 0, 'p'},
-			{"quiet", no_argument, 0, 'q'},
-			{"start", required_argument, 0, 's'},
-			{"yaffs", no_argument, 0, 'y'},
-			{0, 0, 0, 0},
-		};
-
-		int c = getopt_long(argc, argv, short_options,
-				long_options, &option_index);
-		if (c == EOF) {
-			break;
-		}
-
-		switch (c) {
-			case 0:
-				switch (option_index) {
-					case 0:
-						display_help();
-						break;
-					case 1:
-						display_version();
-						break;
-				}
-				break;
-			case 'q':
-				quiet = true;
-				break;
-			case 'a':
-				autoplace = true;
-				break;
-			case 'j':
-				forcejffs2 = true;
-				break;
-			case 'y':
-				forceyaffs = true;
-				break;
-			case 'f':
-				forcelegacy = true;
-				break;
-			case 'n':
-				noecc = true;
-				break;
-			case 'm':
-				markbad = true;
-				break;
-			case 'o':
-				writeoob = true;
-				break;
-			case 'p':
-				pad = true;
-				break;
-			case 's':
-				mtdoffset = strtol (optarg, NULL, 0);
-				break;
-			case 'b':
-				blockalign = atoi (optarg);
-				break;
-			case '?':
-				error++;
-				break;
-		}
-	}
-
-	if (mtdoffset < 0) {
-		fprintf(stderr, "Can't specify a negative device offset `%d'\n",
-				mtdoffset);
-		exit (EXIT_FAILURE);
-	}
-
-	argc -= optind;
-	argv += optind;
-
-	/*
-	 * There must be at least the MTD device node positional
-	 * argument remaining and, optionally, the input file.
-	 */
-
-	if (argc < 1 || argc > 2 || error)
-		display_help ();
-
-	mtd_device = argv[0];
-
-	/*
-	 * Standard input may be specified either explictly as "-" or
-	 * implicity by simply omitting the second of the two
-	 * positional arguments.
-	 */
-
-	img = ((argc == 2) ? argv[1] : standard_input);
-}
-
-static void erase_buffer(void *buffer, size_t size)
-{
-	const uint8_t kEraseByte = 0xff;
-
-	if (buffer != NULL && size > 0) {
-		memset(buffer, kEraseByte, size);
-	}
-}
-
-/*
- * Main program
- */
-int main(int argc, char * const argv[])
-{
-	int cnt = 0;
-	int fd = -1;
-	int ifd = -1;
-	int imglen = 0, pagelen;
-	bool baderaseblock = false;
-	int blockstart = -1;
-	struct mtd_info_user meminfo;
-	struct mtd_oob_buf oob;
-	loff_t offs;
-	int ret, readlen;
-	int oobinfochanged = 0;
-	struct nand_oobinfo old_oobinfo;
-	int readcnt = 0;
-
-	process_options(argc, argv);
-
-	erase_buffer(oobbuf, sizeof(oobbuf));
-
-	if (pad && writeoob) {
-		fprintf(stderr, "Can't pad when oob data is present.\n");
-		exit (EXIT_FAILURE);
-	}
-
-	/* Open the device */
-	if ((fd = open(mtd_device, O_RDWR)) == -1) {
-		perror(mtd_device);
-		exit (EXIT_FAILURE);
-	}
-
-	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
-		close(fd);
-		exit (EXIT_FAILURE);
-	}
-
-	/* Set erasesize to specified number of blocks - to match jffs2
-	 * (virtual) block size */
-	meminfo.erasesize *= blockalign;
-
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit (EXIT_FAILURE);
-	}
-
-	if (autoplace) {
-		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-
-		// autoplace ECC ?
-		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-			oobinfochanged = 1;
-		}
-	}
-
-	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
-		if (ret == 0) {
-			oobinfochanged = 2;
-		} else {
-			switch (errno) {
-			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
-				}
-				oobinfochanged = 1;
-				break;
-			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
-			}
-		}
-	}
-
-	/*
-	 * force oob layout for jffs2 or yaffs ?
-	 * Legacy support
-	 */
-	if (forcejffs2 || forceyaffs) {
-		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
-
-		if (autoplace) {
-			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
-			goto restoreoob;
-		}
-		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
-			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
-			goto restoreoob;
-		}
-		if (meminfo.oobsize == 8) {
-			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
-		}
-
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
-			goto restoreoob;
-		}
-	}
-
-	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
-
-	/* Determine if we are reading from standard input or from a file. */
-	if (strcmp(img, standard_input) == 0) {
-		ifd = STDIN_FILENO;
-	} else {
-		ifd = open(img, O_RDONLY);
-	}
-
-	if (ifd == -1) {
-		perror(img);
-		goto restoreoob;
-	}
-
-	/* For now, don't allow writing oob when reading from standard input. */
-	if (ifd == STDIN_FILENO && writeoob) {
-		fprintf(stderr, "Can't write oob when reading from standard input.\n");
-		goto closeall;
-	}
-
-	pagelen = meminfo.writesize + ((writeoob) ? meminfo.oobsize : 0);
-
-	/*
-	 * For the standard input case, the input size is merely an
-	 * invariant placeholder and is set to the write page
-	 * size. Otherwise, just use the input file size.
-	 *
-	 * TODO: Add support for the -l,--length=length option (see
-	 * previous discussion by Tommi Airikka <tommi.airikka@ericsson.com> at
-	 * <http://lists.infradead.org/pipermail/linux-mtd/2008-September/
-	 * 022913.html>
-	 */
-
-	if (ifd == STDIN_FILENO) {
-	    imglen = pagelen;
-	} else {
-	    imglen = lseek(ifd, 0, SEEK_END);
-	    lseek (ifd, 0, SEEK_SET);
-	}
-
-	// Check, if file is page-aligned
-	if ((!pad) && ((imglen % pagelen) != 0)) {
-		fprintf (stderr, "Input file is not page-aligned. Use the padding "
-				 "option.\n");
-		goto closeall;
-	}
-
-	// Check, if length fits into device
-	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
-		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
-				imglen, pagelen, meminfo.writesize, meminfo.size);
-		perror ("Input file does not fit into device");
-		goto closeall;
-	}
-
-	/*
-	 * Get data from input and write to the device while there is
-	 * still input to read and we are still within the device
-	 * bounds. Note that in the case of standard input, the input
-	 * length is simply a quasi-boolean flag whose values are page
-	 * length or zero.
-	 */
-	while (imglen && (mtdoffset < meminfo.size)) {
-		// new eraseblock , check for bad block(s)
-		// Stay in the loop to be sure if the mtdoffset changes because
-		// of a bad block, that the next block that will be written to
-		// is also checked. Thus avoiding errors if the block(s) after the
-		// skipped block(s) is also bad (number of blocks depending on
-		// the blockalign
-		while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) {
-			blockstart = mtdoffset & (~meminfo.erasesize + 1);
-			offs = blockstart;
-			baderaseblock = false;
-			if (!quiet)
-				fprintf (stdout, "Writing data to block %d at offset 0x%x\n",
-						 blockstart / meminfo.erasesize, blockstart);
-
-			/* Check all the blocks in an erase block for bad blocks */
-			do {
-				if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
-					perror("ioctl(MEMGETBADBLOCK)");
-					goto closeall;
-				}
-				if (ret == 1) {
-					baderaseblock = true;
-					if (!quiet)
-						fprintf (stderr, "Bad block at %x, %u block(s) "
-								"from %x will be skipped\n",
-								(int) offs, blockalign, blockstart);
-				}
-
-				if (baderaseblock) {
-					mtdoffset = blockstart + meminfo.erasesize;
-				}
-				offs +=  meminfo.erasesize / blockalign ;
-			} while ( offs < blockstart + meminfo.erasesize );
-
-		}
-
-		readlen = meminfo.writesize;
-
-		if (ifd != STDIN_FILENO) {
-			int tinycnt = 0;
-
-			if (pad && (imglen < readlen))
-			{
-				readlen = imglen;
-				erase_buffer(writebuf + readlen, meminfo.writesize - readlen);
-			}
-
-			/* Read Page Data from input file */
-			while(tinycnt < readlen) {
-				cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
-				if (cnt == 0) { // EOF
-					break;
-				} else if (cnt < 0) {
-					perror ("File I/O error on input file");
-					goto closeall;
-				}
-				tinycnt += cnt;
-			}
-		} else {
-			int tinycnt = 0;
-
-			while(tinycnt < readlen) {
-				cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
-				if (cnt == 0) { // EOF
-					break;
-				} else if (cnt < 0) {
-					perror ("File I/O error on stdin");
-					goto closeall;
-				}
-				tinycnt += cnt;
-			}
-
-			/* No padding needed - we are done */
-			if (tinycnt == 0) {
-				imglen = 0;
-				break;
-			}
-
-			/* No more bytes - we are done after writing the remaining bytes */
-			if (cnt == 0) {
-				imglen = 0;
-			}
-
-			/* Padding */
-			if (pad && (tinycnt < readlen)) {
-				erase_buffer(writebuf + tinycnt, meminfo.writesize - tinycnt);
-			}
-		}
-
-		if (writeoob) {
-			int tinycnt = 0;
-
-			while(tinycnt < readlen) {
-				cnt = read(ifd, oobreadbuf + tinycnt, meminfo.oobsize - tinycnt);
-				if (cnt == 0) { // EOF
-					break;
-				} else if (cnt < 0) {
-					perror ("File I/O error on input file");
-					goto closeall;
-				}
-				tinycnt += cnt;
-			}
-
-			if (!noecc) {
-				int i, start, len;
-				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
-				 * information from the kernel available
-				 *
-				 * Modified to support out of order oobfree segments,
-				 * such as the layout used by diskonchip.c
-				 */
-				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
-						/* Set the reserved bytes to 0xff */
-						start = old_oobinfo.oobfree[i][0];
-						len = old_oobinfo.oobfree[i][1];
-						memcpy(oobbuf + start,
-								oobreadbuf + start,
-								len);
-					}
-				} else {
-					/* Set at least the ecc byte positions to 0xff */
-					start = old_oobinfo.eccbytes;
-					len = meminfo.oobsize - start;
-					memcpy(oobbuf + start,
-							oobreadbuf + start,
-							len);
-				}
-			}
-			/* Write OOB data first, as ecc will be placed in there*/
-			oob.start = mtdoffset;
-			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
-				perror ("ioctl(MEMWRITEOOB)");
-				goto closeall;
-			}
-			imglen -= meminfo.oobsize;
-		}
-
-		/* Write out the Page data */
-		if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) {
-			int rewind_blocks;
-			off_t rewind_bytes;
-			erase_info_t erase;
-
-			perror ("pwrite");
-			/* Must rewind to blockstart if we can */
-			rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */
-			rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen;
-			if (writeoob)
-				rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize;
-			if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) {
-				perror("lseek");
-				fprintf(stderr, "Failed to seek backwards to recover from write error\n");
-				goto closeall;
-			}
-			erase.start = blockstart;
-			erase.length = meminfo.erasesize;
-			fprintf(stderr, "Erasing failed write from %08lx-%08lx\n",
-				(long)erase.start, (long)erase.start+erase.length-1);
-			if (ioctl(fd, MEMERASE, &erase) != 0) {
-				perror("MEMERASE");
-				goto closeall;
-			}
-
-			if (markbad) {
-				loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1);
-				fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr);
-				if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
-					perror("MEMSETBADBLOCK");
-					/* But continue anyway */
-				}
-			}
-			mtdoffset = blockstart + meminfo.erasesize;
-			imglen += rewind_blocks * meminfo.writesize;
-
-			continue;
-		}
-		if (ifd != STDIN_FILENO) {
-			imglen -= readlen;
-		}
-		mtdoffset += meminfo.writesize;
-	}
-
-closeall:
-	close(ifd);
-
-restoreoob:
-	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
-		}
-	}
-
-	close(fd);
-
-	if ((ifd != STDIN_FILENO) && (imglen > 0)) {
-		perror ("Data was only partially written due to error\n");
-		exit (EXIT_FAILURE);
-	}
-
-	/* Return happy */
-	return EXIT_SUCCESS;
-}

+ 0 - 1
target/ag241/TODO

@@ -1 +0,0 @@
-- update with mtd

+ 0 - 1
target/rb532/TODO

@@ -1 +0,0 @@
-- implement cfgfs for NAND/YAFFS2 rootfs