return 0;
}
-static inline int str2off(const char *p, loff_t *num)
-{
- char *endptr;
-
- *num = simple_strtoull(p, &endptr, 16);
- return *p != '\0' && *endptr == '\0';
-}
-
-static inline int str2long(const char *p, ulong *num)
-{
- char *endptr;
-
- *num = simple_strtoul(p, &endptr, 16);
- return *p != '\0' && *endptr == '\0';
-}
-
-static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
- loff_t *maxsize)
-{
-#ifdef CONFIG_CMD_MTDPARTS
- struct mtd_device *dev;
- struct part_info *part;
- u8 pnum;
- int ret;
-
- ret = mtdparts_init();
- if (ret)
- return ret;
-
- ret = find_dev_and_part(partname, &dev, &pnum, &part);
- if (ret)
- return ret;
-
- if (dev->id->type != MTD_DEV_TYPE_NAND) {
- puts("not a NAND device\n");
- return -1;
- }
-
- *off = part->offset;
- *size = part->size;
- *maxsize = part->size;
- *idx = dev->id->num;
-
- ret = set_dev(*idx);
- if (ret)
- return ret;
-
- return 0;
-#else
- puts("offset is not a number\n");
- return -1;
-#endif
-}
-
-static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
- loff_t *maxsize)
-{
- if (!str2off(arg, off))
- return get_part(arg, idx, off, size, maxsize);
-
- if (*off >= nand_info[*idx].size) {
- puts("Offset exceeds device limit\n");
- return -1;
- }
-
- *maxsize = nand_info[*idx].size - *off;
- *size = *maxsize;
- return 0;
-}
-
-static int arg_off_size(int argc, char *const argv[], int *idx,
- loff_t *off, loff_t *size, loff_t *maxsize)
-{
- int ret;
-
- if (argc == 0) {
- *off = 0;
- *size = nand_info[*idx].size;
- *maxsize = *size;
- goto print;
- }
-
- ret = arg_off(argv[0], idx, off, size, maxsize);
- if (ret)
- return ret;
-
- if (argc == 1)
- goto print;
-
- if (!str2off(argv[1], size)) {
- printf("'%s' is not a number\n", argv[1]);
- return -1;
- }
-
- if (*size > *maxsize) {
- puts("Size exceeds partition or device limit\n");
- return -1;
- }
-
-print:
- printf("device %d ", *idx);
- if (*size == nand_info[*idx].size)
- puts("whole chip\n");
- else
- printf("offset 0x%llx, size 0x%llx\n",
- (unsigned long long)*off, (unsigned long long)*size);
- return 0;
-}
-
#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
static void print_status(ulong start, ulong end, ulong erasesize, int status)
{
goto usage;
/* We don't care about size, or maxsize. */
- if (arg_off(argv[2], &idx, &addr, &maxsize, &maxsize)) {
+ if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
+ MTD_DEV_TYPE_NAND, nand_info[idx].size)) {
+ puts("Offset or partition name expected\n");
+ return 1;
+ }
+ if (set_dev(idx)) {
puts("Offset or partition name expected\n");
return 1;
}
printf("%dx ", chip->numchips);
printf("%s, sector size %u KiB\n",
nand->name, nand->erasesize >> 10);
- printf(" Page size %8d b\n", nand->writesize);
- printf(" OOB size %8d b\n", nand->oobsize);
- printf(" Erase size %8d b\n", nand->erasesize);
+ printf(" Page size %8d b\n", nand->writesize);
+ printf(" OOB size %8d b\n", nand->oobsize);
+ printf(" Erase size %8d b\n", nand->erasesize);
+ printf(" subpagesize %8d b\n", chip->subpagesize);
+ printf(" options 0x%8x\n", chip->options);
+ printf(" bbt options 0x%8x\n", chip->bbt_options);
/* Set geometry info */
setenv_hex("nand_writesize", nand->writesize);
.mode = MTD_OPS_RAW
};
- if (read)
+ if (read) {
ret = mtd_read_oob(nand, off, &ops);
- else
+ } else {
ret = mtd_write_oob(nand, off, &ops);
+ if (!ret)
+ ret = nand_verify_page_oob(nand, &ops, off);
+ }
if (ret) {
printf("%s: error at offset %llx, ret %d\n",
/* Only "dump" is repeatable. */
if (repeat && strcmp(cmd, "dump"))
- return 0;
+ return CMD_RET_FAILURE;
if (strcmp(cmd, "info") == 0) {
if (nand_info[i].name)
nand_print_and_set_info(i);
}
- return 0;
+ return CMD_RET_SUCCESS;
}
if (strcmp(cmd, "device") == 0) {
puts("no devices available\n");
else
nand_print_and_set_info(dev);
- return 0;
+ return CMD_RET_SUCCESS;
}
dev = (int)simple_strtoul(argv[2], NULL, 10);
set_dev(dev);
- return 0;
+ return CMD_RET_SUCCESS;
}
#ifdef CONFIG_ENV_OFFSET_OOB
/* this command operates only on the first nand device */
if (strcmp(cmd, "env.oob") == 0)
- return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
+ return do_nand_env_oob(cmdtp, argc - 1, argv + 1) ?
+ CMD_RET_FAILURE : CMD_RET_SUCCESS;;
#endif
/* The following commands operate on the current device, unless
if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[dev].name) {
puts("\nno devices available\n");
- return 1;
+ return CMD_RET_FAILURE;
}
nand = &nand_info[dev];
for (off = 0; off < nand->size; off += nand->erasesize)
if (nand_block_isbad(nand, off))
printf(" %08llx\n", (unsigned long long)off);
- return 0;
+ return CMD_RET_SUCCESS;
}
/*
printf("\nNAND %s: ", cmd);
/* skip first two or three arguments, look for offset and size */
- if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
- &maxsize) != 0)
- return 1;
+ if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
+ &maxsize, MTD_DEV_TYPE_NAND,
+ nand_info[dev].size) != 0)
+ return CMD_RET_FAILURE;
+
+ if (set_dev(dev))
+ return CMD_RET_FAILURE;
nand = &nand_info[dev];
opts.scrub = 1;
} else {
puts("scrub aborted\n");
- return 1;
+ return CMD_RET_FAILURE;
}
}
}
ret = nand_erase_opts(nand, &opts);
printf("%s\n", ret ? "ERROR" : "OK");
- return ret == 0 ? 0 : 1;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strncmp(cmd, "dump", 4) == 0) {
off = (int)simple_strtoul(argv[2], NULL, 16);
ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
- return ret == 0 ? 1 : 0;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
printf("\nNAND %s: ", read ? "read" : "write");
- nand = &nand_info[dev];
-
s = strchr(cmd, '.');
if (s && !strcmp(s, ".raw")) {
raw = 1;
- if (arg_off(argv[3], &dev, &off, &size, &maxsize))
- return 1;
+ if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
+ MTD_DEV_TYPE_NAND,
+ nand_info[dev].size))
+ return CMD_RET_FAILURE;
+
+ if (set_dev(dev))
+ return CMD_RET_FAILURE;
+
+ nand = &nand_info[dev];
if (argc > 4 && !str2long(argv[4], &pagecount)) {
printf("'%s' is not a number\n", argv[4]);
- return 1;
+ return CMD_RET_FAILURE;
}
if (pagecount * nand->writesize > size) {
puts("Size exceeds partition or device limit\n");
- return -1;
+ return CMD_RET_FAILURE;
}
rwsize = pagecount * (nand->writesize + nand->oobsize);
} else {
- if (arg_off_size(argc - 3, argv + 3, &dev,
- &off, &size, &maxsize) != 0)
- return 1;
+ if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
+ &size, &maxsize,
+ MTD_DEV_TYPE_NAND,
+ nand_info[dev].size) != 0)
+ return CMD_RET_FAILURE;
+
+ if (set_dev(dev))
+ return CMD_RET_FAILURE;
/* size is unspecified */
if (argc < 5)
rwsize = size;
}
+ nand = &nand_info[dev];
+
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
else
ret = nand_write_skip_bad(nand, off, &rwsize,
NULL, maxsize,
- (u_char *)addr, 0);
+ (u_char *)addr,
+ WITH_WR_VERIFY);
#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, NULL,
- maxsize, (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;
+ return CMD_RET_FAILURE;
}
ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
maxsize, (u_char *)addr,
- WITH_YAFFS_OOB);
+ WITH_DROP_FFS | WITH_WR_VERIFY);
#endif
} else if (!strcmp(s, ".oob")) {
/* out-of-band data */
ret = raw_access(nand, addr, off, pagecount, read);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
- return 1;
+ return CMD_RET_FAILURE;
}
printf(" %zu bytes %s: %s\n", rwsize,
read ? "read" : "written", ret ? "ERROR" : "OK");
- return ret == 0 ? 0 : 1;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
#ifdef CONFIG_CMD_NAND_TORTURE
if (!str2off(argv[2], &off)) {
puts("Offset is not a valid number\n");
- return 1;
+ return CMD_RET_FAILURE;
}
printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
ret = nand_torture(nand, off);
printf(" %s\n", ret ? "Failed" : "Passed");
- return ret == 0 ? 0 : 1;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
#endif
--argc;
++argv;
}
- return ret;
+ return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
if (strcmp(cmd, "biterr") == 0) {
/* todo */
- return 1;
+ return CMD_RET_FAILURE;
}
#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
puts("NAND flash successfully locked\n");
} else {
puts("Error locking NAND flash\n");
- return 1;
+ return CMD_RET_FAILURE;
}
}
- return 0;
+ return CMD_RET_SUCCESS;
}
if (strncmp(cmd, "unlock", 5) == 0) {
if (s && !strcmp(s, ".allexcept"))
allexcept = 1;
- if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
- &maxsize) < 0)
- return 1;
+ if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
+ &maxsize, MTD_DEV_TYPE_NAND,
+ nand_info[dev].size) < 0)
+ return CMD_RET_FAILURE;
+
+ if (set_dev(dev))
+ return CMD_RET_FAILURE;
if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
puts("NAND flash successfully unlocked\n");
} else {
puts("Error unlocking NAND flash, "
"write and erase will probably fail\n");
- return 1;
+ return CMD_RET_FAILURE;
}
- return 0;
+ return CMD_RET_SUCCESS;
}
#endif
" write 'size' bytes starting at offset 'off' from memory address\n"
" 'addr', skipping bad blocks and dropping any pages at the end\n"
" of eraseblocks that contain only 0xFF\n"
-#endif
-#ifdef CONFIG_CMD_NAND_YAFFS
- "nand write.yaffs - addr off|partition size\n"
- " write 'size' bytes starting at offset 'off' with yaffs format\n"
- " from memory address 'addr', skipping bad blocks.\n"
#endif
"nand erase[.spread] [clean] off size - erase 'size' bytes "
"from offset 'off'\n"
int r;
char *s;
size_t cnt;
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
image_header_t *hdr;
+#endif
#if defined(CONFIG_FIT)
const void *fit_hdr = NULL;
#endif
(strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
printf("Unknown nand load suffix '%s'\n", s);
bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
- return 1;
+ return CMD_RET_FAILURE;
}
printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
switch (genimg_get_format ((void *)addr)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
hdr = (image_header_t *)addr;
cnt = image_get_image_size (hdr);
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
fit_hdr = (const void *)addr;
default:
bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
puts ("** Unknown image type\n");
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_READ);
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_READ);
if (!fit_check_format (fit_hdr)) {
bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
puts ("** Bad FIT image format\n");
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
fit_print_contents (fit_hdr);
load_addr = addr;
- return bootm_maybe_autostart(cmdtp, cmd);
+ if (bootm_maybe_autostart(cmdtp, cmd))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
(find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
if (dev->id->type != MTD_DEV_TYPE_NAND) {
puts("Not a NAND device\n");
- return 1;
+ return CMD_RET_FAILURE;
}
if (argc > 3)
goto usage;
if (!boot_device) {
puts("\n** No boot device **\n");
bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
printf("\n** Device %d not available\n", idx);
bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
- return 1;
+ return CMD_RET_FAILURE;
}
bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);