/*
 * nandwrite and nanddump ported to busybox from mtd-utils
 *
 * Author: Baruch Siach <baruch@tkos.co.il>, Orex Computed Radiography
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 *
 * TODO: add support for large (>4GB) MTD devices
 */

//config:config NANDWRITE
//config:	bool "nandwrite"
//config:	default y
//config:	select PLATFORM_LINUX
//config:	help
//config:	  Write to the specified MTD device, with bad blocks awareness
//config:
//config:config NANDDUMP
//config:	bool "nanddump"
//config:	default y
//config:	select PLATFORM_LINUX
//config:	help
//config:	  Dump the content of raw NAND chip

//applet:IF_NANDWRITE(APPLET(nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP))
//applet:IF_NANDDUMP(APPLET_ODDNAME(nanddump, nandwrite, BB_DIR_USR_SBIN, BB_SUID_DROP, nanddump))

//kbuild:lib-$(CONFIG_NANDWRITE) += nandwrite.o
//kbuild:lib-$(CONFIG_NANDDUMP) += nandwrite.o

//usage:#define nandwrite_trivial_usage
//usage:	"[-p] [-s ADDR] MTD_DEVICE [FILE]"
//usage:#define nandwrite_full_usage "\n\n"
//usage:	"Write to MTD_DEVICE\n"
//usage:     "\n	-p	Pad to page size"
//usage:     "\n	-s ADDR	Start address"

//usage:#define nanddump_trivial_usage
//usage:	"[-o] [-b] [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE"
//usage:#define nanddump_full_usage "\n\n"
//usage:	"Dump MTD_DEVICE\n"
//usage:     "\n	-o	Dump oob data"
//usage:     "\n	-b	Omit bad block from the dump"
//usage:     "\n	-s ADDR	Start address"
//usage:     "\n	-l LEN	Length"
//usage:     "\n	-f FILE	Dump to file ('-' for stdout)"

#include "libbb.h"
#include <mtd/mtd-user.h>

#define IS_NANDDUMP  (ENABLE_NANDDUMP && (!ENABLE_NANDWRITE || (applet_name[4] == 'd')))
#define IS_NANDWRITE (ENABLE_NANDWRITE && (!ENABLE_NANDDUMP || (applet_name[4] != 'd')))

#define OPT_p  (1 << 0) /* nandwrite only */
#define OPT_o  (1 << 0) /* nanddump only */
#define OPT_s  (1 << 1)
#define OPT_b  (1 << 2)
#define OPT_f  (1 << 3)
#define OPT_l  (1 << 4)

/* helper for writing out 0xff for bad blocks pad */
static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
{
	unsigned char buf[meminfo->writesize];
	unsigned count;

	/* round len to the next page */
	len = (len | ~(meminfo->writesize - 1)) + 1;

	memset(buf, 0xff, sizeof(buf));
	for (count = 0; count < len; count += meminfo->writesize) {
		xwrite(STDOUT_FILENO, buf, meminfo->writesize);
		if (oob)
			xwrite(STDOUT_FILENO, buf, meminfo->oobsize);
	}
}

static unsigned next_good_eraseblock(int fd, struct mtd_info_user *meminfo,
		unsigned block_offset)
{
	while (1) {
		loff_t offs;

		if (block_offset >= meminfo->size) {
			if (IS_NANDWRITE)
				bb_error_msg_and_die("not enough space in MTD device");
			return block_offset; /* let the caller exit */
		}
		offs = block_offset;
		if (xioctl(fd, MEMGETBADBLOCK, &offs) == 0)
			return block_offset;
		/* ioctl returned 1 => "bad block" */
		if (IS_NANDWRITE)
			printf("Skipping bad block at 0x%08x\n", block_offset);
		block_offset += meminfo->erasesize;
	}
}

int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int nandwrite_main(int argc UNUSED_PARAM, char **argv)
{
	/* Buffer for OOB data */
	unsigned char *oobbuf;
	unsigned opts;
	int fd;
	ssize_t cnt;
	unsigned mtdoffset, meminfo_writesize, blockstart, limit;
	unsigned end_addr = ~0;
	struct mtd_info_user meminfo;
	struct mtd_oob_buf oob;
	unsigned char *filebuf;
	const char *opt_s = "0", *opt_f = "-", *opt_l;

	if (IS_NANDDUMP) {
		opt_complementary = "=1";
		opts = getopt32(argv, "os:bf:l:", &opt_s, &opt_f, &opt_l);
	} else { /* nandwrite */
		opt_complementary = "-1:?2";
		opts = getopt32(argv, "ps:", &opt_s);
	}
	argv += optind;

	if (IS_NANDWRITE && argv[1])
		opt_f = argv[1];
	if (!LONE_DASH(opt_f)) {
		int tmp_fd = xopen(opt_f,
			IS_NANDDUMP ? O_WRONLY | O_TRUNC | O_CREAT : O_RDONLY
		);
		xmove_fd(tmp_fd, IS_NANDDUMP ? STDOUT_FILENO : STDIN_FILENO);
	}

	fd = xopen(argv[0], IS_NANDWRITE ? O_RDWR : O_RDONLY);
	xioctl(fd, MEMGETINFO, &meminfo);

	mtdoffset = xstrtou(opt_s, 0);
	if (IS_NANDDUMP && (opts & OPT_l)) {
		unsigned length = xstrtou(opt_l, 0);
		if (length < meminfo.size - mtdoffset)
			end_addr = mtdoffset + length;
	}

	/* Pull it into a CPU register (hopefully) - smaller code that way */
	meminfo_writesize = meminfo.writesize;

	if (mtdoffset & (meminfo_writesize - 1))
		bb_error_msg_and_die("start address is not page aligned");

	filebuf = xmalloc(meminfo_writesize);
	oobbuf = xmalloc(meminfo.oobsize);

	oob.start  = 0;
	oob.length = meminfo.oobsize;
	oob.ptr    = oobbuf;

	blockstart = mtdoffset & ~(meminfo.erasesize - 1);
	if (blockstart != mtdoffset) {
		unsigned tmp;
		/* mtdoffset is in the middle of an erase block, verify that
		 * this block is OK. Advance mtdoffset only if this block is
		 * bad.
		 */
		tmp = next_good_eraseblock(fd, &meminfo, blockstart);
		if (tmp != blockstart) {
			/* bad block(s), advance mtdoffset */
			if (IS_NANDDUMP && !(opts & OPT_b)) {
				int bad_len = MIN(tmp, end_addr) - mtdoffset;
				dump_bad(&meminfo, bad_len, opts & OPT_o);
			}
			mtdoffset = tmp;
		}
	}

	cnt = -1;
	limit = MIN(meminfo.size, end_addr);
	while (mtdoffset < limit) {
		int input_fd = IS_NANDWRITE ? STDIN_FILENO : fd;
		int output_fd = IS_NANDWRITE ? fd : STDOUT_FILENO;

		blockstart = mtdoffset & ~(meminfo.erasesize - 1);
		if (blockstart == mtdoffset) {
			/* starting a new eraseblock */
			mtdoffset = next_good_eraseblock(fd, &meminfo, blockstart);
			if (IS_NANDWRITE)
				printf("Writing at 0x%08x\n", mtdoffset);
			else if (mtdoffset > blockstart && !(opts & OPT_b)) {
				int bad_len = MIN(mtdoffset, limit) - blockstart;
				dump_bad(&meminfo, bad_len, opts & OPT_o);
			}
			if (mtdoffset >= limit)
				break;
		}
		xlseek(fd, mtdoffset, SEEK_SET);

		/* get some more data from input */
		cnt = full_read(input_fd, filebuf, meminfo_writesize);
		if (cnt == 0) {
			/* even with -p, we do not pad past the end of input
			 * (-p only zero-pads last incomplete page)
			 */
			break;
		}
		if (cnt < (ssize_t) meminfo_writesize) {
			if (IS_NANDDUMP)
				bb_error_msg_and_die("short read");
			if (!(opts & OPT_p))
				bb_error_msg_and_die("input size is not rounded up to page size, "
						"use -p to zero pad");
			/* zero pad to end of write block */
			memset(filebuf + cnt, 0, meminfo_writesize - cnt);
		}
		xwrite(output_fd, filebuf, meminfo_writesize);

		if (IS_NANDDUMP && (opts & OPT_o)) {
			/* Dump OOB data */
			oob.start = mtdoffset;
			xioctl(fd, MEMREADOOB, &oob);
			xwrite(output_fd, oobbuf, meminfo.oobsize);
		}

		mtdoffset += meminfo_writesize;
		if (cnt < (ssize_t) meminfo_writesize)
			break;
	}

	if (IS_NANDWRITE && cnt != 0) {
		/* We filled entire MTD, but did we reach EOF on input? */
		if (full_read(STDIN_FILENO, filebuf, meminfo_writesize) != 0) {
			/* no */
			bb_error_msg_and_die("not enough space in MTD device");
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP) {
		free(filebuf);
		close(fd);
	}

	return EXIT_SUCCESS;
}
