summaryrefslogtreecommitdiff
path: root/ubi-utils/src/unubi_analyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils/src/unubi_analyze.c')
-rw-r--r--ubi-utils/src/unubi_analyze.c458
1 files changed, 0 insertions, 458 deletions
diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/src/unubi_analyze.c
deleted file mode 100644
index 3f3a480..0000000
--- a/ubi-utils/src/unubi_analyze.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-/*
- * Authors: Drake Dowsett, dowsett@de.ibm.com
- * Contact: Andreas Arnez, arnez@de.ibm.com
- *
- * unubi uses the following functions to generate analysis output based on
- * the header information in a raw-UBI image
- */
-
-/*
- * TODO: use OOB data to check for eraseblock validity in NAND images
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "unubi_analyze.h"
-#include "crc32.h"
-
-#define EC_X_INT 50
-
-/**
- * intcmp - function needed by qsort to order integers
- **/
-int intcmp(const void *a, const void *b)
-{
- int A = *(int *)a;
- int B = *(int *)b;
- return A - B;
-}
-
-int longcmp(const void *a, const void *b)
-{
- long long A = *(long long *)a;
- long long B = *(long long *)b;
- return A - B;
-}
-
-
-/**
- * unubi_analyze_group_index - finds the normalized index in an array
- * item: look for this item in the array
- * array: array to search through
- * size: length of the array
- * array should be sorted for this algorithm to perform properly;
- * if the item is not found returns -1, otherwise return value is the
- * index in the array (note this contricts the array size to 2^32-1);
- **/
-int
-norm_index(uint32_t item, uint32_t *array, size_t length)
-{
- size_t i, index;
-
- for (index = 0, i = 0; i < length; i++) {
- if ((i != 0) && (array[i] != array[i - 1]))
- index++;
-
- if (item == array[i])
- return index;
- }
-
- return -1;
-}
-
-
-/**
- * unubi_analyze_ec_hdr - generate data table and plot script
- * first: head of simple linked list
- * path: folder to write into
- * generates a data file containing the eraseblock index in the image
- * and the erase counter found in its ec header;
- * if the crc check fails, the line is commented out in the data file;
- * also generates a simple gnuplot sript for quickly viewing one
- * display of the data file;
- **/
-int
-unubi_analyze_ec_hdr(struct eb_info *first, const char *path)
-{
- char filename[PATH_MAX + 1];
- size_t count, eraseblocks;
- uint32_t crc;
- uint64_t *erase_counts;
- FILE* fpdata;
- FILE* fpplot;
- struct eb_info *cur;
-
- if (first == NULL)
- return -1;
-
- /* prepare output files */
- 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, PATH_MAX + 1);
- snprintf(filename, PATH_MAX, "%s/%s", path, FN_EH_PLOT);
- fpplot = fopen(filename, "w");
- if (fpplot == NULL) {
- fclose(fpdata);
- return -1;
- }
-
- /* make executable */
- chmod(filename, 0755);
-
- /* first run: count elements */
- count = 0;
- cur = first;
- while (cur != NULL) {
- cur = cur->next;
- count++;
- }
- 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 */
- count = 0;
- cur = first;
- while (cur != NULL) {
- erase_counts[count] = __be64_to_cpu(cur->ec.ec);
- cur = cur->next;
- count++;
- }
- qsort(erase_counts, eraseblocks, sizeof(*erase_counts),
- (void *)longcmp);
-
- /* third run: generate data file */
- count = 0;
- cur = first;
- fprintf(fpdata, "# eraseblock_no actual_erase_count "
- "sorted_erase_count\n");
- while (cur != NULL) {
- crc = crc32(UBI_CRC32_INIT, &cur->ec, UBI_EC_HDR_SIZE_CRC);
-
- if ((__be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC) ||
- (crc != __be32_to_cpu(cur->ec.hdr_crc)))
- fprintf(fpdata, "# ");
-
- fprintf(fpdata, "%u %llu %llu", count,
- __be64_to_cpu(cur->ec.ec),
- erase_counts[count]);
-
- if (__be32_to_cpu(cur->ec.magic) != UBI_EC_HDR_MAGIC)
- fprintf(fpdata, " ## bad magic: %08x",
- __be32_to_cpu(cur->ec.magic));
-
- if (crc != __be32_to_cpu(cur->ec.hdr_crc))
- fprintf(fpdata, " ## CRC mismatch: given=%08x, "
- "calc=%08x", __be32_to_cpu(cur->ec.hdr_crc),
- crc);
-
- fprintf(fpdata, "\n");
-
- cur = cur->next;
- count++;
- }
- fclose(fpdata);
-
- fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
- fprintf(fpplot, "set xlabel \"eraseblock\"\n");
-
- /* fourth run: generate plot file xtics */
- count = 0;
- cur = first;
- fprintf(fpplot, "set xtics (");
- while (cur != NULL) {
- if ((count % EC_X_INT) == 0) {
- if (count > 0)
- fprintf(fpplot, ", ");
- fprintf(fpplot, "%d", count);
- }
-
- cur = cur->next;
- count++;
- }
- fprintf(fpplot, ")\n");
-
- fprintf(fpplot, "set ylabel \"erase count\"\n");
- fprintf(fpplot, "set xrange [-1:%u]\n", eraseblocks + 1);
- fprintf(fpplot, "# set yrange [-1:%llu]\n",
- 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",
- FN_EH_DATA, FN_EH_DATA);
- fprintf(fpplot, "pause -1 \"press ENTER\"\n");
-
- fclose(fpplot);
-
- return 0;
-}
-
-
-/**
- * unubi_analyze_vid_hdr - generate data table and plot script
- * head: head of complex linked list (eb_chain)
- * path: folder to write into
- * generates a data file containing the volume id, logical number, leb version,
- * and data size from the vid header;
- * all eraseblocks listed in the eb_chain are valid (checked in unubi);
- * also generates a simple gnuplot sript for quickly viewing one
- * display of the data file;
- **/
-int
-unubi_analyze_vid_hdr(struct eb_info **head, const char *path)
-{
- char filename[PATH_MAX + 1];
- int rc, y1, y2;
- size_t count, step, breadth;
- uint32_t *leb_versions, *data_sizes;
- FILE* fpdata;
- FILE* fpplot;
- struct eb_info *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, 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, PATH_MAX + 1);
- snprintf(filename, PATH_MAX, "%s/%s", path, FN_VH_PLOT);
- fpplot = fopen(filename, "w");
- if (fpplot == NULL) {
- rc = -1;
- goto exit;
- }
-
- /* make executable */
- chmod(filename, 0755);
-
- /* first run: count elements */
- count = 0;
- cur = *head;
- while (cur != NULL) {
- cur = cur->next;
- count++;
- }
- breadth = count;
-
- 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(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] = __be32_to_cpu(cur->vid.leb_ver);
- data_sizes[count] = __be32_to_cpu(cur->vid.data_size);
- cur = cur->next;
- count++;
- }
- qsort(leb_versions, breadth, sizeof(*leb_versions), (void *)intcmp);
- qsort(data_sizes, breadth, sizeof(*data_sizes), (void *)intcmp);
-
- /* third run: generate data file */
- count = 0;
- cur = *head;
- fprintf(fpdata, "# x_axis vol_id lnum y1_axis leb_ver "
- "y2_axis data_size\n");
- while (cur != NULL) {
- y1 = norm_index(__be32_to_cpu(cur->vid.leb_ver), leb_versions,
- breadth);
- y2 = norm_index(__be32_to_cpu(cur->vid.data_size), data_sizes,
- breadth);
-
- if ((y1 == -1) || (y2 == -1)) {
- rc = -1;
- goto exit;
- }
-
- fprintf(fpdata, "%u %u %u %u %u %u %u\n",
- count,
- __be32_to_cpu(cur->vid.vol_id),
- __be32_to_cpu(cur->vid.lnum),
- y1,
- __be32_to_cpu(cur->vid.leb_ver),
- y2,
- __be32_to_cpu(cur->vid.data_size));
- cur = cur->next;
- count++;
- }
-
- fprintf(fpplot, "#!/usr/bin/gnuplot -persist\n");
- fprintf(fpplot, "set xlabel \"volume\"\n");
-
- /* fourth run: generate plot file xtics */
- count = 0;
- step = 0;
- cur = *head;
- fprintf(fpplot, "set xtics (");
- while (cur != NULL) {
- if (count > 0)
- fprintf(fpplot, ", ");
- if (step != __be32_to_cpu(cur->vid.vol_id)) {
- step = __be32_to_cpu(cur->vid.vol_id);
- fprintf(fpplot, "\"%d\" %d 0", step, count);
- }
- else
- fprintf(fpplot, "\"%d\" %d 1",
- __be32_to_cpu(cur->vid.lnum), count);
- cur = cur->next;
- count++;
- }
- fprintf(fpplot, ")\n");
- fprintf(fpplot, "set nox2tics\n");
-
- /* fifth run: generate plot file ytics */
- count = 0;
- cur = *head;
- fprintf(fpplot, "set ylabel \"leb version\"\n");
- fprintf(fpplot, "set ytics (");
- while (cur->next != NULL) {
- y1 = norm_index(__be32_to_cpu(cur->vid.leb_ver), leb_versions,
- breadth);
-
- if (y1 == -1) {
- rc = -1;
- goto exit;
- }
-
- if (count > 0)
- fprintf(fpplot, ", ");
-
- fprintf(fpplot, "\"%u\" %u", __be32_to_cpu(cur->vid.leb_ver),
- y1);
-
- cur = cur->next;
- count++;
- }
- fprintf(fpplot, ")\n");
-
- /* sixth run: generate plot file y2tics */
- count = 0;
- cur = *head;
- fprintf(fpplot, "set y2label \"data size\"\n");
- fprintf(fpplot, "set y2tics (");
- while (cur != NULL) {
- y2 = norm_index(__be32_to_cpu(cur->vid.data_size),
- data_sizes, breadth);
-
- if (y2 == -1) {
- rc = -1;
- goto exit;
- }
-
- if (count > 0)
- fprintf(fpplot, ", ");
-
- fprintf(fpplot, "\"%u\" %u", __be32_to_cpu(cur->vid.data_size),
- y2);
-
- cur = cur->next;
- count++;
- }
- fprintf(fpplot, ")\n");
-
- 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:%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\" "
- "axes x1y1 with lp\n", FN_VH_DATA, FN_VH_DATA);
- fprintf(fpplot, "replot \"%s\" u 1:6 t \"data size: %s\" "
- "axes x1y2 with lp\n", FN_VH_DATA, FN_VH_DATA);
- fprintf(fpplot, "pause -1 \"press ENTER\"\n");
-
- 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;
-}
-
-
-/**
- * unubi_analyze - run all analyses
- * head: eb_chain head
- * first: simple linked list of eraseblock headers (use .next)
- * path: directory (without trailing slash) to output to
- * returns 0 upon successful completion, or -1 otherwise
- **/
-int
-unubi_analyze(struct eb_info **head, struct eb_info *first, const char *path)
-{
- int ec_rc, vid_rc;
-
- if (path == NULL)
- return -1;
-
- 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;
-}