[PATCH] nandwrite: new mtd-utils applet

Denys Vlasenko vda.linux at googlemail.com
Sun Aug 22 17:24:19 UTC 2010


On Wednesday 18 August 2010 14:32, Baruch Siach wrote:
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
>  miscutils/nandwrite.c |  130 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 130 insertions(+), 0 deletions(-)
>  create mode 100644 miscutils/nandwrite.c
> 
> diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
> new file mode 100644
> index 0000000..f5ee0be
> --- /dev/null
> +++ b/miscutils/nandwrite.c
> @@ -0,0 +1,130 @@
> +/*
> + * nandwrite.c - ported to busybox from mtd-utils
> + *
> + * Author: Baruch Siach <baruch at tkos.co.il>, Orex Computed Radiography
> + *
> + * Licensed under GPLv2, see file LICENSE in this source tree.
> + *
> + * TODO: add support for large (>4GB) MTD devices
> + */
> +
> +//applet:IF_NANDWRITE(APPLET(nandwrite, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
> +
> +//kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o
> +
> +//config:config NANDWRITE
> +//config:	bool "nandwrite"
> +//config:	default n
> +//config:	depends on PLATFORM_LINUX
> +//config:	help
> +//config:	  Write to the specified MTD device, with bad blocks awareness
> +
> +#include "libbb.h"
> +#include <mtd/mtd-user.h>
> +
> +#define OPTION_P	(1 << 0)
> +#define OPTION_S	(1 << 1)
> +
> +//usage:#define nandwrite_trivial_usage
> +//usage:	"MTD_DEVICE [-p] [-s ADDR] [INPUTFILE | -]"
> +//usage:#define nandwrite_full_usage "\n\n"
> +//usage:	"Write to the specified MTD device\n"
> +//usage:	"\nOptions:"
> +//usage:	"\n	-p	Pad to page size"
> +//usage:	"\n	-s addr	Set start address (default is 0)"
> +
> +static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo, 
> +		unsigned block_offset)
> +{
> +	loff_t offs = block_offset;
> +
> +	while (1) {
> +		if (block_offset >= meminfo->size)
> +			bb_error_msg_and_die("not enough space in MTD device");
> +		if (xioctl(fd, MEMGETBADBLOCK, &offs)) {

xioctl does not return on error. Maybe you need to use plain
ioctl?

> +			offs += meminfo->erasesize;
> +			printf("Skipping bad block at 0x%08llx\n", offs);
> +		} else
> +			return offs;
> +	}
> +
> +}
> +
> +int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
> +int nandwrite_main(int argc, char **argv)
> +{
> +	unsigned opts = 0;
> +	int opt;
> +	char *mtd_device, *img = NULL;
> +	unsigned mtdoffset = 0, blockstart;
> +	int fd, ifd = STDIN_FILENO;
> +	struct mtd_info_user meminfo;
> +	unsigned char *filebuf;
> +	ssize_t cnt = -1;
> +
> +	/* TODO: switch to getopt32 once it supports strtou */
> +	while ((opt = getopt(argc, argv, "ps:")) != -1) {

Do use getopt32.
and btw, why mtdoffset is not off_t? MTDs can be larger than 4G, right?

> +	argc -= optind;
> +	if (argc < 1 || argc > 2)
> +		bb_show_usage();
> +	mtd_device = argv[optind];
> +	if (argc == 2)
> +		img = argv[optind+1];

I am sure using only argv is smaller code. Something like:

	argv += optind;
	mtd_device = argv[0];
	if (!argv[0] || (argv[1] && argv[2]))
		bb_show_usage();
	if (argv[1])
		img = argv[1];

> +	if (img && strcmp(img, "-") != 0)
> +		ifd = xopen(img, O_RDONLY);

Use xopen_stdin() - you can drop check for "-" then.

> +	filebuf = xmalloc(meminfo.writesize);
> +
> +	while (mtdoffset < meminfo.size) {
> +		blockstart = mtdoffset & (~meminfo.erasesize + 1);
> +		if (blockstart == mtdoffset) {
> +			/* starting a new eraseblock */
> +			mtdoffset = next_good_eraseblock(fd, &meminfo,
> +					blockstart);
> +			printf("Writing at 0x%08x\n", mtdoffset);
> +		}
> +
> +		/* get some more data from input */
> +		cnt = full_read(ifd, filebuf, meminfo.writesize);
> +		if (cnt == 0)
> +			break; /* we are done */
> +		if (cnt < meminfo.writesize && !(opts & OPTION_P))
> +			bb_error_msg_and_die("Unexpected EOF, "
> +					"use padding");
> +
> +		xlseek(fd, mtdoffset, SEEK_SET);
> +		xwrite(fd, filebuf, meminfo.writesize);

Where's the zero-padding for cnt < meminfo.writesize and -p case?

> +		mtdoffset += meminfo.writesize;
> +	}


-- 
vda


More information about the busybox mailing list