public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Boris Brezillon <boris.brezillon@bootlin.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 20/21] cmd: mtd: add 'mtd' command
Date: Thu, 12 Jul 2018 00:42:13 +0200	[thread overview]
Message-ID: <20180712004213.71286527@bbrezillon> (raw)
In-Reply-To: <20180711152529.24547-21-miquel.raynal@bootlin.com>

On Wed, 11 Jul 2018 17:25:28 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> +
> +static void mtd_show_device(struct mtd_info *mtd)
> +{
> +	printf("* %s", mtd->name);

Printing the device type might be interesting? And maybe also the size,
writesize, oobsize and erasesize?

> +	if (mtd->dev)
> +		printf(" [device: %s] [parent: %s] [driver: %s]",
> +		       mtd->dev->name, mtd->dev->parent->name,
> +		       mtd->dev->driver->name);
> +
> +	printf("\n");
> +}


> +static int do_mtd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	struct mtd_info *mtd;
> +	const char *cmd;
> +	char *mtdname;
> +	int ret;
> +
> +	/* All MTD commands need at least two arguments */
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	/* Parse the command name and its optional suffixes */
> +	cmd = argv[1];
> +
> +	/* List the MTD devices if that is what the user wants */
> +	if (strcmp(cmd, "list") == 0)
> +		return do_mtd_list();
> +
> +	/*
> +	 * The remaining commands require also at least a device ID.
> +	 * Check the selected device is valid. Ensure it is probed.
> +	 */
> +	if (argc < 3)
> +		return CMD_RET_USAGE;
> +
> +	mtdname = argv[2];
> +	mtd = get_mtd_device_nm(mtdname);
> +	if (IS_ERR_OR_NULL(mtd)) {
> +		mtd_probe_devices_dm();
> +		mtd = get_mtd_device_nm(mtdname);
> +		if (IS_ERR_OR_NULL(mtd)) {
> +			printf("MTD device %s not found, ret %ld\n",
> +			       mtdname, PTR_ERR(mtd));
> +			return 1;
> +		}
> +	}
> +
> +	argc -= 3;
> +	argv += 3;
> +
> +	/* Do the parsing */
> +	if (!strncmp(cmd, "read", 4) || !strncmp(cmd, "dump", 4) ||
> +	    !strncmp(cmd, "write", 5)) {
> +		struct mtd_oob_ops io_op = {};
> +		bool dump, read, raw, woob;
> +		uint user_addr = 0;
> +		uint nb_pages;
> +		u8 *buf;
> +		u64 off, len;
> +		u32 oob_len;
> +
> +		dump = !strncmp(cmd, "dump", 4);
> +		read = dump || !strncmp(cmd, "read", 4);
> +		raw = strstr(cmd, ".raw");
> +		woob = strstr(cmd, ".oob");
> +
> +		if (!dump) {
> +			if (!argc)
> +				return CMD_RET_USAGE;
> +
> +			user_addr = simple_strtoul(argv[0], NULL, 16);
> +			argc--;
> +			argv++;
> +		}
> +
> +		off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
> +		len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->writesize;
> +		nb_pages = mtd_len_to_pages(mtd, len);
> +		oob_len = woob ? nb_pages * mtd->oobsize : 0;
> +
> +		if ((u32)off % mtd->writesize) {
> +			printf("Offset not aligned with a page (0x%x)\n",
> +			       mtd->writesize);
> +			return -EINVAL;
> +		}
> +
> +		if ((u32)len % mtd->writesize) {
> +			printf("Size not a multiple of a page (0x%x)\n",
> +			       mtd->writesize);
> +			return -EINVAL;
> +		}
> +
> +		if (dump)
> +			buf = kmalloc(len + oob_len, GFP_KERNEL);
> +		else
> +			buf = map_sysmem(user_addr, 0);
> +
> +		if (!buf) {
> +			printf("Could not map/allocate the user buffer\n");
> +			return -ENOMEM;
> +		}
> +
> +		printf("%s %lldB (%d page(s)) at offset 0x%08llx%s%s\n",
> +		       read ? "Reading" : "Writing", len, nb_pages, off,
> +		       raw ? " [raw]" : "", woob ? " [oob]" : "");
> +
> +		io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
> +		io_op.len = len;
> +		io_op.ooblen = oob_len;
> +		io_op.datbuf = buf;
> +		io_op.oobbuf = woob ? &buf[len] : NULL;
> +
> +		if (read)
> +			ret = mtd_read_oob(mtd, off, &io_op);
> +		else
> +			ret = mtd_write_oob(mtd, off, &io_op);
> +
> +		if (ret) {
> +			printf("%s on %s failed with error %d\n",
> +			       read ? "Read" : "Write", mtd->name, ret);
> +			return ret;
> +		}
> +
> +		if (dump) {
> +			uint page;
> +
> +			for (page = 0; page < nb_pages; page++) {
> +				u64 data_off = page * mtd->writesize;
> +				printf("\nDump %d data bytes from 0x%08llx:\n",
> +				       mtd->writesize, data_off);
> +				mtd_dump_buf(buf, mtd->writesize, data_off);
> +
> +				if (woob) {
> +					u64 oob_off = page * mtd->oobsize;
> +					printf("Dump %d OOB bytes from page at 0x%08llx:\n",
> +					       mtd->oobsize, data_off);
> +					mtd_dump_buf(&buf[len + oob_off],
> +						     mtd->oobsize, 0);
> +				}
> +			}
> +		}
> +
> +		if (dump)
> +			kfree(buf);
> +		else
> +			unmap_sysmem(buf);
> +
> +	} else if (!strcmp(cmd, "erase")) {
> +		bool scrub = strstr(cmd, ".dontskipbad");
> +		bool full_erase = strstr(cmd, ".chip");

Again, I think .chip extension is not needed. Just consider a full erase
is requested when offset and length are not provided. Plus, chip is
misleading since I guess mtd partitions are also exposed as mtd devices,
and could thus be erased with the .chip extension as well.

> +		struct erase_info erase_op = {};
> +		u64 off, len;
> +
> +		off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
> +		len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->erasesize;

Hm. Are we sure we want the default to be 1 eraseblock? Shouldn't we
consider that missing size means "erase up to the MTD device end". Same
goes for the read/write accesses, but maybe not for dump where dumping
a single page makes more sense.

> +
> +		if (full_erase) {
> +			off = 0;
> +			len = mtd->size;
> +		}
> +
> +		if ((u32)off % mtd->erasesize) {

Sounds dangerous. We have 8GB NANDs on sunxi platforms...

> +			printf("Offset not aligned with a block (0x%x)\n",
> +			       mtd->erasesize);
> +			return -EINVAL;
> +		}
> +
> +		if ((u32)len % mtd->erasesize) {

Same here. I guess there's a do_div() in uboot.

> +			printf("Size not a multiple of a block (0x%x)\n",
> +			       mtd->erasesize);
> +			return -EINVAL;
> +		}
> +
> +		erase_op.mtd = mtd;
> +		erase_op.addr = off;
> +		erase_op.len = len;
> +		erase_op.scrub = scrub;
> +
> +		ret = mtd_erase(mtd, &erase_op);
> +	} else {
> +		return CMD_RET_USAGE;
> +	}
> +
> +	return ret;
> +}
> +
> +static char mtd_help_text[] =
> +#ifdef CONFIG_SYS_LONGHELP
> +	"- generic operations on memory technology devices\n\n"
> +	"mtd list\n"
> +	"mtd read[.raw][.oob]           <name> <addr> [<off> [<size>]]\n"
> +	"mtd dump[.raw][.oob]           <name>        [<off> [<size>]]\n"
> +	"mtd write[.raw][.oob]          <name> <addr> [<off> [<size>]]\n"
> +	"mtd erase[.chip][.dontskipbad] <name>        [<off> [<size>]]\n"
> +	"\n"
> +	"With:\n"
> +	"\t<name>: NAND partition/chip name\n"
> +	"\t<addr>: user address from/to which data will be retrieved/stored\n"
> +	"\t<off>: offset in <name> in bytes (default: start of the part)\n"
> +	"\t\t* must be block-aligned for erase\n"
> +	"\t\t* must be page-aligned otherwise\n"
> +	"\t<size>: length of the operation in bytes\n"
> +	"\t\t* must be a multiple of a block for erase (default: 1 block)\n"
> +	"\t\t* must be a multiple of a page otherwise (default: 1 page)\n"
> +#endif
> +	"";
> +
> +U_BOOT_CMD(mtd, 10, 1, do_mtd, "MTD utils", mtd_help_text);

  reply	other threads:[~2018-07-11 22:42 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-11 15:25 [U-Boot] [PATCH v2 00/21] SPI-NAND support Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 01/21] mtd: Fallback to ->_read/write_oob() when ->_read/write() is missing Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 02/21] mtd: Uninline mtd_write_oob and move it to mtdcore.c Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 03/21] mtd: Add sanity checks in mtd_write/read_oob() Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 04/21] mtd: Fallback to ->_read/write() when ->_read/write_oob() is missing Miquel Raynal
2018-07-11 22:20   ` Boris Brezillon
2018-07-12  8:05     ` Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 05/21] mtd: add get/set of_node/flash_node helpers Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 06/21] mtd: fix build issue with includes Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 07/21] mtd: move definitions to enlarge their range Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 08/21] mtd: move all flash categories inside MTD submenu Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 09/21] mtd: move NAND fiels into a raw/ subdirectory Miquel Raynal
2018-07-11 22:23   ` Boris Brezillon
2018-07-11 15:25 ` [U-Boot] [PATCH v2 10/21] mtd: rename nand into rawnand in Kconfig prompt Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 11/21] mtd: nand: Add core infrastructure to deal with NAND devices Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 12/21] mtd: nand: Pass mode information to nand_page_io_req Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 13/21] spi: Extend the core to ease integration of SPI memory controllers Miquel Raynal
2018-07-12 13:27   ` Stefan Roese
2018-07-12 14:46     ` Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 14/21] mtd: nand: Add core infrastructure to support SPI NANDs Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 15/21] mtd: spinand: Add initial support for Micron MT29F2G01ABAGD Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 16/21] mtd: spinand: Add initial support for Winbond W25M02GV Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 17/21] mtd: spinand: Add initial support for the MX35LF1GE4AB chip Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 18/21] mtd: spinand: Add initial support for the MX35LF2GE4AB chip Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 19/21] mtd: uclass: add probe function Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 20/21] cmd: mtd: add 'mtd' command Miquel Raynal
2018-07-11 22:42   ` Boris Brezillon [this message]
2018-07-12 12:51     ` Miquel Raynal
2018-07-12 13:12       ` Miquel Raynal
2018-07-11 15:25 ` [U-Boot] [PATCH v2 21/21] dt-bindings: Add bindings for SPI NAND devices Miquel Raynal
2018-07-11 22:44   ` Boris Brezillon
2018-07-12 12:29     ` Miquel Raynal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180712004213.71286527@bbrezillon \
    --to=boris.brezillon@bootlin.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox