summaryrefslogtreecommitdiff
path: root/ubi-utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils/src')
-rw-r--r--ubi-utils/src/libmtd.c81
-rw-r--r--ubi-utils/src/ubiformat.c12
2 files changed, 88 insertions, 5 deletions
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)