Merge tag 'fsl-qoriq-2022-10-18' of https://source.denx.de/u-boot/custodians/u-boot...
[platform/kernel/u-boot.git] / tools / fit_image.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008 Semihalf
4  *
5  * (C) Copyright 2000-2004
6  * DENX Software Engineering
7  * Wolfgang Denk, wd@denx.de
8  *
9  * Updated-by: Prafulla Wadaskar <prafulla@marvell.com>
10  *              FIT image specific code abstracted from mkimage.c
11  *              some functions added to address abstraction
12  *
13  * All rights reserved.
14  */
15
16 #include "imagetool.h"
17 #include "fit_common.h"
18 #include "mkimage.h"
19 #include <image.h>
20 #include <string.h>
21 #include <stdarg.h>
22 #include <version.h>
23 #include <u-boot/crc.h>
24
25 static struct legacy_img_hdr header;
26
27 static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
28                              const char *tmpfile)
29 {
30         int tfd, destfd = 0;
31         void *dest_blob = NULL;
32         off_t destfd_size = 0;
33         struct stat sbuf;
34         void *ptr;
35         int ret = 0;
36
37         tfd = mmap_fdt(params->cmdname, tmpfile, size_inc, &ptr, &sbuf, true,
38                        false);
39         if (tfd < 0)
40                 return -EIO;
41
42         if (params->keydest) {
43                 struct stat dest_sbuf;
44
45                 destfd = mmap_fdt(params->cmdname, params->keydest, size_inc,
46                                   &dest_blob, &dest_sbuf, false,
47                                   false);
48                 if (destfd < 0) {
49                         ret = -EIO;
50                         goto err_keydest;
51                 }
52                 destfd_size = dest_sbuf.st_size;
53         }
54
55         /* for first image creation, add a timestamp at offset 0 i.e., root  */
56         if (params->datafile || params->reset_timestamp) {
57                 time_t time = imagetool_get_source_date(params->cmdname,
58                                                         sbuf.st_mtime);
59                 ret = fit_set_timestamp(ptr, 0, time);
60         }
61
62         if (!ret)
63                 ret = fit_pre_load_data(params->keydir, dest_blob, ptr);
64
65         if (!ret) {
66                 ret = fit_cipher_data(params->keydir, dest_blob, ptr,
67                                       params->comment,
68                                       params->require_keys,
69                                       params->engine_id,
70                                       params->cmdname);
71         }
72
73         if (!ret) {
74                 ret = fit_add_verification_data(params->keydir,
75                                                 params->keyfile, dest_blob, ptr,
76                                                 params->comment,
77                                                 params->require_keys,
78                                                 params->engine_id,
79                                                 params->cmdname,
80                                                 params->algo_name,
81                                                 &params->summary);
82         }
83
84         if (dest_blob) {
85                 munmap(dest_blob, destfd_size);
86                 close(destfd);
87         }
88
89 err_keydest:
90         munmap(ptr, sbuf.st_size);
91         close(tfd);
92         return ret;
93 }
94
95 /**
96  * fit_calc_size() - Calculate the approximate size of the FIT we will generate
97  */
98 static int fit_calc_size(struct image_tool_params *params)
99 {
100         struct content_info *cont;
101         int size, total_size;
102
103         size = imagetool_get_filesize(params, params->datafile);
104         if (size < 0)
105                 return -1;
106         total_size = size;
107
108         if (params->fit_ramdisk) {
109                 size = imagetool_get_filesize(params, params->fit_ramdisk);
110                 if (size < 0)
111                         return -1;
112                 total_size += size;
113         }
114
115         for (cont = params->content_head; cont; cont = cont->next) {
116                 size = imagetool_get_filesize(params, cont->fname);
117                 if (size < 0)
118                         return -1;
119
120                 /* Add space for properties and hash node */
121                 total_size += size + 300;
122         }
123
124         /* Add plenty of space for headers, properties, nodes, etc. */
125         total_size += 4096;
126
127         return total_size;
128 }
129
130 static int fdt_property_file(struct image_tool_params *params,
131                              void *fdt, const char *name, const char *fname)
132 {
133         struct stat sbuf;
134         void *ptr;
135         int ret;
136         int fd;
137
138         fd = open(fname, O_RDWR | O_BINARY);
139         if (fd < 0) {
140                 fprintf(stderr, "%s: Can't open %s: %s\n",
141                         params->cmdname, fname, strerror(errno));
142                 return -1;
143         }
144
145         if (fstat(fd, &sbuf) < 0) {
146                 fprintf(stderr, "%s: Can't stat %s: %s\n",
147                         params->cmdname, fname, strerror(errno));
148                 goto err;
149         }
150
151         ret = fdt_property_placeholder(fdt, "data", sbuf.st_size, &ptr);
152         if (ret)
153                 goto err;
154         ret = read(fd, ptr, sbuf.st_size);
155         if (ret != sbuf.st_size) {
156                 fprintf(stderr, "%s: Can't read %s: %s\n",
157                         params->cmdname, fname, strerror(errno));
158                 goto err;
159         }
160         close(fd);
161
162         return 0;
163 err:
164         close(fd);
165         return -1;
166 }
167
168 static int fdt_property_strf(void *fdt, const char *name, const char *fmt, ...)
169 {
170         char str[100];
171         va_list ptr;
172
173         va_start(ptr, fmt);
174         vsnprintf(str, sizeof(str), fmt, ptr);
175         va_end(ptr);
176         return fdt_property_string(fdt, name, str);
177 }
178
179 static void get_basename(char *str, int size, const char *fname)
180 {
181         const char *p, *start, *end;
182         int len;
183
184         /*
185          * Use the base name as the 'name' field. So for example:
186          *
187          * "arch/arm/dts/sun7i-a20-bananapro.dtb"
188          * becomes "sun7i-a20-bananapro"
189          */
190         p = strrchr(fname, '/');
191         start = p ? p + 1 : fname;
192         p = strrchr(fname, '.');
193         end = p ? p : fname + strlen(fname);
194         len = end - start;
195         if (len >= size)
196                 len = size - 1;
197         memcpy(str, start, len);
198         str[len] = '\0';
199 }
200
201 /**
202  * add_hash_node() - Add a hash or signature node
203  *
204  * @params: Image parameters
205  * @fdt: Device tree to add to (in sequential-write mode)
206  *
207  * If there is a key name hint, try to sign the images. Otherwise, just add a
208  * CRC.
209  *
210  * Return: 0 on success, or -1 on failure
211  */
212 static int add_hash_node(struct image_tool_params *params, void *fdt)
213 {
214         if (params->keyname) {
215                 if (!params->algo_name) {
216                         fprintf(stderr,
217                                 "%s: Algorithm name must be specified\n",
218                                 params->cmdname);
219                         return -1;
220                 }
221
222                 fdt_begin_node(fdt, "signature-1");
223                 fdt_property_string(fdt, FIT_ALGO_PROP, params->algo_name);
224                 fdt_property_string(fdt, FIT_KEY_HINT, params->keyname);
225         } else {
226                 fdt_begin_node(fdt, "hash-1");
227                 fdt_property_string(fdt, FIT_ALGO_PROP, "crc32");
228         }
229
230         fdt_end_node(fdt);
231         return 0;
232 }
233
234 /**
235  * fit_write_images() - Write out a list of images to the FIT
236  *
237  * We always include the main image (params->datafile). If there are device
238  * tree files, we include an fdt- node for each of those too.
239  */
240 static int fit_write_images(struct image_tool_params *params, char *fdt)
241 {
242         struct content_info *cont;
243         const char *typename;
244         char str[100];
245         int upto;
246         int ret;
247
248         fdt_begin_node(fdt, "images");
249
250         /* First the main image */
251         typename = genimg_get_type_short_name(params->fit_image_type);
252         snprintf(str, sizeof(str), "%s-1", typename);
253         fdt_begin_node(fdt, str);
254         fdt_property_string(fdt, FIT_DESC_PROP, params->imagename);
255         fdt_property_string(fdt, FIT_TYPE_PROP, typename);
256         fdt_property_string(fdt, FIT_ARCH_PROP,
257                             genimg_get_arch_short_name(params->arch));
258         fdt_property_string(fdt, FIT_OS_PROP,
259                             genimg_get_os_short_name(params->os));
260         fdt_property_string(fdt, FIT_COMP_PROP,
261                             genimg_get_comp_short_name(params->comp));
262         fdt_property_u32(fdt, FIT_LOAD_PROP, params->addr);
263         fdt_property_u32(fdt, FIT_ENTRY_PROP, params->ep);
264
265         /*
266          * Put data last since it is large. SPL may only load the first part
267          * of the DT, so this way it can access all the above fields.
268          */
269         ret = fdt_property_file(params, fdt, FIT_DATA_PROP, params->datafile);
270         if (ret)
271                 return ret;
272         ret = add_hash_node(params, fdt);
273         if (ret)
274                 return ret;
275         fdt_end_node(fdt);
276
277         /* Now the device tree files if available */
278         upto = 0;
279         for (cont = params->content_head; cont; cont = cont->next) {
280                 if (cont->type != IH_TYPE_FLATDT)
281                         continue;
282                 typename = genimg_get_type_short_name(cont->type);
283                 snprintf(str, sizeof(str), "%s-%d", FIT_FDT_PROP, ++upto);
284                 fdt_begin_node(fdt, str);
285
286                 get_basename(str, sizeof(str), cont->fname);
287                 fdt_property_string(fdt, FIT_DESC_PROP, str);
288                 ret = fdt_property_file(params, fdt, FIT_DATA_PROP,
289                                         cont->fname);
290                 if (ret)
291                         return ret;
292                 fdt_property_string(fdt, FIT_TYPE_PROP, typename);
293                 fdt_property_string(fdt, FIT_ARCH_PROP,
294                                     genimg_get_arch_short_name(params->arch));
295                 fdt_property_string(fdt, FIT_COMP_PROP,
296                                     genimg_get_comp_short_name(IH_COMP_NONE));
297                 ret = add_hash_node(params, fdt);
298                 if (ret)
299                         return ret;
300                 fdt_end_node(fdt);
301         }
302
303         /* And a ramdisk file if available */
304         if (params->fit_ramdisk) {
305                 fdt_begin_node(fdt, FIT_RAMDISK_PROP "-1");
306
307                 fdt_property_string(fdt, FIT_TYPE_PROP, FIT_RAMDISK_PROP);
308                 fdt_property_string(fdt, FIT_OS_PROP,
309                                     genimg_get_os_short_name(params->os));
310                 fdt_property_string(fdt, FIT_ARCH_PROP,
311                                     genimg_get_arch_short_name(params->arch));
312
313                 ret = fdt_property_file(params, fdt, FIT_DATA_PROP,
314                                         params->fit_ramdisk);
315                 if (ret)
316                         return ret;
317                 ret = add_hash_node(params, fdt);
318                 if (ret)
319                         return ret;
320                 fdt_end_node(fdt);
321         }
322
323         fdt_end_node(fdt);
324
325         return 0;
326 }
327
328 /**
329  * fit_write_configs() - Write out a list of configurations to the FIT
330  *
331  * If there are device tree files, we include a configuration for each, which
332  * selects the main image (params->datafile) and its corresponding device
333  * tree file.
334  *
335  * Otherwise we just create a configuration with the main image in it.
336  */
337 static void fit_write_configs(struct image_tool_params *params, char *fdt)
338 {
339         struct content_info *cont;
340         const char *typename;
341         char str[100];
342         int upto;
343
344         fdt_begin_node(fdt, "configurations");
345         fdt_property_string(fdt, FIT_DEFAULT_PROP, "conf-1");
346
347         upto = 0;
348         for (cont = params->content_head; cont; cont = cont->next) {
349                 if (cont->type != IH_TYPE_FLATDT)
350                         continue;
351                 typename = genimg_get_type_short_name(cont->type);
352                 snprintf(str, sizeof(str), "conf-%d", ++upto);
353                 fdt_begin_node(fdt, str);
354
355                 get_basename(str, sizeof(str), cont->fname);
356                 fdt_property_string(fdt, FIT_DESC_PROP, str);
357
358                 typename = genimg_get_type_short_name(params->fit_image_type);
359                 snprintf(str, sizeof(str), "%s-1", typename);
360                 fdt_property_string(fdt, typename, str);
361                 fdt_property_string(fdt, FIT_LOADABLE_PROP, str);
362
363                 if (params->fit_ramdisk)
364                         fdt_property_string(fdt, FIT_RAMDISK_PROP,
365                                             FIT_RAMDISK_PROP "-1");
366
367                 snprintf(str, sizeof(str), FIT_FDT_PROP "-%d", upto);
368                 fdt_property_string(fdt, FIT_FDT_PROP, str);
369                 fdt_end_node(fdt);
370         }
371
372         if (!upto) {
373                 fdt_begin_node(fdt, "conf-1");
374                 typename = genimg_get_type_short_name(params->fit_image_type);
375                 snprintf(str, sizeof(str), "%s-1", typename);
376                 fdt_property_string(fdt, typename, str);
377
378                 if (params->fit_ramdisk)
379                         fdt_property_string(fdt, FIT_RAMDISK_PROP,
380                                             FIT_RAMDISK_PROP "-1");
381
382                 fdt_end_node(fdt);
383         }
384
385         fdt_end_node(fdt);
386 }
387
388 static int fit_build_fdt(struct image_tool_params *params, char *fdt, int size)
389 {
390         int ret;
391
392         ret = fdt_create(fdt, size);
393         if (ret)
394                 return ret;
395         fdt_finish_reservemap(fdt);
396         fdt_begin_node(fdt, "");
397         fdt_property_strf(fdt, FIT_DESC_PROP,
398                           "%s image with one or more FDT blobs",
399                           genimg_get_type_name(params->fit_image_type));
400         fdt_property_strf(fdt, "creator", "U-Boot mkimage %s", PLAIN_VERSION);
401         fdt_property_u32(fdt, "#address-cells", 1);
402         ret = fit_write_images(params, fdt);
403         if (ret)
404                 return ret;
405         fit_write_configs(params, fdt);
406         fdt_end_node(fdt);
407         ret = fdt_finish(fdt);
408         if (ret)
409                 return ret;
410
411         return fdt_totalsize(fdt);
412 }
413
414 static int fit_build(struct image_tool_params *params, const char *fname)
415 {
416         char *buf;
417         int size;
418         int ret;
419         int fd;
420
421         size = fit_calc_size(params);
422         if (size < 0)
423                 return -1;
424         buf = calloc(1, size);
425         if (!buf) {
426                 fprintf(stderr, "%s: Out of memory (%d bytes)\n",
427                         params->cmdname, size);
428                 return -1;
429         }
430         ret = fit_build_fdt(params, buf, size);
431         if (ret < 0) {
432                 fprintf(stderr, "%s: Failed to build FIT image\n",
433                         params->cmdname);
434                 goto err_buf;
435         }
436         size = ret;
437         fd = open(fname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666);
438         if (fd < 0) {
439                 fprintf(stderr, "%s: Can't open %s: %s\n",
440                         params->cmdname, fname, strerror(errno));
441                 goto err_buf;
442         }
443         ret = write(fd, buf, size);
444         if (ret != size) {
445                 fprintf(stderr, "%s: Can't write %s: %s\n",
446                         params->cmdname, fname, strerror(errno));
447                 goto err;
448         }
449         close(fd);
450         free(buf);
451
452         return 0;
453 err:
454         close(fd);
455 err_buf:
456         free(buf);
457         return -1;
458 }
459
460 /**
461  * fit_extract_data() - Move all data outside the FIT
462  *
463  * This takes a normal FIT file and removes all the 'data' properties from it.
464  * The data is placed in an area after the FIT so that it can be accessed
465  * using an offset into that area. The 'data' properties turn into
466  * 'data-offset' properties.
467  *
468  * This function cannot cope with FITs with 'data-offset' properties. All
469  * data must be in 'data' properties on entry.
470  */
471 static int fit_extract_data(struct image_tool_params *params, const char *fname)
472 {
473         void *buf = NULL;
474         int buf_ptr;
475         int fit_size, new_size;
476         int fd;
477         struct stat sbuf;
478         void *fdt;
479         int ret;
480         int images;
481         int node;
482         int image_number;
483         int align_size;
484
485         align_size = params->bl_len ? params->bl_len : 4;
486         fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false, false);
487         if (fd < 0)
488                 return -EIO;
489         fit_size = fdt_totalsize(fdt);
490
491         images = fdt_path_offset(fdt, FIT_IMAGES_PATH);
492         if (images < 0) {
493                 debug("%s: Cannot find /images node: %d\n", __func__, images);
494                 ret = -EINVAL;
495                 goto err_munmap;
496         }
497         image_number = fdtdec_get_child_count(fdt, images);
498
499         /*
500          * Allocate space to hold the image data we will extract,
501          * extral space allocate for image alignment to prevent overflow.
502          */
503         buf = calloc(1, fit_size + (align_size * image_number));
504         if (!buf) {
505                 ret = -ENOMEM;
506                 goto err_munmap;
507         }
508         buf_ptr = 0;
509
510         for (node = fdt_first_subnode(fdt, images);
511              node >= 0;
512              node = fdt_next_subnode(fdt, node)) {
513                 const char *data;
514                 int len;
515
516                 data = fdt_getprop(fdt, node, FIT_DATA_PROP, &len);
517                 if (!data)
518                         continue;
519                 memcpy(buf + buf_ptr, data, len);
520                 debug("Extracting data size %x\n", len);
521
522                 ret = fdt_delprop(fdt, node, FIT_DATA_PROP);
523                 if (ret) {
524                         ret = -EPERM;
525                         goto err_munmap;
526                 }
527                 if (params->external_offset > 0) {
528                         /* An external offset positions the data absolutely. */
529                         fdt_setprop_u32(fdt, node, FIT_DATA_POSITION_PROP,
530                                         params->external_offset + buf_ptr);
531                 } else {
532                         fdt_setprop_u32(fdt, node, FIT_DATA_OFFSET_PROP,
533                                         buf_ptr);
534                 }
535                 fdt_setprop_u32(fdt, node, FIT_DATA_SIZE_PROP, len);
536                 buf_ptr += ALIGN(len, align_size);
537         }
538
539         /* Pack the FDT and place the data after it */
540         fdt_pack(fdt);
541
542         new_size = fdt_totalsize(fdt);
543         new_size = ALIGN(new_size, align_size);
544         fdt_set_totalsize(fdt, new_size);
545         debug("Size reduced from %x to %x\n", fit_size, fdt_totalsize(fdt));
546         debug("External data size %x\n", buf_ptr);
547         munmap(fdt, sbuf.st_size);
548
549         if (ftruncate(fd, new_size)) {
550                 debug("%s: Failed to truncate file: %s\n", __func__,
551                       strerror(errno));
552                 ret = -EIO;
553                 goto err;
554         }
555
556         /* Check if an offset for the external data was set. */
557         if (params->external_offset > 0) {
558                 if (params->external_offset < new_size) {
559                         fprintf(stderr,
560                                 "External offset %x overlaps FIT length %x\n",
561                                 params->external_offset, new_size);
562                         ret = -EINVAL;
563                         goto err;
564                 }
565                 new_size = params->external_offset;
566         }
567         if (lseek(fd, new_size, SEEK_SET) < 0) {
568                 debug("%s: Failed to seek to end of file: %s\n", __func__,
569                       strerror(errno));
570                 ret = -EIO;
571                 goto err;
572         }
573         if (write(fd, buf, buf_ptr) != buf_ptr) {
574                 debug("%s: Failed to write external data to file %s\n",
575                       __func__, strerror(errno));
576                 ret = -EIO;
577                 goto err;
578         }
579         free(buf);
580         close(fd);
581         return 0;
582
583 err_munmap:
584         munmap(fdt, sbuf.st_size);
585 err:
586         free(buf);
587         close(fd);
588         return ret;
589 }
590
591 static int fit_import_data(struct image_tool_params *params, const char *fname)
592 {
593         void *fdt, *old_fdt;
594         int fit_size, new_size, size, data_base;
595         int fd;
596         struct stat sbuf;
597         int ret;
598         int images;
599         int node;
600
601         fd = mmap_fdt(params->cmdname, fname, 0, &old_fdt, &sbuf, false, false);
602         if (fd < 0)
603                 return -EIO;
604         fit_size = fdt_totalsize(old_fdt);
605         data_base = ALIGN(fit_size, 4);
606
607         /* Allocate space to hold the new FIT */
608         size = sbuf.st_size + 16384;
609         fdt = calloc(1, size);
610         if (!fdt) {
611                 fprintf(stderr, "%s: Failed to allocate memory (%d bytes)\n",
612                         __func__, size);
613                 ret = -ENOMEM;
614                 goto err_munmap;
615         }
616         ret = fdt_open_into(old_fdt, fdt, size);
617         if (ret) {
618                 debug("%s: Failed to expand FIT: %s\n", __func__,
619                       fdt_strerror(errno));
620                 ret = -EINVAL;
621                 goto err_munmap;
622         }
623
624         images = fdt_path_offset(fdt, FIT_IMAGES_PATH);
625         if (images < 0) {
626                 debug("%s: Cannot find /images node: %d\n", __func__, images);
627                 ret = -EINVAL;
628                 goto err_munmap;
629         }
630
631         for (node = fdt_first_subnode(fdt, images);
632              node >= 0;
633              node = fdt_next_subnode(fdt, node)) {
634                 int buf_ptr;
635                 int len;
636
637                 buf_ptr = fdtdec_get_int(fdt, node, "data-offset", -1);
638                 len = fdtdec_get_int(fdt, node, "data-size", -1);
639                 if (buf_ptr == -1 || len == -1)
640                         continue;
641                 debug("Importing data size %x\n", len);
642
643                 ret = fdt_setprop(fdt, node, "data",
644                                   old_fdt + data_base + buf_ptr, len);
645                 if (ret) {
646                         debug("%s: Failed to write property: %s\n", __func__,
647                               fdt_strerror(ret));
648                         ret = -EINVAL;
649                         goto err_munmap;
650                 }
651         }
652
653         munmap(old_fdt, sbuf.st_size);
654
655         /* Close the old fd so we can re-use it. */
656         close(fd);
657
658         /* Pack the FDT and place the data after it */
659         fdt_pack(fdt);
660
661         new_size = fdt_totalsize(fdt);
662         debug("Size expanded from %x to %x\n", fit_size, new_size);
663
664         fd = open(fname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666);
665         if (fd < 0) {
666                 fprintf(stderr, "%s: Can't open %s: %s\n",
667                         params->cmdname, fname, strerror(errno));
668                 ret = -EIO;
669                 goto err;
670         }
671         if (write(fd, fdt, new_size) != new_size) {
672                 debug("%s: Failed to write external data to file %s\n",
673                       __func__, strerror(errno));
674                 ret = -EIO;
675                 goto err;
676         }
677
678         free(fdt);
679         close(fd);
680         return 0;
681
682 err_munmap:
683         munmap(old_fdt, sbuf.st_size);
684 err:
685         free(fdt);
686         close(fd);
687         return ret;
688 }
689
690 /**
691  * fit_handle_file - main FIT file processing function
692  *
693  * fit_handle_file() runs dtc to convert .its to .itb, includes
694  * binary data, updates timestamp property and calculates hashes.
695  *
696  * datafile  - .its file
697  * imagefile - .itb file
698  *
699  * returns:
700  *     only on success, otherwise calls exit (EXIT_FAILURE);
701  */
702 static int fit_handle_file(struct image_tool_params *params)
703 {
704         char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
705         char bakfile[MKIMAGE_MAX_TMPFILE_LEN + 4] = {0};
706         char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
707         size_t size_inc;
708         int ret;
709
710         /* Flattened Image Tree (FIT) format  handling */
711         debug ("FIT format handling\n");
712
713         /* call dtc to include binary properties into the tmp file */
714         if (strlen (params->imagefile) +
715                 strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > sizeof (tmpfile)) {
716                 fprintf (stderr, "%s: Image file name (%s) too long, "
717                                 "can't create tmpfile.\n",
718                                 params->imagefile, params->cmdname);
719                 return (EXIT_FAILURE);
720         }
721         sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
722
723         /* We either compile the source file, or use the existing FIT image */
724         if (params->auto_its) {
725                 if (fit_build(params, tmpfile)) {
726                         fprintf(stderr, "%s: failed to build FIT\n",
727                                 params->cmdname);
728                         return EXIT_FAILURE;
729                 }
730                 *cmd = '\0';
731         } else if (params->datafile) {
732                 /* dtc -I dts -O dtb -p 500 -o tmpfile datafile */
733                 snprintf(cmd, sizeof(cmd), "%s %s -o \"%s\" \"%s\"",
734                          MKIMAGE_DTC, params->dtc, tmpfile, params->datafile);
735                 debug("Trying to execute \"%s\"\n", cmd);
736         } else {
737                 snprintf(cmd, sizeof(cmd), "cp \"%s\" \"%s\"",
738                          params->imagefile, tmpfile);
739         }
740         if (strlen(cmd) >= MKIMAGE_MAX_DTC_CMDLINE_LEN - 1) {
741                 fprintf(stderr, "WARNING: command-line for FIT creation might be truncated and will probably fail.\n");
742         }
743
744         if (*cmd && system(cmd) == -1) {
745                 fprintf (stderr, "%s: system(%s) failed: %s\n",
746                                 params->cmdname, cmd, strerror(errno));
747                 goto err_system;
748         }
749
750         /* Move the data so it is internal to the FIT, if needed */
751         ret = fit_import_data(params, tmpfile);
752         if (ret)
753                 goto err_system;
754
755         /*
756          * Copy the tmpfile to bakfile, then in the following loop
757          * we copy bakfile to tmpfile. So we always start from the
758          * beginning.
759          */
760         sprintf(bakfile, "%s%s", tmpfile, ".bak");
761         rename(tmpfile, bakfile);
762
763         /*
764          * Set hashes for images in the blob. Unfortunately we may need more
765          * space in either FDT, so keep trying until we succeed.
766          *
767          * Note: this is pretty inefficient for signing, since we must
768          * calculate the signature every time. It would be better to calculate
769          * all the data and then store it in a separate step. However, this
770          * would be considerably more complex to implement. Generally a few
771          * steps of this loop is enough to sign with several keys.
772          */
773         for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) {
774                 if (copyfile(bakfile, tmpfile) < 0) {
775                         printf("Can't copy %s to %s\n", bakfile, tmpfile);
776                         ret = -EIO;
777                         break;
778                 }
779                 ret = fit_add_file_data(params, size_inc, tmpfile);
780                 if (!ret || ret != -ENOSPC)
781                         break;
782         }
783
784         if (ret) {
785                 fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n",
786                         params->cmdname, ret);
787                 goto err_system;
788         }
789
790         /* Move the data so it is external to the FIT, if requested */
791         if (params->external_data) {
792                 ret = fit_extract_data(params, tmpfile);
793                 if (ret)
794                         goto err_system;
795         }
796
797         if (rename (tmpfile, params->imagefile) == -1) {
798                 fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
799                                 params->cmdname, tmpfile, params->imagefile,
800                                 strerror (errno));
801                 unlink (tmpfile);
802                 unlink(bakfile);
803                 unlink (params->imagefile);
804                 return EXIT_FAILURE;
805         }
806         unlink(bakfile);
807         return EXIT_SUCCESS;
808
809 err_system:
810         unlink(tmpfile);
811         unlink(bakfile);
812         return -1;
813 }
814
815 /**
816  * fit_image_extract - extract a FIT component image
817  * @fit: pointer to the FIT format image header
818  * @image_noffset: offset of the component image node
819  * @file_name: name of the file to store the FIT sub-image
820  *
821  * returns:
822  *     zero in case of success or a negative value if fail.
823  */
824 static int fit_image_extract(
825         const void *fit,
826         int image_noffset,
827         const char *file_name)
828 {
829         const void *file_data;
830         size_t file_size = 0;
831         int ret;
832
833         /* get the data address and size of component at offset "image_noffset" */
834         ret = fit_image_get_data_and_size(fit, image_noffset, &file_data, &file_size);
835         if (ret) {
836                 fprintf(stderr, "Could not get component information\n");
837                 return ret;
838         }
839
840         /* save the "file_data" into the file specified by "file_name" */
841         return imagetool_save_subimage(file_name, (ulong) file_data, file_size);
842 }
843
844 /**
845  * fit_extract_contents - retrieve a sub-image component from the FIT image
846  * @ptr: pointer to the FIT format image header
847  * @params: command line parameters
848  *
849  * returns:
850  *     zero in case of success or a negative value if fail.
851  */
852 static int fit_extract_contents(void *ptr, struct image_tool_params *params)
853 {
854         int images_noffset;
855         int noffset;
856         int ndepth;
857         const void *fit = ptr;
858         int count = 0;
859         const char *p;
860
861         /* Indent string is defined in header image.h */
862         p = IMAGE_INDENT_STRING;
863
864         /* Find images parent node offset */
865         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
866         if (images_noffset < 0) {
867                 printf("Can't find images parent node '%s' (%s)\n",
868                        FIT_IMAGES_PATH, fdt_strerror(images_noffset));
869                 return -1;
870         }
871
872         /* Avoid any overrun */
873         count = fit_get_subimage_count(fit, images_noffset);
874         if ((params->pflag < 0) || (count <= params->pflag)) {
875                 printf("No such component at '%d'\n", params->pflag);
876                 return -1;
877         }
878
879         /* Process its subnodes, extract the desired component from image */
880         for (ndepth = 0, count = 0,
881                 noffset = fdt_next_node(fit, images_noffset, &ndepth);
882                 (noffset >= 0) && (ndepth > 0);
883                 noffset = fdt_next_node(fit, noffset, &ndepth)) {
884                 if (ndepth == 1) {
885                         /*
886                          * Direct child node of the images parent node,
887                          * i.e. component image node.
888                          */
889                         if (params->pflag == count) {
890                                 printf("Extracted:\n%s Image %u (%s)\n", p,
891                                        count, fit_get_name(fit, noffset, NULL));
892
893                                 fit_image_print(fit, noffset, p);
894
895                                 return fit_image_extract(fit, noffset,
896                                                 params->outfile);
897                         }
898
899                         count++;
900                 }
901         }
902
903         return 0;
904 }
905
906 static int fit_check_params(struct image_tool_params *params)
907 {
908         if (params->auto_its)
909                 return 0;
910         return  ((params->dflag && params->fflag) ||
911                  (params->fflag && params->lflag) ||
912                  (params->lflag && params->dflag));
913 }
914
915 U_BOOT_IMAGE_TYPE(
916         fitimage,
917         "FIT Image support",
918         sizeof(struct legacy_img_hdr),
919         (void *)&header,
920         fit_check_params,
921         fit_verify_header,
922         fit_print_contents,
923         NULL,
924         fit_extract_contents,
925         fit_check_image_types,
926         fit_handle_file,
927         NULL /* FIT images use DTB header */
928 );