summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ubi-utils/include/libmtd.h19
-rw-r--r--ubi-utils/src/libmtd.c81
-rw-r--r--ubi-utils/src/ubiformat.c12
3 files changed, 103 insertions, 9 deletions
diff --git a/ubi-utils/include/libmtd.h b/ubi-utils/include/libmtd.h
index 8d5bc4f..c8b44e8 100644
--- a/ubi-utils/include/libmtd.h
+++ b/ubi-utils/include/libmtd.h
@@ -149,6 +149,17 @@ int mtd_get_dev_info1(libmtd_t desc, int dev_num, struct mtd_dev_info *mtd);
int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
/**
+ * mtd_torture - torture an eraseblock.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to torture
+ *
+ * This function tortures eraseblock @eb. Returns %0 in case of success and %-1
+ * in case of failure.
+ */
+int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
* mtd_is_bad - check if eraseblock is bad.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
@@ -160,13 +171,13 @@ int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb);
/**
- * mtd_mark_bad - marks the block as bad.
+ * mtd_mark_bad - mark an eraseblock as bad.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
- * @eb: eraseblock to mark bad
+ * @eb: eraseblock to mark as bad
*
- * This function marks the eraseblock @eb as bad. Returns %0 if success
- * %-1 if failure
+ * This function marks eraseblock @eb as bad. Returns %0 in case of success and
+ * %-1 in case of failure.
*/
int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb);
diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c
index 4f1ef41..249fa23 100644
--- a/ubi-utils/src/libmtd.c
+++ b/ubi-utils/src/libmtd.c
@@ -798,6 +798,87 @@ int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
return ioctl(fd, MEMERASE, &ei);
}
+/* Patterns to write to a physical eraseblock when torturing it */
+static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
+
+/**
+ * check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+static int check_pattern(const void *buf, uint8_t patt, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (((const uint8_t *)buf)[i] != patt)
+ return 0;
+ return 1;
+}
+
+int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+ int err, i, patt_count;
+ void *buf;
+
+ normsg("run torture test for PEB %d", eb);
+ patt_count = ARRAY_SIZE(patterns);
+
+ buf = malloc(mtd->eb_size);
+ if (!buf) {
+ errmsg("cannot allocate %d bytes of memory", mtd->eb_size);
+ return -1;
+ }
+
+ for (i = 0; i < patt_count; i++) {
+ err = mtd_erase(mtd, fd, eb);
+ if (err)
+ goto out;
+
+ /* Make sure the PEB contains only 0xFF bytes */
+ err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
+ if (err)
+ goto out;
+
+ err = check_pattern(buf, 0xFF, mtd->eb_size);
+ if (err == 0) {
+ errmsg("erased PEB %d, but a non-0xFF byte found", eb);
+ errno = EIO;
+ goto out;
+ }
+
+ /* Write a pattern and check it */
+ memset(buf, patterns[i], mtd->eb_size);
+ err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size);
+ if (err)
+ goto out;
+
+ memset(buf, ~patterns[i], mtd->eb_size);
+ err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
+ if (err)
+ goto out;
+
+ err = check_pattern(buf, patterns[i], mtd->eb_size);
+ if (err == 0) {
+ errmsg("pattern %x checking failed for PEB %d",
+ patterns[i], eb);
+ errno = EIO;
+ goto out;
+ }
+ }
+
+ err = 0;
+ normsg("PEB %d passed torture test, do not mark it a bad", eb);
+
+out:
+ free(buf);
+ return -1;
+}
+
int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb)
{
int ret;
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c
index 2a62f3b..c15500b 100644
--- a/ubi-utils/src/ubiformat.c
+++ b/ubi-utils/src/ubiformat.c
@@ -530,12 +530,14 @@ static int flash_image(const struct mtd_dev_info *mtd, struct ubi_scan_info *si)
if (errno != EIO)
goto out_close;
- if (mark_bad(mtd, si, eb)) {
- normsg("operation incomplete");
- goto out_close;
+ err = mtd_torture(mtd, args.node_fd, eb);
+ if (err) {
+ if (mark_bad(mtd, si, eb)) {
+ normsg("operation incomplete");
+ goto out_close;
+ }
+ divisor += 1;
}
-
- divisor += 1;
continue;
}
if (++written_ebs >= img_ebs)