|
@@ -137,7 +137,8 @@ static inline int str2long(const char *p, ulong *num)
|
|
return *p != '\0' && *endptr == '\0';
|
|
return *p != '\0' && *endptr == '\0';
|
|
}
|
|
}
|
|
|
|
|
|
-static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
|
|
|
|
|
|
+static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
|
|
|
|
+ loff_t *maxsize)
|
|
{
|
|
{
|
|
#ifdef CONFIG_CMD_MTDPARTS
|
|
#ifdef CONFIG_CMD_MTDPARTS
|
|
struct mtd_device *dev;
|
|
struct mtd_device *dev;
|
|
@@ -160,6 +161,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
|
|
|
|
|
|
*off = part->offset;
|
|
*off = part->offset;
|
|
*size = part->size;
|
|
*size = part->size;
|
|
|
|
+ *maxsize = part->size;
|
|
*idx = dev->id->num;
|
|
*idx = dev->id->num;
|
|
|
|
|
|
ret = set_dev(*idx);
|
|
ret = set_dev(*idx);
|
|
@@ -173,10 +175,11 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
-static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
|
|
|
|
|
|
+static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
|
|
|
|
+ loff_t *maxsize)
|
|
{
|
|
{
|
|
if (!str2off(arg, off))
|
|
if (!str2off(arg, off))
|
|
- return get_part(arg, idx, off, maxsize);
|
|
|
|
|
|
+ return get_part(arg, idx, off, size, maxsize);
|
|
|
|
|
|
if (*off >= nand_info[*idx].size) {
|
|
if (*off >= nand_info[*idx].size) {
|
|
puts("Offset exceeds device limit\n");
|
|
puts("Offset exceeds device limit\n");
|
|
@@ -184,36 +187,35 @@ static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
|
|
}
|
|
}
|
|
|
|
|
|
*maxsize = nand_info[*idx].size - *off;
|
|
*maxsize = nand_info[*idx].size - *off;
|
|
|
|
+ *size = *maxsize;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int arg_off_size(int argc, char *const argv[], int *idx,
|
|
static int arg_off_size(int argc, char *const argv[], int *idx,
|
|
- loff_t *off, loff_t *size)
|
|
|
|
|
|
+ loff_t *off, loff_t *size, loff_t *maxsize)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
- loff_t maxsize = 0;
|
|
|
|
|
|
|
|
if (argc == 0) {
|
|
if (argc == 0) {
|
|
*off = 0;
|
|
*off = 0;
|
|
*size = nand_info[*idx].size;
|
|
*size = nand_info[*idx].size;
|
|
|
|
+ *maxsize = *size;
|
|
goto print;
|
|
goto print;
|
|
}
|
|
}
|
|
|
|
|
|
- ret = arg_off(argv[0], idx, off, &maxsize);
|
|
|
|
|
|
+ ret = arg_off(argv[0], idx, off, size, maxsize);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- if (argc == 1) {
|
|
|
|
- *size = maxsize;
|
|
|
|
|
|
+ if (argc == 1)
|
|
goto print;
|
|
goto print;
|
|
- }
|
|
|
|
|
|
|
|
if (!str2off(argv[1], size)) {
|
|
if (!str2off(argv[1], size)) {
|
|
printf("'%s' is not a number\n", argv[1]);
|
|
printf("'%s' is not a number\n", argv[1]);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (*size > maxsize) {
|
|
|
|
|
|
+ if (*size > *maxsize) {
|
|
puts("Size exceeds partition or device limit\n");
|
|
puts("Size exceeds partition or device limit\n");
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -307,7 +309,8 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
|
|
if (argc < 3)
|
|
if (argc < 3)
|
|
goto usage;
|
|
goto usage;
|
|
|
|
|
|
- if (arg_off(argv[2], &idx, &addr, &maxsize)) {
|
|
|
|
|
|
+ /* We don't care about size, or maxsize. */
|
|
|
|
+ if (arg_off(argv[2], &idx, &addr, &maxsize, &maxsize)) {
|
|
puts("Offset or partition name expected\n");
|
|
puts("Offset or partition name expected\n");
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -426,7 +429,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
{
|
|
int i, ret = 0;
|
|
int i, ret = 0;
|
|
ulong addr;
|
|
ulong addr;
|
|
- loff_t off, size;
|
|
|
|
|
|
+ loff_t off, size, maxsize;
|
|
char *cmd, *s;
|
|
char *cmd, *s;
|
|
nand_info_t *nand;
|
|
nand_info_t *nand;
|
|
#ifdef CONFIG_SYS_NAND_QUIET
|
|
#ifdef CONFIG_SYS_NAND_QUIET
|
|
@@ -551,7 +554,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
|
|
|
|
printf("\nNAND %s: ", cmd);
|
|
printf("\nNAND %s: ", cmd);
|
|
/* skip first two or three arguments, look for offset and size */
|
|
/* skip first two or three arguments, look for offset and size */
|
|
- if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
|
|
|
|
|
|
+ if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
|
|
|
|
+ &maxsize) != 0)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
nand = &nand_info[dev];
|
|
nand = &nand_info[dev];
|
|
@@ -619,7 +623,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
if (s && !strcmp(s, ".raw")) {
|
|
if (s && !strcmp(s, ".raw")) {
|
|
raw = 1;
|
|
raw = 1;
|
|
|
|
|
|
- if (arg_off(argv[3], &dev, &off, &size))
|
|
|
|
|
|
+ if (arg_off(argv[3], &dev, &off, &size, &maxsize))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
if (argc > 4 && !str2long(argv[4], &pagecount)) {
|
|
if (argc > 4 && !str2long(argv[4], &pagecount)) {
|
|
@@ -635,7 +639,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
rwsize = pagecount * (nand->writesize + nand->oobsize);
|
|
rwsize = pagecount * (nand->writesize + nand->oobsize);
|
|
} else {
|
|
} else {
|
|
if (arg_off_size(argc - 3, argv + 3, &dev,
|
|
if (arg_off_size(argc - 3, argv + 3, &dev,
|
|
- &off, &size) != 0)
|
|
|
|
|
|
+ &off, &size, &maxsize) != 0)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
rwsize = size;
|
|
rwsize = size;
|
|
@@ -645,9 +649,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
!strcmp(s, ".e") || !strcmp(s, ".i")) {
|
|
!strcmp(s, ".e") || !strcmp(s, ".i")) {
|
|
if (read)
|
|
if (read)
|
|
ret = nand_read_skip_bad(nand, off, &rwsize,
|
|
ret = nand_read_skip_bad(nand, off, &rwsize,
|
|
|
|
+ NULL, maxsize,
|
|
(u_char *)addr);
|
|
(u_char *)addr);
|
|
else
|
|
else
|
|
ret = nand_write_skip_bad(nand, off, &rwsize,
|
|
ret = nand_write_skip_bad(nand, off, &rwsize,
|
|
|
|
+ NULL, maxsize,
|
|
(u_char *)addr, 0);
|
|
(u_char *)addr, 0);
|
|
#ifdef CONFIG_CMD_NAND_TRIMFFS
|
|
#ifdef CONFIG_CMD_NAND_TRIMFFS
|
|
} else if (!strcmp(s, ".trimffs")) {
|
|
} else if (!strcmp(s, ".trimffs")) {
|
|
@@ -655,8 +661,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
printf("Unknown nand command suffix '%s'\n", s);
|
|
printf("Unknown nand command suffix '%s'\n", s);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
- ret = nand_write_skip_bad(nand, off, &rwsize,
|
|
|
|
- (u_char *)addr,
|
|
|
|
|
|
+ ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
|
|
|
|
+ maxsize, (u_char *)addr,
|
|
WITH_DROP_FFS);
|
|
WITH_DROP_FFS);
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_CMD_NAND_YAFFS
|
|
#ifdef CONFIG_CMD_NAND_YAFFS
|
|
@@ -665,8 +671,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
printf("Unknown nand command suffix '%s'.\n", s);
|
|
printf("Unknown nand command suffix '%s'.\n", s);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
- ret = nand_write_skip_bad(nand, off, &rwsize,
|
|
|
|
- (u_char *)addr,
|
|
|
|
|
|
+ ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
|
|
|
|
+ maxsize, (u_char *)addr,
|
|
WITH_INLINE_OOB);
|
|
WITH_INLINE_OOB);
|
|
#endif
|
|
#endif
|
|
} else if (!strcmp(s, ".oob")) {
|
|
} else if (!strcmp(s, ".oob")) {
|
|
@@ -775,7 +781,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
if (s && !strcmp(s, ".allexcept"))
|
|
if (s && !strcmp(s, ".allexcept"))
|
|
allexcept = 1;
|
|
allexcept = 1;
|
|
|
|
|
|
- if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
|
|
|
|
|
|
+ if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
|
|
|
|
+ &maxsize) < 0)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
|
|
if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
|
|
@@ -873,7 +880,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
|
|
printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
|
|
printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
|
|
|
|
|
|
cnt = nand->writesize;
|
|
cnt = nand->writesize;
|
|
- r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
|
|
|
|
|
|
+ r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
|
|
|
|
+ (u_char *)addr);
|
|
if (r) {
|
|
if (r) {
|
|
puts("** Read error\n");
|
|
puts("** Read error\n");
|
|
bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
|
|
bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
|
|
@@ -905,7 +913,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
|
|
}
|
|
}
|
|
bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
|
|
bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
|
|
|
|
|
|
- r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr);
|
|
|
|
|
|
+ r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
|
|
|
|
+ (u_char *)addr);
|
|
if (r) {
|
|
if (r) {
|
|
puts("** Read error\n");
|
|
puts("** Read error\n");
|
|
bootstage_error(BOOTSTAGE_ID_NAND_READ);
|
|
bootstage_error(BOOTSTAGE_ID_NAND_READ);
|