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