diff options
-rw-r--r-- | ubi-utils/include/libmtd.h | 19 | ||||
-rw-r--r-- | ubi-utils/src/libmtd.c | 81 | ||||
-rw-r--r-- | ubi-utils/src/ubiformat.c | 12 |
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) |