summaryrefslogtreecommitdiff
path: root/ubi-utils/src
diff options
context:
space:
mode:
authorFrank Haverkamp <haver@vnet.ibm.com>2007-09-26 13:40:10 +0200
committerFrank Haverkamp <haver@vnet.ibm.com>2007-09-26 13:40:10 +0200
commit42a842d2815e9eed732c6fde8f20bf6d4b4a54cb (patch)
tree4a03238a99f2f0957809030265ae0873067fc6f4 /ubi-utils/src
parent6affcbe3a1caa6e3df2feef05252c9cf46522a42 (diff)
ubi-utils: Nand2bin add more information when bad blocks occur
When bad blocks occur more debug information is needed. To identify the bad blocks the blocksize is required. The split block mode was added to generate files per block. In split mode the bad block markers are analyzed and a summary is printed at the end. Signed-off-by: Frank Haverkamp <haver@vnet.ibm.com>
Diffstat (limited to 'ubi-utils/src')
-rw-r--r--ubi-utils/src/nand2bin.c157
1 files changed, 136 insertions, 21 deletions
diff --git a/ubi-utils/src/nand2bin.c b/ubi-utils/src/nand2bin.c
index 735fc8b..8db4e77 100644
--- a/ubi-utils/src/nand2bin.c
+++ b/ubi-utils/src/nand2bin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) International Business Machines Corp., 2006
+ * 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
@@ -22,6 +22,8 @@
* 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.
*/
#include <config.h>
@@ -41,7 +43,7 @@
#include "config.h"
#include "nandecc.h"
-#define PROGRAM_VERSION "1.4"
+#define PROGRAM_VERSION "1.5"
#define MAXPATH 1024
#define MIN(x,y) ((x)<(y)?(x):(y))
@@ -50,6 +52,9 @@ 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 */
/* special stuff needed to get additional arguments */
char *arg1;
@@ -60,6 +65,9 @@ static struct args myargs = {
.output_file = "data.bin",
.oob_file = "oob.bin",
.pagesize = 2048,
+ .blocksize = 128 * 1024,
+ .in_len = 0,
+ .split_blocks = 0,
.arg1 = NULL,
.options = NULL,
};
@@ -71,6 +79,9 @@ 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"
+" -v, --verbose verbose output\n"
" -?, --help Give this help list\n"
" --usage Give a short usage message\n";
@@ -79,10 +90,15 @@ static const char *usage =
" [--output=<output>] [--oob=<oob>] [--pagesize=<pagesize>] [--help]\n"
" [--usage] input.mif\n";
+static int verbose = 0;
+
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 = "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}
@@ -127,7 +143,7 @@ parse_opt(int argc, char **argv, struct args *args)
while (1) {
int key;
- key = getopt_long(argc, argv, "o:O:p:?", long_options, NULL);
+ key = getopt_long(argc, argv, "b:o:O:p:sv?", long_options, NULL);
if (key == -1)
break;
@@ -136,6 +152,18 @@ parse_opt(int argc, char **argv, struct args *args)
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 'o': /* --output=<output.bin> */
args->output_file = optarg;
break;
@@ -216,15 +244,24 @@ process_page(uint8_t* buf, uint8_t *oobbuf, size_t pagesize)
return 0;
}
-static int decompose_image(FILE *in_fp, FILE *bin_fp, FILE *oob_fp,
- size_t pagesize)
+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(pagesize);
- uint8_t *buf = malloc(pagesize);
+ 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(pagesize);
+ uint8_t *calc_buf = malloc(args->pagesize);
if (!buf)
exit(EXIT_FAILURE);
@@ -236,12 +273,15 @@ static int decompose_image(FILE *in_fp, FILE *bin_fp, FILE *oob_fp,
exit(EXIT_FAILURE);
while (!feof(in_fp)) {
- read = fread(buf, 1, pagesize, in_fp);
+ read = fread(buf, 1, args->pagesize, in_fp);
if (ferror(in_fp)) {
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
}
- rc = fwrite(buf, 1, pagesize, bin_fp);
+ if (read != (ssize_t)args->pagesize)
+ break;
+
+ rc = fwrite(buf, 1, args->pagesize, bin_fp);
if (ferror(bin_fp)) {
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
@@ -256,13 +296,13 @@ static int decompose_image(FILE *in_fp, FILE *bin_fp, FILE *oob_fp,
fprintf(stderr, "I/O Error.");
exit(EXIT_FAILURE);
}
- process_page(buf, calc_oob, pagesize);
- memcpy(calc_buf, buf, pagesize);
+ process_page(buf, calc_oob, args->pagesize);
+ memcpy(calc_buf, buf, args->pagesize);
rc = nand_correct_data(calc_buf, oob);
- if ((rc != -1) || (memcmp(buf, calc_buf, pagesize) != 0)) {
- fprintf(stdout, "Page %d: data does not match!\n",
+ if ((rc != -1) || (memcmp(buf, calc_buf, args->pagesize) != 0)) {
+ fprintf(stdout, "possible ECC error at page %d\n",
page);
}
page++;
@@ -274,10 +314,74 @@ static int decompose_image(FILE *in_fp, FILE *bin_fp, FILE *oob_fp,
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, *oob;
+ FILE *in, *bin = NULL, *oob = NULL;
+ struct stat file_info;
parse_opt(argc, argv, &myargs);
@@ -286,11 +390,23 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ if (lstat(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");
@@ -301,12 +417,11 @@ main(int argc, char *argv[])
perror("Cannot open file");
exit(EXIT_FAILURE);
}
+ decompose_image(&myargs, in, bin, oob);
- decompose_image(in, bin, oob, myargs.pagesize);
-
- fclose(in);
- fclose(bin);
- fclose(oob);
-
+ out:
+ if (in) fclose(in);
+ if (bin) fclose(bin);
+ if (oob) fclose(oob);
exit(EXIT_SUCCESS);
}