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 
11 #include <command.h>
12 #include <console.h>
13 #include <led.h>
14 #if CONFIG_IS_ENABLED(CMD_MTD_OTP)
15 #include <hexdump.h>
16 #endif
17 #include <malloc.h>
18 #include <mapmem.h>
19 #include <mtd.h>
20 #include <dm/devres.h>
21 #include <linux/err.h>
22 
23 #include <linux/ctype.h>
24 
get_mtd_by_name(const char * name)25 static struct mtd_info *get_mtd_by_name(const char *name)
26 {
27 	struct mtd_info *mtd;
28 
29 	mtd_probe_devices();
30 
31 	mtd = get_mtd_device_nm(name);
32 	if (IS_ERR_OR_NULL(mtd))
33 		printf("MTD device %s not found, ret %ld\n", name,
34 		       PTR_ERR(mtd));
35 
36 	return mtd;
37 }
38 
mtd_len_to_pages(struct mtd_info * mtd,u64 len)39 static uint mtd_len_to_pages(struct mtd_info *mtd, u64 len)
40 {
41 	do_div(len, mtd->writesize);
42 
43 	return len;
44 }
45 
mtd_is_aligned_with_min_io_size(struct mtd_info * mtd,u64 size)46 static bool mtd_is_aligned_with_min_io_size(struct mtd_info *mtd, u64 size)
47 {
48 	return !do_div(size, mtd->writesize);
49 }
50 
mtd_is_aligned_with_block_size(struct mtd_info * mtd,u64 size)51 static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
52 {
53 	return !do_div(size, mtd->erasesize);
54 }
55 
mtd_dump_buf(const u8 * buf,uint len,uint offset)56 static void mtd_dump_buf(const u8 *buf, uint len, uint offset)
57 {
58 	int i, j;
59 
60 	for (i = 0; i < len; ) {
61 		printf("0x%08x:\t", offset + i);
62 		for (j = 0; j < 8; j++)
63 			printf("%02x ", buf[i + j]);
64 		printf(" ");
65 		i += 8;
66 		for (j = 0; j < 8; j++)
67 			printf("%02x ", buf[i + j]);
68 		printf("\n");
69 		i += 8;
70 	}
71 }
72 
mtd_dump_device_buf(struct mtd_info * mtd,u64 start_off,const u8 * buf,u64 len,bool woob)73 static void mtd_dump_device_buf(struct mtd_info *mtd, u64 start_off,
74 				const u8 *buf, u64 len, bool woob)
75 {
76 	bool has_pages = mtd->type == MTD_NANDFLASH ||
77 		mtd->type == MTD_MLCNANDFLASH;
78 	int npages = mtd_len_to_pages(mtd, len);
79 	uint page;
80 
81 	if (has_pages) {
82 		for (page = 0; page < npages; page++) {
83 			u64 data_off = (u64)page * mtd->writesize;
84 
85 			printf("\nDump %d data bytes from 0x%08llx:\n",
86 			       mtd->writesize, start_off + data_off);
87 			mtd_dump_buf(&buf[data_off],
88 				     mtd->writesize, start_off + data_off);
89 
90 			if (woob) {
91 				u64 oob_off = (u64)page * mtd->oobsize;
92 
93 				printf("Dump %d OOB bytes from page at 0x%08llx:\n",
94 				       mtd->oobsize, start_off + data_off);
95 				mtd_dump_buf(&buf[len + oob_off],
96 					     mtd->oobsize, 0);
97 			}
98 		}
99 	} else {
100 		printf("\nDump %lld data bytes from 0x%llx:\n",
101 		       len, start_off);
102 		mtd_dump_buf(buf, len, start_off);
103 	}
104 }
105 
mtd_show_parts(struct mtd_info * mtd,int level)106 static void mtd_show_parts(struct mtd_info *mtd, int level)
107 {
108 	struct mtd_info *part;
109 	int i;
110 
111 	list_for_each_entry(part, &mtd->partitions, node) {
112 		for (i = 0; i < level; i++)
113 			printf("\t");
114 		printf("  - 0x%012llx-0x%012llx : \"%s\"\n",
115 		       part->offset, part->offset + part->size, part->name);
116 
117 		mtd_show_parts(part, level + 1);
118 	}
119 }
120 
mtd_show_device(struct mtd_info * mtd)121 static void mtd_show_device(struct mtd_info *mtd)
122 {
123 	/* Device */
124 	printf("* %s\n", mtd->name);
125 	if (mtd->dev) {
126 		printf("  - device: %s\n", mtd->dev->name);
127 		printf("  - parent: %s\n", mtd->dev->parent->name);
128 		printf("  - driver: %s\n", mtd->dev->driver->name);
129 	}
130 	if (IS_ENABLED(CONFIG_OF_CONTROL) && mtd->dev) {
131 		char buf[256];
132 		int res;
133 
134 		res = ofnode_get_path(mtd_get_ofnode(mtd), buf, 256);
135 		printf("  - path: %s\n", res == 0 ? buf : "unavailable");
136 	}
137 
138 	/* MTD device information */
139 	printf("  - type: ");
140 	switch (mtd->type) {
141 	case MTD_RAM:
142 		printf("RAM\n");
143 		break;
144 	case MTD_ROM:
145 		printf("ROM\n");
146 		break;
147 	case MTD_NORFLASH:
148 		printf("NOR flash\n");
149 		break;
150 	case MTD_NANDFLASH:
151 		printf("NAND flash\n");
152 		break;
153 	case MTD_DATAFLASH:
154 		printf("Data flash\n");
155 		break;
156 	case MTD_UBIVOLUME:
157 		printf("UBI volume\n");
158 		break;
159 	case MTD_MLCNANDFLASH:
160 		printf("MLC NAND flash\n");
161 		break;
162 	case MTD_ABSENT:
163 	default:
164 		printf("Unknown\n");
165 		break;
166 	}
167 
168 	printf("  - block size: 0x%x bytes\n", mtd->erasesize);
169 	printf("  - min I/O: 0x%x bytes\n", mtd->writesize);
170 
171 	if (mtd->oobsize) {
172 		printf("  - OOB size: %u bytes\n", mtd->oobsize);
173 		printf("  - OOB available: %u bytes\n", mtd->oobavail);
174 	}
175 
176 	if (mtd->ecc_strength) {
177 		printf("  - ECC strength: %u bits\n", mtd->ecc_strength);
178 		printf("  - ECC step size: %u bytes\n", mtd->ecc_step_size);
179 		printf("  - bitflip threshold: %u bits\n",
180 		       mtd->bitflip_threshold);
181 	}
182 
183 	printf("  - 0x%012llx-0x%012llx : \"%s\"\n",
184 	       mtd->offset, mtd->offset + mtd->size, mtd->name);
185 
186 	/* MTD partitions, if any */
187 	mtd_show_parts(mtd, 1);
188 }
189 
190 /* Logic taken from fs/ubifs/recovery.c:is_empty() */
mtd_oob_write_is_empty(struct mtd_oob_ops * op)191 static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op)
192 {
193 	int i;
194 
195 	for (i = 0; i < op->len; i++)
196 		if (op->datbuf[i] != 0xff)
197 			return false;
198 
199 	for (i = 0; i < op->ooblen; i++)
200 		if (op->oobbuf[i] != 0xff)
201 			return false;
202 
203 	return true;
204 }
205 
206 #if CONFIG_IS_ENABLED(CMD_MTD_OTP)
do_mtd_otp_read(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])207 static int do_mtd_otp_read(struct cmd_tbl *cmdtp, int flag, int argc,
208 			   char *const argv[])
209 {
210 	struct mtd_info *mtd;
211 	size_t retlen;
212 	off_t from;
213 	size_t len;
214 	bool user;
215 	int ret;
216 	u8 *buf;
217 
218 	if (argc != 5)
219 		return CMD_RET_USAGE;
220 
221 	if (!strcmp(argv[2], "u"))
222 		user = true;
223 	else if (!strcmp(argv[2], "f"))
224 		user = false;
225 	else
226 		return CMD_RET_USAGE;
227 
228 	mtd = get_mtd_by_name(argv[1]);
229 	if (IS_ERR_OR_NULL(mtd))
230 		return CMD_RET_FAILURE;
231 
232 	from = simple_strtoul(argv[3], NULL, 0);
233 	len = simple_strtoul(argv[4], NULL, 0);
234 
235 	ret = CMD_RET_FAILURE;
236 
237 	buf = malloc(len);
238 	if (!buf)
239 		goto put_mtd;
240 
241 	printf("Reading %s OTP from 0x%lx, %zu bytes\n",
242 	       user ? "user" : "factory", from, len);
243 
244 	if (user)
245 		ret = mtd_read_user_prot_reg(mtd, from, len, &retlen, buf);
246 	else
247 		ret = mtd_read_fact_prot_reg(mtd, from, len, &retlen, buf);
248 	if (ret) {
249 		free(buf);
250 		pr_err("OTP read failed: %d\n", ret);
251 		ret = CMD_RET_FAILURE;
252 		goto put_mtd;
253 	}
254 
255 	if (retlen != len)
256 		pr_err("OTP read returns %zu, but %zu expected\n",
257 		       retlen, len);
258 
259 	print_hex_dump("", 0, 16, 1, buf, retlen, true);
260 
261 	free(buf);
262 
263 	ret = CMD_RET_SUCCESS;
264 
265 put_mtd:
266 	put_mtd_device(mtd);
267 
268 	return ret;
269 }
270 
do_mtd_otp_lock(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])271 static int do_mtd_otp_lock(struct cmd_tbl *cmdtp, int flag, int argc,
272 			   char *const argv[])
273 {
274 	struct mtd_info *mtd;
275 	off_t from;
276 	size_t len;
277 	int ret;
278 
279 	if (argc != 4)
280 		return CMD_RET_USAGE;
281 
282 	mtd = get_mtd_by_name(argv[1]);
283 	if (IS_ERR_OR_NULL(mtd))
284 		return CMD_RET_FAILURE;
285 
286 	from = simple_strtoul(argv[2], NULL, 0);
287 	len = simple_strtoul(argv[3], NULL, 0);
288 
289 	ret = mtd_lock_user_prot_reg(mtd, from, len);
290 	if (ret) {
291 		pr_err("OTP lock failed: %d\n", ret);
292 		ret = CMD_RET_FAILURE;
293 		goto put_mtd;
294 	}
295 
296 	ret = CMD_RET_SUCCESS;
297 
298 put_mtd:
299 	put_mtd_device(mtd);
300 
301 	return ret;
302 }
303 
do_mtd_otp_write(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])304 static int do_mtd_otp_write(struct cmd_tbl *cmdtp, int flag, int argc,
305 			    char *const argv[])
306 {
307 	struct mtd_info *mtd;
308 	size_t retlen;
309 	size_t binlen;
310 	u8 *binbuf;
311 	off_t from;
312 	int ret;
313 
314 	if (argc != 4)
315 		return CMD_RET_USAGE;
316 
317 	mtd = get_mtd_by_name(argv[1]);
318 	if (IS_ERR_OR_NULL(mtd))
319 		return CMD_RET_FAILURE;
320 
321 	from = simple_strtoul(argv[2], NULL, 0);
322 	binlen = strlen(argv[3]) / 2;
323 
324 	ret = CMD_RET_FAILURE;
325 	binbuf = malloc(binlen);
326 	if (!binbuf)
327 		goto put_mtd;
328 
329 	hex2bin(binbuf, argv[3], binlen);
330 
331 	printf("Will write:\n");
332 
333 	print_hex_dump("", 0, 16, 1, binbuf, binlen, true);
334 
335 	printf("to 0x%lx\n", from);
336 
337 	printf("Continue (y/n)?\n");
338 
339 	if (confirm_yesno() != 1) {
340 		pr_err("OTP write canceled\n");
341 		ret = CMD_RET_SUCCESS;
342 		goto put_mtd;
343 	}
344 
345 	ret = mtd_write_user_prot_reg(mtd, from, binlen, &retlen, binbuf);
346 	if (ret) {
347 		pr_err("OTP write failed: %d\n", ret);
348 		ret = CMD_RET_FAILURE;
349 		goto put_mtd;
350 	}
351 
352 	if (retlen != binlen)
353 		pr_err("OTP write returns %zu, but %zu expected\n",
354 		       retlen, binlen);
355 
356 	ret = CMD_RET_SUCCESS;
357 
358 put_mtd:
359 	free(binbuf);
360 	put_mtd_device(mtd);
361 
362 	return ret;
363 }
364 
do_mtd_otp_info(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])365 static int do_mtd_otp_info(struct cmd_tbl *cmdtp, int flag, int argc,
366 			   char *const argv[])
367 {
368 	struct otp_info otp_info;
369 	struct mtd_info *mtd;
370 	size_t retlen;
371 	bool user;
372 	int ret;
373 
374 	if (argc != 3)
375 		return CMD_RET_USAGE;
376 
377 	if (!strcmp(argv[2], "u"))
378 		user = true;
379 	else if (!strcmp(argv[2], "f"))
380 		user = false;
381 	else
382 		return CMD_RET_USAGE;
383 
384 	mtd = get_mtd_by_name(argv[1]);
385 	if (IS_ERR_OR_NULL(mtd))
386 		return CMD_RET_FAILURE;
387 
388 	if (user)
389 		ret = mtd_get_user_prot_info(mtd, sizeof(otp_info), &retlen,
390 					     &otp_info);
391 	else
392 		ret = mtd_get_fact_prot_info(mtd, sizeof(otp_info), &retlen,
393 					     &otp_info);
394 	if (ret) {
395 		pr_err("OTP info failed: %d\n", ret);
396 		ret = CMD_RET_FAILURE;
397 		goto put_mtd;
398 	}
399 
400 	if (retlen != sizeof(otp_info)) {
401 		pr_err("OTP info returns %zu, but %zu expected\n",
402 		       retlen, sizeof(otp_info));
403 		ret = CMD_RET_FAILURE;
404 		goto put_mtd;
405 	}
406 
407 	printf("%s OTP region info:\n", user ? "User" : "Factory");
408 	printf("\tstart: %u\n", otp_info.start);
409 	printf("\tlength: %u\n", otp_info.length);
410 	printf("\tlocked: %u\n", otp_info.locked);
411 
412 	ret = CMD_RET_SUCCESS;
413 
414 put_mtd:
415 	put_mtd_device(mtd);
416 
417 	return ret;
418 }
419 #endif
420 
do_mtd_list(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])421 static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
422 		       char *const argv[])
423 {
424 	struct mtd_info *mtd;
425 	int dev_nb = 0;
426 
427 	/* Ensure all devices (and their partitions) are probed */
428 	mtd_probe_devices();
429 
430 	printf("List of MTD devices:\n");
431 	mtd_for_each_device(mtd) {
432 		if (!mtd_is_partition(mtd))
433 			mtd_show_device(mtd);
434 
435 		dev_nb++;
436 	}
437 
438 	if (!dev_nb) {
439 		printf("No MTD device found\n");
440 		return CMD_RET_FAILURE;
441 	}
442 
443 	return CMD_RET_SUCCESS;
444 }
445 
mtd_special_write_oob(struct mtd_info * mtd,u64 off,struct mtd_oob_ops * io_op,bool write_empty_pages,bool woob)446 static int mtd_special_write_oob(struct mtd_info *mtd, u64 off,
447 				 struct mtd_oob_ops *io_op,
448 				 bool write_empty_pages, bool woob)
449 {
450 	int ret = 0;
451 
452 	/*
453 	 * By default, do not write an empty page.
454 	 * Skip it by simulating a successful write.
455 	 */
456 	if (!write_empty_pages && mtd_oob_write_is_empty(io_op)) {
457 		io_op->retlen = mtd->writesize;
458 		io_op->oobretlen = woob ? mtd->oobsize : 0;
459 	} else {
460 		ret = mtd_write_oob(mtd, off, io_op);
461 	}
462 
463 	return ret;
464 }
465 
do_mtd_io(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])466 static int do_mtd_io(struct cmd_tbl *cmdtp, int flag, int argc,
467 		     char *const argv[])
468 {
469 	bool dump, read, raw, woob, write_empty_pages, has_pages = false;
470 	u64 start_off, off, len, remaining, default_len;
471 	struct mtd_oob_ops io_op = {};
472 	uint user_addr = 0, npages;
473 	const char *cmd = argv[0];
474 	struct mtd_info *mtd;
475 	u32 oob_len;
476 	u8 *buf;
477 	int ret;
478 
479 	if (argc < 2)
480 		return CMD_RET_USAGE;
481 
482 	mtd = get_mtd_by_name(argv[1]);
483 	if (IS_ERR_OR_NULL(mtd))
484 		return CMD_RET_FAILURE;
485 
486 	if (mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH)
487 		has_pages = true;
488 
489 	dump = !strncmp(cmd, "dump", 4);
490 	read = dump || !strncmp(cmd, "read", 4);
491 	raw = strstr(cmd, ".raw");
492 	woob = strstr(cmd, ".oob");
493 	write_empty_pages = !has_pages || strstr(cmd, ".dontskipff");
494 
495 	argc -= 2;
496 	argv += 2;
497 
498 	if (!dump) {
499 		if (!argc) {
500 			ret = CMD_RET_USAGE;
501 			goto out_put_mtd;
502 		}
503 
504 		user_addr = hextoul(argv[0], NULL);
505 		argc--;
506 		argv++;
507 	}
508 
509 	start_off = argc > 0 ? hextoul(argv[0], NULL) : 0;
510 	if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
511 		printf("Offset not aligned with a page (0x%x)\n",
512 		       mtd->writesize);
513 		ret = CMD_RET_FAILURE;
514 		goto out_put_mtd;
515 	}
516 
517 	default_len = dump ? mtd->writesize : mtd->size;
518 	len = argc > 1 ? hextoul(argv[1], NULL) : default_len;
519 	if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
520 		len = round_up(len, mtd->writesize);
521 		printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
522 		       mtd->writesize, len);
523 	}
524 
525 	remaining = len;
526 	npages = mtd_len_to_pages(mtd, len);
527 	oob_len = woob ? npages * mtd->oobsize : 0;
528 
529 	if (dump)
530 		buf = kmalloc(len + oob_len, GFP_KERNEL);
531 	else
532 		buf = map_sysmem(user_addr, 0);
533 
534 	if (!buf) {
535 		printf("Could not map/allocate the user buffer\n");
536 		ret = CMD_RET_FAILURE;
537 		goto out_put_mtd;
538 	}
539 
540 	if (has_pages)
541 		printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n",
542 		       read ? "Reading" : "Writing", len, npages, start_off,
543 		       raw ? " [raw]" : "", woob ? " [oob]" : "",
544 		       !read && write_empty_pages ? " [dontskipff]" : "");
545 	else
546 		printf("%s %lld byte(s) at offset 0x%08llx\n",
547 		       read ? "Reading" : "Writing", len, start_off);
548 
549 	io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
550 	io_op.len = has_pages ? mtd->writesize : len;
551 	io_op.ooblen = woob ? mtd->oobsize : 0;
552 	io_op.datbuf = buf;
553 	io_op.oobbuf = woob ? &buf[len] : NULL;
554 
555 	/* Search for the first good block after the given offset */
556 	off = start_off;
557 	while (mtd_block_isbad(mtd, off))
558 		off += mtd->erasesize;
559 
560 	led_activity_blink();
561 
562 	/* Loop over the pages to do the actual read/write */
563 	while (remaining) {
564 		/* Skip the block if it is bad */
565 		if (mtd_is_aligned_with_block_size(mtd, off) &&
566 		    mtd_block_isbad(mtd, off)) {
567 			off += mtd->erasesize;
568 			continue;
569 		}
570 
571 		if (read)
572 			ret = mtd_read_oob(mtd, off, &io_op);
573 		else
574 			ret = mtd_special_write_oob(mtd, off, &io_op,
575 						    write_empty_pages, woob);
576 
577 		if (ret) {
578 			printf("Failure while %s at offset 0x%llx\n",
579 			       read ? "reading" : "writing", off);
580 			break;
581 		}
582 
583 		off += io_op.retlen;
584 		remaining -= io_op.retlen;
585 		io_op.datbuf += io_op.retlen;
586 		io_op.oobbuf += io_op.oobretlen;
587 	}
588 
589 	led_activity_off();
590 
591 	if (!ret && dump)
592 		mtd_dump_device_buf(mtd, start_off, buf, len, woob);
593 
594 	if (dump)
595 		kfree(buf);
596 	else
597 		unmap_sysmem(buf);
598 
599 	if (ret) {
600 		printf("%s on %s failed with error %d\n",
601 		       read ? "Read" : "Write", mtd->name, ret);
602 		ret = CMD_RET_FAILURE;
603 	} else {
604 		ret = CMD_RET_SUCCESS;
605 	}
606 
607 out_put_mtd:
608 	put_mtd_device(mtd);
609 
610 	return ret;
611 }
612 
do_mtd_erase(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])613 static int do_mtd_erase(struct cmd_tbl *cmdtp, int flag, int argc,
614 			char *const argv[])
615 {
616 	struct erase_info erase_op = {};
617 	struct mtd_info *mtd;
618 	u64 off, len;
619 	bool scrub;
620 	int ret = 0;
621 
622 	if (argc < 2)
623 		return CMD_RET_USAGE;
624 
625 	mtd = get_mtd_by_name(argv[1]);
626 	if (IS_ERR_OR_NULL(mtd))
627 		return CMD_RET_FAILURE;
628 
629 	scrub = strstr(argv[0], ".dontskipbad");
630 
631 	argc -= 2;
632 	argv += 2;
633 
634 	off = argc > 0 ? hextoul(argv[0], NULL) : 0;
635 	len = argc > 1 ? hextoul(argv[1], NULL) : mtd->size;
636 
637 	if (!mtd_is_aligned_with_block_size(mtd, off)) {
638 		printf("Offset not aligned with a block (0x%x)\n",
639 		       mtd->erasesize);
640 		ret = CMD_RET_FAILURE;
641 		goto out_put_mtd;
642 	}
643 
644 	if (!mtd_is_aligned_with_block_size(mtd, len)) {
645 		printf("Size not a multiple of a block (0x%x)\n",
646 		       mtd->erasesize);
647 		ret = CMD_RET_FAILURE;
648 		goto out_put_mtd;
649 	}
650 
651 	printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
652 	       off, off + len - 1, mtd_div_by_eb(len, mtd));
653 
654 	erase_op.mtd = mtd;
655 	erase_op.addr = off;
656 	erase_op.len = mtd->erasesize;
657 
658 	led_activity_blink();
659 
660 	while (len) {
661 		if (!scrub) {
662 			ret = mtd_block_isbad(mtd, erase_op.addr);
663 			if (ret < 0) {
664 				printf("Failed to get bad block at 0x%08llx\n",
665 				       erase_op.addr);
666 				ret = CMD_RET_FAILURE;
667 				goto out_put_mtd;
668 			}
669 
670 			if (ret > 0) {
671 				printf("Skipping bad block at 0x%08llx\n",
672 				       erase_op.addr);
673 				ret = 0;
674 				len -= mtd->erasesize;
675 				erase_op.addr += mtd->erasesize;
676 				continue;
677 			}
678 		}
679 
680 		ret = mtd_erase(mtd, &erase_op);
681 		if (ret && ret != -EIO)
682 			break;
683 
684 		len -= mtd->erasesize;
685 		erase_op.addr += mtd->erasesize;
686 	}
687 
688 	led_activity_off();
689 
690 	if (ret && ret != -EIO)
691 		ret = CMD_RET_FAILURE;
692 	else
693 		ret = CMD_RET_SUCCESS;
694 
695 out_put_mtd:
696 	put_mtd_device(mtd);
697 
698 	return ret;
699 }
700 
do_mtd_bad(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])701 static int do_mtd_bad(struct cmd_tbl *cmdtp, int flag, int argc,
702 		      char *const argv[])
703 {
704 	struct mtd_info *mtd;
705 	loff_t off;
706 
707 	if (argc < 2)
708 		return CMD_RET_USAGE;
709 
710 	mtd = get_mtd_by_name(argv[1]);
711 	if (IS_ERR_OR_NULL(mtd))
712 		return CMD_RET_FAILURE;
713 
714 	if (!mtd_can_have_bb(mtd)) {
715 		printf("Only NAND-based devices can have bad blocks\n");
716 		goto out_put_mtd;
717 	}
718 
719 	printf("MTD device %s bad blocks list:\n", mtd->name);
720 	for (off = 0; off < mtd->size; off += mtd->erasesize) {
721 		if (mtd_block_isbad(mtd, off))
722 			printf("\t0x%08llx\n", off);
723 	}
724 
725 out_put_mtd:
726 	put_mtd_device(mtd);
727 
728 	return CMD_RET_SUCCESS;
729 }
730 
731 #ifdef CONFIG_AUTO_COMPLETE
mtd_name_complete(int argc,char * const argv[],char last_char,int maxv,char * cmdv[])732 static int mtd_name_complete(int argc, char *const argv[], char last_char,
733 			     int maxv, char *cmdv[])
734 {
735 	int len = 0, n_found = 0;
736 	struct mtd_info *mtd;
737 
738 	argc--;
739 	argv++;
740 
741 	if (argc > 1 ||
742 	    (argc == 1 && (last_char == '\0' || isblank(last_char))))
743 		return 0;
744 
745 	if (argc)
746 		len = strlen(argv[0]);
747 
748 	mtd_for_each_device(mtd) {
749 		if (argc &&
750 		    (len > strlen(mtd->name) ||
751 		     strncmp(argv[0], mtd->name, len)))
752 			continue;
753 
754 		if (n_found >= maxv - 2) {
755 			cmdv[n_found++] = "...";
756 			break;
757 		}
758 
759 		cmdv[n_found++] = mtd->name;
760 	}
761 
762 	cmdv[n_found] = NULL;
763 
764 	return n_found;
765 }
766 #endif /* CONFIG_AUTO_COMPLETE */
767 
768 U_BOOT_LONGHELP(mtd,
769 	"- generic operations on memory technology devices\n\n"
770 	"mtd list\n"
771 	"mtd read[.raw][.oob]                  <name> <addr> [<off> [<size>]]\n"
772 	"mtd dump[.raw][.oob]                  <name>        [<off> [<size>]]\n"
773 	"mtd write[.raw][.oob][.dontskipff]    <name> <addr> [<off> [<size>]]\n"
774 	"mtd erase[.dontskipbad]               <name>        [<off> [<size>]]\n"
775 	"\n"
776 	"Specific functions:\n"
777 	"mtd bad                               <name>\n"
778 #if CONFIG_IS_ENABLED(CMD_MTD_OTP)
779 	"mtd otpread                           <name> [u|f] <off> <size>\n"
780 	"mtd otpwrite                          <name> <off> <hex string>\n"
781 	"mtd otplock                           <name> <off> <size>\n"
782 	"mtd otpinfo                           <name> [u|f]\n"
783 #endif
784 	"\n"
785 	"With:\n"
786 	"\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
787 	"\t<addr>: user address from/to which data will be retrieved/stored\n"
788 	"\t<off>: offset in <name> in bytes (default: start of the part)\n"
789 	"\t\t* must be block-aligned for erase\n"
790 	"\t\t* must be page-aligned otherwise\n"
791 	"\t<size>: length of the operation in bytes (default: the entire device)\n"
792 	"\t\t* must be a multiple of a block for erase\n"
793 	"\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n"
794 #if CONFIG_IS_ENABLED(CMD_MTD_OTP)
795 	"\t<hex string>: hex string without '0x' and spaces. Example: ABCD1234\n"
796 	"\t[u|f]: user or factory OTP region\n"
797 #endif
798 	"\n"
799 	"The .dontskipff option forces writing empty pages, don't use it if unsure.\n");
800 
801 U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
802 #if CONFIG_IS_ENABLED(CMD_MTD_OTP)
803 		U_BOOT_SUBCMD_MKENT(otpread, 5, 1, do_mtd_otp_read),
804 		U_BOOT_SUBCMD_MKENT(otpwrite, 4, 1, do_mtd_otp_write),
805 		U_BOOT_SUBCMD_MKENT(otplock, 4, 1, do_mtd_otp_lock),
806 		U_BOOT_SUBCMD_MKENT(otpinfo, 3, 1, do_mtd_otp_info),
807 #endif
808 		U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
809 		U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
810 					     mtd_name_complete),
811 		U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
812 					     mtd_name_complete),
813 		U_BOOT_SUBCMD_MKENT_COMPLETE(dump, 4, 0, do_mtd_io,
814 					     mtd_name_complete),
815 		U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase,
816 					     mtd_name_complete),
817 		U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad,
818 					     mtd_name_complete));
819