int i;
u_char *datbuf, *oobbuf, *p;
static loff_t last;
+ int ret = 0;
if (repeat)
off = last + nand->writesize;
last = off;
datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
- oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
- if (!datbuf || !oobbuf) {
+ if (!datbuf) {
puts("No memory for page buffer\n");
return 1;
}
+
+ oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
+ if (!oobbuf) {
+ puts("No memory for page buffer\n");
+ ret = 1;
+ goto free_dat;
+ }
off &= ~(nand->writesize - 1);
loff_t addr = (loff_t) off;
struct mtd_oob_ops ops;
ops.oobbuf = oobbuf;
ops.len = nand->writesize;
ops.ooblen = nand->oobsize;
- ops.mode = MTD_OOB_RAW;
- i = nand->read_oob(nand, addr, &ops);
+ ops.mode = MTD_OPS_RAW;
+ i = mtd_read_oob(nand, addr, &ops);
if (i < 0) {
printf("Error (%d) reading page %08lx\n", i, off);
- free(datbuf);
- free(oobbuf);
- return 1;
+ ret = 1;
+ goto free_all;
}
printf("Page %08lx dump:\n", off);
- i = nand->writesize >> 4;
- p = datbuf;
- while (i--) {
- if (!only_oob)
+ if (!only_oob) {
+ i = nand->writesize >> 4;
+ p = datbuf;
+
+ while (i--) {
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x %02x %02x %02x\n",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
p[8], p[9], p[10], p[11], p[12], p[13], p[14],
p[15]);
- p += 16;
+ p += 16;
+ }
}
+
puts("OOB:\n");
i = nand->oobsize >> 3;
p = oobbuf;
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
p += 8;
}
- free(datbuf);
+
+free_all:
free(oobbuf);
+free_dat:
+ free(datbuf);
- return 0;
+ return ret;
}
/* ------------------------------------------------------------------------- */
.oobbuf = ((u8 *)addr) + nand->writesize,
.len = nand->writesize,
.ooblen = nand->oobsize,
- .mode = MTD_OOB_RAW
+ .mode = MTD_OPS_RAW
};
if (read)
- ret = nand->read_oob(nand, off, &ops);
+ ret = mtd_read_oob(nand, off, &ops);
else
- ret = nand->write_oob(nand, off, &ops);
+ ret = mtd_write_oob(nand, off, &ops);
if (ret) {
printf("%s: error at offset %llx, ret %d\n",
return ret;
}
+/* Adjust a chip/partition size down for bad blocks so we don't
+ * read/write past the end of a chip/partition by accident.
+ */
+static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
+{
+ /* We grab the nand info object here fresh because this is usually
+ * called after arg_off_size() which can change the value of dev.
+ */
+ nand_info_t *nand = &nand_info[dev];
+ loff_t maxoffset = offset + *size;
+ int badblocks = 0;
+
+ /* count badblocks in NAND from offset to offset + size */
+ for (; offset < maxoffset; offset += nand->erasesize) {
+ if (nand_block_isbad(nand, offset))
+ badblocks++;
+ }
+ /* adjust size if any bad blocks found */
+ if (badblocks) {
+ *size -= badblocks * nand->erasesize;
+ printf("size adjusted to 0x%llx (%d bad blocks)\n",
+ (unsigned long long)*size, badblocks);
+ }
+}
+
static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i, ret = 0;
opts.spread = spread;
if (scrub) {
- if (!scrub_yes)
- puts(scrub_warn);
-
- if (scrub_yes)
+ if (scrub_yes) {
opts.scrub = 1;
- else if (getc() == 'y') {
- puts("y");
- if (getc() == '\r')
+ } else {
+ puts(scrub_warn);
+ if (confirm_yesno()) {
opts.scrub = 1;
- else {
+ } else {
puts("scrub aborted\n");
- return -1;
+ return 1;
}
- } else {
- puts("scrub aborted\n");
- return -1;
}
}
ret = nand_erase_opts(nand, &opts);
&off, &size, &maxsize) != 0)
return 1;
+ /* size is unspecified */
+ if (argc < 5)
+ adjust_size_for_badblocks(&size, off, dev);
rwsize = size;
}
mtd_oob_ops_t ops = {
.oobbuf = (u8 *)addr,
.ooblen = rwsize,
- .mode = MTD_OOB_RAW
+ .mode = MTD_OPS_RAW
};
if (read)
- ret = nand->read_oob(nand, off, &ops);
+ ret = mtd_read_oob(nand, off, &ops);
else
- ret = nand->write_oob(nand, off, &ops);
+ ret = mtd_write_oob(nand, off, &ops);
} else if (raw) {
ret = raw_access(nand, addr, off, pagecount, read);
} else {
while (argc > 0) {
addr = simple_strtoul(*argv, NULL, 16);
- if (nand->block_markbad(nand, addr)) {
+ if (mtd_block_markbad(nand, addr)) {
printf("block 0x%08lx NOT marked "
"as bad! ERROR %d\n",
addr, ret);
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
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;