diff options
| -rw-r--r-- | tools/Makefile | 17 | ||||
| -rw-r--r-- | tools/default_image.c | 149 | ||||
| -rw-r--r-- | tools/fit_image.c | 212 | ||||
| -rw-r--r-- | tools/mkimage.c | 543 | ||||
| -rw-r--r-- | tools/mkimage.h | 101 | 
5 files changed, 732 insertions, 290 deletions
| diff --git a/tools/Makefile b/tools/Makefile index 6f36f23dc..858b0e8f0 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -183,8 +183,15 @@ $(obj)inca-swap-bytes$(SFX):	$(obj)inca-swap-bytes.o  	$(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^  	$(STRIP) $@ -$(obj)mkimage$(SFX):	$(obj)crc32.o $(obj)mkimage.o $(obj)image.o $(obj)md5.o $(obj)mkimage.o \ -			$(obj)os_support.o $(obj)sha1.o $(LIBFDT_OBJS) +$(obj)mkimage$(SFX):	$(obj)crc32.o \ +			$(obj)default_image.o \ +			$(obj)fit_image.o \ +			$(obj)image.o \ +			$(obj)md5.o \ +			$(obj)mkimage.o \ +			$(obj)os_support.o \ +			$(obj)sha1.o \ +			$(LIBFDT_OBJS)  	$(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^  	$(STRIP) $@ @@ -200,6 +207,12 @@ $(obj)ubsha1$(SFX):	$(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o  	$(CC) $(CFLAGS) -o $@ $^  # Some files complain if compiled with -pedantic, use FIT_CFLAGS +$(obj)default_image.o: $(SRCTREE)/tools/default_image.c +	$(CC) -g $(FIT_CFLAGS) -c -o $@ $< + +$(obj)fit_image.o: $(SRCTREE)/tools/fit_image.c +	$(CC) -g $(FIT_CFLAGS) -c -o $@ $< +  $(obj)image.o: $(SRCTREE)/common/image.c  	$(CC) -g $(FIT_CFLAGS) -c -o $@ $< diff --git a/tools/default_image.c b/tools/default_image.c new file mode 100644 index 000000000..f5bad4757 --- /dev/null +++ b/tools/default_image.c @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar <prafulla@marvell.com> + *		default_image specific code abstracted from mkimage.c + *		some functions added to address abstraction + * + * All rights reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <image.h> +#include <u-boot/crc.h> + +static image_header_t header; + +static int image_check_image_types (uint8_t type) +{ +	if ((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT)) +		return EXIT_SUCCESS; +	else +		return EXIT_FAILURE; +} + +static int image_check_params (struct mkimage_params *params) +{ +	return	((params->dflag && (params->fflag || params->lflag)) || +		(params->fflag && (params->dflag || params->lflag)) || +		(params->lflag && (params->dflag || params->fflag))); +} + +static int image_verify_header (unsigned char *ptr, int image_size, +			struct mkimage_params *params) +{ +	uint32_t len; +	const unsigned char *data; +	uint32_t checksum; +	image_header_t header; +	image_header_t *hdr = &header; + +	/* +	 * create copy of header so that we can blank out the +	 * checksum field for checking - this can't be done +	 * on the PROT_READ mapped data. +	 */ +	memcpy (hdr, ptr, sizeof(image_header_t)); + +	if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { +		fprintf (stderr, +			"%s: Bad Magic Number: \"%s\" is no valid image\n", +			params->cmdname, params->imagefile); +		return -FDT_ERR_BADMAGIC; +	} + +	data = (const unsigned char *)hdr; +	len  = sizeof(image_header_t); + +	checksum = be32_to_cpu(hdr->ih_hcrc); +	hdr->ih_hcrc = cpu_to_be32(0);	/* clear for re-calculation */ + +	if (crc32 (0, data, len) != checksum) { +		fprintf (stderr, +			"%s: ERROR: \"%s\" has bad header checksum!\n", +			params->cmdname, params->imagefile); +		return -FDT_ERR_BADSTATE; +	} + +	data = (const unsigned char *)ptr + sizeof(image_header_t); +	len  = image_size - sizeof(image_header_t) ; + +	checksum = be32_to_cpu(hdr->ih_dcrc); +	if (crc32 (0, data, len) != checksum) { +		fprintf (stderr, +			"%s: ERROR: \"%s\" has corrupted data!\n", +			params->cmdname, params->imagefile); +		return -FDT_ERR_BADSTRUCTURE; +	} +	return 0; +} + +static void image_set_header (void *ptr, struct stat *sbuf, int ifd, +				struct mkimage_params *params) +{ +	uint32_t checksum; + +	image_header_t * hdr = (image_header_t *)ptr; + +	checksum = crc32 (0, +			(const unsigned char *)(ptr + +				sizeof(image_header_t)), +			sbuf->st_size - sizeof(image_header_t)); + +	/* Build new header */ +	image_set_magic (hdr, IH_MAGIC); +	image_set_time (hdr, sbuf->st_mtime); +	image_set_size (hdr, sbuf->st_size - sizeof(image_header_t)); +	image_set_load (hdr, params->addr); +	image_set_ep (hdr, params->ep); +	image_set_dcrc (hdr, checksum); +	image_set_os (hdr, params->os); +	image_set_arch (hdr, params->arch); +	image_set_type (hdr, params->type); +	image_set_comp (hdr, params->comp); + +	image_set_name (hdr, params->imagename); + +	checksum = crc32 (0, (const unsigned char *)hdr, +				sizeof(image_header_t)); + +	image_set_hcrc (hdr, checksum); +} + +/* + * Default image type parameters definition + */ +static struct image_type_params defimage_params = { +	.name = "Default Image support", +	.header_size = sizeof(image_header_t), +	.hdr = (void*)&header, +	.check_image_type = image_check_image_types, +	.verify_header = image_verify_header, +	.print_header = image_print_contents, +	.set_header = image_set_header, +	.check_params = image_check_params, +}; + +void init_default_image_type (void) +{ +	mkimage_register (&defimage_params); +} diff --git a/tools/fit_image.c b/tools/fit_image.c new file mode 100644 index 000000000..d1e612fec --- /dev/null +++ b/tools/fit_image.c @@ -0,0 +1,212 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar <prafulla@marvell.com> + *		FIT image specific code abstracted from mkimage.c + *		some functions added to address abstraction + * + * All rights reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <image.h> +#include <u-boot/crc.h> + +static image_header_t header; + +static int fit_verify_header (unsigned char *ptr, int image_size, +			struct mkimage_params *params) +{ +	return fdt_check_header ((void *)ptr); +} + +static int fit_check_image_types (uint8_t type) +{ +	if (type == IH_TYPE_FLATDT) +		return EXIT_SUCCESS; +	else +		return EXIT_FAILURE; +} + +/** + * fit_handle_file - main FIT file processing function + * + * fit_handle_file() runs dtc to convert .its to .itb, includes + * binary data, updates timestamp property and calculates hashes. + * + * datafile  - .its file + * imagefile - .itb file + * + * returns: + *     only on success, otherwise calls exit (EXIT_FAILURE); + */ +static int fit_handle_file (struct mkimage_params *params) +{ +	char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; +	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; +	int tfd; +	struct stat sbuf; +	unsigned char *ptr; + +	/* Flattened Image Tree (FIT) format  handling */ +	debug ("FIT format handling\n"); + +	/* call dtc to include binary properties into the tmp file */ +	if (strlen (params->imagefile) + +		strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > sizeof (tmpfile)) { +		fprintf (stderr, "%s: Image file name (%s) too long, " +				"can't create tmpfile", +				params->imagefile, params->cmdname); +		return (EXIT_FAILURE); +	} +	sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); + +	/* dtc -I dts -O -p 200 datafile > tmpfile */ +	sprintf (cmd, "%s %s %s > %s", +		MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); +	debug ("Trying to execute \"%s\"\n", cmd); +	if (system (cmd) == -1) { +		fprintf (stderr, "%s: system(%s) failed: %s\n", +				params->cmdname, cmd, strerror(errno)); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	/* load FIT blob into memory */ +	tfd = open (tmpfile, O_RDWR|O_BINARY); + +	if (tfd < 0) { +		fprintf (stderr, "%s: Can't open %s: %s\n", +				params->cmdname, tmpfile, strerror(errno)); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	if (fstat (tfd, &sbuf) < 0) { +		fprintf (stderr, "%s: Can't stat %s: %s\n", +				params->cmdname, tmpfile, strerror(errno)); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, +				tfd, 0); +	if (ptr == MAP_FAILED) { +		fprintf (stderr, "%s: Can't read %s: %s\n", +				params->cmdname, tmpfile, strerror(errno)); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	/* check if ptr has a valid blob */ +	if (fdt_check_header (ptr)) { +		fprintf (stderr, "%s: Invalid FIT blob\n", params->cmdname); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	/* set hashes for images in the blob */ +	if (fit_set_hashes (ptr)) { +		fprintf (stderr, "%s Can't add hashes to FIT blob", +				params->cmdname); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} + +	/* add a timestamp at offset 0 i.e., root  */ +	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { +		fprintf (stderr, "%s: Can't add image timestamp\n", +				params->cmdname); +		unlink (tmpfile); +		return (EXIT_FAILURE); +	} +	debug ("Added timestamp successfully\n"); + +	munmap ((void *)ptr, sbuf.st_size); +	close (tfd); + +	if (rename (tmpfile, params->imagefile) == -1) { +		fprintf (stderr, "%s: Can't rename %s to %s: %s\n", +				params->cmdname, tmpfile, params->imagefile, +				strerror (errno)); +		unlink (tmpfile); +		unlink (params->imagefile); +		return (EXIT_FAILURE); +	} +	return (EXIT_SUCCESS); +} + +static void fit_set_header (void *ptr, struct stat *sbuf, int ifd, +				struct mkimage_params *params) +{ +	uint32_t checksum; + +	image_header_t * hdr = (image_header_t *)ptr; + +	checksum = crc32 (0, +			(const unsigned char *)(ptr + +				sizeof(image_header_t)), +			sbuf->st_size - sizeof(image_header_t)); + +	/* Build new header */ +	image_set_magic (hdr, IH_MAGIC); +	image_set_time (hdr, sbuf->st_mtime); +	image_set_size (hdr, sbuf->st_size - sizeof(image_header_t)); +	image_set_load (hdr, params->addr); +	image_set_ep (hdr, params->ep); +	image_set_dcrc (hdr, checksum); +	image_set_os (hdr, params->os); +	image_set_arch (hdr, params->arch); +	image_set_type (hdr, params->type); +	image_set_comp (hdr, params->comp); + +	image_set_name (hdr, params->imagename); + +	checksum = crc32 (0, (const unsigned char *)hdr, +				sizeof(image_header_t)); + +	image_set_hcrc (hdr, checksum); +} + +static int fit_check_params (struct mkimage_params *params) +{ +	return	((params->dflag && (params->fflag || params->lflag)) || +		(params->fflag && (params->dflag || params->lflag)) || +		(params->lflag && (params->dflag || params->fflag))); +} + +static struct image_type_params fitimage_params = { +	.name = "FIT Image support", +	.header_size = sizeof(image_header_t), +	.hdr = (void*)&header, +	.verify_header = fit_verify_header, +	.print_header = fit_print_contents, +	.check_image_type = fit_check_image_types, +	.fflag_handle = fit_handle_file, +	.set_header = fit_set_header, +	.check_params = fit_check_params, +}; + +void init_fit_image_type (void) +{ +	mkimage_register (&fitimage_params); +} diff --git a/tools/mkimage.c b/tools/mkimage.c index b0c02ebcf..c43b20772 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -1,7 +1,7 @@  /*   * (C) Copyright 2008 Semihalf   * - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2009   * DENX Software Engineering   * Wolfgang Denk, wd@denx.de   * @@ -23,126 +23,223 @@  #include "mkimage.h"  #include <image.h> -#include <u-boot/crc.h> -static	void		copy_file (int, const char *, int); -static	void		usage (void); -static	int		image_verify_header (char *, int); -static	void		fit_handle_file (void); +static void copy_file(int, const char *, int); +static void usage(void); -char	*datafile; -char	*imagefile; -char	*cmdname; +/* image_type_params link list to maintain registered image type supports */ +struct image_type_params *mkimage_tparams = NULL; -int dflag    = 0; -int eflag    = 0; -int fflag    = 0; -int lflag    = 0; -int vflag    = 0; -int xflag    = 0; -int opt_os   = IH_OS_LINUX; -int opt_arch = IH_ARCH_PPC; -int opt_type = IH_TYPE_KERNEL; -int opt_comp = IH_COMP_GZIP; -char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS; +/* parameters initialized by core will be used by the image type code */ +struct mkimage_params params = { +	.os = IH_OS_LINUX, +	.arch = IH_ARCH_PPC, +	.type = IH_TYPE_KERNEL, +	.comp = IH_COMP_GZIP, +	.dtc = MKIMAGE_DEFAULT_DTC_OPTIONS, +}; -image_header_t header; -image_header_t *hdr = &header; +/* + * mkimage_register - + * + * It is used to register respective image generation/list support to the + * mkimage core + * + * the input struct image_type_params is checked and appended to the link + * list, if the input structure is already registered, error + */ +void mkimage_register (struct image_type_params *tparams) +{ +	struct image_type_params **tp; + +	if (!tparams) { +		fprintf (stderr, "%s: %s: Null input\n", +			params.cmdname, __FUNCTION__); +		exit (EXIT_FAILURE); +	} + +	/* scan the linked list, check for registry and point the last one */ +	for (tp = &mkimage_tparams; *tp != NULL; tp = &(*tp)->next) { +		if (!strcmp((*tp)->name, tparams->name)) { +			fprintf (stderr, "%s: %s already registered\n", +				params.cmdname, tparams->name); +			return; +		} +	} + +	/* add input struct entry at the end of link list */ +	*tp = tparams; +	/* mark input entry as last entry in the link list */ +	tparams->next = NULL; + +	debug ("Registered %s\n", tparams->name); +} + +/* + * mkimage_get_type - + * + * It scans all registers image type supports + * checks the input type_id for each supported image type + * + * if successful, + * 	returns respective image_type_params pointer if success + * if input type_id is not supported by any of image_type_support + * 	returns NULL + */ +struct image_type_params *mkimage_get_type(int type) +{ +	struct image_type_params *curr; + +	for (curr = mkimage_tparams; curr != NULL; curr = curr->next) { +		if (curr->check_image_type) { +			if (!curr->check_image_type (type)) +				return curr; +		} +	} +	return NULL; +} + +/* + * mkimage_verify_print_header - + * + * It scans mkimage_tparams link list, + * verifies image_header for each supported image type + * if verification is successful, prints respective header + * + * returns negative if input image format does not match with any of + * supported image types + */ +int mkimage_verify_print_header (void *ptr, struct stat *sbuf) +{ +	int retval = -1; +	struct image_type_params *curr; + +	for (curr = mkimage_tparams; curr != NULL; curr = curr->next ) { +		if (curr->verify_header) { +			retval = curr->verify_header ( +				(unsigned char *)ptr, sbuf->st_size, +				¶ms); + +			if (retval == 0) { +				/* +				 * Print the image information +				 * if verify is successful +				 */ +				if (curr->print_header) +					curr->print_header (ptr); +				else { +					fprintf (stderr, +					"%s: print_header undefined for %s\n", +					params.cmdname, curr->name); +				} +				break; +			} +		} +	} +	return retval; +}  int  main (int argc, char **argv)  {  	int ifd = -1; -	uint32_t checksum; -	uint32_t addr; -	uint32_t ep;  	struct stat sbuf;  	unsigned char *ptr; -	char *name = "";  	int retval = 0; +	struct image_type_params *tparams = NULL; -	cmdname = *argv; +	/* Init FIT image generation/list support */ +	init_fit_image_type (); +	/* Init Default image generation/list support */ +	init_default_image_type (); -	addr = ep = 0; +	params.cmdname = *argv; +	params.addr = params.ep = 0;  	while (--argc > 0 && **++argv == '-') {  		while (*++*argv) {  			switch (**argv) {  			case 'l': -				lflag = 1; +				params.lflag = 1;  				break;  			case 'A':  				if ((--argc <= 0) || -				    (opt_arch = genimg_get_arch_id (*++argv)) < 0) +					(params.arch = +					genimg_get_arch_id (*++argv)) < 0)  					usage ();  				goto NXTARG;  			case 'C':  				if ((--argc <= 0) || -				    (opt_comp = genimg_get_comp_id (*++argv)) < 0) +					(params.comp = +					genimg_get_comp_id (*++argv)) < 0)  					usage ();  				goto NXTARG;  			case 'D':  				if (--argc <= 0)  					usage (); -				opt_dtc = *++argv; +				params.dtc = *++argv;  				goto NXTARG;  			case 'O':  				if ((--argc <= 0) || -				    (opt_os = genimg_get_os_id (*++argv)) < 0) +					(params.os = +					genimg_get_os_id (*++argv)) < 0)  					usage ();  				goto NXTARG;  			case 'T':  				if ((--argc <= 0) || -				    (opt_type = genimg_get_type_id (*++argv)) < 0) +					(params.type = +					genimg_get_type_id (*++argv)) < 0)  					usage ();  				goto NXTARG;  			case 'a':  				if (--argc <= 0)  					usage (); -				addr = strtoul (*++argv, (char **)&ptr, 16); +				params.addr = strtoul (*++argv, +					(char **)&ptr, 16);  				if (*ptr) {  					fprintf (stderr,  						"%s: invalid load address %s\n", -						cmdname, *argv); +						params.cmdname, *argv);  					exit (EXIT_FAILURE);  				}  				goto NXTARG;  			case 'd':  				if (--argc <= 0)  					usage (); -				datafile = *++argv; -				dflag = 1; +				params.datafile = *++argv; +				params.dflag = 1;  				goto NXTARG;  			case 'e':  				if (--argc <= 0)  					usage (); -				ep = strtoul (*++argv, (char **)&ptr, 16); +				params.ep = strtoul (*++argv, +						(char **)&ptr, 16);  				if (*ptr) {  					fprintf (stderr,  						"%s: invalid entry point %s\n", -						cmdname, *argv); +						params.cmdname, *argv);  					exit (EXIT_FAILURE);  				} -				eflag = 1; +				params.eflag = 1;  				goto NXTARG;  			case 'f':  				if (--argc <= 0)  					usage (); -				datafile = *++argv; -				fflag = 1; +				params.datafile = *++argv; +				params.fflag = 1;  				goto NXTARG;  			case 'n':  				if (--argc <= 0)  					usage (); -				name = *++argv; +				params.imagename = *++argv;  				goto NXTARG;  			case 'v': -				vflag++; +				params.vflag++;  				break;  			case 'x': -				xflag++; +				params.xflag++;  				break;  			default:  				usage (); @@ -151,91 +248,112 @@ main (int argc, char **argv)  NXTARG:		;  	} -	if ((argc != 1) || -		(dflag && (fflag || lflag)) || -		(fflag && (dflag || lflag)) || -		(lflag && (dflag || fflag))) -		usage(); +	if (argc != 1) +		usage (); -	if (!eflag) { -		ep = addr; +	/* set tparams as per input type_id */ +	tparams = mkimage_get_type(params.type); +	if (tparams == NULL) { +		fprintf (stderr, "%s: unsupported type %s\n", +			params.cmdname, genimg_get_type_name(params.type)); +		exit (EXIT_FAILURE); +	} + +	/* +	 * check the passed arguments parameters meets the requirements +	 * as per image type to be generated/listed +	 */ +	if (tparams->check_params) +		if (tparams->check_params (¶ms)) +			usage (); + +	if (!params.eflag) { +		params.ep = params.addr;  		/* If XIP, entry point must be after the U-Boot header */ -		if (xflag) -			ep += image_get_header_size (); +		if (params.xflag) +			params.ep += tparams->header_size;  	}  	/*  	 * If XIP, ensure the entry point is equal to the load address plus  	 * the size of the U-Boot header.  	 */ -	if (xflag) { -		if (ep != addr + image_get_header_size ()) { +	if (params.xflag) { +		if (params.ep != params.addr + tparams->header_size) {  			fprintf (stderr,  				"%s: For XIP, the entry point must be the load addr + %lu\n", -				cmdname, -				(unsigned long)image_get_header_size ()); +				params.cmdname, +				(unsigned long)tparams->header_size);  			exit (EXIT_FAILURE);  		}  	} -	imagefile = *argv; +	params.imagefile = *argv; -	if (!fflag){ -		if (lflag) { -			ifd = open (imagefile, O_RDONLY|O_BINARY); +	if (!params.fflag){ +		if (params.lflag) { +			ifd = open (params.imagefile, O_RDONLY|O_BINARY);  		} else { -			ifd = open (imagefile, +			ifd = open (params.imagefile,  				O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);  		}  		if (ifd < 0) {  			fprintf (stderr, "%s: Can't open %s: %s\n", -				cmdname, imagefile, strerror(errno)); +				params.cmdname, params.imagefile, +				strerror(errno));  			exit (EXIT_FAILURE);  		}  	} -	if (lflag) { +	if (params.lflag) {  		/*  		 * list header information of existing image  		 */  		if (fstat(ifd, &sbuf) < 0) {  			fprintf (stderr, "%s: Can't stat %s: %s\n", -				cmdname, imagefile, strerror(errno)); +				params.cmdname, params.imagefile, +				strerror(errno));  			exit (EXIT_FAILURE);  		} -		if ((unsigned)sbuf.st_size < image_get_header_size ()) { +		if ((unsigned)sbuf.st_size < tparams->header_size) {  			fprintf (stderr, -				"%s: Bad size: \"%s\" is no valid image\n", -				cmdname, imagefile); +				"%s: Bad size: \"%s\" is not valid image\n", +				params.cmdname, params.imagefile);  			exit (EXIT_FAILURE);  		}  		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);  		if (ptr == MAP_FAILED) {  			fprintf (stderr, "%s: Can't read %s: %s\n", -				cmdname, imagefile, strerror(errno)); +				params.cmdname, params.imagefile, +				strerror(errno));  			exit (EXIT_FAILURE);  		} -		if (!(retval = fdt_check_header (ptr))) { -			/* FIT image */ -			fit_print_contents (ptr); -		} else if (!(retval = image_verify_header ((char *)ptr, -							   sbuf.st_size))) { -			/* old-style image */ -			image_print_contents ((image_header_t *)ptr); -		} +		/* +		 * scan through mkimage registry for all supported image types +		 * and verify the input image file header for match +		 * Print the image information for matched image type +		 * Returns the error code if not matched +		 */ +		retval = mkimage_verify_print_header (ptr, &sbuf);  		(void) munmap((void *)ptr, sbuf.st_size);  		(void) close (ifd);  		exit (retval); -	} else if (fflag) { -		/* Flattened Image Tree (FIT) format  handling */ -		debug ("FIT format handling\n"); -		fit_handle_file (); +	} else if (params.fflag) { +		if (tparams->fflag_handle) +			/* +			 * in some cases, some additional processing needs +			 * to be done if fflag is defined +			 * +			 * For ex. fit_handle_file for Fit file support +			 */ +			retval = tparams->fflag_handle(¶ms); +  		exit (retval);  	} @@ -244,16 +362,17 @@ NXTARG:		;  	 *  	 * write dummy header, to be fixed later  	 */ -	memset (hdr, 0, image_get_header_size ()); +	memset (tparams->hdr, 0, tparams->header_size); -	if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { +	if (write(ifd, tparams->hdr, tparams->header_size) +					!= tparams->header_size) {  		fprintf (stderr, "%s: Write error on %s: %s\n", -			cmdname, imagefile, strerror(errno)); +			params.cmdname, params.imagefile, strerror(errno));  		exit (EXIT_FAILURE);  	} -	if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) { -		char *file = datafile; +	if (params.type == IH_TYPE_MULTI || params.type == IH_TYPE_SCRIPT) { +		char *file = params.datafile;  		uint32_t size;  		for (;;) { @@ -266,7 +385,7 @@ NXTARG:		;  				if (stat (file, &sbuf) < 0) {  					fprintf (stderr, "%s: Can't stat %s: %s\n", -						cmdname, file, strerror(errno)); +						params.cmdname, file, strerror(errno));  					exit (EXIT_FAILURE);  				}  				size = cpu_to_uimage (sbuf.st_size); @@ -276,7 +395,8 @@ NXTARG:		;  			if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {  				fprintf (stderr, "%s: Write error on %s: %s\n", -					cmdname, imagefile, strerror(errno)); +					params.cmdname, params.imagefile, +					strerror(errno));  				exit (EXIT_FAILURE);  			} @@ -292,7 +412,7 @@ NXTARG:		;  			}  		} -		file = datafile; +		file = params.datafile;  		for (;;) {  			char *sep = strchr(file, ':'); @@ -307,11 +427,14 @@ NXTARG:		;  			}  		}  	} else { -		copy_file (ifd, datafile, 0); +		copy_file (ifd, params.datafile, 0);  	}  	/* We're a bit of paranoid */ -#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) +#if defined(_POSIX_SYNCHRONIZED_IO) && \ +   !defined(__sun__) && \ +   !defined(__FreeBSD__) && \ +   !defined(__APPLE__)  	(void) fdatasync (ifd);  #else  	(void) fsync (ifd); @@ -319,50 +442,42 @@ NXTARG:		;  	if (fstat(ifd, &sbuf) < 0) {  		fprintf (stderr, "%s: Can't stat %s: %s\n", -			cmdname, imagefile, strerror(errno)); +			params.cmdname, params.imagefile, strerror(errno));  		exit (EXIT_FAILURE);  	}  	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);  	if (ptr == MAP_FAILED) {  		fprintf (stderr, "%s: Can't map %s: %s\n", -			cmdname, imagefile, strerror(errno)); +			params.cmdname, params.imagefile, strerror(errno));  		exit (EXIT_FAILURE);  	} -	hdr = (image_header_t *)ptr; - -	checksum = crc32 (0, -			  (const unsigned char *)(ptr + -				image_get_header_size ()), -			  sbuf.st_size - image_get_header_size () -			 ); - -	/* Build new header */ -	image_set_magic (hdr, IH_MAGIC); -	image_set_time (hdr, sbuf.st_mtime); -	image_set_size (hdr, sbuf.st_size - image_get_header_size ()); -	image_set_load (hdr, addr); -	image_set_ep (hdr, ep); -	image_set_dcrc (hdr, checksum); -	image_set_os (hdr, opt_os); -	image_set_arch (hdr, opt_arch); -	image_set_type (hdr, opt_type); -	image_set_comp (hdr, opt_comp); - -	image_set_name (hdr, name); - -	checksum = crc32 (0, (const unsigned char *)hdr, -					image_get_header_size ()); - -	image_set_hcrc (hdr, checksum); +	/* Setup the image header as per input image type*/ +	if (tparams->set_header) +		tparams->set_header (ptr, &sbuf, ifd, ¶ms); +	else { +		fprintf (stderr, "%s: Can't set header for %s: %s\n", +			params.cmdname, tparams->name, strerror(errno)); +		exit (EXIT_FAILURE); +	} -	image_print_contents (hdr); +	/* Print the image information by processing image header */ +	if (tparams->print_header) +		tparams->print_header (ptr); +	else { +		fprintf (stderr, "%s: Can't print header for %s: %s\n", +			params.cmdname, tparams->name, strerror(errno)); +		exit (EXIT_FAILURE); +	}  	(void) munmap((void *)ptr, sbuf.st_size);  	/* We're a bit of paranoid */ -#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) +#if defined(_POSIX_SYNCHRONIZED_IO) && \ +   !defined(__sun__) && \ +   !defined(__FreeBSD__) && \ +   !defined(__APPLE__)  	(void) fdatasync (ifd);  #else  	(void) fsync (ifd); @@ -370,7 +485,7 @@ NXTARG:		;  	if (close(ifd)) {  		fprintf (stderr, "%s: Write error on %s: %s\n", -			cmdname, imagefile, strerror(errno)); +			params.cmdname, params.imagefile, strerror(errno));  		exit (EXIT_FAILURE);  	} @@ -387,31 +502,32 @@ copy_file (int ifd, const char *datafile, int pad)  	int zero = 0;  	int offset = 0;  	int size; +	struct image_type_params *tparams = mkimage_get_type (params.type); -	if (vflag) { +	if (params.vflag) {  		fprintf (stderr, "Adding Image %s\n", datafile);  	}  	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {  		fprintf (stderr, "%s: Can't open %s: %s\n", -			cmdname, datafile, strerror(errno)); +			params.cmdname, datafile, strerror(errno));  		exit (EXIT_FAILURE);  	}  	if (fstat(dfd, &sbuf) < 0) {  		fprintf (stderr, "%s: Can't stat %s: %s\n", -			cmdname, datafile, strerror(errno)); +			params.cmdname, datafile, strerror(errno));  		exit (EXIT_FAILURE);  	}  	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);  	if (ptr == MAP_FAILED) {  		fprintf (stderr, "%s: Can't read %s: %s\n", -			cmdname, datafile, strerror(errno)); +			params.cmdname, datafile, strerror(errno));  		exit (EXIT_FAILURE);  	} -	if (xflag) { +	if (params.xflag) {  		unsigned char *p = NULL;  		/*  		 * XIP: do not append the image_header_t at the @@ -419,29 +535,29 @@ copy_file (int ifd, const char *datafile, int pad)  		 * reserved for it.  		 */ -		if ((unsigned)sbuf.st_size < image_get_header_size ()) { +		if ((unsigned)sbuf.st_size < tparams->header_size) {  			fprintf (stderr,  				"%s: Bad size: \"%s\" is too small for XIP\n", -				cmdname, datafile); +				params.cmdname, datafile);  			exit (EXIT_FAILURE);  		} -		for (p = ptr; p < ptr + image_get_header_size (); p++) { +		for (p = ptr; p < ptr + tparams->header_size; p++) {  			if ( *p != 0xff ) {  				fprintf (stderr,  					"%s: Bad file: \"%s\" has invalid buffer for XIP\n", -					cmdname, datafile); +					params.cmdname, datafile);  				exit (EXIT_FAILURE);  			}  		} -		offset = image_get_header_size (); +		offset = tparams->header_size;  	}  	size = sbuf.st_size - offset;  	if (write(ifd, ptr + offset, size) != size) {  		fprintf (stderr, "%s: Write error on %s: %s\n", -			cmdname, imagefile, strerror(errno)); +			params.cmdname, params.imagefile, strerror(errno));  		exit (EXIT_FAILURE);  	} @@ -449,7 +565,8 @@ copy_file (int ifd, const char *datafile, int pad)  		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {  			fprintf (stderr, "%s: Write error on %s: %s\n", -				cmdname, imagefile, strerror(errno)); +				params.cmdname, params.imagefile, +				strerror(errno));  			exit (EXIT_FAILURE);  		}  	} @@ -463,7 +580,7 @@ usage ()  {  	fprintf (stderr, "Usage: %s -l image\n"  			 "          -l ==> list image header information\n", -		cmdname); +		params.cmdname);  	fprintf (stderr, "       %s [-x] -A arch -O os -T type -C comp "  			 "-a addr -e ep -n name -d data_file[:data_file...] image\n"  			 "          -A ==> set architecture to 'arch'\n" @@ -475,157 +592,9 @@ usage ()  			 "          -n ==> set image name to 'name'\n"  			 "          -d ==> use image data from 'datafile'\n"  			 "          -x ==> set XIP (execute in place)\n", -		cmdname); +		params.cmdname);  	fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n", -		cmdname); +		params.cmdname);  	exit (EXIT_FAILURE);  } - -static int -image_verify_header (char *ptr, int image_size) -{ -	int len; -	const unsigned char *data; -	uint32_t checksum; -	image_header_t header; -	image_header_t *hdr = &header; - -	/* -	 * create copy of header so that we can blank out the -	 * checksum field for checking - this can't be done -	 * on the PROT_READ mapped data. -	 */ -	memcpy (hdr, ptr, sizeof(image_header_t)); - -	if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { -		fprintf (stderr, -			"%s: Bad Magic Number: \"%s\" is no valid image\n", -			cmdname, imagefile); -		return -FDT_ERR_BADMAGIC; -	} - -	data = (const unsigned char *)hdr; -	len  = sizeof(image_header_t); - -	checksum = be32_to_cpu(hdr->ih_hcrc); -	hdr->ih_hcrc = cpu_to_be32(0);	/* clear for re-calculation */ - -	if (crc32 (0, data, len) != checksum) { -		fprintf (stderr, -			"%s: ERROR: \"%s\" has bad header checksum!\n", -			cmdname, imagefile); -		return -FDT_ERR_BADSTATE; -	} - -	data = (const unsigned char *)ptr + sizeof(image_header_t); -	len  = image_size - sizeof(image_header_t) ; - -	if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) { -		fprintf (stderr, -			"%s: ERROR: \"%s\" has corrupted data!\n", -			cmdname, imagefile); -		return -FDT_ERR_BADSTRUCTURE; -	} -	return 0; -} - -/** - * fit_handle_file - main FIT file processing function - * - * fit_handle_file() runs dtc to convert .its to .itb, includes - * binary data, updates timestamp property and calculates hashes. - * - * datafile  - .its file - * imagefile - .itb file - * - * returns: - *     only on success, otherwise calls exit (EXIT_FAILURE); - */ -static void fit_handle_file (void) -{ -	char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; -	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; -	int tfd; -	struct stat sbuf; -	unsigned char *ptr; - -	/* call dtc to include binary properties into the tmp file */ -	if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > -		sizeof (tmpfile)) { -		fprintf (stderr, "%s: Image file name (%s) too long, " -				"can't create tmpfile", -				imagefile, cmdname); -		exit (EXIT_FAILURE); -	} -	sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX); - -	/* dtc -I dts -O -p 200 datafile > tmpfile */ -	sprintf (cmd, "%s %s %s > %s", -			MKIMAGE_DTC, opt_dtc, datafile, tmpfile); -	debug ("Trying to execute \"%s\"\n", cmd); -	if (system (cmd) == -1) { -		fprintf (stderr, "%s: system(%s) failed: %s\n", -				cmdname, cmd, strerror(errno)); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	/* load FIT blob into memory */ -	tfd = open (tmpfile, O_RDWR|O_BINARY); - -	if (tfd < 0) { -		fprintf (stderr, "%s: Can't open %s: %s\n", -				cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	if (fstat (tfd, &sbuf) < 0) { -		fprintf (stderr, "%s: Can't stat %s: %s\n", -				cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); -	if (ptr == MAP_FAILED) { -		fprintf (stderr, "%s: Can't read %s: %s\n", -				cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	/* check if ptr has a valid blob */ -	if (fdt_check_header (ptr)) { -		fprintf (stderr, "%s: Invalid FIT blob\n", cmdname); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	/* set hashes for images in the blob */ -	if (fit_set_hashes (ptr)) { -		fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} - -	/* add a timestamp at offset 0 i.e., root  */ -	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { -		fprintf (stderr, "%s: Can't add image timestamp\n", cmdname); -		unlink (tmpfile); -		exit (EXIT_FAILURE); -	} -	debug ("Added timestamp successfully\n"); - -	munmap ((void *)ptr, sbuf.st_size); -	close (tfd); - -	if (rename (tmpfile, imagefile) == -1) { -		fprintf (stderr, "%s: Can't rename %s to %s: %s\n", -				cmdname, tmpfile, imagefile, strerror (errno)); -		unlink (tmpfile); -		unlink (imagefile); -		exit (EXIT_FAILURE); -	} -} diff --git a/tools/mkimage.h b/tools/mkimage.h index c077dc955..120970fc6 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -19,6 +19,9 @@   * MA 02111-1307 USA   */ +#ifndef _MKIIMAGE_H_ +#define _MKIIMAGE_H_ +  #include "os_support.h"  #include <errno.h>  #include <fcntl.h> @@ -31,7 +34,7 @@  #include <sha1.h>  #include "fdt_host.h" -#define MKIMAGE_DEBUG +#undef MKIMAGE_DEBUG  #ifdef MKIMAGE_DEBUG  #define debug(fmt,args...)	printf (fmt ,##args) @@ -44,3 +47,99 @@  #define MKIMAGE_DEFAULT_DTC_OPTIONS	"-I dts -O dtb -p 500"  #define MKIMAGE_MAX_DTC_CMDLINE_LEN	512  #define MKIMAGE_DTC			"dtc"   /* assume dtc is in $PATH */ + +/* + * This structure defines all such variables those are initialized by + * mkimage main core and need to be referred by image type specific + * functions + */ +struct mkimage_params { +	int dflag; +	int eflag; +	int fflag; +	int lflag; +	int vflag; +	int xflag; +	int os; +	int arch; +	int type; +	int comp; +	char *dtc; +	unsigned int addr; +	unsigned int ep; +	char *imagename; +	char *datafile; +	char *imagefile; +	char *cmdname; +}; + +/* + * image type specific variables and callback functions + */ +struct image_type_params { +	/* name is an identification tag string for added support */ +	char *name; +	/* +	 * header size is local to the specific image type to be supported, +	 * mkimage core treats this as number of bytes +	 */ +	uint32_t header_size; +	/* Image type header pointer */ +	void *hdr; +	/* +	 * There are several arguments that are passed on the command line +	 * and are registered as flags in mkimage_params structure. +	 * This callback function can be used to check the passed arguments +	 * are in-lined with the image type to be supported +	 * +	 * Returns 1 if parameter check is successful +	 */ +	int (*check_params) (struct mkimage_params *); +	/* +	 * This function is used by list command (i.e. mkimage -l <filename>) +	 * image type verification code must be put here +	 * +	 * Returns 0 if image header verification is successful +	 * otherwise, returns respective negative error codes +	 */ +	int (*verify_header) (unsigned char *, int, struct mkimage_params *); +	/* Prints image information abstracting from image header */ +	void (*print_header) (void *); +	/* +	 * The header or image contents need to be set as per image type to +	 * be generated using this callback function. +	 * further output file post processing (for ex. checksum calculation, +	 * padding bytes etc..) can also be done in this callback function. +	 */ +	void (*set_header) (void *, struct stat *, int, +					struct mkimage_params *); +	/* +	 * Some image generation support for ex (default image type) supports +	 * more than one type_ids, this callback function is used to check +	 * whether input (-T <image_type>) is supported by registered image +	 * generation/list low level code +	 */ +	int (*check_image_type) (uint8_t); +	/* This callback function will be executed if fflag is defined */ +	int (*fflag_handle) (struct mkimage_params *); +	/* pointer to the next registered entry in linked list */ +	struct image_type_params *next; +}; + +/* + * Exported functions + */ +void mkimage_register (struct image_type_params *tparams); + +/* + * There is a c file associated with supported image type low level code + * for ex. default_image.c, fit_image.c + * init is the only function referred by mkimage core. + * to avoid a single lined header file, you can define them here + * + * Supported image types init functions + */ +void init_default_image_type (void); +void init_fit_image_type (void); + +#endif /* _MKIIMAGE_H_ */ |