summaryrefslogtreecommitdiff
path: root/ubi-utils/src
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-07-26 15:40:32 +0300
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-07-26 15:40:32 +0300
commit6624ef2ba2e9687929c53fe838910786270cd5c9 (patch)
tree28514674f90840ab2614c728b1d51699db2fdb8d /ubi-utils/src
parent5cf9d3cf66dd32bd5a348e0e9805c5d7a3c34573 (diff)
ubiformat: torture eraseblocks on write errors
When fail to write to PEBs, and the error is EIO, torture the PEB before marking it as bad. Basically, the code is copied from the kernel UBI. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
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)