[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