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 (¶ms))
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(¶ms);
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, ¶ms);
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(¶ms, 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, ¶ms);
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, ¶ms);
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, ¶ms);
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