211 lines
5.7 KiB
C
211 lines
5.7 KiB
C
/*
|
|
* Copyright (C) 2008 Nokia Corporation
|
|
* Copyright (C) 2012 Wolfram Sang, Pengutronix
|
|
*
|
|
* 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 format MTD devices into UBI and flash UBI images.
|
|
*
|
|
* Author: Artem Bityutskiy
|
|
*/
|
|
|
|
/*
|
|
* Maximum amount of consequtive eraseblocks which are considered as normal by
|
|
* this utility. Otherwise it is assume that something is wrong with the flash
|
|
* or the driver, and eraseblocks are stopped being marked as bad.
|
|
*/
|
|
#define MAX_CONSECUTIVE_BAD_BLOCKS 4
|
|
|
|
#define PROGRAM_NAME "ubiformat"
|
|
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <fs.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <crc.h>
|
|
#include <stdlib.h>
|
|
#include <clock.h>
|
|
#include <malloc.h>
|
|
#include <ioctl.h>
|
|
#include <libbb.h>
|
|
#include <libfile.h>
|
|
#include <ubiformat.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/ubi.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/mtd/mtd-abi.h>
|
|
#include <mtd/libscan.h>
|
|
#include <mtd/libubigen.h>
|
|
#include <mtd/ubi-user.h>
|
|
#include <mtd/utils.h>
|
|
#include <mtd/ubi-media.h>
|
|
#include <mtd/mtd-peb.h>
|
|
|
|
static int parse_opt(int argc, char *argv[], struct ubiformat_args *args,
|
|
char **node)
|
|
{
|
|
srand(get_time_ns());
|
|
memset(args, 0, sizeof(*args));
|
|
|
|
while (1) {
|
|
int key;
|
|
unsigned long int image_seq;
|
|
|
|
key = getopt(argc, argv, "nyqve:x:s:O:f:S:Q:");
|
|
if (key == -1)
|
|
break;
|
|
|
|
switch (key) {
|
|
case 's':
|
|
args->subpage_size = strtoull_suffix(optarg, NULL, 0);
|
|
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 = simple_strtoul(optarg, NULL, 0);
|
|
if (args->vid_hdr_offs <= 0)
|
|
return errmsg("bad VID header offset: \"%s\"", optarg);
|
|
break;
|
|
|
|
case 'e':
|
|
args->ec = simple_strtoull(optarg, NULL, 0);
|
|
if (args->ec < 0)
|
|
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 'n':
|
|
args->novtbl = 1;
|
|
break;
|
|
|
|
case 'y':
|
|
args->yes = 1;
|
|
break;
|
|
|
|
case 'q':
|
|
args->quiet = 1;
|
|
break;
|
|
|
|
case 'x':
|
|
args->ubi_ver = simple_strtoul(optarg, NULL, 0);
|
|
if (args->ubi_ver < 0)
|
|
return errmsg("bad UBI version: \"%s\"", optarg);
|
|
break;
|
|
|
|
case 'Q':
|
|
image_seq = simple_strtoul(optarg, NULL, 0);
|
|
if (image_seq > 0xFFFFFFFF)
|
|
return errmsg("bad UBI image sequence number: \"%s\"", optarg);
|
|
args->image_seq = image_seq;
|
|
break;
|
|
|
|
case 'v':
|
|
args->verbose = 1;
|
|
break;
|
|
|
|
default:
|
|
return COMMAND_ERROR_USAGE;
|
|
}
|
|
}
|
|
|
|
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");
|
|
else if (optind != argc - 1)
|
|
return errmsg("more then one MTD device specified");
|
|
|
|
if (args->image && args->novtbl)
|
|
return errmsg("-n cannot be used together with -f");
|
|
|
|
|
|
*node = argv[optind];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_ubiformat(int argc, char *argv[])
|
|
{
|
|
int err, fd;
|
|
struct ubiformat_args args;
|
|
char *node = NULL;
|
|
struct mtd_info_user mtd_user;
|
|
|
|
err = parse_opt(argc, argv, &args, &node);
|
|
if (err)
|
|
return err;
|
|
|
|
fd = open(node, O_RDWR);
|
|
if (fd < 0)
|
|
return sys_errmsg("cannot open \"%s\"", node);
|
|
|
|
err = ioctl(fd, MEMGETINFO, &mtd_user);
|
|
if (err) {
|
|
sys_errmsg("MEMGETINFO ioctl request failed");
|
|
goto out_close;
|
|
}
|
|
|
|
err = ubiformat(mtd_user.mtd, &args);
|
|
|
|
out_close:
|
|
close(fd);
|
|
|
|
return err;
|
|
}
|
|
|
|
BAREBOX_CMD_HELP_START(ubiformat)
|
|
BAREBOX_CMD_HELP_TEXT("A tool to format MTD devices and flash UBI images")
|
|
BAREBOX_CMD_HELP_TEXT("")
|
|
BAREBOX_CMD_HELP_TEXT("Options:")
|
|
BAREBOX_CMD_HELP_OPT("-s BYTES", "minimum input/output unit used for UBI headers")
|
|
BAREBOX_CMD_HELP_OPT("\t", "e.g. sub-page size in case of NAND flash")
|
|
BAREBOX_CMD_HELP_OPT("-O OFFS\t", "offset if the VID header from start of the")
|
|
BAREBOX_CMD_HELP_OPT("\t", "physical eraseblock (default is the next minimum I/O unit or")
|
|
BAREBOX_CMD_HELP_OPT("\t", "sub-page after the EC header)")
|
|
BAREBOX_CMD_HELP_OPT("-n\t", "only erase all eraseblock and preserve erase")
|
|
BAREBOX_CMD_HELP_OPT("\t", "counters, do not write empty volume table")
|
|
BAREBOX_CMD_HELP_OPT("-f FILE\t", "flash image file")
|
|
BAREBOX_CMD_HELP_OPT("-e VALUE", "use VALUE as erase counter value for all eraseblocks")
|
|
BAREBOX_CMD_HELP_OPT("-x NUM\t", "UBI version number to put to EC headers (default 1)")
|
|
BAREBOX_CMD_HELP_OPT("-Q NUM\t", "32-bit UBI image sequence number to use")
|
|
BAREBOX_CMD_HELP_OPT("-y\t", "Assume yes for all questions")
|
|
BAREBOX_CMD_HELP_OPT("-q\t", "suppress progress percentage information")
|
|
BAREBOX_CMD_HELP_OPT("-v\t", "be verbose")
|
|
BAREBOX_CMD_HELP_TEXT("")
|
|
BAREBOX_CMD_HELP_TEXT("Example 1: ubiformat /dev/nand0 -y - format nand0 and assume yes")
|
|
BAREBOX_CMD_HELP_TEXT("Example 2: ubiformat /dev/nand0 -q -e 0 - format nand0,")
|
|
BAREBOX_CMD_HELP_TEXT("\tbe quiet and force erase counter value 0.")
|
|
BAREBOX_CMD_HELP_END
|
|
|
|
BAREBOX_CMD_START(ubiformat)
|
|
.cmd = do_ubiformat,
|
|
BAREBOX_CMD_DESC("format an ubi volume")
|
|
BAREBOX_CMD_OPTS("[-sOnfexQqv] MTDEVICE")
|
|
BAREBOX_CMD_GROUP(CMD_GRP_PART)
|
|
BAREBOX_CMD_HELP(cmd_ubiformat_help)
|
|
BAREBOX_CMD_END
|