nanddump.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * nanddump.c
  3. *
  4. * Copyright (C) 2000 David Woodhouse (dwmw2@infradead.org)
  5. * Steven J. Hill (sjhill@realitydiluted.com)
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Overview:
  12. * This utility dumps the contents of raw NAND chips or NAND
  13. * chips contained in DoC devices.
  14. */
  15. #define PROGRAM_NAME "nanddump"
  16. #include <ctype.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <stdbool.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include <getopt.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <asm/types.h>
  29. #include <mtd/mtd-user.h>
  30. #include "common.h"
  31. #include <libmtd.h>
  32. static void display_help(int status)
  33. {
  34. fprintf(status == EXIT_SUCCESS ? stdout : stderr,
  35. "Usage: %s [OPTIONS] MTD-device\n"
  36. "Dumps the contents of a nand mtd partition.\n"
  37. "\n"
  38. "-h --help Display this help and exit\n"
  39. " --version Output version information and exit\n"
  40. " --bb=METHOD Choose bad block handling method (see below).\n"
  41. "-a --forcebinary Force printing of binary data to tty\n"
  42. "-c --canonicalprint Print canonical Hex+ASCII dump\n"
  43. "-f file --file=file Dump to file\n"
  44. "-l length --length=length Length\n"
  45. "-n --noecc Read without error correction\n"
  46. " --omitoob Omit OOB data (default)\n"
  47. "-o --oob Dump OOB data\n"
  48. "-p --prettyprint Print nice (hexdump)\n"
  49. "-q --quiet Don't display progress and status messages\n"
  50. "-s addr --startaddress=addr Start address\n"
  51. " --skip-bad-blocks-to-start\n"
  52. " Skip bad blocks when seeking to the start address\n"
  53. "\n"
  54. "--bb=METHOD, where METHOD can be `padbad', `dumpbad', or `skipbad':\n"
  55. " padbad: dump flash data, substituting 0xFF for any bad blocks\n"
  56. " dumpbad: dump flash data, including any bad blocks\n"
  57. " skipbad: dump good data, completely skipping any bad blocks (default)\n",
  58. PROGRAM_NAME);
  59. exit(status);
  60. }
  61. static void display_version(void)
  62. {
  63. common_print_version();
  64. printf("%1$s comes with NO WARRANTY\n"
  65. "to the extent permitted by law.\n"
  66. "\n"
  67. "You may redistribute copies of %1$s\n"
  68. "under the terms of the GNU General Public Licence.\n"
  69. "See the file `COPYING' for more information.\n",
  70. PROGRAM_NAME);
  71. exit(EXIT_SUCCESS);
  72. }
  73. // Option variables
  74. static bool pretty_print = false; // print nice
  75. static bool noecc = false; // don't error correct
  76. static bool omitoob = true; // omit oob data
  77. static long long start_addr; // start address
  78. static long long length; // dump length
  79. static const char *mtddev; // mtd device name
  80. static const char *dumpfile; // dump file name
  81. static bool quiet = false; // suppress diagnostic output
  82. static bool canonical = false; // print nice + ascii
  83. static bool forcebinary = false; // force printing binary to tty
  84. static bool skip_bad_blocks_to_start = false;
  85. static enum {
  86. padbad, // dump flash data, substituting 0xFF for any bad blocks
  87. dumpbad, // dump flash data, including any bad blocks
  88. skipbad, // dump good data, completely skipping any bad blocks
  89. } bb_method = skipbad;
  90. static void process_options(int argc, char * const argv[])
  91. {
  92. int error = 0;
  93. bool oob_default = true;
  94. for (;;) {
  95. int option_index = 0;
  96. static const char short_options[] = "hs:f:l:opqncaV";
  97. static const struct option long_options[] = {
  98. {"version", no_argument, 0, 'V'},
  99. {"bb", required_argument, 0, 0},
  100. {"omitoob", no_argument, 0, 0},
  101. {"skip-bad-blocks-to-start", no_argument, 0, 0 },
  102. {"help", no_argument, 0, 'h'},
  103. {"forcebinary", no_argument, 0, 'a'},
  104. {"canonicalprint", no_argument, 0, 'c'},
  105. {"file", required_argument, 0, 'f'},
  106. {"oob", no_argument, 0, 'o'},
  107. {"prettyprint", no_argument, 0, 'p'},
  108. {"startaddress", required_argument, 0, 's'},
  109. {"length", required_argument, 0, 'l'},
  110. {"noecc", no_argument, 0, 'n'},
  111. {"quiet", no_argument, 0, 'q'},
  112. {0, 0, 0, 0},
  113. };
  114. int c = getopt_long(argc, argv, short_options,
  115. long_options, &option_index);
  116. if (c == EOF) {
  117. break;
  118. }
  119. switch (c) {
  120. case 0:
  121. switch (option_index) {
  122. case 1:
  123. /* Handle --bb=METHOD */
  124. if (!strcmp(optarg, "padbad"))
  125. bb_method = padbad;
  126. else if (!strcmp(optarg, "dumpbad"))
  127. bb_method = dumpbad;
  128. else if (!strcmp(optarg, "skipbad"))
  129. bb_method = skipbad;
  130. else
  131. error++;
  132. break;
  133. case 2: /* --omitoob */
  134. if (oob_default) {
  135. oob_default = false;
  136. omitoob = true;
  137. } else {
  138. errmsg_die("--oob and --oomitoob are mutually exclusive");
  139. }
  140. break;
  141. case 3: /* --skip-bad-blocks-to-start */
  142. skip_bad_blocks_to_start = true;
  143. break;
  144. }
  145. break;
  146. case 'V':
  147. display_version();
  148. break;
  149. case 's':
  150. start_addr = simple_strtoll(optarg, &error);
  151. break;
  152. case 'f':
  153. free(dumpfile);
  154. dumpfile = xstrdup(optarg);
  155. break;
  156. case 'l':
  157. length = simple_strtoll(optarg, &error);
  158. break;
  159. case 'o':
  160. if (oob_default) {
  161. oob_default = false;
  162. omitoob = false;
  163. } else {
  164. errmsg_die("--oob and --oomitoob are mutually exclusive");
  165. }
  166. break;
  167. case 'a':
  168. forcebinary = true;
  169. break;
  170. case 'c':
  171. canonical = true;
  172. /* fall-through */
  173. case 'p':
  174. pretty_print = true;
  175. break;
  176. case 'q':
  177. quiet = true;
  178. break;
  179. case 'n':
  180. noecc = true;
  181. break;
  182. case 'h':
  183. display_help(EXIT_SUCCESS);
  184. break;
  185. case '?':
  186. error++;
  187. break;
  188. }
  189. }
  190. if (start_addr < 0)
  191. errmsg_die("Can't specify negative offset with option -s: %lld",
  192. start_addr);
  193. if (length < 0)
  194. errmsg_die("Can't specify negative length with option -l: %lld", length);
  195. if (quiet && pretty_print) {
  196. fprintf(stderr, "The quiet and pretty print options are mutually-\n"
  197. "exclusive. Choose one or the other.\n");
  198. exit(EXIT_FAILURE);
  199. }
  200. if (forcebinary && pretty_print) {
  201. fprintf(stderr, "The forcebinary and pretty print options are\n"
  202. "mutually-exclusive. Choose one or the "
  203. "other.\n");
  204. exit(EXIT_FAILURE);
  205. }
  206. if ((argc - optind) != 1 || error)
  207. display_help(EXIT_FAILURE);
  208. mtddev = argv[optind];
  209. }
  210. #define PRETTY_ROW_SIZE 16
  211. #define PRETTY_BUF_LEN 80
  212. /**
  213. * pretty_dump_to_buffer - formats a blob of data to "hex ASCII" in memory
  214. * @buf: data blob to dump
  215. * @len: number of bytes in the @buf
  216. * @linebuf: where to put the converted data
  217. * @linebuflen: total size of @linebuf, including space for terminating NULL
  218. * @pagedump: true - dumping as page format; false - dumping as OOB format
  219. * @ascii: dump ascii formatted data next to hexdump
  220. * @prefix: address to print before line in a page dump, ignored if !pagedump
  221. *
  222. * pretty_dump_to_buffer() works on one "line" of output at a time, i.e.,
  223. * PRETTY_ROW_SIZE bytes of input data converted to hex + ASCII output.
  224. *
  225. * Given a buffer of unsigned char data, pretty_dump_to_buffer() converts the
  226. * input data to a hex/ASCII dump at the supplied memory location. A prefix
  227. * is included based on whether we are dumping page or OOB data. The converted
  228. * output is always NULL-terminated.
  229. *
  230. * e.g.
  231. * pretty_dump_to_buffer(data, data_len, prettybuf, linelen, true,
  232. * false, 256);
  233. * produces:
  234. * 0x00000100: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
  235. * NOTE: This function was adapted from linux kernel, "lib/hexdump.c"
  236. */
  237. static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
  238. char *linebuf, size_t linebuflen, bool pagedump, bool ascii,
  239. unsigned long long prefix)
  240. {
  241. static const char hex_asc[] = "0123456789abcdef";
  242. unsigned char ch;
  243. unsigned int j, lx = 0, ascii_column;
  244. if (pagedump)
  245. lx += sprintf(linebuf, "0x%.8llx: ", prefix);
  246. else
  247. lx += sprintf(linebuf, " OOB Data: ");
  248. if (!len)
  249. goto nil;
  250. if (len > PRETTY_ROW_SIZE) /* limit to one line at a time */
  251. len = PRETTY_ROW_SIZE;
  252. for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
  253. ch = buf[j];
  254. linebuf[lx++] = hex_asc[(ch & 0xf0) >> 4];
  255. linebuf[lx++] = hex_asc[ch & 0x0f];
  256. linebuf[lx++] = ' ';
  257. }
  258. if (j)
  259. lx--;
  260. ascii_column = 3 * PRETTY_ROW_SIZE + 14;
  261. if (!ascii)
  262. goto nil;
  263. /* Spacing between hex and ASCII - ensure at least one space */
  264. lx += sprintf(linebuf + lx, "%*s",
  265. MAX((int)MIN(linebuflen, ascii_column) - 1 - lx, 1),
  266. " ");
  267. linebuf[lx++] = '|';
  268. for (j = 0; (j < len) && (lx + 2) < linebuflen; j++)
  269. linebuf[lx++] = (isascii(buf[j]) && isprint(buf[j])) ? buf[j]
  270. : '.';
  271. linebuf[lx++] = '|';
  272. nil:
  273. linebuf[lx++] = '\n';
  274. linebuf[lx++] = '\0';
  275. }
  276. /**
  277. * ofd_write - writes whole buffer to the file associated with a descriptor
  278. *
  279. * On failure an error (negative number) is returned. Otherwise 0 is returned.
  280. */
  281. static int ofd_write(int ofd, const void *buf, size_t nbyte)
  282. {
  283. const unsigned char *data = buf;
  284. ssize_t bytes;
  285. while (nbyte) {
  286. bytes = write(ofd, data, nbyte);
  287. if (bytes < 0) {
  288. int err = -errno;
  289. sys_errmsg("Unable to write to output");
  290. return err;
  291. }
  292. data += bytes;
  293. nbyte -= bytes;
  294. }
  295. return 0;
  296. }
  297. /*
  298. * Main program
  299. */
  300. int main(int argc, char * const argv[])
  301. {
  302. long long ofs, end_addr = 0;
  303. long long blockstart = 1;
  304. int i, fd, ofd = 0, bs, badblock = 0;
  305. struct mtd_dev_info mtd;
  306. char pretty_buf[PRETTY_BUF_LEN];
  307. int firstblock = 1;
  308. struct mtd_ecc_stats stat1, stat2;
  309. bool eccstats = false;
  310. unsigned char *readbuf = NULL, *oobbuf = NULL;
  311. libmtd_t mtd_desc;
  312. int err;
  313. process_options(argc, argv);
  314. /* Initialize libmtd */
  315. mtd_desc = libmtd_open();
  316. if (!mtd_desc)
  317. return errmsg("can't initialize libmtd");
  318. /* Open MTD device */
  319. if ((fd = open(mtddev, O_RDONLY)) == -1) {
  320. perror(mtddev);
  321. exit(EXIT_FAILURE);
  322. }
  323. /* Fill in MTD device capability structure */
  324. if (mtd_get_dev_info(mtd_desc, mtddev, &mtd) < 0)
  325. return errmsg("mtd_get_dev_info failed");
  326. /* Allocate buffers */
  327. oobbuf = xmalloc(mtd.oob_size);
  328. readbuf = xmalloc(mtd.min_io_size);
  329. if (noecc) {
  330. if (ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW) != 0) {
  331. perror("MTDFILEMODE");
  332. goto closeall;
  333. }
  334. } else {
  335. /* check if we can read ecc stats */
  336. if (!ioctl(fd, ECCGETSTATS, &stat1)) {
  337. eccstats = true;
  338. if (!quiet) {
  339. fprintf(stderr, "ECC failed: %d\n", stat1.failed);
  340. fprintf(stderr, "ECC corrected: %d\n", stat1.corrected);
  341. fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks);
  342. fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks);
  343. }
  344. } else
  345. perror("No ECC status information available");
  346. }
  347. /* Open output file for writing. If file name is "-", write to standard
  348. * output. */
  349. if (!dumpfile) {
  350. ofd = STDOUT_FILENO;
  351. } else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
  352. perror(dumpfile);
  353. goto closeall;
  354. }
  355. if (!pretty_print && !forcebinary && isatty(ofd)) {
  356. fprintf(stderr, "Not printing binary garbage to tty. Use '-a'\n"
  357. "or '--forcebinary' to override.\n");
  358. goto closeall;
  359. }
  360. /* Initialize start/end addresses and block size */
  361. if (start_addr & (mtd.min_io_size - 1)) {
  362. fprintf(stderr, "the start address (-s parameter) is not page-aligned!\n"
  363. "The pagesize of this NAND Flash is 0x%x.\n",
  364. mtd.min_io_size);
  365. goto closeall;
  366. }
  367. if (skip_bad_blocks_to_start) {
  368. long long bbs_offset = 0;
  369. while (bbs_offset < start_addr) {
  370. err = mtd_is_bad(&mtd, fd, bbs_offset / mtd.eb_size);
  371. if (err < 0) {
  372. sys_errmsg("%s: MTD get bad block failed", mtddev);
  373. goto closeall;
  374. } else if (err == 1) {
  375. if (!quiet)
  376. fprintf(stderr, "Bad block at %llx\n", bbs_offset);
  377. start_addr += mtd.eb_size;
  378. }
  379. bbs_offset += mtd.eb_size;
  380. }
  381. }
  382. if (length)
  383. end_addr = start_addr + length;
  384. if (!length || end_addr > mtd.size)
  385. end_addr = mtd.size;
  386. bs = mtd.min_io_size;
  387. /* Print informative message */
  388. if (!quiet) {
  389. fprintf(stderr, "Block size %d, page size %d, OOB size %d\n",
  390. mtd.eb_size, mtd.min_io_size, mtd.oob_size);
  391. fprintf(stderr,
  392. "Dumping data starting at 0x%08llx and ending at 0x%08llx...\n",
  393. start_addr, end_addr);
  394. }
  395. /* Dump the flash contents */
  396. for (ofs = start_addr; ofs < end_addr; ofs += bs) {
  397. /* Check for bad block */
  398. if (bb_method == dumpbad) {
  399. badblock = 0;
  400. } else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
  401. firstblock) {
  402. blockstart = ofs & (~mtd.eb_size + 1);
  403. firstblock = 0;
  404. if ((badblock = mtd_is_bad(&mtd, fd, ofs / mtd.eb_size)) < 0) {
  405. errmsg("libmtd: mtd_is_bad");
  406. goto closeall;
  407. }
  408. }
  409. if (badblock) {
  410. /* skip bad block, increase end_addr */
  411. if (bb_method == skipbad) {
  412. end_addr += mtd.eb_size;
  413. ofs += mtd.eb_size - bs;
  414. if (end_addr > mtd.size)
  415. end_addr = mtd.size;
  416. continue;
  417. }
  418. memset(readbuf, 0xff, bs);
  419. } else {
  420. /* Read page data and exit on failure */
  421. if (mtd_read(&mtd, fd, ofs / mtd.eb_size, ofs % mtd.eb_size, readbuf, bs)) {
  422. errmsg("mtd_read");
  423. goto closeall;
  424. }
  425. }
  426. /* ECC stats available ? */
  427. if (eccstats) {
  428. if (ioctl(fd, ECCGETSTATS, &stat2)) {
  429. perror("ioctl(ECCGETSTATS)");
  430. goto closeall;
  431. }
  432. if (stat1.failed != stat2.failed)
  433. fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
  434. " at offset 0x%08llx\n",
  435. stat2.failed - stat1.failed, ofs);
  436. if (stat1.corrected != stat2.corrected)
  437. fprintf(stderr, "ECC: %d corrected bitflip(s) at"
  438. " offset 0x%08llx\n",
  439. stat2.corrected - stat1.corrected, ofs);
  440. stat1 = stat2;
  441. }
  442. /* Write out page data */
  443. if (pretty_print) {
  444. for (i = 0; i < bs; i += PRETTY_ROW_SIZE) {
  445. pretty_dump_to_buffer(readbuf + i, PRETTY_ROW_SIZE,
  446. pretty_buf, PRETTY_BUF_LEN, true, canonical, ofs + i);
  447. err = ofd_write(ofd, pretty_buf, strlen(pretty_buf));
  448. if (err)
  449. goto closeall;
  450. }
  451. } else {
  452. /* Write requested length if oob is omitted */
  453. size_t size_left = end_addr - ofs;
  454. if (omitoob && (size_left < bs))
  455. err = ofd_write(ofd, readbuf, size_left);
  456. else
  457. err = ofd_write(ofd, readbuf, bs);
  458. if (err)
  459. goto closeall;
  460. }
  461. if (omitoob)
  462. continue;
  463. if (badblock) {
  464. memset(oobbuf, 0xff, mtd.oob_size);
  465. } else {
  466. /* Read OOB data and exit on failure */
  467. if (mtd_read_oob(mtd_desc, &mtd, fd, ofs, mtd.oob_size, oobbuf)) {
  468. errmsg("libmtd: mtd_read_oob");
  469. goto closeall;
  470. }
  471. }
  472. /* Write out OOB data */
  473. if (pretty_print) {
  474. for (i = 0; i < mtd.oob_size; i += PRETTY_ROW_SIZE) {
  475. pretty_dump_to_buffer(oobbuf + i, mtd.oob_size - i,
  476. pretty_buf, PRETTY_BUF_LEN, false, canonical, 0);
  477. err = ofd_write(ofd, pretty_buf, strlen(pretty_buf));
  478. if (err)
  479. goto closeall;
  480. }
  481. } else {
  482. err = ofd_write(ofd, oobbuf, mtd.oob_size);
  483. if (err)
  484. goto closeall;
  485. }
  486. }
  487. /* Close the output file and MTD device, free memory */
  488. close(fd);
  489. close(ofd);
  490. free(oobbuf);
  491. free(readbuf);
  492. /* Exit happy */
  493. return EXIT_SUCCESS;
  494. closeall:
  495. close(fd);
  496. if (ofd > 0 && ofd != STDOUT_FILENO)
  497. close(ofd);
  498. free(oobbuf);
  499. free(readbuf);
  500. exit(EXIT_FAILURE);
  501. }