xref: /openbmc/u-boot/tools/mkimage.c (revision 449609f5b11cce6beba7338bc4ce0f3345376a0b)
15b1d7137Swdenk /*
29d25438fSBartlomiej Sieka  * (C) Copyright 2008 Semihalf
39d25438fSBartlomiej Sieka  *
40c852a28Swdenk  * (C) Copyright 2000-2004
55b1d7137Swdenk  * DENX Software Engineering
65b1d7137Swdenk  * Wolfgang Denk, wd@denx.de
70c852a28Swdenk  *
80c852a28Swdenk  * This program is free software; you can redistribute it and/or
90c852a28Swdenk  * modify it under the terms of the GNU General Public License as
100c852a28Swdenk  * published by the Free Software Foundation; either version 2 of
110c852a28Swdenk  * the License, or (at your option) any later version.
120c852a28Swdenk  *
130c852a28Swdenk  * This program is distributed in the hope that it will be useful,
140c852a28Swdenk  * but WITHOUT ANY WARRANTY; without even the implied warranty of
150c852a28Swdenk  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
160c852a28Swdenk  * GNU General Public License for more details.
170c852a28Swdenk  *
180c852a28Swdenk  * You should have received a copy of the GNU General Public License
190c852a28Swdenk  * along with this program; if not, write to the Free Software
200c852a28Swdenk  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
210c852a28Swdenk  * MA 02111-1307 USA
225b1d7137Swdenk  */
235b1d7137Swdenk 
24b97a2a0aSMarian Balakowicz #include "mkimage.h"
255b1d7137Swdenk #include <image.h>
26*449609f5SPrafulla Wadaskar #include <u-boot/crc.h>
275b1d7137Swdenk 
285b1d7137Swdenk static	void		copy_file (int, const char *, int);
295b1d7137Swdenk static	void		usage (void);
30f7644c0bSPrafulla Wadaskar static	int		image_verify_header (char *, int);
319d25438fSBartlomiej Sieka static	void		fit_handle_file (void);
325b1d7137Swdenk 
335b1d7137Swdenk char	*datafile;
345b1d7137Swdenk char	*imagefile;
35570abb0aSMarian Balakowicz char	*cmdname;
365b1d7137Swdenk 
375b1d7137Swdenk int dflag    = 0;
385b1d7137Swdenk int eflag    = 0;
399d25438fSBartlomiej Sieka int fflag    = 0;
405b1d7137Swdenk int lflag    = 0;
415b1d7137Swdenk int vflag    = 0;
425b1d7137Swdenk int xflag    = 0;
435b1d7137Swdenk int opt_os   = IH_OS_LINUX;
44b97a2a0aSMarian Balakowicz int opt_arch = IH_ARCH_PPC;
455b1d7137Swdenk int opt_type = IH_TYPE_KERNEL;
465b1d7137Swdenk int opt_comp = IH_COMP_GZIP;
479d25438fSBartlomiej Sieka char *opt_dtc = MKIMAGE_DEFAULT_DTC_OPTIONS;
485b1d7137Swdenk 
495b1d7137Swdenk image_header_t header;
505b1d7137Swdenk image_header_t *hdr = &header;
515b1d7137Swdenk 
525b1d7137Swdenk int
535b1d7137Swdenk main (int argc, char **argv)
545b1d7137Swdenk {
559d25438fSBartlomiej Sieka 	int ifd = -1;
565b1d7137Swdenk 	uint32_t checksum;
575b1d7137Swdenk 	uint32_t addr;
585b1d7137Swdenk 	uint32_t ep;
595b1d7137Swdenk 	struct stat sbuf;
605b1d7137Swdenk 	unsigned char *ptr;
615b1d7137Swdenk 	char *name = "";
62*449609f5SPrafulla Wadaskar 	int retval = 0;
635b1d7137Swdenk 
645b1d7137Swdenk 	cmdname = *argv;
655b1d7137Swdenk 
665b1d7137Swdenk 	addr = ep = 0;
675b1d7137Swdenk 
685b1d7137Swdenk 	while (--argc > 0 && **++argv == '-') {
695b1d7137Swdenk 		while (*++*argv) {
705b1d7137Swdenk 			switch (**argv) {
715b1d7137Swdenk 			case 'l':
725b1d7137Swdenk 				lflag = 1;
735b1d7137Swdenk 				break;
745b1d7137Swdenk 			case 'A':
755b1d7137Swdenk 				if ((--argc <= 0) ||
76570abb0aSMarian Balakowicz 				    (opt_arch = genimg_get_arch_id (*++argv)) < 0)
775b1d7137Swdenk 					usage ();
785b1d7137Swdenk 				goto NXTARG;
795b1d7137Swdenk 			case 'C':
805b1d7137Swdenk 				if ((--argc <= 0) ||
81570abb0aSMarian Balakowicz 				    (opt_comp = genimg_get_comp_id (*++argv)) < 0)
825b1d7137Swdenk 					usage ();
835b1d7137Swdenk 				goto NXTARG;
849d25438fSBartlomiej Sieka 			case 'D':
859d25438fSBartlomiej Sieka 				if (--argc <= 0)
869d25438fSBartlomiej Sieka 					usage ();
879d25438fSBartlomiej Sieka 				opt_dtc = *++argv;
889d25438fSBartlomiej Sieka 				goto NXTARG;
899d25438fSBartlomiej Sieka 
905b1d7137Swdenk 			case 'O':
915b1d7137Swdenk 				if ((--argc <= 0) ||
92570abb0aSMarian Balakowicz 				    (opt_os = genimg_get_os_id (*++argv)) < 0)
935b1d7137Swdenk 					usage ();
945b1d7137Swdenk 				goto NXTARG;
955b1d7137Swdenk 			case 'T':
965b1d7137Swdenk 				if ((--argc <= 0) ||
97570abb0aSMarian Balakowicz 				    (opt_type = genimg_get_type_id (*++argv)) < 0)
985b1d7137Swdenk 					usage ();
995b1d7137Swdenk 				goto NXTARG;
1005b1d7137Swdenk 
1015b1d7137Swdenk 			case 'a':
1025b1d7137Swdenk 				if (--argc <= 0)
1035b1d7137Swdenk 					usage ();
1045b1d7137Swdenk 				addr = strtoul (*++argv, (char **)&ptr, 16);
1055b1d7137Swdenk 				if (*ptr) {
1065b1d7137Swdenk 					fprintf (stderr,
1075b1d7137Swdenk 						"%s: invalid load address %s\n",
1085b1d7137Swdenk 						cmdname, *argv);
1095b1d7137Swdenk 					exit (EXIT_FAILURE);
1105b1d7137Swdenk 				}
1115b1d7137Swdenk 				goto NXTARG;
1125b1d7137Swdenk 			case 'd':
1135b1d7137Swdenk 				if (--argc <= 0)
1145b1d7137Swdenk 					usage ();
1155b1d7137Swdenk 				datafile = *++argv;
1165b1d7137Swdenk 				dflag = 1;
1175b1d7137Swdenk 				goto NXTARG;
1185b1d7137Swdenk 			case 'e':
1195b1d7137Swdenk 				if (--argc <= 0)
1205b1d7137Swdenk 					usage ();
1215b1d7137Swdenk 				ep = strtoul (*++argv, (char **)&ptr, 16);
1225b1d7137Swdenk 				if (*ptr) {
1235b1d7137Swdenk 					fprintf (stderr,
1245b1d7137Swdenk 						"%s: invalid entry point %s\n",
1255b1d7137Swdenk 						cmdname, *argv);
1265b1d7137Swdenk 					exit (EXIT_FAILURE);
1275b1d7137Swdenk 				}
1285b1d7137Swdenk 				eflag = 1;
1295b1d7137Swdenk 				goto NXTARG;
1309d25438fSBartlomiej Sieka 			case 'f':
1319d25438fSBartlomiej Sieka 				if (--argc <= 0)
1329d25438fSBartlomiej Sieka 					usage ();
1339d25438fSBartlomiej Sieka 				datafile = *++argv;
1349d25438fSBartlomiej Sieka 				fflag = 1;
1359d25438fSBartlomiej Sieka 				goto NXTARG;
1365b1d7137Swdenk 			case 'n':
1375b1d7137Swdenk 				if (--argc <= 0)
1385b1d7137Swdenk 					usage ();
1395b1d7137Swdenk 				name = *++argv;
1405b1d7137Swdenk 				goto NXTARG;
1415b1d7137Swdenk 			case 'v':
1425b1d7137Swdenk 				vflag++;
1435b1d7137Swdenk 				break;
1445b1d7137Swdenk 			case 'x':
1455b1d7137Swdenk 				xflag++;
1465b1d7137Swdenk 				break;
1475b1d7137Swdenk 			default:
1485b1d7137Swdenk 				usage ();
1495b1d7137Swdenk 			}
1505b1d7137Swdenk 		}
1515b1d7137Swdenk NXTARG:		;
1525b1d7137Swdenk 	}
1535b1d7137Swdenk 
1549d25438fSBartlomiej Sieka 	if ((argc != 1) ||
1559d25438fSBartlomiej Sieka 		(dflag && (fflag || lflag)) ||
1569d25438fSBartlomiej Sieka 		(fflag && (dflag || lflag)) ||
1579d25438fSBartlomiej Sieka 		(lflag && (dflag || fflag)))
1585b1d7137Swdenk 		usage();
1595b1d7137Swdenk 
1605b1d7137Swdenk 	if (!eflag) {
1615b1d7137Swdenk 		ep = addr;
1625b1d7137Swdenk 		/* If XIP, entry point must be after the U-Boot header */
1635b1d7137Swdenk 		if (xflag)
164b97a2a0aSMarian Balakowicz 			ep += image_get_header_size ();
1655b1d7137Swdenk 	}
1665b1d7137Swdenk 
1675b1d7137Swdenk 	/*
1685b1d7137Swdenk 	 * If XIP, ensure the entry point is equal to the load address plus
1695b1d7137Swdenk 	 * the size of the U-Boot header.
1705b1d7137Swdenk 	 */
1715b1d7137Swdenk 	if (xflag) {
172b97a2a0aSMarian Balakowicz 		if (ep != addr + image_get_header_size ()) {
1733577d3a3SWolfgang Denk 			fprintf (stderr,
1743577d3a3SWolfgang Denk 				"%s: For XIP, the entry point must be the load addr + %lu\n",
175a6c7ad2fSwdenk 				cmdname,
176b97a2a0aSMarian Balakowicz 				(unsigned long)image_get_header_size ());
1775b1d7137Swdenk 			exit (EXIT_FAILURE);
1785b1d7137Swdenk 		}
1795b1d7137Swdenk 	}
1805b1d7137Swdenk 
1815b1d7137Swdenk 	imagefile = *argv;
1825b1d7137Swdenk 
1839d25438fSBartlomiej Sieka 	if (!fflag){
1845b1d7137Swdenk 		if (lflag) {
185ef1464ccSwdenk 			ifd = open (imagefile, O_RDONLY|O_BINARY);
1865b1d7137Swdenk 		} else {
1879d25438fSBartlomiej Sieka 			ifd = open (imagefile,
1889d25438fSBartlomiej Sieka 				O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
1895b1d7137Swdenk 		}
1905b1d7137Swdenk 
1915b1d7137Swdenk 		if (ifd < 0) {
1925b1d7137Swdenk 			fprintf (stderr, "%s: Can't open %s: %s\n",
1935b1d7137Swdenk 				cmdname, imagefile, strerror(errno));
1945b1d7137Swdenk 			exit (EXIT_FAILURE);
1955b1d7137Swdenk 		}
1969d25438fSBartlomiej Sieka 	}
1975b1d7137Swdenk 
1985b1d7137Swdenk 	if (lflag) {
1995b1d7137Swdenk 		/*
2005b1d7137Swdenk 		 * list header information of existing image
2015b1d7137Swdenk 		 */
2025b1d7137Swdenk 		if (fstat(ifd, &sbuf) < 0) {
2035b1d7137Swdenk 			fprintf (stderr, "%s: Can't stat %s: %s\n",
2045b1d7137Swdenk 				cmdname, imagefile, strerror(errno));
2055b1d7137Swdenk 			exit (EXIT_FAILURE);
2065b1d7137Swdenk 		}
2075b1d7137Swdenk 
208b97a2a0aSMarian Balakowicz 		if ((unsigned)sbuf.st_size < image_get_header_size ()) {
2095b1d7137Swdenk 			fprintf (stderr,
2105b1d7137Swdenk 				"%s: Bad size: \"%s\" is no valid image\n",
2115b1d7137Swdenk 				cmdname, imagefile);
2125b1d7137Swdenk 			exit (EXIT_FAILURE);
2135b1d7137Swdenk 		}
2145b1d7137Swdenk 
215fa956fdeSMike Frysinger 		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
216fa956fdeSMike Frysinger 		if (ptr == MAP_FAILED) {
2175b1d7137Swdenk 			fprintf (stderr, "%s: Can't read %s: %s\n",
2185b1d7137Swdenk 				cmdname, imagefile, strerror(errno));
2195b1d7137Swdenk 			exit (EXIT_FAILURE);
2205b1d7137Swdenk 		}
2215b1d7137Swdenk 
222f7644c0bSPrafulla Wadaskar 		if (!(retval = fdt_check_header (ptr))) {
2239d25438fSBartlomiej Sieka 			/* FIT image */
224edbed247SBartlomiej Sieka 			fit_print_contents (ptr);
225f7644c0bSPrafulla Wadaskar 		} else if (!(retval = image_verify_header ((char *)ptr,
226f7644c0bSPrafulla Wadaskar 							   sbuf.st_size))) {
227f7644c0bSPrafulla Wadaskar 			/* old-style image */
228f7644c0bSPrafulla Wadaskar 			image_print_contents ((image_header_t *)ptr);
2299d25438fSBartlomiej Sieka 		}
2305b1d7137Swdenk 
2315b1d7137Swdenk 		(void) munmap((void *)ptr, sbuf.st_size);
2325b1d7137Swdenk 		(void) close (ifd);
2335b1d7137Swdenk 
234f7644c0bSPrafulla Wadaskar 		exit (retval);
2359d25438fSBartlomiej Sieka 	} else if (fflag) {
2369d25438fSBartlomiej Sieka 		/* Flattened Image Tree (FIT) format  handling */
2379d25438fSBartlomiej Sieka 		debug ("FIT format handling\n");
2389d25438fSBartlomiej Sieka 		fit_handle_file ();
239f7644c0bSPrafulla Wadaskar 		exit (retval);
2405b1d7137Swdenk 	}
2415b1d7137Swdenk 
2425b1d7137Swdenk 	/*
2435b1d7137Swdenk 	 * Must be -w then:
2445b1d7137Swdenk 	 *
2455b1d7137Swdenk 	 * write dummy header, to be fixed later
2465b1d7137Swdenk 	 */
247b97a2a0aSMarian Balakowicz 	memset (hdr, 0, image_get_header_size ());
2485b1d7137Swdenk 
249b97a2a0aSMarian Balakowicz 	if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) {
2505b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
2515b1d7137Swdenk 			cmdname, imagefile, strerror(errno));
2525b1d7137Swdenk 		exit (EXIT_FAILURE);
2535b1d7137Swdenk 	}
2545b1d7137Swdenk 
2555b1d7137Swdenk 	if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) {
2565b1d7137Swdenk 		char *file = datafile;
2573bb66806SWolfgang Denk 		uint32_t size;
2585b1d7137Swdenk 
2595b1d7137Swdenk 		for (;;) {
2605b1d7137Swdenk 			char *sep = NULL;
2615b1d7137Swdenk 
2625b1d7137Swdenk 			if (file) {
2635b1d7137Swdenk 				if ((sep = strchr(file, ':')) != NULL) {
2645b1d7137Swdenk 					*sep = '\0';
2655b1d7137Swdenk 				}
2665b1d7137Swdenk 
2675b1d7137Swdenk 				if (stat (file, &sbuf) < 0) {
2685b1d7137Swdenk 					fprintf (stderr, "%s: Can't stat %s: %s\n",
2695b1d7137Swdenk 						cmdname, file, strerror(errno));
2705b1d7137Swdenk 					exit (EXIT_FAILURE);
2715b1d7137Swdenk 				}
2729a4daad0SMarian Balakowicz 				size = cpu_to_uimage (sbuf.st_size);
2735b1d7137Swdenk 			} else {
2745b1d7137Swdenk 				size = 0;
2755b1d7137Swdenk 			}
2765b1d7137Swdenk 
2775b1d7137Swdenk 			if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
2785b1d7137Swdenk 				fprintf (stderr, "%s: Write error on %s: %s\n",
2795b1d7137Swdenk 					cmdname, imagefile, strerror(errno));
2805b1d7137Swdenk 				exit (EXIT_FAILURE);
2815b1d7137Swdenk 			}
2825b1d7137Swdenk 
2835b1d7137Swdenk 			if (!file) {
2845b1d7137Swdenk 				break;
2855b1d7137Swdenk 			}
2865b1d7137Swdenk 
2875b1d7137Swdenk 			if (sep) {
2885b1d7137Swdenk 				*sep = ':';
2895b1d7137Swdenk 				file = sep + 1;
2905b1d7137Swdenk 			} else {
2915b1d7137Swdenk 				file = NULL;
2925b1d7137Swdenk 			}
2935b1d7137Swdenk 		}
2945b1d7137Swdenk 
2955b1d7137Swdenk 		file = datafile;
2965b1d7137Swdenk 
2975b1d7137Swdenk 		for (;;) {
2985b1d7137Swdenk 			char *sep = strchr(file, ':');
2995b1d7137Swdenk 			if (sep) {
3005b1d7137Swdenk 				*sep = '\0';
3015b1d7137Swdenk 				copy_file (ifd, file, 1);
3025b1d7137Swdenk 				*sep++ = ':';
3035b1d7137Swdenk 				file = sep;
3045b1d7137Swdenk 			} else {
3055b1d7137Swdenk 				copy_file (ifd, file, 0);
3065b1d7137Swdenk 				break;
3075b1d7137Swdenk 			}
3085b1d7137Swdenk 		}
3095b1d7137Swdenk 	} else {
3105b1d7137Swdenk 		copy_file (ifd, datafile, 0);
3115b1d7137Swdenk 	}
3125b1d7137Swdenk 
3135b1d7137Swdenk 	/* We're a bit of paranoid */
3145dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
3155b1d7137Swdenk 	(void) fdatasync (ifd);
3165b1d7137Swdenk #else
3175b1d7137Swdenk 	(void) fsync (ifd);
3185b1d7137Swdenk #endif
3195b1d7137Swdenk 
3205b1d7137Swdenk 	if (fstat(ifd, &sbuf) < 0) {
3215b1d7137Swdenk 		fprintf (stderr, "%s: Can't stat %s: %s\n",
3225b1d7137Swdenk 			cmdname, imagefile, strerror(errno));
3235b1d7137Swdenk 		exit (EXIT_FAILURE);
3245b1d7137Swdenk 	}
3255b1d7137Swdenk 
326fa956fdeSMike Frysinger 	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
327fa956fdeSMike Frysinger 	if (ptr == MAP_FAILED) {
3285b1d7137Swdenk 		fprintf (stderr, "%s: Can't map %s: %s\n",
3295b1d7137Swdenk 			cmdname, imagefile, strerror(errno));
3305b1d7137Swdenk 		exit (EXIT_FAILURE);
3315b1d7137Swdenk 	}
3325b1d7137Swdenk 
3335b1d7137Swdenk 	hdr = (image_header_t *)ptr;
3345b1d7137Swdenk 
3355b1d7137Swdenk 	checksum = crc32 (0,
336*449609f5SPrafulla Wadaskar 			  (const unsigned char *)(ptr +
337*449609f5SPrafulla Wadaskar 				image_get_header_size ()),
338b97a2a0aSMarian Balakowicz 			  sbuf.st_size - image_get_header_size ()
3395b1d7137Swdenk 			 );
3405b1d7137Swdenk 
3415b1d7137Swdenk 	/* Build new header */
342b97a2a0aSMarian Balakowicz 	image_set_magic (hdr, IH_MAGIC);
343b97a2a0aSMarian Balakowicz 	image_set_time (hdr, sbuf.st_mtime);
344b97a2a0aSMarian Balakowicz 	image_set_size (hdr, sbuf.st_size - image_get_header_size ());
345b97a2a0aSMarian Balakowicz 	image_set_load (hdr, addr);
346b97a2a0aSMarian Balakowicz 	image_set_ep (hdr, ep);
347b97a2a0aSMarian Balakowicz 	image_set_dcrc (hdr, checksum);
348b97a2a0aSMarian Balakowicz 	image_set_os (hdr, opt_os);
349b97a2a0aSMarian Balakowicz 	image_set_arch (hdr, opt_arch);
350b97a2a0aSMarian Balakowicz 	image_set_type (hdr, opt_type);
351b97a2a0aSMarian Balakowicz 	image_set_comp (hdr, opt_comp);
3525b1d7137Swdenk 
353b97a2a0aSMarian Balakowicz 	image_set_name (hdr, name);
3545b1d7137Swdenk 
355*449609f5SPrafulla Wadaskar 	checksum = crc32 (0, (const unsigned char *)hdr,
356*449609f5SPrafulla Wadaskar 					image_get_header_size ());
3575b1d7137Swdenk 
358b97a2a0aSMarian Balakowicz 	image_set_hcrc (hdr, checksum);
3595b1d7137Swdenk 
360edbed247SBartlomiej Sieka 	image_print_contents (hdr);
3615b1d7137Swdenk 
3625b1d7137Swdenk 	(void) munmap((void *)ptr, sbuf.st_size);
3635b1d7137Swdenk 
3645b1d7137Swdenk 	/* We're a bit of paranoid */
3655dfaa50eSAubrey.Li #if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__)
3665b1d7137Swdenk 	(void) fdatasync (ifd);
3675b1d7137Swdenk #else
3685b1d7137Swdenk 	(void) fsync (ifd);
3695b1d7137Swdenk #endif
3705b1d7137Swdenk 
3715b1d7137Swdenk 	if (close(ifd)) {
3725b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
3735b1d7137Swdenk 			cmdname, imagefile, strerror(errno));
3745b1d7137Swdenk 		exit (EXIT_FAILURE);
3755b1d7137Swdenk 	}
3765b1d7137Swdenk 
3775b1d7137Swdenk 	exit (EXIT_SUCCESS);
3785b1d7137Swdenk }
3795b1d7137Swdenk 
3805b1d7137Swdenk static void
3815b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad)
3825b1d7137Swdenk {
3835b1d7137Swdenk 	int dfd;
3845b1d7137Swdenk 	struct stat sbuf;
3855b1d7137Swdenk 	unsigned char *ptr;
3865b1d7137Swdenk 	int tail;
3875b1d7137Swdenk 	int zero = 0;
3885b1d7137Swdenk 	int offset = 0;
3895b1d7137Swdenk 	int size;
3905b1d7137Swdenk 
3915b1d7137Swdenk 	if (vflag) {
3925b1d7137Swdenk 		fprintf (stderr, "Adding Image %s\n", datafile);
3935b1d7137Swdenk 	}
3945b1d7137Swdenk 
395ef1464ccSwdenk 	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
3965b1d7137Swdenk 		fprintf (stderr, "%s: Can't open %s: %s\n",
3975b1d7137Swdenk 			cmdname, datafile, strerror(errno));
3985b1d7137Swdenk 		exit (EXIT_FAILURE);
3995b1d7137Swdenk 	}
4005b1d7137Swdenk 
4015b1d7137Swdenk 	if (fstat(dfd, &sbuf) < 0) {
4025b1d7137Swdenk 		fprintf (stderr, "%s: Can't stat %s: %s\n",
4035b1d7137Swdenk 			cmdname, datafile, strerror(errno));
4045b1d7137Swdenk 		exit (EXIT_FAILURE);
4055b1d7137Swdenk 	}
4065b1d7137Swdenk 
407fa956fdeSMike Frysinger 	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
408fa956fdeSMike Frysinger 	if (ptr == MAP_FAILED) {
4095b1d7137Swdenk 		fprintf (stderr, "%s: Can't read %s: %s\n",
4105b1d7137Swdenk 			cmdname, datafile, strerror(errno));
4115b1d7137Swdenk 		exit (EXIT_FAILURE);
4125b1d7137Swdenk 	}
4135b1d7137Swdenk 
4145b1d7137Swdenk 	if (xflag) {
4155b1d7137Swdenk 		unsigned char *p = NULL;
4165b1d7137Swdenk 		/*
4175b1d7137Swdenk 		 * XIP: do not append the image_header_t at the
4185b1d7137Swdenk 		 * beginning of the file, but consume the space
4195b1d7137Swdenk 		 * reserved for it.
4205b1d7137Swdenk 		 */
4215b1d7137Swdenk 
422b97a2a0aSMarian Balakowicz 		if ((unsigned)sbuf.st_size < image_get_header_size ()) {
4235b1d7137Swdenk 			fprintf (stderr,
4245b1d7137Swdenk 				"%s: Bad size: \"%s\" is too small for XIP\n",
4255b1d7137Swdenk 				cmdname, datafile);
4265b1d7137Swdenk 			exit (EXIT_FAILURE);
4275b1d7137Swdenk 		}
4285b1d7137Swdenk 
429b97a2a0aSMarian Balakowicz 		for (p = ptr; p < ptr + image_get_header_size (); p++) {
4305b1d7137Swdenk 			if ( *p != 0xff ) {
4315b1d7137Swdenk 				fprintf (stderr,
4325b1d7137Swdenk 					"%s: Bad file: \"%s\" has invalid buffer for XIP\n",
4335b1d7137Swdenk 					cmdname, datafile);
4345b1d7137Swdenk 				exit (EXIT_FAILURE);
4355b1d7137Swdenk 			}
4365b1d7137Swdenk 		}
4375b1d7137Swdenk 
438b97a2a0aSMarian Balakowicz 		offset = image_get_header_size ();
4395b1d7137Swdenk 	}
4405b1d7137Swdenk 
4415b1d7137Swdenk 	size = sbuf.st_size - offset;
4425b1d7137Swdenk 	if (write(ifd, ptr + offset, size) != size) {
4435b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
4445b1d7137Swdenk 			cmdname, imagefile, strerror(errno));
4455b1d7137Swdenk 		exit (EXIT_FAILURE);
4465b1d7137Swdenk 	}
4475b1d7137Swdenk 
4485b1d7137Swdenk 	if (pad && ((tail = size % 4) != 0)) {
4495b1d7137Swdenk 
4505b1d7137Swdenk 		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
4515b1d7137Swdenk 			fprintf (stderr, "%s: Write error on %s: %s\n",
4525b1d7137Swdenk 				cmdname, imagefile, strerror(errno));
4535b1d7137Swdenk 			exit (EXIT_FAILURE);
4545b1d7137Swdenk 		}
4555b1d7137Swdenk 	}
4565b1d7137Swdenk 
4575b1d7137Swdenk 	(void) munmap((void *)ptr, sbuf.st_size);
4585b1d7137Swdenk 	(void) close (dfd);
4595b1d7137Swdenk }
4605b1d7137Swdenk 
4615b1d7137Swdenk void
4625b1d7137Swdenk usage ()
4635b1d7137Swdenk {
4645b1d7137Swdenk 	fprintf (stderr, "Usage: %s -l image\n"
4659d25438fSBartlomiej Sieka 			 "          -l ==> list image header information\n",
4669d25438fSBartlomiej Sieka 		cmdname);
4679d25438fSBartlomiej Sieka 	fprintf (stderr, "       %s [-x] -A arch -O os -T type -C comp "
4689d25438fSBartlomiej Sieka 			 "-a addr -e ep -n name -d data_file[:data_file...] image\n"
4699d25438fSBartlomiej Sieka 			 "          -A ==> set architecture to 'arch'\n"
4705b1d7137Swdenk 			 "          -O ==> set operating system to 'os'\n"
4715b1d7137Swdenk 			 "          -T ==> set image type to 'type'\n"
4725b1d7137Swdenk 			 "          -C ==> set compression type 'comp'\n"
4735b1d7137Swdenk 			 "          -a ==> set load address to 'addr' (hex)\n"
4745b1d7137Swdenk 			 "          -e ==> set entry point to 'ep' (hex)\n"
4755b1d7137Swdenk 			 "          -n ==> set image name to 'name'\n"
4765b1d7137Swdenk 			 "          -d ==> use image data from 'datafile'\n"
4779d25438fSBartlomiej Sieka 			 "          -x ==> set XIP (execute in place)\n",
4789d25438fSBartlomiej Sieka 		cmdname);
4799d25438fSBartlomiej Sieka 	fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n",
4809d25438fSBartlomiej Sieka 		cmdname);
4819d25438fSBartlomiej Sieka 
4825b1d7137Swdenk 	exit (EXIT_FAILURE);
4835b1d7137Swdenk }
4849d25438fSBartlomiej Sieka 
485f7644c0bSPrafulla Wadaskar static int
4869d25438fSBartlomiej Sieka image_verify_header (char *ptr, int image_size)
4879d25438fSBartlomiej Sieka {
4889d25438fSBartlomiej Sieka 	int len;
489*449609f5SPrafulla Wadaskar 	const unsigned char *data;
4909d25438fSBartlomiej Sieka 	uint32_t checksum;
4919d25438fSBartlomiej Sieka 	image_header_t header;
4929d25438fSBartlomiej Sieka 	image_header_t *hdr = &header;
4939d25438fSBartlomiej Sieka 
4949d25438fSBartlomiej Sieka 	/*
4959d25438fSBartlomiej Sieka 	 * create copy of header so that we can blank out the
4969d25438fSBartlomiej Sieka 	 * checksum field for checking - this can't be done
4979d25438fSBartlomiej Sieka 	 * on the PROT_READ mapped data.
4989d25438fSBartlomiej Sieka 	 */
4999d25438fSBartlomiej Sieka 	memcpy (hdr, ptr, sizeof(image_header_t));
5009d25438fSBartlomiej Sieka 
50137566090SMike Frysinger 	if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) {
5029d25438fSBartlomiej Sieka 		fprintf (stderr,
5039d25438fSBartlomiej Sieka 			"%s: Bad Magic Number: \"%s\" is no valid image\n",
5049d25438fSBartlomiej Sieka 			cmdname, imagefile);
505f7644c0bSPrafulla Wadaskar 		return -FDT_ERR_BADMAGIC;
5069d25438fSBartlomiej Sieka 	}
5079d25438fSBartlomiej Sieka 
508*449609f5SPrafulla Wadaskar 	data = (const unsigned char *)hdr;
5099d25438fSBartlomiej Sieka 	len  = sizeof(image_header_t);
5109d25438fSBartlomiej Sieka 
51137566090SMike Frysinger 	checksum = be32_to_cpu(hdr->ih_hcrc);
51237566090SMike Frysinger 	hdr->ih_hcrc = cpu_to_be32(0);	/* clear for re-calculation */
5139d25438fSBartlomiej Sieka 
5149d25438fSBartlomiej Sieka 	if (crc32 (0, data, len) != checksum) {
5159d25438fSBartlomiej Sieka 		fprintf (stderr,
5169d25438fSBartlomiej Sieka 			"%s: ERROR: \"%s\" has bad header checksum!\n",
5179d25438fSBartlomiej Sieka 			cmdname, imagefile);
518f7644c0bSPrafulla Wadaskar 		return -FDT_ERR_BADSTATE;
5199d25438fSBartlomiej Sieka 	}
5209d25438fSBartlomiej Sieka 
521*449609f5SPrafulla Wadaskar 	data = (const unsigned char *)ptr + sizeof(image_header_t);
5229d25438fSBartlomiej Sieka 	len  = image_size - sizeof(image_header_t) ;
5239d25438fSBartlomiej Sieka 
52437566090SMike Frysinger 	if (crc32 (0, data, len) != be32_to_cpu(hdr->ih_dcrc)) {
5259d25438fSBartlomiej Sieka 		fprintf (stderr,
5269d25438fSBartlomiej Sieka 			"%s: ERROR: \"%s\" has corrupted data!\n",
5279d25438fSBartlomiej Sieka 			cmdname, imagefile);
528f7644c0bSPrafulla Wadaskar 		return -FDT_ERR_BADSTRUCTURE;
5299d25438fSBartlomiej Sieka 	}
530f7644c0bSPrafulla Wadaskar 	return 0;
5319d25438fSBartlomiej Sieka }
5329d25438fSBartlomiej Sieka 
5339d25438fSBartlomiej Sieka /**
5349d25438fSBartlomiej Sieka  * fit_handle_file - main FIT file processing function
5359d25438fSBartlomiej Sieka  *
5369d25438fSBartlomiej Sieka  * fit_handle_file() runs dtc to convert .its to .itb, includes
5379d25438fSBartlomiej Sieka  * binary data, updates timestamp property and calculates hashes.
5389d25438fSBartlomiej Sieka  *
5399d25438fSBartlomiej Sieka  * datafile  - .its file
5409d25438fSBartlomiej Sieka  * imagefile - .itb file
5419d25438fSBartlomiej Sieka  *
5429d25438fSBartlomiej Sieka  * returns:
5439d25438fSBartlomiej Sieka  *     only on success, otherwise calls exit (EXIT_FAILURE);
5449d25438fSBartlomiej Sieka  */
5459d25438fSBartlomiej Sieka static void fit_handle_file (void)
5469d25438fSBartlomiej Sieka {
5479d25438fSBartlomiej Sieka 	char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
5489d25438fSBartlomiej Sieka 	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
5499d25438fSBartlomiej Sieka 	int tfd;
5509d25438fSBartlomiej Sieka 	struct stat sbuf;
5519d25438fSBartlomiej Sieka 	unsigned char *ptr;
5529d25438fSBartlomiej Sieka 
5539d25438fSBartlomiej Sieka 	/* call dtc to include binary properties into the tmp file */
5549d25438fSBartlomiej Sieka 	if (strlen (imagefile) + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 >
5559d25438fSBartlomiej Sieka 		sizeof (tmpfile)) {
5569d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Image file name (%s) too long, "
5579d25438fSBartlomiej Sieka 				"can't create tmpfile",
5589d25438fSBartlomiej Sieka 				imagefile, cmdname);
5599d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
5609d25438fSBartlomiej Sieka 	}
5619d25438fSBartlomiej Sieka 	sprintf (tmpfile, "%s%s", imagefile, MKIMAGE_TMPFILE_SUFFIX);
5629d25438fSBartlomiej Sieka 
5639d25438fSBartlomiej Sieka 	/* dtc -I dts -O -p 200 datafile > tmpfile */
5649d25438fSBartlomiej Sieka 	sprintf (cmd, "%s %s %s > %s",
5659d25438fSBartlomiej Sieka 			MKIMAGE_DTC, opt_dtc, datafile, tmpfile);
5669d25438fSBartlomiej Sieka 	debug ("Trying to execute \"%s\"\n", cmd);
5679d25438fSBartlomiej Sieka 	if (system (cmd) == -1) {
5689d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: system(%s) failed: %s\n",
5699d25438fSBartlomiej Sieka 				cmdname, cmd, strerror(errno));
5709d25438fSBartlomiej Sieka 		unlink (tmpfile);
5719d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
5729d25438fSBartlomiej Sieka 	}
5739d25438fSBartlomiej Sieka 
5749d25438fSBartlomiej Sieka 	/* load FIT blob into memory */
5759d25438fSBartlomiej Sieka 	tfd = open (tmpfile, O_RDWR|O_BINARY);
5769d25438fSBartlomiej Sieka 
5779d25438fSBartlomiej Sieka 	if (tfd < 0) {
5789d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Can't open %s: %s\n",
5799d25438fSBartlomiej Sieka 				cmdname, tmpfile, strerror(errno));
5809d25438fSBartlomiej Sieka 		unlink (tmpfile);
5819d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
5829d25438fSBartlomiej Sieka 	}
5839d25438fSBartlomiej Sieka 
5849d25438fSBartlomiej Sieka 	if (fstat (tfd, &sbuf) < 0) {
5859d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Can't stat %s: %s\n",
5869d25438fSBartlomiej Sieka 				cmdname, tmpfile, strerror(errno));
5879d25438fSBartlomiej Sieka 		unlink (tmpfile);
5889d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
5899d25438fSBartlomiej Sieka 	}
5909d25438fSBartlomiej Sieka 
591fa956fdeSMike Frysinger 	ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, tfd, 0);
592fa956fdeSMike Frysinger 	if (ptr == MAP_FAILED) {
5939d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Can't read %s: %s\n",
5949d25438fSBartlomiej Sieka 				cmdname, tmpfile, strerror(errno));
5959d25438fSBartlomiej Sieka 		unlink (tmpfile);
5969d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
5979d25438fSBartlomiej Sieka 	}
5989d25438fSBartlomiej Sieka 
5999d25438fSBartlomiej Sieka 	/* check if ptr has a valid blob */
6009d25438fSBartlomiej Sieka 	if (fdt_check_header (ptr)) {
6019d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Invalid FIT blob\n", cmdname);
6029d25438fSBartlomiej Sieka 		unlink (tmpfile);
6039d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
6049d25438fSBartlomiej Sieka 	}
6059d25438fSBartlomiej Sieka 
6069d25438fSBartlomiej Sieka 	/* set hashes for images in the blob */
6079d25438fSBartlomiej Sieka 	if (fit_set_hashes (ptr)) {
6089d25438fSBartlomiej Sieka 		fprintf (stderr, "%s Can't add hashes to FIT blob", cmdname);
6099d25438fSBartlomiej Sieka 		unlink (tmpfile);
6109d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
6119d25438fSBartlomiej Sieka 	}
6129d25438fSBartlomiej Sieka 
6139d25438fSBartlomiej Sieka 	/* add a timestamp at offset 0 i.e., root  */
6149d25438fSBartlomiej Sieka 	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
6159d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Can't add image timestamp\n", cmdname);
6169d25438fSBartlomiej Sieka 		unlink (tmpfile);
6179d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
6189d25438fSBartlomiej Sieka 	}
6199d25438fSBartlomiej Sieka 	debug ("Added timestamp successfully\n");
6209d25438fSBartlomiej Sieka 
6219d25438fSBartlomiej Sieka 	munmap ((void *)ptr, sbuf.st_size);
6229d25438fSBartlomiej Sieka 	close (tfd);
6239d25438fSBartlomiej Sieka 
6249d25438fSBartlomiej Sieka 	if (rename (tmpfile, imagefile) == -1) {
6259d25438fSBartlomiej Sieka 		fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
6269d25438fSBartlomiej Sieka 				cmdname, tmpfile, imagefile, strerror (errno));
6279d25438fSBartlomiej Sieka 		unlink (tmpfile);
6289d25438fSBartlomiej Sieka 		unlink (imagefile);
6299d25438fSBartlomiej Sieka 		exit (EXIT_FAILURE);
6309d25438fSBartlomiej Sieka 	}
6319d25438fSBartlomiej Sieka }
632