[OE-core] [PATCH] mtd-utils: 1) extend nativesdk support

Li xin lixin.fnst at cn.fujitsu.com
Fri Jun 26 09:55:30 UTC 2015


2) install bin2nand and nand2bin
taken from:
http://git.infradead.org/mtd-utils.git/tree/3c3674a6e1d3f59554b0ff68ca59be2fd4134e0c:/ubi-utils/old-utils/src

Signed-off-by: Li Xin <lixin.fnst at cn.fujitsu.com>
---
 .../mtd/mtd-utils/add-bin2nand-nand2bin.patch      | 1524 ++++++++++++++++++++
 meta/recipes-devtools/mtd/mtd-utils_git.bb         |    3 +-
 2 files changed, 1526 insertions(+), 1 deletion(-)
 create mode 100644 meta/recipes-devtools/mtd/mtd-utils/add-bin2nand-nand2bin.patch

diff --git a/meta/recipes-devtools/mtd/mtd-utils/add-bin2nand-nand2bin.patch b/meta/recipes-devtools/mtd/mtd-utils/add-bin2nand-nand2bin.patch
new file mode 100644
index 0000000..b3a624e
--- /dev/null
+++ b/meta/recipes-devtools/mtd/mtd-utils/add-bin2nand-nand2bin.patch
@@ -0,0 +1,1524 @@
+diff -Nurp git.org/bin2nand.c git/bin2nand.c
+--- git.org/bin2nand.c	1970-01-01 09:00:00.000000000 +0900
++++ git/bin2nand.c	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,344 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2007
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Oliver Lohmann
++ */
++
++/*
++ * Create a flashable NAND image from a binary image
++ *
++ * History:
++ * 1.0 Initial release (tglx)
++ * 1.1 Understands hex and dec input parameters (tglx)
++ * 1.2 Generates separated OOB data, if needed. (oloh)
++ * 1.3 Padds data/oob to a given size. (oloh)
++ * 1.4 Removed argp because we want to use uClibc.
++ * 1.5 Minor cleanup
++ * 1.6 written variable not initialized (-j did not work) (haver)
++ */
++
++#include <unistd.h>
++#include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <fcntl.h>
++#include <getopt.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <errno.h>
++
++#include "error.h"
++#include "config.h"
++#include "nandecc.h"
++
++#define PROGRAM_VERSION "1.6"
++
++#define CHECK_ENDP(option, endp) do {			\
++	if (*endp) {					\
++		fprintf(stderr,				\
++			"Parse error option \'%s\'. "	\
++			"No correct numeric value.\n"	\
++			, option);			\
++		exit(EXIT_FAILURE);			\
++	}						\
++} while(0)
++
++typedef enum action_t {
++	ACT_NORMAL	    = 0x00000001,
++} action_t;
++
++#define PAGESIZE	2048
++#define PADDING		   0 /* 0 means, do not adjust anything */
++#define BUFSIZE		4096
++
++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
++	"bin2nand - a tool for adding OOB information to a "
++	"binary input file.\n";
++
++static const char *optionsstr =
++"  -c, --copyright          Print copyright informatoin.\n"
++"  -j, --padding=<num>      Padding in Byte/Mi/ki. Default = no padding\n"
++"  -p, --pagesize=<num>     Pagesize in Byte/Mi/ki. Default = 2048\n"
++"  -o, --output=<fname>     Output filename.  Interleaved Data/OOB if\n"
++"                           output-oob not specified.\n"
++"  -q, --output-oob=<fname> Write OOB data in separate file.\n"
++"  -?, --help               Give this help list\n"
++"      --usage              Give a short usage message\n"
++"  -V, --version            Print program version\n";
++
++static const char *usage =
++"Usage: bin2nand [-c?V] [-j <num>] [-p <num>] [-o <fname>] [-q <fname>]\n"
++"            [--copyright] [--padding=<num>] [--pagesize=<num>]\n"
++"            [--output=<fname>] [--output-oob=<fname>] [--help] [--usage]\n"
++"            [--version]\n";
++
++struct option long_options[] = {
++	{ .name = "copyright", .has_arg = 0, .flag = NULL, .val = 'c' },
++	{ .name = "padding", .has_arg = 1, .flag = NULL, .val = 'j' },
++	{ .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' },
++	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
++	{ .name = "output-oob", .has_arg = 1, .flag = NULL, .val = 'q' },
++	{ .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
++	{ .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
++	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
++	{ NULL, 0, NULL, 0}
++};
++
++static const char copyright [] __attribute__((unused)) =
++	"Copyright IBM Corp. 2006";
++
++typedef struct myargs {
++	action_t action;
++
++	size_t pagesize;
++	size_t padding;
++
++	FILE* fp_in;
++	char *file_out_data; /* Either: Data and OOB interleaved
++				or plain data */
++	char *file_out_oob; /* OOB Data only. */
++
++	/* special stuff needed to get additional arguments */
++	char *arg1;
++	char **options;			/* [STRING...] */
++} myargs;
++
++
++static int ustrtoull(const char *cp, char **endp, unsigned int base)
++{
++	unsigned long long res = strtoull(cp, endp, base);
++
++	switch (**endp) {
++	case 'G':
++		res *= 1024;
++	case 'M':
++		res *= 1024;
++	case 'k':
++	case 'K':
++		res *= 1024;
++	/* "Ki", "ki", "Mi" or "Gi" are to be used. */
++		if ((*endp)[1] == 'i')
++			(*endp) += 2;
++	}
++	return res;
++}
++
++static int
++parse_opt(int argc, char **argv, myargs *args)
++{
++	char* endp;
++
++	while (1) {
++		int key;
++
++		key = getopt_long(argc, argv, "cj:p:o:q:?V", long_options, NULL);
++		if (key == -1)
++			break;
++
++		switch (key) {
++			case 'p': /* pagesize */
++				args->pagesize = (size_t)
++					ustrtoull(optarg, &endp, 0);
++				CHECK_ENDP("p", endp);
++				break;
++			case 'j': /* padding */
++				args->padding = (size_t)
++					ustrtoull(optarg, &endp, 0);
++				CHECK_ENDP("j", endp);
++				break;
++			case 'o': /* output */
++				args->file_out_data = optarg;
++				break;
++			case 'q': /* output oob */
++				args->file_out_oob = optarg;
++				break;
++			case '?': /* help */
++				printf("%s", doc);
++				printf("%s", optionsstr);
++				exit(0);
++				break;
++			case 'V':
++				printf("%s\n", PROGRAM_VERSION);
++				exit(0);
++				break;
++			case 'c':
++				printf("%s\n", copyright);
++				exit(0);
++			default:
++				printf("%s", usage);
++				exit(-1);
++		}
++	}
++
++	if (optind < argc) {
++		args->fp_in = fopen(argv[optind++], "rb");
++		if ((args->fp_in) == NULL) {
++			err_quit("Cannot open file %s for input\n",
++				 argv[optind++]);
++		}
++	}
++
++	return 0;
++}
++
++static int
++process_page(uint8_t* buf, size_t pagesize,
++	FILE *fp_data, FILE* fp_oob, size_t* written)
++{
++	int eccpoi, oobsize;
++	size_t i;
++	uint8_t oobbuf[64];
++
++	memset(oobbuf, 0xff, sizeof(oobbuf));
++
++	switch(pagesize) {
++	case 2048: oobsize = 64; eccpoi = 64 / 2; break;
++	case 512:  oobsize = 16; eccpoi = 16 / 2; break;
++	default:
++		err_msg("Unsupported page size: %d\n", pagesize);
++		return -EINVAL;
++	}
++
++	for (i = 0; i < pagesize; i += 256, eccpoi += 3) {
++		oobbuf[eccpoi++] = 0x0;
++		/* Calculate ECC */
++		nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]);
++	}
++
++	/* write data */
++	*written += fwrite(buf, 1, pagesize, fp_data);
++
++	/* either separate oob or interleave with data */
++	if (fp_oob) {
++		i = fwrite(oobbuf, 1, oobsize, fp_oob);
++		if (ferror(fp_oob)) {
++			err_msg("IO error\n");
++			return -EIO;
++		}
++	}
++	else {
++		i = fwrite(oobbuf, 1, oobsize, fp_data);
++		if (ferror(fp_data)) {
++			err_msg("IO error\n");
++			return -EIO;
++		}
++	}
++
++	return 0;
++}
++
++int main (int argc, char** argv)
++{
++	int rc = -1;
++	int res = 0;
++	size_t written = 0, read;
++	myargs args = {
++		.action	  = ACT_NORMAL,
++		.pagesize = PAGESIZE,
++		.padding  = PADDING,
++		.fp_in	  = NULL,
++		.file_out_data = NULL,
++		.file_out_oob = NULL,
++	};
++
++	FILE* fp_out_data = stdout;
++	FILE* fp_out_oob = NULL;
++
++	parse_opt(argc, argv, &args);
++
++	uint8_t* buf = calloc(1, BUFSIZE);
++	if (!buf) {
++		err_quit("Cannot allocate page buffer.\n");
++	}
++
++	if (!args.fp_in) {
++		err_msg("No input image specified!\n");
++		goto err;
++	}
++
++	if (args.file_out_data) {
++		fp_out_data = fopen(args.file_out_data, "wb");
++		if (fp_out_data == NULL) {
++			err_sys("Cannot open file %s for output\n",
++					args.file_out_data);
++			goto err;
++		}
++	}
++
++	if (args.file_out_oob) {
++		fp_out_oob = fopen(args.file_out_oob, "wb");
++		if (fp_out_oob == NULL) {
++			err_sys("Cannot open file %s for output\n",
++					args.file_out_oob);
++			goto err;
++		}
++	}
++
++
++	while(1) {
++		read = fread(buf, 1, args.pagesize, args.fp_in);
++		if (feof(args.fp_in) && read == 0)
++			break;
++
++		if (read < args.pagesize) {
++			err_msg("Image not page aligned\n");
++			goto err;
++		}
++
++		if (ferror(args.fp_in)) {
++			err_msg("Read error\n");
++			goto err;
++		}
++
++		res = process_page(buf, args.pagesize, fp_out_data,
++				fp_out_oob, &written);
++		if (res != 0)
++			goto err;
++	}
++
++	while (written < args.padding) {
++		memset(buf, 0xff, args.pagesize);
++		res = process_page(buf, args.pagesize, fp_out_data,
++				fp_out_oob, &written);
++		if (res != 0)
++			goto err;
++	}
++
++	rc = 0;
++err:
++	free(buf);
++
++	if (args.fp_in)
++		fclose(args.fp_in);
++
++	if (fp_out_oob)
++		fclose(fp_out_oob);
++
++	if (fp_out_data && fp_out_data != stdout)
++		fclose(fp_out_data);
++
++	if (rc != 0) {
++		err_msg("Error during conversion. rc: %d\n", rc);
++		if (args.file_out_data)
++			remove(args.file_out_data);
++		if (args.file_out_oob)
++			remove(args.file_out_oob);
++	}
++	return rc;
++}
+diff -Nurp git.org/config.h git/config.h
+--- git.org/config.h	1970-01-01 09:00:00.000000000 +0900
++++ git/config.h	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,28 @@
++#ifndef __CONFIG_H__
++#define __CONFIG_H__
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Frank Haverkamp
++ */
++
++#define PACKAGE_BUGREPORT						\
++	"haver at vnet.ibm.com, dedekind at linutronix.de, or tglx at linutronix.de"
++
++#define ubi_unused __attribute__((unused))
++
++#endif
+diff -Nurp git.org/error.c git/error.c
+--- git.org/error.c	1970-01-01 09:00:00.000000000 +0900
++++ git/error.c	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,240 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <stdio.h>
++#include <stdarg.h>
++#include <syslog.h>
++#include <stdlib.h>
++#include <sys/errno.h>
++#include <string.h>
++#include "error.h"
++
++#define MAXLINE 4096
++#define MAXWIDTH 80
++
++static FILE *logfp = NULL;
++
++static void err_doit(int, int, const char *, va_list);
++
++int
++read_procfile(FILE *fp_out, const char *procfile)
++{
++	FILE *fp;
++
++	if (!fp_out)
++		return -ENXIO;
++
++	fp = fopen(procfile, "r");
++	if (!fp)
++		return -ENOENT;
++
++	while(!feof(fp)) {
++		int c = fgetc(fp);
++
++		if (c == EOF)
++			return 0;
++
++		if (putc(c, fp_out) == EOF)
++			return -EIO;
++
++		if (ferror(fp))
++			return -EIO;
++	}
++	return fclose(fp);
++}
++
++void
++error_initlog(const char *logfile)
++{
++	if (!logfile)
++		return;
++
++	logfp = fopen(logfile, "a+");
++	read_procfile(logfp, "/proc/cpuinfo");
++}
++
++void
++info_msg(const char *fmt, ...)
++{
++	FILE* fpout;
++	char buf[MAXLINE + 1];
++	va_list	ap;
++	int n;
++
++	fpout = stdout;
++
++	va_start(ap, fmt);
++	vsnprintf(buf, MAXLINE, fmt, ap);
++	n = strlen(buf);
++	strcat(buf, "\n");
++
++	fputs(buf, fpout);
++	fflush(fpout);
++	if (fpout != stdout)
++		fclose(fpout);
++
++	va_end(ap);
++	return;
++}
++
++void
++__err_ret(const char *fmt, ...)
++{
++	va_list		ap;
++
++	va_start(ap, fmt);
++	err_doit(1, LOG_INFO, fmt, ap);
++	va_end(ap);
++	return;
++}
++
++void
++__err_sys(const char *fmt, ...)
++{
++	va_list		ap;
++
++	va_start(ap, fmt);
++	err_doit(1, LOG_ERR, fmt, ap);
++	va_end(ap);
++	exit(EXIT_FAILURE);
++}
++
++
++void
++__err_msg(const char *fmt, ...)
++{
++	va_list	ap;
++
++	va_start(ap, fmt);
++	err_doit(0, LOG_INFO, fmt, ap);
++	va_end(ap);
++
++	return;
++}
++
++void
++__err_quit(const char *fmt, ...)
++{
++	va_list		ap;
++
++	va_start(ap, fmt);
++	err_doit(0, LOG_ERR, fmt, ap);
++	va_end(ap);
++	exit(EXIT_FAILURE);
++}
++
++void
++__err_dump(const char *fmt, ...)
++{
++	va_list		ap;
++
++	va_start(ap, fmt);
++	err_doit(1, LOG_ERR, fmt, ap);
++	va_end(ap);
++	abort();		/* dump core and terminate */
++	exit(EXIT_FAILURE);	/* shouldn't get here */
++}
++
++/**
++ * If a logfile is used we must not print on stderr and stdout
++ * anymore. Since pfilfash might be used in a server context, it is
++ * even dangerous to write to those descriptors.
++ */
++static void
++err_doit(int errnoflag, int level __attribute__((unused)),
++	 const char *fmt, va_list ap)
++{
++	FILE* fpout;
++	int errno_save, n;
++	char buf[MAXLINE + 1];
++	fpout = stderr;
++
++	errno_save = errno; /* value caller might want printed */
++
++	vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
++
++	n = strlen(buf);
++
++	if (errnoflag)
++		snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
++	strcat(buf, "\n");
++
++	if (logfp) {
++		fputs(buf, logfp);
++		fflush(logfp);
++		return;		/* exit when logging completes */
++	}
++
++	if (fpout == stderr) {
++		/* perform line wrap when outputting to stderr */
++		int word_len, post_len, chars;
++		char *buf_ptr;
++		const char *frmt = "%*s%n %n";
++
++		chars = 0;
++		buf_ptr = buf;
++		while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) {
++			int i;
++			char word[word_len + 1];
++			char post[post_len + 1];
++
++			strncpy(word, buf_ptr, word_len);
++			word[word_len] = '\0';
++			buf_ptr += word_len;
++			post_len -= word_len;
++
++			if (chars + word_len > MAXWIDTH) {
++				fputc('\n', fpout);
++				chars = 0;
++			}
++			fputs(word, fpout);
++			chars += word_len;
++
++			if (post_len > 0) {
++				strncpy(post, buf_ptr, post_len);
++				post[post_len] = '\0';
++				buf_ptr += post_len;
++			}
++			for (i = 0; i < post_len; i++) {
++				int inc = 1, chars_new;
++
++				if (post[i] == '\t')
++					inc = 8;
++				if (post[i] == '\n') {
++					inc = 0;
++					chars_new = 0;
++				} else
++					chars_new = chars + inc;
++
++				if (chars_new > MAXWIDTH) {
++					fputc('\n', fpout);
++					chars_new = inc;
++				}
++				fputc(post[i], fpout);
++				chars = chars_new;
++			}
++		}
++	}
++	else
++		fputs(buf, fpout);
++	fflush(fpout);
++	if (fpout != stderr)
++		fclose(fpout);
++
++	return;
++}
+diff -Nurp git.org/error.h git/error.h
+--- git.org/error.h	1970-01-01 09:00:00.000000000 +0900
++++ git/error.h	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,84 @@
++#ifndef __ERROR_H__
++#define __ERROR_H__
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <stdio.h>
++
++void error_initlog(const char *logfile);
++int read_procfile(FILE *fp_out, const char *procfile);
++
++void __err_ret(const char *fmt, ...);
++void __err_sys(const char *fmt, ...);
++void __err_msg(const char *fmt, ...);
++void __err_quit(const char *fmt, ...);
++void __err_dump(const char *fmt, ...);
++
++void info_msg(const char *fmt, ...);
++
++#ifdef DEBUG
++#define __loc_msg(str) do {					\
++	__err_msg("[%s. FILE: %s FUNC: %s LINE: %d]\n",		\
++		str, __FILE__, __FUNCTION__, __LINE__);		\
++} while (0)
++#else
++#define __loc_msg(str)
++#endif
++
++
++#define err_dump(fmt, ...) do {					\
++	__loc_msg("ErrDump");					\
++	__err_dump(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++#define err_quit(fmt, ...) do {					\
++	__loc_msg("ErrQuit");					\
++	__err_quit(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++
++#define err_ret(fmt, ...) do {					\
++	__loc_msg("ErrRet");					\
++	__err_ret(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++#define err_sys(fmt, ...) do {					\
++	__loc_msg("ErrSys");					\
++	__err_sys(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++#define err_msg(fmt, ...) do {					\
++	__loc_msg("ErrMsg");					\
++	__err_msg(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++#define log_msg(fmt, ...) do {					\
++		/* __loc_msg("LogMsg");	*/			\
++	__err_msg(fmt, ##__VA_ARGS__);				\
++} while (0)
++
++#ifdef DEBUG
++#define dbg_msg(fmt, ...) do {					\
++	__loc_msg("DbgMsg");					\
++	__err_msg(fmt, ##__VA_ARGS__);				\
++} while (0)
++#else
++#define dbg_msg(fmt, ...) do {} while (0)
++#endif
++
++#endif /* __ERROR_H__ */
+diff -Nurp git.org/Makefile git/Makefile
+--- git.org/Makefile	2013-02-22 00:53:07.000000000 +0900
++++ git/Makefile	2013-05-10 12:14:22.512590255 +0900
+@@ -24,6 +24,7 @@ MTD_BINS = \
+ 	nftldump nftl_format docfdisk \
+ 	rfddump rfdformat \
+ 	serve_image recv_image \
++	bin2nand nand2bin \
+ 	sumtool jffs2reader
+ UBI_BINS = \
+ 	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+@@ -87,6 +88,9 @@ obj-mkfs.jffs2 = compr_rtime.o compr_zli
+ LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+ LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
+ 
++obj-bin2nand = bin2nand.o error.o nandecc.o
++obj-nand2bin = nand2bin.o error.o nandecc.o nandcorr.o
++
+ LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+ LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
+ 
+diff -Nurp git.org/nand2bin.c git/nand2bin.c
+--- git.org/nand2bin.c	1970-01-01 09:00:00.000000000 +0900
++++ git/nand2bin.c	2013-05-10 12:12:44.134590273 +0900
+@@ -0,0 +1,492 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006, 2007
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Author: Frank Haverkamp
++ *
++ * An utility to decompose NAND images and strip OOB off. Not yet finished ...
++ *
++ * 1.2 Removed argp because we want to use uClibc.
++ * 1.3 Minor cleanup
++ * 1.4 Fixed OOB output file
++ * 1.5 Added verbose output and option to set blocksize.
++ *     Added split block mode for more convenient analysis.
++ * 1.6 Fixed ECC error detection and correction.
++ */
++
++#include <errno.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <stdint.h>
++#include <getopt.h>
++#include <stdarg.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/ioctl.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++
++#include "config.h"
++#include "nandecc.h"
++
++#define PROGRAM_VERSION "1.6"
++
++#define MAXPATH		1024
++#define MIN(x,y)	((x)<(y)?(x):(y))
++
++struct args {
++	const char *oob_file;
++	const char *output_file;
++	size_t pagesize;
++	size_t blocksize;
++	int split_blocks;
++	size_t in_len;		/* size of input file */
++	int correct_ecc;
++
++	/* special stuff needed to get additional arguments */
++	char *arg1;
++	char **options;		/* [STRING...] */
++};
++
++static struct args myargs = {
++	.output_file = "data.bin",
++	.oob_file = "oob.bin",
++	.pagesize = 2048,
++	.blocksize = 128 * 1024,
++	.in_len = 0,
++	.split_blocks = 0,
++	.correct_ecc = 0,
++	.arg1 = NULL,
++	.options = NULL,
++};
++
++static char doc[] = "\nVersion: " PROGRAM_VERSION "\n"
++	"nand2bin - split data and OOB.\n";
++
++static const char *optionsstr =
++"  -o, --output=<output>      Data output file\n"
++"  -O, --oob=<oob>            OOB output file\n"
++"  -p, --pagesize=<pagesize>  NAND pagesize\n"
++"  -b, --blocksize=<blocksize> NAND blocksize\n"
++"  -s, --split-blocks         generate binaries for each block\n"
++"  -e, --correct-ecc          Correct data according to ECC info\n"
++"  -v, --verbose              verbose output\n"
++"  -?, --help                 Give this help list\n"
++"      --usage                Give a short usage message\n";
++
++static const char *usage =
++"Usage: nand2bin [-?] [-o <output>] [-O <oob>] [-p <pagesize>]\n"
++"          [--output=<output>] [--oob=<oob>] [--pagesize=<pagesize>] [--help]\n"
++"          [--usage] input.mif\n";
++
++static int verbose = 0;
++
++static struct option long_options[] = {
++	{ .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
++	{ .name = "oob", .has_arg = 1, .flag = NULL, .val = 'O' },
++	{ .name = "pagesize", .has_arg = 1, .flag = NULL, .val = 'p' },
++	{ .name = "blocksize", .has_arg = 1, .flag = NULL, .val = 'b' },
++	{ .name = "split-blocks", .has_arg = 0, .flag = NULL, .val = 's' },
++	{ .name = "correct-ecc", .has_arg = 0, .flag = NULL, .val = 'e' },
++	{ .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
++	{ .name = "help", .has_arg = 0, .flag = NULL, .val = '?' },
++	{ .name = "usage", .has_arg = 0, .flag = NULL, .val = 0 },
++	{ NULL, 0, NULL, 0}
++};
++
++/*
++ * str_to_num - Convert string into number and cope with endings like
++ *              k, K, kib, KiB for kilobyte
++ *              m, M, mib, MiB for megabyte
++ */
++static uint32_t str_to_num(char *str)
++{
++	char *s = str;
++	ulong num = strtoul(s, &s, 0);
++
++	if (*s != '\0') {
++		if (strcmp(s, "KiB") == 0)
++			num *= 1024;
++		else if (strcmp(s, "MiB") == 0)
++			num *= 1024*1024;
++		else {
++			fprintf(stderr, "WARNING: Wrong number format "
++				"\"%s\", check your paramters!\n", str);
++		}
++	}
++	return num;
++}
++
++/*
++ * @brief Parse the arguments passed into the test case.
++ *
++ * @param argc           The number of arguments
++ * @param argv           The argument list
++ * @param args           Pointer to program args structure
++ *
++ * @return error
++ *
++ */
++static int parse_opt(int argc, char **argv, struct args *args)
++{
++	while (1) {
++		int key;
++
++		key = getopt_long(argc, argv, "b:eo:O:p:sv?", long_options, NULL);
++		if (key == -1)
++			break;
++
++		switch (key) {
++		case 'p': /* --pagesize<pagesize> */
++			args->pagesize = str_to_num(optarg);
++			break;
++
++		case 'b': /* --blocksize<blocksize> */
++			args->blocksize = str_to_num(optarg);
++			break;
++
++		case 'v': /* --verbose */
++			verbose++;
++			break;
++
++		case 's': /* --split-blocks */
++			args->split_blocks = 1;
++			break;
++
++		case 'e': /* --correct-ecc */
++			args->correct_ecc = 1;
++			break;
++
++		case 'o': /* --output=<output.bin> */
++			args->output_file = optarg;
++			break;
++
++		case 'O': /* --oob=<oob.bin> */
++			args->oob_file = optarg;
++			break;
++
++		case '?': /* help */
++			printf("Usage: nand2bin [OPTION...] input.mif\n");
++			printf("%s", doc);
++			printf("%s", optionsstr);
++			printf("\nReport bugs to %s\n",
++			       PACKAGE_BUGREPORT);
++			exit(0);
++			break;
++
++		case 'V':
++			printf("%s\n", PROGRAM_VERSION);
++			exit(0);
++			break;
++
++		default:
++			printf("%s", usage);
++			exit(-1);
++		}
++	}
++
++	if (optind < argc)
++		args->arg1 = argv[optind++];
++
++	return 0;
++}
++
++static int calc_oobsize(size_t pagesize)
++{
++	switch (pagesize) {
++	case 512:  return 16;
++	case 2048: return 64;
++	default:
++		exit(EXIT_FAILURE);
++	}
++	return 0;
++}
++
++static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size)
++{
++	int k;
++
++	for (k = 0; k < size; k++) {
++		fprintf(fp, "%02x ", buf[k]);
++		if ((k & 15) == 15)
++			fprintf(fp, "\n");
++	}
++}
++
++static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize)
++{
++	int eccpoi, oobsize;
++	size_t i;
++
++	switch (pagesize) {
++	case 2048: oobsize = 64; eccpoi = 64 / 2; break;
++	case 512:  oobsize = 16; eccpoi = 16 / 2; break;
++	default:
++		fprintf(stderr, "Unsupported page size: %zd\n", pagesize);
++		return -EINVAL;
++	}
++	memset(oobbuf, 0xff, oobsize);
++
++	for (i = 0; i < pagesize; i += 256, eccpoi += 3) {
++		oobbuf[eccpoi++] = 0x0;
++		/* Calculate ECC */
++		nand_calculate_ecc(&buf[i], &oobbuf[eccpoi]);
++	}
++	return 0;
++}
++
++static int bad_marker_offs_in_oob(int pagesize)
++{
++	switch (pagesize) {
++	case 2048: return 0;
++	case 512:  return 5;
++	}
++	return -EINVAL;
++}
++
++static int decompose_image(struct args *args, FILE *in_fp,
++			   FILE *bin_fp, FILE *oob_fp)
++{
++	int read, rc, page = 0;
++	size_t oobsize = calc_oobsize(args->pagesize);
++	uint8_t *buf = malloc(args->pagesize);
++	uint8_t *oob = malloc(oobsize);
++	uint8_t *calc_oob = malloc(oobsize);
++	uint8_t *calc_buf = malloc(args->pagesize);
++	uint8_t *page_buf;
++	int pages_per_block = args->blocksize / args->pagesize;
++	int eccpoi = 0, eccpoi_start;
++	unsigned int i;
++	int badpos = bad_marker_offs_in_oob(args->pagesize);
++
++	switch (args->pagesize) {
++	case 2048: eccpoi_start = 64 / 2; break;
++	case 512:  eccpoi_start = 16 / 2; break;
++	default:   exit(EXIT_FAILURE);
++	}
++
++	if (!buf)
++		exit(EXIT_FAILURE);
++	if (!oob)
++		exit(EXIT_FAILURE);
++	if (!calc_oob)
++		exit(EXIT_FAILURE);
++	if (!calc_buf)
++		exit(EXIT_FAILURE);
++
++	while (!feof(in_fp)) {
++		/* read page by page */
++		read = fread(buf, 1, args->pagesize, in_fp);
++		if (ferror(in_fp)) {
++			fprintf(stderr, "I/O Error.");
++			exit(EXIT_FAILURE);
++		}
++		if (read != (ssize_t)args->pagesize)
++			break;
++
++		read = fread(oob, 1, oobsize, in_fp);
++		if (ferror(in_fp)) {
++			fprintf(stderr, "I/O Error.");
++			exit(EXIT_FAILURE);
++		}
++
++		page_buf = buf;	/* default is unmodified data */
++
++		if ((page == 0 || page == 1) && (oob[badpos] != 0xff)) {
++			if (verbose)
++				printf("Block %d is bad\n",
++				       page / pages_per_block);
++			goto write_data;
++		}
++		if (args->correct_ecc)
++			page_buf = calc_buf;
++
++		process_page(buf, calc_oob, args->pagesize);
++		memcpy(calc_buf, buf, args->pagesize);
++
++		/*
++		 * Our oob format uses only the last 3 bytes out of 4.
++		 * The first byte is 0x00 when the ECC is generated by
++		 * our toolset and 0xff when generated by Linux. This
++		 * is to be fixed when we want nand2bin work for other
++		 * ECC layouts too.
++		 */
++		for (i = 0, eccpoi = eccpoi_start; i < args->pagesize;
++		     i += 256, eccpoi += 4)
++			oob[eccpoi] = calc_oob[eccpoi] = 0xff;
++
++		if (verbose && memcmp(oob, calc_oob, oobsize) != 0) {
++			printf("\nECC compare mismatch found at block %d page %d!\n",
++			       page / pages_per_block, page % pages_per_block);
++
++			printf("Read out OOB Data:\n");
++			hexdump(stdout, oob, oobsize);
++
++			printf("Calculated OOB Data:\n");
++			hexdump(stdout, calc_oob, oobsize);
++		}
++
++		/* Do correction on subpage base */
++		for (i = 0, eccpoi = eccpoi_start; i < args->pagesize;
++		     i += 256, eccpoi += 4) {
++			rc = nand_correct_data(calc_buf + i, &oob[eccpoi + 1],
++					       &calc_oob[eccpoi + 1]);
++
++			if (rc == -1)
++				fprintf(stdout, "Uncorrectable ECC error at "
++					"block %d page %d/%d\n",
++					page / pages_per_block,
++					page % pages_per_block, i / 256);
++			else if (rc > 0)
++				fprintf(stdout, "Correctable ECC error at "
++					"block %d page %d/%d\n",
++					page / pages_per_block,
++					page % pages_per_block, i / 256);
++		}
++
++	write_data:
++		rc = fwrite(page_buf, 1, args->pagesize, bin_fp);
++		if (ferror(bin_fp)) {
++			fprintf(stderr, "I/O Error.");
++			exit(EXIT_FAILURE);
++		}
++		rc = fwrite(oob, 1, oobsize, oob_fp);
++		if (ferror(bin_fp)) {
++			fprintf(stderr, "I/O Error.");
++			exit(EXIT_FAILURE);
++		}
++
++		page++;
++	}
++	free(calc_buf);
++	free(calc_oob);
++	free(oob);
++	free(buf);
++	return 0;
++}
++
++static int split_blocks(struct args *args, FILE *in_fp)
++{
++	uint8_t *buf;
++	size_t oobsize = calc_oobsize(args->pagesize);
++	int pages_per_block = args->blocksize / args->pagesize;
++	int block_len = pages_per_block * (args->pagesize + oobsize);
++	int blocks = args->in_len / block_len;
++	char bname[256] = { 0, };
++	int badpos = bad_marker_offs_in_oob(args->pagesize);
++	int bad_blocks = 0, i, bad_block = 0;
++	ssize_t rc;
++	FILE *b;
++
++	buf = malloc(block_len);
++	if (!buf) {
++		perror("Not enough memory");
++		exit(EXIT_FAILURE);
++	}
++
++	for (i = 0; i < blocks; i++) {
++		rc = fread(buf, 1, block_len, in_fp);
++		if (rc != block_len) {
++			fprintf(stderr, "cannot read enough data!\n");
++			exit(EXIT_FAILURE);
++		}
++
++		/* do block analysis */
++		bad_block = 0;
++		if ((buf[args->pagesize + badpos] != 0xff) ||
++		    (buf[2 * args->pagesize + oobsize + badpos] != 0xff)) {
++			bad_blocks++;
++			bad_block = 1;
++		}
++		if ((verbose && bad_block) || (verbose > 1)) {
++			printf("-- (block %d oob of page 0 and 1)\n", i);
++			hexdump(stdout, buf + args->pagesize, oobsize);
++			printf("--\n");
++			hexdump(stdout, buf + 2 * args->pagesize +
++				oobsize, oobsize);
++		}
++
++		/* write complete block out */
++		snprintf(bname, sizeof(bname) - 1, "%s.%d", args->arg1, i);
++		b = fopen(bname, "w+");
++		if (!b) {
++			perror("Cannot open file");
++			exit(EXIT_FAILURE);
++		}
++		rc = fwrite(buf, 1, block_len, b);
++		if (rc != block_len) {
++			fprintf(stderr, "could not write all data!\n");
++			exit(EXIT_FAILURE);
++		}
++		fclose(b);
++	}
++
++	free(buf);
++	if (bad_blocks || verbose)
++		fprintf(stderr, "%d blocks, %d bad blocks\n",
++			blocks, bad_blocks);
++	return 0;
++}
++
++int
++main(int argc, char *argv[])
++{
++	FILE *in, *bin = NULL, *oob = NULL;
++	struct stat file_info;
++
++	parse_opt(argc, argv, &myargs);
++
++	if (!myargs.arg1) {
++		fprintf(stderr, "Please specify input file!\n");
++		exit(EXIT_FAILURE);
++	}
++
++	if (stat(myargs.arg1, &file_info) != 0) {
++		perror("Cannot fetch file size from input file.\n");
++		exit(EXIT_FAILURE);
++	}
++	myargs.in_len = file_info.st_size;
++
++	in = fopen(myargs.arg1, "r");
++	if (!in) {
++		perror("Cannot open file");
++		exit(EXIT_FAILURE);
++	}
++
++	if (myargs.split_blocks) {
++		split_blocks(&myargs, in);
++		goto out;
++	}
++
++	bin = fopen(myargs.output_file, "w+");
++	if (!bin) {
++		perror("Cannot open file");
++		exit(EXIT_FAILURE);
++	}
++	oob = fopen(myargs.oob_file, "w+");
++	if (!oob) {
++		perror("Cannot open file");
++		exit(EXIT_FAILURE);
++	}
++	decompose_image(&myargs, in, bin, oob);
++
++ out:
++	if (in)	 fclose(in);
++	if (bin) fclose(bin);
++	if (oob) fclose(oob);
++	exit(EXIT_SUCCESS);
++}
+diff -Nurp git.org/nandcorr.c git/nandcorr.c
+--- git.org/nandcorr.c	1970-01-01 09:00:00.000000000 +0900
++++ git/nandcorr.c	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * ECC algorithm for NAND FLASH. Detects and corrects 1 bit errors in
++ * a 256 bytes of data.
++ *
++ * Reimplement by Thomas Gleixner after staring long enough at the
++ * mess in drivers/mtd/nand/nandecc.c
++ *
++ */
++
++#include "nandecc.h"
++
++static int countbits(uint32_t byte)
++{
++	int res = 0;
++
++	for (;byte; byte >>= 1)
++		res += byte & 0x01;
++	return res;
++}
++
++/**
++ * @dat:       data which should be corrected
++ * @read_ecc:  ecc information read from flash
++ * @calc_ecc:  calculated ecc information from the data
++ * @return:    number of corrected bytes
++ *             or -1 when no correction is possible
++ */
++int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
++		      const uint8_t *calc_ecc)
++{
++	uint8_t s0, s1, s2;
++
++	/*
++	 * Do error detection
++	 *
++	 * Be careful, the index magic is due to a pointer to a
++	 * uint32_t.
++	 */
++	s0 = calc_ecc[0] ^ read_ecc[0];
++	s1 = calc_ecc[1] ^ read_ecc[1];
++	s2 = calc_ecc[2] ^ read_ecc[2];
++
++	if ((s0 | s1 | s2) == 0)
++		return 0;
++
++	/* Check for a single bit error */
++	if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
++	    ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
++	    ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
++
++		uint32_t byteoffs, bitnum;
++
++		byteoffs = (s1 << 0) & 0x80;
++		byteoffs |= (s1 << 1) & 0x40;
++		byteoffs |= (s1 << 2) & 0x20;
++		byteoffs |= (s1 << 3) & 0x10;
++
++		byteoffs |= (s0 >> 4) & 0x08;
++		byteoffs |= (s0 >> 3) & 0x04;
++		byteoffs |= (s0 >> 2) & 0x02;
++		byteoffs |= (s0 >> 1) & 0x01;
++
++		bitnum = (s2 >> 5) & 0x04;
++		bitnum |= (s2 >> 4) & 0x02;
++		bitnum |= (s2 >> 3) & 0x01;
++
++		dat[byteoffs] ^= (1 << bitnum);
++
++		return 1;
++	}
++
++	if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
++		return 1;
++
++	return -1;
++}
++
+diff -Nurp git.org/nandecc.c git/nandecc.c
+--- git.org/nandecc.c	1970-01-01 09:00:00.000000000 +0900
++++ git/nandecc.c	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,159 @@
++/*
++ * This file contains an ECC algorithm from Toshiba that detects and
++ * corrects 1 bit errors in a 256 byte block of data.
++ *
++ * drivers/mtd/nand/nand_ecc.c
++ *
++ * Copyright (C) 2000-2004 Steven J. Hill (sjhill at realitydiluted.com)
++ *			   Toshiba America Electronics Components, Inc.
++ *
++ * This file is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 or (at your option) any
++ * later version.
++ *
++ * This file is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this file; if not, write to the Free Software Foundation, Inc.,
++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * As a special exception, if other files instantiate templates or use
++ * macros or inline functions from these files, or you compile these
++ * files and link them with other works to produce a work based on these
++ * files, these files do not by themselves cause the resulting work to be
++ * covered by the GNU General Public License. However the source code for
++ * these files must still be made available in accordance with section (3)
++ * of the GNU General Public License.
++ *
++ * This exception does not invalidate any other reasons why a work based on
++ * this file might be covered by the GNU General Public License.
++ */
++
++#include "nandecc.h"
++
++/*
++ * Pre-calculated 256-way 1 byte column parity
++ */
++static const uint8_t nand_ecc_precalc_table[] = {
++	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
++	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
++	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
++	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
++	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
++	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
++	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
++	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
++	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
++	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
++	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
++	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
++	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
++	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
++	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
++	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
++	0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
++	0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
++	0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
++	0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
++	0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
++	0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
++	0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
++	0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
++	0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
++	0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
++	0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
++	0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
++	0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
++	0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
++	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
++	0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
++};
++
++/**
++ * nand_trans_result - [GENERIC] create non-inverted ECC
++ * @reg2:	line parity reg 2
++ * @reg3:	line parity reg 3
++ * @ecc_code:	ecc
++ *
++ * Creates non-inverted ECC code from line parity
++ */
++static void nand_trans_result(uint8_t reg2, uint8_t reg3,
++	uint8_t *ecc_code)
++{
++	uint8_t a, b, i, tmp1, tmp2;
++
++	/* Initialize variables */
++	a = b = 0x80;
++	tmp1 = tmp2 = 0;
++
++	/* Calculate first ECC byte */
++	for (i = 0; i < 4; i++) {
++		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
++			tmp1 |= b;
++		b >>= 1;
++		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
++			tmp1 |= b;
++		b >>= 1;
++		a >>= 1;
++	}
++
++	/* Calculate second ECC byte */
++	b = 0x80;
++	for (i = 0; i < 4; i++) {
++		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
++			tmp2 |= b;
++		b >>= 1;
++		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
++			tmp2 |= b;
++		b >>= 1;
++		a >>= 1;
++	}
++
++	/* Store two of the ECC bytes */
++	ecc_code[1] = tmp1;
++	ecc_code[0] = tmp2;
++}
++
++/**
++ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for
++ * 256 byte block
++ *
++ * @dat:	raw data
++ * @ecc_code:	buffer for ECC
++ */
++int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code)
++{
++	uint8_t idx, reg1, reg2, reg3;
++	int j;
++
++	/* Initialize variables */
++	reg1 = reg2 = reg3 = 0;
++	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
++
++	/* Build up column parity */
++	for(j = 0; j < 256; j++) {
++
++		/* Get CP0 - CP5 from table */
++		idx = nand_ecc_precalc_table[dat[j]];
++		reg1 ^= (idx & 0x3f);
++
++		/* All bit XOR = 1 ? */
++		if (idx & 0x40) {
++			reg3 ^= (uint8_t) j;
++			reg2 ^= ~((uint8_t) j);
++		}
++	}
++
++	/* Create non-inverted ECC code from line parity */
++	nand_trans_result(reg2, reg3, ecc_code);
++
++	/* Calculate final ECC code */
++	ecc_code[0] = ~ecc_code[0];
++	ecc_code[1] = ~ecc_code[1];
++	ecc_code[2] = ((~reg1) << 2) | 0x03;
++	return 0;
++}
+diff -Nurp git.org/nandecc.h git/nandecc.h
+--- git.org/nandecc.h	1970-01-01 09:00:00.000000000 +0900
++++ git/nandecc.h	2013-05-10 12:12:34.569591044 +0900
+@@ -0,0 +1,29 @@
++#ifndef _NAND_ECC_H
++#define _NAND_ECC_H
++/*
++ * Copyright (c) International Business Machines Corp., 2006
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
++ * the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * NAND ecc functions
++ */
++
++#include <stdint.h>
++
++int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code);
++int nand_correct_data(uint8_t *dat, const uint8_t *read_ecc,
++		      const uint8_t *calc_ecc);
++
++#endif
diff --git a/meta/recipes-devtools/mtd/mtd-utils_git.bb b/meta/recipes-devtools/mtd/mtd-utils_git.bb
index 7010cac..61673bd 100644
--- a/meta/recipes-devtools/mtd/mtd-utils_git.bb
+++ b/meta/recipes-devtools/mtd/mtd-utils_git.bb
@@ -15,6 +15,7 @@ SRC_URI = "git://git.infradead.org/mtd-utils.git \
            file://fix-armv7-neon-alignment.patch \
            file://0001-hashtable-Remove-duplicate-hashtable_iterator_value-.patch \
            file://mtd-utils-fix-corrupt-cleanmarker-with-flash_erase--j-command.patch \
+           file://add-bin2nand-nand2bin.patch \
 "
 
 S = "${WORKDIR}/git/"
@@ -31,7 +32,7 @@ FILES_mtd-utils-jffs2 = "${sbindir}/mkfs.jffs2 ${sbindir}/jffs2dump ${sbindir}/j
 FILES_mtd-utils-ubifs = "${sbindir}/mkfs.ubifs ${sbindir}/ubi*"
 FILES_mtd-utils-misc = "${sbindir}/nftl* ${sbindir}/ftl* ${sbindir}/rfd* ${sbindir}/doc* ${sbindir}/serve_image ${sbindir}/recv_image"
 
-BBCLASSEXTEND = "native"
+BBCLASSEXTEND = "native nativesdk"
 
 # git/.compr.c.dep:46: warning: NUL character seen; rest of line ignored
 # git/.compr.c.dep:47: *** missing separator.  Stop.
-- 
1.8.4.2




More information about the Openembedded-core mailing list