aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ubi-utils/TODO7
-rw-r--r--ubi-utils/scripts/bin2nand2bin_test.sh43
-rw-r--r--ubi-utils/src/bin2nand.c156
-rw-r--r--ubi-utils/src/ecclayouts.h66
-rw-r--r--ubi-utils/src/nand2bin.c212
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 */