xref: /openbmc/u-boot/tools/mkimage.c (revision a02221f29deb88145f6a1494450a8b9d20c9d596)
15b1d7137Swdenk /*
29d25438fSBartlomiej Sieka  * (C) Copyright 2008 Semihalf
39d25438fSBartlomiej Sieka  *
489a4d6b1SPrafulla Wadaskar  * (C) Copyright 2000-2009
55b1d7137Swdenk  * DENX Software Engineering
65b1d7137Swdenk  * Wolfgang Denk, wd@denx.de
70c852a28Swdenk  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
95b1d7137Swdenk  */
105b1d7137Swdenk 
11b97a2a0aSMarian Balakowicz #include "mkimage.h"
125b1d7137Swdenk #include <image.h>
13976b38c0SWolfgang Denk #include <version.h>
145b1d7137Swdenk 
155b1d7137Swdenk static void copy_file(int, const char *, int);
165b1d7137Swdenk static void usage(void);
175b1d7137Swdenk 
1889a4d6b1SPrafulla Wadaskar /* parameters initialized by core will be used by the image type code */
19f86ed6a8SGuilherme Maciel Ferreira struct image_tool_params params = {
2089a4d6b1SPrafulla Wadaskar 	.os = IH_OS_LINUX,
2189a4d6b1SPrafulla Wadaskar 	.arch = IH_ARCH_PPC,
2289a4d6b1SPrafulla Wadaskar 	.type = IH_TYPE_KERNEL,
2389a4d6b1SPrafulla Wadaskar 	.comp = IH_COMP_GZIP,
2489a4d6b1SPrafulla Wadaskar 	.dtc = MKIMAGE_DEFAULT_DTC_OPTIONS,
2504387d24SWolfgang Denk 	.imagename = "",
265d898a00SShaohui Xie 	.imagename2 = "",
2789a4d6b1SPrafulla Wadaskar };
285b1d7137Swdenk 
295b9d44dfSSimon Glass static int h_compare_image_name(const void *vtype1, const void *vtype2)
305b9d44dfSSimon Glass {
315b9d44dfSSimon Glass 	const int *type1 = vtype1;
325b9d44dfSSimon Glass 	const int *type2 = vtype2;
335b9d44dfSSimon Glass 	const char *name1 = genimg_get_type_short_name(*type1);
345b9d44dfSSimon Glass 	const char *name2 = genimg_get_type_short_name(*type2);
355b9d44dfSSimon Glass 
365b9d44dfSSimon Glass 	return strcmp(name1, name2);
375b9d44dfSSimon Glass }
385b9d44dfSSimon Glass 
395b9d44dfSSimon Glass /* Show all image types supported by mkimage */
405b9d44dfSSimon Glass static void show_image_types(void)
415b9d44dfSSimon Glass {
425b9d44dfSSimon Glass 	struct image_type_params *tparams;
435b9d44dfSSimon Glass 	int order[IH_TYPE_COUNT];
445b9d44dfSSimon Glass 	int count;
455b9d44dfSSimon Glass 	int type;
465b9d44dfSSimon Glass 	int i;
475b9d44dfSSimon Glass 
485b9d44dfSSimon Glass 	/* Sort the names in order of short name for easier reading */
495b9d44dfSSimon Glass 	memset(order, '\0', sizeof(order));
505b9d44dfSSimon Glass 	for (count = 0, type = 0; type < IH_TYPE_COUNT; type++) {
515b9d44dfSSimon Glass 		tparams = imagetool_get_type(type);
525b9d44dfSSimon Glass 		if (tparams)
535b9d44dfSSimon Glass 			order[count++] = type;
545b9d44dfSSimon Glass 	}
555b9d44dfSSimon Glass 	qsort(order, count, sizeof(int), h_compare_image_name);
565b9d44dfSSimon Glass 
575b9d44dfSSimon Glass 	fprintf(stderr, "\nInvalid image type. Supported image types:\n");
585b9d44dfSSimon Glass 	for (i = 0; i < count; i++) {
595b9d44dfSSimon Glass 		type = order[i];
605b9d44dfSSimon Glass 		tparams = imagetool_get_type(type);
615b9d44dfSSimon Glass 		if (tparams) {
625b9d44dfSSimon Glass 			fprintf(stderr, "\t%-15s  %s\n",
635b9d44dfSSimon Glass 				genimg_get_type_short_name(type),
645b9d44dfSSimon Glass 				genimg_get_type_name(type));
655b9d44dfSSimon Glass 		}
665b9d44dfSSimon Glass 	}
675b9d44dfSSimon Glass 	fprintf(stderr, "\n");
685b9d44dfSSimon Glass }
695b9d44dfSSimon Glass 
700b443deeSSimon Glass static void process_args(int argc, char **argv)
715b1d7137Swdenk {
72a2513e27SPeter Tyser 	char *ptr;
73*a02221f2SSimon Glass 	int opt;
745b1d7137Swdenk 
75*a02221f2SSimon Glass 	while ((opt = getopt(argc, argv,
76*a02221f2SSimon Glass 			     "a:A:cC:d:D:e:f:Fk:K:ln:O:rR:sT:vVx")) != -1) {
77*a02221f2SSimon Glass 		switch (opt) {
785b1d7137Swdenk 		case 'l':
7989a4d6b1SPrafulla Wadaskar 			params.lflag = 1;
805b1d7137Swdenk 			break;
815b1d7137Swdenk 		case 'A':
82*a02221f2SSimon Glass 			params.arch = genimg_get_arch_id(optarg);
83*a02221f2SSimon Glass 			if (params.arch < 0)
845b1d7137Swdenk 				usage();
85*a02221f2SSimon Glass 			break;
864f610427SSimon Glass 		case 'c':
87*a02221f2SSimon Glass 			params.comment = optarg;
88*a02221f2SSimon Glass 			break;
895b1d7137Swdenk 		case 'C':
90*a02221f2SSimon Glass 			params.comp = genimg_get_comp_id(optarg);
91*a02221f2SSimon Glass 			if (params.comp < 0)
925b1d7137Swdenk 				usage();
93*a02221f2SSimon Glass 			break;
949d25438fSBartlomiej Sieka 		case 'D':
95*a02221f2SSimon Glass 			params.dtc = optarg;
96*a02221f2SSimon Glass 			break;
975b1d7137Swdenk 		case 'O':
98*a02221f2SSimon Glass 			params.os = genimg_get_os_id(optarg);
99*a02221f2SSimon Glass 			if (params.os < 0)
1005b1d7137Swdenk 				usage();
101*a02221f2SSimon Glass 			break;
1025b1d7137Swdenk 		case 'T':
103*a02221f2SSimon Glass 			params.type = genimg_get_type_id(optarg);
1045b9d44dfSSimon Glass 			if (params.type < 0) {
1055b9d44dfSSimon Glass 				show_image_types();
1065b1d7137Swdenk 				usage();
1075b9d44dfSSimon Glass 			}
108*a02221f2SSimon Glass 			break;
1095b1d7137Swdenk 		case 'a':
110*a02221f2SSimon Glass 			params.addr = strtoull(optarg, &ptr, 16);
1115b1d7137Swdenk 			if (*ptr) {
112*a02221f2SSimon Glass 				fprintf(stderr, "%s: invalid load address %s\n",
113*a02221f2SSimon Glass 					params.cmdname, optarg);
1145b1d7137Swdenk 				exit(EXIT_FAILURE);
1155b1d7137Swdenk 			}
116*a02221f2SSimon Glass 			break;
1175b1d7137Swdenk 		case 'd':
118*a02221f2SSimon Glass 			params.datafile = optarg;
11989a4d6b1SPrafulla Wadaskar 			params.dflag = 1;
120*a02221f2SSimon Glass 			break;
1215b1d7137Swdenk 		case 'e':
122*a02221f2SSimon Glass 			params.ep = strtoull(optarg, &ptr, 16);
1235b1d7137Swdenk 			if (*ptr) {
124*a02221f2SSimon Glass 				fprintf(stderr, "%s: invalid entry point %s\n",
125*a02221f2SSimon Glass 					params.cmdname, optarg);
1265b1d7137Swdenk 				exit(EXIT_FAILURE);
1275b1d7137Swdenk 			}
12889a4d6b1SPrafulla Wadaskar 			params.eflag = 1;
129*a02221f2SSimon Glass 			break;
1309d25438fSBartlomiej Sieka 		case 'f':
131*a02221f2SSimon Glass 			params.datafile = optarg;
13295d77b44SSimon Glass 			/* no break */
13395d77b44SSimon Glass 		case 'F':
1341a99de2cSPeter Tyser 			/*
1351a99de2cSPeter Tyser 			 * The flattened image tree (FIT) format
1361a99de2cSPeter Tyser 			 * requires a flattened device tree image type
1371a99de2cSPeter Tyser 			 */
1381a99de2cSPeter Tyser 			params.type = IH_TYPE_FLATDT;
139fbc1c8f6SPeter Tyser 			params.fflag = 1;
140*a02221f2SSimon Glass 			break;
14180e4df8aSSimon Glass 		case 'k':
142*a02221f2SSimon Glass 			params.keydir = optarg;
143*a02221f2SSimon Glass 			break;
144e29495d3SSimon Glass 		case 'K':
145*a02221f2SSimon Glass 			params.keydest = optarg;
146*a02221f2SSimon Glass 			break;
1475b1d7137Swdenk 		case 'n':
148*a02221f2SSimon Glass 			params.imagename = optarg;
149*a02221f2SSimon Glass 			break;
150399c744bSSimon Glass 		case 'r':
151399c744bSSimon Glass 			params.require_keys = 1;
152399c744bSSimon Glass 			break;
1535d898a00SShaohui Xie 		case 'R':
1545d898a00SShaohui Xie 			/*
1555d898a00SShaohui Xie 			 * This entry is for the second configuration
1565d898a00SShaohui Xie 			 * file, if only one is not enough.
1575d898a00SShaohui Xie 			 */
158*a02221f2SSimon Glass 			params.imagename2 = optarg;
159*a02221f2SSimon Glass 			break;
160f0662105SStefano Babic 		case 's':
161f0662105SStefano Babic 			params.skipcpy = 1;
162f0662105SStefano Babic 			break;
1635b1d7137Swdenk 		case 'v':
16489a4d6b1SPrafulla Wadaskar 			params.vflag++;
1655b1d7137Swdenk 			break;
166976b38c0SWolfgang Denk 		case 'V':
167976b38c0SWolfgang Denk 			printf("mkimage version %s\n", PLAIN_VERSION);
168976b38c0SWolfgang Denk 			exit(EXIT_SUCCESS);
1695b1d7137Swdenk 		case 'x':
17089a4d6b1SPrafulla Wadaskar 			params.xflag++;
1715b1d7137Swdenk 			break;
1725b1d7137Swdenk 		default:
1735b1d7137Swdenk 			usage();
1745b1d7137Swdenk 		}
1755b1d7137Swdenk 	}
1765b1d7137Swdenk 
177*a02221f2SSimon Glass 	if (optind >= argc)
1785b1d7137Swdenk 		usage();
179*a02221f2SSimon Glass 	params.imagefile = argv[optind];
1800b443deeSSimon Glass }
1810b443deeSSimon Glass 
1820b443deeSSimon Glass 
1830b443deeSSimon Glass int main(int argc, char **argv)
1840b443deeSSimon Glass {
1850b443deeSSimon Glass 	int ifd = -1;
1860b443deeSSimon Glass 	struct stat sbuf;
1870b443deeSSimon Glass 	char *ptr;
1880b443deeSSimon Glass 	int retval = 0;
1890b443deeSSimon Glass 	struct image_type_params *tparams = NULL;
1900b443deeSSimon Glass 	int pad_len = 0;
1910b443deeSSimon Glass 	int dfd;
1920b443deeSSimon Glass 
1930b443deeSSimon Glass 	params.cmdname = *argv;
1940b443deeSSimon Glass 	params.addr = 0;
1950b443deeSSimon Glass 	params.ep = 0;
1960b443deeSSimon Glass 
1970b443deeSSimon Glass 	process_args(argc, argv);
1985b1d7137Swdenk 
19989a4d6b1SPrafulla Wadaskar 	/* set tparams as per input type_id */
200a93648d1SGuilherme Maciel Ferreira 	tparams = imagetool_get_type(params.type);
20189a4d6b1SPrafulla Wadaskar 	if (tparams == NULL) {
20289a4d6b1SPrafulla Wadaskar 		fprintf (stderr, "%s: unsupported type %s\n",
20389a4d6b1SPrafulla Wadaskar 			params.cmdname, genimg_get_type_name(params.type));
20489a4d6b1SPrafulla Wadaskar 		exit (EXIT_FAILURE);
20589a4d6b1SPrafulla Wadaskar 	}
20689a4d6b1SPrafulla Wadaskar 
20789a4d6b1SPrafulla Wadaskar 	/*
20889a4d6b1SPrafulla Wadaskar 	 * check the passed arguments parameters meets the requirements
20989a4d6b1SPrafulla Wadaskar 	 * as per image type to be generated/listed
21089a4d6b1SPrafulla Wadaskar 	 */
21189a4d6b1SPrafulla Wadaskar 	if (tparams->check_params)
21289a4d6b1SPrafulla Wadaskar 		if (tparams->check_params (&params))
21389a4d6b1SPrafulla Wadaskar 			usage();
21489a4d6b1SPrafulla Wadaskar 
21589a4d6b1SPrafulla Wadaskar 	if (!params.eflag) {
21689a4d6b1SPrafulla Wadaskar 		params.ep = params.addr;
2175b1d7137Swdenk 		/* If XIP, entry point must be after the U-Boot header */
21889a4d6b1SPrafulla Wadaskar 		if (params.xflag)
21989a4d6b1SPrafulla Wadaskar 			params.ep += tparams->header_size;
2205b1d7137Swdenk 	}
2215b1d7137Swdenk 
222c81296c1SPeter Tyser 	if (params.fflag){
223c81296c1SPeter Tyser 		if (tparams->fflag_handle)
224c81296c1SPeter Tyser 			/*
225c81296c1SPeter Tyser 			 * in some cases, some additional processing needs
226c81296c1SPeter Tyser 			 * to be done if fflag is defined
227c81296c1SPeter Tyser 			 *
228c81296c1SPeter Tyser 			 * For ex. fit_handle_file for Fit file support
229c81296c1SPeter Tyser 			 */
230c81296c1SPeter Tyser 			retval = tparams->fflag_handle(&params);
231c81296c1SPeter Tyser 
232c81296c1SPeter Tyser 		if (retval != EXIT_SUCCESS)
233c81296c1SPeter Tyser 			exit (retval);
234c81296c1SPeter Tyser 	}
235c81296c1SPeter Tyser 
236c81296c1SPeter Tyser 	if (params.lflag || params.fflag) {
23789a4d6b1SPrafulla Wadaskar 		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
2385b1d7137Swdenk 	} else {
23989a4d6b1SPrafulla Wadaskar 		ifd = open (params.imagefile,
2409d25438fSBartlomiej Sieka 			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
2415b1d7137Swdenk 	}
2425b1d7137Swdenk 
2435b1d7137Swdenk 	if (ifd < 0) {
2445b1d7137Swdenk 		fprintf (stderr, "%s: Can't open %s: %s\n",
24589a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile,
24689a4d6b1SPrafulla Wadaskar 			strerror(errno));
2475b1d7137Swdenk 		exit (EXIT_FAILURE);
2485b1d7137Swdenk 	}
2495b1d7137Swdenk 
250c81296c1SPeter Tyser 	if (params.lflag || params.fflag) {
2515b1d7137Swdenk 		/*
2525b1d7137Swdenk 		 * list header information of existing image
2535b1d7137Swdenk 		 */
2545b1d7137Swdenk 		if (fstat(ifd, &sbuf) < 0) {
2555b1d7137Swdenk 			fprintf (stderr, "%s: Can't stat %s: %s\n",
25689a4d6b1SPrafulla Wadaskar 				params.cmdname, params.imagefile,
25789a4d6b1SPrafulla Wadaskar 				strerror(errno));
2585b1d7137Swdenk 			exit (EXIT_FAILURE);
2595b1d7137Swdenk 		}
2605b1d7137Swdenk 
26189a4d6b1SPrafulla Wadaskar 		if ((unsigned)sbuf.st_size < tparams->header_size) {
2625b1d7137Swdenk 			fprintf (stderr,
26389a4d6b1SPrafulla Wadaskar 				"%s: Bad size: \"%s\" is not valid image\n",
26489a4d6b1SPrafulla Wadaskar 				params.cmdname, params.imagefile);
2655b1d7137Swdenk 			exit (EXIT_FAILURE);
2665b1d7137Swdenk 		}
2675b1d7137Swdenk 
268fa956fdeSMike Frysinger 		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
269fa956fdeSMike Frysinger 		if (ptr == MAP_FAILED) {
2705b1d7137Swdenk 			fprintf (stderr, "%s: Can't read %s: %s\n",
27189a4d6b1SPrafulla Wadaskar 				params.cmdname, params.imagefile,
27289a4d6b1SPrafulla Wadaskar 				strerror(errno));
2735b1d7137Swdenk 			exit (EXIT_FAILURE);
2745b1d7137Swdenk 		}
2755b1d7137Swdenk 
27689a4d6b1SPrafulla Wadaskar 		/*
27789a4d6b1SPrafulla Wadaskar 		 * scan through mkimage registry for all supported image types
27889a4d6b1SPrafulla Wadaskar 		 * and verify the input image file header for match
27989a4d6b1SPrafulla Wadaskar 		 * Print the image information for matched image type
28089a4d6b1SPrafulla Wadaskar 		 * Returns the error code if not matched
28189a4d6b1SPrafulla Wadaskar 		 */
2820ca6691cSGuilherme Maciel Ferreira 		retval = imagetool_verify_print_header(ptr, &sbuf,
2830ca6691cSGuilherme Maciel Ferreira 				tparams, &params);
2845b1d7137Swdenk 
2855b1d7137Swdenk 		(void) munmap((void *)ptr, sbuf.st_size);
2865b1d7137Swdenk 		(void) close (ifd);
2875b1d7137Swdenk 
288f7644c0bSPrafulla Wadaskar 		exit (retval);
2895b1d7137Swdenk 	}
2905b1d7137Swdenk 
29134633141SMarek Vasut 	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT)) {
29292a655c3SSimon Glass 		dfd = open(params.datafile, O_RDONLY | O_BINARY);
29392a655c3SSimon Glass 		if (dfd < 0) {
29492a655c3SSimon Glass 			fprintf(stderr, "%s: Can't open %s: %s\n",
2956ae6e160SPhilippe De Swert 				params.cmdname, params.datafile,
2966ae6e160SPhilippe De Swert 				strerror(errno));
29792a655c3SSimon Glass 			exit(EXIT_FAILURE);
29892a655c3SSimon Glass 		}
29992a655c3SSimon Glass 
30092a655c3SSimon Glass 		if (fstat(dfd, &sbuf) < 0) {
30192a655c3SSimon Glass 			fprintf(stderr, "%s: Can't stat %s: %s\n",
3026ae6e160SPhilippe De Swert 				params.cmdname, params.datafile,
3036ae6e160SPhilippe De Swert 				strerror(errno));
30492a655c3SSimon Glass 			exit(EXIT_FAILURE);
30592a655c3SSimon Glass 		}
30692a655c3SSimon Glass 
30792a655c3SSimon Glass 		params.file_size = sbuf.st_size + tparams->header_size;
30892a655c3SSimon Glass 		close(dfd);
3096ae6e160SPhilippe De Swert 	}
31092a655c3SSimon Glass 
3115b1d7137Swdenk 	/*
312f0662105SStefano Babic 	 * In case there an header with a variable
313f0662105SStefano Babic 	 * length will be added, the corresponding
314f0662105SStefano Babic 	 * function is called. This is responsible to
315f0662105SStefano Babic 	 * allocate memory for the header itself.
3165b1d7137Swdenk 	 */
317f0662105SStefano Babic 	if (tparams->vrec_header)
3189bac0bb3SStefano Babic 		pad_len = tparams->vrec_header(&params, tparams);
319f0662105SStefano Babic 	else
32089a4d6b1SPrafulla Wadaskar 		memset(tparams->hdr, 0, tparams->header_size);
3215b1d7137Swdenk 
32289a4d6b1SPrafulla Wadaskar 	if (write(ifd, tparams->hdr, tparams->header_size)
32389a4d6b1SPrafulla Wadaskar 					!= tparams->header_size) {
3245b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
32589a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile, strerror(errno));
3265b1d7137Swdenk 		exit (EXIT_FAILURE);
3275b1d7137Swdenk 	}
3285b1d7137Swdenk 
329d1be8f92SChristian Riesch 	if (!params.skipcpy) {
330d1be8f92SChristian Riesch 		if (params.type == IH_TYPE_MULTI ||
331d1be8f92SChristian Riesch 		    params.type == IH_TYPE_SCRIPT) {
33289a4d6b1SPrafulla Wadaskar 			char *file = params.datafile;
3333bb66806SWolfgang Denk 			uint32_t size;
3345b1d7137Swdenk 
3355b1d7137Swdenk 			for (;;) {
3365b1d7137Swdenk 				char *sep = NULL;
3375b1d7137Swdenk 
3385b1d7137Swdenk 				if (file) {
3395b1d7137Swdenk 					if ((sep = strchr(file, ':')) != NULL) {
3405b1d7137Swdenk 						*sep = '\0';
3415b1d7137Swdenk 					}
3425b1d7137Swdenk 
3435b1d7137Swdenk 					if (stat (file, &sbuf) < 0) {
3445b1d7137Swdenk 						fprintf (stderr, "%s: Can't stat %s: %s\n",
34589a4d6b1SPrafulla Wadaskar 							 params.cmdname, file, strerror(errno));
3465b1d7137Swdenk 						exit (EXIT_FAILURE);
3475b1d7137Swdenk 					}
3489a4daad0SMarian Balakowicz 					size = cpu_to_uimage (sbuf.st_size);
3495b1d7137Swdenk 				} else {
3505b1d7137Swdenk 					size = 0;
3515b1d7137Swdenk 				}
3525b1d7137Swdenk 
3535b1d7137Swdenk 				if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
3545b1d7137Swdenk 					fprintf (stderr, "%s: Write error on %s: %s\n",
35589a4d6b1SPrafulla Wadaskar 						 params.cmdname, params.imagefile,
35689a4d6b1SPrafulla Wadaskar 						 strerror(errno));
3575b1d7137Swdenk 					exit (EXIT_FAILURE);
3585b1d7137Swdenk 				}
3595b1d7137Swdenk 
3605b1d7137Swdenk 				if (!file) {
3615b1d7137Swdenk 					break;
3625b1d7137Swdenk 				}
3635b1d7137Swdenk 
3645b1d7137Swdenk 				if (sep) {
3655b1d7137Swdenk 					*sep = ':';
3665b1d7137Swdenk 					file = sep + 1;
3675b1d7137Swdenk 				} else {
3685b1d7137Swdenk 					file = NULL;
3695b1d7137Swdenk 				}
3705b1d7137Swdenk 			}
3715b1d7137Swdenk 
37289a4d6b1SPrafulla Wadaskar 			file = params.datafile;
3735b1d7137Swdenk 
3745b1d7137Swdenk 			for (;;) {
3755b1d7137Swdenk 				char *sep = strchr(file, ':');
3765b1d7137Swdenk 				if (sep) {
3775b1d7137Swdenk 					*sep = '\0';
3785b1d7137Swdenk 					copy_file (ifd, file, 1);
3795b1d7137Swdenk 					*sep++ = ':';
3805b1d7137Swdenk 					file = sep;
3815b1d7137Swdenk 				} else {
3825b1d7137Swdenk 					copy_file (ifd, file, 0);
3835b1d7137Swdenk 					break;
3845b1d7137Swdenk 				}
3855b1d7137Swdenk 			}
3865d898a00SShaohui Xie 		} else if (params.type == IH_TYPE_PBLIMAGE) {
3875d898a00SShaohui Xie 			/* PBL has special Image format, implements its' own */
3885d898a00SShaohui Xie 			pbl_load_uboot(ifd, &params);
3895b1d7137Swdenk 		} else {
3909bac0bb3SStefano Babic 			copy_file(ifd, params.datafile, pad_len);
3915b1d7137Swdenk 		}
392d1be8f92SChristian Riesch 	}
3935b1d7137Swdenk 
3945b1d7137Swdenk 	/* We're a bit of paranoid */
39589a4d6b1SPrafulla Wadaskar #if defined(_POSIX_SYNCHRONIZED_IO) && \
39689a4d6b1SPrafulla Wadaskar    !defined(__sun__) && \
39789a4d6b1SPrafulla Wadaskar    !defined(__FreeBSD__) && \
39831cbe80cSLuka Perkov    !defined(__OpenBSD__) && \
39989a4d6b1SPrafulla Wadaskar    !defined(__APPLE__)
4005b1d7137Swdenk 	(void) fdatasync (ifd);
4015b1d7137Swdenk #else
4025b1d7137Swdenk 	(void) fsync (ifd);
4035b1d7137Swdenk #endif
4045b1d7137Swdenk 
4055b1d7137Swdenk 	if (fstat(ifd, &sbuf) < 0) {
4065b1d7137Swdenk 		fprintf (stderr, "%s: Can't stat %s: %s\n",
40789a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile, strerror(errno));
4085b1d7137Swdenk 		exit (EXIT_FAILURE);
4095b1d7137Swdenk 	}
41092a655c3SSimon Glass 	params.file_size = sbuf.st_size;
4115b1d7137Swdenk 
412fa956fdeSMike Frysinger 	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
413fa956fdeSMike Frysinger 	if (ptr == MAP_FAILED) {
4145b1d7137Swdenk 		fprintf (stderr, "%s: Can't map %s: %s\n",
41589a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile, strerror(errno));
4165b1d7137Swdenk 		exit (EXIT_FAILURE);
4175b1d7137Swdenk 	}
4185b1d7137Swdenk 
41989a4d6b1SPrafulla Wadaskar 	/* Setup the image header as per input image type*/
42089a4d6b1SPrafulla Wadaskar 	if (tparams->set_header)
42189a4d6b1SPrafulla Wadaskar 		tparams->set_header (ptr, &sbuf, ifd, &params);
42289a4d6b1SPrafulla Wadaskar 	else {
42389a4d6b1SPrafulla Wadaskar 		fprintf (stderr, "%s: Can't set header for %s: %s\n",
42489a4d6b1SPrafulla Wadaskar 			params.cmdname, tparams->name, strerror(errno));
42589a4d6b1SPrafulla Wadaskar 		exit (EXIT_FAILURE);
42689a4d6b1SPrafulla Wadaskar 	}
4275b1d7137Swdenk 
42889a4d6b1SPrafulla Wadaskar 	/* Print the image information by processing image header */
42989a4d6b1SPrafulla Wadaskar 	if (tparams->print_header)
43089a4d6b1SPrafulla Wadaskar 		tparams->print_header (ptr);
43189a4d6b1SPrafulla Wadaskar 	else {
43289a4d6b1SPrafulla Wadaskar 		fprintf (stderr, "%s: Can't print header for %s: %s\n",
43389a4d6b1SPrafulla Wadaskar 			params.cmdname, tparams->name, strerror(errno));
43489a4d6b1SPrafulla Wadaskar 		exit (EXIT_FAILURE);
43589a4d6b1SPrafulla Wadaskar 	}
4365b1d7137Swdenk 
4375b1d7137Swdenk 	(void) munmap((void *)ptr, sbuf.st_size);
4385b1d7137Swdenk 
4395b1d7137Swdenk 	/* We're a bit of paranoid */
44089a4d6b1SPrafulla Wadaskar #if defined(_POSIX_SYNCHRONIZED_IO) && \
44189a4d6b1SPrafulla Wadaskar    !defined(__sun__) && \
44289a4d6b1SPrafulla Wadaskar    !defined(__FreeBSD__) && \
44331cbe80cSLuka Perkov    !defined(__OpenBSD__) && \
44489a4d6b1SPrafulla Wadaskar    !defined(__APPLE__)
4455b1d7137Swdenk 	(void) fdatasync (ifd);
4465b1d7137Swdenk #else
4475b1d7137Swdenk 	(void) fsync (ifd);
4485b1d7137Swdenk #endif
4495b1d7137Swdenk 
4505b1d7137Swdenk 	if (close(ifd)) {
4515b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
45289a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile, strerror(errno));
4535b1d7137Swdenk 		exit (EXIT_FAILURE);
4545b1d7137Swdenk 	}
4555b1d7137Swdenk 
4565b1d7137Swdenk 	exit (EXIT_SUCCESS);
4575b1d7137Swdenk }
4585b1d7137Swdenk 
4595b1d7137Swdenk static void
4605b1d7137Swdenk copy_file (int ifd, const char *datafile, int pad)
4615b1d7137Swdenk {
4625b1d7137Swdenk 	int dfd;
4635b1d7137Swdenk 	struct stat sbuf;
4645b1d7137Swdenk 	unsigned char *ptr;
4655b1d7137Swdenk 	int tail;
4665b1d7137Swdenk 	int zero = 0;
4679bac0bb3SStefano Babic 	uint8_t zeros[4096];
4685b1d7137Swdenk 	int offset = 0;
4695b1d7137Swdenk 	int size;
470a93648d1SGuilherme Maciel Ferreira 	struct image_type_params *tparams = imagetool_get_type(params.type);
4715b1d7137Swdenk 
4729bac0bb3SStefano Babic 	memset(zeros, 0, sizeof(zeros));
4739bac0bb3SStefano Babic 
47489a4d6b1SPrafulla Wadaskar 	if (params.vflag) {
4755b1d7137Swdenk 		fprintf (stderr, "Adding Image %s\n", datafile);
4765b1d7137Swdenk 	}
4775b1d7137Swdenk 
478ef1464ccSwdenk 	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
4795b1d7137Swdenk 		fprintf (stderr, "%s: Can't open %s: %s\n",
48089a4d6b1SPrafulla Wadaskar 			params.cmdname, datafile, strerror(errno));
4815b1d7137Swdenk 		exit (EXIT_FAILURE);
4825b1d7137Swdenk 	}
4835b1d7137Swdenk 
4845b1d7137Swdenk 	if (fstat(dfd, &sbuf) < 0) {
4855b1d7137Swdenk 		fprintf (stderr, "%s: Can't stat %s: %s\n",
48689a4d6b1SPrafulla Wadaskar 			params.cmdname, datafile, strerror(errno));
4875b1d7137Swdenk 		exit (EXIT_FAILURE);
4885b1d7137Swdenk 	}
4895b1d7137Swdenk 
490fa956fdeSMike Frysinger 	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
491fa956fdeSMike Frysinger 	if (ptr == MAP_FAILED) {
4925b1d7137Swdenk 		fprintf (stderr, "%s: Can't read %s: %s\n",
49389a4d6b1SPrafulla Wadaskar 			params.cmdname, datafile, strerror(errno));
4945b1d7137Swdenk 		exit (EXIT_FAILURE);
4955b1d7137Swdenk 	}
4965b1d7137Swdenk 
49789a4d6b1SPrafulla Wadaskar 	if (params.xflag) {
4985b1d7137Swdenk 		unsigned char *p = NULL;
4995b1d7137Swdenk 		/*
5005b1d7137Swdenk 		 * XIP: do not append the image_header_t at the
5015b1d7137Swdenk 		 * beginning of the file, but consume the space
5025b1d7137Swdenk 		 * reserved for it.
5035b1d7137Swdenk 		 */
5045b1d7137Swdenk 
50589a4d6b1SPrafulla Wadaskar 		if ((unsigned)sbuf.st_size < tparams->header_size) {
5065b1d7137Swdenk 			fprintf (stderr,
5075b1d7137Swdenk 				"%s: Bad size: \"%s\" is too small for XIP\n",
50889a4d6b1SPrafulla Wadaskar 				params.cmdname, datafile);
5095b1d7137Swdenk 			exit (EXIT_FAILURE);
5105b1d7137Swdenk 		}
5115b1d7137Swdenk 
51289a4d6b1SPrafulla Wadaskar 		for (p = ptr; p < ptr + tparams->header_size; p++) {
5135b1d7137Swdenk 			if ( *p != 0xff ) {
5145b1d7137Swdenk 				fprintf (stderr,
5155b1d7137Swdenk 					"%s: Bad file: \"%s\" has invalid buffer for XIP\n",
51689a4d6b1SPrafulla Wadaskar 					params.cmdname, datafile);
5175b1d7137Swdenk 				exit (EXIT_FAILURE);
5185b1d7137Swdenk 			}
5195b1d7137Swdenk 		}
5205b1d7137Swdenk 
52189a4d6b1SPrafulla Wadaskar 		offset = tparams->header_size;
5225b1d7137Swdenk 	}
5235b1d7137Swdenk 
5245b1d7137Swdenk 	size = sbuf.st_size - offset;
5255b1d7137Swdenk 	if (write(ifd, ptr + offset, size) != size) {
5265b1d7137Swdenk 		fprintf (stderr, "%s: Write error on %s: %s\n",
52789a4d6b1SPrafulla Wadaskar 			params.cmdname, params.imagefile, strerror(errno));
5285b1d7137Swdenk 		exit (EXIT_FAILURE);
5295b1d7137Swdenk 	}
5305b1d7137Swdenk 
5319bac0bb3SStefano Babic 	tail = size % 4;
5329bac0bb3SStefano Babic 	if ((pad == 1) && (tail != 0)) {
5335b1d7137Swdenk 
5345b1d7137Swdenk 		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
5355b1d7137Swdenk 			fprintf (stderr, "%s: Write error on %s: %s\n",
53689a4d6b1SPrafulla Wadaskar 				params.cmdname, params.imagefile,
53789a4d6b1SPrafulla Wadaskar 				strerror(errno));
5385b1d7137Swdenk 			exit (EXIT_FAILURE);
5395b1d7137Swdenk 		}
5409bac0bb3SStefano Babic 	} else if (pad > 1) {
541424b86aeSSimon Glass 		while (pad > 0) {
542424b86aeSSimon Glass 			int todo = sizeof(zeros);
543424b86aeSSimon Glass 
544424b86aeSSimon Glass 			if (todo > pad)
545424b86aeSSimon Glass 				todo = pad;
546424b86aeSSimon Glass 			if (write(ifd, (char *)&zeros, todo) != todo) {
5479bac0bb3SStefano Babic 				fprintf(stderr, "%s: Write error on %s: %s\n",
5489bac0bb3SStefano Babic 					params.cmdname, params.imagefile,
5499bac0bb3SStefano Babic 					strerror(errno));
5509bac0bb3SStefano Babic 				exit(EXIT_FAILURE);
5519bac0bb3SStefano Babic 			}
552424b86aeSSimon Glass 			pad -= todo;
553424b86aeSSimon Glass 		}
5545b1d7137Swdenk 	}
5555b1d7137Swdenk 
5565b1d7137Swdenk 	(void) munmap((void *)ptr, sbuf.st_size);
5575b1d7137Swdenk 	(void) close (dfd);
5585b1d7137Swdenk }
5595b1d7137Swdenk 
560f1cc458cSGuilherme Maciel Ferreira static void usage(void)
5615b1d7137Swdenk {
5625b1d7137Swdenk 	fprintf (stderr, "Usage: %s -l image\n"
5639d25438fSBartlomiej Sieka 			 "          -l ==> list image header information\n",
56489a4d6b1SPrafulla Wadaskar 		params.cmdname);
5659d25438fSBartlomiej Sieka 	fprintf (stderr, "       %s [-x] -A arch -O os -T type -C comp "
5669d25438fSBartlomiej Sieka 			 "-a addr -e ep -n name -d data_file[:data_file...] image\n"
5679d25438fSBartlomiej Sieka 			 "          -A ==> set architecture to 'arch'\n"
5685b1d7137Swdenk 			 "          -O ==> set operating system to 'os'\n"
5695b1d7137Swdenk 			 "          -T ==> set image type to 'type'\n"
5705b1d7137Swdenk 			 "          -C ==> set compression type 'comp'\n"
5715b1d7137Swdenk 			 "          -a ==> set load address to 'addr' (hex)\n"
5725b1d7137Swdenk 			 "          -e ==> set entry point to 'ep' (hex)\n"
5735b1d7137Swdenk 			 "          -n ==> set image name to 'name'\n"
5745b1d7137Swdenk 			 "          -d ==> use image data from 'datafile'\n"
5759d25438fSBartlomiej Sieka 			 "          -x ==> set XIP (execute in place)\n",
57689a4d6b1SPrafulla Wadaskar 		params.cmdname);
57795d77b44SSimon Glass 	fprintf(stderr, "       %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n",
57889a4d6b1SPrafulla Wadaskar 		params.cmdname);
57935497307STom Rini 	fprintf(stderr, "          -D => set all options for device tree compiler\n"
58080e4df8aSSimon Glass 			"          -f => input filename for FIT source\n");
58180e4df8aSSimon Glass #ifdef CONFIG_FIT_SIGNATURE
582399c744bSSimon Glass 	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n"
583e29495d3SSimon Glass 			"          -k => set directory containing private keys\n"
58495d77b44SSimon Glass 			"          -K => write public keys to this .dtb file\n"
5854f610427SSimon Glass 			"          -c => add comment in signature node\n"
586399c744bSSimon Glass 			"          -F => re-sign existing FIT image\n"
587399c744bSSimon Glass 			"          -r => mark keys used as 'required' in dtb\n");
58880e4df8aSSimon Glass #else
58980e4df8aSSimon Glass 	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
59080e4df8aSSimon Glass #endif
591976b38c0SWolfgang Denk 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
592976b38c0SWolfgang Denk 		params.cmdname);
5935b9d44dfSSimon Glass 	fprintf(stderr, "Use -T to see a list of available image types\n");
5949d25438fSBartlomiej Sieka 
5955b1d7137Swdenk 	exit (EXIT_FAILURE);
5965b1d7137Swdenk }
597