From c4c8cdf621a5d1ea4f0f01ff004c6f1c33be9daa Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 31 Aug 2011 13:00:36 -0700 Subject: mtdutils: move OOB auto-layout into libmtd's mtd_write With the addition of the the new ioctl(MEMWRITE), we can use the kernel's internal OOB autoplacement option. It's a cleaner interface and avoids too much duplication of coding effort. This patch moves any legacy code (using MEMGETOOBSEL) into a legacy function in libmtd.c. It's not exactly a "pre-2.6.30" feature, so I'm not moving it to libmtd_legacy.c. Now, autoplacement features are only activated if we call mtd_write with mode == MTD_OPS_AUTO_OOB. This should fix some discrepancies for nandwrite, where we weren't handling OOB consistently (i.e., we had different functionality when the kernel did/didn't support MEMWRITE). But that also means that we now default to using MTD_OPS_PLACE_OOB instead of AUTO layout. To re-enable autoplacement, we can re-implement the `--autoplace' option that had previously rotted. This patch also cleans up a need for an extra OOB buffer in nandwrite. This has been tested a little in nandsim as well as on SLC NAND flash. Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy --- lib/libmtd.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'lib') diff --git a/lib/libmtd.c b/lib/libmtd.c index d47b307..1b16de5 100644 --- a/lib/libmtd.c +++ b/lib/libmtd.c @@ -1071,6 +1071,42 @@ int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, return 0; } +static int legacy_auto_oob_layout(const struct mtd_dev_info *mtd, int fd, + int ooblen, void *oob) { + struct nand_oobinfo old_oobinfo; + int start, len; + uint8_t *tmp_buf; + + /* Read the current oob info */ + if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo)) + return sys_errmsg("MEMGETOOBSEL failed"); + + tmp_buf = malloc(ooblen); + memcpy(tmp_buf, oob, ooblen); + + /* + * We use autoplacement and have the oobinfo with the autoplacement + * information from the kernel available + */ + if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) { + int i, tags_pos = 0; + for (i = 0; old_oobinfo.oobfree[i][1]; i++) { + /* Set the reserved bytes to 0xff */ + start = old_oobinfo.oobfree[i][0]; + len = old_oobinfo.oobfree[i][1]; + memcpy(oob + start, tmp_buf + tags_pos, len); + tags_pos += len; + } + } else { + /* Set at least the ecc byte positions to 0xff */ + start = old_oobinfo.eccbytes; + len = mtd->oob_size - start; + memcpy(oob + start, tmp_buf + start, len); + } + + return 0; +} + int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, int offs, void *data, int len, void *oob, int ooblen, uint8_t mode) @@ -1120,6 +1156,9 @@ int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, /* Fall back to old methods if necessary */ if (oob) { + if (mode == MTD_OPS_AUTO_OOB) + if (legacy_auto_oob_layout(mtd, fd, ooblen, oob)) + return -1; if (mtd_write_oob(desc, mtd, fd, seek, ooblen, oob) < 0) return sys_errmsg("cannot write to OOB"); } -- cgit v1.2.3