[U-Boot] [PATCH] Add +size syntax to nand commands to pad lengths to page sizes.

Josh Karabin
2009-05-01T20:24:20Z

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@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"
--
1.6.0.6