xref: /OK3568_Linux_fs/u-boot/tools/mkimage.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2008 Semihalf
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * (C) Copyright 2000-2009
5*4882a593Smuzhiyun  * DENX Software Engineering
6*4882a593Smuzhiyun  * Wolfgang Denk, wd@denx.de
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "mkimage.h"
12*4882a593Smuzhiyun #include "imximage.h"
13*4882a593Smuzhiyun #include <image.h>
14*4882a593Smuzhiyun #include <version.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun static void copy_file(int, const char *, int);
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* parameters initialized by core will be used by the image type code */
19*4882a593Smuzhiyun static struct image_tool_params params = {
20*4882a593Smuzhiyun 	.os = IH_OS_LINUX,
21*4882a593Smuzhiyun 	.arch = IH_ARCH_PPC,
22*4882a593Smuzhiyun 	.type = IH_TYPE_KERNEL,
23*4882a593Smuzhiyun 	.comp = IH_COMP_GZIP,
24*4882a593Smuzhiyun 	.dtc = MKIMAGE_DEFAULT_DTC_OPTIONS,
25*4882a593Smuzhiyun 	.imagename = "",
26*4882a593Smuzhiyun 	.imagename2 = "",
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun static enum ih_category cur_category;
30*4882a593Smuzhiyun 
h_compare_category_name(const void * vtype1,const void * vtype2)31*4882a593Smuzhiyun static int h_compare_category_name(const void *vtype1, const void *vtype2)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	const int *type1 = vtype1;
34*4882a593Smuzhiyun 	const int *type2 = vtype2;
35*4882a593Smuzhiyun 	const char *name1 = genimg_get_cat_short_name(cur_category, *type1);
36*4882a593Smuzhiyun 	const char *name2 = genimg_get_cat_short_name(cur_category, *type2);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	return strcmp(name1, name2);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
show_valid_options(enum ih_category category)41*4882a593Smuzhiyun static int show_valid_options(enum ih_category category)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	int *order;
44*4882a593Smuzhiyun 	int count;
45*4882a593Smuzhiyun 	int item;
46*4882a593Smuzhiyun 	int i;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	count = genimg_get_cat_count(category);
49*4882a593Smuzhiyun 	order = calloc(count, sizeof(*order));
50*4882a593Smuzhiyun 	if (!order)
51*4882a593Smuzhiyun 		return -ENOMEM;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* Sort the names in order of short name for easier reading */
54*4882a593Smuzhiyun 	for (item = 0; item < count; item++)
55*4882a593Smuzhiyun 		order[item] = item;
56*4882a593Smuzhiyun 	cur_category = category;
57*4882a593Smuzhiyun 	qsort(order, count, sizeof(int), h_compare_category_name);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	fprintf(stderr, "\nInvalid %s, supported are:\n",
60*4882a593Smuzhiyun 		genimg_get_cat_desc(category));
61*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
62*4882a593Smuzhiyun 		item = order[i];
63*4882a593Smuzhiyun 		fprintf(stderr, "\t%-15s  %s\n",
64*4882a593Smuzhiyun 			genimg_get_cat_short_name(category, item),
65*4882a593Smuzhiyun 			genimg_get_cat_name(category, item));
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 	fprintf(stderr, "\n");
68*4882a593Smuzhiyun 	free(order);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
usage(const char * msg)73*4882a593Smuzhiyun static void usage(const char *msg)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	fprintf(stderr, "Error: %s\n", msg);
76*4882a593Smuzhiyun 	fprintf(stderr, "Usage: %s -l image\n"
77*4882a593Smuzhiyun 			 "          -l ==> list image header information\n",
78*4882a593Smuzhiyun 		params.cmdname);
79*4882a593Smuzhiyun 	fprintf(stderr,
80*4882a593Smuzhiyun 		"       %s [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image\n"
81*4882a593Smuzhiyun 		"          -A ==> set architecture to 'arch'\n"
82*4882a593Smuzhiyun 		"          -O ==> set operating system to 'os'\n"
83*4882a593Smuzhiyun 		"          -T ==> set image type to 'type'\n"
84*4882a593Smuzhiyun 		"          -C ==> set compression type 'comp'\n"
85*4882a593Smuzhiyun 		"          -a ==> set load address to 'addr' (hex)\n"
86*4882a593Smuzhiyun 		"          -e ==> set entry point to 'ep' (hex)\n"
87*4882a593Smuzhiyun 		"          -n ==> set image name to 'name'\n"
88*4882a593Smuzhiyun 		"          -d ==> use image data from 'datafile'\n"
89*4882a593Smuzhiyun 		"          -x ==> set XIP (execute in place)\n",
90*4882a593Smuzhiyun 		params.cmdname);
91*4882a593Smuzhiyun 	fprintf(stderr,
92*4882a593Smuzhiyun 		"       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb> [-b <dtb>]] [-i <ramdisk.cpio.gz>] fit-image\n"
93*4882a593Smuzhiyun 		"           <dtb> file is used with -f auto, it may occur multiple times.\n",
94*4882a593Smuzhiyun 		params.cmdname);
95*4882a593Smuzhiyun 	fprintf(stderr,
96*4882a593Smuzhiyun 		"          -D => set all options for device tree compiler\n"
97*4882a593Smuzhiyun 		"          -f => input filename for FIT source\n"
98*4882a593Smuzhiyun 		"          -i => input filename for ramdisk file\n"
99*4882a593Smuzhiyun 		"          -v => set FIT image version in decimal\n");
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #ifdef CONFIG_FIT_SIGNATURE
102*4882a593Smuzhiyun 	fprintf(stderr,
103*4882a593Smuzhiyun 		"Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
104*4882a593Smuzhiyun 		"          -E => place data outside of the FIT structure\n"
105*4882a593Smuzhiyun 		"          -k => set directory containing private keys\n"
106*4882a593Smuzhiyun 		"          -K => write public keys to this .dtb file\n"
107*4882a593Smuzhiyun 		"          -c => add comment in signature node\n"
108*4882a593Smuzhiyun 		"          -F => re-sign existing FIT image\n"
109*4882a593Smuzhiyun 		"          -p => place external data at a static position\n"
110*4882a593Smuzhiyun 		"          -r => mark keys used as 'required' in dtb\n"
111*4882a593Smuzhiyun 		"          -N => engine to use for signing (pkcs11)\n");
112*4882a593Smuzhiyun #else
113*4882a593Smuzhiyun 	fprintf(stderr,
114*4882a593Smuzhiyun 		"Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
115*4882a593Smuzhiyun #endif
116*4882a593Smuzhiyun 	fprintf(stderr, "       %s -V ==> print version information and exit\n",
117*4882a593Smuzhiyun 		params.cmdname);
118*4882a593Smuzhiyun 	fprintf(stderr, "Use '-T list' to see a list of available image types\n");
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	exit(EXIT_FAILURE);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
add_content(int type,const char * fname)123*4882a593Smuzhiyun static int add_content(int type, const char *fname)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct content_info *cont;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	cont = calloc(1, sizeof(*cont));
128*4882a593Smuzhiyun 	if (!cont)
129*4882a593Smuzhiyun 		return -1;
130*4882a593Smuzhiyun 	cont->type = type;
131*4882a593Smuzhiyun 	cont->fname = fname;
132*4882a593Smuzhiyun 	if (params.content_tail)
133*4882a593Smuzhiyun 		params.content_tail->next = cont;
134*4882a593Smuzhiyun 	else
135*4882a593Smuzhiyun 		params.content_head = cont;
136*4882a593Smuzhiyun 	params.content_tail = cont;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return 0;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
process_args(int argc,char ** argv)141*4882a593Smuzhiyun static void process_args(int argc, char **argv)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	char *ptr;
144*4882a593Smuzhiyun 	int type = IH_TYPE_INVALID;
145*4882a593Smuzhiyun 	char *datafile = NULL;
146*4882a593Smuzhiyun 	int opt;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	while ((opt = getopt(argc, argv,
149*4882a593Smuzhiyun 			     "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:v:VxX:")) != -1) {
150*4882a593Smuzhiyun 		switch (opt) {
151*4882a593Smuzhiyun 		case 'a':
152*4882a593Smuzhiyun 			params.addr = strtoull(optarg, &ptr, 16);
153*4882a593Smuzhiyun 			if (*ptr) {
154*4882a593Smuzhiyun 				fprintf(stderr, "%s: invalid load address %s\n",
155*4882a593Smuzhiyun 					params.cmdname, optarg);
156*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
157*4882a593Smuzhiyun 			}
158*4882a593Smuzhiyun 			break;
159*4882a593Smuzhiyun 		case 'A':
160*4882a593Smuzhiyun 			params.arch = genimg_get_arch_id(optarg);
161*4882a593Smuzhiyun 			if (params.arch < 0) {
162*4882a593Smuzhiyun 				show_valid_options(IH_ARCH);
163*4882a593Smuzhiyun 				usage("Invalid architecture");
164*4882a593Smuzhiyun 			}
165*4882a593Smuzhiyun 			break;
166*4882a593Smuzhiyun 		case 'b':
167*4882a593Smuzhiyun 			if (add_content(IH_TYPE_FLATDT, optarg)) {
168*4882a593Smuzhiyun 				fprintf(stderr,
169*4882a593Smuzhiyun 					"%s: Out of memory adding content '%s'",
170*4882a593Smuzhiyun 					params.cmdname, optarg);
171*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
172*4882a593Smuzhiyun 			}
173*4882a593Smuzhiyun 			break;
174*4882a593Smuzhiyun 		case 'c':
175*4882a593Smuzhiyun 			params.comment = optarg;
176*4882a593Smuzhiyun 			break;
177*4882a593Smuzhiyun 		case 'C':
178*4882a593Smuzhiyun 			params.comp = genimg_get_comp_id(optarg);
179*4882a593Smuzhiyun 			if (params.comp < 0) {
180*4882a593Smuzhiyun 				show_valid_options(IH_COMP);
181*4882a593Smuzhiyun 				usage("Invalid compression type");
182*4882a593Smuzhiyun 			}
183*4882a593Smuzhiyun 			break;
184*4882a593Smuzhiyun 		case 'd':
185*4882a593Smuzhiyun 			params.datafile = optarg;
186*4882a593Smuzhiyun 			params.dflag = 1;
187*4882a593Smuzhiyun 			break;
188*4882a593Smuzhiyun 		case 'D':
189*4882a593Smuzhiyun 			params.dtc = optarg;
190*4882a593Smuzhiyun 			break;
191*4882a593Smuzhiyun 		case 'e':
192*4882a593Smuzhiyun 			params.ep = strtoull(optarg, &ptr, 16);
193*4882a593Smuzhiyun 			if (*ptr) {
194*4882a593Smuzhiyun 				fprintf(stderr, "%s: invalid entry point %s\n",
195*4882a593Smuzhiyun 					params.cmdname, optarg);
196*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
197*4882a593Smuzhiyun 			}
198*4882a593Smuzhiyun 			params.eflag = 1;
199*4882a593Smuzhiyun 			break;
200*4882a593Smuzhiyun 		case 'E':
201*4882a593Smuzhiyun 			params.external_data = true;
202*4882a593Smuzhiyun 			break;
203*4882a593Smuzhiyun 		case 'f':
204*4882a593Smuzhiyun 			datafile = optarg;
205*4882a593Smuzhiyun 			params.auto_its = !strcmp(datafile, "auto");
206*4882a593Smuzhiyun 			/* no break */
207*4882a593Smuzhiyun 		case 'F':
208*4882a593Smuzhiyun 			/*
209*4882a593Smuzhiyun 			 * The flattened image tree (FIT) format
210*4882a593Smuzhiyun 			 * requires a flattened device tree image type
211*4882a593Smuzhiyun 			 */
212*4882a593Smuzhiyun 			params.type = IH_TYPE_FLATDT;
213*4882a593Smuzhiyun 			params.fflag = 1;
214*4882a593Smuzhiyun 			break;
215*4882a593Smuzhiyun 		case 'i':
216*4882a593Smuzhiyun 			params.fit_ramdisk = optarg;
217*4882a593Smuzhiyun 			break;
218*4882a593Smuzhiyun 		case 'k':
219*4882a593Smuzhiyun 			params.keydir = optarg;
220*4882a593Smuzhiyun 			break;
221*4882a593Smuzhiyun 		case 'K':
222*4882a593Smuzhiyun 			params.keydest = optarg;
223*4882a593Smuzhiyun 			break;
224*4882a593Smuzhiyun 		case 'l':
225*4882a593Smuzhiyun 			params.lflag = 1;
226*4882a593Smuzhiyun 			break;
227*4882a593Smuzhiyun 		case 'n':
228*4882a593Smuzhiyun 			params.imagename = optarg;
229*4882a593Smuzhiyun 			break;
230*4882a593Smuzhiyun 		case 'N':
231*4882a593Smuzhiyun 			params.engine_id = optarg;
232*4882a593Smuzhiyun 			break;
233*4882a593Smuzhiyun 		case 'O':
234*4882a593Smuzhiyun 			params.os = genimg_get_os_id(optarg);
235*4882a593Smuzhiyun 			if (params.os < 0) {
236*4882a593Smuzhiyun 				show_valid_options(IH_OS);
237*4882a593Smuzhiyun 				usage("Invalid operating system");
238*4882a593Smuzhiyun 			}
239*4882a593Smuzhiyun 			break;
240*4882a593Smuzhiyun 		case 'p':
241*4882a593Smuzhiyun 			params.external_offset = strtoull(optarg, &ptr, 16);
242*4882a593Smuzhiyun 			if (*ptr) {
243*4882a593Smuzhiyun 				fprintf(stderr, "%s: invalid offset size %s\n",
244*4882a593Smuzhiyun 					params.cmdname, optarg);
245*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
246*4882a593Smuzhiyun 			}
247*4882a593Smuzhiyun 			break;
248*4882a593Smuzhiyun 		case 'q':
249*4882a593Smuzhiyun 			params.quiet = 1;
250*4882a593Smuzhiyun 			break;
251*4882a593Smuzhiyun 		case 'r':
252*4882a593Smuzhiyun 			params.require_keys = 1;
253*4882a593Smuzhiyun 			break;
254*4882a593Smuzhiyun 		case 'R':
255*4882a593Smuzhiyun 			/*
256*4882a593Smuzhiyun 			 * This entry is for the second configuration
257*4882a593Smuzhiyun 			 * file, if only one is not enough.
258*4882a593Smuzhiyun 			 */
259*4882a593Smuzhiyun 			params.imagename2 = optarg;
260*4882a593Smuzhiyun 			break;
261*4882a593Smuzhiyun 		case 's':
262*4882a593Smuzhiyun 			params.skipcpy = 1;
263*4882a593Smuzhiyun 			break;
264*4882a593Smuzhiyun 		case 'T':
265*4882a593Smuzhiyun 			if (strcmp(optarg, "list") == 0) {
266*4882a593Smuzhiyun 				show_valid_options(IH_TYPE);
267*4882a593Smuzhiyun 				exit(EXIT_SUCCESS);
268*4882a593Smuzhiyun 			}
269*4882a593Smuzhiyun 			type = genimg_get_type_id(optarg);
270*4882a593Smuzhiyun 			if (type < 0) {
271*4882a593Smuzhiyun 				show_valid_options(IH_TYPE);
272*4882a593Smuzhiyun 				usage("Invalid image type");
273*4882a593Smuzhiyun 			}
274*4882a593Smuzhiyun 			break;
275*4882a593Smuzhiyun 		case 'v':
276*4882a593Smuzhiyun 			params.vflag = strtoull(optarg, &ptr, 10);
277*4882a593Smuzhiyun 			if (*ptr) {
278*4882a593Smuzhiyun 				fprintf(stderr, "%s: invalid version length %s\n",
279*4882a593Smuzhiyun 					params.cmdname, optarg);
280*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
281*4882a593Smuzhiyun 			}
282*4882a593Smuzhiyun 			break;
283*4882a593Smuzhiyun 		case 'V':
284*4882a593Smuzhiyun 			printf("mkimage version %s\n", PLAIN_VERSION);
285*4882a593Smuzhiyun 			exit(EXIT_SUCCESS);
286*4882a593Smuzhiyun 		case 'x':
287*4882a593Smuzhiyun 			params.xflag++;
288*4882a593Smuzhiyun 			break;
289*4882a593Smuzhiyun 		case 'X':
290*4882a593Smuzhiyun 			params.extraparams = optarg;
291*4882a593Smuzhiyun 			break;
292*4882a593Smuzhiyun 		default:
293*4882a593Smuzhiyun 			usage("Invalid option");
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	/* The last parameter is expected to be the imagefile */
298*4882a593Smuzhiyun 	if (optind < argc)
299*4882a593Smuzhiyun 		params.imagefile = argv[optind];
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	/*
302*4882a593Smuzhiyun 	 * For auto-generated FIT images we need to know the image type to put
303*4882a593Smuzhiyun 	 * in the FIT, which is separate from the file's image type (which
304*4882a593Smuzhiyun 	 * will always be IH_TYPE_FLATDT in this case).
305*4882a593Smuzhiyun 	 */
306*4882a593Smuzhiyun 	if (params.type == IH_TYPE_FLATDT) {
307*4882a593Smuzhiyun 		params.fit_image_type = type ? type : IH_TYPE_KERNEL;
308*4882a593Smuzhiyun 		/* For auto_its, datafile is always 'auto' */
309*4882a593Smuzhiyun 		if (!params.auto_its)
310*4882a593Smuzhiyun 			params.datafile = datafile;
311*4882a593Smuzhiyun 		else if (!params.datafile)
312*4882a593Smuzhiyun 			usage("Missing data file for auto-FIT (use -d)");
313*4882a593Smuzhiyun 	} else if (type != IH_TYPE_INVALID) {
314*4882a593Smuzhiyun 		params.type = type;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	if (!params.imagefile)
318*4882a593Smuzhiyun 		usage("Missing output filename");
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
main(int argc,char ** argv)321*4882a593Smuzhiyun int main(int argc, char **argv)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	int ifd = -1;
324*4882a593Smuzhiyun 	struct stat sbuf;
325*4882a593Smuzhiyun 	char *ptr;
326*4882a593Smuzhiyun 	int retval = 0;
327*4882a593Smuzhiyun 	struct image_type_params *tparams = NULL;
328*4882a593Smuzhiyun 	int pad_len = 0;
329*4882a593Smuzhiyun 	int dfd;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	params.cmdname = *argv;
332*4882a593Smuzhiyun 	params.addr = 0;
333*4882a593Smuzhiyun 	params.ep = 0;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	process_args(argc, argv);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	/* set tparams as per input type_id */
338*4882a593Smuzhiyun 	tparams = imagetool_get_type(params.type);
339*4882a593Smuzhiyun 	if (tparams == NULL) {
340*4882a593Smuzhiyun 		fprintf (stderr, "%s: unsupported type %s\n",
341*4882a593Smuzhiyun 			params.cmdname, genimg_get_type_name(params.type));
342*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	/*
346*4882a593Smuzhiyun 	 * check the passed arguments parameters meets the requirements
347*4882a593Smuzhiyun 	 * as per image type to be generated/listed
348*4882a593Smuzhiyun 	 */
349*4882a593Smuzhiyun 	if (tparams->check_params)
350*4882a593Smuzhiyun 		if (tparams->check_params (&params))
351*4882a593Smuzhiyun 			usage("Bad parameters for image type");
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (!params.eflag) {
354*4882a593Smuzhiyun 		params.ep = params.addr;
355*4882a593Smuzhiyun 		/* If XIP, entry point must be after the U-Boot header */
356*4882a593Smuzhiyun 		if (params.xflag)
357*4882a593Smuzhiyun 			params.ep += tparams->header_size;
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	if (params.fflag){
361*4882a593Smuzhiyun 		if (tparams->fflag_handle)
362*4882a593Smuzhiyun 			/*
363*4882a593Smuzhiyun 			 * in some cases, some additional processing needs
364*4882a593Smuzhiyun 			 * to be done if fflag is defined
365*4882a593Smuzhiyun 			 *
366*4882a593Smuzhiyun 			 * For ex. fit_handle_file for Fit file support
367*4882a593Smuzhiyun 			 */
368*4882a593Smuzhiyun 			retval = tparams->fflag_handle(&params);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 		if (retval != EXIT_SUCCESS)
371*4882a593Smuzhiyun 			exit (retval);
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	if (params.lflag || params.fflag) {
375*4882a593Smuzhiyun 		ifd = open (params.imagefile, O_RDONLY|O_BINARY);
376*4882a593Smuzhiyun 	} else {
377*4882a593Smuzhiyun 		ifd = open (params.imagefile,
378*4882a593Smuzhiyun 			O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
379*4882a593Smuzhiyun 	}
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	if (ifd < 0) {
382*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't open %s: %s\n",
383*4882a593Smuzhiyun 			params.cmdname, params.imagefile,
384*4882a593Smuzhiyun 			strerror(errno));
385*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
386*4882a593Smuzhiyun 	}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	if (params.lflag || params.fflag) {
389*4882a593Smuzhiyun 		/*
390*4882a593Smuzhiyun 		 * list header information of existing image
391*4882a593Smuzhiyun 		 */
392*4882a593Smuzhiyun 		if (fstat(ifd, &sbuf) < 0) {
393*4882a593Smuzhiyun 			fprintf (stderr, "%s: Can't stat %s: %s\n",
394*4882a593Smuzhiyun 				params.cmdname, params.imagefile,
395*4882a593Smuzhiyun 				strerror(errno));
396*4882a593Smuzhiyun 			exit (EXIT_FAILURE);
397*4882a593Smuzhiyun 		}
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 		if ((unsigned)sbuf.st_size < tparams->header_size) {
400*4882a593Smuzhiyun 			fprintf (stderr,
401*4882a593Smuzhiyun 				"%s: Bad size: \"%s\" is not valid image\n",
402*4882a593Smuzhiyun 				params.cmdname, params.imagefile);
403*4882a593Smuzhiyun 			exit (EXIT_FAILURE);
404*4882a593Smuzhiyun 		}
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 		ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
407*4882a593Smuzhiyun 		if (ptr == MAP_FAILED) {
408*4882a593Smuzhiyun 			fprintf (stderr, "%s: Can't read %s: %s\n",
409*4882a593Smuzhiyun 				params.cmdname, params.imagefile,
410*4882a593Smuzhiyun 				strerror(errno));
411*4882a593Smuzhiyun 			exit (EXIT_FAILURE);
412*4882a593Smuzhiyun 		}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 		/*
415*4882a593Smuzhiyun 		 * scan through mkimage registry for all supported image types
416*4882a593Smuzhiyun 		 * and verify the input image file header for match
417*4882a593Smuzhiyun 		 * Print the image information for matched image type
418*4882a593Smuzhiyun 		 * Returns the error code if not matched
419*4882a593Smuzhiyun 		 */
420*4882a593Smuzhiyun 		retval = imagetool_verify_print_header(ptr, &sbuf,
421*4882a593Smuzhiyun 				tparams, &params);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 		(void) munmap((void *)ptr, sbuf.st_size);
424*4882a593Smuzhiyun 		(void) close (ifd);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 		exit (retval);
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	if ((params.type != IH_TYPE_MULTI) && (params.type != IH_TYPE_SCRIPT) &&
430*4882a593Smuzhiyun 	    (params.type != IH_TYPE_RKNAND)) {
431*4882a593Smuzhiyun 		dfd = open(params.datafile, O_RDONLY | O_BINARY);
432*4882a593Smuzhiyun 		if (dfd < 0) {
433*4882a593Smuzhiyun 			fprintf(stderr, "%s: Can't open %s: %s\n",
434*4882a593Smuzhiyun 				params.cmdname, params.datafile,
435*4882a593Smuzhiyun 				strerror(errno));
436*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
437*4882a593Smuzhiyun 		}
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 		if (fstat(dfd, &sbuf) < 0) {
440*4882a593Smuzhiyun 			fprintf(stderr, "%s: Can't stat %s: %s\n",
441*4882a593Smuzhiyun 				params.cmdname, params.datafile,
442*4882a593Smuzhiyun 				strerror(errno));
443*4882a593Smuzhiyun 			exit(EXIT_FAILURE);
444*4882a593Smuzhiyun 		}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		params.file_size = sbuf.st_size + tparams->header_size;
447*4882a593Smuzhiyun 		close(dfd);
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	/*
451*4882a593Smuzhiyun 	 * In case there an header with a variable
452*4882a593Smuzhiyun 	 * length will be added, the corresponding
453*4882a593Smuzhiyun 	 * function is called. This is responsible to
454*4882a593Smuzhiyun 	 * allocate memory for the header itself.
455*4882a593Smuzhiyun 	 */
456*4882a593Smuzhiyun 	if (tparams->vrec_header)
457*4882a593Smuzhiyun 		pad_len = tparams->vrec_header(&params, tparams);
458*4882a593Smuzhiyun 	else
459*4882a593Smuzhiyun 		memset(tparams->hdr, 0, tparams->header_size);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	if (write(ifd, tparams->hdr, tparams->header_size)
462*4882a593Smuzhiyun 					!= tparams->header_size) {
463*4882a593Smuzhiyun 		fprintf (stderr, "%s: Write error on %s: %s\n",
464*4882a593Smuzhiyun 			params.cmdname, params.imagefile, strerror(errno));
465*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
466*4882a593Smuzhiyun 	}
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	if (!params.skipcpy) {
469*4882a593Smuzhiyun 		if (params.type == IH_TYPE_MULTI ||
470*4882a593Smuzhiyun 		    params.type == IH_TYPE_SCRIPT) {
471*4882a593Smuzhiyun 			char *file = params.datafile;
472*4882a593Smuzhiyun 			uint32_t size;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 			for (;;) {
475*4882a593Smuzhiyun 				char *sep = NULL;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 				if (file) {
478*4882a593Smuzhiyun 					if ((sep = strchr(file, ':')) != NULL) {
479*4882a593Smuzhiyun 						*sep = '\0';
480*4882a593Smuzhiyun 					}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 					if (stat (file, &sbuf) < 0) {
483*4882a593Smuzhiyun 						fprintf (stderr, "%s: Can't stat %s: %s\n",
484*4882a593Smuzhiyun 							 params.cmdname, file, strerror(errno));
485*4882a593Smuzhiyun 						exit (EXIT_FAILURE);
486*4882a593Smuzhiyun 					}
487*4882a593Smuzhiyun 					size = cpu_to_uimage (sbuf.st_size);
488*4882a593Smuzhiyun 				} else {
489*4882a593Smuzhiyun 					size = IMAGE_PARAM_INVAL;
490*4882a593Smuzhiyun 				}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 				if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
493*4882a593Smuzhiyun 					fprintf (stderr, "%s: Write error on %s: %s\n",
494*4882a593Smuzhiyun 						 params.cmdname, params.imagefile,
495*4882a593Smuzhiyun 						 strerror(errno));
496*4882a593Smuzhiyun 					exit (EXIT_FAILURE);
497*4882a593Smuzhiyun 				}
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 				if (!file) {
500*4882a593Smuzhiyun 					break;
501*4882a593Smuzhiyun 				}
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 				if (sep) {
504*4882a593Smuzhiyun 					*sep = ':';
505*4882a593Smuzhiyun 					file = sep + 1;
506*4882a593Smuzhiyun 				} else {
507*4882a593Smuzhiyun 					file = NULL;
508*4882a593Smuzhiyun 				}
509*4882a593Smuzhiyun 			}
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 			file = params.datafile;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 			for (;;) {
514*4882a593Smuzhiyun 				char *sep = strchr(file, ':');
515*4882a593Smuzhiyun 				if (sep) {
516*4882a593Smuzhiyun 					*sep = '\0';
517*4882a593Smuzhiyun 					copy_file (ifd, file, 1);
518*4882a593Smuzhiyun 					*sep++ = ':';
519*4882a593Smuzhiyun 					file = sep;
520*4882a593Smuzhiyun 				} else {
521*4882a593Smuzhiyun 					copy_file (ifd, file, 0);
522*4882a593Smuzhiyun 					break;
523*4882a593Smuzhiyun 				}
524*4882a593Smuzhiyun 			}
525*4882a593Smuzhiyun 		} else if (params.type == IH_TYPE_PBLIMAGE) {
526*4882a593Smuzhiyun 			/* PBL has special Image format, implements its' own */
527*4882a593Smuzhiyun 			pbl_load_uboot(ifd, &params);
528*4882a593Smuzhiyun 		} else if ((params.type == IH_TYPE_RKSD) ||
529*4882a593Smuzhiyun 				(params.type == IH_TYPE_RKSPI) ||
530*4882a593Smuzhiyun 				(params.type == IH_TYPE_RKNAND)) {
531*4882a593Smuzhiyun 			/* Rockchip has special Image format */
532*4882a593Smuzhiyun 			int ret;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 			ret = rockchip_copy_image(ifd, &params);
535*4882a593Smuzhiyun 			if (ret)
536*4882a593Smuzhiyun 				return ret;
537*4882a593Smuzhiyun 		} else {
538*4882a593Smuzhiyun 			copy_file(ifd, params.datafile, pad_len);
539*4882a593Smuzhiyun 		}
540*4882a593Smuzhiyun 		if (params.type == IH_TYPE_FIRMWARE_IVT) {
541*4882a593Smuzhiyun 			/* Add alignment and IVT */
542*4882a593Smuzhiyun 			uint32_t aligned_filesize = (params.file_size + 0x1000
543*4882a593Smuzhiyun 					- 1) & ~(0x1000 - 1);
544*4882a593Smuzhiyun 			flash_header_v2_t ivt_header = { { 0xd1, 0x2000, 0x40 },
545*4882a593Smuzhiyun 					params.addr, 0, 0, 0, params.addr
546*4882a593Smuzhiyun 							+ aligned_filesize
547*4882a593Smuzhiyun 							- tparams->header_size,
548*4882a593Smuzhiyun 					params.addr + aligned_filesize
549*4882a593Smuzhiyun 							- tparams->header_size
550*4882a593Smuzhiyun 							+ 0x20, 0 };
551*4882a593Smuzhiyun 			int i = params.file_size;
552*4882a593Smuzhiyun 			for (; i < aligned_filesize; i++) {
553*4882a593Smuzhiyun 				if (write(ifd, (char *) &i, 1) != 1) {
554*4882a593Smuzhiyun 					fprintf(stderr,
555*4882a593Smuzhiyun 							"%s: Write error on %s: %s\n",
556*4882a593Smuzhiyun 							params.cmdname,
557*4882a593Smuzhiyun 							params.imagefile,
558*4882a593Smuzhiyun 							strerror(errno));
559*4882a593Smuzhiyun 					exit(EXIT_FAILURE);
560*4882a593Smuzhiyun 				}
561*4882a593Smuzhiyun 			}
562*4882a593Smuzhiyun 			if (write(ifd, &ivt_header, sizeof(flash_header_v2_t))
563*4882a593Smuzhiyun 					!= sizeof(flash_header_v2_t)) {
564*4882a593Smuzhiyun 				fprintf(stderr, "%s: Write error on %s: %s\n",
565*4882a593Smuzhiyun 						params.cmdname,
566*4882a593Smuzhiyun 						params.imagefile,
567*4882a593Smuzhiyun 						strerror(errno));
568*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
569*4882a593Smuzhiyun 			}
570*4882a593Smuzhiyun 		}
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	/* We're a bit of paranoid */
574*4882a593Smuzhiyun #if defined(_POSIX_SYNCHRONIZED_IO) && \
575*4882a593Smuzhiyun    !defined(__sun__) && \
576*4882a593Smuzhiyun    !defined(__FreeBSD__) && \
577*4882a593Smuzhiyun    !defined(__OpenBSD__) && \
578*4882a593Smuzhiyun    !defined(__APPLE__)
579*4882a593Smuzhiyun 	(void) fdatasync (ifd);
580*4882a593Smuzhiyun #else
581*4882a593Smuzhiyun 	(void) fsync (ifd);
582*4882a593Smuzhiyun #endif
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	if (fstat(ifd, &sbuf) < 0) {
585*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't stat %s: %s\n",
586*4882a593Smuzhiyun 			params.cmdname, params.imagefile, strerror(errno));
587*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
588*4882a593Smuzhiyun 	}
589*4882a593Smuzhiyun 	params.file_size = sbuf.st_size;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
592*4882a593Smuzhiyun 	if (ptr == MAP_FAILED) {
593*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't map %s: %s\n",
594*4882a593Smuzhiyun 			params.cmdname, params.imagefile, strerror(errno));
595*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
596*4882a593Smuzhiyun 	}
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	/* Setup the image header as per input image type*/
599*4882a593Smuzhiyun 	if (tparams->set_header)
600*4882a593Smuzhiyun 		tparams->set_header (ptr, &sbuf, ifd, &params);
601*4882a593Smuzhiyun 	else {
602*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't set header for %s: %s\n",
603*4882a593Smuzhiyun 			params.cmdname, tparams->name, strerror(errno));
604*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	/* Print the image information by processing image header */
608*4882a593Smuzhiyun 	if (tparams->print_header)
609*4882a593Smuzhiyun 		tparams->print_header (ptr);
610*4882a593Smuzhiyun 	else {
611*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't print header for %s: %s\n",
612*4882a593Smuzhiyun 			params.cmdname, tparams->name, strerror(errno));
613*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
614*4882a593Smuzhiyun 	}
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	(void) munmap((void *)ptr, sbuf.st_size);
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	/* We're a bit of paranoid */
619*4882a593Smuzhiyun #if defined(_POSIX_SYNCHRONIZED_IO) && \
620*4882a593Smuzhiyun    !defined(__sun__) && \
621*4882a593Smuzhiyun    !defined(__FreeBSD__) && \
622*4882a593Smuzhiyun    !defined(__OpenBSD__) && \
623*4882a593Smuzhiyun    !defined(__APPLE__)
624*4882a593Smuzhiyun 	(void) fdatasync (ifd);
625*4882a593Smuzhiyun #else
626*4882a593Smuzhiyun 	(void) fsync (ifd);
627*4882a593Smuzhiyun #endif
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	if (close(ifd)) {
630*4882a593Smuzhiyun 		fprintf (stderr, "%s: Write error on %s: %s\n",
631*4882a593Smuzhiyun 			params.cmdname, params.imagefile, strerror(errno));
632*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
633*4882a593Smuzhiyun 	}
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	exit (EXIT_SUCCESS);
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun static void
copy_file(int ifd,const char * datafile,int pad)639*4882a593Smuzhiyun copy_file (int ifd, const char *datafile, int pad)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun 	int dfd;
642*4882a593Smuzhiyun 	struct stat sbuf;
643*4882a593Smuzhiyun 	unsigned char *ptr;
644*4882a593Smuzhiyun 	int tail;
645*4882a593Smuzhiyun 	int zero = 0;
646*4882a593Smuzhiyun 	uint8_t zeros[4096];
647*4882a593Smuzhiyun 	int offset = 0;
648*4882a593Smuzhiyun 	int size;
649*4882a593Smuzhiyun 	struct image_type_params *tparams = imagetool_get_type(params.type);
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	memset(zeros, 0, sizeof(zeros));
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	if (params.vflag) {
654*4882a593Smuzhiyun 		fprintf (stderr, "Adding Image %s\n", datafile);
655*4882a593Smuzhiyun 	}
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
658*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't open %s: %s\n",
659*4882a593Smuzhiyun 			params.cmdname, datafile, strerror(errno));
660*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
661*4882a593Smuzhiyun 	}
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	if (fstat(dfd, &sbuf) < 0) {
664*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't stat %s: %s\n",
665*4882a593Smuzhiyun 			params.cmdname, datafile, strerror(errno));
666*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
667*4882a593Smuzhiyun 	}
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	if (sbuf.st_size == 0) {
670*4882a593Smuzhiyun 		(void) close (dfd);
671*4882a593Smuzhiyun 		return;
672*4882a593Smuzhiyun 	}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
675*4882a593Smuzhiyun 	if (ptr == MAP_FAILED) {
676*4882a593Smuzhiyun 		fprintf (stderr, "%s: Can't read %s: %s\n",
677*4882a593Smuzhiyun 			params.cmdname, datafile, strerror(errno));
678*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
679*4882a593Smuzhiyun 	}
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	if (params.xflag) {
682*4882a593Smuzhiyun 		unsigned char *p = NULL;
683*4882a593Smuzhiyun 		/*
684*4882a593Smuzhiyun 		 * XIP: do not append the image_header_t at the
685*4882a593Smuzhiyun 		 * beginning of the file, but consume the space
686*4882a593Smuzhiyun 		 * reserved for it.
687*4882a593Smuzhiyun 		 */
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 		if ((unsigned)sbuf.st_size < tparams->header_size) {
690*4882a593Smuzhiyun 			fprintf (stderr,
691*4882a593Smuzhiyun 				"%s: Bad size: \"%s\" is too small for XIP\n",
692*4882a593Smuzhiyun 				params.cmdname, datafile);
693*4882a593Smuzhiyun 			exit (EXIT_FAILURE);
694*4882a593Smuzhiyun 		}
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 		for (p = ptr; p < ptr + tparams->header_size; p++) {
697*4882a593Smuzhiyun 			if ( *p != 0xff ) {
698*4882a593Smuzhiyun 				fprintf (stderr,
699*4882a593Smuzhiyun 					"%s: Bad file: \"%s\" has invalid buffer for XIP\n",
700*4882a593Smuzhiyun 					params.cmdname, datafile);
701*4882a593Smuzhiyun 				exit (EXIT_FAILURE);
702*4882a593Smuzhiyun 			}
703*4882a593Smuzhiyun 		}
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 		offset = tparams->header_size;
706*4882a593Smuzhiyun 	}
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	size = sbuf.st_size - offset;
709*4882a593Smuzhiyun 	if (write(ifd, ptr + offset, size) != size) {
710*4882a593Smuzhiyun 		fprintf (stderr, "%s: Write error on %s: %s\n",
711*4882a593Smuzhiyun 			params.cmdname, params.imagefile, strerror(errno));
712*4882a593Smuzhiyun 		exit (EXIT_FAILURE);
713*4882a593Smuzhiyun 	}
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	tail = size % 4;
716*4882a593Smuzhiyun 	if ((pad == 1) && (tail != 0)) {
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
719*4882a593Smuzhiyun 			fprintf (stderr, "%s: Write error on %s: %s\n",
720*4882a593Smuzhiyun 				params.cmdname, params.imagefile,
721*4882a593Smuzhiyun 				strerror(errno));
722*4882a593Smuzhiyun 			exit (EXIT_FAILURE);
723*4882a593Smuzhiyun 		}
724*4882a593Smuzhiyun 	} else if (pad > 1) {
725*4882a593Smuzhiyun 		while (pad > 0) {
726*4882a593Smuzhiyun 			int todo = sizeof(zeros);
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 			if (todo > pad)
729*4882a593Smuzhiyun 				todo = pad;
730*4882a593Smuzhiyun 			if (write(ifd, (char *)&zeros, todo) != todo) {
731*4882a593Smuzhiyun 				fprintf(stderr, "%s: Write error on %s: %s\n",
732*4882a593Smuzhiyun 					params.cmdname, params.imagefile,
733*4882a593Smuzhiyun 					strerror(errno));
734*4882a593Smuzhiyun 				exit(EXIT_FAILURE);
735*4882a593Smuzhiyun 			}
736*4882a593Smuzhiyun 			pad -= todo;
737*4882a593Smuzhiyun 		}
738*4882a593Smuzhiyun 	}
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	(void) munmap((void *)ptr, sbuf.st_size);
741*4882a593Smuzhiyun 	(void) close (dfd);
742*4882a593Smuzhiyun }
743