[U-Boot] [PATCH] Add a + prefix form to nand commands.

Josh Karabin gkarabin at vocollect.com
Tue May 19 05:58:45 CEST 2009


Permit the use of a + prefix to sizes in nand commands to extend operations
to multiples of the appropriate page or erase block size.

Signed-off-by: Josh Karabin <gkarabin at vocollect.com>
---
 common/cmd_nand.c |  122 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 99 insertions(+), 23 deletions(-)

diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 1992531..516363e 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -102,14 +102,23 @@ static inline int str2long(char *p, ulong *num)
 }
 
 static int
-arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, size_t *size)
+arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, 
+	size_t *size, size_t *headsize, size_t *tailsize)
 {
 	int idx = nand_curr_device;
+	char *ps = argv[1];
+	size_t max_tailsize;
 #if defined(CONFIG_CMD_MTDPARTS)
 	struct mtd_device *dev;
 	struct part_info *part;
 	u8 pnum;
+#endif
+	max_tailsize = *tailsize;
+
+	if (argc >= 1 && *ps == '+')
+		ps++;
 
+#if defined(CONFIG_CMD_MTDPARTS)
 	if (argc >= 1 && !(str2long(argv[0], off))) {
 		if ((mtdparts_init() == 0) &&
 		    (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
@@ -119,8 +128,8 @@ arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, size_t *size
 			}
 			*off = part->offset;
 			if (argc >= 2) {
-				if (!(str2long(argv[1], (ulong *)size))) {
-					printf("'%s' is not a number\n", argv[1]);
+				if (!(str2long(ps, (ulong *)size))) {
+					printf("'%s' is not a number\n", ps);
 					return -1;
 				}
 				if (*size > part->size)
@@ -145,8 +154,8 @@ arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, size_t *size
 	}
 
 	if (argc >= 2) {
-		if (!(str2long(argv[1], (ulong *)size))) {
-			printf("'%s' is not a number\n", argv[1]);
+		if (!(str2long(ps, (ulong *)size))) {
+			printf("'%s' is not a number\n", ps);
 			return -1;
 		}
 	} else {
@@ -156,6 +165,16 @@ arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, size_t *size
 #if defined(CONFIG_CMD_MTDPARTS)
 out:
 #endif
+	if (ps != argv[1]) {
+		*tailsize = *size & (max_tailsize - 1);
+		*headsize = *size - *tailsize;
+		if (*tailsize)
+			*size = *headsize + max_tailsize;
+	} else {
+		*tailsize = 0;
+		*headsize = *size;
+	}
+
 	printf("device %d ", idx);
 	if (*size == nand->size)
 		puts("whole chip\n");
@@ -229,6 +248,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	int quiet = 0;
 #endif
 	const char *quiet_str = getenv("quiet");
+	size_t tailsize = 0;
+	size_t headsize = 0;
 
 	/* at least two arguments please */
 	if (argc < 2)
@@ -317,12 +338,14 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
 		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
 		/* skip first two or three arguments, look for offset and size */
-		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
+		tailsize = nand->erasesize;
+		if (arg_off_size(argc - o, argv + o, nand, &off, &size,
+					&headsize, &tailsize) != 0)
 			return 1;
 
 		memset(&opts, 0, sizeof(opts));
 		opts.offset = off;
-		opts.length = size;
+		opts.length = headsize;
 		opts.jffs2  = clean;
 		opts.quiet  = quiet;
 
@@ -346,7 +369,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 				return -1;
 			}
 		}
-		ret = nand_erase_opts(nand, &opts);
+
+		if (headsize)
+			ret = nand_erase_opts(nand, &opts);
+		else
+			ret = 0;
+		
+		if (!ret && tailsize) {
+			opts.offset = off + headsize;
+			opts.length = nand->erasesize;
+			ret = nand_erase_opts(nand, &opts);
+		}
+
 		printf("%s\n", ret ? "ERROR" : "OK");
 
 		return ret == 0 ? 0 : 1;
@@ -378,23 +412,52 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 
 		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
 		printf("\nNAND %s: ", read ? "read" : "write");
-		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
+		tailsize = nand->writesize;
+		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size,
+					&headsize, &tailsize) != 0)
 			return 1;
 
 		s = strchr(cmd, '.');
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
 			if (read)
-				ret = nand_read_skip_bad(nand, off, &size,
-							 (u_char *)addr);
-			else
-				ret = nand_write_skip_bad(nand, off, &size,
-							  (u_char *)addr);
+				ret = nand_read_skip_bad(nand, off, &headsize,
+							(u_char *)addr);
+  			else {
+				if (headsize)
+					ret = nand_write_skip_bad(nand, off, 
+								&headsize,
+								(u_char *)addr);
+				else
+					ret = 0;
+				
+				if (!ret && tailsize) {
+					size_t pagesize = nand->writesize;
+					u_char *tailpage;
+					
+					tailpage = malloc(pagesize);
+					if (tailpage) {
+						memcpy(tailpage, 
+							(u_char *)addr + 
+							headsize, tailsize);
+						memset(tailpage + tailsize,
+							  0xff,
+							  pagesize - tailsize);
+						ret = nand_write_skip_bad(
+							nand, 
+							  off + headsize,
+							&pagesize,
+							tailpage);
+					}
+					else
+						ret = 1;
+				}
+			}
 		} else if (!strcmp(s, ".oob")) {
 			/* out-of-band data */
 			mtd_oob_ops_t ops = {
 				.oobbuf = (u8 *)addr,
-				.ooblen = size,
+				.ooblen = size + tailsize,
 				.mode = MTD_OOB_RAW
 			};
 
@@ -457,10 +520,20 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 	}
 
 	if (strcmp(cmd, "unlock") == 0) {
-		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
+		tailsize = nand->erasesize;
+		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size, 
+					&headsize, &tailsize) < 0)
 			return 1;
 
-		if (!nand_unlock(nand, off, size)) {
+		if (headsize)
+			ret = nand_unlock(nand, off, headsize);
+		else
+			ret = 0;
+
+		if (!ret && tailsize)
+			ret = nand_unlock(nand, off+headsize, nand->erasesize);
+
+ 		if (!ret) {
 			puts("NAND flash successfully unlocked\n");
 		} else {
 			puts("Error unlocking NAND flash, "
@@ -480,12 +553,14 @@ U_BOOT_CMD(nand, 5, 1, do_nand,
 	   "NAND sub-system",
 	   "info - show available NAND devices\n"
 	   "nand device [dev] - show or set current device\n"
-	   "nand read - addr off|partition size\n"
-	   "nand write - addr off|partition size\n"
+	   "nand read - addr off|partition [+]size\n"
+	   "nand write - addr off|partition [+]size\n"
 	   "    read/write 'size' bytes starting at offset 'off'\n"
-	   "    to/from memory address 'addr', skipping bad blocks.\n"
-	   "nand erase [clean] [off size] - erase 'size' bytes from\n"
-	   "    offset 'off' (entire device if not specified)\n"
+	   "    to/from memory address 'addr', skipping bad blocks,\n"
+	   "    extending to a page size if '+' is specified.\n"
+	   "nand erase [clean] [off [+]size] - erase 'size' bytes from\n"
+	   "    extending to an erase block if '+' is specified,\n"
+	   "    from offset 'off' (entire device if not specified)\n"
 	   "nand bad - show bad blocks\n"
 	   "nand dump[.oob] off - dump page\n"
 	   "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
@@ -494,7 +569,8 @@ U_BOOT_CMD(nand, 5, 1, do_nand,
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 	   "nand lock [tight] [status]\n"
 	   "    bring nand to lock state or display locked pages\n"
-	   "nand unlock [offset] [size] - unlock section\n"
+	   "nand unlock [offset] [[+]size] - unlock section\n"
+	   "    extending to an erase block if + is specified.\n"
 #endif
 );
 
-- 
1.6.0.4



More information about the U-Boot mailing list