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 <[email protected]>
---
 .../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                                             \
++      "[email protected], [email protected], or [email protected]"
++
++#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 ([email protected])
++ *                       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

-- 
_______________________________________________
Openembedded-core mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-core

Reply via email to