nandwrite.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * nandwrite.c
  3. *
  4. * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  5. * 2003 Thomas Gleixner (tglx@linutronix.de)
  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 writes a binary image directly to a NAND flash
  13. * chip or NAND chips contained in DoC devices. This is the
  14. * "inverse operation" of nanddump.
  15. *
  16. * tglx: Major rewrite to handle bad blocks, write data with or without ECC
  17. * write oob data only on request
  18. *
  19. * Bug/ToDo:
  20. */
  21. #define PROGRAM_NAME "nandwrite"
  22. #include <ctype.h>
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <stdbool.h>
  26. #include <stddef.h>
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <unistd.h>
  33. #include <sys/stat.h>
  34. #include <sys/ioctl.h>
  35. #include <sys/types.h>
  36. #include <getopt.h>
  37. #include <asm/types.h>
  38. #include "mtd/mtd-user.h"
  39. #include "common.h"
  40. #include <libmtd.h>
  41. static void display_help(int status)
  42. {
  43. fprintf(status == EXIT_SUCCESS ? stdout : stderr,
  44. "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
  45. "Writes to the specified MTD device.\n"
  46. "\n"
  47. " -a, --autoplace Use auto OOB layout\n"
  48. " -k, --skip-all-ffs Skip pages that contain only 0xff bytes\n"
  49. " -m, --markbad Mark blocks bad if write fails\n"
  50. " -n, --noecc Write without ecc\n"
  51. " -N, --noskipbad Write without bad block skipping\n"
  52. " -o, --oob Input contains oob data\n"
  53. " -O, --onlyoob Input contains oob data and only write the oob part\n"
  54. " -s addr, --start=addr Set output start address (default is 0)\n"
  55. " --skip-bad-blocks-to-start"
  56. " Skip bad blocks when seeking to the start address\n"
  57. " -p, --pad Pad writes to page size\n"
  58. " -b, --blockalign=1|2|4 Set multiple of eraseblocks to align to\n"
  59. " --input-skip=length Skip |length| bytes of the input file\n"
  60. " --input-size=length Only read |length| bytes of the input file\n"
  61. " -q, --quiet Don't display progress messages\n"
  62. " -h, --help Display this help and exit\n"
  63. " -V, --version Output version information and exit\n"
  64. );
  65. exit(status);
  66. }
  67. static void display_version(void)
  68. {
  69. common_print_version();
  70. printf("Copyright (C) 2003 Thomas Gleixner \n"
  71. "\n"
  72. "%1$s comes with NO WARRANTY\n"
  73. "to the extent permitted by law.\n"
  74. "\n"
  75. "You may redistribute copies of %1$s\n"
  76. "under the terms of the GNU General Public Licence.\n"
  77. "See the file `COPYING' for more information.\n",
  78. PROGRAM_NAME);
  79. exit(EXIT_SUCCESS);
  80. }
  81. static const char *standard_input = "-";
  82. static const char *mtd_device, *img;
  83. static long long mtdoffset = 0;
  84. static long long inputskip = 0;
  85. static long long inputsize = 0;
  86. static bool quiet = false;
  87. static bool writeoob = false;
  88. static bool onlyoob = false;
  89. static bool markbad = false;
  90. static bool noecc = false;
  91. static bool autoplace = false;
  92. static bool skipallffs = false;
  93. static bool noskipbad = false;
  94. static bool pad = false;
  95. static bool skip_bad_blocks_to_start = false;
  96. static int blockalign = 1; /* default to using actual block size */
  97. static void process_options(int argc, char * const argv[])
  98. {
  99. int error = 0;
  100. for (;;) {
  101. int option_index = 0;
  102. static const char short_options[] = "hb:mnNoOpqs:akV";
  103. static const struct option long_options[] = {
  104. /* Order of these args with val==0 matters; see option_index. */
  105. {"version", no_argument, 0, 'V'},
  106. {"input-skip", required_argument, 0, 0},
  107. {"input-size", required_argument, 0, 0},
  108. {"skip-bad-blocks-to-start", no_argument, 0, 0},
  109. {"help", no_argument, 0, 'h'},
  110. {"blockalign", required_argument, 0, 'b'},
  111. {"markbad", no_argument, 0, 'm'},
  112. {"noecc", no_argument, 0, 'n'},
  113. {"noskipbad", no_argument, 0, 'N'},
  114. {"oob", no_argument, 0, 'o'},
  115. {"onlyoob", no_argument, 0, 'O'},
  116. {"pad", no_argument, 0, 'p'},
  117. {"quiet", no_argument, 0, 'q'},
  118. {"start", required_argument, 0, 's'},
  119. {"autoplace", no_argument, 0, 'a'},
  120. {"skip-all-ffs", no_argument, 0, 'k'},
  121. {0, 0, 0, 0},
  122. };
  123. int c = getopt_long(argc, argv, short_options,
  124. long_options, &option_index);
  125. if (c == EOF)
  126. break;
  127. switch (c) {
  128. case 0:
  129. switch (option_index) {
  130. case 1: /* --input-skip */
  131. inputskip = simple_strtoll(optarg, &error);
  132. break;
  133. case 2: /* --input-size */
  134. inputsize = simple_strtoll(optarg, &error);
  135. break;
  136. case 3: /* --skip-bad-blocks-to-start */
  137. skip_bad_blocks_to_start = true;
  138. break;
  139. }
  140. break;
  141. case 'V':
  142. display_version();
  143. break;
  144. case 'q':
  145. quiet = true;
  146. break;
  147. case 'n':
  148. noecc = true;
  149. break;
  150. case 'N':
  151. noskipbad = true;
  152. break;
  153. case 'm':
  154. markbad = true;
  155. break;
  156. case 'o':
  157. writeoob = true;
  158. break;
  159. case 'O':
  160. writeoob = true;
  161. onlyoob = true;
  162. break;
  163. case 'p':
  164. pad = true;
  165. break;
  166. case 's':
  167. mtdoffset = simple_strtoll(optarg, &error);
  168. break;
  169. case 'b':
  170. blockalign = atoi(optarg);
  171. break;
  172. case 'a':
  173. autoplace = true;
  174. break;
  175. case 'k':
  176. skipallffs = true;
  177. break;
  178. case 'h':
  179. display_help(EXIT_SUCCESS);
  180. break;
  181. case '?':
  182. error++;
  183. break;
  184. }
  185. }
  186. if (mtdoffset < 0)
  187. errmsg_die("Can't specify negative device offset with option"
  188. " -s: %lld", mtdoffset);
  189. if (blockalign <= 0)
  190. errmsg_die("Can't specify negative or zero blockalign with "
  191. "option -b: %d", blockalign);
  192. if (!is_power_of_2(blockalign))
  193. errmsg_die("Can't specify a non-power-of-two blockalign with "
  194. "option -b: %d", blockalign);
  195. if (autoplace && noecc)
  196. errmsg_die("Autoplacement and no-ECC are mutually exclusive");
  197. if (!onlyoob && (pad && writeoob))
  198. errmsg_die("Can't pad when oob data is present");
  199. argc -= optind;
  200. argv += optind;
  201. /*
  202. * There must be at least the MTD device node positional
  203. * argument remaining and, optionally, the input file.
  204. */
  205. if (argc < 1 || argc > 2 || error)
  206. display_help(EXIT_FAILURE);
  207. mtd_device = argv[0];
  208. /*
  209. * Standard input may be specified either explictly as "-" or
  210. * implicity by simply omitting the second of the two
  211. * positional arguments.
  212. */
  213. img = ((argc == 2) ? argv[1] : standard_input);
  214. }
  215. static void erase_buffer(void *buffer, size_t size)
  216. {
  217. const uint8_t kEraseByte = 0xff;
  218. if (buffer != NULL && size > 0)
  219. memset(buffer, kEraseByte, size);
  220. }
  221. static int is_virt_block_bad(struct mtd_dev_info *mtd, int fd,
  222. long long offset)
  223. {
  224. int i, ret = 0;
  225. for (i = 0; i < blockalign; ++i) {
  226. ret = mtd_is_bad(mtd, fd, offset / mtd->eb_size + i);
  227. if (ret)
  228. break;
  229. }
  230. return ret;
  231. }
  232. /*
  233. * Main program
  234. */
  235. int main(int argc, char * const argv[])
  236. {
  237. int fd = -1;
  238. int ifd = -1;
  239. int pagelen;
  240. long long imglen = 0;
  241. long long blockstart = -1;
  242. struct mtd_dev_info mtd;
  243. int ret;
  244. bool failed = true;
  245. /* contains all the data read from the file so far for the current eraseblock */
  246. unsigned char *filebuf = NULL;
  247. size_t filebuf_max = 0;
  248. size_t filebuf_len = 0;
  249. /* points to the current page inside filebuf */
  250. unsigned char *writebuf = NULL;
  251. /* points to the OOB for the current page in filebuf */
  252. unsigned char *oobbuf = NULL;
  253. libmtd_t mtd_desc;
  254. int ebsize_aligned;
  255. uint8_t write_mode;
  256. process_options(argc, argv);
  257. /* Open the device */
  258. if ((fd = open(mtd_device, O_RDWR)) == -1)
  259. sys_errmsg_die("%s", mtd_device);
  260. mtd_desc = libmtd_open();
  261. if (!mtd_desc)
  262. errmsg_die("can't initialize libmtd");
  263. /* Fill in MTD device capability structure */
  264. if (mtd_get_dev_info(mtd_desc, mtd_device, &mtd) < 0)
  265. errmsg_die("mtd_get_dev_info failed");
  266. /*
  267. * Pretend erasesize is specified number of blocks - to match jffs2
  268. * (virtual) block size
  269. * Use this value throughout unless otherwise necessary
  270. */
  271. ebsize_aligned = mtd.eb_size * blockalign;
  272. if (mtdoffset & (mtd.min_io_size - 1))
  273. errmsg_die("The start address is not page-aligned !\n"
  274. "The pagesize of this NAND Flash is 0x%x.\n",
  275. mtd.min_io_size);
  276. /* Select OOB write mode */
  277. if (noecc)
  278. write_mode = MTD_OPS_RAW;
  279. else if (autoplace)
  280. write_mode = MTD_OPS_AUTO_OOB;
  281. else
  282. write_mode = MTD_OPS_PLACE_OOB;
  283. if (noecc) {
  284. ret = ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW);
  285. if (ret) {
  286. switch (errno) {
  287. case ENOTTY:
  288. errmsg_die("ioctl MTDFILEMODE is missing");
  289. default:
  290. sys_errmsg_die("MTDFILEMODE");
  291. }
  292. }
  293. }
  294. /* Determine if we are reading from standard input or from a file. */
  295. if (strcmp(img, standard_input) == 0)
  296. ifd = STDIN_FILENO;
  297. else
  298. ifd = open(img, O_RDONLY);
  299. if (ifd == -1) {
  300. perror(img);
  301. goto closeall;
  302. }
  303. pagelen = mtd.min_io_size + ((writeoob) ? mtd.oob_size : 0);
  304. if (ifd == STDIN_FILENO) {
  305. imglen = inputsize ? : pagelen;
  306. if (inputskip) {
  307. errmsg("seeking stdin not supported");
  308. goto closeall;
  309. }
  310. } else {
  311. if (!inputsize) {
  312. struct stat st;
  313. if (fstat(ifd, &st)) {
  314. sys_errmsg("unable to stat input image");
  315. goto closeall;
  316. }
  317. imglen = st.st_size - inputskip;
  318. } else
  319. imglen = inputsize;
  320. if (inputskip && lseek(ifd, inputskip, SEEK_CUR) == -1) {
  321. sys_errmsg("lseek input by %lld failed", inputskip);
  322. goto closeall;
  323. }
  324. }
  325. /* Check, if file is page-aligned */
  326. if (!pad && (imglen % pagelen) != 0) {
  327. fprintf(stderr, "Input file is not page-aligned. Use the padding "
  328. "option.\n");
  329. goto closeall;
  330. }
  331. /* Skip bad blocks on the way to the start address if necessary */
  332. if (skip_bad_blocks_to_start) {
  333. long long bbs_offset = 0;
  334. while (bbs_offset < mtdoffset) {
  335. ret = is_virt_block_bad(&mtd, fd, bbs_offset);
  336. if (ret < 0) {
  337. sys_errmsg("%s: MTD get bad block failed", mtd_device);
  338. goto closeall;
  339. } else if (ret == 1) {
  340. if (!quiet)
  341. fprintf(stderr, "Bad block at %llx, %u block(s) "
  342. "from %llx will be skipped\n",
  343. bbs_offset, blockalign, bbs_offset);
  344. mtdoffset += ebsize_aligned;
  345. }
  346. bbs_offset += ebsize_aligned;
  347. }
  348. }
  349. /* Check, if length fits into device */
  350. if ((imglen / pagelen) * mtd.min_io_size > mtd.size - mtdoffset) {
  351. fprintf(stderr, "Image %lld bytes, NAND page %d bytes, OOB area %d"
  352. " bytes, device size %lld bytes\n",
  353. imglen, pagelen, mtd.oob_size, mtd.size);
  354. sys_errmsg("Input file does not fit into device");
  355. goto closeall;
  356. }
  357. /*
  358. * Allocate a buffer big enough to contain all the data (OOB included)
  359. * for one eraseblock. The order of operations here matters; if ebsize
  360. * and pagelen are large enough, then "ebsize_aligned * pagelen" could
  361. * overflow a 32-bit data type.
  362. */
  363. filebuf_max = ebsize_aligned / mtd.min_io_size * pagelen;
  364. filebuf = xmalloc(filebuf_max);
  365. erase_buffer(filebuf, filebuf_max);
  366. /*
  367. * Get data from input and write to the device while there is
  368. * still input to read and we are still within the device
  369. * bounds. Note that in the case of standard input, the input
  370. * length is simply a quasi-boolean flag whose values are page
  371. * length or zero.
  372. */
  373. while ((imglen > 0 || writebuf < filebuf + filebuf_len)
  374. && mtdoffset < mtd.size) {
  375. /*
  376. * New eraseblock, check for bad block(s)
  377. * Stay in the loop to be sure that, if mtdoffset changes because
  378. * of a bad block, the next block that will be written to
  379. * is also checked. Thus, we avoid errors if the block(s) after the
  380. * skipped block(s) is also bad (number of blocks depending on
  381. * the blockalign).
  382. */
  383. while (blockstart != (mtdoffset & (~ebsize_aligned + 1))) {
  384. blockstart = mtdoffset & (~ebsize_aligned + 1);
  385. /*
  386. * if writebuf == filebuf, we are rewinding so we must
  387. * not reset the buffer but just replay it
  388. */
  389. if (writebuf != filebuf) {
  390. erase_buffer(filebuf, filebuf_len);
  391. filebuf_len = 0;
  392. writebuf = filebuf;
  393. }
  394. if (!quiet)
  395. fprintf(stdout, "Writing data to block %lld at offset 0x%llx\n",
  396. blockstart / ebsize_aligned, blockstart);
  397. if (noskipbad)
  398. continue;
  399. ret = is_virt_block_bad(&mtd, fd, blockstart);
  400. if (ret < 0) {
  401. sys_errmsg("%s: MTD get bad block failed", mtd_device);
  402. goto closeall;
  403. } else if (ret == 1) {
  404. if (!quiet)
  405. fprintf(stderr,
  406. "Bad block at %llx, %u block(s) "
  407. "will be skipped\n",
  408. blockstart, blockalign);
  409. mtdoffset = blockstart + ebsize_aligned;
  410. if (mtdoffset > mtd.size) {
  411. errmsg("too many bad blocks, cannot complete request");
  412. goto closeall;
  413. }
  414. }
  415. }
  416. /* Read more data from the input if there isn't enough in the buffer */
  417. if (writebuf + mtd.min_io_size > filebuf + filebuf_len) {
  418. size_t readlen = mtd.min_io_size;
  419. size_t alreadyread = (filebuf + filebuf_len) - writebuf;
  420. size_t tinycnt = alreadyread;
  421. ssize_t cnt = 0;
  422. while (tinycnt < readlen) {
  423. cnt = read(ifd, writebuf + tinycnt, readlen - tinycnt);
  424. if (cnt == 0) { /* EOF */
  425. break;
  426. } else if (cnt < 0) {
  427. perror("File I/O error on input");
  428. goto closeall;
  429. }
  430. tinycnt += cnt;
  431. }
  432. /* No padding needed - we are done */
  433. if (tinycnt == 0) {
  434. /*
  435. * For standard input, set imglen to 0 to signal
  436. * the end of the "file". For nonstandard input,
  437. * leave it as-is to detect an early EOF.
  438. */
  439. if (ifd == STDIN_FILENO)
  440. imglen = 0;
  441. break;
  442. }
  443. /* Padding */
  444. if (tinycnt < readlen) {
  445. if (!pad) {
  446. fprintf(stderr, "Unexpected EOF. Expecting at least "
  447. "%zu more bytes. Use the padding option.\n",
  448. readlen - tinycnt);
  449. goto closeall;
  450. }
  451. erase_buffer(writebuf + tinycnt, readlen - tinycnt);
  452. }
  453. filebuf_len += readlen - alreadyread;
  454. if (ifd != STDIN_FILENO) {
  455. imglen -= tinycnt - alreadyread;
  456. } else if (cnt == 0) {
  457. /* No more bytes - we are done after writing the remaining bytes */
  458. imglen = 0;
  459. }
  460. }
  461. if (writeoob) {
  462. oobbuf = writebuf + mtd.min_io_size;
  463. /* Read more data for the OOB from the input if there isn't enough in the buffer */
  464. if (oobbuf + mtd.oob_size > filebuf + filebuf_len) {
  465. size_t readlen = mtd.oob_size;
  466. size_t alreadyread = (filebuf + filebuf_len) - oobbuf;
  467. size_t tinycnt = alreadyread;
  468. ssize_t cnt;
  469. while (tinycnt < readlen) {
  470. cnt = read(ifd, oobbuf + tinycnt, readlen - tinycnt);
  471. if (cnt == 0) { /* EOF */
  472. break;
  473. } else if (cnt < 0) {
  474. perror("File I/O error on input");
  475. goto closeall;
  476. }
  477. tinycnt += cnt;
  478. }
  479. if (tinycnt < readlen) {
  480. fprintf(stderr, "Unexpected EOF. Expecting at least "
  481. "%zu more bytes for OOB\n", readlen - tinycnt);
  482. goto closeall;
  483. }
  484. filebuf_len += readlen - alreadyread;
  485. if (ifd != STDIN_FILENO) {
  486. imglen -= tinycnt - alreadyread;
  487. } else if (cnt == 0) {
  488. /* No more bytes - we are done after writing the remaining bytes */
  489. imglen = 0;
  490. }
  491. }
  492. }
  493. ret = 0;
  494. if (!skipallffs || !buffer_check_pattern(writebuf, mtd.min_io_size, 0xff)) {
  495. /* Write out data */
  496. ret = mtd_write(mtd_desc, &mtd, fd, mtdoffset / mtd.eb_size,
  497. mtdoffset % mtd.eb_size,
  498. onlyoob ? NULL : writebuf,
  499. onlyoob ? 0 : mtd.min_io_size,
  500. writeoob ? oobbuf : NULL,
  501. writeoob ? mtd.oob_size : 0,
  502. write_mode);
  503. }
  504. if (ret) {
  505. if (errno != EIO) {
  506. sys_errmsg("%s: MTD write failure", mtd_device);
  507. goto closeall;
  508. }
  509. /* Must rewind to blockstart if we can */
  510. writebuf = filebuf;
  511. fprintf(stderr, "Erasing failed write from %#08llx to %#08llx\n",
  512. blockstart, blockstart + ebsize_aligned - 1);
  513. if (mtd_erase_multi(mtd_desc, &mtd, fd,
  514. blockstart / mtd.eb_size, blockalign)) {
  515. int errno_tmp = errno;
  516. sys_errmsg("%s: MTD Erase failure", mtd_device);
  517. if (errno_tmp != EIO)
  518. goto closeall;
  519. }
  520. if (markbad) {
  521. fprintf(stderr, "Marking block at %08llx bad\n",
  522. mtdoffset & (~mtd.eb_size + 1));
  523. if (mtd_mark_bad(&mtd, fd, mtdoffset / mtd.eb_size)) {
  524. sys_errmsg("%s: MTD Mark bad block failure", mtd_device);
  525. goto closeall;
  526. }
  527. }
  528. mtdoffset = blockstart + ebsize_aligned;
  529. continue;
  530. }
  531. mtdoffset += mtd.min_io_size;
  532. writebuf += pagelen;
  533. }
  534. failed = false;
  535. closeall:
  536. if (ifd > 0 && ifd != STDIN_FILENO)
  537. close(ifd);
  538. libmtd_close(mtd_desc);
  539. free(filebuf);
  540. close(fd);
  541. if (failed || (ifd != STDIN_FILENO && imglen > 0)
  542. || (writebuf < filebuf + filebuf_len))
  543. sys_errmsg_die("Data was only partially written due to error");
  544. /* Return happy */
  545. return EXIT_SUCCESS;
  546. }