diff options
Diffstat (limited to 'ubi-utils/src')
| -rw-r--r-- | ubi-utils/src/libmtd.c | 81 | ||||
| -rw-r--r-- | ubi-utils/src/ubiformat.c | 12 | 
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) | 
