Patchwork [U-Boot] U-boot nand bug, read.part should fail

login
register
mail settings
Submitter Harvey Chapman
Date Feb. 8, 2013, 4:44 p.m.
Message ID <AE2124FA-64A9-49A4-A02A-ECCAB85BBA6F@3gfp.com>
Download mbox | patch
Permalink /patch/219220/
State RFC
Delegated to: Scott Wood
Headers show

Comments

Harvey Chapman - Feb. 8, 2013, 4:44 p.m.
Eh, I shouldn't post code that quickly… Try this:

Patch

diff --git a/common/cmd_nand.c b/common/cmd_nand.c
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -621,60 +621,80 @@  int do_nand(cmd_tbl_t * cmdtp, int flag,
 
 		nand = &nand_info[dev];
 
 		s = strchr(cmd, '.');
 
 		if (s && !strcmp(s, ".raw")) {
 			raw = 1;
 
 			if (arg_off(argv[3], &dev, &off, &size))
 				return 1;
 
 			if (argc > 4 && !str2long(argv[4], &pagecount)) {
 				printf("'%s' is not a number\n", argv[4]);
 				return 1;
 			}
 
 			if (pagecount * nand->writesize > size) {
 				puts("Size exceeds partition or device limit\n");
 				return -1;
 			}
 
 			rwsize = pagecount * (nand->writesize + nand->oobsize);
 		} else {
 			if (arg_off_size(argc - 3, argv + 3, &dev,
 						&off, &size) != 0)
 				return 1;
 
 			rwsize = size;
 		}
 
+                /* If no size was given, it has been calculated for us as
+                 * the remainder of the chip or partition from offset. Adjust
+                 * down for bad blocks, if necessary.
+                 */
+                if (argc < 5) {
+                        nand_info_t *nand = &nand_info[dev];
+                        int size = rwsize;
+                        int maxoffset = off + rwsize;
+                        int offset = off;
+                        int badblocks = 0;
+                        for (offset = off; offset < maxoffset; offset += nand->erasesize)
+                                if (nand_block_isbad(nand, offset))
+                                        badblocks++;
+                        if (badblocks) {
+                                rwsize -= badblocks * nand->erasesize;
+                                printf("size adjusted to 0x%llx (%d bad blocks)\n",
+                                       (unsigned long long)rwsize, badblocks);
+                        }
+                }
+
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i") || !strcmp(s, ".part")) {
 			if (read)
 				ret = nand_read_skip_bad(nand, off, &rwsize,
 							 (u_char *)addr);
 			else
 				ret = nand_write_skip_bad(nand, off, &rwsize,
 							  (u_char *)addr, 0);
 #ifdef CONFIG_CMD_NAND_TRIMFFS
 		} else if (!strcmp(s, ".trimffs")) {
 			if (read) {
 				printf("Unknown nand command suffix '%s'\n", s);
 				return 1;
 			}
 			ret = nand_write_skip_bad(nand, off, &rwsize,
 						(u_char *)addr,
 						WITH_DROP_FFS);
 #endif
 #ifdef CONFIG_CMD_NAND_YAFFS
 		} else if (!strcmp(s, ".yaffs")) {
 			if (read) {
 				printf("Unknown nand command suffix '%s'.\n", s);
 				return 1;
 			}
 			ret = nand_write_skip_bad(nand, off, &rwsize,
 						(u_char *)addr,
 						WITH_INLINE_OOB);
 #endif
 		} else if (!strcmp(s, ".oob")) {
 			/* out-of-band data */