[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