diff options
author | Dongsheng Yang <yangds.fnst@cn.fujitsu.com> | 2015-10-31 11:12:01 +0800 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2015-11-11 14:38:40 -0800 |
commit | 7d81790ced345585b1e647ca9d0f6678e7062fa4 (patch) | |
tree | 02f61270c7a0fff7bb6b2e28f247a3d2fd6ff490 /nandtest.c | |
parent | 344753f2aacb94d98ce238f81fc4a4b6ef6adea9 (diff) |
mtd-utils: Restructure the mtd-utils source.
* There is no code modification in this commit, only moving
* the files to proper place.
The user tools looks a little messy as we place almost
the all tools in the root directory of mtd-utils. To make
it more clear, I propose to introduce the following structure
for our source code.
mtd-utils/
|-- lib
|-- include
|-- misc-utils
|-- jffsX-utils
|-- nand-utils
|-- nor-utils
|-- ubi-utils
|-- ubifs-utils
`-- tests
Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'nandtest.c')
-rw-r--r-- | nandtest.c | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/nandtest.c b/nandtest.c deleted file mode 100644 index 2ef7cc8..0000000 --- a/nandtest.c +++ /dev/null @@ -1,317 +0,0 @@ -#define PROGRAM_NAME "nandtest" - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <getopt.h> - -#include <asm/types.h> -#include "mtd/mtd-user.h" -#include "common.h" - -void usage(int status) -{ - fprintf(status ? stderr : stdout, - "usage: %s [OPTIONS] <device>\n\n" - " -h, --help Display this help output\n" - " -m, --markbad Mark blocks bad if they appear so\n" - " -s, --seed Supply random seed\n" - " -p, --passes Number of passes\n" - " -r <n>, --reads=<n> Read & check <n> times per pass\n" - " -o, --offset Start offset on flash\n" - " -l, --length Length of flash to test\n" - " -k, --keep Restore existing contents after test\n", - PROGRAM_NAME); - exit(status); -} - -struct mtd_info_user meminfo; -struct mtd_ecc_stats oldstats, newstats; -int fd; -int markbad=0; -int seed; - -int read_and_compare(loff_t ofs, unsigned char *data, unsigned char *rbuf) -{ - ssize_t len; - int i; - - len = pread(fd, rbuf, meminfo.erasesize, ofs); - if (len < meminfo.erasesize) { - printf("\n"); - if (len) - fprintf(stderr, "Short read (%zd bytes)\n", len); - else - perror("read"); - exit(1); - } - - if (ioctl(fd, ECCGETSTATS, &newstats)) { - printf("\n"); - perror("ECCGETSTATS"); - close(fd); - exit(1); - } - - if (newstats.corrected > oldstats.corrected) { - printf("\n %d bit(s) ECC corrected at %08x\n", - newstats.corrected - oldstats.corrected, - (unsigned) ofs); - oldstats.corrected = newstats.corrected; - } - if (newstats.failed > oldstats.failed) { - printf("\nECC failed at %08x\n", (unsigned) ofs); - oldstats.failed = newstats.failed; - } - - printf("\r%08x: checking...", (unsigned)ofs); - fflush(stdout); - - if (memcmp(data, rbuf, meminfo.erasesize)) { - printf("\n"); - fprintf(stderr, "compare failed. seed %d\n", seed); - for (i=0; i<meminfo.erasesize; i++) { - if (data[i] != rbuf[i]) - printf("Byte 0x%x is %02x should be %02x\n", - i, rbuf[i], data[i]); - } - return 1; - } - return 0; -} - -int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf, int nr_reads) -{ - struct erase_info_user er; - ssize_t len; - int i, read_errs = 0; - - printf("\r%08x: erasing... ", (unsigned)ofs); - fflush(stdout); - - er.start = ofs; - er.length = meminfo.erasesize; - - if (ioctl(fd, MEMERASE, &er)) { - perror("MEMERASE"); - if (markbad) { - printf("Mark block bad at %08lx\n", (long)ofs); - ioctl(fd, MEMSETBADBLOCK, &ofs); - } - return 1; - } - - printf("\r%08x: writing...", (unsigned)ofs); - fflush(stdout); - - len = pwrite(fd, data, meminfo.erasesize, ofs); - if (len < 0) { - printf("\n"); - perror("write"); - if (markbad) { - printf("Mark block bad at %08lx\n", (long)ofs); - ioctl(fd, MEMSETBADBLOCK, &ofs); - } - return 1; - } - if (len < meminfo.erasesize) { - printf("\n"); - fprintf(stderr, "Short write (%zd bytes)\n", len); - exit(1); - } - - for (i=1; i<=nr_reads; i++) { - printf("\r%08x: reading (%d of %d)...", (unsigned)ofs, i, nr_reads); - fflush(stdout); - if (read_and_compare(ofs, data, rbuf)) - read_errs++; - } - if (read_errs) { - fprintf(stderr, "read/check %d of %d failed. seed %d\n", read_errs, nr_reads, seed); - return 1; - } - return 0; -} - - -/* - * Main program - */ -int main(int argc, char **argv) -{ - int i; - unsigned char *wbuf, *rbuf, *kbuf; - int pass; - int nr_passes = 1; - int nr_reads = 4; - int keep_contents = 0; - uint32_t offset = 0; - uint32_t length = -1; - int error = 0; - - seed = time(NULL); - - for (;;) { - static const char short_options[] = "hkl:mo:p:r:s:"; - static const struct option long_options[] = { - { "help", no_argument, 0, 'h' }, - { "markbad", no_argument, 0, 'm' }, - { "seed", required_argument, 0, 's' }, - { "passes", required_argument, 0, 'p' }, - { "offset", required_argument, 0, 'o' }, - { "length", required_argument, 0, 'l' }, - { "reads", required_argument, 0, 'r' }, - { "keep", no_argument, 0, 'k' }, - {0, 0, 0, 0}, - }; - int option_index = 0; - int c = getopt_long(argc, argv, short_options, long_options, &option_index); - if (c == EOF) - break; - - switch (c) { - case 'h': - usage(0); - break; - - case '?': - usage(1); - break; - - case 'm': - markbad = 1; - break; - - case 'k': - keep_contents = 1; - break; - - case 's': - seed = atol(optarg); - break; - - case 'p': - nr_passes = atol(optarg); - break; - - case 'r': - nr_reads = atol(optarg); - break; - - case 'o': - offset = simple_strtoul(optarg, &error); - break; - - case 'l': - length = simple_strtoul(optarg, &error); - break; - - } - } - if (argc - optind != 1) - usage(1); - if (error) - errmsg_die("Try --help for more information"); - - fd = open(argv[optind], O_RDWR); - if (fd < 0) { - perror("open"); - exit(1); - } - - if (ioctl(fd, MEMGETINFO, &meminfo)) { - perror("MEMGETINFO"); - close(fd); - exit(1); - } - - if (length == -1) - length = meminfo.size; - - if (offset % meminfo.erasesize) { - fprintf(stderr, "Offset %x not multiple of erase size %x\n", - offset, meminfo.erasesize); - exit(1); - } - if (length % meminfo.erasesize) { - fprintf(stderr, "Length %x not multiple of erase size %x\n", - length, meminfo.erasesize); - exit(1); - } - if (length + offset > meminfo.size) { - fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", - length, offset, meminfo.size); - exit(1); - } - - wbuf = malloc(meminfo.erasesize * 3); - if (!wbuf) { - fprintf(stderr, "Could not allocate %d bytes for buffer\n", - meminfo.erasesize * 2); - exit(1); - } - rbuf = wbuf + meminfo.erasesize; - kbuf = rbuf + meminfo.erasesize; - - if (ioctl(fd, ECCGETSTATS, &oldstats)) { - perror("ECCGETSTATS"); - close(fd); - exit(1); - } - - printf("ECC corrections: %d\n", oldstats.corrected); - printf("ECC failures : %d\n", oldstats.failed); - printf("Bad blocks : %d\n", oldstats.badblocks); - printf("BBT blocks : %d\n", oldstats.bbtblocks); - - srand(seed); - - for (pass = 0; pass < nr_passes; pass++) { - loff_t test_ofs; - - for (test_ofs = offset; test_ofs < offset+length; test_ofs += meminfo.erasesize) { - ssize_t len; - - seed = rand(); - srand(seed); - - if (ioctl(fd, MEMGETBADBLOCK, &test_ofs)) { - printf("\rBad block at 0x%08x\n", (unsigned)test_ofs); - continue; - } - - for (i=0; i<meminfo.erasesize; i++) - wbuf[i] = rand(); - - if (keep_contents) { - printf("\r%08x: reading... ", (unsigned)test_ofs); - fflush(stdout); - - len = pread(fd, kbuf, meminfo.erasesize, test_ofs); - if (len < meminfo.erasesize) { - printf("\n"); - if (len) - fprintf(stderr, "Short read (%zd bytes)\n", len); - else - perror("read"); - exit(1); - } - } - if (erase_and_write(test_ofs, wbuf, rbuf, nr_reads)) - continue; - if (keep_contents) - erase_and_write(test_ofs, kbuf, rbuf, 1); - } - printf("\nFinished pass %d successfully\n", pass+1); - } - /* Return happy */ - return 0; -} |