
This change implements the suggestion from an earlier thread for how to handle padding of non-page sized writes to NAND flashes.
See http://lists.denx.de/pipermail/u-boot/2009-February/047795.html for the original discussion. Note that validity of tail page's memory is the reponsibility of the caller.
Signed-off-by: Josh Karabin gkarabin@vocollect.com --- common/cmd_nand.c | 41 +++++++++++++++++++++++++++++++---------- 1 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 1992531..f094101 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -102,9 +102,11 @@ 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, int *plussed) { int idx = nand_curr_device; + char *ps = argv[1]; #if defined(CONFIG_CMD_MTDPARTS) struct mtd_device *dev; struct part_info *part; @@ -119,8 +121,12 @@ 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 (plussed && *ps == '+') { + *plussed = 1; + ps++; + } + if (!(str2long(ps, (ulong *)size))) { + printf("'%s' is not a number\n", ps); return -1; } if (*size > part->size) @@ -145,8 +151,12 @@ 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 (plussed && *ps == '+') { + *plussed = 1; + ps++; + } + if (!(str2long(ps, (ulong *)size))) { + printf("'%s' is not a number\n", ps); return -1; } } else { @@ -317,7 +327,7 @@ 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) + if (arg_off_size(argc - o, argv + o, nand, &off, &size, NULL) != 0) return 1;
memset(&opts, 0, sizeof(opts)); @@ -378,8 +388,18 @@ 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) + if (read && arg_off_size(argc - 3, argv + 3, nand, &off, &size, NULL) != 0) return 1; + else if (!read) { + int plussed = 0; + if (arg_off_size(argc - 3, argv + 3, nand, &off, &size, &plussed) != 0) + return 1; + if (plussed) { + int tailsize = size & (nand->writesize - 1); + memset ((u_char *)addr + size, 0xff, nand->writesize - tailsize); + size += nand->writesize - tailsize; + } + }
s = strchr(cmd, '.'); if (!s || !strcmp(s, ".jffs2") || @@ -457,7 +477,7 @@ 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) + if (arg_off_size(argc - 2, argv + 2, nand, &off, &size, NULL) < 0) return 1;
if (!nand_unlock(nand, off, size)) { @@ -481,9 +501,10 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "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 write - addr off|partition [+]size\n" " read/write 'size' bytes starting at offset 'off'\n" - " to/from memory address 'addr', skipping bad blocks.\n" + " to/from memory address 'addr', skipping bad blocks,\n" + " rounding up to a page size if '+' is specified.\n" "nand erase [clean] [off size] - erase 'size' bytes from\n" " offset 'off' (entire device if not specified)\n" "nand bad - show bad blocks\n"