Signed-off-by: Baruch Siach <[email protected]> --- 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 <[email protected]>, 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)) { + 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) { + switch (opt) { + case 'p': + opts |= OPTION_P; + break; + case 's': + mtdoffset = bb_strtou(optarg, NULL, 0); + break; + default: + bb_show_usage(); + break; + } + } + argc -= optind; + if (argc < 1 || argc > 2) + bb_show_usage(); + mtd_device = argv[optind]; + if (argc == 2) + img = argv[optind+1]; + + fd = xopen(mtd_device, O_RDWR); + + xioctl(fd, MEMGETINFO, &meminfo); + + if (mtdoffset & (meminfo.writesize - 1)) + bb_error_msg_and_die("start address is not page aligned"); + + if (img && strcmp(img, "-") != 0) + ifd = xopen(img, O_RDONLY); + + 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); + mtdoffset += meminfo.writesize; + } + + if (cnt != 0) /* didn't reach input EOF */ + bb_error_msg_and_die("not enough space in MTD device"); + + if (ENABLE_FEATURE_CLEAN_UP) { + free(filebuf); + close(ifd); + close(fd); + } + + return EXIT_SUCCESS; +} -- 1.7.1 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
