/* * Main program */ int main(int argc, char **argv) { int i; unsigned char *wbuf, *rbuf, *kbuf; int pass; int nr_passes = 1; int keep_contents = 0; uint32_t offset = 0; uint32_t length = -1; char *mtd_dev = "/dev/mtd10", data_str[20]; int data = -1; seed = time(NULL); for (;;) { static const char *short_options="hkl:mo:p:s:d:"; 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' }, { "keep", no_argument, 0, 'k' }, { "data", required_argument, 0, 'd' }, {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': case '?': usage(); 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 'o': offset = strtol(optarg, NULL, 0); break; case 'l': length = strtol(optarg, NULL, 0); break; case 'd': data = (int)strtol(optarg, NULL, 0) & 0xFF; sprintf(data_str, "0x%02X", data); break; } } #if defined(RTAC55U) if (argc - optind == 1) mtd_dev = argv[optind]; #else if (argc - optind != 1) usage(); mtd_dev = argv[optind]; #endif fd = open(mtd_dev, O_RDWR); if (fd < 0) { perror("open"); exit(1); } if (ioctl(fd, MEMGETINFO, &meminfo)) { perror("MEMGETINFO"); close(fd); exit(1); } if (length == -1) { #if defined(RTAC55U) if (!strcmp(mtd_dev, "/dev/mtd10") && !offset) { /* skip first block of /dev/mtd10 for RT-AC55U. */ offset = meminfo.erasesize; length = meminfo.size - offset; } else { length = meminfo.size; } #else length = meminfo.size; #endif } 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); } if (!offset) { char c; fprintf(stderr, "Offset = 0. Start test (Y/N)?"); c = getchar(); if (c != 'y' && c != 'Y') exit(1); } printf("MTD device : %s\n", mtd_dev); 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); printf("Pattern : %s\n", (data >= 0 && data <= 0xFF)? data_str:"random"); printf("Start offset : %08x\n", offset); printf("Length : %08x\n", length); 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; } if (data >= 0 && data <= 0xFF) { memset(wbuf, data, meminfo.erasesize); } else { 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)) continue; if (keep_contents) erase_and_write(test_ofs, kbuf, rbuf); } printf("\nFinished pass %d successfully\n", pass+1); } /* Return happy */ return 0; }
/* Main program. */ static int do_nandtest(int argc, char *argv[]) { int opt, do_nandtest_dev = -1, ret = -1; loff_t flash_offset = 0, test_ofs, length = 0; unsigned int nr_iterations = 1, iter; unsigned char *wbuf, *rbuf; ecc_failed_cnt = 0; ecc_stats_over = 0; markbad = 0; fd = -1; memset(ecc_stats, 0, sizeof(*ecc_stats)); while ((opt = getopt(argc, argv, "ms:i:o:l:t")) > 0) { switch (opt) { case 'm': markbad = 1; break; case 's': seed = simple_strtoul(optarg, NULL, 0); break; case 'i': nr_iterations = simple_strtoul(optarg, NULL, 0); break; case 'o': flash_offset = simple_strtoul(optarg, NULL, 0); break; case 'l': length = simple_strtoul(optarg, NULL, 0); break; case 't': do_nandtest_dev = 1; break; default: return COMMAND_ERROR_USAGE; } } /* Check if no device is given */ if (optind >= argc) return COMMAND_ERROR_USAGE; if (do_nandtest_dev == -1) { printf("Please add -t parameter to start nandtest.\n"); return 0; } printf("Open device %s\n", argv[optind]); fd = open(argv[optind], O_RDWR); if (fd < 0) { perror("open"); return COMMAND_ERROR_USAGE; } /* Getting flash information. */ ret = ioctl(fd, MEMGETINFO, &meminfo); if (ret < 0) { perror("MEMGETINFO"); goto err; } ret = ioctl(fd, MEMGETREGIONINFO, &memregion); if (ret < 0) { perror("MEMGETREGIONINFO"); goto err; } ret = ioctl(fd, ECCGETSTATS, &oldstats); if (ret < 0) { perror("ECCGETSTATS"); goto err; } if (!length) { length = meminfo.size; length -= flash_offset; } printf("Flash offset: 0x%08llx\n", flash_offset + memregion.offset); printf("Length: 0x%08llx\n", length); printf("End address: 0x%08llx\n", flash_offset + length + memregion.offset); printf("Erasesize: 0x%08x\n", meminfo.erasesize); printf("Starting nandtest...\n"); if (!IS_ALIGNED(meminfo.erasesize, meminfo.writesize)) { printf("Erasesize 0x%08x is not a multiple " "of writesize 0x%08x.\n" "Please check driver implementation\n", meminfo.erasesize, meminfo.writesize); goto err; } if (!IS_ALIGNED(flash_offset, meminfo.erasesize)) { printf("Offset 0x%08llx not multiple of erase size 0x%08x\n", flash_offset, meminfo.erasesize); goto err; } if (!IS_ALIGNED(length, meminfo.erasesize)) { printf("Length 0x%08llx not multiple of erase size 0x%08x\n", length, meminfo.erasesize); goto err; } if (length + flash_offset > meminfo.size) { printf("Length 0x%08llx + offset 0x%08llx exceeds " "device size 0x%08llx\n", length, flash_offset, meminfo.size); goto err; } wbuf = malloc(meminfo.erasesize * 2); if (!wbuf) { printf("Could not allocate %d bytes for buffer\n", meminfo.erasesize * 2); goto err; } rbuf = wbuf + meminfo.erasesize; for (iter = 0; iter < nr_iterations; iter++) { init_progression_bar(length); for (test_ofs = 0; test_ofs < length; test_ofs += meminfo.erasesize) { show_progress(test_ofs); srand(seed); seed = rand(); if (ioctl(fd, MEMGETBADBLOCK, &test_ofs)) { printf("\nBad block at 0x%08llx\n", test_ofs + memregion.offset); init_progression_bar(length); show_progress(test_ofs); continue; } get_random_bytes(wbuf, meminfo.erasesize); ret = erase_and_write(test_ofs, wbuf, rbuf, length); if (ret < 0) goto err2; } show_progress(test_ofs); printf("\nFinished pass %d successfully\n", iter + 1); } print_stats(nr_iterations, length); ret = close(fd); if (ret < 0) { perror("close"); goto err2; } free(wbuf); return 0; err2: free(wbuf); err: printf("Error occurred.\n"); close(fd); return 1; }
/* Main program. */ static int do_nandtest(int argc, char *argv[]) { int opt, length = -1, do_nandtest_dev = -1; off_t flash_offset = 0; off_t test_ofs; unsigned int nr_passes = 1, pass; int i; int ret = -1; unsigned char *wbuf, *rbuf; ecc_failed_cnt = 0; ecc_stats_over = 0; markbad = 0; fd = -1; memset(ecc_stats, 0, MAX_ECC_BITS); while ((opt = getopt(argc, argv, "ms:p:o:l:t")) > 0) { switch (opt) { case 'm': markbad = 1; break; case 's': seed = simple_strtoul(optarg, NULL, 0); break; case 'p': nr_passes = simple_strtoul(optarg, NULL, 0); break; case 'o': flash_offset = simple_strtoul(optarg, NULL, 0); break; case 'l': length = simple_strtoul(optarg, NULL, 0); break; case 't': do_nandtest_dev = 1; break; default: return COMMAND_ERROR_USAGE; } } /* Check if no device is given */ if (optind >= argc) return COMMAND_ERROR_USAGE; if (do_nandtest_dev == -1) { printf("Please add -t parameter to start nandtest.\n"); return 0; } printf("Open device %s\n", argv[optind]); fd = open(argv[optind], O_RDWR); if (fd < 0) { perror("open"); return COMMAND_ERROR_USAGE; } /* Getting flash information. */ ret = ioctl(fd, MEMGETINFO, &meminfo); if (ret < 0) { perror("MEMGETINFO"); goto err; } ret = ioctl(fd, MEMGETREGIONINFO, &memregion); if (ret < 0) { perror("MEMGETREGIONINFO"); goto err; } ret = ioctl(fd, ECCGETSTATS, &oldstats); if (ret < 0) { perror("ECCGETSTATS"); goto err; } if (length == -1) { length = meminfo.size; length -= flash_offset; } printf("Flash offset: 0x%08x\n", (unsigned)(flash_offset+memregion.offset)); printf("Length: 0x%08x\n", (unsigned)length); printf("End address: 0x%08x\n", (unsigned)(flash_offset+length+memregion.offset)); printf("Erasesize: 0x%08x\n", (unsigned)(meminfo.erasesize)); printf("Starting nandtest...\n"); if (flash_offset % meminfo.erasesize) { printf("Offset 0x%08x not multiple of erase size 0x%08x\n", (unsigned)flash_offset, meminfo.erasesize); goto err; } if (length % meminfo.erasesize) { printf("Length 0x%08x not multiple of erase size 0x%08x\n", length, meminfo.erasesize); goto err; } if (length + flash_offset > meminfo.size) { printf("Length 0x%08x + offset 0x%08x exceeds " "device size 0x%08x\n", length, (unsigned)flash_offset, meminfo.size); goto err; } wbuf = malloc(meminfo.erasesize * 2); if (!wbuf) { printf("Could not allocate %d bytes for buffer\n", meminfo.erasesize * 2); goto err; } rbuf = wbuf + meminfo.erasesize; for (pass = 0; pass < nr_passes; pass++) { for (test_ofs = flash_offset; test_ofs < flash_offset+length; test_ofs += meminfo.erasesize) { srand(seed); seed = rand(); if (ioctl(fd, MEMGETBADBLOCK, (void *)test_ofs)) { printf("\rBad block at 0x%08x\n", (unsigned)(test_ofs + memregion.offset)); continue; } for (i = 0; i < meminfo.erasesize; i++) wbuf[i] = rand(); ret = erase_and_write(test_ofs, wbuf, rbuf); if (ret < 0) goto err2; } printf("\nFinished pass %d successfully\n", pass+1); } print_stats(nr_passes, length); ret = close(fd); if (ret < 0) { perror("close"); goto err2; } free(wbuf); return 0; err2: free(wbuf); err: printf("Error occurred.\n"); close(fd); return 1; }