diff options
Diffstat (limited to 'ubi-utils')
| -rw-r--r-- | ubi-utils/new-utils/src/ubiformat.c | 96 | 
1 files changed, 77 insertions, 19 deletions
| diff --git a/ubi-utils/new-utils/src/ubiformat.c b/ubi-utils/new-utils/src/ubiformat.c index c2888e0..05caed9 100644 --- a/ubi-utils/new-utils/src/ubiformat.c +++ b/ubi-utils/new-utils/src/ubiformat.c @@ -51,6 +51,7 @@ struct args {  	int subpage_size;  	int vid_hdr_offs;  	int ubi_ver; +	off_t image_sz;  	long long ec;  	const char *image;  	const char *node; @@ -62,7 +63,7 @@ static struct args args =  };  static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION -		 " - a tool to format MTD devices and flash UBI images"; +		" - 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" @@ -75,7 +76,8 @@ static const char *optionsstr =  "                             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\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" @@ -93,7 +95,7 @@ static const char *usage =  "\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>]\n\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" @@ -105,6 +107,7 @@ static const struct option long_options[] = {  	{ .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' }, @@ -121,7 +124,7 @@ static int parse_opt(int argc, char * const argv[])  		int key;  		char *endp; -		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:", long_options, NULL); +		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);  		if (key == -1)  			break; @@ -153,6 +156,12 @@ static int parse_opt(int argc, char * const argv[])  			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; @@ -284,7 +293,7 @@ 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) +		if (((const uint8_t *)buf)[i] != 0xFF)  		      break;          /* The resulting length must be aligned to the minimum flash I/O size */ @@ -294,27 +303,75 @@ static int drop_ffs(const struct mtd_info *mtd, const void *buf, int len)          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; -	struct stat st; +	off_t st_size; -	if (stat(args.image, &st)) -		return sys_errmsg("cannot open \"%s\"", args.image); +	fd = open_file(mtd, si, &st_size); +	if (fd < 0) +		return fd; -	img_ebs = st.st_size / mtd->eb_size; -	if (img_ebs > si->good_cnt) -		return sys_errmsg("file \"%s\" is too large (%lld bytes)", -				  args.image, (long long)st.st_size); +	img_ebs = st_size / mtd->eb_size; -	if (st.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.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; +	} -	fd = open(args.image, O_RDONLY); -	if (fd == -1) -		return sys_errmsg("cannot open \"%s\"", args.image); +	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; @@ -345,7 +402,8 @@ static int flash_image(const struct mtd_info *mtd, const struct ubigen_info *ui,  			goto out_close;  		} -		if (read(fd, buf, mtd->eb_size) != mtd->eb_size) { +		err = read_all(fd, buf, mtd->eb_size); +		if (err) {  			sys_errmsg("failed to read eraseblock %d from \"%s\"",  				   written_ebs, args.image);  			goto out_close; | 
