aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Haverkamp <haver@vnet.ibm.com>2007-11-24 11:04:50 +0100
committerFrank Haverkamp <haver@vnet.ibm.com>2007-11-24 11:04:50 +0100
commitdb9cd63b656507b86723500840ec1543fab9c7cf (patch)
tree91e18526fee0c79abb40a9c94092e3f7dec032c1
parent26b91d381b06145e003cb1781b5a3467270a8347 (diff)
ubi-utils: Update and bugfix unubi
Drake Dawsett had done some changes to our unubi which where not yet published. I hereby send his latest code and integrated the parameter handling which was changed in our version. When reviewing this very huge patch we need to ensure that possible changes of others are not reversed. Signed-off-by: Frank Haverkamp <haver@vnet.ibm.com>
-rw-r--r--ubi-utils/src/eb_chain.c35
-rw-r--r--ubi-utils/src/eb_chain.h4
-rw-r--r--ubi-utils/src/unubi.c401
-rw-r--r--ubi-utils/src/unubi_analyze.c169
4 files changed, 402 insertions, 207 deletions
diff --git a/ubi-utils/src/eb_chain.c b/ubi-utils/src/eb_chain.c
index 501a838..22594c5 100644
--- a/ubi-utils/src/eb_chain.c
+++ b/ubi-utils/src/eb_chain.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include "eb_chain.h"
+#include "crc32.h"
#define COPY(dst, src) \
do \
@@ -66,9 +67,9 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
return 0;
}
- new_vol = ubi32_to_cpu(new->inner.vol_id);
- new_num = ubi32_to_cpu(new->inner.lnum);
- new_ver = ubi32_to_cpu(new->inner.leb_ver);
+ new_vol = ubi32_to_cpu(new->vid.vol_id);
+ new_num = ubi32_to_cpu(new->vid.lnum);
+ new_ver = ubi32_to_cpu(new->vid.leb_ver);
/** TRAVERSE HORIZONTALY **/
@@ -76,8 +77,8 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
prev = NULL;
/* traverse until vol_id/lnum align */
- vol = ubi32_to_cpu(cur->inner.vol_id);
- num = ubi32_to_cpu(cur->inner.lnum);
+ vol = ubi32_to_cpu(cur->vid.vol_id);
+ num = ubi32_to_cpu(cur->vid.lnum);
while ((new_vol > vol) || ((new_vol == vol) && (new_num > num)))
{
/* insert new at end of chain */
@@ -91,8 +92,8 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
prev = cur;
cur = cur->next;
- vol = ubi32_to_cpu(cur->inner.vol_id);
- num = ubi32_to_cpu(cur->inner.lnum);
+ vol = ubi32_to_cpu(cur->vid.vol_id);
+ num = ubi32_to_cpu(cur->vid.lnum);
}
if (prev == NULL)
@@ -115,7 +116,7 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
prev = NULL;
/* traverse until versions align */
- ver = ubi32_to_cpu(cur->inner.leb_ver);
+ ver = ubi32_to_cpu(cur->vid.leb_ver);
while (new_ver < ver)
{
/* insert new at bottom of history */
@@ -130,7 +131,7 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
prev = hist;
hist = hist->older;
- ver = ubi32_to_cpu(hist->inner.leb_ver);
+ ver = ubi32_to_cpu(hist->vid.leb_ver);
}
if (prev == NULL)
@@ -181,8 +182,8 @@ eb_chain_position(eb_info_t *head, uint32_t vol_id, uint32_t *lnum,
cur = *head;
while (cur != NULL)
{
- vol = ubi32_to_cpu(cur->inner.vol_id);
- num = ubi32_to_cpu(cur->inner.lnum);
+ vol = ubi32_to_cpu(cur->vid.vol_id);
+ num = ubi32_to_cpu(cur->vid.lnum);
if (vol_id == vol)
if ((lnum == NULL) || (*lnum == num))
@@ -227,17 +228,17 @@ eb_chain_print(FILE* stream, eb_info_t *head)
eb_info_t hist;
fprintf(stream, " VOL %4u-%04u | VER 0x%8x\n",
- ubi32_to_cpu(cur->inner.vol_id),
- ubi32_to_cpu(cur->inner.lnum),
- ubi32_to_cpu(cur->inner.leb_ver));
+ ubi32_to_cpu(cur->vid.vol_id),
+ ubi32_to_cpu(cur->vid.lnum),
+ ubi32_to_cpu(cur->vid.leb_ver));
hist = cur->older;
while (hist != NULL)
{
fprintf(stream, "+ VOL %4u-%04u | VER 0x%8x\n",
- ubi32_to_cpu(hist->inner.vol_id),
- ubi32_to_cpu(hist->inner.lnum),
- ubi32_to_cpu(hist->inner.leb_ver));
+ ubi32_to_cpu(hist->vid.vol_id),
+ ubi32_to_cpu(hist->vid.lnum),
+ ubi32_to_cpu(hist->vid.leb_ver));
hist = hist->older;
}
diff --git a/ubi-utils/src/eb_chain.h b/ubi-utils/src/eb_chain.h
index f640c54..4c94058 100644
--- a/ubi-utils/src/eb_chain.h
+++ b/ubi-utils/src/eb_chain.h
@@ -52,8 +52,8 @@
typedef struct eb_info *eb_info_t;
struct eb_info {
- struct ubi_ec_hdr outer;
- struct ubi_vid_hdr inner;
+ struct ubi_ec_hdr ec;
+ struct ubi_vid_hdr vid;
fpos_t eb_top;
uint32_t linear;
diff --git a/ubi-utils/src/unubi.c b/ubi-utils/src/unubi.c
index 81db5fa..e0a71a6 100644
--- a/ubi-utils/src/unubi.c
+++ b/ubi-utils/src/unubi.c
@@ -21,7 +21,8 @@
* Drake Dowsett, dowsett@de.ibm.com
*
* 1.2 Removed argp because we want to use uClibc.
- * 1.3 Minor cleanups
+ * 1.3 Minor cleanups.
+ * 1.4 Meanwhile Drake had done a lot of changes, syncing those.
*/
/*
@@ -54,22 +55,30 @@
#define EXEC "unubi"
#define CONTACT "haver@vnet.ibm.com"
-#define VERSION "1.3"
+#define VERSION "1.4"
-static char doc[] = "\nVersion: " VERSION "\n"
- "unubi - analyze raw flash containing UBI data.\n";
+static char doc[] = "\nVersion: " VERSION "\n";
+static int debug = 0;
static const char *optionsstr =
-" OPTIONS\n"
-" -r, --rebuild=<volume-id> Extract and rebuild volume\n"
-"\n"
-" -d, --dir=<output-dir> Specify output directory\n"
+"Extract volumes and/or analysis information from an UBI data file.\n"
+"When no parameters are flagged or given, the default operation is\n"
+"to rebuild all valid complete UBI volumes found within the image.\n"
"\n"
+" OPERATIONS\n"
" -a, --analyze Analyze image\n"
+" -i, --info-table Extract volume information tables\n"
+" -r, --rebuild=<volume-id> Extract and rebuild volume\n"
"\n"
+" OPTIONS\n"
" -b, --blocksize=<block-size> Specify size of eraseblocks in image in bytes\n"
" (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"
"\n"
+" ADVANCED\n"
" -e, --eb-split Generate individual eraseblock images (all\n"
" eraseblocks)\n"
" -v, --vol-split Generate individual eraseblock images (valid\n"
@@ -78,13 +87,16 @@ static const char *optionsstr =
"\n"
" -?, --help Give this help list\n"
" --usage Give a short usage message\n"
-" --version Print program version\n";
+" --version Print program version\n"
+"\n";
static const char *usage =
-"Usage: unubi [-aevV?] [-r <volume-id>] [-d <output-dir>] [-b <block-size>]\n"
-" [--rebuild=<volume-id>] [--dir=<output-dir>] [--analyze]\n"
-" [--blocksize=<block-size>] [--eb-split] [--vol-split]\n"
-" [--vol-split!] [--help] [--usage] [--version] image-file\n";
+"Usage: unubi [-aievV?] [-r <volume-id>] [-b <block-size>] [-d <output-dir>]\n"
+" [-s <header-size>] [--analyze] [--info-table]\n"
+" [--rebuild=<volume-id>] [--blocksize=<block-size>]\n"
+" [--dir=<output-dir>] [--headersize=<header-size>] [--eb-split]\n"
+" [--vol-split] [--vol-split!] [--help] [--usage] [--version]\n"
+" image-file\n";
#define ERR_MSG(fmt...) \
fprintf(stderr, EXEC ": " fmt)
@@ -101,13 +113,15 @@ static const char *usage =
#define FN_INVAL "%s/eb%04u%s" /* invalid eraseblock */
#define FN_NSURE "%s/eb%04u_%03u_%03u_%03x%s" /* unsure eraseblock */
#define FN_VALID "%s/eb%04u_%03u_%03u_%03x%s" /* valid eraseblock */
-#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04zu" /* split volume */
+#define FN_VOLSP "%s/vol%03u_%03u_%03u_%04u" /* split volume */
#define FN_VOLWH "%s/volume%03u" /* whole volume */
+#define FN_VITBL "%s/vol_info_table%u" /* vol info table */
static uint32_t crc32_table[256];
/* struct args:
* bsize int, blocksize of image blocks
+ * hsize int, eraseblock header size
* analyze flag, when non-zero produce analysis
* eb_split flag, when non-zero output eb####
* note: SPLIT_DATA vs. SPLIT_RAW
@@ -121,13 +135,15 @@ static uint32_t crc32_table[256];
* count_set() and collapse()
*/
struct args {
- uint32_t bsize;
int analyze;
+ int itable;
+ uint32_t *vols;
+ size_t bsize;
+ size_t hsize;
+ char *odir_path;
int eb_split;
int vol_split;
- char *odir_path;
char *img_path;
- uint32_t *vols;
char **options;
};
@@ -164,7 +180,7 @@ str_to_num(char *str)
if ((strcmp(s, "KiB") == 0) || (strcmp(s, "K") == 0) ||
(strcmp(s, "kib") == 0) || (strcmp(s, "k") == 0))
num *= KIB;
- if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) ||
+ else if ((strcmp(s, "MiB") == 0) || (strcmp(s, "M") == 0) ||
(strcmp(s, "mib") == 0) || (strcmp(s, "m") == 0))
num *= MIB;
else
@@ -182,56 +198,63 @@ parse_opt(int argc, char **argv, struct args *args)
while (1) {
int key;
- key = getopt_long(argc, argv, "r:d:ab:evV?", long_options, NULL);
+ key = getopt_long(argc, argv, "ab:s:d:Deir:vV?J",
+ long_options, NULL);
if (key == -1)
break;
switch (key) {
- case 'a':
- args->analyze = 1;
- break;
- case 'b':
- args->bsize = str_to_num(optarg);
- break;
- case 'd':
- args->odir_path = optarg;
- break;
- case 'e':
- args->eb_split = SPLIT_RAW;
- break;
- case 'r':
- i = str_to_num(optarg);
- if (i < UBI_MAX_VOLUMES)
- args->vols[str_to_num(optarg)] = 1;
- else {
- ERR_MSG("volume-id out of bounds\n");
- return -1;
- }
- break;
- case 'v':
- if (args->vol_split != SPLIT_RAW)
- args->vol_split = SPLIT_DATA;
- break;
- case 'V':
- args->vol_split = SPLIT_RAW;
- break;
- case '?': /* help */
- fprintf(stderr,
- "Usage: unubi [OPTION...] "
- "image-file\n");
- fprintf(stderr, "%s", doc);
- fprintf(stderr, "%s", optionsstr);
- fprintf(stderr,
- "\nReport bugs to %s\n", CONTACT);
- exit(0);
- break;
- case 'J':
- fprintf(stderr, "%s\n", VERSION);
- exit(0);
- break;
- default:
- fprintf(stderr, "%s", usage);
- exit(-1);
+ case 'a':
+ args->analyze = 1;
+ break;
+ case 'b':
+ args->bsize = str_to_num(optarg);
+ break;
+ case 's':
+ args->hsize = str_to_num(optarg);
+ break;
+ case 'd':
+ args->odir_path = optarg;
+ break;
+ case 'D': /* I wanted to use -v but that was
+ already used ... */
+ debug = 1;
+ break;
+ case 'e':
+ args->eb_split = SPLIT_RAW;
+ break;
+ case 'i':
+ args->itable = 1;
+ break;
+ case 'r':
+ i = str_to_num(optarg);
+ if (i < UBI_MAX_VOLUMES)
+ args->vols[str_to_num(optarg)] = 1;
+ else {
+ ERR_MSG("volume-id out of bounds\n");
+ return -1;
+ }
+ break;
+ case 'v':
+ if (args->vol_split != SPLIT_RAW)
+ args->vol_split = SPLIT_DATA;
+ break;
+ case 'V':
+ args->vol_split = SPLIT_RAW;
+ break;
+ case '?': /* help */
+ fprintf(stderr, "Usage: unubi [OPTION...] "
+ "image-file\n%s%s\nReport bugs to %s\n",
+ doc, optionsstr, CONTACT);
+ exit(0);
+ break;
+ case 'J':
+ fprintf(stderr, "%s\n", VERSION);
+ exit(0);
+ break;
+ default:
+ fprintf(stderr, "%s", usage);
+ exit(-1);
}
}
@@ -287,7 +310,7 @@ collapse(uint32_t *full_array, size_t full_len,
/**
* header_crc: calculate the crc of EITHER a eb_hdr or vid_hdr
- * one of the first to args MUST be NULL, the other is the header
+ * one of the first two args MUST be NULL, the other is the header
* to caculate the crc on
* always returns 0
**/
@@ -391,15 +414,129 @@ extract_data(FILE* fpin, size_t len, const char *path)
/**
+ * extract volume information table from block. saves and reloads fpin
+ * position
+ * returns -1 when a fpos set or get fails, otherwise <= -2 on other
+ * failure and 0 on success
+ **/
+static int
+extract_itable(FILE* fpin, eb_info_t cur, size_t bsize, size_t num,
+ const char* path)
+{
+ char filename[MAXPATH + 1];
+ int rc;
+ size_t i, max;
+ fpos_t temp;
+ FILE* fpout = NULL;
+ struct ubi_vol_tbl_record rec;
+
+ if (fpin == NULL || cur == NULL || path == NULL)
+ return -2;
+
+ /* remember position */
+ rc = fgetpos(fpin, &temp);
+ if (rc < 0)
+ return -1;
+
+ /* jump to top of eraseblock, skip to data section */
+ fsetpos(fpin, &cur->eb_top);
+ if (rc < 0)
+ return -1;
+ fseek(fpin, ubi32_to_cpu(cur->ec.data_offset), SEEK_CUR);
+
+ /* prepare output file */
+ if (ubi32_to_cpu(cur->vid.vol_id) != UBI_LAYOUT_VOL_ID)
+ return -2;
+ memset(filename, 0, MAXPATH + 1);
+ snprintf(filename, MAXPATH, FN_VITBL, path, num);
+ fpout = fopen(filename, "w");
+ if (fpout == NULL)
+ return -2;
+
+ /* loop through entries */
+ fprintf(fpout,
+ "index\trpebs\talign\ttype\tcrc\t\tname\n");
+ max = bsize - ubi32_to_cpu(cur->ec.data_offset);
+ for (i = 0; i < (max / sizeof(rec)); i++) {
+ int blank = 1;
+ char *ptr, *base;
+ char name[UBI_VOL_NAME_MAX + 1];
+ const char *type = "unknown\0";
+ uint32_t crc;
+
+ /* read record */
+ rc = fread(&rec, 1, sizeof(rec), fpin);
+ if (rc == 0)
+ break;
+ if (rc != sizeof(rec)) {
+ ERR_MSG("reading volume information "
+ "table record failed\n");
+ rc = -3;
+ goto exit;
+ }
+
+ /* check crc */
+ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &rec,
+ UBI_VTBL_RECORD_SIZE_CRC);
+ if (crc != ubi32_to_cpu(rec.crc))
+ continue;
+
+ /* check for empty */
+ base = (char *)&rec;
+ ptr = base;
+ while (blank &&
+ ((unsigned)(ptr - base) < UBI_VTBL_RECORD_SIZE_CRC)) {
+ if (*ptr != 0)
+ blank = 0;
+ ptr++;
+ }
+
+ if (blank)
+ continue;
+
+ /* prep type string */
+ if (rec.vol_type == UBI_VID_DYNAMIC)
+ type = "dynamic\0";
+ else if (rec.vol_type == UBI_VID_STATIC)
+ type = "static\0";
+
+ /* prep name string */
+ rec.name[ubi16_to_cpu(rec.name_len)] = '\0';
+ sprintf(name, "%s", rec.name);
+
+ /* print record line to fpout */
+ fprintf(fpout, "%u\t%u\t%u\t%s\t0x%08x\t%s\n",
+ i,
+ ubi32_to_cpu(rec.reserved_pebs),
+ ubi32_to_cpu(rec.alignment),
+ type,
+ ubi32_to_cpu(rec.crc),
+ name);
+ }
+
+ exit:
+ /* reset position */
+ if (fsetpos(fpin, &temp) < 0)
+ rc = -1;
+
+ if (fpout != NULL)
+ fclose(fpout);
+
+ return rc;
+}
+
+
+/**
* using eb chain, tries to rebuild the data of volume at vol_id, or for all
* 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)
+rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path,
+ size_t block_size, size_t header_size)
{
char filename[MAXPATH];
int rc;
- uint32_t vol, num;
+ uint32_t vol, num, data_size;
FILE* fpout;
eb_info_t cur;
@@ -411,13 +548,13 @@ rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path)
/* when vol_id is null, then do all */
if (vol_id == NULL) {
cur = *head;
- vol = ubi32_to_cpu(cur->inner.vol_id);
- }
- else {
+ vol = ubi32_to_cpu(cur->vid.vol_id);
+ } else {
vol = *vol_id;
eb_chain_position(head, vol, NULL, &cur);
if (cur == NULL) {
- ERR_MSG("no valid volume %d was found\n", vol);
+ if (debug)
+ ERR_MSG("no valid volume %d was found\n", vol);
return -1;
}
}
@@ -433,7 +570,7 @@ rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path)
while (cur != NULL) {
size_t i;
- if (ubi32_to_cpu(cur->inner.vol_id) != vol) {
+ if (ubi32_to_cpu(cur->vid.vol_id) != vol) {
/* close out file */
fclose(fpout);
@@ -442,7 +579,7 @@ rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path)
goto out;
/* begin with next */
- vol = ubi32_to_cpu(cur->inner.vol_id);
+ vol = ubi32_to_cpu(cur->vid.vol_id);
num = 0;
snprintf(filename, MAXPATH, FN_VOLWH, path, vol);
fpout = fopen(filename, "wb");
@@ -453,17 +590,27 @@ rebuild_volume(FILE* fpin, uint32_t *vol_id, eb_info_t *head, const char* path)
}
}
- if (ubi32_to_cpu(cur->inner.lnum) != num) {
- ERR_MSG("missing valid block %d for volume %d\n",
- num, vol);
+ while (num < ubi32_to_cpu(cur->vid.lnum)) {
+ /* FIXME haver: I hope an empty block is
+ written out so that the binary has no holes
+ ... */
+ if (debug)
+ ERR_MSG("missing valid block %d for volume %d\n",
+ num, vol);
+ num++;
}
rc = fsetpos(fpin, &(cur->eb_top));
if (rc < 0)
goto out;
- fseek(fpin, ubi32_to_cpu(cur->outer.data_offset), SEEK_CUR);
+ fseek(fpin, ubi32_to_cpu(cur->ec.data_offset), SEEK_CUR);
- for (i = 0; i < ubi32_to_cpu(cur->inner.data_size); i++) {
+ if (cur->vid.vol_type == UBI_VID_DYNAMIC)
+ data_size = block_size - header_size;
+ else
+ data_size = ubi32_to_cpu(cur->vid.data_size);
+
+ for (i = 0; i < data_size; i++) {
int c = fgetc(fpin);
if (c == EOF) {
ERR_MSG("unexpected EOF while writing: %s\n",
@@ -500,7 +647,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
char filename[MAXPATH + 1];
char reason[MAXPATH + 1];
int rc;
- size_t i, count;
+ size_t i, count, itable_num;
/* relations:
* cur ~ head
* next ~ first */
@@ -509,6 +656,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
rc = 0;
count = 0;
+ itable_num = 0;
head = NULL;
first = NULL;
next = NULL;
@@ -532,25 +680,25 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
raw_path = FN_INVAL;
/* read erasecounter header */
- rc = fread(&cur->outer, 1, sizeof(cur->outer), fpin);
+ rc = fread(&cur->ec, 1, sizeof(cur->ec), fpin);
if (rc == 0)
goto out; /* EOF */
- if (rc != sizeof(cur->outer)) {
- ERR_MSG("reading ec-hdr failed rc=%d\n", rc);
+ if (rc != sizeof(cur->ec)) {
+ ERR_MSG("reading ec-hdr failed\n");
rc = -1;
goto err;
}
/* check erasecounter header magic */
- if (ubi32_to_cpu(cur->outer.magic) != UBI_EC_HDR_MAGIC) {
+ if (ubi32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) {
snprintf(reason, MAXPATH, ".invalid.ec_magic");
goto invalid;
}
/* check erasecounter header crc */
- header_crc(&(cur->outer), NULL, &crc);
+ header_crc(&(cur->ec), NULL, &crc);
- if (ubi32_to_cpu(cur->outer.hdr_crc) != crc) {
+ if (ubi32_to_cpu(cur->ec.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.ec_hdr_crc");
goto invalid;
}
@@ -559,27 +707,26 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
rc = fsetpos(fpin, &(cur->eb_top));
if (rc != 0)
goto err;
- fseek(fpin, ubi32_to_cpu(cur->outer.vid_hdr_offset), SEEK_CUR);
-
- /* read erasecounter header */
- rc = fread(&cur->inner, 1, sizeof(cur->inner), fpin);
+ fseek(fpin, ubi32_to_cpu(cur->ec.vid_hdr_offset), SEEK_CUR);
+ rc = fread(&cur->vid, 1, sizeof(cur->vid), fpin);
if (rc == 0)
goto out; /* EOF */
- if (rc != sizeof(cur->inner)) {
- ERR_MSG("reading vid-hdr failed rc=%d\n", rc);
+ if (rc != sizeof(cur->vid)) {
+ ERR_MSG("reading vid-hdr failed\n");
rc = -1;
goto err;
}
- /* empty? */
- if (ubi32_to_cpu(cur->inner.magic) == 0xffffffff) {
+ /* if the magic number is 0xFFFFFFFF, then it's very likely
+ * that the volume is empty */
+ if (ubi32_to_cpu(cur->vid.magic) == 0xffffffff) {
snprintf(reason, MAXPATH, ".empty");
goto invalid;
}
/* vol_id should be in bounds */
- if ((ubi32_to_cpu(cur->inner.vol_id) >= UBI_MAX_VOLUMES) &&
- (ubi32_to_cpu(cur->inner.vol_id) <
+ if ((ubi32_to_cpu(cur->vid.vol_id) >= UBI_MAX_VOLUMES) &&
+ (ubi32_to_cpu(cur->vid.vol_id) <
UBI_INTERNAL_VOL_START)) {
snprintf(reason, MAXPATH, ".invalid");
goto invalid;
@@ -587,25 +734,28 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
raw_path = FN_NSURE;
/* check volume id header magic */
- if (ubi32_to_cpu(cur->inner.magic) != UBI_VID_HDR_MAGIC) {
+ if (ubi32_to_cpu(cur->vid.magic) != UBI_VID_HDR_MAGIC) {
snprintf(reason, MAXPATH, ".invalid.vid_magic");
goto invalid;
}
/* check volume id header crc */
- header_crc(NULL, &(cur->inner), &crc);
- if (ubi32_to_cpu(cur->inner.hdr_crc) != crc) {
+ header_crc(NULL, &(cur->vid), &crc);
+ if (ubi32_to_cpu(cur->vid.hdr_crc) != crc) {
snprintf(reason, MAXPATH, ".invalid.vid_hdr_crc");
goto invalid;
}
- /* check data crc */
- rc = data_crc(fpin, ubi32_to_cpu(cur->inner.data_size), &crc);
- if (rc < 0)
- goto err;
- if (ubi32_to_cpu(cur->inner.data_crc) != crc) {
- snprintf(reason, MAXPATH, ".invalid.data_crc");
- goto invalid;
+ /* check data crc, but only for a static volume */
+ if (cur->vid.vol_type == UBI_VID_STATIC) {
+ rc = data_crc(fpin, ubi32_to_cpu(cur->vid.data_size),
+ &crc);
+ if (rc < 0)
+ goto err;
+ if (ubi32_to_cpu(cur->vid.data_crc) != crc) {
+ snprintf(reason, MAXPATH, ".invalid.data_crc");
+ goto invalid;
+ }
}
/* enlist this vol, it's valid */
@@ -622,6 +772,15 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
goto err;
}
+ /* extract info-table */
+ if (a->itable &&
+ (ubi32_to_cpu(cur->vid.vol_id) == UBI_LAYOUT_VOL_ID)) {
+ extract_itable(fpin, cur, a->bsize,
+ itable_num, a->odir_path);
+ itable_num++;
+ }
+
+ /* split volumes */
if (a->vol_split) {
size_t size = 0;
@@ -631,9 +790,9 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
if (a->vol_split == SPLIT_DATA) {
/* write only data section */
- size = ubi32_to_cpu(cur->inner.data_size);
+ size = ubi32_to_cpu(cur->vid.data_size);
fseek(fpin,
- ubi32_to_cpu(cur->outer.data_offset),
+ ubi32_to_cpu(cur->ec.data_offset),
SEEK_CUR);
}
else if (a->vol_split == SPLIT_RAW)
@@ -642,15 +801,16 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
snprintf(filename, MAXPATH, FN_VOLSP,
a->odir_path,
- ubi32_to_cpu(cur->inner.vol_id),
- ubi32_to_cpu(cur->inner.lnum),
- ubi32_to_cpu(cur->inner.leb_ver), count);
+ ubi32_to_cpu(cur->vid.vol_id),
+ ubi32_to_cpu(cur->vid.lnum),
+ ubi32_to_cpu(cur->vid.leb_ver), count);
rc = extract_data(fpin, size, filename);
if (rc < 0)
goto err;
}
invalid:
+ /* split eraseblocks */
if (a->eb_split) {
/* jump to top of block */
rc = fsetpos(fpin, &(cur->eb_top));
@@ -664,9 +824,9 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
snprintf(filename, MAXPATH, raw_path,
a->odir_path,
count,
- ubi32_to_cpu(cur->inner.vol_id),
- ubi32_to_cpu(cur->inner.lnum),
- ubi32_to_cpu(cur->inner.leb_ver),
+ ubi32_to_cpu(cur->vid.vol_id),
+ ubi32_to_cpu(cur->vid.lnum),
+ ubi32_to_cpu(cur->vid.leb_ver),
reason);
rc = extract_data(fpin, a->bsize, filename);
@@ -704,15 +864,18 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
out:
for (i = 0; i < vc; i++) {
- rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path);
+ rc = rebuild_volume(fpin, &vols[i], &head, a->odir_path,
+ a->bsize, a->hsize);
if (rc < 0)
goto err;
}
/* if there were no volumes specified, rebuild them all,
* UNLESS eb_ or vol_ split or analyze was specified */
- if ((vc == 0) && (!a->eb_split) && (!a->vol_split) && (!a->analyze)) {
- rc = rebuild_volume(fpin, NULL, &head, a->odir_path);
+ if ((vc == 0) && (!a->eb_split) && (!a->vol_split) &&
+ (!a->analyze) && (!a->itable)) {
+ rc = rebuild_volume(fpin, NULL, &head, a->odir_path, a->bsize,
+ a->hsize);
if (rc < 0)
goto err;
}
@@ -722,6 +885,7 @@ unubi_volumes(FILE* fpin, uint32_t *vols, size_t vc, struct args *a)
if (a->analyze)
unubi_analyze(&head, first, a->odir_path);
+
eb_chain_destroy(&head);
eb_chain_destroy(&first);
@@ -751,6 +915,7 @@ main(int argc, char *argv[])
/* setup struct args a */
memset(&a, 0, sizeof(a));
a.bsize = 128 * KIB;
+ a.hsize = 2 * KIB;
a.vols = malloc(sizeof(*a.vols) * UBI_MAX_VOLUMES);
if (a.vols == NULL) {
ERR_MSG("out of memory\n");
@@ -818,8 +983,8 @@ main(int argc, char *argv[])
/* unubi volumes */
rc = unubi_volumes(fpin, vols, vols_len, &a);
if (rc < 0) {
- ERR_MSG("error encountered while working on image file: "
- "%s\n", a.img_path);
+ /* ERR_MSG("error encountered while working on image file: "
+ "%s\n", a.img_path); */
rc = -rc;
goto err;
}
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
index 6009fc0..e5bbb23 100644
--- a/ubi-utils/src/unubi_analyze.c
+++ b/ubi-utils/src/unubi_analyze.c
@@ -113,6 +113,9 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
FILE* fpplot;
eb_info_t cur;
+ if (first == NULL)
+ return -1;
+
/* crc check still needed for `first' linked list */
init_crc32_table(crc32_table);
@@ -126,9 +129,12 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
memset(filename, 0, MAXPATH + 1);
snprintf(filename, MAXPATH, "%s/%s", path, FN_EH_PLOT);
fpplot = fopen(filename, "w");
- if (fpplot == NULL)
+ if (fpplot == NULL) {
+ fclose(fpdata);
return -1;
+ }
+ /* make executable */
chmod(filename, 0755);
/* first run: count elements */
@@ -146,8 +152,8 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
/* second run: populate array to sort */
count = 0;
cur = first;
- while(cur != NULL) {
- erase_counts[count] = ubi64_to_cpu(cur->outer.ec);
+ while (cur != NULL) {
+ erase_counts[count] = ubi64_to_cpu(cur->ec.ec);
cur = cur->next;
count++;
}
@@ -160,24 +166,24 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
fprintf(fpdata, "# eraseblock_no actual_erase_count "
"sorted_erase_count\n");
while (cur != NULL) {
- crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->outer,
+ crc = clc_crc32(crc32_table, UBI_CRC32_INIT, &cur->ec,
UBI_EC_HDR_SIZE_CRC);
- if ((ubi32_to_cpu(cur->outer.magic) != UBI_EC_HDR_MAGIC) ||
- (crc != ubi32_to_cpu(cur->outer.hdr_crc)))
+ if ((ubi32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) ||
+ (crc != ubi32_to_cpu(cur->ec.hdr_crc)))
fprintf(fpdata, "# ");
- fprintf(fpdata, "%zu %llu %llu", count,
- (unsigned long long) ubi64_to_cpu(cur->outer.ec),
- (unsigned long long) erase_counts[count]);
+ fprintf(fpdata, "%u %llu %llu", count,
+ ubi64_to_cpu(cur->ec.ec),
+ erase_counts[count]);
- if (ubi32_to_cpu(cur->outer.magic) != UBI_EC_HDR_MAGIC)
+ if (ubi32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC)
fprintf(fpdata, " ## bad magic: %08x",
- ubi32_to_cpu(cur->outer.magic));
+ ubi32_to_cpu(cur->ec.magic));
- if (crc != ubi32_to_cpu(cur->outer.hdr_crc))
+ if (crc != ubi32_to_cpu(cur->ec.hdr_crc))
fprintf(fpdata, " ## CRC mismatch: given=%08x, "
- "calc=%08x", ubi32_to_cpu(cur->outer.hdr_crc),
+ "calc=%08x", ubi32_to_cpu(cur->ec.hdr_crc),
crc);
fprintf(fpdata, "\n");
@@ -198,7 +204,7 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
if ((count % EC_X_INT) == 0) {
if (count > 0)
fprintf(fpplot, ", ");
- fprintf(fpplot, "%zd", count);
+ fprintf(fpplot, "%d", count);
}
cur = cur->next;
@@ -207,9 +213,9 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
fprintf(fpplot, ")\n");
fprintf(fpplot, "set ylabel \"erase count\"\n");
- fprintf(fpplot, "set xrange [-1:%zu]\n", eraseblocks + 1);
+ fprintf(fpplot, "set xrange [-1:%u]\n", eraseblocks + 1);
fprintf(fpplot, "# set yrange [-1:%llu]\n",
- (unsigned long long) erase_counts[eraseblocks - 1] + 1);
+ erase_counts[eraseblocks - 1] + 1);
fprintf(fpplot, "plot \"%s\" u 1:2 t \"unsorted: %s\" with boxes\n",
FN_EH_DATA, FN_EH_DATA);
fprintf(fpplot, "# replot \"%s\" u 1:3 t \"sorted: %s\" with lines\n",
@@ -236,26 +242,40 @@ int
unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
{
char filename[MAXPATH + 1];
- int y1, y2;
+ int rc, y1, y2;
size_t count, step, breadth;
uint32_t *leb_versions, *data_sizes;
FILE* fpdata;
FILE* fpplot;
eb_info_t cur;
+ if (head == NULL || *head == NULL)
+ return -1;
+
+ rc = 0;
+ fpdata = NULL;
+ fpplot = NULL;
+ data_sizes = NULL;
+ leb_versions = NULL;
+
/* prepare output files */
memset(filename, 0, MAXPATH + 1);
snprintf(filename, MAXPATH, "%s/%s", path, FN_VH_DATA);
fpdata = fopen(filename, "w");
- if (fpdata == NULL)
- return -1;
+ if (fpdata == NULL) {
+ rc = -1;
+ goto exit;
+ }
memset(filename, 0, MAXPATH + 1);
snprintf(filename, MAXPATH, "%s/%s", path, FN_VH_PLOT);
fpplot = fopen(filename, "w");
- if (fpplot == NULL)
- return -1;
+ if (fpplot == NULL) {
+ rc = -1;
+ goto exit;
+ }
+ /* make executable */
chmod(filename, 0755);
/* first run: count elements */
@@ -267,18 +287,26 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
}
breadth = count;
- leb_versions = malloc(breadth * sizeof(*leb_versions));
- memset(leb_versions, 0, breadth * sizeof(*leb_versions));
+ leb_versions = malloc(breadth * sizeof(uint32_t));
+ if (leb_versions == NULL) {
+ rc = -1;
+ goto exit;
+ }
+ memset(leb_versions, 0, breadth * sizeof(uint32_t));
- data_sizes = malloc(breadth * sizeof(*data_sizes));
+ data_sizes = malloc(breadth * sizeof(uint32_t));
+ if (data_sizes == NULL) {
+ rc = -1;
+ goto exit;
+ }
memset(data_sizes, 0, breadth * sizeof(*data_sizes));
/* second run: populate arrays to sort */
count = 0;
cur = *head;
while (cur != NULL) {
- leb_versions[count] = ubi32_to_cpu(cur->inner.leb_ver);
- data_sizes[count] = ubi32_to_cpu(cur->inner.data_size);
+ leb_versions[count] = ubi32_to_cpu(cur->vid.leb_ver);
+ data_sizes[count] = ubi32_to_cpu(cur->vid.data_size);
cur = cur->next;
count++;
}
@@ -291,26 +319,27 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
fprintf(fpdata, "# x_axis vol_id lnum y1_axis leb_ver "
"y2_axis data_size\n");
while (cur != NULL) {
- y1 = norm_index(ubi32_to_cpu(cur->inner.leb_ver), leb_versions,
+ y1 = norm_index(ubi32_to_cpu(cur->vid.leb_ver), leb_versions,
breadth);
- y2 = norm_index(ubi32_to_cpu(cur->inner.data_size), data_sizes,
+ y2 = norm_index(ubi32_to_cpu(cur->vid.data_size), data_sizes,
breadth);
- if ((y1 == -1) || (y2 == -1))
- return -1;
+ if ((y1 == -1) || (y2 == -1)) {
+ rc = -1;
+ goto exit;
+ }
- fprintf(fpdata, "%zu %u %u %u %u %u %u\n",
+ fprintf(fpdata, "%u %u %u %u %u %u %u\n",
count,
- ubi32_to_cpu(cur->inner.vol_id),
- ubi32_to_cpu(cur->inner.lnum),
+ ubi32_to_cpu(cur->vid.vol_id),
+ ubi32_to_cpu(cur->vid.lnum),
y1,
- ubi32_to_cpu(cur->inner.leb_ver),
+ ubi32_to_cpu(cur->vid.leb_ver),
y2,
- ubi32_to_cpu(cur->inner.data_size));
+ ubi32_to_cpu(cur->vid.data_size));
cur = cur->next;
count++;
}
- fclose(fpdata);
fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
fprintf(fpplot, "set xlabel \"volume\"\n");
@@ -323,13 +352,13 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
while (cur != NULL) {
if (count > 0)
fprintf(fpplot, ", ");
- if (step != ubi32_to_cpu(cur->inner.vol_id)) {
- step = ubi32_to_cpu(cur->inner.vol_id);
- fprintf(fpplot, "\"%zd\" %zd 0", step, count);
+ if (step != ubi32_to_cpu(cur->vid.vol_id)) {
+ step = ubi32_to_cpu(cur->vid.vol_id);
+ fprintf(fpplot, "\"%d\" %d 0", step, count);
}
else
- fprintf(fpplot, "\"%d\" %zd 1",
- ubi32_to_cpu(cur->inner.lnum), count);
+ fprintf(fpplot, "\"%d\" %d 1",
+ ubi32_to_cpu(cur->vid.lnum), count);
cur = cur->next;
count++;
}
@@ -341,17 +370,19 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
cur = *head;
fprintf(fpplot, "set ylabel \"leb version\"\n");
fprintf(fpplot, "set ytics (");
- while (cur != NULL) {
- y1 = norm_index(ubi32_to_cpu(cur->inner.leb_ver), leb_versions,
+ while (cur->next != NULL) {
+ y1 = norm_index(ubi32_to_cpu(cur->vid.leb_ver), leb_versions,
breadth);
- if (y1 == -1)
- return -1;
+ if (y1 == -1) {
+ rc = -1;
+ goto exit;
+ }
if (count > 0)
fprintf(fpplot, ", ");
- fprintf(fpplot, "\"%u\" %u", ubi32_to_cpu(cur->inner.leb_ver),
+ fprintf(fpplot, "\"%u\" %u", ubi32_to_cpu(cur->vid.leb_ver),
y1);
cur = cur->next;
@@ -365,16 +396,18 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
fprintf(fpplot, "set y2label \"data size\"\n");
fprintf(fpplot, "set y2tics (");
while (cur != NULL) {
- y2 = norm_index(ubi32_to_cpu(cur->inner.data_size),
+ y2 = norm_index(ubi32_to_cpu(cur->vid.data_size),
data_sizes, breadth);
- if (y2 == -1)
- return -1;
+ if (y2 == -1) {
+ rc = -1;
+ goto exit;
+ }
if (count > 0)
fprintf(fpplot, ", ");
- fprintf(fpplot, "\"%u\" %u", ubi32_to_cpu(cur->inner.data_size),
+ fprintf(fpplot, "\"%u\" %u", ubi32_to_cpu(cur->vid.data_size),
y2);
cur = cur->next;
@@ -384,7 +417,7 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
y1 = norm_index(leb_versions[breadth - 1], leb_versions, breadth);
y2 = norm_index(data_sizes[breadth - 1], data_sizes, breadth);
- fprintf(fpplot, "set xrange [-1:%zu]\n", count + 1);
+ fprintf(fpplot, "set xrange [-1:%u]\n", count + 1);
fprintf(fpplot, "set yrange [-1:%u]\n", y1 + 1);
fprintf(fpplot, "set y2range [-1:%u]\n", y2 + 1);
fprintf(fpplot, "plot \"%s\" u 1:4 t \"leb version: %s\" "
@@ -393,12 +426,17 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
"axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA);
fprintf(fpplot, "pause -1 \"press ENTER\"\n");
- fclose(fpplot);
-
- free(data_sizes);
- free(leb_versions);
-
- return 0;
+ exit:
+ if (fpdata != NULL)
+ fclose(fpdata);
+ if (fpplot != NULL)
+ fclose(fpplot);
+ if (data_sizes != NULL)
+ free(data_sizes);
+ if (leb_versions != NULL)
+ free(leb_versions);
+
+ return rc;
}
@@ -412,23 +450,14 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
int
unubi_analyze(eb_info_t *head, eb_info_t first, const char *path)
{
- int rc;
+ int ec_rc, vid_rc;
if (path == NULL)
return -1;
- if (first == NULL)
- return -1;
-
- if ((head == NULL) || (*head == NULL))
- return -1;
-
- rc = unubi_analyze_ec_hdr(first, path);
- if (rc < 0)
- return -1;
-
- rc = unubi_analyze_vid_hdr(head, path);
- if (rc < 0)
+ ec_rc = unubi_analyze_ec_hdr(first, path);
+ vid_rc = unubi_analyze_vid_hdr(head, path);
+ if (ec_rc < 0 || vid_rc < 0)
return -1;
return 0;