diff options
Diffstat (limited to 'ubi-utils/src')
-rw-r--r-- | ubi-utils/src/eb_chain.c | 135 | ||||
-rw-r--r-- | ubi-utils/src/eb_chain.h | 73 | ||||
-rw-r--r-- | ubi-utils/src/unubi.c | 141 | ||||
-rw-r--r-- | ubi-utils/src/unubi_analyze.c | 48 | ||||
-rw-r--r-- | ubi-utils/src/unubi_analyze.h | 70 |
5 files changed, 231 insertions, 236 deletions
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__ */ |