From mboxrd@z Thu Jan 1 00:00:00 1970 From: Heiko Schocher Date: Wed, 11 Feb 2015 07:45:17 +0100 Subject: [U-Boot] [PATCH 1/5] nand: Add verification functions In-Reply-To: <1422986296-26086-1-git-send-email-ptyser@xes-inc.com> References: <1422986296-26086-1-git-send-email-ptyser@xes-inc.com> Message-ID: <54DAFA7D.5030505@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello Peter, Am 03.02.2015 18:58, schrieb Peter Tyser: > Add nand_verify() and nand_verify_page_oob(). nand_verify() verifies > NAND contents against an arbitrarily sized buffer using ECC while > nand_verify_page_oob() verifies a NAND page's contents and OOB. > > Signed-off-by: Peter Tyser > --- > > drivers/mtd/nand/nand_util.c | 97 +++++++++++++++++++++++++++++++++++++++++++- > include/nand.h | 4 ++ > 2 files changed, 100 insertions(+), 1 deletion(-) Tested on the am335x based dxr2 board with writing a ubifs image into a nand mtd partition. Tested-by: Heiko Schocher Acked-by: Heiko Schocher bye, Heiko > > diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c > index afdd160..f487756 100644 > --- a/drivers/mtd/nand/nand_util.c > +++ b/drivers/mtd/nand/nand_util.c > @@ -464,6 +464,87 @@ static size_t drop_ffs(const nand_info_t *nand, const u_char *buf, > #endif > > /** > + * nand_verify_page_oob: > + * > + * Verify a page of NAND flash, including the OOB. > + * Reads page of NAND and verifies the contents and OOB against the > + * values in ops. > + * > + * @param nand NAND device > + * @param ops MTD operations, including data to verify > + * @param ofs offset in flash > + * @return 0 in case of success > + */ > +int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs) > +{ > + int rval; > + struct mtd_oob_ops vops; > + size_t verlen = nand->writesize + nand->oobsize; > + > + memcpy(&vops, ops, sizeof(vops)); > + > + vops.datbuf = malloc(verlen); > + > + if (!vops.datbuf) > + return -ENOMEM; > + > + vops.oobbuf = vops.datbuf + nand->writesize; > + > + rval = mtd_read_oob(nand, ofs, &vops); > + if (!rval) > + rval = memcmp(ops->datbuf, vops.datbuf, vops.len); > + if (!rval) > + rval = memcmp(ops->oobbuf, vops.oobbuf, vops.ooblen); > + > + free(vops.datbuf); > + > + return rval ? -EIO : 0; > +} > + > +/** > + * nand_verify: > + * > + * Verify a region of NAND flash. > + * Reads NAND in page-sized chunks and verifies the contents against > + * the contents of a buffer. The offset into the NAND must be > + * page-aligned, and the function doesn't handle skipping bad blocks. > + * > + * @param nand NAND device > + * @param ofs offset in flash > + * @param len buffer length > + * @param buf buffer to read from > + * @return 0 in case of success > + */ > +int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf) > +{ > + int rval = 0; > + size_t verofs; > + size_t verlen = nand->writesize; > + uint8_t *verbuf = malloc(verlen); > + > + if (!verbuf) > + return -ENOMEM; > + > + /* Read the NAND back in page-size groups to limit malloc size */ > + for (verofs = ofs; verofs < ofs + len; > + verofs += verlen, buf += verlen) { > + verlen = min(nand->writesize, (uint32_t)(ofs + len - verofs)); > + rval = nand_read(nand, verofs, &verlen, verbuf); > + if (!rval || (rval == -EUCLEAN)) > + rval = memcmp(buf, verbuf, verlen); > + > + if (rval) > + break; > + } > + > + free(verbuf); > + > + return rval ? -EIO : 0; > +} > + > + > + > +/** > * nand_write_skip_bad: > * > * Write image to NAND flash. > @@ -501,7 +582,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > > #ifdef CONFIG_CMD_NAND_YAFFS > if (flags & WITH_YAFFS_OOB) { > - if (flags & ~WITH_YAFFS_OOB) > + if (flags & (~WITH_YAFFS_OOB & ~WITH_WR_VERIFY)) > return -EINVAL; > > int pages; > @@ -554,6 +635,10 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > > if (!need_skip && !(flags & WITH_DROP_FFS)) { > rval = nand_write(nand, offset, length, buffer); > + > + if ((flags & WITH_WR_VERIFY) && !rval) > + rval = nand_verify(nand, offset, *length, buffer); > + > if (rval == 0) > return 0; > > @@ -601,6 +686,11 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > ops.oobbuf = ops.datbuf + pagesize; > > rval = mtd_write_oob(nand, offset, &ops); > + > + if ((flags & WITH_WR_VERIFY) && !rval) > + rval = nand_verify_page_oob(nand, > + &ops, offset); > + > if (rval != 0) > break; > > @@ -620,6 +710,11 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > > rval = nand_write(nand, offset, &truncated_write_size, > p_buffer); > + > + if ((flags & WITH_WR_VERIFY) && !rval) > + rval = nand_verify(nand, offset, > + truncated_write_size, p_buffer); > + > offset += write_size; > p_buffer += write_size; > } > diff --git a/include/nand.h b/include/nand.h > index 15e31ab..49a05dc 100644 > --- a/include/nand.h > +++ b/include/nand.h > @@ -134,11 +134,15 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > * is a 'mode' meaning it cannot be mixed with > * other flags */ > #define WITH_DROP_FFS (1 << 1) /* drop trailing all-0xff pages */ > +#define WITH_WR_VERIFY (1 << 2) /* verify data was written correctly */ > > int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, > size_t *actual, loff_t lim, u_char *buffer, int flags); > int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts); > int nand_torture(nand_info_t *nand, loff_t offset); > +int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, > + loff_t ofs); > +int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf); > > #define NAND_LOCK_STATUS_TIGHT 0x01 > #define NAND_LOCK_STATUS_UNLOCK 0x04 > -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany