image: Remove remaining #ifdefs in image-fit.c
[platform/kernel/u-boot.git] / common / image-fit.c
1 /*
2  * Copyright (c) 2013, Google Inc.
3  *
4  * (C) Copyright 2008 Semihalf
5  *
6  * (C) Copyright 2000-2006
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #ifdef USE_HOSTCC
29 #include "mkimage.h"
30 #include <image.h>
31 #include <time.h>
32 #else
33 #include <common.h>
34 #endif /* !USE_HOSTCC*/
35
36 #include <bootstage.h>
37 #include <sha1.h>
38 #include <u-boot/crc.h>
39 #include <u-boot/md5.h>
40
41 /*****************************************************************************/
42 /* New uImage format routines */
43 /*****************************************************************************/
44 #ifndef USE_HOSTCC
45 static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
46                 ulong *addr, const char **name)
47 {
48         const char *sep;
49
50         *addr = addr_curr;
51         *name = NULL;
52
53         sep = strchr(spec, sepc);
54         if (sep) {
55                 if (sep - spec > 0)
56                         *addr = simple_strtoul(spec, NULL, 16);
57
58                 *name = sep + 1;
59                 return 1;
60         }
61
62         return 0;
63 }
64
65 /**
66  * fit_parse_conf - parse FIT configuration spec
67  * @spec: input string, containing configuration spec
68  * @add_curr: current image address (to be used as a possible default)
69  * @addr: pointer to a ulong variable, will hold FIT image address of a given
70  * configuration
71  * @conf_name double pointer to a char, will hold pointer to a configuration
72  * unit name
73  *
74  * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
75  * where <addr> is a FIT image address that contains configuration
76  * with a <conf> unit name.
77  *
78  * Address part is optional, and if omitted default add_curr will
79  * be used instead.
80  *
81  * returns:
82  *     1 if spec is a valid configuration string,
83  *     addr and conf_name are set accordingly
84  *     0 otherwise
85  */
86 int fit_parse_conf(const char *spec, ulong addr_curr,
87                 ulong *addr, const char **conf_name)
88 {
89         return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
90 }
91
92 /**
93  * fit_parse_subimage - parse FIT subimage spec
94  * @spec: input string, containing subimage spec
95  * @add_curr: current image address (to be used as a possible default)
96  * @addr: pointer to a ulong variable, will hold FIT image address of a given
97  * subimage
98  * @image_name: double pointer to a char, will hold pointer to a subimage name
99  *
100  * fit_parse_subimage() expects subimage spec in the for of
101  * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
102  * subimage with a <subimg> unit name.
103  *
104  * Address part is optional, and if omitted default add_curr will
105  * be used instead.
106  *
107  * returns:
108  *     1 if spec is a valid subimage string,
109  *     addr and image_name are set accordingly
110  *     0 otherwise
111  */
112 int fit_parse_subimage(const char *spec, ulong addr_curr,
113                 ulong *addr, const char **image_name)
114 {
115         return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
116 }
117 #endif /* !USE_HOSTCC */
118
119 static void fit_get_debug(const void *fit, int noffset,
120                 char *prop_name, int err)
121 {
122         debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
123               prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
124               fdt_strerror(err));
125 }
126
127 /**
128  * fit_print_contents - prints out the contents of the FIT format image
129  * @fit: pointer to the FIT format image header
130  * @p: pointer to prefix string
131  *
132  * fit_print_contents() formats a multi line FIT image contents description.
133  * The routine prints out FIT image properties (root node level) follwed by
134  * the details of each component image.
135  *
136  * returns:
137  *     no returned results
138  */
139 void fit_print_contents(const void *fit)
140 {
141         char *desc;
142         char *uname;
143         int images_noffset;
144         int confs_noffset;
145         int noffset;
146         int ndepth;
147         int count = 0;
148         int ret;
149         const char *p;
150         time_t timestamp;
151
152         /* Indent string is defined in header image.h */
153         p = IMAGE_INDENT_STRING;
154
155         /* Root node properties */
156         ret = fit_get_desc(fit, 0, &desc);
157         printf("%sFIT description: ", p);
158         if (ret)
159                 printf("unavailable\n");
160         else
161                 printf("%s\n", desc);
162
163         if (IMAGE_ENABLE_TIMESTAMP) {
164                 ret = fit_get_timestamp(fit, 0, &timestamp);
165                 printf("%sCreated:         ", p);
166                 if (ret)
167                         printf("unavailable\n");
168                 else
169                         genimg_print_time(timestamp);
170         }
171
172         /* Find images parent node offset */
173         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
174         if (images_noffset < 0) {
175                 printf("Can't find images parent node '%s' (%s)\n",
176                        FIT_IMAGES_PATH, fdt_strerror(images_noffset));
177                 return;
178         }
179
180         /* Process its subnodes, print out component images details */
181         for (ndepth = 0, count = 0,
182                 noffset = fdt_next_node(fit, images_noffset, &ndepth);
183              (noffset >= 0) && (ndepth > 0);
184              noffset = fdt_next_node(fit, noffset, &ndepth)) {
185                 if (ndepth == 1) {
186                         /*
187                          * Direct child node of the images parent node,
188                          * i.e. component image node.
189                          */
190                         printf("%s Image %u (%s)\n", p, count++,
191                                fit_get_name(fit, noffset, NULL));
192
193                         fit_image_print(fit, noffset, p);
194                 }
195         }
196
197         /* Find configurations parent node offset */
198         confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
199         if (confs_noffset < 0) {
200                 debug("Can't get configurations parent node '%s' (%s)\n",
201                       FIT_CONFS_PATH, fdt_strerror(confs_noffset));
202                 return;
203         }
204
205         /* get default configuration unit name from default property */
206         uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
207         if (uname)
208                 printf("%s Default Configuration: '%s'\n", p, uname);
209
210         /* Process its subnodes, print out configurations details */
211         for (ndepth = 0, count = 0,
212                 noffset = fdt_next_node(fit, confs_noffset, &ndepth);
213              (noffset >= 0) && (ndepth > 0);
214              noffset = fdt_next_node(fit, noffset, &ndepth)) {
215                 if (ndepth == 1) {
216                         /*
217                          * Direct child node of the configurations parent node,
218                          * i.e. configuration node.
219                          */
220                         printf("%s Configuration %u (%s)\n", p, count++,
221                                fit_get_name(fit, noffset, NULL));
222
223                         fit_conf_print(fit, noffset, p);
224                 }
225         }
226 }
227
228 /**
229  * fit_image_print_data() - prints out the hash node details
230  * @fit: pointer to the FIT format image header
231  * @noffset: offset of the hash node
232  * @p: pointer to prefix string
233  *
234  * fit_image_print_data() lists properies for the processed hash node
235  *
236  * returns:
237  *     no returned results
238  */
239 static void fit_image_print_data(const void *fit, int noffset, const char *p)
240 {
241         char *algo;
242         uint8_t *value;
243         int value_len;
244         int i, ret;
245
246         /*
247          * Check subnode name, must be equal to "hash".
248          * Multiple hash nodes require unique unit node
249          * names, e.g. hash@1, hash@2, etc.
250          */
251         if (strncmp(fit_get_name(fit, noffset, NULL),
252                     FIT_HASH_NODENAME,
253                     strlen(FIT_HASH_NODENAME)) != 0)
254                 return;
255
256         debug("%s  Hash node:    '%s'\n", p,
257               fit_get_name(fit, noffset, NULL));
258
259         printf("%s  Hash algo:    ", p);
260         if (fit_image_hash_get_algo(fit, noffset, &algo)) {
261                 printf("invalid/unsupported\n");
262                 return;
263         }
264         printf("%s\n", algo);
265
266         ret = fit_image_hash_get_value(fit, noffset, &value,
267                                         &value_len);
268         printf("%s  Hash value:   ", p);
269         if (ret) {
270                 printf("unavailable\n");
271         } else {
272                 for (i = 0; i < value_len; i++)
273                         printf("%02x", value[i]);
274                 printf("\n");
275         }
276
277         debug("%s  Hash len:     %d\n", p, value_len);
278 }
279
280 /**
281  * fit_image_print_verification_data() - prints out the hash/signature details
282  * @fit: pointer to the FIT format image header
283  * @noffset: offset of the hash or signature node
284  * @p: pointer to prefix string
285  *
286  * This lists properies for the processed hash node
287  *
288  * returns:
289  *     no returned results
290  */
291 static void fit_image_print_verification_data(const void *fit, int noffset,
292                                        const char *p)
293 {
294         const char *name;
295
296         /*
297          * Check subnode name, must be equal to "hash" or "signature".
298          * Multiple hash/signature nodes require unique unit node
299          * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
300          */
301         name = fit_get_name(fit, noffset, NULL);
302         if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
303                 fit_image_print_data(fit, noffset, p);
304 }
305
306 /**
307  * fit_image_print - prints out the FIT component image details
308  * @fit: pointer to the FIT format image header
309  * @image_noffset: offset of the component image node
310  * @p: pointer to prefix string
311  *
312  * fit_image_print() lists all mandatory properies for the processed component
313  * image. If present, hash nodes are printed out as well. Load
314  * address for images of type firmware is also printed out. Since the load
315  * address is not mandatory for firmware images, it will be output as
316  * "unavailable" when not present.
317  *
318  * returns:
319  *     no returned results
320  */
321 void fit_image_print(const void *fit, int image_noffset, const char *p)
322 {
323         char *desc;
324         uint8_t type, arch, os, comp;
325         size_t size;
326         ulong load, entry;
327         const void *data;
328         int noffset;
329         int ndepth;
330         int ret;
331
332         /* Mandatory properties */
333         ret = fit_get_desc(fit, image_noffset, &desc);
334         printf("%s  Description:  ", p);
335         if (ret)
336                 printf("unavailable\n");
337         else
338                 printf("%s\n", desc);
339
340         fit_image_get_type(fit, image_noffset, &type);
341         printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
342
343         fit_image_get_comp(fit, image_noffset, &comp);
344         printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
345
346         ret = fit_image_get_data(fit, image_noffset, &data, &size);
347
348 #ifndef USE_HOSTCC
349         printf("%s  Data Start:   ", p);
350         if (ret)
351                 printf("unavailable\n");
352         else
353                 printf("0x%08lx\n", (ulong)data);
354 #endif
355
356         printf("%s  Data Size:    ", p);
357         if (ret)
358                 printf("unavailable\n");
359         else
360                 genimg_print_size(size);
361
362         /* Remaining, type dependent properties */
363         if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
364             (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
365             (type == IH_TYPE_FLATDT)) {
366                 fit_image_get_arch(fit, image_noffset, &arch);
367                 printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
368         }
369
370         if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
371                 fit_image_get_os(fit, image_noffset, &os);
372                 printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
373         }
374
375         if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
376             (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
377                 ret = fit_image_get_load(fit, image_noffset, &load);
378                 printf("%s  Load Address: ", p);
379                 if (ret)
380                         printf("unavailable\n");
381                 else
382                         printf("0x%08lx\n", load);
383         }
384
385         if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
386             (type == IH_TYPE_RAMDISK)) {
387                 fit_image_get_entry(fit, image_noffset, &entry);
388                 printf("%s  Entry Point:  ", p);
389                 if (ret)
390                         printf("unavailable\n");
391                 else
392                         printf("0x%08lx\n", entry);
393         }
394
395         /* Process all hash subnodes of the component image node */
396         for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
397              (noffset >= 0) && (ndepth > 0);
398              noffset = fdt_next_node(fit, noffset, &ndepth)) {
399                 if (ndepth == 1) {
400                         /* Direct child node of the component image node */
401                         fit_image_print_verification_data(fit, noffset, p);
402                 }
403         }
404 }
405
406 /**
407  * fit_get_desc - get node description property
408  * @fit: pointer to the FIT format image header
409  * @noffset: node offset
410  * @desc: double pointer to the char, will hold pointer to the descrption
411  *
412  * fit_get_desc() reads description property from a given node, if
413  * description is found pointer to it is returened in third call argument.
414  *
415  * returns:
416  *     0, on success
417  *     -1, on failure
418  */
419 int fit_get_desc(const void *fit, int noffset, char **desc)
420 {
421         int len;
422
423         *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
424         if (*desc == NULL) {
425                 fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
426                 return -1;
427         }
428
429         return 0;
430 }
431
432 /**
433  * fit_get_timestamp - get node timestamp property
434  * @fit: pointer to the FIT format image header
435  * @noffset: node offset
436  * @timestamp: pointer to the time_t, will hold read timestamp
437  *
438  * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
439  * is found and has a correct size its value is retured in third call
440  * argument.
441  *
442  * returns:
443  *     0, on success
444  *     -1, on property read failure
445  *     -2, on wrong timestamp size
446  */
447 int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
448 {
449         int len;
450         const void *data;
451
452         data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
453         if (data == NULL) {
454                 fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
455                 return -1;
456         }
457         if (len != sizeof(uint32_t)) {
458                 debug("FIT timestamp with incorrect size of (%u)\n", len);
459                 return -2;
460         }
461
462         *timestamp = uimage_to_cpu(*((uint32_t *)data));
463         return 0;
464 }
465
466 /**
467  * fit_image_get_node - get node offset for component image of a given unit name
468  * @fit: pointer to the FIT format image header
469  * @image_uname: component image node unit name
470  *
471  * fit_image_get_node() finds a component image (withing the '/images'
472  * node) of a provided unit name. If image is found its node offset is
473  * returned to the caller.
474  *
475  * returns:
476  *     image node offset when found (>=0)
477  *     negative number on failure (FDT_ERR_* code)
478  */
479 int fit_image_get_node(const void *fit, const char *image_uname)
480 {
481         int noffset, images_noffset;
482
483         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
484         if (images_noffset < 0) {
485                 debug("Can't find images parent node '%s' (%s)\n",
486                       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
487                 return images_noffset;
488         }
489
490         noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
491         if (noffset < 0) {
492                 debug("Can't get node offset for image unit name: '%s' (%s)\n",
493                       image_uname, fdt_strerror(noffset));
494         }
495
496         return noffset;
497 }
498
499 /**
500  * fit_image_get_os - get os id for a given component image node
501  * @fit: pointer to the FIT format image header
502  * @noffset: component image node offset
503  * @os: pointer to the uint8_t, will hold os numeric id
504  *
505  * fit_image_get_os() finds os property in a given component image node.
506  * If the property is found, its (string) value is translated to the numeric
507  * id which is returned to the caller.
508  *
509  * returns:
510  *     0, on success
511  *     -1, on failure
512  */
513 int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
514 {
515         int len;
516         const void *data;
517
518         /* Get OS name from property data */
519         data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
520         if (data == NULL) {
521                 fit_get_debug(fit, noffset, FIT_OS_PROP, len);
522                 *os = -1;
523                 return -1;
524         }
525
526         /* Translate OS name to id */
527         *os = genimg_get_os_id(data);
528         return 0;
529 }
530
531 /**
532  * fit_image_get_arch - get arch id for a given component image node
533  * @fit: pointer to the FIT format image header
534  * @noffset: component image node offset
535  * @arch: pointer to the uint8_t, will hold arch numeric id
536  *
537  * fit_image_get_arch() finds arch property in a given component image node.
538  * If the property is found, its (string) value is translated to the numeric
539  * id which is returned to the caller.
540  *
541  * returns:
542  *     0, on success
543  *     -1, on failure
544  */
545 int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
546 {
547         int len;
548         const void *data;
549
550         /* Get architecture name from property data */
551         data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
552         if (data == NULL) {
553                 fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
554                 *arch = -1;
555                 return -1;
556         }
557
558         /* Translate architecture name to id */
559         *arch = genimg_get_arch_id(data);
560         return 0;
561 }
562
563 /**
564  * fit_image_get_type - get type id for a given component image node
565  * @fit: pointer to the FIT format image header
566  * @noffset: component image node offset
567  * @type: pointer to the uint8_t, will hold type numeric id
568  *
569  * fit_image_get_type() finds type property in a given component image node.
570  * If the property is found, its (string) value is translated to the numeric
571  * id which is returned to the caller.
572  *
573  * returns:
574  *     0, on success
575  *     -1, on failure
576  */
577 int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
578 {
579         int len;
580         const void *data;
581
582         /* Get image type name from property data */
583         data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
584         if (data == NULL) {
585                 fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
586                 *type = -1;
587                 return -1;
588         }
589
590         /* Translate image type name to id */
591         *type = genimg_get_type_id(data);
592         return 0;
593 }
594
595 /**
596  * fit_image_get_comp - get comp id for a given component image node
597  * @fit: pointer to the FIT format image header
598  * @noffset: component image node offset
599  * @comp: pointer to the uint8_t, will hold comp numeric id
600  *
601  * fit_image_get_comp() finds comp property in a given component image node.
602  * If the property is found, its (string) value is translated to the numeric
603  * id which is returned to the caller.
604  *
605  * returns:
606  *     0, on success
607  *     -1, on failure
608  */
609 int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
610 {
611         int len;
612         const void *data;
613
614         /* Get compression name from property data */
615         data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
616         if (data == NULL) {
617                 fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
618                 *comp = -1;
619                 return -1;
620         }
621
622         /* Translate compression name to id */
623         *comp = genimg_get_comp_id(data);
624         return 0;
625 }
626
627 /**
628  * fit_image_get_load() - get load addr property for given component image node
629  * @fit: pointer to the FIT format image header
630  * @noffset: component image node offset
631  * @load: pointer to the uint32_t, will hold load address
632  *
633  * fit_image_get_load() finds load address property in a given component
634  * image node. If the property is found, its value is returned to the caller.
635  *
636  * returns:
637  *     0, on success
638  *     -1, on failure
639  */
640 int fit_image_get_load(const void *fit, int noffset, ulong *load)
641 {
642         int len;
643         const uint32_t *data;
644
645         data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len);
646         if (data == NULL) {
647                 fit_get_debug(fit, noffset, FIT_LOAD_PROP, len);
648                 return -1;
649         }
650
651         *load = uimage_to_cpu(*data);
652         return 0;
653 }
654
655 /**
656  * fit_image_get_entry() - get entry point address property
657  * @fit: pointer to the FIT format image header
658  * @noffset: component image node offset
659  * @entry: pointer to the uint32_t, will hold entry point address
660  *
661  * This gets the entry point address property for a given component image
662  * node.
663  *
664  * fit_image_get_entry() finds entry point address property in a given
665  * component image node.  If the property is found, its value is returned
666  * to the caller.
667  *
668  * returns:
669  *     0, on success
670  *     -1, on failure
671  */
672 int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
673 {
674         int len;
675         const uint32_t *data;
676
677         data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len);
678         if (data == NULL) {
679                 fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len);
680                 return -1;
681         }
682
683         *entry = uimage_to_cpu(*data);
684         return 0;
685 }
686
687 /**
688  * fit_image_get_data - get data property and its size for a given component image node
689  * @fit: pointer to the FIT format image header
690  * @noffset: component image node offset
691  * @data: double pointer to void, will hold data property's data address
692  * @size: pointer to size_t, will hold data property's data size
693  *
694  * fit_image_get_data() finds data property in a given component image node.
695  * If the property is found its data start address and size are returned to
696  * the caller.
697  *
698  * returns:
699  *     0, on success
700  *     -1, on failure
701  */
702 int fit_image_get_data(const void *fit, int noffset,
703                 const void **data, size_t *size)
704 {
705         int len;
706
707         *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
708         if (*data == NULL) {
709                 fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
710                 *size = 0;
711                 return -1;
712         }
713
714         *size = len;
715         return 0;
716 }
717
718 /**
719  * fit_image_hash_get_algo - get hash algorithm name
720  * @fit: pointer to the FIT format image header
721  * @noffset: hash node offset
722  * @algo: double pointer to char, will hold pointer to the algorithm name
723  *
724  * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
725  * If the property is found its data start address is returned to the caller.
726  *
727  * returns:
728  *     0, on success
729  *     -1, on failure
730  */
731 int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
732 {
733         int len;
734
735         *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
736         if (*algo == NULL) {
737                 fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
738                 return -1;
739         }
740
741         return 0;
742 }
743
744 /**
745  * fit_image_hash_get_value - get hash value and length
746  * @fit: pointer to the FIT format image header
747  * @noffset: hash node offset
748  * @value: double pointer to uint8_t, will hold address of a hash value data
749  * @value_len: pointer to an int, will hold hash data length
750  *
751  * fit_image_hash_get_value() finds hash value property in a given hash node.
752  * If the property is found its data start address and size are returned to
753  * the caller.
754  *
755  * returns:
756  *     0, on success
757  *     -1, on failure
758  */
759 int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
760                                 int *value_len)
761 {
762         int len;
763
764         *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
765         if (*value == NULL) {
766                 fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
767                 *value_len = 0;
768                 return -1;
769         }
770
771         *value_len = len;
772         return 0;
773 }
774
775 /**
776  * fit_image_hash_get_ignore - get hash ignore flag
777  * @fit: pointer to the FIT format image header
778  * @noffset: hash node offset
779  * @ignore: pointer to an int, will hold hash ignore flag
780  *
781  * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
782  * If the property is found and non-zero, the hash algorithm is not verified by
783  * u-boot automatically.
784  *
785  * returns:
786  *     0, on ignore not found
787  *     value, on ignore found
788  */
789 static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
790 {
791         int len;
792         int *value;
793
794         value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
795         if (value == NULL || len != sizeof(int))
796                 *ignore = 0;
797         else
798                 *ignore = *value;
799
800         return 0;
801 }
802
803 /**
804  * fit_set_timestamp - set node timestamp property
805  * @fit: pointer to the FIT format image header
806  * @noffset: node offset
807  * @timestamp: timestamp value to be set
808  *
809  * fit_set_timestamp() attempts to set timestamp property in the requested
810  * node and returns operation status to the caller.
811  *
812  * returns:
813  *     0, on success
814  *     -1, on property read failure
815  */
816 int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
817 {
818         uint32_t t;
819         int ret;
820
821         t = cpu_to_uimage(timestamp);
822         ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
823                                 sizeof(uint32_t));
824         if (ret) {
825                 printf("Can't set '%s' property for '%s' node (%s)\n",
826                        FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
827                        fdt_strerror(ret));
828                 return -1;
829         }
830
831         return 0;
832 }
833
834 /**
835  * calculate_hash - calculate and return hash for provided input data
836  * @data: pointer to the input data
837  * @data_len: data length
838  * @algo: requested hash algorithm
839  * @value: pointer to the char, will hold hash value data (caller must
840  * allocate enough free space)
841  * value_len: length of the calculated hash
842  *
843  * calculate_hash() computes input data hash according to the requested
844  * algorithm.
845  * Resulting hash value is placed in caller provided 'value' buffer, length
846  * of the calculated hash is returned via value_len pointer argument.
847  *
848  * returns:
849  *     0, on success
850  *    -1, when algo is unsupported
851  */
852 int calculate_hash(const void *data, int data_len, const char *algo,
853                         uint8_t *value, int *value_len)
854 {
855         if (strcmp(algo, "crc32") == 0) {
856                 *((uint32_t *)value) = crc32_wd(0, data, data_len,
857                                                         CHUNKSZ_CRC32);
858                 *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
859                 *value_len = 4;
860         } else if (strcmp(algo, "sha1") == 0) {
861                 sha1_csum_wd((unsigned char *)data, data_len,
862                              (unsigned char *)value, CHUNKSZ_SHA1);
863                 *value_len = 20;
864         } else if (strcmp(algo, "md5") == 0) {
865                 md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
866                 *value_len = 16;
867         } else {
868                 debug("Unsupported hash alogrithm\n");
869                 return -1;
870         }
871         return 0;
872 }
873
874 static int fit_image_check_hash(const void *fit, int noffset, const void *data,
875                                 size_t size, char **err_msgp)
876 {
877         uint8_t value[FIT_MAX_HASH_LEN];
878         int value_len;
879         char *algo;
880         uint8_t *fit_value;
881         int fit_value_len;
882         int ignore;
883
884         *err_msgp = NULL;
885
886         if (fit_image_hash_get_algo(fit, noffset, &algo)) {
887                 *err_msgp = "Can't get hash algo property";
888                 return -1;
889         }
890         printf("%s", algo);
891
892         if (IMAGE_ENABLE_IGNORE) {
893                 fit_image_hash_get_ignore(fit, noffset, &ignore);
894                 if (ignore) {
895                         printf("-skipped ");
896                         return 0;
897                 }
898         }
899
900         if (fit_image_hash_get_value(fit, noffset, &fit_value,
901                                      &fit_value_len)) {
902                 *err_msgp = "Can't get hash value property";
903                 return -1;
904         }
905
906         if (calculate_hash(data, size, algo, value, &value_len)) {
907                 *err_msgp = "Unsupported hash algorithm";
908                 return -1;
909         }
910
911         if (value_len != fit_value_len) {
912                 *err_msgp = "Bad hash value len";
913                 return -1;
914         } else if (memcmp(value, fit_value, value_len) != 0) {
915                 *err_msgp = "Bad hash value";
916                 return -1;
917         }
918
919         return 0;
920 }
921
922 /**
923  * fit_image_verify - verify data intergity
924  * @fit: pointer to the FIT format image header
925  * @image_noffset: component image node offset
926  *
927  * fit_image_verify() goes over component image hash nodes,
928  * re-calculates each data hash and compares with the value stored in hash
929  * node.
930  *
931  * returns:
932  *     1, if all hashes are valid
933  *     0, otherwise (or on error)
934  */
935 int fit_image_verify(const void *fit, int image_noffset)
936 {
937         const void      *data;
938         size_t          size;
939         int             noffset;
940         char            *err_msg = "";
941
942         /* Get image data and data length */
943         if (fit_image_get_data(fit, image_noffset, &data, &size)) {
944                 err_msg = "Can't get image data/size";
945                 return 0;
946         }
947
948         /* Process all hash subnodes of the component image node */
949         for (noffset = fdt_first_subnode(fit, image_noffset);
950              noffset >= 0;
951              noffset = fdt_next_subnode(fit, noffset)) {
952                 const char *name = fit_get_name(fit, noffset, NULL);
953
954                 /*
955                  * Check subnode name, must be equal to "hash".
956                  * Multiple hash nodes require unique unit node
957                  * names, e.g. hash@1, hash@2, etc.
958                  */
959                 if (!strncmp(name, FIT_HASH_NODENAME,
960                              strlen(FIT_HASH_NODENAME))) {
961                         if (fit_image_check_hash(fit, noffset, data, size,
962                                                  &err_msg))
963                                 goto error;
964                         puts("+ ");
965                 }
966         }
967
968         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
969                 err_msg = "Corrupted or truncated tree";
970                 goto error;
971         }
972
973         return 1;
974
975 error:
976         printf(" error!\n%s for '%s' hash node in '%s' image node\n",
977                err_msg, fit_get_name(fit, noffset, NULL),
978                fit_get_name(fit, image_noffset, NULL));
979         return 0;
980 }
981
982 /**
983  * fit_all_image_verify - verify data intergity for all images
984  * @fit: pointer to the FIT format image header
985  *
986  * fit_all_image_verify() goes over all images in the FIT and
987  * for every images checks if all it's hashes are valid.
988  *
989  * returns:
990  *     1, if all hashes of all images are valid
991  *     0, otherwise (or on error)
992  */
993 int fit_all_image_verify(const void *fit)
994 {
995         int images_noffset;
996         int noffset;
997         int ndepth;
998         int count;
999
1000         /* Find images parent node offset */
1001         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1002         if (images_noffset < 0) {
1003                 printf("Can't find images parent node '%s' (%s)\n",
1004                        FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1005                 return 0;
1006         }
1007
1008         /* Process all image subnodes, check hashes for each */
1009         printf("## Checking hash(es) for FIT Image at %08lx ...\n",
1010                (ulong)fit);
1011         for (ndepth = 0, count = 0,
1012              noffset = fdt_next_node(fit, images_noffset, &ndepth);
1013                         (noffset >= 0) && (ndepth > 0);
1014                         noffset = fdt_next_node(fit, noffset, &ndepth)) {
1015                 if (ndepth == 1) {
1016                         /*
1017                          * Direct child node of the images parent node,
1018                          * i.e. component image node.
1019                          */
1020                         printf("   Hash(es) for Image %u (%s): ", count++,
1021                                fit_get_name(fit, noffset, NULL));
1022
1023                         if (!fit_image_verify(fit, noffset))
1024                                 return 0;
1025                         printf("\n");
1026                 }
1027         }
1028         return 1;
1029 }
1030
1031 /**
1032  * fit_image_check_os - check whether image node is of a given os type
1033  * @fit: pointer to the FIT format image header
1034  * @noffset: component image node offset
1035  * @os: requested image os
1036  *
1037  * fit_image_check_os() reads image os property and compares its numeric
1038  * id with the requested os. Comparison result is returned to the caller.
1039  *
1040  * returns:
1041  *     1 if image is of given os type
1042  *     0 otherwise (or on error)
1043  */
1044 int fit_image_check_os(const void *fit, int noffset, uint8_t os)
1045 {
1046         uint8_t image_os;
1047
1048         if (fit_image_get_os(fit, noffset, &image_os))
1049                 return 0;
1050         return (os == image_os);
1051 }
1052
1053 /**
1054  * fit_image_check_arch - check whether image node is of a given arch
1055  * @fit: pointer to the FIT format image header
1056  * @noffset: component image node offset
1057  * @arch: requested imagearch
1058  *
1059  * fit_image_check_arch() reads image arch property and compares its numeric
1060  * id with the requested arch. Comparison result is returned to the caller.
1061  *
1062  * returns:
1063  *     1 if image is of given arch
1064  *     0 otherwise (or on error)
1065  */
1066 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
1067 {
1068         uint8_t image_arch;
1069
1070         if (fit_image_get_arch(fit, noffset, &image_arch))
1071                 return 0;
1072         return (arch == image_arch);
1073 }
1074
1075 /**
1076  * fit_image_check_type - check whether image node is of a given type
1077  * @fit: pointer to the FIT format image header
1078  * @noffset: component image node offset
1079  * @type: requested image type
1080  *
1081  * fit_image_check_type() reads image type property and compares its numeric
1082  * id with the requested type. Comparison result is returned to the caller.
1083  *
1084  * returns:
1085  *     1 if image is of given type
1086  *     0 otherwise (or on error)
1087  */
1088 int fit_image_check_type(const void *fit, int noffset, uint8_t type)
1089 {
1090         uint8_t image_type;
1091
1092         if (fit_image_get_type(fit, noffset, &image_type))
1093                 return 0;
1094         return (type == image_type);
1095 }
1096
1097 /**
1098  * fit_image_check_comp - check whether image node uses given compression
1099  * @fit: pointer to the FIT format image header
1100  * @noffset: component image node offset
1101  * @comp: requested image compression type
1102  *
1103  * fit_image_check_comp() reads image compression property and compares its
1104  * numeric id with the requested compression type. Comparison result is
1105  * returned to the caller.
1106  *
1107  * returns:
1108  *     1 if image uses requested compression
1109  *     0 otherwise (or on error)
1110  */
1111 int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
1112 {
1113         uint8_t image_comp;
1114
1115         if (fit_image_get_comp(fit, noffset, &image_comp))
1116                 return 0;
1117         return (comp == image_comp);
1118 }
1119
1120 /**
1121  * fit_check_format - sanity check FIT image format
1122  * @fit: pointer to the FIT format image header
1123  *
1124  * fit_check_format() runs a basic sanity FIT image verification.
1125  * Routine checks for mandatory properties, nodes, etc.
1126  *
1127  * returns:
1128  *     1, on success
1129  *     0, on failure
1130  */
1131 int fit_check_format(const void *fit)
1132 {
1133         /* mandatory / node 'description' property */
1134         if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
1135                 debug("Wrong FIT format: no description\n");
1136                 return 0;
1137         }
1138
1139         if (IMAGE_ENABLE_TIMESTAMP) {
1140                 /* mandatory / node 'timestamp' property */
1141                 if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
1142                         debug("Wrong FIT format: no timestamp\n");
1143                         return 0;
1144                 }
1145         }
1146
1147         /* mandatory subimages parent '/images' node */
1148         if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
1149                 debug("Wrong FIT format: no images parent node\n");
1150                 return 0;
1151         }
1152
1153         return 1;
1154 }
1155
1156
1157 /**
1158  * fit_conf_find_compat
1159  * @fit: pointer to the FIT format image header
1160  * @fdt: pointer to the device tree to compare against
1161  *
1162  * fit_conf_find_compat() attempts to find the configuration whose fdt is the
1163  * most compatible with the passed in device tree.
1164  *
1165  * Example:
1166  *
1167  * / o image-tree
1168  *   |-o images
1169  *   | |-o fdt@1
1170  *   | |-o fdt@2
1171  *   |
1172  *   |-o configurations
1173  *     |-o config@1
1174  *     | |-fdt = fdt@1
1175  *     |
1176  *     |-o config@2
1177  *       |-fdt = fdt@2
1178  *
1179  * / o U-Boot fdt
1180  *   |-compatible = "foo,bar", "bim,bam"
1181  *
1182  * / o kernel fdt1
1183  *   |-compatible = "foo,bar",
1184  *
1185  * / o kernel fdt2
1186  *   |-compatible = "bim,bam", "baz,biz"
1187  *
1188  * Configuration 1 would be picked because the first string in U-Boot's
1189  * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
1190  * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
1191  *
1192  * returns:
1193  *     offset to the configuration to use if one was found
1194  *     -1 otherwise
1195  */
1196 int fit_conf_find_compat(const void *fit, const void *fdt)
1197 {
1198         int ndepth = 0;
1199         int noffset, confs_noffset, images_noffset;
1200         const void *fdt_compat;
1201         int fdt_compat_len;
1202         int best_match_offset = 0;
1203         int best_match_pos = 0;
1204
1205         confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1206         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1207         if (confs_noffset < 0 || images_noffset < 0) {
1208                 debug("Can't find configurations or images nodes.\n");
1209                 return -1;
1210         }
1211
1212         fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
1213         if (!fdt_compat) {
1214                 debug("Fdt for comparison has no \"compatible\" property.\n");
1215                 return -1;
1216         }
1217
1218         /*
1219          * Loop over the configurations in the FIT image.
1220          */
1221         for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
1222                         (noffset >= 0) && (ndepth > 0);
1223                         noffset = fdt_next_node(fit, noffset, &ndepth)) {
1224                 const void *kfdt;
1225                 const char *kfdt_name;
1226                 int kfdt_noffset;
1227                 const char *cur_fdt_compat;
1228                 int len;
1229                 size_t size;
1230                 int i;
1231
1232                 if (ndepth > 1)
1233                         continue;
1234
1235                 kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
1236                 if (!kfdt_name) {
1237                         debug("No fdt property found.\n");
1238                         continue;
1239                 }
1240                 kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
1241                                                   kfdt_name);
1242                 if (kfdt_noffset < 0) {
1243                         debug("No image node named \"%s\" found.\n",
1244                               kfdt_name);
1245                         continue;
1246                 }
1247                 /*
1248                  * Get a pointer to this configuration's fdt.
1249                  */
1250                 if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
1251                         debug("Failed to get fdt \"%s\".\n", kfdt_name);
1252                         continue;
1253                 }
1254
1255                 len = fdt_compat_len;
1256                 cur_fdt_compat = fdt_compat;
1257                 /*
1258                  * Look for a match for each U-Boot compatibility string in
1259                  * turn in this configuration's fdt.
1260                  */
1261                 for (i = 0; len > 0 &&
1262                      (!best_match_offset || best_match_pos > i); i++) {
1263                         int cur_len = strlen(cur_fdt_compat) + 1;
1264
1265                         if (!fdt_node_check_compatible(kfdt, 0,
1266                                                        cur_fdt_compat)) {
1267                                 best_match_offset = noffset;
1268                                 best_match_pos = i;
1269                                 break;
1270                         }
1271                         len -= cur_len;
1272                         cur_fdt_compat += cur_len;
1273                 }
1274         }
1275         if (!best_match_offset) {
1276                 debug("No match found.\n");
1277                 return -1;
1278         }
1279
1280         return best_match_offset;
1281 }
1282
1283 /**
1284  * fit_conf_get_node - get node offset for configuration of a given unit name
1285  * @fit: pointer to the FIT format image header
1286  * @conf_uname: configuration node unit name
1287  *
1288  * fit_conf_get_node() finds a configuration (withing the '/configurations'
1289  * parant node) of a provided unit name. If configuration is found its node
1290  * offset is returned to the caller.
1291  *
1292  * When NULL is provided in second argument fit_conf_get_node() will search
1293  * for a default configuration node instead. Default configuration node unit
1294  * name is retrived from FIT_DEFAULT_PROP property of the '/configurations'
1295  * node.
1296  *
1297  * returns:
1298  *     configuration node offset when found (>=0)
1299  *     negative number on failure (FDT_ERR_* code)
1300  */
1301 int fit_conf_get_node(const void *fit, const char *conf_uname)
1302 {
1303         int noffset, confs_noffset;
1304         int len;
1305
1306         confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1307         if (confs_noffset < 0) {
1308                 debug("Can't find configurations parent node '%s' (%s)\n",
1309                       FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1310                 return confs_noffset;
1311         }
1312
1313         if (conf_uname == NULL) {
1314                 /* get configuration unit name from the default property */
1315                 debug("No configuration specified, trying default...\n");
1316                 conf_uname = (char *)fdt_getprop(fit, confs_noffset,
1317                                                  FIT_DEFAULT_PROP, &len);
1318                 if (conf_uname == NULL) {
1319                         fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
1320                                       len);
1321                         return len;
1322                 }
1323                 debug("Found default configuration: '%s'\n", conf_uname);
1324         }
1325
1326         noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
1327         if (noffset < 0) {
1328                 debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
1329                       conf_uname, fdt_strerror(noffset));
1330         }
1331
1332         return noffset;
1333 }
1334
1335 int fit_conf_get_prop_node(const void *fit, int noffset,
1336                 const char *prop_name)
1337 {
1338         char *uname;
1339         int len;
1340
1341         /* get kernel image unit name from configuration kernel property */
1342         uname = (char *)fdt_getprop(fit, noffset, prop_name, &len);
1343         if (uname == NULL)
1344                 return len;
1345
1346         return fit_image_get_node(fit, uname);
1347 }
1348
1349 /**
1350  * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
1351  * a given configuration
1352  * @fit: pointer to the FIT format image header
1353  * @noffset: configuration node offset
1354  *
1355  * fit_conf_get_kernel_node() retrives kernel image node unit name from
1356  * configuration FIT_KERNEL_PROP property and translates it to the node
1357  * offset.
1358  *
1359  * returns:
1360  *     image node offset when found (>=0)
1361  *     negative number on failure (FDT_ERR_* code)
1362  */
1363 int fit_conf_get_kernel_node(const void *fit, int noffset)
1364 {
1365         return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
1366 }
1367
1368 /**
1369  * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
1370  * a given configuration
1371  * @fit: pointer to the FIT format image header
1372  * @noffset: configuration node offset
1373  *
1374  * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
1375  * configuration FIT_KERNEL_PROP property and translates it to the node
1376  * offset.
1377  *
1378  * returns:
1379  *     image node offset when found (>=0)
1380  *     negative number on failure (FDT_ERR_* code)
1381  */
1382 int fit_conf_get_ramdisk_node(const void *fit, int noffset)
1383 {
1384         return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
1385 }
1386
1387 /**
1388  * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
1389  * a given configuration
1390  * @fit: pointer to the FIT format image header
1391  * @noffset: configuration node offset
1392  *
1393  * fit_conf_get_fdt_node() retrives fdt image node unit name from
1394  * configuration FIT_KERNEL_PROP property and translates it to the node
1395  * offset.
1396  *
1397  * returns:
1398  *     image node offset when found (>=0)
1399  *     negative number on failure (FDT_ERR_* code)
1400  */
1401 int fit_conf_get_fdt_node(const void *fit, int noffset)
1402 {
1403         return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
1404 }
1405
1406 /**
1407  * fit_conf_print - prints out the FIT configuration details
1408  * @fit: pointer to the FIT format image header
1409  * @noffset: offset of the configuration node
1410  * @p: pointer to prefix string
1411  *
1412  * fit_conf_print() lists all mandatory properies for the processed
1413  * configuration node.
1414  *
1415  * returns:
1416  *     no returned results
1417  */
1418 void fit_conf_print(const void *fit, int noffset, const char *p)
1419 {
1420         char *desc;
1421         char *uname;
1422         int ret;
1423
1424         /* Mandatory properties */
1425         ret = fit_get_desc(fit, noffset, &desc);
1426         printf("%s  Description:  ", p);
1427         if (ret)
1428                 printf("unavailable\n");
1429         else
1430                 printf("%s\n", desc);
1431
1432         uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
1433         printf("%s  Kernel:       ", p);
1434         if (uname == NULL)
1435                 printf("unavailable\n");
1436         else
1437                 printf("%s\n", uname);
1438
1439         /* Optional properties */
1440         uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
1441         if (uname)
1442                 printf("%s  Init Ramdisk: %s\n", p, uname);
1443
1444         uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
1445         if (uname)
1446                 printf("%s  FDT:          %s\n", p, uname);
1447 }
1448
1449 /**
1450  * fit_check_ramdisk - verify FIT format ramdisk subimage
1451  * @fit_hdr: pointer to the FIT ramdisk header
1452  * @rd_noffset: ramdisk subimage node offset within FIT image
1453  * @arch: requested ramdisk image architecture type
1454  * @verify: data CRC verification flag
1455  *
1456  * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
1457  * specified FIT image.
1458  *
1459  * returns:
1460  *     1, on success
1461  *     0, on failure
1462  */
1463 int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
1464                         int verify)
1465 {
1466         fit_image_print(fit, rd_noffset, "   ");
1467
1468         if (verify) {
1469                 puts("   Verifying Hash Integrity ... ");
1470                 if (!fit_image_verify(fit, rd_noffset)) {
1471                         puts("Bad Data Hash\n");
1472                         bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
1473                         return 0;
1474                 }
1475                 puts("OK\n");
1476         }
1477
1478         bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
1479         if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) ||
1480             !fit_image_check_arch(fit, rd_noffset, arch) ||
1481             !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) {
1482                 printf("No Linux %s Ramdisk Image\n",
1483                        genimg_get_arch_name(arch));
1484                 bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
1485                 return 0;
1486         }
1487
1488         bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
1489         return 1;
1490 }