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