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