summaryrefslogtreecommitdiff
path: root/ubi-utils/src/unubi.c
diff options
context:
space:
mode:
authorFrank Haverkamp <haver@vnet.ibm.com>2007-11-24 11:04:51 +0100
committerFrank Haverkamp <haver@vnet.ibm.com>2007-11-24 11:04:51 +0100
commit26c965bc654d67881fc54f4b24a552600752dadd (patch)
treeec8033e92872dd7a594063a893bd6cd4b708e0c4 /ubi-utils/src/unubi.c
parent0d2d0f43b9aa9b08f610169b412fd24a15dea154 (diff)
ubi-utils: various fixes in unubi
The extraction of data from blocks used for dynamic volumes was totally broken. The data size was calculated wrong. This fix is not perfect, the alignment is still ignored. The parameter "header-size" is very misleading. It does not reflect the vid hdr offset properly. I assume therefor that it only works for the layout I am using where the vid hdr is at the _end_ of the 1st NAND page (2048). I added the generation of a textfile with information about the blocks which are going into the internal graph representation. Instead of a graph I think that a simple array will simplify the code very much. The array must than be sorted properly to cope with older and newer block-copies but that should not be a problem. discussed the tool with my coleage Andreas Arnez and we found that it might be a good idea to replace it even with a perl program for the same purpose since that would offer the flexibility to change it on the fly when needed. The tool is mainly used for crash analysis so it could be an advantage to change it without needing a C-compiler. Signed-off-by: Frank Haverkamp <haver@vnet.ibm.com>
Diffstat (limited to 'ubi-utils/src/unubi.c')
-rw-r--r--ubi-utils/src/unubi.c141
1 files changed, 81 insertions, 60 deletions
diff --git a/ubi-utils/src/unubi.c b/ubi-utils/src/unubi.c
index e0a71a6..6ca9405 100644
--- a/ubi-utils/src/unubi.c
+++ b/ubi-utils/src/unubi.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
@@ -17,12 +17,13 @@
*/
/*
- * Authors: Frank Haverkamp, haver@vnet.ibm.com
- * Drake Dowsett, dowsett@de.ibm.com
+ * Authors: Drake Dowsett, dowsett@de.ibm.com
+ * Frank Haverkamp, haver@vnet.ibm.com
*
* 1.2 Removed argp because we want to use uClibc.
* 1.3 Minor cleanups.
* 1.4 Meanwhile Drake had done a lot of changes, syncing those.
+ * 1.5 Bugfixes, simplifications
*/
/*
@@ -44,18 +45,18 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mtd/ubi-header.h>
#include "crc32.h"
-#include "eb_chain.h"
#include "unubi_analyze.h"
#define EXEC "unubi"
#define CONTACT "haver@vnet.ibm.com"
-#define VERSION "1.4"
+#define VERSION "1.5"
static char doc[] = "\nVersion: " VERSION "\n";
static int debug = 0;
@@ -66,7 +67,7 @@ static const char *optionsstr =
"to rebuild all valid complete UBI volumes found within the image.\n"
"\n"
" OPERATIONS\n"
-" -a, --analyze Analyze image\n"
+" -a, --analyze Analyze image and create gnuplot graphs\n"
" -i, --info-table Extract volume information tables\n"
" -r, --rebuild=<volume-id> Extract and rebuild volume\n"
"\n"
@@ -75,8 +76,11 @@ static const char *optionsstr =
" (default 128KiB)\n"
" -d, --dir=<output-dir> Specify output directory\n"
" -D, --debug Enable debug output\n"
-" -s, --headersize=<header-size> Specify size of eraseblock header in image\n"
-" in bytes (default 2048 Byte)\n"
+" -s, --headersize=<header-size> Specify size reserved for metadata in eraseblock\n"
+ " in bytes (default 2048 Byte)\n"
+ /* the -s option might be insufficient when using different vid
+ offset than what we used when writing this tool ... Better would
+ probably be --vid-hdr-offset or alike */
"\n"
" ADVANCED\n"
" -e, --eb-split Generate individual eraseblock images (all\n"
@@ -138,8 +142,12 @@ struct args {
int analyze;
int itable;
uint32_t *vols;
- size_t bsize;
+
+ size_t vid_hdr_offset;
+ size_t data_offset;
+ size_t bsize; /* FIXME replace by vid_hdr/data offs? */
size_t hsize;
+
char *odir_path;
int eb_split;
int vol_split;
@@ -204,29 +212,30 @@ parse_opt(int argc, char **argv, struct args *args)
break;
switch (key) {
- case 'a':
+ case 'a': /* --analyze */
args->analyze = 1;
break;
- case 'b':
+ case 'b': /* --block-size=<block-size> */
args->bsize = str_to_num(optarg);
break;
- case 's':
+ case 's': /* --header-size=<header-size> */
args->hsize = str_to_num(optarg);
break;
- case 'd':
+ case 'd': /* --dir=<output-dir> */
args->odir_path = optarg;
break;
- case 'D': /* I wanted to use -v but that was
- already used ... */
+ case 'D': /* --debug */
+ /* I wanted to use -v but that was already
+ used ... */
debug = 1;
break;
- case 'e':
+ case 'e': /* --eb-split */
args->eb_split = SPLIT_RAW;
break;
- case 'i':
+ case 'i': /* --info-table */
args->itable = 1;
break;
- case 'r':
+ case 'r': /* --rebuild=<volume-id> */
i = str_to_num(optarg);
if (i < UBI_MAX_VOLUMES)
args->vols[str_to_num(optarg)] = 1;
@@ -235,11 +244,11 @@ parse_opt(int argc, char **argv, struct args *args)
return -1;
}
break;
- case 'v':
+ case 'v': /* --vol-split */
if (args->vol_split != SPLIT_RAW)
args->vol_split = SPLIT_DATA;
break;
- case 'V':
+ case 'V': /* --vol-split! */
args->vol_split = SPLIT_RAW;
break;
case '?': /* help */
@@ -258,6 +267,10 @@ parse_opt(int argc, char **argv, struct args *args)
}
}
+ /* FIXME I suppose hsize should be replaced! */
+ args->vid_hdr_offset = args->hsize - UBI_VID_HDR_SIZE;
+ args->data_offset = args->hsize;
+
if (optind < argc)
args->img_path = argv[optind++];
return 0;
@@ -307,33 +320,6 @@ collapse(uint32_t *full_array, size_t full_len,
return j;
}
-
-/**
- * header_crc: calculate the crc of EITHER a eb_hdr or vid_hdr
- * one of the first two args MUST be NULL, the other is the header
- * to caculate the crc on
- * always returns 0
- **/
-static int
-header_crc(struct ubi_ec_hdr *ebh, struct ubi_vid_hdr *vidh, uint32_t *ret_crc)
-{
- uint32_t crc = UBI_CRC32_INIT;
-
- if (ret_crc == NULL)
- return 0;
-
- if ((ebh != NULL) && (vidh == NULL))
- crc = clc_crc32(crc32_table, crc, ebh, UBI_EC_HDR_SIZE_CRC);
- else if ((ebh == NULL) && (vidh != NULL))
- crc = clc_crc32(crc32_table, crc, vidh, UBI_VID_HDR_SIZE_CRC);
- else
- return 0;
-
- *ret_crc = crc;
- return 0;
-}
-
-
/**
* data_crc: save the FILE* position, calculate the crc over a span,
* reset the position
@@ -420,8 +406,8 @@ extract_data(FILE* fpin, size_t len, const char *path)
* failure and 0 on success
**/
static int
-extract_itable(FILE* fpin, eb_info_t cur, size_t bsize, size_t num,
- const char* path)
+extract_itable(FILE *fpin, struct eb_info *cur, size_t bsize, size_t num,
+ const char *path)
{
char filename[MAXPATH + 1];
int rc;
@@ -531,14 +517,14 @@ extract_itable(FILE* fpin, eb_info_t cur, size_t bsize, size_t num,
* the known volumes, if vol_id is NULL;
**/
static int
-rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path,
- size_t block_size, size_t header_size)
+rebuild_volume(FILE * fpin, uint32_t *vol_id, struct eb_info **head,
+ const char *path, size_t block_size, size_t header_size)
{
char filename[MAXPATH];
int rc;
uint32_t vol, num, data_size;
FILE* fpout;
- eb_info_t cur;
+ struct eb_info *cur;
rc = 0;
@@ -606,6 +592,7 @@ rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path,
fseek(fpin, ubi32_to_cpu(cur->ec.data_offset), SEEK_CUR);
if (cur->vid.vol_type == UBI_VID_DYNAMIC)
+ /* FIXME It might be that alignment has influence */
data_size = block_size - header_size;
else
data_size = ubi32_to_cpu(cur->vid.data_size);
@@ -651,8 +638,8 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
/* relations:
* cur ~ head
* next ~ first */
- eb_info_t head, cur, first, next;
- eb_info_t *next_ptr;
+ struct eb_info *head, *cur, *first, *next;
+ struct eb_info **next_ptr;
rc = 0;
count = 0;
@@ -673,6 +660,11 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
const char *raw_path;
uint32_t crc;
+ cur->phys_addr = ftell(fpin);
+ cur->data_crc_ok = 0;
+ cur->ec_crc_ok = 0;
+ cur->vid_crc_ok = 0;
+
memset(filename, 0, MAXPATH + 1);
memset(reason, 0, MAXPATH + 1);
@@ -696,8 +688,8 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
}
/* check erasecounter header crc */
- header_crc(&(cur->ec), NULL, &crc);
-
+ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->ec),
+ UBI_EC_HDR_SIZE_CRC);
if (ubi32_to_cpu(cur->ec.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc");
goto invalid;
@@ -738,13 +730,16 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
snprintf(reason, MAXPATH, ".invalid.vid_magic");
goto invalid;
}
+ cur->ec_crc_ok = 1;
/* check volume id header crc */
- header_crc(NULL, &(cur->vid), &crc);
+ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &(cur->vid),
+ UBI_VID_HDR_SIZE_CRC);
if (ubi32_to_cpu(cur->vid.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc");
goto invalid;
}
+ cur->vid_crc_ok = 1;
/* check data crc, but only for a static volume */
if (cur->vid.vol_type == UBI_VID_STATIC) {
@@ -756,6 +751,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
snprintf(reason, MAXPATH, ".invalid.data_crc");
goto invalid;
}
+ cur->data_crc_ok = 1;
}
/* enlist this vol, it's valid */
@@ -788,9 +784,22 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
if (rc != 0)
goto err;
+ /*
+ * FIXME For dynamic UBI volumes we must write
+ * the maximum available data. The
+ * vid.data_size field is not used in this
+ * case. The dynamic volume user is
+ * responsible for the content.
+ */
if (a->vol_split == SPLIT_DATA) {
- /* write only data section */
- size = ubi32_to_cpu(cur->vid.data_size);
+ /* Write only data section */
+ if (cur->vid.vol_type == UBI_VID_DYNAMIC) {
+ /* FIXME Formular is not
+ always right ... */
+ size = a->bsize - a->hsize;
+ } else
+ size = ubi32_to_cpu(cur->vid.data_size);
+
fseek(fpin,
ubi32_to_cpu(cur->ec.data_offset),
SEEK_CUR);
@@ -883,9 +892,21 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
err:
free(cur);
- if (a->analyze)
+ if (a->analyze) {
+ char fname[PATH_MAX];
+ FILE *fp;
+
unubi_analyze(&head, first, a->odir_path);
+ /* prepare output files */
+ memset(fname, 0, PATH_MAX + 1);
+ snprintf(fname, PATH_MAX, "%s/%s", a->odir_path, FN_EH_STAT);
+ fp = fopen(fname, "w");
+ if (fp != NULL) {
+ eb_chain_print(fp, head);
+ fclose(fp);
+ }
+ }
eb_chain_destroy(&head);
eb_chain_destroy(&first);