diff options
-rw-r--r-- | ubi-utils/TODO | 7 | ||||
-rw-r--r-- | ubi-utils/scripts/bin2nand2bin_test.sh | 43 | ||||
-rw-r--r-- | ubi-utils/src/bin2nand.c | 156 | ||||
-rw-r--r-- | ubi-utils/src/ecclayouts.h | 66 | ||||
-rw-r--r-- | ubi-utils/src/nand2bin.c | 212 |
5 files changed, 304 insertions, 180 deletions
diff --git a/ubi-utils/TODO b/ubi-utils/TODO index a604170..4683bd7 100644 --- a/ubi-utils/TODO +++ b/ubi-utils/TODO @@ -3,12 +3,15 @@ TODO * Range checking is broken, reserving 2M and offering 3M binary data ... works!? No! - * Remove the above misterious statement or make it understandable + * Remove the above mysterious statement or make it understandable * doc/ directory contains a file which refers images from /home/frank/ - please fix this or remove the whole doc/ altogether. * the tests from the scripts/ directory should live in - mit-utils/tests/ubi-tests/ and it would be nice to have a short + mtd-utils/tests/ubi-tests/ and it would be nice to have a short description of the tests * the stuff from the perl/ directory should go to the scripts/ * May we pleas split UBI-related stuff and pure NAND-related stuff and not to keep this all in one. + + * nand2bin and bin2nand need more flexibility to influence the ECC + data placement. diff --git a/ubi-utils/scripts/bin2nand2bin_test.sh b/ubi-utils/scripts/bin2nand2bin_test.sh index a17c91b..2192f02 100644 --- a/ubi-utils/scripts/bin2nand2bin_test.sh +++ b/ubi-utils/scripts/bin2nand2bin_test.sh @@ -1,5 +1,8 @@ #!/bin/sh # +# Version: 1.1 +# Author: Frank Haverkamp <haver@vnet.ibm.com> +# # Testcase for nand2bin and bin2nand. Generate testdata and inject # biterrors. Convert data back and compare with original data. # @@ -8,14 +11,44 @@ # inject_biterror=./scripts/inject_biterror.pl - pagesize=2048 oobsize=64 # Create test data dd if=/dev/urandom of=testblock.bin bs=131072 count=1 -echo "Test conversion without bitflips ..." +for layout in IBM MTD ; do + echo "*** Simple test with $layout layout ..." + + echo -n "Convert bin to mif ... " + bin2nand -l$layout --pagesize=${pagesize} -o testblock.mif testblock.bin + if [ $? -ne "0" ]; then + echo "failed!" + exit 1 + else + echo "ok" + fi + + echo -n "Convert mif to bin ... " + nand2bin -l$layout --pagesize=${pagesize} -o testblock.img testblock.mif + if [ $? -ne "0" ]; then + echo "failed!" + exit 1 + else + echo "ok" + fi + + echo -n "Comparing data ... " + diff testblock.bin testblock.img + if [ $? -ne "0" ]; then + echo "failed!" + exit 1 + else + echo "ok" + fi +done + +echo "*** Test conversion without bitflips ..." echo -n "Convert bin to mif ... " bin2nand --pagesize=${pagesize} -o testblock.mif testblock.bin @@ -44,7 +77,7 @@ else echo "ok" fi -echo "Test conversion with uncorrectable ECC erors ..." +echo "*** Test conversion with uncorrectable ECC erors ..." echo -n "Inject biterror at offset $ioffs ... " ${inject_biterror} --offset=0 --bitmask=0x81 \ --input=testblock.mif \ @@ -76,7 +109,7 @@ else exit 1 fi -echo "Test bitflips in data ... " +echo "*** Test bitflips in data ... " for offs in `seq 0 255` ; do cp testblock.mif testblock_bitflip.mif @@ -142,7 +175,7 @@ for offs in `seq 0 255` ; do fi done -echo "Test bitflips in OOB data ... " +echo "*** Test bitflips in OOB data ... " for offs in `seq 0 $oobsize` ; do let ioffs=$pagesize+$offs diff --git a/ubi-utils/src/bin2nand.c b/ubi-utils/src/bin2nand.c index c7c7ccc..83f50cc 100644 --- a/ubi-utils/src/bin2nand.c +++ b/ubi-utils/src/bin2nand.c @@ -28,7 +28,8 @@ * 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) + * 1.6 Written variable not initialized (-j did not work) (haver) + * 1.7 Made NAND ECC layout configurable (haver) */ #include <unistd.h> @@ -46,8 +47,11 @@ #include "error.h" #include "config.h" #include "nandecc.h" +#include "ecclayouts.h" -#define PROGRAM_VERSION "1.6" +#define PROGRAM_VERSION "1.7" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define CHECK_ENDP(option, endp) do { \ if (*endp) { \ @@ -74,8 +78,9 @@ static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" static const char *optionsstr = " -c, --copyright Print copyright informatoin.\n" " -j, --padding=<num> Padding in Byte/Mi/ki. Default = no padding\n" +" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n" " -p, --pagesize=<num> Pagesize in Byte/Mi/ki. Default = 2048\n" -" -o, --output=<fname> Output filename. Interleaved Data/OOB if\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" @@ -94,30 +99,33 @@ struct option long_options[] = { { .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 = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' }, { .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"; +#define __unused __attribute__((unused)) +static const char copyright [] __unused = "Copyright IBM Corp. 2007"; -typedef struct myargs { +struct args { action_t action; size_t pagesize; + size_t oobsize; 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. */ + const char *file_out_data; /* Either: Data and OOB interleaved + or plain data */ + const char *file_out_oob; /* OOB Data only. */ + struct nand_ecclayout *nand_oob; /* special stuff needed to get additional arguments */ char *arg1; char **options; /* [STRING...] */ -} myargs; +}; static int ustrtoull(const char *cp, char **endp, unsigned int base) @@ -140,49 +148,53 @@ static int ustrtoull(const char *cp, char **endp, unsigned int base) } static int -parse_opt(int argc, char **argv, myargs *args) +parse_opt(int argc, char **argv, struct args *args) { + const char *ecc_layout = NULL; + unsigned int i, oob_idx = 0; char* endp; while (1) { int key; - key = getopt_long(argc, argv, "cj:p:o:q:?V", long_options, NULL); + key = getopt_long(argc, argv, "cj:l: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); + 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 'l': /* --ecc-layout=<...> */ + ecc_layout = optarg; + break; + case '?': /* help */ + printf("%s%s", doc, 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); } } @@ -194,46 +206,55 @@ parse_opt(int argc, char **argv, myargs *args) } } + switch (args->pagesize) { + case 512: args->oobsize = 16; oob_idx = 0; break; + case 2048: args->oobsize = 64; oob_idx = 1; break; + default: + err_msg("Unsupported page size: %d\n", args->pagesize); + return -EINVAL; + } + + /* Figure out correct oob layout if it differs from default */ + if (ecc_layout) { + for (i = 0; i < ARRAY_SIZE(oob_placement); i++) + if (strcmp(ecc_layout, oob_placement[i].name) == 0) + args->nand_oob = + oob_placement[i].nand_oob[oob_idx]; + } return 0; } static int -process_page(uint8_t* buf, size_t pagesize, - FILE *fp_data, FILE* fp_oob, size_t* written) +process_page(struct args *args, uint8_t *buf, FILE *fp_data, FILE *fp_oob, + size_t *written) { - int eccpoi, oobsize; + int eccpoi; size_t i; uint8_t oobbuf[64]; + uint8_t ecc_code[3] = { 0, }; /* temp */ + /* Calculate ECC for each subpage of 256 bytes */ 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]); + for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) { + int j; + nand_calculate_ecc(&buf[i], ecc_code); + for (j = 0; j < 3; j++) + oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j]; } /* write data */ - *written += fwrite(buf, 1, pagesize, fp_data); + *written += fwrite(buf, 1, args->pagesize, fp_data); /* either separate oob or interleave with data */ if (fp_oob) { - i = fwrite(oobbuf, 1, oobsize, fp_oob); + i = fwrite(oobbuf, 1, args->oobsize, fp_oob); if (ferror(fp_oob)) { err_msg("IO error\n"); return -EIO; } } else { - i = fwrite(oobbuf, 1, oobsize, fp_data); + i = fwrite(oobbuf, 1, args->oobsize, fp_data); if (ferror(fp_data)) { err_msg("IO error\n"); return -EIO; @@ -248,13 +269,14 @@ int main (int argc, char** argv) int rc = -1; int res = 0; size_t written = 0, read; - myargs args = { + struct args args = { .action = ACT_NORMAL, .pagesize = PAGESIZE, .padding = PADDING, .fp_in = NULL, .file_out_data = NULL, .file_out_oob = NULL, + .nand_oob = &ibm_nand_oob_64, }; FILE* fp_out_data = stdout; @@ -306,16 +328,16 @@ int main (int argc, char** argv) goto err; } - res = process_page(buf, args.pagesize, fp_out_data, - fp_out_oob, &written); + res = process_page(&args, buf, 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); + res = process_page(&args, buf, fp_out_data, fp_out_oob, + &written); if (res != 0) goto err; } diff --git a/ubi-utils/src/ecclayouts.h b/ubi-utils/src/ecclayouts.h new file mode 100644 index 0000000..a1c7823 --- /dev/null +++ b/ubi-utils/src/ecclayouts.h @@ -0,0 +1,66 @@ +#ifndef __ECCLAYOUTS_H__ +#define __ECCLAYOUTS_H__ +/* + * 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. + */ + +#include <stdint.h> +#include <mtd/mtd-abi.h> + +/* Define default oob placement schemes for large and small page devices */ +static struct nand_ecclayout mtd_nand_oob_16 = { + .eccbytes = 6, + .eccpos = { 0, 1, 2, 3, 6, 7 }, + .oobfree = {{ .offset = 8, .length = 8 }} +}; + +static struct nand_ecclayout mtd_nand_oob_64 = { + .eccbytes = 24, + .eccpos = { 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63 }, + .oobfree = {{ .offset = 2, .length = 38 }} +}; + +/* Define IBM oob placement schemes */ +static struct nand_ecclayout ibm_nand_oob_16 = { + .eccbytes = 6, + .eccpos = { 9, 10, 11, 13, 14, 15 }, + .oobfree = {{ .offset = 8, .length = 8 }} +}; + +static struct nand_ecclayout ibm_nand_oob_64 = { + .eccbytes = 24, + .eccpos = { 33, 34, 35, 37, 38, 39, 41, 42, + 43, 45, 46, 47, 49, 50, 51, 53, + 54, 55, 57, 58, 59, 61, 62, 63 }, + .oobfree = {{ .offset = 2, .length = 30 }} +}; + +struct oob_placement { + const char *name; + struct nand_ecclayout *nand_oob[2]; +}; + +static struct oob_placement oob_placement[] = { + { .name = "IBM", + .nand_oob = { &ibm_nand_oob_16, &ibm_nand_oob_64 }}, + { .name = "MTD", + .nand_oob = { &mtd_nand_oob_16, &mtd_nand_oob_64 }}, +}; + +#endif diff --git a/ubi-utils/src/nand2bin.c b/ubi-utils/src/nand2bin.c index be62e30..8c95b27 100644 --- a/ubi-utils/src/nand2bin.c +++ b/ubi-utils/src/nand2bin.c @@ -25,6 +25,9 @@ * 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. + * 1.7 Made NAND ECC layout configurable, the holes which were previously + * filled with 0x00 are untouched now and will be 0xff just like MTD + * behaves when writing the oob (haver) */ #include <config.h> @@ -43,9 +46,11 @@ #include "config.h" #include "nandecc.h" +#include "ecclayouts.h" -#define PROGRAM_VERSION "1.6" +#define PROGRAM_VERSION "1.7" +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define MAXPATH 1024 #define MIN(x,y) ((x)<(y)?(x):(y)) @@ -53,10 +58,13 @@ struct args { const char *oob_file; const char *output_file; size_t pagesize; + size_t oobsize; + int bad_marker_offs_in_oob; size_t blocksize; int split_blocks; size_t in_len; /* size of input file */ int correct_ecc; + struct nand_ecclayout *nand_oob; /* special stuff needed to get additional arguments */ char *arg1; @@ -68,6 +76,7 @@ static struct args myargs = { .oob_file = "oob.bin", .pagesize = 2048, .blocksize = 128 * 1024, + .nand_oob = &ibm_nand_oob_64, .in_len = 0, .split_blocks = 0, .correct_ecc = 0, @@ -79,6 +88,7 @@ static char doc[] = "\nVersion: " PROGRAM_VERSION "\n" "nand2bin - split data and OOB.\n"; static const char *optionsstr = +" -l, --ecc-placement=<MTD,IBM> OOB placement scheme (default is IBM).\n" " -o, --output=<output> Data output file\n" " -O, --oob=<oob> OOB output file\n" " -p, --pagesize=<pagesize> NAND pagesize\n" @@ -97,6 +107,7 @@ static const char *usage = static int verbose = 0; static struct option long_options[] = { + { .name = "ecc-layout", .has_arg = 1, .flag = NULL, .val = 'l' }, { .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' }, @@ -144,56 +155,52 @@ static uint32_t str_to_num(char *str) */ static int parse_opt(int argc, char **argv, struct args *args) { + unsigned int i, oob_idx = 0; + const char *ecc_layout = NULL; + while (1) { int key; - key = getopt_long(argc, argv, "b:eo:O:p:sv?", long_options, NULL); + key = getopt_long(argc, argv, "b:el:o: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 'l': /* --ecc-layout=<...> */ + ecc_layout = optarg; + break; case 'o': /* --output=<output.bin> */ args->output_file = optarg; break; - case 'O': /* --oob=<oob.bin> */ args->oob_file = optarg; break; - + case 'p': /* --pagesize<pagesize> */ + args->pagesize = str_to_num(optarg); + break; + case 's': /* --split-blocks */ + args->split_blocks = 1; + break; + case 'v': /* --verbose */ + verbose++; + break; + case 'V': + printf("%s\n", PROGRAM_VERSION); + exit(0); + break; case '?': /* help */ printf("Usage: nand2bin [OPTION...] input.mif\n"); - printf("%s", doc); - printf("%s", optionsstr); + printf("%s%s", doc, 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); @@ -203,17 +210,44 @@ static int parse_opt(int argc, char **argv, struct args *args) if (optind < argc) args->arg1 = argv[optind++]; + switch (args->pagesize) { + case 512: + args->oobsize = 16; + args->bad_marker_offs_in_oob = 5; + oob_idx = 0; + break; + case 2048: + args->oobsize = 64; + args->bad_marker_offs_in_oob = 0; + oob_idx = 1; + break; + default: + fprintf(stderr, "Unsupported page size: %d\n", args->pagesize); + return -EINVAL; + } + + /* Figure out correct oob layout if it differs from default */ + if (ecc_layout) { + for (i = 0; i < ARRAY_SIZE(oob_placement); i++) + if (strcmp(ecc_layout, oob_placement[i].name) == 0) + args->nand_oob = + oob_placement[i].nand_oob[oob_idx]; + } return 0; } -static int calc_oobsize(size_t pagesize) +/* + * We must only compare the relevant bytes in the OOB area. All other + * bytes can be ignored. The information we need to do this is in + * nand_oob. + */ +static int oob_cmp(struct nand_ecclayout *nand_oob, uint8_t *oob, + uint8_t *calc_oob) { - switch (pagesize) { - case 512: return 16; - case 2048: return 64; - default: - exit(EXIT_FAILURE); - } + unsigned int i; + for (i = 0; i < nand_oob->eccbytes; i++) + if (oob[nand_oob->eccpos[i]] != calc_oob[nand_oob->eccpos[i]]) + return 1; return 0; } @@ -228,65 +262,38 @@ static inline void hexdump(FILE *fp, const uint8_t *buf, ssize_t size) } } -static int process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize) +static int process_page(struct args *args, uint8_t *buf, uint8_t *oobbuf) { - 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]); + size_t i, j; + int eccpoi; + uint8_t ecc_code[3] = { 0, }; /* temp */ + + /* Calculate ECC */ + memset(oobbuf, 0xff, args->oobsize); + for (eccpoi = 0, i = 0; i < args->pagesize; i += 256, eccpoi += 3) { + nand_calculate_ecc(&buf[i], ecc_code); + for (j = 0; j < 3; j++) + oobbuf[args->nand_oob->eccpos[eccpoi + j]] = ecc_code[j]; } 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) { + unsigned int i, eccpoi; 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 *oob = malloc(args->oobsize); + uint8_t *calc_oob = malloc(args->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); - } + int badpos = args->bad_marker_offs_in_oob; + uint8_t ecc_code[3] = { 0, }; /* temp */ + uint8_t calc_ecc_code[3] = { 0, }; /* temp */ - if (!buf) - exit(EXIT_FAILURE); - if (!oob) - exit(EXIT_FAILURE); - if (!calc_oob) - exit(EXIT_FAILURE); - if (!calc_buf) + if (!buf || !oob || !calc_oob || !calc_buf) exit(EXIT_FAILURE); while (!feof(in_fp)) { @@ -299,7 +306,7 @@ static int decompose_image(struct args *args, FILE *in_fp, if (read != (ssize_t)args->pagesize) break; - read = fread(oob, 1, oobsize, in_fp); + read = fread(oob, 1, args->oobsize, in_fp); if (ferror(in_fp)) { fprintf(stderr, "I/O Error."); exit(EXIT_FAILURE); @@ -316,37 +323,31 @@ static int decompose_image(struct args *args, FILE *in_fp, if (args->correct_ecc) page_buf = calc_buf; - process_page(buf, calc_oob, args->pagesize); + process_page(args, buf, calc_oob); 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) { + if (verbose && oob_cmp(args->nand_oob, oob, calc_oob) != 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); + hexdump(stdout, oob, args->oobsize); printf("Calculated OOB Data:\n"); - hexdump(stdout, calc_oob, oobsize); + hexdump(stdout, calc_oob, args->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]); - + for (i = 0, eccpoi = 0; i < args->pagesize; i += 256, eccpoi += 3) { + int j; + + for (j = 0; j < 3; j++) { + ecc_code[j] = oob[args->nand_oob->eccpos[eccpoi + j]]; + calc_ecc_code[j] = + calc_oob[args->nand_oob->eccpos[eccpoi + j]]; + } + rc = nand_correct_data(calc_buf + i, ecc_code, + calc_ecc_code); if (rc == -1) fprintf(stdout, "Uncorrectable ECC error at " "block %d page %d/%d\n", @@ -365,7 +366,7 @@ static int decompose_image(struct args *args, FILE *in_fp, fprintf(stderr, "I/O Error."); exit(EXIT_FAILURE); } - rc = fwrite(oob, 1, oobsize, oob_fp); + rc = fwrite(oob, 1, args->oobsize, oob_fp); if (ferror(bin_fp)) { fprintf(stderr, "I/O Error."); exit(EXIT_FAILURE); @@ -383,12 +384,11 @@ static int decompose_image(struct args *args, FILE *in_fp, 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 block_len = pages_per_block * (args->pagesize + args->oobsize); int blocks = args->in_len / block_len; char bname[256] = { 0, }; - int badpos = bad_marker_offs_in_oob(args->pagesize); + int badpos = args->bad_marker_offs_in_oob; int bad_blocks = 0, i, bad_block = 0; ssize_t rc; FILE *b; @@ -409,16 +409,16 @@ static int split_blocks(struct args *args, FILE *in_fp) /* do block analysis */ bad_block = 0; if ((buf[args->pagesize + badpos] != 0xff) || - (buf[2 * args->pagesize + oobsize + badpos] != 0xff)) { + (buf[2 * args->pagesize + args->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); + hexdump(stdout, buf + args->pagesize, args->oobsize); printf("--\n"); hexdump(stdout, buf + 2 * args->pagesize + - oobsize, oobsize); + args->oobsize, args->oobsize); } /* write complete block out */ |