aboutsummaryrefslogtreecommitdiff
path: root/ubi-utils
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils')
-rw-r--r--ubi-utils/scripts/unubi_test.sh82
-rw-r--r--ubi-utils/src/eb_chain.c135
-rw-r--r--ubi-utils/src/eb_chain.h73
-rw-r--r--ubi-utils/src/unubi.c141
-rw-r--r--ubi-utils/src/unubi_analyze.c48
-rw-r--r--ubi-utils/src/unubi_analyze.h70
6 files changed, 294 insertions, 255 deletions
diff --git a/ubi-utils/scripts/unubi_test.sh b/ubi-utils/scripts/unubi_test.sh
index 1cbe426..40dc2e2 100644
--- a/ubi-utils/scripts/unubi_test.sh
+++ b/ubi-utils/scripts/unubi_test.sh
@@ -6,56 +6,100 @@
# 2007 Frank Haverkamp <haver@vnet.ibm.com>
#
-version=1.0
+version=1.1
image=data.mif
oob=oob.bin
data=data.bin
pagesize=2048
volmax=31
-datadir=unubi_data.bin
+datadir=unubi_data
-echo "Testcase: ${0} Version: ${version}"
-echo
-
-if [ -f $1 ]; then
- image=${1}
-fi
+# general arguments e.g. debug enablement
+# unubi_args="-D"
+echo "------------------------------------------------------------------------"
+echo "Testcase: ${0} Version: ${version}"
+echo "------------------------------------------------------------------------"
echo "Testing nand2bin ..."
echo " Input: ${image}"
echo " Data: ${data}"
echo " OOB: ${oob}"
echo " Pagesize: ${pagesize}"
-
nand2bin --pagesize ${pagesize} -o ${data} -O ${oob} ${image}
echo
+echo "------------------------------------------------------------------------"
echo "Testing unubi ..."
+echo "------------------------------------------------------------------------"
unubi --version
+echo
+echo "------------------------------------------------------------------------"
echo "Trying to extract first ${volmax} volumes ..."
+echo "------------------------------------------------------------------------"
+mkdir -p ${datadir}/volumes
for v in `seq 0 ${volmax}` ; do
- unubi -r${v} ${data}
+ unubi ${unubi_args} -r${v} -d${datadir}/volumes ${data}
echo -n "."
done
echo "ok"
+ls -l ${datadir}/volumes
+echo
-ls -l unubi_data.bin/
-
+echo "------------------------------------------------------------------------"
echo "Extracting graphics ..."
-unubi -a ${data}
+echo "------------------------------------------------------------------------"
+unubi -a -d${datadir} ${data}
+echo "Use gnuplot to display:"
+ls ${datadir}/*.plot
+ls ${datadir}/*.data
+echo
+echo "------------------------------------------------------------------------"
+echo "eb-split"
+echo "------------------------------------------------------------------------"
+unubi -e -d${datadir}/eb-split ${data}
+ls -l ${datadir}/eb-split
+echo
-echo "Extracting volume info table ..."
-unubi -i ${data}
+echo "------------------------------------------------------------------------"
+echo "vol-split"
+echo "------------------------------------------------------------------------"
+unubi -v -d${datadir}/vol-split ${data}
+ls -l ${datadir}/vol-split
+echo
+echo "The generated images contain only the data (126KiB in our "
+echo "case) not including the UBI erase count and volume info "
+echo "header. For dynamic volumes the data should be the full "
+echo "126KiB. Unubi cannot know how much of the data is valid. "
+echo
+
+echo "------------------------------------------------------------------------"
+echo "!vol-split"
+echo "------------------------------------------------------------------------"
+unubi -V -d${datadir}/vol-split! ${data}
+ls -l ${datadir}/vol-split\!
+echo
+echo "The generated images contain the full block data of 128KiB "
+echo "including the UBI erase count and volume information header."
+echo
+echo "------------------------------------------------------------------------"
+echo "Extracting volume info table ..."
+echo "------------------------------------------------------------------------"
+unubi -i -d${datadir} ${data}
+echo "I strongly hope that empty ubi blocks are filled with 0xff! "
echo
+
+echo "------------------------------------------------------------------------"
echo "Table 0"
-echo "-------"
+echo "------------------------------------------------------------------------"
cat ${datadir}/vol_info_table0
-
echo
+
+echo "------------------------------------------------------------------------"
echo "Table 1"
-echo "-------"
-cat ${datadir}/vol_info_table1 \ No newline at end of file
+echo "------------------------------------------------------------------------"
+cat ${datadir}/vol_info_table1
+echo
diff --git a/ubi-utils/src/eb_chain.c b/ubi-utils/src/eb_chain.c
index 22594c5..8f6e327 100644
--- a/ubi-utils/src/eb_chain.c
+++ b/ubi-utils/src/eb_chain.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
@@ -26,12 +26,11 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include "eb_chain.h"
+#include "unubi_analyze.h"
#include "crc32.h"
#define COPY(dst, src) \
- do \
- { \
+ do { \
dst = malloc(sizeof(*dst)); \
if (dst == NULL) \
return -ENOMEM; \
@@ -50,18 +49,17 @@
* meaning there is a bug or a case not being handled here;
**/
int
-eb_chain_insert(eb_info_t *head, eb_info_t new)
+eb_chain_insert(struct eb_info **head, struct eb_info *new)
{
uint32_t vol, num, ver;
uint32_t new_vol, new_num, new_ver;
- eb_info_t prev, cur, hist, ins;
- eb_info_t *prev_ptr;
+ struct eb_info *prev, *cur, *hist, *ins;
+ struct eb_info **prev_ptr;
if ((head == NULL) || (new == NULL))
return 0;
- if (*head == NULL)
- {
+ if (*head == NULL) {
COPY(*head, new);
(*head)->next = NULL;
return 0;
@@ -79,11 +77,9 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
/* traverse until vol_id/lnum align */
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)))
- {
+ while ((new_vol > vol) || ((new_vol == vol) && (new_num > num))) {
/* insert new at end of chain */
- if (cur->next == NULL)
- {
+ if (cur->next == NULL) {
COPY(ins, new);
ins->next = NULL;
cur->next = ins;
@@ -102,8 +98,7 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
prev_ptr = &(prev->next);
/* insert new into the middle of chain */
- if ((new_vol != vol) || (new_num != num))
- {
+ if ((new_vol != vol) || (new_num != num)) {
COPY(ins, new);
ins->next = cur;
*prev_ptr = ins;
@@ -117,11 +112,9 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
/* traverse until versions align */
ver = ubi32_to_cpu(cur->vid.leb_ver);
- while (new_ver < ver)
- {
+ while (new_ver < ver) {
/* insert new at bottom of history */
- if (hist->older == NULL)
- {
+ if (hist->older == NULL) {
COPY(ins, new);
ins->next = NULL;
ins->older = NULL;
@@ -134,8 +127,7 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
ver = ubi32_to_cpu(hist->vid.leb_ver);
}
- if (prev == NULL)
- {
+ if (prev == NULL) {
/* replace active version */
COPY(ins, new);
ins->next = hist->next;
@@ -146,18 +138,13 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
hist->next = NULL;
return 0;
}
- else
- {
- /* insert between versions, beneath active version */
- COPY(ins, new);
- ins->next = NULL;
- ins->older = prev->older;
- prev->older = ins;
- return 0;
- }
- /* logically impossible to reach this point... hopefully */
- return -EAGAIN;
+ /* insert between versions, beneath active version */
+ COPY(ins, new);
+ ins->next = NULL;
+ ins->older = prev->older;
+ prev->older = ins;
+ return 0;
}
@@ -168,11 +155,11 @@ eb_chain_insert(eb_info_t *head, eb_info_t new)
* always returns 0;
**/
int
-eb_chain_position(eb_info_t *head, uint32_t vol_id, uint32_t *lnum,
- eb_info_t *pos)
+eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
+ struct eb_info **pos)
{
uint32_t vol, num;
- eb_info_t cur;
+ struct eb_info *cur;
if ((head == NULL) || (*head == NULL) || (pos == NULL))
return 0;
@@ -180,17 +167,14 @@ eb_chain_position(eb_info_t *head, uint32_t vol_id, uint32_t *lnum,
*pos = NULL;
cur = *head;
- while (cur != NULL)
- {
+ while (cur != NULL) {
vol = ubi32_to_cpu(cur->vid.vol_id);
num = ubi32_to_cpu(cur->vid.lnum);
- if (vol_id == vol)
- if ((lnum == NULL) || (*lnum == num))
- {
- *pos = cur;
- return 0;
- }
+ if ((vol_id == vol) && ((lnum == NULL) || (*lnum == num))) {
+ *pos = cur;
+ return 0;
+ }
cur = cur->next;
}
@@ -206,43 +190,53 @@ eb_chain_position(eb_info_t *head, uint32_t vol_id, uint32_t *lnum,
* always returns 0;
**/
int
-eb_chain_print(FILE* stream, eb_info_t *head)
+eb_chain_print(FILE* stream, struct eb_info *head)
{
- eb_info_t cur;
-
- if (head == NULL)
- return 0;
+ struct eb_info *cur;
if (stream == NULL)
stream = stdout;
- if (*head == NULL)
- {
+ if (head == NULL) {
fprintf(stream, "EMPTY\n");
return 0;
}
+ /* 012345678012345678012345678012301230123 01234567 0123457 01234567*/
+ fprintf(stream, "VOL_ID LNUM LEB_VER EC VID DAT PADDR DSIZE EC\n");
+ cur = head;
+ while (cur != NULL) {
+ struct eb_info *hist;
- cur = *head;
- while (cur != NULL)
- {
- eb_info_t hist;
-
- fprintf(stream, " VOL %4u-%04u | VER 0x%8x\n",
+ fprintf(stream, "%08x %-8u %-8u %-4s%-4s",
ubi32_to_cpu(cur->vid.vol_id),
ubi32_to_cpu(cur->vid.lnum),
- ubi32_to_cpu(cur->vid.leb_ver));
+ ubi32_to_cpu(cur->vid.leb_ver),
+ cur->ec_crc_ok ? "ok":"bad",
+ cur->vid_crc_ok ? "ok":"bad");
+ if (cur->vid.vol_type == UBI_VID_STATIC)
+ fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"bad");
+ else fprintf(stream, "%-4s", cur->data_crc_ok ? "ok":"ign");
+ fprintf(stream, " %08x %-8u %-8llu\n", cur->phys_addr,
+ ubi32_to_cpu(cur->vid.data_size),
+ ubi64_to_cpu(cur->ec.ec));
hist = cur->older;
- while (hist != NULL)
- {
- fprintf(stream, "+ VOL %4u-%04u | VER 0x%8x\n",
+ while (hist != NULL) {
+ fprintf(stream, "%08x %-8u %-8u %-4s%-4s",
ubi32_to_cpu(hist->vid.vol_id),
ubi32_to_cpu(hist->vid.lnum),
- ubi32_to_cpu(hist->vid.leb_ver));
+ ubi32_to_cpu(hist->vid.leb_ver),
+ hist->ec_crc_ok ? "ok":"bad",
+ hist->vid_crc_ok ? "ok":"bad");
+ if (hist->vid.vol_type == UBI_VID_STATIC)
+ fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"bad");
+ else fprintf(stream, "%-4s", hist->data_crc_ok ? "ok":"ign");
+ fprintf(stream, " %08x %-8u %-8llu (*)\n", hist->phys_addr,
+ ubi32_to_cpu(hist->vid.data_size),
+ ubi64_to_cpu(hist->ec.ec));
hist = hist->older;
}
-
cur = cur->next;
}
@@ -256,33 +250,28 @@ eb_chain_print(FILE* stream, eb_info_t *head)
* always returns 0;
**/
int
-eb_chain_destroy(eb_info_t *head)
+eb_chain_destroy(struct eb_info **head)
{
if (head == NULL)
return 0;
- while (*head != NULL)
- {
- eb_info_t cur;
- eb_info_t hist;
+ while (*head != NULL) {
+ struct eb_info *cur;
+ struct eb_info *hist;
cur = *head;
*head = (*head)->next;
hist = cur->older;
- while (hist != NULL)
- {
- eb_info_t temp;
+ while (hist != NULL) {
+ struct eb_info *temp;
temp = hist;
hist = hist->older;
-
free(temp);
}
-
free(cur);
}
-
return 0;
}
diff --git a/ubi-utils/src/eb_chain.h b/ubi-utils/src/eb_chain.h
deleted file mode 100644
index 4c94058..0000000
--- a/ubi-utils/src/eb_chain.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __EB_CHAIN_H__
-#define __EB_CHAIN_H__
-
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- */
-
-/*
- * Author: Drake Dowsett
- * Contact: Andreas Arnez (arnez@de.ibm.com)
- *
- * Eraseblock Chain
- *
- * A linked list structure to order eraseblocks by volume and logical number
- * and to update by version number. Doesn't contain actual eraseblock data
- * but rather the erasecounter and volume id headers as well as a position
- * indicator.
- *
- * Diagram Example:
- *
- * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL
- * | | | | | |
- * NULL [V1.1v1] [V1.2v0] [V2.0v1] NULL [V2.2v0]
- * | | | |
- * [V1.1v0] NULL [V2.0v0] NULL
- * | |
- * NULL NULL
- *
- * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A,
- * lnum B and leb_ver C
- * -> represents the `next' pointer
- * | represents the `older' pointer
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <mtd/ubi-header.h>
-
-typedef struct eb_info *eb_info_t;
-struct eb_info {
- struct ubi_ec_hdr ec;
- struct ubi_vid_hdr vid;
- fpos_t eb_top;
- uint32_t linear;
-
- eb_info_t next;
- eb_info_t older;
-};
-
-int eb_chain_insert(eb_info_t *head, eb_info_t item);
-
-int eb_chain_position(eb_info_t *head, uint32_t vol_id, uint32_t *lnum,
- eb_info_t *pos);
-
-int eb_chain_print(FILE *stream, eb_info_t *head);
-
-int eb_chain_destroy(eb_info_t *head);
-
-#endif /* __EB_CHAIN_H__ */
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);
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
index e5bbb23..c2fbe47 100644
--- a/ubi-utils/src/unubi_analyze.c
+++ b/ubi-utils/src/unubi_analyze.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
@@ -32,22 +32,15 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include "eb_chain.h"
+#include "unubi_analyze.h"
#include "crc32.h"
-#define MAXPATH 1024
#define EC_X_INT 50
-#define FN_STATS "analysis_stats.txt"
-#define FN_EH_DATA "analysis_ec_hdr.data"
-#define FN_EH_PLOT "analysis_ec_hdr.plot"
-#define FN_VH_DATA "analysis_vid_hdr.data"
-#define FN_VH_PLOT "analysis_vid_hdr.plot"
-
-
/**
* intcmp - function needed by qsort to order integers
**/
@@ -103,15 +96,15 @@ norm_index(uint32_t item, uint32_t *array, size_t length)
* display of the data file;
**/
int
-unubi_analyze_ec_hdr(eb_info_t first, const char *path)
+unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
{
- char filename[MAXPATH + 1];
+ char filename[PATH_MAX + 1];
size_t count, eraseblocks;
uint32_t crc, crc32_table[256];
uint64_t *erase_counts;
FILE* fpdata;
FILE* fpplot;
- eb_info_t cur;
+ struct eb_info *cur;
if (first == NULL)
return -1;
@@ -120,14 +113,14 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
init_crc32_table(crc32_table);
/* prepare output files */
- memset(filename, 0, MAXPATH + 1);
- snprintf(filename, MAXPATH, "%s/%s", path, FN_EH_DATA);
+ memset(filename, 0, PATH_MAX + 1);
+ snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_DATA);
fpdata = fopen(filename, "w");
if (fpdata == NULL)
return -1;
- memset(filename, 0, MAXPATH + 1);
- snprintf(filename, MAXPATH, "%s/%s", path, FN_EH_PLOT);
+ memset(filename, 0, PATH_MAX + 1);
+ snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT);
fpplot = fopen(filename, "w");
if (fpplot == NULL) {
fclose(fpdata);
@@ -147,6 +140,11 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
eraseblocks = count;
erase_counts = malloc(eraseblocks * sizeof(*erase_counts));
+ if (!erase_counts) {
+ perror("out of memory");
+ exit(EXIT_FAILURE);
+ }
+
memset(erase_counts, 0, eraseblocks * sizeof(*erase_counts));
/* second run: populate array to sort */
@@ -239,15 +237,15 @@ unubi_analyze_ec_hdr(eb_info_t first, const char *path)
* display of the data file;
**/
int
-unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
+unubi_analyze_vid_hdr(struct eb_info **head, const char *path)
{
- char filename[MAXPATH + 1];
+ char filename[PATH_MAX + 1];
int rc, y1, y2;
size_t count, step, breadth;
uint32_t *leb_versions, *data_sizes;
FILE* fpdata;
FILE* fpplot;
- eb_info_t cur;
+ struct eb_info *cur;
if (head == NULL || *head == NULL)
return -1;
@@ -259,16 +257,16 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
leb_versions = NULL;
/* prepare output files */
- memset(filename, 0, MAXPATH + 1);
- snprintf(filename, MAXPATH, "%s/%s", path, FN_VH_DATA);
+ memset(filename, 0, PATH_MAX + 1);
+ snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_DATA);
fpdata = fopen(filename, "w");
if (fpdata == NULL) {
rc = -1;
goto exit;
}
- memset(filename, 0, MAXPATH + 1);
- snprintf(filename, MAXPATH, "%s/%s", path, FN_VH_PLOT);
+ memset(filename, 0, PATH_MAX + 1);
+ snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT);
fpplot = fopen(filename, "w");
if (fpplot == NULL) {
rc = -1;
@@ -448,7 +446,7 @@ unubi_analyze_vid_hdr(eb_info_t *head, const char *path)
* returns 0 upon successful completion, or -1 otherwise
**/
int
-unubi_analyze(eb_info_t *head, eb_info_t first, const char *path)
+unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path)
{
int ec_rc, vid_rc;
diff --git a/ubi-utils/src/unubi_analyze.h b/ubi-utils/src/unubi_analyze.h
index ac01a44..243ea58 100644
--- a/ubi-utils/src/unubi_analyze.h
+++ b/ubi-utils/src/unubi_analyze.h
@@ -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
@@ -16,11 +16,71 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#ifndef __UNUBI_ANALYZE_H__
+#define __UNUBI_ANALYZE_H__
+
/*
- * Authors: Drake Dowsett, dowsett@de.ibm.com
+ * Author: Drake Dowsett
+ * Contact: Andreas Arnez (arnez@de.ibm.com)
+ *
+ * Eraseblock Chain
+ *
+ * A linked list structure to order eraseblocks by volume and logical number
+ * and to update by version number. Doesn't contain actual eraseblock data
+ * but rather the erasecounter and volume id headers as well as a position
+ * indicator.
+ *
+ * Diagram Example:
+ *
+ * [V1.0v0]->[V1.1v2]->[V1.2v1]->[V2.0v2]->[V2.1v0]->[V2.2v1]->NULL
+ * | | | | | |
+ * NULL [V1.1v1] [V1.2v0] [V2.0v1] NULL [V2.2v0]
+ * | | | |
+ * [V1.1v0] NULL [V2.0v0] NULL
+ * | |
+ * NULL NULL
+ *
+ * [VA.BvC] represents the eb_info for the eraseblock with the vol_id A,
+ * lnum B and leb_ver C
+ * -> represents the `next' pointer
+ * | represents the `older' pointer
*/
-#include "eb_chain.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <mtd/ubi-header.h>
+
+#define FN_EH_STAT "analysis_blocks.txt"
+#define FN_EH_DATA "analysis_ec_hdr.data"
+#define FN_EH_PLOT "analysis_ec_hdr.plot"
+#define FN_VH_DATA "analysis_vid_hdr.data"
+#define FN_VH_PLOT "analysis_vid_hdr.plot"
+
+struct eb_info {
+ struct ubi_ec_hdr ec;
+ struct ubi_vid_hdr vid;
+
+ fpos_t eb_top;
+ uint32_t linear;
+ int ec_crc_ok;
+ int vid_crc_ok;
+ int data_crc_ok;
+ uint32_t phys_addr;
+
+ struct eb_info *next;
+ struct eb_info *older;
+};
+
+int eb_chain_insert(struct eb_info **head, struct eb_info *item);
+
+int eb_chain_position(struct eb_info **head, uint32_t vol_id, uint32_t *lnum,
+ struct eb_info **pos);
+
+int eb_chain_print(FILE *stream, struct eb_info *head);
+
+int eb_chain_destroy(struct eb_info **head);
+
+int unubi_analyze(struct eb_info **head, struct eb_info *first,
+ const char *path);
-int
-unubi_analyze(eb_info_t *head, eb_info_t first, const char *path);
+#endif /* __UNUBI_ANALYZE_H__ */