xref: /rk3399_rockchip-uboot/common/image-fit.c (revision 1fe7d93891905b9af1d81c9aef7b5646452ceb41)
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 }
1491