]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/mkimage.c
arm: mx5: clock: add support for changing CPU clock via cmdline
[karo-tx-uboot.git] / tools / mkimage.c
1 /*
2  * (C) Copyright 2008 Semihalf
3  *
4  * (C) Copyright 2000-2009
5  * DENX Software Engineering
6  * Wolfgang Denk, wd@denx.de
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include "mkimage.h"
12 #include <image.h>
13 #include <version.h>
14
15 static void copy_file(int, const char *, int);
16 static void usage(void);
17
18 /* image_type_params link list to maintain registered image type supports */
19 struct image_type_params *mkimage_tparams = NULL;
20
21 /* parameters initialized by core will be used by the image type code */
22 struct mkimage_params params = {
23         .os = IH_OS_LINUX,
24         .arch = IH_ARCH_PPC,
25         .type = IH_TYPE_KERNEL,
26         .comp = IH_COMP_GZIP,
27         .dtc = MKIMAGE_DEFAULT_DTC_OPTIONS,
28         .imagename = "",
29         .imagename2 = "",
30 };
31
32 /*
33  * mkimage_register -
34  *
35  * It is used to register respective image generation/list support to the
36  * mkimage core
37  *
38  * the input struct image_type_params is checked and appended to the link
39  * list, if the input structure is already registered, error
40  */
41 void mkimage_register (struct image_type_params *tparams)
42 {
43         struct image_type_params **tp;
44
45         if (!tparams) {
46                 fprintf (stderr, "%s: %s: Null input\n",
47                         params.cmdname, __FUNCTION__);
48                 exit (EXIT_FAILURE);
49         }
50
51         /* scan the linked list, check for registry and point the last one */
52         for (tp = &mkimage_tparams; *tp != NULL; tp = &(*tp)->next) {
53                 if (!strcmp((*tp)->name, tparams->name)) {
54                         fprintf (stderr, "%s: %s already registered\n",
55                                 params.cmdname, tparams->name);
56                         return;
57                 }
58         }
59
60         /* add input struct entry at the end of link list */
61         *tp = tparams;
62         /* mark input entry as last entry in the link list */
63         tparams->next = NULL;
64
65         debug ("Registered %s\n", tparams->name);
66 }
67
68 /*
69  * mkimage_get_type -
70  *
71  * It scans all registers image type supports
72  * checks the input type_id for each supported image type
73  *
74  * if successful,
75  *      returns respective image_type_params pointer if success
76  * if input type_id is not supported by any of image_type_support
77  *      returns NULL
78  */
79 struct image_type_params *mkimage_get_type(int type)
80 {
81         struct image_type_params *curr;
82
83         for (curr = mkimage_tparams; curr != NULL; curr = curr->next) {
84                 if (curr->check_image_type) {
85                         if (!curr->check_image_type (type))
86                                 return curr;
87                 }
88         }
89         return NULL;
90 }
91
92 /*
93  * mkimage_verify_print_header -
94  *
95  * It scans mkimage_tparams link list,
96  * verifies image_header for each supported image type
97  * if verification is successful, prints respective header
98  *
99  * returns negative if input image format does not match with any of
100  * supported image types
101  */
102 int mkimage_verify_print_header (void *ptr, struct stat *sbuf)
103 {
104         int retval = -1;
105         struct image_type_params *curr;
106
107         for (curr = mkimage_tparams; curr != NULL; curr = curr->next ) {
108                 if (curr->verify_header) {
109                         retval = curr->verify_header (
110                                 (unsigned char *)ptr, sbuf->st_size,
111                                 &params);
112
113                         if (retval == 0) {
114                                 /*
115                                  * Print the image information
116                                  * if verify is successful
117                                  */
118                                 if (curr->print_header)
119                                         curr->print_header (ptr);
120                                 else {
121                                         fprintf (stderr,
122                                         "%s: print_header undefined for %s\n",
123                                         params.cmdname, curr->name);
124                                 }
125                                 break;
126                         }
127                 }
128         }
129         return retval;
130 }
131
132 int
133 main (int argc, char **argv)
134 {
135         int ifd = -1;
136         struct stat sbuf;
137         char *ptr;
138         int retval = 0;
139         struct image_type_params *tparams = NULL;
140
141         /* Init Freescale PBL Boot image generation/list support */
142         init_pbl_image_type();
143         /* Init Kirkwood Boot image generation/list support */
144         init_kwb_image_type ();
145         /* Init Freescale imx Boot image generation/list support */
146         init_imx_image_type ();
147         /* Init FIT image generation/list support */
148         init_fit_image_type ();
149         /* Init TI OMAP Boot image generation/list support */
150         init_omap_image_type();
151         /* Init Default image generation/list support */
152         init_default_image_type ();
153         /* Init Davinci UBL support */
154         init_ubl_image_type();
155         /* Init Davinci AIS support */
156         init_ais_image_type();
157
158         params.cmdname = *argv;
159         params.addr = params.ep = 0;
160
161         while (--argc > 0 && **++argv == '-') {
162                 while (*++*argv) {
163                         switch (**argv) {
164                         case 'l':
165                                 params.lflag = 1;
166                                 break;
167                         case 'A':
168                                 if ((--argc <= 0) ||
169                                         (params.arch =
170                                         genimg_get_arch_id (*++argv)) < 0)
171                                         usage ();
172                                 goto NXTARG;
173                         case 'c':
174                                 if (--argc <= 0)
175                                         usage();
176                                 params.comment = *++argv;
177                                 goto NXTARG;
178                         case 'C':
179                                 if ((--argc <= 0) ||
180                                         (params.comp =
181                                         genimg_get_comp_id (*++argv)) < 0)
182                                         usage ();
183                                 goto NXTARG;
184                         case 'D':
185                                 if (--argc <= 0)
186                                         usage ();
187                                 params.dtc = *++argv;
188                                 goto NXTARG;
189
190                         case 'O':
191                                 if ((--argc <= 0) ||
192                                         (params.os =
193                                         genimg_get_os_id (*++argv)) < 0)
194                                         usage ();
195                                 goto NXTARG;
196                         case 'T':
197                                 if ((--argc <= 0) ||
198                                         (params.type =
199                                         genimg_get_type_id (*++argv)) < 0)
200                                         usage ();
201                                 goto NXTARG;
202
203                         case 'a':
204                                 if (--argc <= 0)
205                                         usage ();
206                                 params.addr = strtoul (*++argv, &ptr, 16);
207                                 if (*ptr) {
208                                         fprintf (stderr,
209                                                 "%s: invalid load address %s\n",
210                                                 params.cmdname, *argv);
211                                         exit (EXIT_FAILURE);
212                                 }
213                                 goto NXTARG;
214                         case 'd':
215                                 if (--argc <= 0)
216                                         usage ();
217                                 params.datafile = *++argv;
218                                 params.dflag = 1;
219                                 goto NXTARG;
220                         case 'e':
221                                 if (--argc <= 0)
222                                         usage ();
223                                 params.ep = strtoul (*++argv, &ptr, 16);
224                                 if (*ptr) {
225                                         fprintf (stderr,
226                                                 "%s: invalid entry point %s\n",
227                                                 params.cmdname, *argv);
228                                         exit (EXIT_FAILURE);
229                                 }
230                                 params.eflag = 1;
231                                 goto NXTARG;
232                         case 'f':
233                                 if (--argc <= 0)
234                                         usage ();
235                                 params.datafile = *++argv;
236                                 /* no break */
237                         case 'F':
238                                 /*
239                                  * The flattened image tree (FIT) format
240                                  * requires a flattened device tree image type
241                                  */
242                                 params.type = IH_TYPE_FLATDT;
243                                 params.fflag = 1;
244                                 goto NXTARG;
245                         case 'k':
246                                 if (--argc <= 0)
247                                         usage();
248                                 params.keydir = *++argv;
249                                 goto NXTARG;
250                         case 'K':
251                                 if (--argc <= 0)
252                                         usage();
253                                 params.keydest = *++argv;
254                                 goto NXTARG;
255                         case 'n':
256                                 if (--argc <= 0)
257                                         usage ();
258                                 params.imagename = *++argv;
259                                 goto NXTARG;
260                         case 'r':
261                                 params.require_keys = 1;
262                                 break;
263                         case 'R':
264                                 if (--argc <= 0)
265                                         usage();
266                                 /*
267                                  * This entry is for the second configuration
268                                  * file, if only one is not enough.
269                                  */
270                                 params.imagename2 = *++argv;
271                                 goto NXTARG;
272                         case 's':
273                                 params.skipcpy = 1;
274                                 break;
275                         case 'v':
276                                 params.vflag++;
277                                 break;
278                         case 'V':
279                                 printf("mkimage version %s\n", PLAIN_VERSION);
280                                 exit(EXIT_SUCCESS);
281                         case 'x':
282                                 params.xflag++;
283                                 break;
284                         default:
285                                 usage ();
286                         }
287                 }
288 NXTARG:         ;
289         }
290
291         if (argc != 1)
292                 usage ();
293
294         /* set tparams as per input type_id */
295         tparams = mkimage_get_type(params.type);
296         if (tparams == NULL) {
297                 fprintf (stderr, "%s: unsupported type %s\n",
298                         params.cmdname, genimg_get_type_name(params.type));
299                 exit (EXIT_FAILURE);
300         }
301
302         /*
303          * check the passed arguments parameters meets the requirements
304          * as per image type to be generated/listed
305          */
306         if (tparams->check_params)
307                 if (tparams->check_params (&params))
308                         usage ();
309
310         if (!params.eflag) {
311                 params.ep = params.addr;
312                 /* If XIP, entry point must be after the U-Boot header */
313                 if (params.xflag)
314                         params.ep += tparams->header_size;
315         }
316
317         params.imagefile = *argv;
318
319         if (params.fflag){
320                 if (tparams->fflag_handle)
321                         /*
322                          * in some cases, some additional processing needs
323                          * to be done if fflag is defined
324                          *
325                          * For ex. fit_handle_file for Fit file support
326                          */
327                         retval = tparams->fflag_handle(&params);
328
329                 if (retval != EXIT_SUCCESS)
330                         exit (retval);
331         }
332
333         if (params.lflag || params.fflag) {
334                 ifd = open (params.imagefile, O_RDONLY|O_BINARY);
335         } else {
336                 ifd = open (params.imagefile,
337                         O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
338         }
339
340         if (ifd < 0) {
341                 fprintf (stderr, "%s: Can't open %s: %s\n",
342                         params.cmdname, params.imagefile,
343                         strerror(errno));
344                 exit (EXIT_FAILURE);
345         }
346
347         if (params.lflag || params.fflag) {
348                 /*
349                  * list header information of existing image
350                  */
351                 if (fstat(ifd, &sbuf) < 0) {
352                         fprintf (stderr, "%s: Can't stat %s: %s\n",
353                                 params.cmdname, params.imagefile,
354                                 strerror(errno));
355                         exit (EXIT_FAILURE);
356                 }
357
358                 if ((unsigned)sbuf.st_size < tparams->header_size) {
359                         fprintf (stderr,
360                                 "%s: Bad size: \"%s\" is not valid image\n",
361                                 params.cmdname, params.imagefile);
362                         exit (EXIT_FAILURE);
363                 }
364
365                 ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0);
366                 if (ptr == MAP_FAILED) {
367                         fprintf (stderr, "%s: Can't read %s: %s\n",
368                                 params.cmdname, params.imagefile,
369                                 strerror(errno));
370                         exit (EXIT_FAILURE);
371                 }
372
373                 /*
374                  * scan through mkimage registry for all supported image types
375                  * and verify the input image file header for match
376                  * Print the image information for matched image type
377                  * Returns the error code if not matched
378                  */
379                 retval = mkimage_verify_print_header (ptr, &sbuf);
380
381                 (void) munmap((void *)ptr, sbuf.st_size);
382                 (void) close (ifd);
383
384                 exit (retval);
385         }
386
387         /*
388          * In case there an header with a variable
389          * length will be added, the corresponding
390          * function is called. This is responsible to
391          * allocate memory for the header itself.
392          */
393         if (tparams->vrec_header)
394                 tparams->vrec_header(&params, tparams);
395         else
396                 memset(tparams->hdr, 0, tparams->header_size);
397
398         if (write(ifd, tparams->hdr, tparams->header_size)
399                                         != tparams->header_size) {
400                 fprintf (stderr, "%s: Write error on %s: %s\n",
401                         params.cmdname, params.imagefile, strerror(errno));
402                 exit (EXIT_FAILURE);
403         }
404
405         if (!params.skipcpy) {
406                 if (params.type == IH_TYPE_MULTI ||
407                     params.type == IH_TYPE_SCRIPT) {
408                         char *file = params.datafile;
409                         uint32_t size;
410
411                         for (;;) {
412                                 char *sep = NULL;
413
414                                 if (file) {
415                                         if ((sep = strchr(file, ':')) != NULL) {
416                                                 *sep = '\0';
417                                         }
418
419                                         if (stat (file, &sbuf) < 0) {
420                                                 fprintf (stderr, "%s: Can't stat %s: %s\n",
421                                                          params.cmdname, file, strerror(errno));
422                                                 exit (EXIT_FAILURE);
423                                         }
424                                         size = cpu_to_uimage (sbuf.st_size);
425                                 } else {
426                                         size = 0;
427                                 }
428
429                                 if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
430                                         fprintf (stderr, "%s: Write error on %s: %s\n",
431                                                  params.cmdname, params.imagefile,
432                                                  strerror(errno));
433                                         exit (EXIT_FAILURE);
434                                 }
435
436                                 if (!file) {
437                                         break;
438                                 }
439
440                                 if (sep) {
441                                         *sep = ':';
442                                         file = sep + 1;
443                                 } else {
444                                         file = NULL;
445                                 }
446                         }
447
448                         file = params.datafile;
449
450                         for (;;) {
451                                 char *sep = strchr(file, ':');
452                                 if (sep) {
453                                         *sep = '\0';
454                                         copy_file (ifd, file, 1);
455                                         *sep++ = ':';
456                                         file = sep;
457                                 } else {
458                                         copy_file (ifd, file, 0);
459                                         break;
460                                 }
461                         }
462                 } else if (params.type == IH_TYPE_PBLIMAGE) {
463                         /* PBL has special Image format, implements its' own */
464                         pbl_load_uboot(ifd, &params);
465                 } else {
466                         copy_file (ifd, params.datafile, 0);
467                 }
468         }
469
470         /* We're a bit of paranoid */
471 #if defined(_POSIX_SYNCHRONIZED_IO) && \
472    !defined(__sun__) && \
473    !defined(__FreeBSD__) && \
474    !defined(__APPLE__)
475         (void) fdatasync (ifd);
476 #else
477         (void) fsync (ifd);
478 #endif
479
480         if (fstat(ifd, &sbuf) < 0) {
481                 fprintf (stderr, "%s: Can't stat %s: %s\n",
482                         params.cmdname, params.imagefile, strerror(errno));
483                 exit (EXIT_FAILURE);
484         }
485
486         ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
487         if (ptr == MAP_FAILED) {
488                 fprintf (stderr, "%s: Can't map %s: %s\n",
489                         params.cmdname, params.imagefile, strerror(errno));
490                 exit (EXIT_FAILURE);
491         }
492
493         /* Setup the image header as per input image type*/
494         if (tparams->set_header)
495                 tparams->set_header (ptr, &sbuf, ifd, &params);
496         else {
497                 fprintf (stderr, "%s: Can't set header for %s: %s\n",
498                         params.cmdname, tparams->name, strerror(errno));
499                 exit (EXIT_FAILURE);
500         }
501
502         /* Print the image information by processing image header */
503         if (tparams->print_header)
504                 tparams->print_header (ptr);
505         else {
506                 fprintf (stderr, "%s: Can't print header for %s: %s\n",
507                         params.cmdname, tparams->name, strerror(errno));
508                 exit (EXIT_FAILURE);
509         }
510
511         (void) munmap((void *)ptr, sbuf.st_size);
512
513         /* We're a bit of paranoid */
514 #if defined(_POSIX_SYNCHRONIZED_IO) && \
515    !defined(__sun__) && \
516    !defined(__FreeBSD__) && \
517    !defined(__APPLE__)
518         (void) fdatasync (ifd);
519 #else
520         (void) fsync (ifd);
521 #endif
522
523         if (close(ifd)) {
524                 fprintf (stderr, "%s: Write error on %s: %s\n",
525                         params.cmdname, params.imagefile, strerror(errno));
526                 exit (EXIT_FAILURE);
527         }
528
529         exit (EXIT_SUCCESS);
530 }
531
532 static void
533 copy_file (int ifd, const char *datafile, int pad)
534 {
535         int dfd;
536         struct stat sbuf;
537         unsigned char *ptr;
538         int tail;
539         int zero = 0;
540         int offset = 0;
541         int size;
542         struct image_type_params *tparams = mkimage_get_type (params.type);
543
544         if (params.vflag) {
545                 fprintf (stderr, "Adding Image %s\n", datafile);
546         }
547
548         if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
549                 fprintf (stderr, "%s: Can't open %s: %s\n",
550                         params.cmdname, datafile, strerror(errno));
551                 exit (EXIT_FAILURE);
552         }
553
554         if (fstat(dfd, &sbuf) < 0) {
555                 fprintf (stderr, "%s: Can't stat %s: %s\n",
556                         params.cmdname, datafile, strerror(errno));
557                 exit (EXIT_FAILURE);
558         }
559
560         ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
561         if (ptr == MAP_FAILED) {
562                 fprintf (stderr, "%s: Can't read %s: %s\n",
563                         params.cmdname, datafile, strerror(errno));
564                 exit (EXIT_FAILURE);
565         }
566
567         if (params.xflag) {
568                 unsigned char *p = NULL;
569                 /*
570                  * XIP: do not append the image_header_t at the
571                  * beginning of the file, but consume the space
572                  * reserved for it.
573                  */
574
575                 if ((unsigned)sbuf.st_size < tparams->header_size) {
576                         fprintf (stderr,
577                                 "%s: Bad size: \"%s\" is too small for XIP\n",
578                                 params.cmdname, datafile);
579                         exit (EXIT_FAILURE);
580                 }
581
582                 for (p = ptr; p < ptr + tparams->header_size; p++) {
583                         if ( *p != 0xff ) {
584                                 fprintf (stderr,
585                                         "%s: Bad file: \"%s\" has invalid buffer for XIP\n",
586                                         params.cmdname, datafile);
587                                 exit (EXIT_FAILURE);
588                         }
589                 }
590
591                 offset = tparams->header_size;
592         }
593
594         size = sbuf.st_size - offset;
595         if (write(ifd, ptr + offset, size) != size) {
596                 fprintf (stderr, "%s: Write error on %s: %s\n",
597                         params.cmdname, params.imagefile, strerror(errno));
598                 exit (EXIT_FAILURE);
599         }
600
601         if (pad && ((tail = size % 4) != 0)) {
602
603                 if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
604                         fprintf (stderr, "%s: Write error on %s: %s\n",
605                                 params.cmdname, params.imagefile,
606                                 strerror(errno));
607                         exit (EXIT_FAILURE);
608                 }
609         }
610
611         (void) munmap((void *)ptr, sbuf.st_size);
612         (void) close (dfd);
613 }
614
615 void
616 usage ()
617 {
618         fprintf (stderr, "Usage: %s -l image\n"
619                          "          -l ==> list image header information\n",
620                 params.cmdname);
621         fprintf (stderr, "       %s [-x] -A arch -O os -T type -C comp "
622                          "-a addr -e ep -n name -d data_file[:data_file...] image\n"
623                          "          -A ==> set architecture to 'arch'\n"
624                          "          -O ==> set operating system to 'os'\n"
625                          "          -T ==> set image type to 'type'\n"
626                          "          -C ==> set compression type 'comp'\n"
627                          "          -a ==> set load address to 'addr' (hex)\n"
628                          "          -e ==> set entry point to 'ep' (hex)\n"
629                          "          -n ==> set image name to 'name'\n"
630                          "          -d ==> use image data from 'datafile'\n"
631                          "          -x ==> set XIP (execute in place)\n",
632                 params.cmdname);
633         fprintf(stderr, "       %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n",
634                 params.cmdname);
635         fprintf(stderr, "          -D => set options for device tree compiler\n"
636                         "          -f => input filename for FIT source\n");
637 #ifdef CONFIG_FIT_SIGNATURE
638         fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n"
639                         "          -k => set directory containing private keys\n"
640                         "          -K => write public keys to this .dtb file\n"
641                         "          -c => add comment in signature node\n"
642                         "          -F => re-sign existing FIT image\n"
643                         "          -r => mark keys used as 'required' in dtb\n");
644 #else
645         fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
646 #endif
647         fprintf (stderr, "       %s -V ==> print version information and exit\n",
648                 params.cmdname);
649
650         exit (EXIT_FAILURE);
651 }