summaryrefslogtreecommitdiff
path: root/ubi-utils/src/ubinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ubi-utils/src/ubinfo.c')
-rw-r--r--ubi-utils/src/ubinfo.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c
new file mode 100644
index 0000000..358f208
--- /dev/null
+++ b/ubi-utils/src/ubinfo.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: Artem Bityutskiy
+ */
+
+/*
+ * An utility to get UBI information.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME "ubinfo"
+
+/* The variables below is set by command line arguments */
+struct args {
+ int devn;
+ int vol_id;
+ int all;
+ char node[MAX_NODE_LEN + 2];
+ int node_given;
+};
+
+static struct args myargs = {
+ .vol_id = -1,
+ .devn = -1,
+ .all = 0,
+ .node_given = 0,
+};
+
+static const char *doc = "Version " PROGRAM_VERSION "\n"
+ PROGRAM_NAME " - a tool to UBI information.";
+
+static const char *optionsstr =
+"-d, --devn=<UBI device number> UBI device number to get information about\n"
+"-n, --vol_id=<volume ID> ID of UBI volume to print information about\n"
+"-a, --all print information about all devices and volumes,\n"
+" or about all volumes if the UBI device was\n"
+" specified\n"
+"-h, --help print help message\n"
+"-V, --version print program version";
+
+static const char *usage =
+"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID>] [-a] [-h] [-V] [--vol_id=<volume ID>]\n"
+"\t\t[--devn <UBI device number>] [--all] [--help] [--version]\n"
+"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n"
+"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n"
+"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n"
+"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n"
+" device /dev/ubi0\n"
+"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n"
+"Example 5: " PROGRAM_NAME " -a - print all information\n";
+
+static const struct option long_options[] = {
+ { .name = "devn", .has_arg = 1, .flag = NULL, .val = 'd' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "all", .has_arg = 0, .flag = NULL, .val = 'a' },
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[], struct args *args)
+{
+ char *endp;
+
+ while (1) {
+ int key;
+
+ key = getopt_long(argc, argv, "an:d:hV", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'a':
+ args->all = 1;
+ break;
+
+ case 'n':
+ args->vol_id = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || args->vol_id < 0) {
+ errmsg("bad volume ID: " "\"%s\"", optarg);
+ return -1;
+ }
+ break;
+
+ case 'd':
+ args->devn = strtoul(optarg, &endp, 0);
+ if (*endp != '\0' || endp == optarg || args->devn < 0) {
+ errmsg("bad UBI device number: \"%s\"", optarg);
+ return -1;
+ }
+
+ break;
+
+ case 'h':
+ fprintf(stderr, "%s\n\n", doc);
+ fprintf(stderr, "%s\n\n", usage);
+ fprintf(stderr, "%s\n", optionsstr);
+ exit(0);
+
+ case 'V':
+ fprintf(stderr, "%s\n", PROGRAM_VERSION);
+ exit(0);
+
+ case ':':
+ errmsg("parameter is missing");
+ return -1;
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ exit(-1);
+ }
+ }
+
+ return 0;
+}
+
+static int translate_dev(libubi_t libubi, const char *node)
+{
+ int err;
+
+ if (strlen(node) > MAX_NODE_LEN) {
+ errmsg("too long device node name: \"%s\" (%d characters), max. is %d",
+ node, strlen(node), MAX_NODE_LEN);
+ return -1;
+ }
+
+ err = ubi_node_type(libubi, node);
+ if (err == -1) {
+ if (errno) {
+ errmsg("unrecognized device node \"%s\"", node);
+ perror("ubi_node_type");
+ return -1;
+ }
+ errmsg("\"%s\" does not correspond to any UBI device or volume",
+ node);
+ return -1;
+ }
+
+ if (err == 1) {
+ struct ubi_dev_info dev_info;
+
+ err = ubi_get_dev_info(libubi, node, &dev_info);
+ if (err) {
+ errmsg("cannot get information about UBI device \"%s\"",
+ node);
+ perror("ubi_get_dev_info");
+ return -1;
+ }
+
+ myargs.devn = dev_info.dev_num;
+ } else {
+ struct ubi_vol_info vol_info;
+
+ err = ubi_get_vol_info(libubi, node, &vol_info);
+ if (err) {
+ errmsg("cannot get information about UBI volume \"%s\"",
+ node);
+ perror("ubi_get_vol_info");
+ return -1;
+ }
+
+ if (myargs.vol_id != -1) {
+ errmsg("both volume character device node (\"%s\") and "
+ "volume ID (%d) are specify, use only one of them"
+ "(use -h for help)", node, myargs.vol_id);
+ return -1;
+ }
+
+ myargs.devn = vol_info.dev_num;
+ myargs.vol_id = vol_info.vol_id;
+ }
+
+ return 0;
+}
+
+static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
+{
+ int err;
+ struct ubi_vol_info vol_info;
+
+ err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info);
+ if (err) {
+ errmsg("cannot get information about UBI volume %d on ubi%d",
+ vol_id, dev_num);
+ perror("ubi_get_vol_info1");
+ return -1;
+ }
+
+ printf("Volume ID: %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num);
+ printf("Type: %s\n",
+ vol_info.type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static");
+ printf("Alignment: %d\n", vol_info.alignment);
+
+ printf("Size: %d LEBs (", vol_info.rsvd_ebs);
+ ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+ printf(")\n");
+
+ if (vol_info.type == UBI_STATIC_VOLUME) {
+ printf("Data bytes: ");
+ ubiutils_print_bytes(vol_info.data_bytes, 1);
+ }
+ printf("State: %s\n", vol_info.corrupted ? "corrupted" : "OK");
+ printf("Name: %s\n", vol_info.name);
+ printf("Character device major/minor: %d:%d\n",
+ vol_info.major, vol_info.minor);
+
+ return 0;
+}
+
+static int print_dev_info(libubi_t libubi, int dev_num, int all)
+{
+ int i, err, first = 1;
+ struct ubi_dev_info dev_info;
+ struct ubi_vol_info vol_info;
+
+ err = ubi_get_dev_info1(libubi, dev_num, &dev_info);
+ if (err) {
+ errmsg("cannot get information about UBI device %d", dev_num);
+ perror("ubi_get_dev_info1");
+ return -1;
+ }
+
+ printf("ubi%d:\n", dev_info.dev_num);
+ printf("Volumes count: %d\n", dev_info.vol_count);
+ printf("Logical eraseblock size: %d\n", dev_info.eb_size);
+
+ printf("Total amount of logical eraseblocks: %d (", dev_info.total_ebs);
+ ubiutils_print_bytes(dev_info.total_bytes, 0);
+ printf(")\n");
+
+ printf("Amount of available logical eraseblocks: %d", dev_info.avail_ebs);
+ ubiutils_print_bytes(dev_info.avail_bytes, 0);
+ printf(")\n");
+
+ printf("Maximum count of volumes %d\n", dev_info.max_vol_count);
+ printf("Count of bad physical eraseblocks: %d\n", dev_info.bad_count);
+ printf("Count of reserved physical eraseblocks: %d\n", dev_info.bad_rsvd);
+ printf("Current maximum erase counter value: %lld\n", dev_info.max_ec);
+ printf("Minimum input/output unit size: %d bytes\n", dev_info.min_io_size);
+ printf("Character device major/minor: %d:%d\n",
+ dev_info.major, dev_info.minor);
+
+ if (dev_info.vol_count == 0)
+ return 0;
+
+ printf("Present volumes: ");
+ for (i = dev_info.lowest_vol_num;
+ i <= dev_info.highest_vol_num; i++) {
+ err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+ if (err == -1) {
+ if (errno == ENOENT)
+ continue;
+
+ errmsg("libubi failed to probe volume %d on ubi%d",
+ i, dev_info.dev_num);
+ perror("ubi_get_vol_info1");
+ return -1;
+ }
+
+ if (!first)
+ printf(", %d", i);
+ else {
+ printf("%d", i);
+ first = 0;
+ }
+ }
+ printf("\n");
+
+ if (!all)
+ return 0;
+
+ first = 1;
+ printf("\n");
+
+ for (i = dev_info.lowest_vol_num;
+ i <= dev_info.highest_vol_num; i++) {
+ if(!first)
+ printf("-----------------------------------\n");
+ err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+ if (err == -1) {
+ if (errno == ENOENT)
+ continue;
+
+ errmsg("libubi failed to probe volume %d on ubi%d",
+ i, dev_info.dev_num);
+ perror("ubi_get_vol_info1");
+ return -1;
+ }
+ first = 0;
+
+ err = print_vol_info(libubi, dev_info.dev_num, i);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int print_general_info(libubi_t libubi, int all)
+{
+ int i, err, first = 1;
+ struct ubi_info ubi_info;
+ struct ubi_dev_info dev_info;
+
+ err = ubi_get_info(libubi, &ubi_info);
+ if (err) {
+ errmsg("cannot get UBI information");
+ perror("ubi_get_info");
+ return -1;
+ }
+
+ printf("UBI version: %d\n", ubi_info.version);
+ printf("Count of UBI devices: %d\n", ubi_info.dev_count);
+ printf("UBI control device major/minor: %d:%d\n",
+ ubi_info.ctrl_major, ubi_info.ctrl_minor);
+
+ if (ubi_info.dev_count == 0)
+ return 0;
+
+ printf("Present UBI devices: ");
+ for (i = ubi_info.lowest_dev_num;
+ i <= ubi_info.highest_dev_num; i++) {
+ err = ubi_get_dev_info1(libubi, i, &dev_info);
+ if (err == -1) {
+ if (errno == ENOENT)
+ continue;
+
+ errmsg("libubi failed to probe UBI device %d", i);
+ perror("ubi_get_dev_info1");
+ return -1;
+ }
+
+ if (!first)
+ printf(", ubi%d", i);
+ else {
+ printf("ubi%d", i);
+ first = 0;
+ }
+ }
+ printf("\n");
+
+ if (!all)
+ return 0;
+
+ first = 1;
+ printf("\n");
+
+ for (i = ubi_info.lowest_dev_num;
+ i <= ubi_info.highest_dev_num; i++) {
+ if(!first)
+ printf("\n===================================\n\n");
+ err = ubi_get_dev_info1(libubi, i, &dev_info);
+ if (err == -1) {
+ if (errno == ENOENT)
+ continue;
+
+ errmsg("libubi failed to probe UBI device %d", i);
+ perror("ubi_get_dev_info1");
+ return -1;
+ }
+ first = 0;
+
+ err = print_dev_info(libubi, i, all);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libubi_t libubi;
+
+ if (argc > 1 && argv[1][0] != '-') {
+ strncpy(myargs.node, argv[1], MAX_NODE_LEN + 1);
+ myargs.node_given = 1;
+ }
+
+ if (argc > 2 && argv[2][0] != '-') {
+ errmsg("incorrect arguments, use -h for help");
+ return -1;
+ }
+
+ err = parse_opt(argc, argv, &myargs);
+ if (err)
+ return -1;
+
+ if (argc > 1 && !myargs.node_given && myargs.devn != -1) {
+ errmsg("specify either device number or node file (use -h for help)");
+ return -1;
+ }
+
+ libubi = libubi_open();
+ if (libubi == NULL) {
+ errmsg("cannot open libubi");
+ perror("libubi_open");
+ return -1;
+ }
+
+ if (myargs.node_given) {
+ /*
+ * A character device was specified, translate this into UBI
+ * device number and volume ID.
+ */
+ err = translate_dev(libubi, myargs.node);
+ if (err)
+ goto out_libubi;
+ }
+
+ if (myargs.vol_id != -1 && myargs.devn == -1) {
+ errmsg("volume ID is specified, but UBI device number is not "
+ "(use -h for help)\n");
+ goto out_libubi;
+ }
+
+ if (myargs.devn != -1 && myargs.vol_id != -1) {
+ print_vol_info(libubi, myargs.devn, myargs.vol_id);
+ goto out;
+ }
+
+ if (myargs.devn == -1 && myargs.vol_id == -1)
+ err = print_general_info(libubi, myargs.all);
+ else if (myargs.devn != -1 && myargs.vol_id == -1)
+ err = print_dev_info(libubi, myargs.devn, myargs.all);
+
+ if (err)
+ goto out_libubi;
+
+out:
+ libubi_close(libubi);
+ return 0;
+
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}