mtd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * mtd.c
  4. *
  5. * Generic command to handle basic operations on any memory device.
  6. *
  7. * Copyright: Bootlin, 2018
  8. * Author: Miquèl Raynal <miquel.raynal@bootlin.com>
  9. */
  10. #include <command.h>
  11. #include <common.h>
  12. #include <console.h>
  13. #include <malloc.h>
  14. #include <mapmem.h>
  15. #include <mtd.h>
  16. #include <linux/ctype.h>
  17. static struct mtd_info *get_mtd_by_name(const char *name)
  18. {
  19. struct mtd_info *mtd;
  20. mtd_probe_devices();
  21. mtd = get_mtd_device_nm(name);
  22. if (IS_ERR_OR_NULL(mtd))
  23. printf("MTD device %s not found, ret %ld\n", name,
  24. PTR_ERR(mtd));
  25. return mtd;
  26. }
  27. static uint mtd_len_to_pages(struct mtd_info *mtd, u64 len)
  28. {
  29. do_div(len, mtd->writesize);
  30. return len;
  31. }
  32. static bool mtd_is_aligned_with_min_io_size(struct mtd_info *mtd, u64 size)
  33. {
  34. return !do_div(size, mtd->writesize);
  35. }
  36. static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
  37. {
  38. return !do_div(size, mtd->erasesize);
  39. }
  40. static void mtd_dump_buf(const u8 *buf, uint len, uint offset)
  41. {
  42. int i, j;
  43. for (i = 0; i < len; ) {
  44. printf("0x%08x:\t", offset + i);
  45. for (j = 0; j < 8; j++)
  46. printf("%02x ", buf[i + j]);
  47. printf(" ");
  48. i += 8;
  49. for (j = 0; j < 8; j++)
  50. printf("%02x ", buf[i + j]);
  51. printf("\n");
  52. i += 8;
  53. }
  54. }
  55. static void mtd_dump_device_buf(struct mtd_info *mtd, u64 start_off,
  56. const u8 *buf, u64 len, bool woob)
  57. {
  58. bool has_pages = mtd->type == MTD_NANDFLASH ||
  59. mtd->type == MTD_MLCNANDFLASH;
  60. int npages = mtd_len_to_pages(mtd, len);
  61. uint page;
  62. if (has_pages) {
  63. for (page = 0; page < npages; page++) {
  64. u64 data_off = page * mtd->writesize;
  65. printf("\nDump %d data bytes from 0x%08llx:\n",
  66. mtd->writesize, start_off + data_off);
  67. mtd_dump_buf(&buf[data_off],
  68. mtd->writesize, start_off + data_off);
  69. if (woob) {
  70. u64 oob_off = page * mtd->oobsize;
  71. printf("Dump %d OOB bytes from page at 0x%08llx:\n",
  72. mtd->oobsize, start_off + data_off);
  73. mtd_dump_buf(&buf[len + oob_off],
  74. mtd->oobsize, 0);
  75. }
  76. }
  77. } else {
  78. printf("\nDump %lld data bytes from 0x%llx:\n",
  79. len, start_off);
  80. mtd_dump_buf(buf, len, start_off);
  81. }
  82. }
  83. static void mtd_show_parts(struct mtd_info *mtd, int level)
  84. {
  85. struct mtd_info *part;
  86. int i;
  87. list_for_each_entry(part, &mtd->partitions, node) {
  88. for (i = 0; i < level; i++)
  89. printf("\t");
  90. printf(" - 0x%012llx-0x%012llx : \"%s\"\n",
  91. part->offset, part->offset + part->size, part->name);
  92. mtd_show_parts(part, level + 1);
  93. }
  94. }
  95. static void mtd_show_device(struct mtd_info *mtd)
  96. {
  97. /* Device */
  98. printf("* %s\n", mtd->name);
  99. #if defined(CONFIG_DM)
  100. if (mtd->dev) {
  101. printf(" - device: %s\n", mtd->dev->name);
  102. printf(" - parent: %s\n", mtd->dev->parent->name);
  103. printf(" - driver: %s\n", mtd->dev->driver->name);
  104. }
  105. #endif
  106. /* MTD device information */
  107. printf(" - type: ");
  108. switch (mtd->type) {
  109. case MTD_RAM:
  110. printf("RAM\n");
  111. break;
  112. case MTD_ROM:
  113. printf("ROM\n");
  114. break;
  115. case MTD_NORFLASH:
  116. printf("NOR flash\n");
  117. break;
  118. case MTD_NANDFLASH:
  119. printf("NAND flash\n");
  120. break;
  121. case MTD_DATAFLASH:
  122. printf("Data flash\n");
  123. break;
  124. case MTD_UBIVOLUME:
  125. printf("UBI volume\n");
  126. break;
  127. case MTD_MLCNANDFLASH:
  128. printf("MLC NAND flash\n");
  129. break;
  130. case MTD_ABSENT:
  131. default:
  132. printf("Unknown\n");
  133. break;
  134. }
  135. printf(" - block size: 0x%x bytes\n", mtd->erasesize);
  136. printf(" - min I/O: 0x%x bytes\n", mtd->writesize);
  137. if (mtd->oobsize) {
  138. printf(" - OOB size: %u bytes\n", mtd->oobsize);
  139. printf(" - OOB available: %u bytes\n", mtd->oobavail);
  140. }
  141. if (mtd->ecc_strength) {
  142. printf(" - ECC strength: %u bits\n", mtd->ecc_strength);
  143. printf(" - ECC step size: %u bytes\n", mtd->ecc_step_size);
  144. printf(" - bitflip threshold: %u bits\n",
  145. mtd->bitflip_threshold);
  146. }
  147. printf(" - 0x%012llx-0x%012llx : \"%s\"\n",
  148. mtd->offset, mtd->offset + mtd->size, mtd->name);
  149. /* MTD partitions, if any */
  150. mtd_show_parts(mtd, 1);
  151. }
  152. /* Logic taken from fs/ubifs/recovery.c:is_empty() */
  153. static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op)
  154. {
  155. int i;
  156. for (i = 0; i < op->len; i++)
  157. if (op->datbuf[i] != 0xff)
  158. return false;
  159. for (i = 0; i < op->ooblen; i++)
  160. if (op->oobbuf[i] != 0xff)
  161. return false;
  162. return true;
  163. }
  164. static int do_mtd_list(cmd_tbl_t *cmdtp, int flag, int argc,
  165. char * const argv[])
  166. {
  167. struct mtd_info *mtd;
  168. int dev_nb = 0;
  169. /* Ensure all devices (and their partitions) are probed */
  170. mtd_probe_devices();
  171. printf("List of MTD devices:\n");
  172. mtd_for_each_device(mtd) {
  173. if (!mtd_is_partition(mtd))
  174. mtd_show_device(mtd);
  175. dev_nb++;
  176. }
  177. if (!dev_nb) {
  178. printf("No MTD device found\n");
  179. return CMD_RET_FAILURE;
  180. }
  181. return CMD_RET_SUCCESS;
  182. }
  183. static int mtd_special_write_oob(struct mtd_info *mtd, u64 off,
  184. struct mtd_oob_ops *io_op,
  185. bool write_empty_pages, bool woob)
  186. {
  187. int ret = 0;
  188. /*
  189. * By default, do not write an empty page.
  190. * Skip it by simulating a successful write.
  191. */
  192. if (!write_empty_pages && mtd_oob_write_is_empty(io_op)) {
  193. io_op->retlen = mtd->writesize;
  194. io_op->oobretlen = woob ? mtd->oobsize : 0;
  195. } else {
  196. ret = mtd_write_oob(mtd, off, io_op);
  197. }
  198. return ret;
  199. }
  200. static int do_mtd_io(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  201. {
  202. bool dump, read, raw, woob, write_empty_pages, has_pages = false;
  203. u64 start_off, off, len, remaining, default_len;
  204. struct mtd_oob_ops io_op = {};
  205. uint user_addr = 0, npages;
  206. const char *cmd = argv[0];
  207. struct mtd_info *mtd;
  208. u32 oob_len;
  209. u8 *buf;
  210. int ret;
  211. if (argc < 2)
  212. return CMD_RET_USAGE;
  213. mtd = get_mtd_by_name(argv[1]);
  214. if (IS_ERR_OR_NULL(mtd))
  215. return CMD_RET_FAILURE;
  216. if (mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH)
  217. has_pages = true;
  218. dump = !strncmp(cmd, "dump", 4);
  219. read = dump || !strncmp(cmd, "read", 4);
  220. raw = strstr(cmd, ".raw");
  221. woob = strstr(cmd, ".oob");
  222. write_empty_pages = !has_pages || strstr(cmd, ".dontskipff");
  223. argc -= 2;
  224. argv += 2;
  225. if (!dump) {
  226. if (!argc) {
  227. ret = CMD_RET_USAGE;
  228. goto out_put_mtd;
  229. }
  230. user_addr = simple_strtoul(argv[0], NULL, 16);
  231. argc--;
  232. argv++;
  233. }
  234. start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
  235. if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
  236. printf("Offset not aligned with a page (0x%x)\n",
  237. mtd->writesize);
  238. ret = CMD_RET_FAILURE;
  239. goto out_put_mtd;
  240. }
  241. default_len = dump ? mtd->writesize : mtd->size;
  242. len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : default_len;
  243. if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
  244. len = round_up(len, mtd->writesize);
  245. printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
  246. mtd->writesize, len);
  247. }
  248. remaining = len;
  249. npages = mtd_len_to_pages(mtd, len);
  250. oob_len = woob ? npages * mtd->oobsize : 0;
  251. if (dump)
  252. buf = kmalloc(len + oob_len, GFP_KERNEL);
  253. else
  254. buf = map_sysmem(user_addr, 0);
  255. if (!buf) {
  256. printf("Could not map/allocate the user buffer\n");
  257. ret = CMD_RET_FAILURE;
  258. goto out_put_mtd;
  259. }
  260. if (has_pages)
  261. printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n",
  262. read ? "Reading" : "Writing", len, npages, start_off,
  263. raw ? " [raw]" : "", woob ? " [oob]" : "",
  264. !read && write_empty_pages ? " [dontskipff]" : "");
  265. else
  266. printf("%s %lld byte(s) at offset 0x%08llx\n",
  267. read ? "Reading" : "Writing", len, start_off);
  268. io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
  269. io_op.len = has_pages ? mtd->writesize : len;
  270. io_op.ooblen = woob ? mtd->oobsize : 0;
  271. io_op.datbuf = buf;
  272. io_op.oobbuf = woob ? &buf[len] : NULL;
  273. /* Search for the first good block after the given offset */
  274. off = start_off;
  275. while (mtd_block_isbad(mtd, off))
  276. off += mtd->erasesize;
  277. /* Loop over the pages to do the actual read/write */
  278. while (remaining) {
  279. /* Skip the block if it is bad */
  280. if (mtd_is_aligned_with_block_size(mtd, off) &&
  281. mtd_block_isbad(mtd, off)) {
  282. off += mtd->erasesize;
  283. continue;
  284. }
  285. if (read)
  286. ret = mtd_read_oob(mtd, off, &io_op);
  287. else
  288. ret = mtd_special_write_oob(mtd, off, &io_op,
  289. write_empty_pages, woob);
  290. if (ret) {
  291. printf("Failure while %s at offset 0x%llx\n",
  292. read ? "reading" : "writing", off);
  293. break;
  294. }
  295. off += io_op.retlen;
  296. remaining -= io_op.retlen;
  297. io_op.datbuf += io_op.retlen;
  298. io_op.oobbuf += io_op.oobretlen;
  299. }
  300. if (!ret && dump)
  301. mtd_dump_device_buf(mtd, start_off, buf, len, woob);
  302. if (dump)
  303. kfree(buf);
  304. else
  305. unmap_sysmem(buf);
  306. if (ret) {
  307. printf("%s on %s failed with error %d\n",
  308. read ? "Read" : "Write", mtd->name, ret);
  309. ret = CMD_RET_FAILURE;
  310. } else {
  311. ret = CMD_RET_SUCCESS;
  312. }
  313. out_put_mtd:
  314. put_mtd_device(mtd);
  315. return ret;
  316. }
  317. static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
  318. char * const argv[])
  319. {
  320. struct erase_info erase_op = {};
  321. struct mtd_info *mtd;
  322. u64 off, len;
  323. bool scrub;
  324. int ret;
  325. if (argc < 2)
  326. return CMD_RET_USAGE;
  327. mtd = get_mtd_by_name(argv[1]);
  328. if (IS_ERR_OR_NULL(mtd))
  329. return CMD_RET_FAILURE;
  330. scrub = strstr(argv[0], ".dontskipbad");
  331. argc -= 2;
  332. argv += 2;
  333. off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
  334. len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size;
  335. if (!mtd_is_aligned_with_block_size(mtd, off)) {
  336. printf("Offset not aligned with a block (0x%x)\n",
  337. mtd->erasesize);
  338. ret = CMD_RET_FAILURE;
  339. goto out_put_mtd;
  340. }
  341. if (!mtd_is_aligned_with_block_size(mtd, len)) {
  342. printf("Size not a multiple of a block (0x%x)\n",
  343. mtd->erasesize);
  344. ret = CMD_RET_FAILURE;
  345. goto out_put_mtd;
  346. }
  347. printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
  348. off, off + len - 1, mtd_div_by_eb(len, mtd));
  349. erase_op.mtd = mtd;
  350. erase_op.addr = off;
  351. erase_op.len = len;
  352. erase_op.scrub = scrub;
  353. while (erase_op.len) {
  354. ret = mtd_erase(mtd, &erase_op);
  355. /* Abort if its not a bad block error */
  356. if (ret != -EIO)
  357. break;
  358. printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
  359. /* Skip bad block and continue behind it */
  360. erase_op.len -= erase_op.fail_addr - erase_op.addr;
  361. erase_op.len -= mtd->erasesize;
  362. erase_op.addr = erase_op.fail_addr + mtd->erasesize;
  363. }
  364. if (ret && ret != -EIO)
  365. ret = CMD_RET_FAILURE;
  366. else
  367. ret = CMD_RET_SUCCESS;
  368. out_put_mtd:
  369. put_mtd_device(mtd);
  370. return ret;
  371. }
  372. static int do_mtd_bad(cmd_tbl_t *cmdtp, int flag, int argc,
  373. char * const argv[])
  374. {
  375. struct mtd_info *mtd;
  376. loff_t off;
  377. if (argc < 2)
  378. return CMD_RET_USAGE;
  379. mtd = get_mtd_by_name(argv[1]);
  380. if (IS_ERR_OR_NULL(mtd))
  381. return CMD_RET_FAILURE;
  382. if (!mtd_can_have_bb(mtd)) {
  383. printf("Only NAND-based devices can have bad blocks\n");
  384. goto out_put_mtd;
  385. }
  386. printf("MTD device %s bad blocks list:\n", mtd->name);
  387. for (off = 0; off < mtd->size; off += mtd->erasesize) {
  388. if (mtd_block_isbad(mtd, off))
  389. printf("\t0x%08llx\n", off);
  390. }
  391. out_put_mtd:
  392. put_mtd_device(mtd);
  393. return CMD_RET_SUCCESS;
  394. }
  395. #ifdef CONFIG_AUTO_COMPLETE
  396. static int mtd_name_complete(int argc, char * const argv[], char last_char,
  397. int maxv, char *cmdv[])
  398. {
  399. int len = 0, n_found = 0;
  400. struct mtd_info *mtd;
  401. argc--;
  402. argv++;
  403. if (argc > 1 ||
  404. (argc == 1 && (last_char == '\0' || isblank(last_char))))
  405. return 0;
  406. if (argc)
  407. len = strlen(argv[0]);
  408. mtd_for_each_device(mtd) {
  409. if (argc &&
  410. (len > strlen(mtd->name) ||
  411. strncmp(argv[0], mtd->name, len)))
  412. continue;
  413. if (n_found >= maxv - 2) {
  414. cmdv[n_found++] = "...";
  415. break;
  416. }
  417. cmdv[n_found++] = mtd->name;
  418. }
  419. cmdv[n_found] = NULL;
  420. return n_found;
  421. }
  422. #endif /* CONFIG_AUTO_COMPLETE */
  423. #ifdef CONFIG_SYS_LONGHELP
  424. static char mtd_help_text[] =
  425. "- generic operations on memory technology devices\n\n"
  426. "mtd list\n"
  427. "mtd read[.raw][.oob] <name> <addr> [<off> [<size>]]\n"
  428. "mtd dump[.raw][.oob] <name> [<off> [<size>]]\n"
  429. "mtd write[.raw][.oob][.dontskipff] <name> <addr> [<off> [<size>]]\n"
  430. "mtd erase[.dontskipbad] <name> [<off> [<size>]]\n"
  431. "\n"
  432. "Specific functions:\n"
  433. "mtd bad <name>\n"
  434. "\n"
  435. "With:\n"
  436. "\t<name>: NAND partition/chip name\n"
  437. "\t<addr>: user address from/to which data will be retrieved/stored\n"
  438. "\t<off>: offset in <name> in bytes (default: start of the part)\n"
  439. "\t\t* must be block-aligned for erase\n"
  440. "\t\t* must be page-aligned otherwise\n"
  441. "\t<size>: length of the operation in bytes (default: the entire device)\n"
  442. "\t\t* must be a multiple of a block for erase\n"
  443. "\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n"
  444. "\n"
  445. "The .dontskipff option forces writing empty pages, don't use it if unsure.\n";
  446. #endif
  447. U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
  448. U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
  449. U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
  450. mtd_name_complete),
  451. U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
  452. mtd_name_complete),
  453. U_BOOT_SUBCMD_MKENT_COMPLETE(dump, 4, 0, do_mtd_io,
  454. mtd_name_complete),
  455. U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase,
  456. mtd_name_complete),
  457. U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad,
  458. mtd_name_complete));