aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2011-08-31 13:00:36 -0700
committerArtem Bityutskiy <artem.bityutskiy@intel.com>2011-09-11 16:11:41 +0300
commitc4c8cdf621a5d1ea4f0f01ff004c6f1c33be9daa (patch)
tree7f2c6fe98d2d87bb33105fe79e8043f19c6dfb67
parent040c937ca2c5ae1f35c24a3cc0154e9a31df5933 (diff)
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 <computersforpeace@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
-rw-r--r--lib/libmtd.c39
-rw-r--r--nandwrite.c53
2 files changed, 43 insertions, 49 deletions
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");
}
diff --git a/nandwrite.c b/nandwrite.c
index a78b0b6..920863f 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -233,7 +233,6 @@ int main(int argc, char * const argv[])
/* points to the current page inside filebuf */
unsigned char *writebuf = NULL;
/* points to the OOB for the current page in filebuf */
- unsigned char *oobreadbuf = NULL;
unsigned char *oobbuf = NULL;
libmtd_t mtd_desc;
int ebsize_aligned;
@@ -345,9 +344,6 @@ int main(int argc, char * const argv[])
filebuf = xmalloc(filebuf_max);
erase_buffer(filebuf, filebuf_max);
- oobbuf = xmalloc(mtd.oob_size);
- erase_buffer(oobbuf, mtd.oob_size);
-
/*
* Get data from input and write to the device while there is
* still input to read and we are still within the device
@@ -460,16 +456,16 @@ int main(int argc, char * const argv[])
}
if (writeoob) {
- oobreadbuf = writebuf + mtd.min_io_size;
+ oobbuf = writebuf + mtd.min_io_size;
/* Read more data for the OOB from the input if there isn't enough in the buffer */
- if ((oobreadbuf + mtd.oob_size) > (filebuf + filebuf_len)) {
+ if ((oobbuf + mtd.oob_size) > (filebuf + filebuf_len)) {
int readlen = mtd.oob_size;
- int alreadyread = (filebuf + filebuf_len) - oobreadbuf;
+ int alreadyread = (filebuf + filebuf_len) - oobbuf;
int tinycnt = alreadyread;
while (tinycnt < readlen) {
- cnt = read(ifd, oobreadbuf + tinycnt, readlen - tinycnt);
+ cnt = read(ifd, oobbuf + tinycnt, readlen - tinycnt);
if (cnt == 0) { /* EOF */
break;
} else if (cnt < 0) {
@@ -494,46 +490,6 @@ int main(int argc, char * const argv[])
imglen = 0;
}
}
-
- if (!noecc) {
- int start, len;
- struct nand_oobinfo old_oobinfo;
-
- /* Read the current oob info */
- if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
- perror("MEMGETOOBSEL");
- close(fd);
- exit(EXIT_FAILURE);
- }
-
- /*
- * We use autoplacement and have the oobinfo with the autoplacement
- * information from the kernel available
- *
- * Modified to support out of order oobfree segments,
- * such as the layout used by diskonchip.c
- */
- if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
- int i, tags_pos = 0, tmp_ofs;
- 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];
- tmp_ofs = rawoob ? start : tags_pos;
- memcpy(oobbuf + start, oobreadbuf + tmp_ofs, len);
- tags_pos += len;
- }
- } else {
- /* Set at least the ecc byte positions to 0xff */
- start = old_oobinfo.eccbytes;
- len = mtd.oob_size - start;
- memcpy(oobbuf + start,
- oobreadbuf + start,
- len);
- }
- } else {
- memcpy(oobbuf, oobreadbuf, mtd.oob_size);
- }
}
/* Write out data */
@@ -588,7 +544,6 @@ closeall:
close(ifd);
libmtd_close(mtd_desc);
free(filebuf);
- free(oobbuf);
close(fd);
if (failed