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);
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.