From patchwork Tue Jul 29 09:41:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: hujianyang X-Patchwork-Id: 374389 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 831961400DD for ; Tue, 29 Jul 2014 19:43:28 +1000 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XC3v8-00049U-Sl; Tue, 29 Jul 2014 09:42:10 +0000 Received: from szxga02-in.huawei.com ([119.145.14.65]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XC3v5-00045W-1m for linux-mtd@lists.infradead.org; Tue, 29 Jul 2014 09:42:09 +0000 Received: from 172.24.2.119 (EHLO szxeml451-hub.china.huawei.com) ([172.24.2.119]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id BXH53633; Tue, 29 Jul 2014 17:41:15 +0800 (CST) Received: from [127.0.0.1] (10.111.68.144) by szxeml451-hub.china.huawei.com (10.82.67.194) with Microsoft SMTP Server id 14.3.158.1; Tue, 29 Jul 2014 17:41:05 +0800 Message-ID: <53D76C2F.6080908@huawei.com> Date: Tue, 29 Jul 2014 17:41:03 +0800 From: hujianyang User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 To: linux-mtd Subject: [PATCH 3/5] ubi-utils: Introduce ubidump References: <53D7677A.6000905@huawei.com> In-Reply-To: <53D7677A.6000905@huawei.com> X-Originating-IP: [10.111.68.144] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140729_024207_685528_092F200A X-CRM114-Status: GOOD ( 17.64 ) X-Spam-Score: -1.4 (-) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-1.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [119.145.14.65 listed in list.dnswl.org] -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record Cc: Bill Pringlemeir , Artem Bityutskiy X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Read data by MTD functionality now. Also move some dump code to libdump. rename options: -n ---> -l -N ---> --ubifs -H ---> --ubi Signed-off-by: hujianyang --- ubi-utils/ubidump.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) 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..95d055b --- /dev/null +++ b/ubi-utils/ubidump.c @@ -0,0 +1,293 @@ +/* + * 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. + */ + +/* + * An utility to dump UBI/UBIFS format data in eraseblock + * + * Author: Hu Jianyang + */ + +#define PROGRAM_NAME "ubidump" + +#include +#include +#include + +#include +#include +#include +#include "common.h" +#include "ubiutils-common.h" + +#define MTD_DEV_PATT "/dev/mtd%d" + +/* The variables below are set by command line arguments */ +struct args { + const char *vol; + int lnum; + int info:1; + int ubi:1; + int ubifs:1; +}; + +static struct args args = +{ + .vol = NULL, + .lnum = -1, + .info = 0, + .ubi = 0, + .ubifs = 0, +}; + +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\n" +"-i, --info show explicit information about ubifs-level\n" +" --ubi dump ubi-level stuff only\n" +" --ubifs dump ubifs-level stuff only\n" +"-V, --version print program version"; + +static const char usage[] = +"Usage: " PROGRAM_NAME " [-l ] [-i]\n" +"\t\t\t[--help] [--version]\n\n" +"Example 1: " PROGRAM_NAME " /dev/ubi0_1 --lnum 2 - dump leb 2 in volume 1\n" +"Example 2: " PROGRAM_NAME " /dev/ubi0_0 -l 1234 -i - dump leb 1234 with explicit info\n"; + +static const struct option long_options[] = { + { .name = "ubi", .has_arg = 0, .flag = NULL, .val = 0 }, + { .name = "ubifs", .has_arg = 0, .flag = NULL, .val = 0 }, + { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' }, + { .name = "lnum", .has_arg = 1, .flag = NULL, .val = 'l' }, + { .name = "info", .has_arg = 0, .flag = NULL, .val = 'i' }, + { .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 option_index, key, error = 0; + + key = getopt_long(argc, argv, "h?il:", long_options, &option_index); + if (key == -1) + break; + + switch (key) { + case 0: + switch (option_index) { + case 0: + args.ubi = 1; + break; + case 1: + args.ubifs = 1; + break; + } + break; + case 'l': + args.lnum = simple_strtoul(optarg, &error); + if (error || args.lnum < 0) + return errmsg("bad lnum: \"%s\"", optarg); + break; + + case 'i': + args.info = 1; + 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]; + + if (args.lnum < 0) + return errmsg("lnum was not specified (use -h for help)"); + if (args.ubi && (args.info || args.ubifs)) + return errmsg("cannot specify --ubi with -i or --ubifs"); + + return 0; +} + +static int leb_get_pnum(int *pnum) +{ + int fd, err; + + fd = open(args.vol, O_RDONLY); + if (fd == -1) { + sys_errmsg("cannot open UBI volume \"%s\"", args.vol); + return -1; + } + + *pnum = -1; + err = ubi_lnum_to_pnum(fd, args.lnum, pnum); + if (err) + sys_errmsg("ubi_lnum_to_pnum() failed, err = %d", err); + + close(fd); + return err; +} + +static int dump_eraseblock(int mtd_num, int pnum) +{ + int err, fd, peb_size, ret; + int ubi = !args.ubifs; + int ubifs = !args.ubi; + off_t offs; + libmtd_t libmtd; + struct mtd_info mtd_info; + struct mtd_dev_info mtd; + char file[strlen(MTD_DEV_PATT) + 100]; + char *buf; + + libmtd = libmtd_open(); + if (!libmtd) + return errmsg("MTD subsystem is not present"); + + err = mtd_get_info(libmtd, &mtd_info); + if (err) { + if (errno == ENODEV) + errmsg("MTD is not present"); + sys_errmsg("cannot get MTD information"); + goto out; + } + + err = mtd_get_dev_info1(libmtd, mtd_num, &mtd); + if (err) { + sys_errmsg("cannot get information about mtd%d\n", mtd_num); + goto out; + } + + peb_size = mtd.eb_size; + buf = malloc(peb_size); + if (!buf) { + sys_errmsg("cannot alloc %d bytes memoroy", peb_size); + err = -ENOMEM; + goto out; + } + + sprintf(file, MTD_DEV_PATT, mtd_num); + fd = open(file, O_RDONLY); + if (fd == -1) { + sys_errmsg("cannot open MTD device %s, mtd_num = %d", file, mtd_num); + goto out_free; + } + + offs = pnum * peb_size; + ret = pread(fd, buf, peb_size, offs); + if (ret != peb_size) { + errmsg("cannot read %d bytes at pnum %d, read %d", peb_size, + pnum, ret); + err = -EIO; + goto out_fd; + } + + printf("leb %d is mapped to peb %d, start to dump:\n", args.lnum, pnum); + ubidump(buf, peb_size, ubi, ubifs, args.info); + +out_fd: + close(fd); +out_free: + free(buf); +out: + libmtd_close(libmtd); + return err; +} + +int main(int argc, char * const argv[]) +{ + int err, pnum, mtd_num; + libubi_t libubi; + struct ubi_vol_info vol_info; + struct ubi_dev_info dev_info; + + err = parse_opt(argc, argv); + if (err) + return -1; + + libubi = libubi_open(); + if (!libubi) { + if (errno == 0) + errmsg("UBI is not present in the system"); + else + sys_errmsg("cannot open libubi"); + goto out_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; + } + + err = leb_get_pnum(&pnum); + if (err) { + sys_errmsg("cannot get pnum of leb %d", args.lnum); + goto out_libubi; + } else if (pnum == -1) { + errmsg("leb %d is not mapped", args.lnum); + goto out_libubi; + } + + err = ubi_get_dev_info1(libubi, vol_info.dev_num, &dev_info); + if (err) { + sys_errmsg("cannot get information about UBI%d", vol_info.dev_num); + goto out_libubi; + } + mtd_num = dev_info.mtd_num; + + err = dump_eraseblock(mtd_num, pnum); + if (err) + goto out_libubi; + + libubi_close(libubi); + return 0; + +out_libubi: + libubi_close(libubi); + return -1; +}