diff options
Diffstat (limited to 'tools/mkimage.c')
| -rw-r--r-- | tools/mkimage.c | 257 | 
1 files changed, 205 insertions, 52 deletions
| diff --git a/tools/mkimage.c b/tools/mkimage.c index 5cb2bc74e..6e1ff2b1e 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -1,4 +1,6 @@  /* + * (C) Copyright 2008 Semihalf + *   * (C) Copyright 2000-2004   * DENX Software Engineering   * Wolfgang Denk, wd@denx.de @@ -32,6 +34,8 @@ extern int errno;  extern	unsigned long	crc32 (unsigned long crc, const char *buf, unsigned int len);  static	void		copy_file (int, const char *, int);  static	void		usage (void); +static	void		image_verify_header (char *, int); +static	void		fit_handle_file (void);  char	*datafile;  char	*imagefile; @@ -39,6 +43,7 @@ char	*cmdname;  int dflag    = 0;  int eflag    = 0; +int fflag    = 0;  int lflag    = 0;  int vflag    = 0;  int xflag    = 0; @@ -46,6 +51,7 @@ 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;  image_header_t header;  image_header_t *hdr = &header; @@ -53,7 +59,7 @@ image_header_t *hdr = &header;  int  main (int argc, char **argv)  { -	int ifd; +	int ifd = -1;  	uint32_t checksum;  	uint32_t addr;  	uint32_t ep; @@ -81,6 +87,12 @@ main (int argc, char **argv)  				    (opt_comp = genimg_get_comp_id (*++argv)) < 0)  					usage ();  				goto NXTARG; +			case 'D': +				if (--argc <= 0) +					usage (); +				opt_dtc = *++argv; +				goto NXTARG; +  			case 'O':  				if ((--argc <= 0) ||  				    (opt_os = genimg_get_os_id (*++argv)) < 0) @@ -121,6 +133,12 @@ main (int argc, char **argv)  				}  				eflag = 1;  				goto NXTARG; +			case 'f': +				if (--argc <= 0) +					usage (); +				datafile = *++argv; +				fflag = 1; +				goto NXTARG;  			case 'n':  				if (--argc <= 0)  					usage (); @@ -139,7 +157,10 @@ main (int argc, char **argv)  NXTARG:		;  	} -	if ((argc != 1) || ((lflag ^ dflag) == 0)) +	if ((argc != 1) || +		(dflag && (fflag || lflag)) || +		(fflag && (dflag || lflag)) || +		(lflag && (dflag || fflag)))  		usage();  	if (!eflag) { @@ -165,21 +186,22 @@ NXTARG:		;  	imagefile = *argv; -	if (lflag) { -		ifd = open(imagefile, O_RDONLY|O_BINARY); -	} else { -		ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); -	} +	if (!fflag){ +		if (lflag) { +			ifd = open (imagefile, O_RDONLY|O_BINARY); +		} else { +			ifd = open (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)); -		exit (EXIT_FAILURE); +		if (ifd < 0) { +			fprintf (stderr, "%s: Can't open %s: %s\n", +				cmdname, imagefile, strerror(errno)); +			exit (EXIT_FAILURE); +		}  	}  	if (lflag) { -		int len; -		char *data;  		/*  		 * list header information of existing image  		 */ @@ -204,44 +226,24 @@ NXTARG:		;  			exit (EXIT_FAILURE);  		} -		/* -		 * image_check_hcrc() creates 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. -		 */ -		hdr = (image_header_t *)ptr; - -		if (!image_check_magic (hdr)) { -			fprintf (stderr, -				"%s: Bad Magic Number: \"%s\" is no valid image\n", -				cmdname, imagefile); -			exit (EXIT_FAILURE); -		} - -		if (!image_check_hcrc (hdr)) { -			fprintf (stderr, -				"%s: ERROR: \"%s\" has bad header checksum!\n", -				cmdname, imagefile); -			exit (EXIT_FAILURE); +		if (fdt_check_header (ptr)) { +			/* old-style image */ +			image_verify_header ((char *)ptr, sbuf.st_size); +			image_print_contents_noindent ((image_header_t *)ptr); +		} else { +			/* FIT image */ +			fit_print_contents_noindent (ptr);  		} -		data = (char *)image_get_data (hdr); -		len  = sbuf.st_size - image_get_header_size (); - -		if (crc32(0, data, len) != image_get_dcrc (hdr)) { -			fprintf (stderr, -				"%s: ERROR: \"%s\" has corrupted data!\n", -				cmdname, imagefile); -			exit (EXIT_FAILURE); -		} - -		/* for multi-file images we need the data part, too */ -		image_print_contents_noindent ((image_header_t *)ptr); -  		(void) munmap((void *)ptr, sbuf.st_size);  		(void) close (ifd);  		exit (EXIT_SUCCESS); +	} else if (fflag) { +		/* Flattened Image Tree (FIT) format  handling */ +		debug ("FIT format handling\n"); +		fit_handle_file (); +		exit (EXIT_SUCCESS);  	}  	/* @@ -467,11 +469,11 @@ void  usage ()  {  	fprintf (stderr, "Usage: %s -l image\n" -			 "          -l ==> list image header information\n" -			 "       %s [-x] -A arch -O os -T type -C comp " -			 "-a addr -e ep -n name -d data_file[:data_file...] image\n", -		cmdname, cmdname); -	fprintf (stderr, "          -A ==> set architecture to 'arch'\n" +			 "          -l ==> list image header information\n", +		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"  			 "          -O ==> set operating system to 'os'\n"  			 "          -T ==> set image type to 'type'\n"  			 "          -C ==> set compression type 'comp'\n" @@ -479,7 +481,158 @@ usage ()  			 "          -e ==> set entry point to 'ep' (hex)\n"  			 "          -n ==> set image name to 'name'\n"  			 "          -d ==> use image data from 'datafile'\n" -			 "          -x ==> set XIP (execute in place)\n" -		); +			 "          -x ==> set XIP (execute in place)\n", +		cmdname); +	fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n", +		cmdname); +  	exit (EXIT_FAILURE);  } + +static void +image_verify_header (char *ptr, int image_size) +{ +	int len; +	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 (ntohl(hdr->ih_magic) != IH_MAGIC) { +		fprintf (stderr, +			"%s: Bad Magic Number: \"%s\" is no valid image\n", +			cmdname, imagefile); +		exit (EXIT_FAILURE); +	} + +	data = (char *)hdr; +	len  = sizeof(image_header_t); + +	checksum = ntohl(hdr->ih_hcrc); +	hdr->ih_hcrc = htonl(0);	/* clear for re-calculation */ + +	if (crc32 (0, data, len) != checksum) { +		fprintf (stderr, +			"%s: ERROR: \"%s\" has bad header checksum!\n", +			cmdname, imagefile); +		exit (EXIT_FAILURE); +	} + +	data = ptr + sizeof(image_header_t); +	len  = image_size - sizeof(image_header_t) ; + +	if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { +		fprintf (stderr, +			"%s: ERROR: \"%s\" has corrupted data!\n", +			cmdname, imagefile); +		exit (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 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 = (unsigned char *)mmap (0, sbuf.st_size, +			PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0); +	if ((caddr_t)ptr == (caddr_t)-1) { +		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); +	} +} |