⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ubiformat.c

📁 mtd-utils 是一套更改linux mtd設備的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 format MTD devices into UBI and flash UBI images. * * Author: Artem Bityutskiy */#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdint.h>#include <stdlib.h>#include <getopt.h>#include <fcntl.h>#include <libubi.h>#include <libmtd.h>#include <libscan.h>#include <libubigen.h>#include <mtd_swab.h>#include "crc32.h"#include "common.h"#define PROGRAM_VERSION "1.0"#define PROGRAM_NAME    "ubiformat"/* The variables below are set by command line arguments */struct args {	unsigned int yes:1;	unsigned int quiet:1;	unsigned int verbose:1;	unsigned int override_ec:1;	unsigned int novtbl:1;	int subpage_size;	int vid_hdr_offs;	int ubi_ver;	off_t image_sz;	long long ec;	const char *image;	const char *node;};static struct args args ={	.ubi_ver = 1,};static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION		" - a tool to format MTD devices and flash UBI images";static const char *optionsstr ="-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n""                             headers, e.g. sub-page size in case of NAND\n""                             flash (equivalent to the minimum input/output\n""                             unit size by default)\n""-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n""                             physical eraseblock (default is the next\n""                             minimum I/O unit or sub-page after the EC\n""                             header)\n""-n, --no-volume-table        only erase all eraseblock and preserve erase\n""                             counters, do not write empty volume table\n""-f, --flash-image=<file>     flash image file, or '-' for stdin\n""-S, --image-size=<bytes>     bytes in input, if not reading from file\n""-e, --erase-counter=<value>  use <value> as the erase counter value for all\n""                             eraseblocks\n""-y, --yes                    assume the answer is \"yes\" for all question\n""                             this program would otherwise ask\n""-q, --quiet                  suppress progress percentage information\n""-v, --verbose                be verbose\n""-x, --ubi-ver=<num>          UBI version number to put to EC headers\n""                             (default is 1)\n""-h, -?, --help               print help message\n""-V, --version                print program version\n";static const char *usage ="Usage: " PROGRAM_NAME " <MTD device node file name> [-h] [-V] [-y] [-q] [-v]\n""\t\t\t[-x <num>] [-E <value>] [-s <bytes>] [-O <offs>] [-n]\n""\t\t\t[--help] [--version] [--yes] [--verbose] [--quiet]\n""\t\t\t[--ec=<value>] [--vid-hdr-offset=<offs>]\n""\t\t\t[--ubi-ver=<num>] [--no-volume-table]\n""\t\t\t[--flash-image=<file>] [--image-size=<bytes>]\n\n""Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n""           not ask questions.\n""Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n""           be quiet and force erase counter value 0.";static const struct option long_options[] = {	{ .name = "sub-page-size",   .has_arg = 1, .flag = NULL, .val = 's' },	{ .name = "vid-hdr-offset",  .has_arg = 1, .flag = NULL, .val = 'O' },	{ .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' },	{ .name = "flash-image",     .has_arg = 1, .flag = NULL, .val = 'f' },	{ .name = "image-size",      .has_arg = 1, .flag = NULL, .val = 'S' },	{ .name = "yes",             .has_arg = 0, .flag = NULL, .val = 'y' },	{ .name = "erase-counter",   .has_arg = 1, .flag = NULL, .val = 'e' },	{ .name = "quiet",           .has_arg = 0, .flag = NULL, .val = 'q' },	{ .name = "verbose",         .has_arg = 0, .flag = NULL, .val = 'v' },	{ .name = "ubi-ver",         .has_arg = 1, .flag = NULL, .val = 'x' },	{ .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[]){	while (1) {		int key;		char *endp;		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);		if (key == -1)			break;		switch (key) {		case 's':			args.subpage_size = ubiutils_get_bytes(optarg);			if (args.subpage_size <= 0)				return errmsg("bad sub-page size: \"%s\"", optarg);			if (!is_power_of_2(args.subpage_size))				return errmsg("sub-page size should be power of 2");			break;		case 'O':			args.vid_hdr_offs = strtoul(optarg, &endp, 0);			if (args.vid_hdr_offs <= 0 || *endp != '\0' || endp == optarg)				return errmsg("bad VID header offset: \"%s\"", optarg);			break;		case 'e':			args.ec = strtoull(optarg, &endp, 0);			if (args.ec <= 0 || *endp != '\0' || endp == optarg)				return errmsg("bad erase counter value: \"%s\"", optarg);			if (args.ec >= EC_MAX)				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);			args.override_ec = 1;			break;		case 'f':			args.image = optarg;			break;		case 'S':			args.image_sz = ubiutils_get_bytes(optarg);			if (args.image_sz <= 0)				return errmsg("bad image-size: \"%s\"", optarg);			break;		case 'n':			args.novtbl = 1;			break;		case 'y':			args.yes = 1;			break;		case 'q':			args.quiet = 1;			break;		case 'x':			args.ubi_ver = strtoul(optarg, &endp, 0);			if (args.ubi_ver < 0 || *endp != '\0' || endp == optarg)				return errmsg("bad UBI version: \"%s\"", optarg);			break;		case 'v':			args.verbose = 1;			break;		case 'V':			fprintf(stderr, "%s\n", PROGRAM_VERSION);			exit(EXIT_SUCCESS);		case 'h':		case '?':			fprintf(stderr, "%s\n\n", doc);			fprintf(stderr, "%s\n\n", usage);			fprintf(stderr, "%s\n", optionsstr);			exit(EXIT_SUCCESS);		case ':':			return errmsg("parameter is missing");		default:			fprintf(stderr, "Use -h for help\n");			return -1;		}	}	if (args.quiet && args.verbose)		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");	if (optind == argc)		return errmsg("MTD device name was not specified (use -h for help)");	else if (optind != argc - 1)		return errmsg("more then one MTD device specified (use -h for help)");	if (args.image && args.novtbl)		return errmsg("-n cannot be used together with -f");	args.node = argv[optind];	return 0;}static int want_exit(void){	char buf[4];	while (1) {		normsg_cont("continue? (yes/no)  ");		scanf("%3s", buf);		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))			return 0;		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))			return 1;	}}static int answer_is_yes(void){	char buf[4];	while (1) {		scanf("%3s", buf);		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))			return 1;		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))			return 0;	}}static void print_bad_eraseblocks(const struct mtd_info *mtd,				  const struct ubi_scan_info *si){	int first = 1, eb;	if (si->bad_cnt == 0)		return;	normsg_cont("bad eraseblocks: ");	for (eb = 0; eb < mtd->eb_cnt; eb++) {		if (si->ec[eb] != EB_BAD)			continue;		if (first) {			printf("%d", eb);			first = 0;		} else			printf(", %d", eb);	}	printf("\n");}static int change_ec(struct ubi_ec_hdr *hdr, long long ec){	uint32_t crc;	/* Check the EC header */	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)		return errmsg("bad UBI magic %#08x, should be %#08x",			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);	if (be32_to_cpu(hdr->hdr_crc) != crc)		return errmsg("bad CRC %#08x, should be %#08x\n",			      crc, be32_to_cpu(hdr->hdr_crc));	hdr->ec = cpu_to_be64(ec);	crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);	hdr->hdr_crc = cpu_to_be32(crc);	return 0;}static int drop_ffs(const struct mtd_info *mtd, const void *buf, int len){	int i;        for (i = len - 1; i >= 0; i--)		if (((const uint8_t *)buf)[i] != 0xFF)		      break;        /* The resulting length must be aligned to the minimum flash I/O size */        len = i + 1;	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;	len *=  mtd->min_io_size;        return len;}static int open_file(const struct mtd_info *mtd, struct ubi_scan_info *si,		     off_t *sz){	int fd;	if (!strcmp(args.image, "-")) {		if (args.image_sz == 0)			return errmsg("must use '-S' with non-zero value when reading from stdin");		*sz = args.image_sz;		fd  = dup(STDIN_FILENO);		if (fd < 0)			return sys_errmsg("failed to dup stdin");	} else {		struct stat st;		if (stat(args.image, &st))			return sys_errmsg("cannot open \"%s\"", args.image);		*sz = st.st_size;		fd  = open(args.image, O_RDONLY);		if (fd == -1)			return sys_errmsg("cannot open \"%s\"", args.image);	}	return fd;}static int read_all(int fd, void *buf, size_t len){	while (len > 0) {		ssize_t l = read(fd, buf, len);		if (l == 0)			return errmsg("eof reached; %d bytes remaining", len);		else if (l > 0) {			buf += l;			len -= l;		} else if (errno == EINTR || errno == EAGAIN)			continue;		else			return sys_errmsg("reading failed; %d bytes remaining", len);	}	return 0;}static int flash_image(const struct mtd_info *mtd, const struct ubigen_info *ui,		       struct ubi_scan_info *si){	int fd, img_ebs, eb, written_ebs = 0, divisor;	off_t st_size;	fd = open_file(mtd, si, &st_size);	if (fd < 0)		return fd;	img_ebs = st_size / mtd->eb_size;	if (img_ebs > si->good_cnt) {		sys_errmsg("file \"%s\" is too large (%lld bytes)",			   args.image, (long long)st_size);		goto out_close;	}	if (st_size % mtd->eb_size) {		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of eraseblock size (%d bytes)",				  args.image, (long long)st_size, mtd->eb_size);		goto out_close;	}	verbose(args.verbose, "will write %d eraseblocks", img_ebs);	divisor = img_ebs;	for (eb = 0; eb < mtd->eb_cnt; eb++) {		int err, new_len;		char buf[mtd->eb_size];		long long ec;		if (!args.quiet && !args.verbose) {			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete  ",			       eb, (long long)(eb + 1) * 100 / divisor);			fflush(stdout);		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -