1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008 Semihalf
4  *
5  * (C) Copyright 2000-2009
6  * DENX Software Engineering
7  * Wolfgang Denk, wd@denx.de
8  */
9 
10 #include "imagetool.h"
11 #include "mkimage.h"
12 #include "imximage.h"
13 #include <fit_common.h>
14 #include <getopt.h>
15 #include <image.h>
16 #include <version.h>
17 #ifdef __linux__
18 #include <sys/ioctl.h>
19 #endif
20 
21 static void copy_file(int, const char *, int);
22 
23 /* parameters initialized by core will be used by the image type code */
24 static struct image_tool_params params = {
25 	.os = IH_OS_LINUX,
26 	.arch = IH_ARCH_PPC,
27 	.type = IH_TYPE_KERNEL,
28 	.comp = IH_COMP_GZIP,
29 	.dtc = MKIMAGE_DEFAULT_DTC_OPTIONS,
30 	.imagename = "",
31 	.imagename2 = "",
32 };
33 
34 static enum ih_category cur_category;
35 
h_compare_category_name(const void * vtype1,const void * vtype2)36 static int h_compare_category_name(const void *vtype1, const void *vtype2)
37 {
38 	const int *type1 = vtype1;
39 	const int *type2 = vtype2;
40 	const char *name1 = genimg_get_cat_short_name(cur_category, *type1);
41 	const char *name2 = genimg_get_cat_short_name(cur_category, *type2);
42 
43 	return strcmp(name1, name2);
44 }
45 
show_valid_options(enum ih_category category)46 static int show_valid_options(enum ih_category category)
47 {
48 	int *order;
49 	int count;
50 	int item;
51 	int i;
52 
53 	count = genimg_get_cat_count(category);
54 	order = calloc(count, sizeof(*order));
55 	if (!order)
56 		return -ENOMEM;
57 
58 	/* Sort the names in order of short name for easier reading */
59 	for (i = 0, item = 0; i < count; i++, item++) {
60 		while (!genimg_cat_has_id(category, item) && i < count) {
61 			item++;
62 			count--;
63 		}
64 		order[i] = item;
65 	}
66 	cur_category = category;
67 	qsort(order, count, sizeof(int), h_compare_category_name);
68 
69 	fprintf(stderr, "\nInvalid %s, supported are:\n",
70 		genimg_get_cat_desc(category));
71 	for (i = 0; i < count; i++) {
72 		item = order[i];
73 		fprintf(stderr, "\t%-15s  %s\n",
74 			genimg_get_cat_short_name(category, item),
75 			genimg_get_cat_name(category, item));
76 	}
77 	fprintf(stderr, "\n");
78 	free(order);
79 
80 	return 0;
81 }
82 
usage(const char * msg)83 static void usage(const char *msg)
84 {
85 	fprintf(stderr, "Error: %s\n", msg);
86 	fprintf(stderr, "Usage: %s [-T type] -l image\n"
87 			 "          -l ==> list image header information\n"
88 			 "          -T ==> parse image file as 'type'\n"
89 			 "          -q ==> quiet\n",
90 		params.cmdname);
91 	fprintf(stderr,
92 		"       %s [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image\n"
93 		"          -A ==> set architecture to 'arch'\n"
94 		"          -O ==> set operating system to 'os'\n"
95 		"          -T ==> set image type to 'type'\n"
96 		"          -C ==> set compression type 'comp'\n"
97 		"          -a ==> set load address to 'addr' (hex)\n"
98 		"          -e ==> set entry point to 'ep' (hex)\n"
99 		"          -n ==> set image name to 'name'\n"
100 		"          -R ==> set second image name to 'name'\n"
101 		"          -d ==> use image data from 'datafile'\n"
102 		"          -x ==> set XIP (execute in place)\n"
103 		"          -s ==> create an image with no data\n"
104 		"          -v ==> verbose\n",
105 		params.cmdname);
106 	fprintf(stderr,
107 		"       %s [-D dtc_options] [-f fit-image.its|-f auto|-f auto-conf|-F] [-b <dtb> [-b <dtb>]] [-E] [-B size] [-i <ramdisk.cpio.gz>] fit-image\n"
108 		"           <dtb> file is used with -f auto, it may occur multiple times.\n",
109 		params.cmdname);
110 	fprintf(stderr,
111 		"          -D => set all options for device tree compiler\n"
112 		"          -f => input filename for FIT source\n"
113 		"          -i => input filename for ramdisk file\n"
114 		"          -E => place data outside of the FIT structure\n"
115 		"          -B => align size in hex for FIT structure and header\n"
116 		"          -b => append the device tree binary to the FIT\n"
117 		"          -t => update the timestamp in the FIT\n");
118 #if CONFIG_IS_ENABLED(FIT_SIGNATURE)
119 	fprintf(stderr,
120 		"Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
121 		"          -k => set directory containing private keys\n"
122 		"          -K => write public keys to this .dtb file\n"
123 		"          -g => set key name hint\n"
124 		"          -G => use this signing key (in lieu of -k)\n"
125 		"          -c => add comment in signature node\n"
126 		"          -F => re-sign existing FIT image\n"
127 		"          -p => place external data at a static position\n"
128 		"          -r => mark keys used as 'required' in dtb\n"
129 		"          -N => openssl engine to use for signing\n"
130 		"          -o => algorithm to use for signing\n");
131 #else
132 	fprintf(stderr,
133 		"Signing / verified boot not supported (CONFIG_TOOLS_FIT_SIGNATURE undefined)\n");
134 #endif
135 
136 	fprintf(stderr, "       %s -V ==> print version information and exit\n",
137 		params.cmdname);
138 	fprintf(stderr, "Use '-T list' to see a list of available image types\n");
139 	fprintf(stderr, "Long options are available; read the man page for details\n");
140 
141 	exit(EXIT_FAILURE);
142 }
143 
add_content(int type,const char * fname)144 static int add_content(int type, const char *fname)
145 {
146 	struct content_info *cont;
147 
148 	cont = calloc(1, sizeof(*cont));
149 	if (!cont)
150 		return -1;
151 	cont->type = type;
152 	cont->fname = fname;
153 	if (params.content_tail)
154 		params.content_tail->next = cont;
155 	else
156 		params.content_head = cont;
157 	params.content_tail = cont;
158 
159 	return 0;
160 }
161 
162 static const char optstring[] =
163 	"a:A:b:B:c:C:d:D:e:Ef:Fg:G:i:k:K:ln:N:o:O:p:qrR:stT:vVx";
164 
165 static const struct option longopts[] = {
166 	{ "load-address", required_argument, NULL, 'a' },
167 	{ "architecture", required_argument, NULL, 'A' },
168 	{ "device-tree", required_argument, NULL, 'b' },
169 	{ "alignment", required_argument, NULL, 'B' },
170 	{ "comment", required_argument, NULL, 'c' },
171 	{ "compression", required_argument, NULL, 'C' },
172 	{ "image", required_argument, NULL, 'd' },
173 	{ "dtcopts", required_argument, NULL, 'D' },
174 	{ "entry-point", required_argument, NULL, 'e' },
175 	{ "external", no_argument, NULL, 'E' },
176 	{ "fit", required_argument, NULL, 'f' },
177 	{ "update", no_argument, NULL, 'F' },
178 	{ "key-name-hint", required_argument, NULL, 'g' },
179 	{ "key-file", required_argument, NULL, 'G' },
180 	{ "help", no_argument, NULL, 'h' },
181 	{ "initramfs", required_argument, NULL, 'i' },
182 	{ "key-dir", required_argument, NULL, 'k' },
183 	{ "key-dest", required_argument, NULL, 'K' },
184 	{ "list", no_argument, NULL, 'l' },
185 	{ "config", required_argument, NULL, 'n' },
186 	{ "engine", required_argument, NULL, 'N' },
187 	{ "algo", required_argument, NULL, 'o' },
188 	{ "os", required_argument, NULL, 'O' },
189 	{ "position", required_argument, NULL, 'p' },
190 	{ "quiet", no_argument, NULL, 'q' },
191 	{ "key-required", no_argument, NULL, 'r' },
192 	{ "secondary-config", required_argument, NULL, 'R' },
193 	{ "no-copy", no_argument, NULL, 's' },
194 	{ "touch", no_argument, NULL, 't' },
195 	{ "type", required_argument, NULL, 'T' },
196 	{ "verbose", no_argument, NULL, 'v' },
197 	{ "version", no_argument, NULL, 'V' },
198 	{ "xip", no_argument, NULL, 'x' },
199 	{ /* sentinel */ },
200 };
201 
process_args(int argc,char ** argv)202 static void process_args(int argc, char **argv)
203 {
204 	char *ptr;
205 	int type = IH_TYPE_INVALID;
206 	char *datafile = NULL;
207 	int opt;
208 
209 	while ((opt = getopt_long(argc, argv, optstring,
210 				  longopts, NULL)) != -1) {
211 		switch (opt) {
212 		case 'a':
213 			params.addr = strtoull(optarg, &ptr, 16);
214 			if (*ptr) {
215 				fprintf(stderr, "%s: invalid load address %s\n",
216 					params.cmdname, optarg);
217 				exit(EXIT_FAILURE);
218 			}
219 			break;
220 		case 'A':
221 			params.arch = genimg_get_arch_id(optarg);
222 			if (params.arch < 0) {
223 				show_valid_options(IH_ARCH);
224 				usage("Invalid architecture");
225 			}
226 			params.Aflag = 1;
227 			break;
228 		case 'b':
229 			if (add_content(IH_TYPE_FLATDT, optarg)) {
230 				fprintf(stderr,
231 					"%s: Out of memory adding content '%s'",
232 					params.cmdname, optarg);
233 				exit(EXIT_FAILURE);
234 			}
235 			break;
236 		case 'B':
237 			params.bl_len = strtoull(optarg, &ptr, 16);
238 			if (*ptr) {
239 				fprintf(stderr, "%s: invalid block length %s\n",
240 					params.cmdname, optarg);
241 				exit(EXIT_FAILURE);
242 			}
243 
244 			break;
245 		case 'c':
246 			params.comment = optarg;
247 			break;
248 		case 'C':
249 			params.comp = genimg_get_comp_id(optarg);
250 			if (params.comp < 0) {
251 				show_valid_options(IH_COMP);
252 				usage("Invalid compression type");
253 			}
254 			break;
255 		case 'd':
256 			params.datafile = optarg;
257 			params.dflag = 1;
258 			break;
259 		case 'D':
260 			params.dtc = optarg;
261 			break;
262 		case 'e':
263 			params.ep = strtoull(optarg, &ptr, 16);
264 			if (*ptr) {
265 				fprintf(stderr, "%s: invalid entry point %s\n",
266 					params.cmdname, optarg);
267 				exit(EXIT_FAILURE);
268 			}
269 			params.eflag = 1;
270 			break;
271 		case 'E':
272 			params.external_data = true;
273 			break;
274 		case 'f':
275 			datafile = optarg;
276 			if (!strcmp(datafile, "auto"))
277 				params.auto_fit = AF_HASHED_IMG;
278 			else if (!strcmp(datafile, "auto-conf"))
279 				params.auto_fit = AF_SIGNED_CONF;
280 			/* fallthrough */
281 		case 'F':
282 			/*
283 			 * The flattened image tree (FIT) format
284 			 * requires a flattened device tree image type
285 			 */
286 			params.type = IH_TYPE_FLATDT;
287 			params.fflag = 1;
288 			break;
289 		case 'g':
290 			params.keyname = optarg;
291 			break;
292 		case 'G':
293 			params.keyfile = optarg;
294 			break;
295 		case 'i':
296 			params.fit_ramdisk = optarg;
297 			break;
298 		case 'k':
299 			params.keydir = optarg;
300 			break;
301 		case 'K':
302 			params.keydest = optarg;
303 			break;
304 		case 'l':
305 			params.lflag = 1;
306 			break;
307 		case 'n':
308 			params.imagename = optarg;
309 			break;
310 		case 'N':
311 			params.engine_id = optarg;
312 			break;
313 		case 'o':
314 			params.algo_name = optarg;
315 			break;
316 		case 'O':
317 			params.os = genimg_get_os_id(optarg);
318 			if (params.os < 0) {
319 				show_valid_options(IH_OS);
320 				usage("Invalid operating system");
321 			}
322 			break;
323 		case 'p':
324 			params.external_offset = strtoull(optarg, &ptr, 16);
325 			if (*ptr) {
326 				fprintf(stderr, "%s: invalid offset size %s\n",
327 					params.cmdname, optarg);
328 				exit(EXIT_FAILURE);
329 			}
330 			break;
331 		case 'q':
332 			params.quiet = 1;
333 			break;
334 		case 'r':
335 			params.require_keys = 1;
336 			break;
337 		case 'R':
338 			/*
339 			 * This entry is for the second configuration
340 			 * file, if only one is not enough.
341 			 */
342 			params.imagename2 = optarg;
343 			break;
344 		case 's':
345 			params.skipcpy = 1;
346 			break;
347 		case 't':
348 			params.reset_timestamp = 1;
349 			break;
350 		case 'T':
351 			if (strcmp(optarg, "list") == 0) {
352 				show_valid_options(IH_TYPE);
353 				exit(EXIT_SUCCESS);
354 			}
355 			type = genimg_get_type_id(optarg);
356 			if (type < 0) {
357 				show_valid_options(IH_TYPE);
358 				usage("Invalid image type");
359 			}
360 			break;
361 		case 'v':
362 			params.vflag++;
363 			break;
364 		case 'V':
365 			printf("mkimage version %s\n", PLAIN_VERSION);
366 			exit(EXIT_SUCCESS);
367 		case 'x':
368 			params.xflag++;
369 			break;
370 		default:
371 			usage("Invalid option");
372 		}
373 	}
374 
375 	/* The last parameter is expected to be the imagefile */
376 	if (optind < argc)
377 		params.imagefile = argv[optind];
378 
379 	if (params.auto_fit == AF_SIGNED_CONF) {
380 		if (!params.keyname || !params.algo_name)
381 			usage("Missing key/algo for auto-FIT with signed configs (use -g -o)");
382 	} else if (params.auto_fit == AF_HASHED_IMG && params.keyname) {
383 		params.auto_fit = AF_SIGNED_IMG;
384 		if (!params.algo_name)
385 			usage("Missing algorithm for auto-FIT with signed images (use -g)");
386 	}
387 
388 	/*
389 	 * For auto-generated FIT images we need to know the image type to put
390 	 * in the FIT, which is separate from the file's image type (which
391 	 * will always be IH_TYPE_FLATDT in this case).
392 	 */
393 	if (params.type == IH_TYPE_FLATDT) {
394 		params.fit_image_type = type ? type : IH_TYPE_KERNEL;
395 		/* For auto-FIT, datafile has to be provided with -d */
396 		if (!params.auto_fit)
397 			params.datafile = datafile;
398 		else if (!params.datafile)
399 			usage("Missing data file for auto-FIT (use -d)");
400 	} else if (params.lflag || type != IH_TYPE_INVALID) {
401 		if (type == IH_TYPE_SCRIPT && !params.datafile)
402 			usage("Missing data file for script (use -d)");
403 		params.type = type;
404 	}
405 
406 	if (!params.imagefile)
407 		usage("Missing output filename");
408 }
409 
verify_image(const struct image_type_params * tparams)410 static void verify_image(const struct image_type_params *tparams)
411 {
412 	struct stat sbuf;
413 	void *ptr;
414 	int ifd;
415 
416 	ifd = open(params.imagefile, O_RDONLY | O_BINARY);
417 	if (ifd < 0) {
418 		fprintf(stderr, "%s: Can't open %s: %s\n",
419 			params.cmdname, params.imagefile,
420 			strerror(errno));
421 		exit(EXIT_FAILURE);
422 	}
423 
424 	if (fstat(ifd, &sbuf) < 0) {
425 		fprintf(stderr, "%s: Can't stat %s: %s\n",
426 			params.cmdname, params.imagefile, strerror(errno));
427 		exit(EXIT_FAILURE);
428 	}
429 	params.file_size = sbuf.st_size;
430 
431 	ptr = mmap(0, params.file_size, PROT_READ, MAP_SHARED, ifd, 0);
432 	if (ptr == MAP_FAILED) {
433 		fprintf(stderr, "%s: Can't map %s: %s\n",
434 			params.cmdname, params.imagefile, strerror(errno));
435 		exit(EXIT_FAILURE);
436 	}
437 
438 	if (tparams->verify_header((unsigned char *)ptr, params.file_size, &params) != 0) {
439 		fprintf(stderr, "%s: Failed to verify header of %s\n",
440 			params.cmdname, params.imagefile);
441 		exit(EXIT_FAILURE);
442 	}
443 
444 	(void)munmap(ptr, params.file_size);
445 	(void)close(ifd);
446 }
447 
copy_datafile(int ifd,char * file)448 void copy_datafile(int ifd, char *file)
449 {
450 	if (!file)
451 		return;
452 	for (;;) {
453 		char *sep = strchr(file, ':');
454 
455 		if (sep) {
456 			*sep = '\0';
457 			copy_file(ifd, file, 1);
458 			*sep++ = ':';
459 			file = sep;
460 		} else {
461 			copy_file(ifd, file, 0);
462 			break;
463 		}
464 	}
465 }
466 
main(int argc,char ** argv)467 int main(int argc, char **argv)
468 {
469 	int ifd = -1;
470 	struct stat sbuf;
471 	char *ptr;
472 	int retval = 0;
473 	struct image_type_params *tparams = NULL;
474 	int pad_len = 0;
475 	int dfd;
476 	size_t map_len;
477 
478 	params.cmdname = *argv;
479 	params.addr = 0;
480 	params.ep = 0;
481 
482 	process_args(argc, argv);
483 
484 	/* set tparams as per input type_id */
485 	tparams = imagetool_get_type(params.type);
486 	if (tparams == NULL && !params.lflag) {
487 		fprintf (stderr, "%s: unsupported type %s\n",
488 			params.cmdname, genimg_get_type_name(params.type));
489 		exit (EXIT_FAILURE);
490 	}
491 
492 	/*
493 	 * check the passed arguments parameters meets the requirements
494 	 * as per image type to be generated/listed
495 	 */
496 	if (tparams && tparams->check_params)
497 		if (tparams->check_params (&params))
498 			usage("Bad parameters for image type");
499 
500 	if (!params.eflag) {
501 		params.ep = params.addr;
502 		/* If XIP, entry point must be after the U-Boot header */
503 		if (params.xflag && tparams)
504 			params.ep += tparams->header_size;
505 	}
506 
507 	if (params.fflag){
508 		if (!tparams) {
509 			fprintf(stderr, "%s: Missing FIT support\n",
510 				params.cmdname);
511 			exit (EXIT_FAILURE);
512 		}
513 		if (tparams->fflag_handle)
514 			/*
515 			 * in some cases, some additional processing needs
516 			 * to be done if fflag is defined
517 			 *
518 			 * For ex. fit_handle_file for Fit file support
519 			 */
520 			retval = tparams->fflag_handle(&params);
521 
522 		if (retval != EXIT_SUCCESS) {
523 			if (retval == FDT_ERR_NOTFOUND) {
524 				// Already printed error, exit cleanly
525 				exit(EXIT_FAILURE);
526 			}
527 			usage("Bad parameters for FIT image type");
528 		}
529 	}
530 
531 	if (params.lflag || params.fflag) {
532 		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
533 	} else {
534 		ifd = open (params.imagefile,
535 			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
536 	}
537 
538 	if (ifd < 0) {
539 		fprintf (stderr, "%s: Can't open %s: %s\n",
540 			params.cmdname, params.imagefile,
541 			strerror(errno));
542 		exit (EXIT_FAILURE);
543 	}
544 
545 	if (params.lflag || params.fflag) {
546 		uint64_t size;
547 		/*
548 		 * list header information of existing image
549 		 */
550 		if (fstat(ifd, &sbuf) < 0) {
551 			fprintf (stderr, "%s: Can't stat %s: %s\n",
552 				params.cmdname, params.imagefile,
553 				strerror(errno));
554 			exit (EXIT_FAILURE);
555 		}
556 
557 		if ((sbuf.st_mode & S_IFMT) == S_IFBLK) {
558 #ifdef __linux__
559 #if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
560 #define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
561 #endif
562 			if (ioctl(ifd, BLKGETSIZE64, &size) < 0) {
563 				fprintf (stderr,
564 					"%s: failed to get size of block device \"%s\"\n",
565 					params.cmdname, params.imagefile);
566 				exit (EXIT_FAILURE);
567 			}
568 #else
569 			fprintf (stderr,
570 				"%s: \"%s\" is block device, don't know how to get its size\n",
571 				params.cmdname, params.imagefile);
572 			exit (EXIT_FAILURE);
573 #endif
574 		} else if (tparams && sbuf.st_size < (off_t)tparams->header_size) {
575 			fprintf (stderr,
576 				"%s: Bad size: \"%s\" is not valid image: size %llu < %u\n",
577 				params.cmdname, params.imagefile,
578 				(unsigned long long) sbuf.st_size,
579 				tparams->header_size);
580 			exit (EXIT_FAILURE);
581 		} else {
582 			size = sbuf.st_size;
583 		}
584 
585 		ptr = mmap(0, size, PROT_READ, MAP_SHARED, ifd, 0);
586 		if (ptr == MAP_FAILED) {
587 			fprintf (stderr, "%s: Can't read %s: %s\n",
588 				params.cmdname, params.imagefile,
589 				strerror(errno));
590 			exit (EXIT_FAILURE);
591 		}
592 
593 		/*
594 		 * Verifies the header format based on the expected header for image
595 		 * type in tparams. If tparams is NULL simply check all image types
596 		 * to find one that matches our header.
597 		 */
598 		retval = imagetool_verify_print_header(ptr, &sbuf, tparams, &params);
599 
600 		(void) munmap((void *)ptr, sbuf.st_size);
601 		(void) close (ifd);
602 		if (!retval)
603 			summary_show(&params.summary, params.imagefile,
604 				     params.keydest);
605 
606 		exit (retval);
607 	}
608 
609 	if (!params.skipcpy && params.type != IH_TYPE_MULTI && params.type != IH_TYPE_SCRIPT) {
610 		if (!params.datafile) {
611 			fprintf(stderr, "%s: Option -d with image data file was not specified\n",
612 				params.cmdname);
613 			exit(EXIT_FAILURE);
614 		}
615 		dfd = open(params.datafile, O_RDONLY | O_BINARY);
616 		if (dfd < 0) {
617 			fprintf(stderr, "%s: Can't open %s: %s\n",
618 				params.cmdname, params.datafile,
619 				strerror(errno));
620 			exit(EXIT_FAILURE);
621 		}
622 
623 		if (fstat(dfd, &sbuf) < 0) {
624 			fprintf(stderr, "%s: Can't stat %s: %s\n",
625 				params.cmdname, params.datafile,
626 				strerror(errno));
627 			exit(EXIT_FAILURE);
628 		}
629 
630 		params.file_size = sbuf.st_size + tparams->header_size;
631 		close(dfd);
632 	}
633 
634 	/*
635 	 * In case there an header with a variable
636 	 * length will be added, the corresponding
637 	 * function is called. This is responsible to
638 	 * allocate memory for the header itself.
639 	 */
640 	if (tparams->vrec_header)
641 		pad_len = tparams->vrec_header(&params, tparams);
642 	else
643 		memset(tparams->hdr, 0, tparams->header_size);
644 
645 	if (write(ifd, tparams->hdr, tparams->header_size)
646 					!= tparams->header_size) {
647 		fprintf (stderr, "%s: Write error on %s: %s\n",
648 			params.cmdname, params.imagefile, strerror(errno));
649 		exit (EXIT_FAILURE);
650 	}
651 
652 	if (!params.skipcpy) {
653 		if (params.type == IH_TYPE_MULTI ||
654 		    params.type == IH_TYPE_SCRIPT) {
655 			char *file = params.datafile;
656 			uint32_t size;
657 
658 			for (;;) {
659 				char *sep = NULL;
660 
661 				if (file) {
662 					if ((sep = strchr(file, ':')) != NULL) {
663 						*sep = '\0';
664 					}
665 
666 					if (stat (file, &sbuf) < 0) {
667 						fprintf (stderr, "%s: Can't stat %s: %s\n",
668 							 params.cmdname, file, strerror(errno));
669 						exit (EXIT_FAILURE);
670 					}
671 					size = cpu_to_uimage (sbuf.st_size);
672 				} else {
673 					size = 0;
674 				}
675 
676 				if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
677 					fprintf (stderr, "%s: Write error on %s: %s\n",
678 						 params.cmdname, params.imagefile,
679 						 strerror(errno));
680 					exit (EXIT_FAILURE);
681 				}
682 
683 				if (!file) {
684 					break;
685 				}
686 
687 				if (sep) {
688 					*sep = ':';
689 					file = sep + 1;
690 				} else {
691 					file = NULL;
692 				}
693 			}
694 			copy_datafile(ifd, params.datafile);
695 		} else if (params.type == IH_TYPE_PBLIMAGE) {
696 			/* PBL has special Image format, implements its' own */
697 			pbl_load_uboot(ifd, &params);
698 		} else if (params.type == IH_TYPE_ZYNQMPBIF) {
699 			/* Image file is meta, walk through actual targets */
700 			int ret;
701 
702 			ret = zynqmpbif_copy_image(ifd, &params);
703 			if (ret)
704 				return ret;
705 		} else if (params.type == IH_TYPE_IMX8IMAGE) {
706 			/* i.MX8/8X has special Image format */
707 			int ret;
708 
709 			ret = imx8image_copy_image(ifd, &params);
710 			if (ret)
711 				return ret;
712 		} else if (params.type == IH_TYPE_IMX8MIMAGE) {
713 			/* i.MX8M has special Image format */
714 			int ret;
715 
716 			ret = imx8mimage_copy_image(ifd, &params);
717 			if (ret)
718 				return ret;
719 		} else if ((params.type == IH_TYPE_RKSD) ||
720 				(params.type == IH_TYPE_RKSPI)) {
721 			/* Rockchip has special Image format */
722 			int ret;
723 
724 			ret = rockchip_copy_image(ifd, &params);
725 			if (ret)
726 				return ret;
727 		} else {
728 			copy_file(ifd, params.datafile, pad_len);
729 		}
730 		if (params.type == IH_TYPE_FIRMWARE_IVT) {
731 			/* Add alignment and IVT */
732 			uint32_t aligned_filesize = ALIGN(params.file_size,
733 							  0x1000);
734 			flash_header_v2_t ivt_header = { { 0xd1, 0x2000, 0x40 },
735 					params.addr, 0, 0, 0, params.addr
736 							+ aligned_filesize
737 							- tparams->header_size,
738 					params.addr + aligned_filesize
739 							- tparams->header_size
740 							+ 0x20, 0 };
741 			int i = params.file_size;
742 			for (; i < aligned_filesize; i++) {
743 				if (write(ifd, (char *) &i, 1) != 1) {
744 					fprintf(stderr,
745 							"%s: Write error on %s: %s\n",
746 							params.cmdname,
747 							params.imagefile,
748 							strerror(errno));
749 					exit(EXIT_FAILURE);
750 				}
751 			}
752 			if (write(ifd, &ivt_header, sizeof(flash_header_v2_t))
753 					!= sizeof(flash_header_v2_t)) {
754 				fprintf(stderr, "%s: Write error on %s: %s\n",
755 						params.cmdname,
756 						params.imagefile,
757 						strerror(errno));
758 				exit(EXIT_FAILURE);
759 			}
760 		}
761 	}
762 
763 	/* We're a bit of paranoid */
764 #if defined(_POSIX_SYNCHRONIZED_IO) && \
765    !defined(__sun__) && \
766    !defined(__FreeBSD__) && \
767    !defined(__OpenBSD__) && \
768    !defined(__APPLE__)
769 	(void) fdatasync (ifd);
770 #else
771 	(void) fsync (ifd);
772 #endif
773 
774 	if (fstat(ifd, &sbuf) < 0) {
775 		fprintf (stderr, "%s: Can't stat %s: %s\n",
776 			params.cmdname, params.imagefile, strerror(errno));
777 		exit (EXIT_FAILURE);
778 	}
779 	params.file_size = sbuf.st_size;
780 
781 	map_len = sbuf.st_size;
782 	ptr = mmap(0, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, ifd, 0);
783 	if (ptr == MAP_FAILED) {
784 		fprintf (stderr, "%s: Can't map %s: %s\n",
785 			params.cmdname, params.imagefile, strerror(errno));
786 		exit (EXIT_FAILURE);
787 	}
788 
789 	/* Setup the image header as per input image type*/
790 	if (tparams->set_header)
791 		tparams->set_header (ptr, &sbuf, ifd, &params);
792 	else {
793 		fprintf (stderr, "%s: Can't set header for %s\n",
794 			params.cmdname, tparams->name);
795 		exit (EXIT_FAILURE);
796 	}
797 
798 	/* Print the image information by processing image header */
799 	if (tparams->print_header)
800 		tparams->print_header (ptr, &params);
801 	else {
802 		fprintf (stderr, "%s: Can't print header for %s\n",
803 			params.cmdname, tparams->name);
804 	}
805 
806 	(void)munmap((void *)ptr, map_len);
807 
808 	/* We're a bit of paranoid */
809 #if defined(_POSIX_SYNCHRONIZED_IO) && \
810    !defined(__sun__) && \
811    !defined(__FreeBSD__) && \
812    !defined(__OpenBSD__) && \
813    !defined(__APPLE__)
814 	(void) fdatasync (ifd);
815 #else
816 	(void) fsync (ifd);
817 #endif
818 
819 	if (close(ifd)) {
820 		fprintf (stderr, "%s: Write error on %s: %s\n",
821 			params.cmdname, params.imagefile, strerror(errno));
822 		exit (EXIT_FAILURE);
823 	}
824 
825 	if (tparams->verify_header)
826 		verify_image(tparams);
827 
828 	exit (EXIT_SUCCESS);
829 }
830 
831 static void
copy_file(int ifd,const char * datafile,int pad)832 copy_file (int ifd, const char *datafile, int pad)
833 {
834 	int dfd;
835 	struct stat sbuf;
836 	unsigned char *ptr;
837 	int tail;
838 	int zero = 0;
839 	uint8_t zeros[4096];
840 	int offset = 0;
841 	int size, ret;
842 	struct image_type_params *tparams = imagetool_get_type(params.type);
843 
844 	memset(zeros, 0, sizeof(zeros));
845 
846 	if (params.vflag) {
847 		fprintf (stderr, "Adding Image %s\n", datafile);
848 	}
849 
850 	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
851 		fprintf (stderr, "%s: Can't open %s: %s\n",
852 			params.cmdname, datafile, strerror(errno));
853 		exit (EXIT_FAILURE);
854 	}
855 
856 	if (fstat(dfd, &sbuf) < 0) {
857 		fprintf (stderr, "%s: Can't stat %s: %s\n",
858 			params.cmdname, datafile, strerror(errno));
859 		exit (EXIT_FAILURE);
860 	}
861 
862 	if (sbuf.st_size == 0) {
863 		fprintf (stderr, "%s: Input file %s is empty, bailing out\n",
864 			params.cmdname, datafile);
865 		exit (EXIT_FAILURE);
866 	}
867 
868 	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
869 	if (ptr == MAP_FAILED) {
870 		fprintf (stderr, "%s: Can't read %s: %s\n",
871 			params.cmdname, datafile, strerror(errno));
872 		exit (EXIT_FAILURE);
873 	}
874 
875 	if (params.xflag &&
876 	    (((params.type > IH_TYPE_INVALID) && (params.type < IH_TYPE_FLATDT)) ||
877 	     (params.type == IH_TYPE_KERNEL_NOLOAD) || (params.type == IH_TYPE_FIRMWARE_IVT))) {
878 		unsigned char *p = NULL;
879 		/*
880 		 * XIP: do not append the struct legacy_img_hdr at the
881 		 * beginning of the file, but consume the space
882 		 * reserved for it.
883 		 */
884 
885 		if ((unsigned)sbuf.st_size < tparams->header_size) {
886 			fprintf (stderr,
887 				"%s: Bad size: \"%s\" is too small for XIP\n",
888 				params.cmdname, datafile);
889 			exit (EXIT_FAILURE);
890 		}
891 
892 		for (p = ptr; p < ptr + tparams->header_size; p++) {
893 			if ( *p != 0xff ) {
894 				fprintf (stderr,
895 					"%s: Bad file: \"%s\" has invalid buffer for XIP\n",
896 					params.cmdname, datafile);
897 				exit (EXIT_FAILURE);
898 			}
899 		}
900 
901 		offset = tparams->header_size;
902 	}
903 
904 	size = sbuf.st_size - offset;
905 
906 	ret = write(ifd, ptr + offset, size);
907 	if (ret != size) {
908 		if (ret < 0)
909 			fprintf (stderr, "%s: Write error on %s: %s\n",
910 				 params.cmdname, params.imagefile, strerror(errno));
911 		else if (ret < size)
912 			fprintf (stderr, "%s: Write only %d/%d bytes, "\
913 				 "probably no space left on the device\n",
914 				 params.cmdname, ret, size);
915 		exit (EXIT_FAILURE);
916 	}
917 
918 	tail = size % 4;
919 	if ((pad == 1) && (tail != 0)) {
920 
921 		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
922 			fprintf (stderr, "%s: Write error on %s: %s\n",
923 				params.cmdname, params.imagefile,
924 				strerror(errno));
925 			exit (EXIT_FAILURE);
926 		}
927 	} else if (pad > 1) {
928 		while (pad > 0) {
929 			int todo = sizeof(zeros);
930 
931 			if (todo > pad)
932 				todo = pad;
933 			if (write(ifd, (char *)&zeros, todo) != todo) {
934 				fprintf(stderr, "%s: Write error on %s: %s\n",
935 					params.cmdname, params.imagefile,
936 					strerror(errno));
937 				exit(EXIT_FAILURE);
938 			}
939 			pad -= todo;
940 		}
941 	}
942 
943 	(void) munmap((void *)ptr, sbuf.st_size);
944 	(void) close (dfd);
945 }
946