* [PATCH v6 1/3] ubi-utils: add library file libdump for ubidump
@ 2014-12-05 9:26 hujianyang
2014-12-05 9:31 ` [PATCH v6 2/3] ubi-utils: introduce ubidump hujianyang
2014-12-05 9:33 ` [PATCH v6 3/3] ubi-utils: ubidump compile enable hujianyang
0 siblings, 2 replies; 3+ messages in thread
From: hujianyang @ 2014-12-05 9:26 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: linux-mtd
This is a preparatory patch for ubidump, an utility printing on-media
format of UBIFS partitions. This patch includes the library functions
used by ubidump.
These functions are taken from linux kernel. Some of them are modified
in order to work well in userspace.
Signed-off-by: hujianyang <hujianyang@huawei.com>
---
ubi-utils/include/libdump.h | 67 +++++++
ubi-utils/libdump.c | 433 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 500 insertions(+), 0 deletions(-)
create mode 100644 ubi-utils/include/libdump.h
create mode 100644 ubi-utils/libdump.c
diff --git a/ubi-utils/include/libdump.h b/ubi-utils/include/libdump.h
new file mode 100644
index 0000000..486af0d
--- /dev/null
+++ b/ubi-utils/include/libdump.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006-2008 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
+ */
+
+/*
+ * The *scan* part of code was taken from the kernel UBIFS implementation.
+ */
+
+#ifndef __LIBDUMP_H__
+#define __LIBDUMP_H__
+
+#include <mtd/ubifs-media.h>
+#include <mtd/ubi-media.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ubidump - dump ubi/ubifs information
+ * @lnum: logical eraseblock number
+ * @buf: buffer to dump
+ * @leb_size: size of buffer/logical eraseblock size
+ *
+ * This function dump ubi/ubifs information on the buffer.
+ */
+int ubi_dump(int lnum, void *buf, int leb_size);
+
+/* Taken from kernel UBIFS implementation */
+
+/*
+ * 'ubifs_scan_a_node()' return values.
+ *
+ * SCANNED_GARBAGE: scanned garbage
+ * SCANNED_EMPTY_SPACE: scanned empty space
+ * SCANNED_A_NODE: scanned a valid node
+ * SCANNED_A_CORRUPT_NODE: scanned a corrupted node
+ * SCANNED_A_BAD_PAD_NODE: scanned a padding node with invalid pad length
+ *
+ * Greater than zero means: 'scanned that number of padding bytes'
+ */
+enum {
+ SCANNED_GARBAGE = 0,
+ SCANNED_EMPTY_SPACE = -1,
+ SCANNED_A_NODE = -2,
+ SCANNED_A_CORRUPT_NODE = -3,
+ SCANNED_A_BAD_PAD_NODE = -4,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*!__LIBDUMP_H__ */
diff --git a/ubi-utils/libdump.c b/ubi-utils/libdump.c
new file mode 100644
index 0000000..bbac7eb
--- /dev/null
+++ b/ubi-utils/libdump.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2006-2008 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
+ */
+
+/*
+ * Great deal of the code was taken from kernel UBIFS implementation including
+ * fs/ubifs/scan.c and fs/ubifs/dump.c. There is a little difference in
+ * ubifs_scan(). The struct *ubifs_scan_leb* which contains the list of scanned
+ * NODEs was dropped because we can deal with each NODE directly. We don't need
+ * *corrupt* part of code either. In addition, a new parameter is added to
+ * indicate if ubifs_dump_node() is needed for a scanned NODE.
+ *
+ * Besides, ubifs_dump_node() can't dump all kinds of NODEs because some of
+ * them contain user data and useless for debugging.
+ */
+
+#define PROGRAM_NAME "libdump"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <libdump.h>
+#include <mtd_swab.h>
+#include "common.h"
+
+static const char *get_key_fmt(int fmt)
+{
+ switch (fmt) {
+ case UBIFS_SIMPLE_KEY_FMT:
+ return "simple";
+ default:
+ return "unknown/invalid format";
+ }
+}
+
+static const char *get_key_hash(int hash)
+{
+ switch (hash) {
+ case UBIFS_KEY_HASH_R5:
+ return "R5";
+ case UBIFS_KEY_HASH_TEST:
+ return "test";
+ default:
+ return "unknown/invalid name hash";
+ }
+}
+
+static const char *node_ntype(int type)
+{
+ switch (type) {
+ case UBIFS_PAD_NODE:
+ return "padding node";
+ case UBIFS_SB_NODE:
+ return "superblock node";
+ case UBIFS_MST_NODE:
+ return "master node";
+ case UBIFS_REF_NODE:
+ return "reference node";
+ case UBIFS_INO_NODE:
+ return "inode node";
+ case UBIFS_DENT_NODE:
+ return "direntry node";
+ case UBIFS_XENT_NODE:
+ return "xentry node";
+ case UBIFS_DATA_NODE:
+ return "data node";
+ case UBIFS_TRUN_NODE:
+ return "truncate node";
+ case UBIFS_IDX_NODE:
+ return "indexing node";
+ case UBIFS_CS_NODE:
+ return "commit start node";
+ case UBIFS_ORPH_NODE:
+ return "orphan node";
+ default:
+ return "unknown node";
+ }
+}
+
+static const char *node_gtype(int type)
+{
+ switch (type) {
+ case UBIFS_NO_NODE_GROUP:
+ return "no node group";
+ case UBIFS_IN_NODE_GROUP:
+ return "in node group";
+ case UBIFS_LAST_OF_NODE_GROUP:
+ return "last of node group";
+ default:
+ return "unknown";
+ }
+}
+
+static void dump_ch(const struct ubifs_ch *ch)
+{
+ printf("\tmagic %#x\n", le32_to_cpu(ch->magic));
+ printf("\tcrc %#x\n", le32_to_cpu(ch->crc));
+ printf("\tnode_type %d (%s)\n", ch->node_type,
+ node_ntype(ch->node_type));
+ printf("\tgroup_type %d (%s)\n", ch->group_type,
+ node_gtype(ch->group_type));
+ printf("\tsqnum %llu\n",
+ (unsigned long long)le64_to_cpu(ch->sqnum));
+ printf("\tlen %u\n", le32_to_cpu(ch->len));
+}
+
+/*
+ * This function is copied from linux kernel fs/ubifs/debug.c but
+ * just enable the dumping of PAD_NODE, SB_NODE, MST_NODE, REF_NODE
+ * and CS_NODE.
+ *
+ * One can add more functions by taking the code from kernel and
+ * put the on-media format to include/mtd/ubifs-media.h
+ */
+static void ubifs_dump_node(const void *node)
+{
+ const struct ubifs_ch *ch = node;
+
+ if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {
+ printf("Not a node, first %zu bytes:\n", UBIFS_CH_SZ);
+ return;
+ }
+
+ dump_ch(node);
+
+ switch (ch->node_type) {
+ case UBIFS_PAD_NODE:
+ {
+ const struct ubifs_pad_node *pad = node;
+
+ printf("\tpad_len %u\n", le32_to_cpu(pad->pad_len));
+ break;
+ }
+ case UBIFS_SB_NODE:
+ {
+ const struct ubifs_sb_node *sup = node;
+ unsigned int sup_flags = le32_to_cpu(sup->flags);
+
+ printf("\tkey_hash %d (%s)\n",
+ (int)sup->key_hash, get_key_hash(sup->key_hash));
+ printf("\tkey_fmt %d (%s)\n",
+ (int)sup->key_fmt, get_key_fmt(sup->key_fmt));
+ printf("\tflags %#x\n", sup_flags);
+ printf("\tbig_lpt %u\n",
+ !!(sup_flags & UBIFS_FLG_BIGLPT));
+ printf("\tspace_fixup %u\n",
+ !!(sup_flags & UBIFS_FLG_SPACE_FIXUP));
+ printf("\tmin_io_size %u\n", le32_to_cpu(sup->min_io_size));
+ printf("\tleb_size %u\n", le32_to_cpu(sup->leb_size));
+ printf("\tleb_cnt %u\n", le32_to_cpu(sup->leb_cnt));
+ printf("\tmax_leb_cnt %u\n", le32_to_cpu(sup->max_leb_cnt));
+ printf("\tmax_bud_bytes %llu\n",
+ (unsigned long long)le64_to_cpu(sup->max_bud_bytes));
+ printf("\tlog_lebs %u\n", le32_to_cpu(sup->log_lebs));
+ printf("\tlpt_lebs %u\n", le32_to_cpu(sup->lpt_lebs));
+ printf("\torph_lebs %u\n", le32_to_cpu(sup->orph_lebs));
+ printf("\tjhead_cnt %u\n", le32_to_cpu(sup->jhead_cnt));
+ printf("\tfanout %u\n", le32_to_cpu(sup->fanout));
+ printf("\tlsave_cnt %u\n", le32_to_cpu(sup->lsave_cnt));
+ printf("\tdefault_compr %u\n",
+ (int)le16_to_cpu(sup->default_compr));
+ printf("\trp_size %llu\n",
+ (unsigned long long)le64_to_cpu(sup->rp_size));
+ printf("\trp_uid %u\n", le32_to_cpu(sup->rp_uid));
+ printf("\trp_gid %u\n", le32_to_cpu(sup->rp_gid));
+ printf("\tfmt_version %u\n", le32_to_cpu(sup->fmt_version));
+ printf("\ttime_gran %u\n", le32_to_cpu(sup->time_gran));
+ printf("\tUUID %pUB\n", sup->uuid);
+ break;
+ }
+ case UBIFS_MST_NODE:
+ {
+ const struct ubifs_mst_node *mst = node;
+
+ printf("\thighest_inum %llu\n",
+ (unsigned long long)le64_to_cpu(mst->highest_inum));
+ printf("\tcommit number %llu\n",
+ (unsigned long long)le64_to_cpu(mst->cmt_no));
+ printf("\tflags %#x\n", le32_to_cpu(mst->flags));
+ printf("\tlog_lnum %u\n", le32_to_cpu(mst->log_lnum));
+ printf("\troot_lnum %u\n", le32_to_cpu(mst->root_lnum));
+ printf("\troot_offs %u\n", le32_to_cpu(mst->root_offs));
+ printf("\troot_len %u\n", le32_to_cpu(mst->root_len));
+ printf("\tgc_lnum %u\n", le32_to_cpu(mst->gc_lnum));
+ printf("\tihead_lnum %u\n", le32_to_cpu(mst->ihead_lnum));
+ printf("\tihead_offs %u\n", le32_to_cpu(mst->ihead_offs));
+ printf("\tindex_size %llu\n",
+ (unsigned long long)le64_to_cpu(mst->index_size));
+ printf("\tlpt_lnum %u\n", le32_to_cpu(mst->lpt_lnum));
+ printf("\tlpt_offs %u\n", le32_to_cpu(mst->lpt_offs));
+ printf("\tnhead_lnum %u\n", le32_to_cpu(mst->nhead_lnum));
+ printf("\tnhead_offs %u\n", le32_to_cpu(mst->nhead_offs));
+ printf("\tltab_lnum %u\n", le32_to_cpu(mst->ltab_lnum));
+ printf("\tltab_offs %u\n", le32_to_cpu(mst->ltab_offs));
+ printf("\tlsave_lnum %u\n", le32_to_cpu(mst->lsave_lnum));
+ printf("\tlsave_offs %u\n", le32_to_cpu(mst->lsave_offs));
+ printf("\tlscan_lnum %u\n", le32_to_cpu(mst->lscan_lnum));
+ printf("\tleb_cnt %u\n", le32_to_cpu(mst->leb_cnt));
+ printf("\tempty_lebs %u\n", le32_to_cpu(mst->empty_lebs));
+ printf("\tidx_lebs %u\n", le32_to_cpu(mst->idx_lebs));
+ printf("\ttotal_free %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_free));
+ printf("\ttotal_dirty %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dirty));
+ printf("\ttotal_used %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_used));
+ printf("\ttotal_dead %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dead));
+ printf("\ttotal_dark %llu\n",
+ (unsigned long long)le64_to_cpu(mst->total_dark));
+ break;
+ }
+ case UBIFS_REF_NODE:
+ {
+ const struct ubifs_ref_node *ref = node;
+
+ printf("\tlnum %u\n", le32_to_cpu(ref->lnum));
+ printf("\toffs %u\n", le32_to_cpu(ref->offs));
+ printf("\tjhead %u\n", le32_to_cpu(ref->jhead));
+ break;
+ }
+ case UBIFS_CS_NODE:
+ case UBIFS_INO_NODE:
+ case UBIFS_DENT_NODE:
+ case UBIFS_XENT_NODE:
+ case UBIFS_DATA_NODE:
+ case UBIFS_TRUN_NODE:
+ case UBIFS_IDX_NODE:
+ case UBIFS_ORPH_NODE:
+ break;
+ default:
+ printf("node type %d was not recognized\n",
+ (int)ch->node_type);
+ }
+}
+
+/**
+ * scan_padding_bytes - scan for padding bytes.
+ * @buf: buffer to scan
+ * @len: length of buffer
+ *
+ * This function returns the number of padding bytes on success and
+ * %SCANNED_GARBAGE on failure.
+ */
+static int scan_padding_bytes(void *buf, int len)
+{
+ int pad_len = 0, max_pad_len = min_t(int, UBIFS_PAD_NODE_SZ, len);
+ uint8_t *p = buf;
+
+ while (pad_len < max_pad_len && *p++ == UBIFS_PADDING_BYTE)
+ pad_len += 1;
+
+ if (!pad_len || (pad_len & 7))
+ return SCANNED_GARBAGE;
+
+ printf("not a node: %d padding bytes\n", pad_len);
+
+ return pad_len;
+}
+
+/**
+ * ubifs_scan_a_node - scan for a node or padding.
+ * @buf: buffer to scan
+ * @size: logical eraseblock size
+ * @len: length of buffer
+ * @lnum: logical eraseblock number
+ * @offs: offset within the logical eraseblock
+ *
+ * This function returns a scanning code to indicate what was scanned.
+ */
+static int ubifs_scan_a_node(void *buf, int leb_size, int len, int lnum, int offs)
+{
+ struct ubifs_ch *ch = buf;
+ uint32_t magic;
+
+ magic = le32_to_cpu(ch->magic);
+
+ if (magic == 0xFFFFFFFF) {
+ printf("hit empty space at LEB %d:%d\n", lnum, offs);
+ return SCANNED_EMPTY_SPACE;
+ }
+
+ if (magic != UBIFS_NODE_MAGIC)
+ return scan_padding_bytes(buf, len);
+
+ if (len < UBIFS_CH_SZ)
+ return SCANNED_GARBAGE;
+
+ printf("scanning %s at LEB %d:%d\n",
+ node_ntype(ch->node_type), lnum, offs);
+
+ /* No ubifs_check_nodei() perform here */
+
+ if (ch->node_type == UBIFS_PAD_NODE) {
+ struct ubifs_pad_node *pad = buf;
+ int pad_len = le32_to_cpu(pad->pad_len);
+ int node_len = le32_to_cpu(ch->len);
+
+ /* Validate the padding node */
+ if (pad_len < 0 ||
+ offs + node_len + pad_len > leb_size) {
+ printf("bad pad node at LEB %d:%d\n", lnum, offs);
+ ubifs_dump_node(pad);
+ return SCANNED_A_BAD_PAD_NODE;
+ }
+
+ /* Make the node pads to 8-byte boundary */
+ if ((node_len + pad_len) & 7) {
+ printf("bad padding length %d - %d\n",
+ offs, offs + node_len + pad_len);
+ return SCANNED_A_BAD_PAD_NODE;
+ }
+
+ printf("%d bytes padded at LEB %d:%d, offset now %d\n", pad_len,
+ lnum, offs, ALIGN(offs + node_len + pad_len, 8));
+
+ return node_len + pad_len;
+ }
+
+ return SCANNED_A_NODE;
+}
+
+/**
+ * ubifs_scan - scan a logical eraseblock.
+ * @lnum: logical eraseblock number
+ * @sbuf: scan buffer
+ * @size: size of @buf in bytes
+ * @offs: offset to start at (usually zero)
+ *
+ * This function scans LEB number @lnum and prints complete information about
+ * its contents. A non-zero number is returned in case of an error.
+ *
+ * Note, it's a simplified version of ubifs_scan() in kernel fs/ubifs/scan.c.
+ * The struct *ubifs_scan_leb* is removed, we directly deal with each scanned
+ * NODE. The *corrupt* part of code is removed either because this function
+ * just print the contents of an LEB without checking its correctness.
+ */
+static int ubifs_scan(int lnum, void *sbuf, int leb_size, int offs)
+{
+ void *buf = sbuf + offs;
+ int len = leb_size - offs;
+
+ printf("scan LEB %d:%d\n", lnum, offs);
+
+ while (len >= 8) {
+ struct ubifs_ch *ch = buf;
+ int node_len, ret;
+
+ printf("look at LEB %d:%d (%d bytes left)\n",
+ lnum, offs, len);
+
+ ret = ubifs_scan_a_node(buf, leb_size, len, lnum, offs);
+ if (ret > 0) {
+ /* Padding bytes or a valid padding node */
+ offs += ret;
+ buf += ret;
+ len -= ret;
+ continue;
+ }
+
+ if (ret == SCANNED_EMPTY_SPACE)
+ /* Empty space is checked later */
+ break;
+
+ switch (ret) {
+ case SCANNED_GARBAGE:
+ printf("garbage\n");
+ goto corrupted;
+ case SCANNED_A_NODE:
+ ubifs_dump_node(buf);
+ break;
+ case SCANNED_A_CORRUPT_NODE:
+ case SCANNED_A_BAD_PAD_NODE:
+ printf("bad node\n");
+ goto corrupted;
+ default:
+ printf("unknown\n");
+ return -EINVAL;
+ }
+
+ node_len = ALIGN(le32_to_cpu(ch->len), 8);
+ offs += node_len;
+ buf += node_len;
+ len -= node_len;
+ }
+
+ for (; len > 4; offs += 4, buf = buf + 4, len -= 4)
+ if (*(uint32_t *)buf != 0xffffffff)
+ break;
+ for (; len; offs++, buf++, len--)
+ if (*(uint8_t *)buf != 0xff) {
+ printf("corrupt empty space at LEB %d:%d\n",
+ lnum, offs);
+ goto corrupted;
+ }
+
+ printf("stop scanning LEB %d at offset %d\n", lnum, offs);
+ return 0;
+
+corrupted:
+ printf("corruption at LEB %d:%d\n", lnum, offs);
+ return -EUCLEAN;
+}
+
+/**
+ * ubidump - dump ubi/ubifs information
+ * @lnum: logical eraseblock number
+ * @buf: buffer to dump
+ * @leb_size: size of buffer/logical eraseblock size
+ *
+ * This function dump ubi/ubifs information on the buffer.
+ */
+int ubi_dump(int lnum, void *buf, int leb_size)
+{
+ int err;
+
+ err = ubifs_scan(lnum, buf, leb_size, 0);
+ if (err)
+ printf("LEB %d scanning failed, error %d\n", lnum, err);
+ return err;
+}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH v6 2/3] ubi-utils: introduce ubidump
2014-12-05 9:26 [PATCH v6 1/3] ubi-utils: add library file libdump for ubidump hujianyang
@ 2014-12-05 9:31 ` hujianyang
2014-12-05 9:33 ` [PATCH v6 3/3] ubi-utils: ubidump compile enable hujianyang
1 sibling, 0 replies; 3+ messages in thread
From: hujianyang @ 2014-12-05 9:31 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: linux-mtd
This patch introduce a new utility named ubidump. This utility can dump
a specific leb to userspace(maybe a arrange of lebs in the future).
We don't have an useful tool to get data from a specified logical erase
block and to describe what it contains in userspace before. I suppose
if this utility could help us overcome these problems and give us a new
way to analyze the behavior of UBI/UBIFS without changing kernel.
Artem (dedekind1@gmail.com) and Bill (bpringlemeir@nbsps.com) also
contribute a lot to this utility. I appreciate their help very much.
Only the UBIFS level dumping is supported now, we've discussed and tried
many ways to realize UBI level dumping but didn't reach an agreement.
I'll keep working on it.
I think this work is just the beginning of enriching UBI/UBIFS debugging.
Changes in v6:
- remove ubifs-media.h from patch set. This file has been
added with commit 789d2d7019
- remove flag '-i'. All the dumping messages are now directly
printed without any extra flags.
- support none '--lnum, -l' dump. If *lnum* is not specific,
all the LEBs in target device will be scanned and dumped.
An error was returned in previous version.
v1:
http://lists.infradead.org/pipermail/linux-mtd/2014-July/054541.html
v2:
http://lists.infradead.org/pipermail/linux-mtd/2014-July/054831.html
v3:
http://lists.infradead.org/pipermail/linux-mtd/2014-September/055463.html
v4:
http://lists.infradead.org/pipermail/linux-mtd/2014-September/055644.html
v5:
http://lists.infradead.org/pipermail/linux-mtd/2014-October/056048.html
Signed-off-by: hujianyang <hujianyang@huawei.com>
---
ubi-utils/ubidump.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 218 insertions(+), 0 deletions(-)
create mode 100644 ubi-utils/ubidump.c
diff --git a/ubi-utils/ubidump.c b/ubi-utils/ubidump.c
new file mode 100644
index 0000000..d04ab94
--- /dev/null
+++ b/ubi-utils/ubidump.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * 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.
+ */
+
+/*
+ * An utility to dump UBI/UBIFS format data in eraseblock
+ *
+ * Author: Hu Jianyang <hujianyang@huawei.com>
+ */
+
+#define PROGRAM_NAME "ubidump"
+
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <libubi.h>
+#include <libdump.h>
+#include <libmtd.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+ const char *vol;
+ int lnum;
+};
+
+static struct args args =
+{
+ .vol = NULL,
+ .lnum = -1,
+};
+
+static const char doc[] = PROGRAM_NAME " version " VERSION
+ " - an utility to dump UBI/UBIFS format data in eraseblock";
+
+static const char optionsstr[] =
+"-h, --help print help message\n"
+"-l, --lnum logic eraseblock num to dump, print all LEBs if not specific\n"
+"-V, --version print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI volume node file name> [-l <lnum>]\n"
+"\t\t\t[--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi0_1 --lnum 2 - dump LEB 2 in /dev/ubi0_1\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi0_0 - dump all LEBs in /dev/ubi0_0\n";
+
+static const struct option long_options[] = {
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "lnum", .has_arg = 1, .flag = NULL, .val = 'l' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0}
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+ while (1) {
+ int key, error = 0;
+
+ key = getopt_long(argc, argv, "hV?l:", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'l':
+ args.lnum = simple_strtoul(optarg, &error);
+ if (error || args.lnum < 0)
+ return errmsg("bad lnum: \"%s\"", optarg);
+ break;
+
+ case 'h':
+ case '?':
+ printf("%s\n\n", doc);
+ printf("%s\n\n", usage);
+ printf("%s\n", optionsstr);
+ exit(EXIT_SUCCESS);
+
+ case 'V':
+ common_print_version();
+ exit(EXIT_SUCCESS);
+
+ case ':':
+ return errmsg("parameter is missing");
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ return -1;
+ }
+ }
+ if (optind == argc)
+ return errmsg("UBI device name was not specified (use -h for help)");
+ else if (optind != argc - 1)
+ return errmsg("more then one UBI device specified (use -h for help)");
+
+ args.vol = argv[optind];
+
+ return 0;
+}
+
+static int dump_eraseblock(int fd, struct ubi_vol_info *vol_info)
+{
+ int ret, leb_size, count, lnum;
+ off_t offs;
+ char *buf;
+
+ leb_size = vol_info->leb_size;
+ if (args.lnum == -1) {
+ count = vol_info->rsvd_lebs;
+ lnum = 0;
+ } else {
+ count = 1;
+ lnum = args.lnum;
+ }
+
+ buf = (char*)malloc(leb_size);
+ if (!buf)
+ return errmsg("cannot allocate %d bytes of memory",
+ leb_size);
+
+ for (; count > 0; count--, lnum++) {
+ ret = ubi_is_mapped(fd, lnum);
+ if (ret == 0) {
+ printf("lnum %d is not mapped\n", lnum);
+ continue;
+ } else if (ret < 0) {
+ sys_errmsg("lnum %d: ubi_is_mapped() failed", lnum);
+ goto out;
+ }
+
+ offs = lnum * leb_size;
+
+ ret = pread(fd, buf, leb_size, offs);
+ if (ret != leb_size) {
+ errmsg("cannot read %d bytes at lnum %d, read %d",
+ leb_size, lnum, ret);
+ goto out;
+ }
+
+ ret = ubi_dump(lnum, buf, leb_size);
+ }
+
+out:
+ free(buf);
+ return ret;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err, fd;
+ libubi_t libubi;
+ struct ubi_vol_info vol_info;
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return -1;
+
+ libubi = libubi_open();
+ if (!libubi) {
+ if (errno == 0)
+ return errmsg("UBI is not present in the system");
+ return sys_errmsg("cannot open libubi");
+ }
+
+ err = ubi_probe_node(libubi, args.vol);
+ if (err == 1) {
+ errmsg("\"%s\" is an UBI device node, not an UBI volume node",
+ args.vol);
+ goto out_libubi;
+ } else if (err < 0) {
+ if (errno == ENODEV)
+ errmsg("\"%s\" is not an UBI volume node", args.vol);
+ else
+ sys_errmsg("error while probing \"%s\"", args.vol);
+ goto out_libubi;
+ }
+
+ err = ubi_get_vol_info(libubi, args.vol, &vol_info);
+ if (err) {
+ sys_errmsg("cannot get information about UBI volume \"%s\"",
+ args.vol);
+ goto out_libubi;
+ }
+
+ fd = open(args.vol, O_RDONLY);
+ if (fd == -1) {
+ sys_errmsg("cannot open UBI volume \"%s\"", args.vol);
+ goto out_libubi;
+ }
+
+ err = dump_eraseblock(fd, &vol_info);
+ if (err)
+ goto out_fd;
+
+ close(fd);
+ libubi_close(libubi);
+ return 0;
+
+out_fd:
+ close(fd);
+out_libubi:
+ libubi_close(libubi);
+ return -1;
+}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH v6 3/3] ubi-utils: ubidump compile enable
2014-12-05 9:26 [PATCH v6 1/3] ubi-utils: add library file libdump for ubidump hujianyang
2014-12-05 9:31 ` [PATCH v6 2/3] ubi-utils: introduce ubidump hujianyang
@ 2014-12-05 9:33 ` hujianyang
1 sibling, 0 replies; 3+ messages in thread
From: hujianyang @ 2014-12-05 9:33 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: linux-mtd
This patch enable the compile of ubidump.
Signed-off-by: hujianyang <hujianyang@huawei.com>
---
Makefile | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index eade234..9dc9645 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,8 @@ MTD_BINS = \
sumtool jffs2reader
UBI_BINS = \
ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
- ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock
+ ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock \
+ ubidump
BINS = $(MTD_BINS)
BINS += mkfs.ubifs/mkfs.ubifs
@@ -115,10 +116,12 @@ obj-libiniparser.a = libiniparser.o dictionary.o
obj-libscan.a = libscan.o
obj-libubi.a = libubi.o
obj-libubigen.a = libubigen.o
+obj-libdump.a = libdump.o
obj-mtdinfo = libubigen.a
obj-ubinize = libubigen.a libiniparser.a
obj-ubiformat = libubigen.a libscan.a
+obj-ubidump = libdump.a
-$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
+$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a libdump.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
$(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-common.o)))
--
1.6.0.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-12-05 9:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-05 9:26 [PATCH v6 1/3] ubi-utils: add library file libdump for ubidump hujianyang
2014-12-05 9:31 ` [PATCH v6 2/3] ubi-utils: introduce ubidump hujianyang
2014-12-05 9:33 ` [PATCH v6 3/3] ubi-utils: ubidump compile enable hujianyang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).