Sorry for all of the e-mails while I fumble with git send-email. On Feb 26, 2013, at 12:43 AM, Harvey Chapman <hchap...@3gfp.com> wrote:
> Adjust the sizes calculated for whole partition/chip operations by > removing the size of bad blocks so we don't try to erase/read/write > past a partition/chip boundary. > > Signed-off-by: Harvey Chapman <hchap...@3gfp.com> > --- > common/cmd_nand.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 51 insertions(+) > > diff --git a/common/cmd_nand.c b/common/cmd_nand.c > index 495610c..657ea23 100644 > --- a/common/cmd_nand.c > +++ b/common/cmd_nand.c > @@ -428,6 +428,32 @@ static int raw_access(nand_info_t *nand, ulong addr, > loff_t off, ulong count, > return ret; > } > > +static int 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 original_size = *size; > + 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); > + } > + /* return size adjusted as a positive value so callers > + * can use the return code to determine if anything happened > + */ > + return (original_size - *size); > +} > + > static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) > { > int i, ret = 0; > @@ -524,6 +550,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > int scrub = !strncmp(cmd, "scrub", 5); > int spread = 0; > int args = 2; > + int adjust_size = 0; > const char *scrub_warn = > "Warning: " > "scrub option will erase all factory set bad blocks!\n" > @@ -540,8 +567,10 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > spread = 1; > } else if (!strcmp(&cmd[5], ".part")) { > args = 1; > + adjust_size = 1; > } else if (!strcmp(&cmd[5], ".chip")) { > args = 0; > + adjust_size = 1; > } else { > goto usage; > } > @@ -560,6 +589,15 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0) > return 1; > > + /* The size for erase.part and erase.chip has been calculated > + * for us as the remainder of the chip/partition from offset. > + * Adjust down for bad blocks, if necessary, so we don't > + * erase past the end of the chip/partition by accident. > + */ > + if (adjust_size && !scrub) { > + adjust_size_for_badblocks(&size, off, dev); > + } > + > nand = &nand_info[dev]; > > memset(&opts, 0, sizeof(opts)); > @@ -644,6 +682,19 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, > char * const argv[]) > &off, &size) != 0) > return 1; > > + /* If no size was given, it has been calculated for us > as > + * the remainder of the chip/partition from offset. > Adjust > + * down for bad blocks, if necessary, so we don't > + * read/write past the end of the partition by accident. > + * > + * nand read addr part size "size" is arg 5 > + */ > + if (argc < 5) { > + /* Don't try to use rwsize here, it's not the > + * right type > + */ > + adjust_size_for_badblocks(&size, off, dev); > + } > rwsize = size; > } > > -- > 1.7.10.4 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot