nanddump.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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 _GNU_SOURCE
  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. #define PROGRAM "nanddump"
  31. #define VERSION "$Revision: 1.29 $"
  32. static struct nand_oobinfo none_oobinfo = {
  33. .useecc = MTD_NANDECC_OFF,
  34. };
  35. static void display_help (void)
  36. {
  37. printf(
  38. "Usage: nanddump [OPTIONS] MTD-device\n"
  39. "Dumps the contents of a nand mtd partition.\n"
  40. "\n"
  41. " --help Display this help and exit\n"
  42. " --version Output version information and exit\n"
  43. "-f file --file=file Dump to file\n"
  44. "-i --ignoreerrors Ignore errors\n"
  45. "-l length --length=length Length\n"
  46. "-n --noecc Read without error correction\n"
  47. "-o --omitoob Omit oob data\n"
  48. "-b --omitbad Omit bad blocks from the dump\n"
  49. "-p --prettyprint Print nice (hexdump)\n"
  50. "-q --quiet Don't display progress and status messages\n"
  51. "-s addr --startaddress=addr Start address\n"
  52. );
  53. exit(EXIT_SUCCESS);
  54. }
  55. static void display_version (void)
  56. {
  57. printf(PROGRAM " " VERSION "\n"
  58. "\n"
  59. PROGRAM " comes with NO WARRANTY\n"
  60. "to the extent permitted by law.\n"
  61. "\n"
  62. "You may redistribute copies of " PROGRAM "\n"
  63. "under the terms of the GNU General Public Licence.\n"
  64. "See the file `COPYING' for more information.\n");
  65. exit(EXIT_SUCCESS);
  66. }
  67. // Option variables
  68. static bool ignoreerrors = false; // ignore errors
  69. static bool pretty_print = false; // print nice in ascii
  70. static bool noecc = false; // don't error correct
  71. static bool omitoob = false; // omit oob data
  72. static unsigned long start_addr; // start address
  73. static unsigned long length; // dump length
  74. static const char *mtddev; // mtd device name
  75. static const char *dumpfile; // dump file name
  76. static bool omitbad = false;
  77. static bool quiet = false; // suppress diagnostic output
  78. static void process_options (int argc, char * const argv[])
  79. {
  80. int error = 0;
  81. for (;;) {
  82. int option_index = 0;
  83. static const char *short_options = "bs:f:il:opqn";
  84. static const struct option long_options[] = {
  85. {"help", no_argument, 0, 0},
  86. {"version", no_argument, 0, 0},
  87. {"file", required_argument, 0, 'f'},
  88. {"ignoreerrors", no_argument, 0, 'i'},
  89. {"prettyprint", no_argument, 0, 'p'},
  90. {"omitoob", no_argument, 0, 'o'},
  91. {"omitbad", no_argument, 0, 'b'},
  92. {"startaddress", required_argument, 0, 's'},
  93. {"length", required_argument, 0, 'l'},
  94. {"noecc", no_argument, 0, 'n'},
  95. {"quiet", no_argument, 0, 'q'},
  96. {0, 0, 0, 0},
  97. };
  98. int c = getopt_long(argc, argv, short_options,
  99. long_options, &option_index);
  100. if (c == EOF) {
  101. break;
  102. }
  103. switch (c) {
  104. case 0:
  105. switch (option_index) {
  106. case 0:
  107. display_help();
  108. break;
  109. case 1:
  110. display_version();
  111. break;
  112. }
  113. break;
  114. case 'b':
  115. omitbad = true;
  116. break;
  117. case 's':
  118. start_addr = strtol(optarg, NULL, 0);
  119. break;
  120. case 'f':
  121. if (!(dumpfile = strdup(optarg))) {
  122. perror("stddup");
  123. exit(EXIT_FAILURE);
  124. }
  125. break;
  126. case 'i':
  127. ignoreerrors = true;
  128. break;
  129. case 'l':
  130. length = strtol(optarg, NULL, 0);
  131. break;
  132. case 'o':
  133. omitoob = true;
  134. break;
  135. case 'p':
  136. pretty_print = true;
  137. break;
  138. case 'q':
  139. quiet = true;
  140. break;
  141. case 'n':
  142. noecc = true;
  143. break;
  144. case '?':
  145. error++;
  146. break;
  147. }
  148. }
  149. if (quiet && pretty_print) {
  150. fprintf(stderr, "The quiet and pretty print options are mutually-\n"
  151. "exclusive. Choose one or the other.\n");
  152. exit(EXIT_FAILURE);
  153. }
  154. if ((argc - optind) != 1 || error)
  155. display_help ();
  156. mtddev = argv[optind];
  157. }
  158. /*
  159. * Buffers for reading data from flash
  160. */
  161. static unsigned char readbuf[4096];
  162. static unsigned char oobbuf[128];
  163. /*
  164. * Main program
  165. */
  166. int main(int argc, char * const argv[])
  167. {
  168. unsigned long ofs, end_addr = 0;
  169. unsigned long long blockstart = 1;
  170. int ret, i, fd, ofd, bs, badblock = 0;
  171. struct mtd_oob_buf oob = {0, 16, oobbuf};
  172. mtd_info_t meminfo;
  173. char pretty_buf[80];
  174. int oobinfochanged = 0 ;
  175. struct nand_oobinfo old_oobinfo;
  176. struct mtd_ecc_stats stat1, stat2;
  177. bool eccstats = false;
  178. process_options(argc, argv);
  179. /* Open MTD device */
  180. if ((fd = open(mtddev, O_RDONLY)) == -1) {
  181. perror(mtddev);
  182. exit (EXIT_FAILURE);
  183. }
  184. /* Fill in MTD device capability structure */
  185. if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
  186. perror("MEMGETINFO");
  187. close(fd);
  188. exit (EXIT_FAILURE);
  189. }
  190. /* Make sure device page sizes are valid */
  191. if (!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
  192. !(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
  193. !(meminfo.oobsize == 32 && meminfo.writesize == 1024) &&
  194. !(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
  195. !(meminfo.oobsize == 8 && meminfo.writesize == 256)) {
  196. fprintf(stderr, "Unknown flash (not normal NAND)\n");
  197. close(fd);
  198. exit(EXIT_FAILURE);
  199. }
  200. /* Read the real oob length */
  201. oob.length = meminfo.oobsize;
  202. if (noecc) {
  203. ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
  204. if (ret == 0) {
  205. oobinfochanged = 2;
  206. } else {
  207. switch (errno) {
  208. case ENOTTY:
  209. if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
  210. perror ("MEMGETOOBSEL");
  211. close (fd);
  212. exit (EXIT_FAILURE);
  213. }
  214. if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
  215. perror ("MEMSETOOBSEL");
  216. close (fd);
  217. exit (EXIT_FAILURE);
  218. }
  219. oobinfochanged = 1;
  220. break;
  221. default:
  222. perror ("MTDFILEMODE");
  223. close (fd);
  224. exit (EXIT_FAILURE);
  225. }
  226. }
  227. } else {
  228. /* check if we can read ecc stats */
  229. if (!ioctl(fd, ECCGETSTATS, &stat1)) {
  230. eccstats = true;
  231. if (!quiet) {
  232. fprintf(stderr, "ECC failed: %d\n", stat1.failed);
  233. fprintf(stderr, "ECC corrected: %d\n", stat1.corrected);
  234. fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks);
  235. fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks);
  236. }
  237. } else
  238. perror("No ECC status information available");
  239. }
  240. /* Open output file for writing. If file name is "-", write to standard
  241. * output. */
  242. if (!dumpfile) {
  243. ofd = STDOUT_FILENO;
  244. } else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
  245. perror (dumpfile);
  246. close(fd);
  247. exit(EXIT_FAILURE);
  248. }
  249. /* Initialize start/end addresses and block size */
  250. if (length)
  251. end_addr = start_addr + length;
  252. if (!length || end_addr > meminfo.size)
  253. end_addr = meminfo.size;
  254. bs = meminfo.writesize;
  255. /* Print informative message */
  256. if (!quiet) {
  257. fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
  258. meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
  259. fprintf(stderr,
  260. "Dumping data starting at 0x%08x and ending at 0x%08x...\n",
  261. (unsigned int) start_addr, (unsigned int) end_addr);
  262. }
  263. /* Dump the flash contents */
  264. for (ofs = start_addr; ofs < end_addr ; ofs+=bs) {
  265. // new eraseblock , check for bad block
  266. if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
  267. blockstart = ofs & (~meminfo.erasesize + 1);
  268. if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
  269. perror("ioctl(MEMGETBADBLOCK)");
  270. goto closeall;
  271. }
  272. }
  273. if (badblock) {
  274. if (omitbad)
  275. continue;
  276. memset (readbuf, 0xff, bs);
  277. } else {
  278. /* Read page data and exit on failure */
  279. if (pread(fd, readbuf, bs, ofs) != bs) {
  280. perror("pread");
  281. goto closeall;
  282. }
  283. }
  284. /* ECC stats available ? */
  285. if (eccstats) {
  286. if (ioctl(fd, ECCGETSTATS, &stat2)) {
  287. perror("ioctl(ECCGETSTATS)");
  288. goto closeall;
  289. }
  290. if (stat1.failed != stat2.failed)
  291. fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
  292. " at offset 0x%08lx\n",
  293. stat2.failed - stat1.failed, ofs);
  294. if (stat1.corrected != stat2.corrected)
  295. fprintf(stderr, "ECC: %d corrected bitflip(s) at"
  296. " offset 0x%08lx\n",
  297. stat2.corrected - stat1.corrected, ofs);
  298. stat1 = stat2;
  299. }
  300. /* Write out page data */
  301. if (pretty_print) {
  302. for (i = 0; i < bs; i += 16) {
  303. sprintf(pretty_buf,
  304. "0x%08x: %02x %02x %02x %02x %02x %02x %02x "
  305. "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  306. (unsigned int) (ofs + i), readbuf[i],
  307. readbuf[i+1], readbuf[i+2],
  308. readbuf[i+3], readbuf[i+4],
  309. readbuf[i+5], readbuf[i+6],
  310. readbuf[i+7], readbuf[i+8],
  311. readbuf[i+9], readbuf[i+10],
  312. readbuf[i+11], readbuf[i+12],
  313. readbuf[i+13], readbuf[i+14],
  314. readbuf[i+15]);
  315. write(ofd, pretty_buf, 60);
  316. }
  317. } else
  318. write(ofd, readbuf, bs);
  319. if (omitoob)
  320. continue;
  321. if (badblock) {
  322. memset (readbuf, 0xff, meminfo.oobsize);
  323. } else {
  324. /* Read OOB data and exit on failure */
  325. oob.start = ofs;
  326. if (ioctl(fd, MEMREADOOB, &oob) != 0) {
  327. perror("ioctl(MEMREADOOB)");
  328. goto closeall;
  329. }
  330. }
  331. /* Write out OOB data */
  332. if (pretty_print) {
  333. if (meminfo.oobsize < 16) {
  334. sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x "
  335. "%02x %02x\n",
  336. oobbuf[0], oobbuf[1], oobbuf[2],
  337. oobbuf[3], oobbuf[4], oobbuf[5],
  338. oobbuf[6], oobbuf[7]);
  339. write(ofd, pretty_buf, 48);
  340. continue;
  341. }
  342. for (i = 0; i < meminfo.oobsize; i += 16) {
  343. sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x "
  344. "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  345. oobbuf[i], oobbuf[i+1], oobbuf[i+2],
  346. oobbuf[i+3], oobbuf[i+4], oobbuf[i+5],
  347. oobbuf[i+6], oobbuf[i+7], oobbuf[i+8],
  348. oobbuf[i+9], oobbuf[i+10], oobbuf[i+11],
  349. oobbuf[i+12], oobbuf[i+13], oobbuf[i+14],
  350. oobbuf[i+15]);
  351. write(ofd, pretty_buf, 60);
  352. }
  353. } else
  354. write(ofd, oobbuf, meminfo.oobsize);
  355. }
  356. /* reset oobinfo */
  357. if (oobinfochanged == 1) {
  358. if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
  359. perror ("MEMSETOOBSEL");
  360. close(fd);
  361. close(ofd);
  362. return EXIT_FAILURE;
  363. }
  364. }
  365. /* Close the output file and MTD device */
  366. close(fd);
  367. close(ofd);
  368. /* Exit happy */
  369. return EXIT_SUCCESS;
  370. closeall:
  371. /* The new mode change is per file descriptor ! */
  372. if (oobinfochanged == 1) {
  373. if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
  374. perror ("MEMSETOOBSEL");
  375. }
  376. }
  377. close(fd);
  378. close(ofd);
  379. exit(EXIT_FAILURE);
  380. }