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
