xref: /openbmc/u-boot/common/image-fit.c (revision b7d9107ff7600605034563dd990f02672a674e35)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
253fbb7e8SSimon Glass /*
353fbb7e8SSimon Glass  * Copyright (c) 2013, Google Inc.
453fbb7e8SSimon Glass  *
553fbb7e8SSimon Glass  * (C) Copyright 2008 Semihalf
653fbb7e8SSimon Glass  *
753fbb7e8SSimon Glass  * (C) Copyright 2000-2006
853fbb7e8SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
953fbb7e8SSimon Glass  */
1053fbb7e8SSimon Glass 
1153fbb7e8SSimon Glass #ifdef USE_HOSTCC
1253fbb7e8SSimon Glass #include "mkimage.h"
1353fbb7e8SSimon Glass #include <time.h>
1453fbb7e8SSimon Glass #else
15eba3fbd6SAndreas Dannenberg #include <linux/compiler.h>
16020198b0SYork Sun #include <linux/kconfig.h>
1753fbb7e8SSimon Glass #include <common.h>
18782cfbb2SSimon Glass #include <errno.h>
190eb25b61SJoe Hershberger #include <mapmem.h>
20782cfbb2SSimon Glass #include <asm/io.h>
21169043d8SPantelis Antoniou #include <malloc.h>
22782cfbb2SSimon Glass DECLARE_GLOBAL_DATA_PTR;
2353fbb7e8SSimon Glass #endif /* !USE_HOSTCC*/
2453fbb7e8SSimon Glass 
25eba3fbd6SAndreas Dannenberg #include <image.h>
2653fbb7e8SSimon Glass #include <bootstage.h>
2753fbb7e8SSimon Glass #include <u-boot/crc.h>
2853fbb7e8SSimon Glass #include <u-boot/md5.h>
292b9912e6SJeroen Hofstee #include <u-boot/sha1.h>
302b9912e6SJeroen Hofstee #include <u-boot/sha256.h>
31e9221d03SReuben Dowle #include <u-boot/sha512.h>
3253fbb7e8SSimon Glass 
3353fbb7e8SSimon Glass /*****************************************************************************/
3453fbb7e8SSimon Glass /* New uImage format routines */
3553fbb7e8SSimon Glass /*****************************************************************************/
3653fbb7e8SSimon Glass #ifndef USE_HOSTCC
fit_parse_spec(const char * spec,char sepc,ulong addr_curr,ulong * addr,const char ** name)3753fbb7e8SSimon Glass static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
3853fbb7e8SSimon Glass 		ulong *addr, const char **name)
3953fbb7e8SSimon Glass {
4053fbb7e8SSimon Glass 	const char *sep;
4153fbb7e8SSimon Glass 
4253fbb7e8SSimon Glass 	*addr = addr_curr;
4353fbb7e8SSimon Glass 	*name = NULL;
4453fbb7e8SSimon Glass 
4553fbb7e8SSimon Glass 	sep = strchr(spec, sepc);
4653fbb7e8SSimon Glass 	if (sep) {
4753fbb7e8SSimon Glass 		if (sep - spec > 0)
4853fbb7e8SSimon Glass 			*addr = simple_strtoul(spec, NULL, 16);
4953fbb7e8SSimon Glass 
5053fbb7e8SSimon Glass 		*name = sep + 1;
5153fbb7e8SSimon Glass 		return 1;
5253fbb7e8SSimon Glass 	}
5353fbb7e8SSimon Glass 
5453fbb7e8SSimon Glass 	return 0;
5553fbb7e8SSimon Glass }
5653fbb7e8SSimon Glass 
5753fbb7e8SSimon Glass /**
5853fbb7e8SSimon Glass  * fit_parse_conf - parse FIT configuration spec
5953fbb7e8SSimon Glass  * @spec: input string, containing configuration spec
6053fbb7e8SSimon Glass  * @add_curr: current image address (to be used as a possible default)
6153fbb7e8SSimon Glass  * @addr: pointer to a ulong variable, will hold FIT image address of a given
6253fbb7e8SSimon Glass  * configuration
6353fbb7e8SSimon Glass  * @conf_name double pointer to a char, will hold pointer to a configuration
6453fbb7e8SSimon Glass  * unit name
6553fbb7e8SSimon Glass  *
66069d5945SMasahiro Yamada  * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
6753fbb7e8SSimon Glass  * where <addr> is a FIT image address that contains configuration
6853fbb7e8SSimon Glass  * with a <conf> unit name.
6953fbb7e8SSimon Glass  *
7053fbb7e8SSimon Glass  * Address part is optional, and if omitted default add_curr will
7153fbb7e8SSimon Glass  * be used instead.
7253fbb7e8SSimon Glass  *
7353fbb7e8SSimon Glass  * returns:
7453fbb7e8SSimon Glass  *     1 if spec is a valid configuration string,
7553fbb7e8SSimon Glass  *     addr and conf_name are set accordingly
7653fbb7e8SSimon Glass  *     0 otherwise
7753fbb7e8SSimon Glass  */
fit_parse_conf(const char * spec,ulong addr_curr,ulong * addr,const char ** conf_name)7853fbb7e8SSimon Glass int fit_parse_conf(const char *spec, ulong addr_curr,
7953fbb7e8SSimon Glass 		ulong *addr, const char **conf_name)
8053fbb7e8SSimon Glass {
8153fbb7e8SSimon Glass 	return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
8253fbb7e8SSimon Glass }
8353fbb7e8SSimon Glass 
8453fbb7e8SSimon Glass /**
8553fbb7e8SSimon Glass  * fit_parse_subimage - parse FIT subimage spec
8653fbb7e8SSimon Glass  * @spec: input string, containing subimage spec
8753fbb7e8SSimon Glass  * @add_curr: current image address (to be used as a possible default)
8853fbb7e8SSimon Glass  * @addr: pointer to a ulong variable, will hold FIT image address of a given
8953fbb7e8SSimon Glass  * subimage
9053fbb7e8SSimon Glass  * @image_name: double pointer to a char, will hold pointer to a subimage name
9153fbb7e8SSimon Glass  *
92069d5945SMasahiro Yamada  * fit_parse_subimage() expects subimage spec in the form of
9353fbb7e8SSimon Glass  * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
9453fbb7e8SSimon Glass  * subimage with a <subimg> unit name.
9553fbb7e8SSimon Glass  *
9653fbb7e8SSimon Glass  * Address part is optional, and if omitted default add_curr will
9753fbb7e8SSimon Glass  * be used instead.
9853fbb7e8SSimon Glass  *
9953fbb7e8SSimon Glass  * returns:
10053fbb7e8SSimon Glass  *     1 if spec is a valid subimage string,
10153fbb7e8SSimon Glass  *     addr and image_name are set accordingly
10253fbb7e8SSimon Glass  *     0 otherwise
10353fbb7e8SSimon Glass  */
fit_parse_subimage(const char * spec,ulong addr_curr,ulong * addr,const char ** image_name)10453fbb7e8SSimon Glass int fit_parse_subimage(const char *spec, ulong addr_curr,
10553fbb7e8SSimon Glass 		ulong *addr, const char **image_name)
10653fbb7e8SSimon Glass {
10753fbb7e8SSimon Glass 	return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
10853fbb7e8SSimon Glass }
10953fbb7e8SSimon Glass #endif /* !USE_HOSTCC */
11053fbb7e8SSimon Glass 
fit_get_debug(const void * fit,int noffset,char * prop_name,int err)11153fbb7e8SSimon Glass static void fit_get_debug(const void *fit, int noffset,
11253fbb7e8SSimon Glass 		char *prop_name, int err)
11353fbb7e8SSimon Glass {
11453fbb7e8SSimon Glass 	debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
11553fbb7e8SSimon Glass 	      prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
11653fbb7e8SSimon Glass 	      fdt_strerror(err));
11753fbb7e8SSimon Glass }
11853fbb7e8SSimon Glass 
11939931f96SGuilherme Maciel Ferreira /**
12039931f96SGuilherme Maciel Ferreira  * fit_get_subimage_count - get component (sub-image) count
12139931f96SGuilherme Maciel Ferreira  * @fit: pointer to the FIT format image header
12239931f96SGuilherme Maciel Ferreira  * @images_noffset: offset of images node
12339931f96SGuilherme Maciel Ferreira  *
12439931f96SGuilherme Maciel Ferreira  * returns:
12539931f96SGuilherme Maciel Ferreira  *     number of image components
12639931f96SGuilherme Maciel Ferreira  */
fit_get_subimage_count(const void * fit,int images_noffset)12739931f96SGuilherme Maciel Ferreira int fit_get_subimage_count(const void *fit, int images_noffset)
12839931f96SGuilherme Maciel Ferreira {
12939931f96SGuilherme Maciel Ferreira 	int noffset;
13039931f96SGuilherme Maciel Ferreira 	int ndepth;
13139931f96SGuilherme Maciel Ferreira 	int count = 0;
13239931f96SGuilherme Maciel Ferreira 
13339931f96SGuilherme Maciel Ferreira 	/* Process its subnodes, print out component images details */
13439931f96SGuilherme Maciel Ferreira 	for (ndepth = 0, count = 0,
13539931f96SGuilherme Maciel Ferreira 		noffset = fdt_next_node(fit, images_noffset, &ndepth);
13639931f96SGuilherme Maciel Ferreira 	     (noffset >= 0) && (ndepth > 0);
13739931f96SGuilherme Maciel Ferreira 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
13839931f96SGuilherme Maciel Ferreira 		if (ndepth == 1) {
13939931f96SGuilherme Maciel Ferreira 			count++;
14039931f96SGuilherme Maciel Ferreira 		}
14139931f96SGuilherme Maciel Ferreira 	}
14239931f96SGuilherme Maciel Ferreira 
14339931f96SGuilherme Maciel Ferreira 	return count;
14439931f96SGuilherme Maciel Ferreira }
14539931f96SGuilherme Maciel Ferreira 
146b527b9c6SMarek Vasut #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT)
14753fbb7e8SSimon Glass /**
14816c4b169STom Rini  * fit_image_print_data() - prints out the hash node details
14916c4b169STom Rini  * @fit: pointer to the FIT format image header
15016c4b169STom Rini  * @noffset: offset of the hash node
15116c4b169STom Rini  * @p: pointer to prefix string
15216c4b169STom Rini  * @type: Type of information to print ("hash" or "sign")
15316c4b169STom Rini  *
15416c4b169STom Rini  * fit_image_print_data() lists properties for the processed hash node
15516c4b169STom Rini  *
15616c4b169STom Rini  * This function avoid using puts() since it prints a newline on the host
15716c4b169STom Rini  * but does not in U-Boot.
15816c4b169STom Rini  *
15916c4b169STom Rini  * returns:
16016c4b169STom Rini  *     no returned results
16116c4b169STom Rini  */
fit_image_print_data(const void * fit,int noffset,const char * p,const char * type)16216c4b169STom Rini static void fit_image_print_data(const void *fit, int noffset, const char *p,
16316c4b169STom Rini 				 const char *type)
16416c4b169STom Rini {
16516c4b169STom Rini 	const char *keyname;
16616c4b169STom Rini 	uint8_t *value;
16716c4b169STom Rini 	int value_len;
16816c4b169STom Rini 	char *algo;
16920031567SPhilippe Reynes 	const char *padding;
17016c4b169STom Rini 	int required;
17116c4b169STom Rini 	int ret, i;
17216c4b169STom Rini 
17316c4b169STom Rini 	debug("%s  %s node:    '%s'\n", p, type,
17416c4b169STom Rini 	      fit_get_name(fit, noffset, NULL));
17516c4b169STom Rini 	printf("%s  %s algo:    ", p, type);
17616c4b169STom Rini 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
17716c4b169STom Rini 		printf("invalid/unsupported\n");
17816c4b169STom Rini 		return;
17916c4b169STom Rini 	}
18016c4b169STom Rini 	printf("%s", algo);
18116c4b169STom Rini 	keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
18216c4b169STom Rini 	required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
18316c4b169STom Rini 	if (keyname)
18416c4b169STom Rini 		printf(":%s", keyname);
18516c4b169STom Rini 	if (required)
18616c4b169STom Rini 		printf(" (required)");
18716c4b169STom Rini 	printf("\n");
18816c4b169STom Rini 
18920031567SPhilippe Reynes 	padding = fdt_getprop(fit, noffset, "padding", NULL);
19020031567SPhilippe Reynes 	if (padding)
19120031567SPhilippe Reynes 		printf("%s  %s padding: %s\n", p, type, padding);
19220031567SPhilippe Reynes 
19316c4b169STom Rini 	ret = fit_image_hash_get_value(fit, noffset, &value,
19416c4b169STom Rini 				       &value_len);
19516c4b169STom Rini 	printf("%s  %s value:   ", p, type);
19616c4b169STom Rini 	if (ret) {
19716c4b169STom Rini 		printf("unavailable\n");
19816c4b169STom Rini 	} else {
19916c4b169STom Rini 		for (i = 0; i < value_len; i++)
20016c4b169STom Rini 			printf("%02x", value[i]);
20116c4b169STom Rini 		printf("\n");
20216c4b169STom Rini 	}
20316c4b169STom Rini 
20416c4b169STom Rini 	debug("%s  %s len:     %d\n", p, type, value_len);
20516c4b169STom Rini 
20616c4b169STom Rini 	/* Signatures have a time stamp */
20716c4b169STom Rini 	if (IMAGE_ENABLE_TIMESTAMP && keyname) {
20816c4b169STom Rini 		time_t timestamp;
20916c4b169STom Rini 
21016c4b169STom Rini 		printf("%s  Timestamp:    ", p);
21116c4b169STom Rini 		if (fit_get_timestamp(fit, noffset, &timestamp))
21216c4b169STom Rini 			printf("unavailable\n");
21316c4b169STom Rini 		else
21416c4b169STom Rini 			genimg_print_time(timestamp);
21516c4b169STom Rini 	}
21616c4b169STom Rini }
21716c4b169STom Rini 
21816c4b169STom Rini /**
21916c4b169STom Rini  * fit_image_print_verification_data() - prints out the hash/signature details
22016c4b169STom Rini  * @fit: pointer to the FIT format image header
22116c4b169STom Rini  * @noffset: offset of the hash or signature node
22216c4b169STom Rini  * @p: pointer to prefix string
22316c4b169STom Rini  *
22416c4b169STom Rini  * This lists properties for the processed hash node
22516c4b169STom Rini  *
22616c4b169STom Rini  * returns:
22716c4b169STom Rini  *     no returned results
22816c4b169STom Rini  */
fit_image_print_verification_data(const void * fit,int noffset,const char * p)22916c4b169STom Rini static void fit_image_print_verification_data(const void *fit, int noffset,
23016c4b169STom Rini 					      const char *p)
23116c4b169STom Rini {
23216c4b169STom Rini 	const char *name;
23316c4b169STom Rini 
23416c4b169STom Rini 	/*
23516c4b169STom Rini 	 * Check subnode name, must be equal to "hash" or "signature".
23616c4b169STom Rini 	 * Multiple hash/signature nodes require unique unit node
23716c4b169STom Rini 	 * names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
23816c4b169STom Rini 	 */
23916c4b169STom Rini 	name = fit_get_name(fit, noffset, NULL);
24016c4b169STom Rini 	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
24116c4b169STom Rini 		fit_image_print_data(fit, noffset, p, "Hash");
24216c4b169STom Rini 	} else if (!strncmp(name, FIT_SIG_NODENAME,
24316c4b169STom Rini 				strlen(FIT_SIG_NODENAME))) {
24416c4b169STom Rini 		fit_image_print_data(fit, noffset, p, "Sign");
24516c4b169STom Rini 	}
24616c4b169STom Rini }
24716c4b169STom Rini 
24816c4b169STom Rini /**
24916c4b169STom Rini  * fit_conf_print - prints out the FIT configuration details
25016c4b169STom Rini  * @fit: pointer to the FIT format image header
25116c4b169STom Rini  * @noffset: offset of the configuration node
25216c4b169STom Rini  * @p: pointer to prefix string
25316c4b169STom Rini  *
25416c4b169STom Rini  * fit_conf_print() lists all mandatory properties for the processed
25516c4b169STom Rini  * configuration node.
25616c4b169STom Rini  *
25716c4b169STom Rini  * returns:
25816c4b169STom Rini  *     no returned results
25916c4b169STom Rini  */
fit_conf_print(const void * fit,int noffset,const char * p)26016c4b169STom Rini static void fit_conf_print(const void *fit, int noffset, const char *p)
26116c4b169STom Rini {
26216c4b169STom Rini 	char *desc;
26316c4b169STom Rini 	const char *uname;
26416c4b169STom Rini 	int ret;
26516c4b169STom Rini 	int fdt_index, loadables_index;
26616c4b169STom Rini 	int ndepth;
26716c4b169STom Rini 
26816c4b169STom Rini 	/* Mandatory properties */
26916c4b169STom Rini 	ret = fit_get_desc(fit, noffset, &desc);
27016c4b169STom Rini 	printf("%s  Description:  ", p);
27116c4b169STom Rini 	if (ret)
27216c4b169STom Rini 		printf("unavailable\n");
27316c4b169STom Rini 	else
27416c4b169STom Rini 		printf("%s\n", desc);
27516c4b169STom Rini 
27616c4b169STom Rini 	uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
27716c4b169STom Rini 	printf("%s  Kernel:       ", p);
27816c4b169STom Rini 	if (!uname)
27916c4b169STom Rini 		printf("unavailable\n");
28016c4b169STom Rini 	else
28116c4b169STom Rini 		printf("%s\n", uname);
28216c4b169STom Rini 
28316c4b169STom Rini 	/* Optional properties */
28416c4b169STom Rini 	uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
28516c4b169STom Rini 	if (uname)
28616c4b169STom Rini 		printf("%s  Init Ramdisk: %s\n", p, uname);
28716c4b169STom Rini 
28816c4b169STom Rini 	uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL);
28916c4b169STom Rini 	if (uname)
29016c4b169STom Rini 		printf("%s  Firmware:     %s\n", p, uname);
29116c4b169STom Rini 
29216c4b169STom Rini 	for (fdt_index = 0;
29316c4b169STom Rini 	     uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
29416c4b169STom Rini 					fdt_index, NULL), uname;
29516c4b169STom Rini 	     fdt_index++) {
29616c4b169STom Rini 		if (fdt_index == 0)
29716c4b169STom Rini 			printf("%s  FDT:          ", p);
29816c4b169STom Rini 		else
29916c4b169STom Rini 			printf("%s                ", p);
30016c4b169STom Rini 		printf("%s\n", uname);
30116c4b169STom Rini 	}
30216c4b169STom Rini 
30316c4b169STom Rini 	uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
30416c4b169STom Rini 	if (uname)
30516c4b169STom Rini 		printf("%s  FPGA:         %s\n", p, uname);
30616c4b169STom Rini 
30716c4b169STom Rini 	/* Print out all of the specified loadables */
30816c4b169STom Rini 	for (loadables_index = 0;
30916c4b169STom Rini 	     uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
31016c4b169STom Rini 					loadables_index, NULL), uname;
31116c4b169STom Rini 	     loadables_index++) {
31216c4b169STom Rini 		if (loadables_index == 0) {
31316c4b169STom Rini 			printf("%s  Loadables:    ", p);
31416c4b169STom Rini 		} else {
31516c4b169STom Rini 			printf("%s                ", p);
31616c4b169STom Rini 		}
31716c4b169STom Rini 		printf("%s\n", uname);
31816c4b169STom Rini 	}
31916c4b169STom Rini 
32016c4b169STom Rini 	/* Process all hash subnodes of the component configuration node */
32116c4b169STom Rini 	for (ndepth = 0, noffset = fdt_next_node(fit, noffset, &ndepth);
32216c4b169STom Rini 	     (noffset >= 0) && (ndepth > 0);
32316c4b169STom Rini 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
32416c4b169STom Rini 		if (ndepth == 1) {
32516c4b169STom Rini 			/* Direct child node of the component configuration node */
32616c4b169STom Rini 			fit_image_print_verification_data(fit, noffset, p);
32716c4b169STom Rini 		}
32816c4b169STom Rini 	}
32916c4b169STom Rini }
33016c4b169STom Rini 
33116c4b169STom Rini /**
33253fbb7e8SSimon Glass  * fit_print_contents - prints out the contents of the FIT format image
33353fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
33453fbb7e8SSimon Glass  * @p: pointer to prefix string
33553fbb7e8SSimon Glass  *
33653fbb7e8SSimon Glass  * fit_print_contents() formats a multi line FIT image contents description.
337e17adbb3SAndreas Dannenberg  * The routine prints out FIT image properties (root node level) followed by
33853fbb7e8SSimon Glass  * the details of each component image.
33953fbb7e8SSimon Glass  *
34053fbb7e8SSimon Glass  * returns:
34153fbb7e8SSimon Glass  *     no returned results
34253fbb7e8SSimon Glass  */
fit_print_contents(const void * fit)34353fbb7e8SSimon Glass void fit_print_contents(const void *fit)
34453fbb7e8SSimon Glass {
34553fbb7e8SSimon Glass 	char *desc;
34653fbb7e8SSimon Glass 	char *uname;
34753fbb7e8SSimon Glass 	int images_noffset;
34853fbb7e8SSimon Glass 	int confs_noffset;
34953fbb7e8SSimon Glass 	int noffset;
35053fbb7e8SSimon Glass 	int ndepth;
35153fbb7e8SSimon Glass 	int count = 0;
35253fbb7e8SSimon Glass 	int ret;
35353fbb7e8SSimon Glass 	const char *p;
35453fbb7e8SSimon Glass 	time_t timestamp;
35553fbb7e8SSimon Glass 
3561fe7d938SSimon Glass 	/* Indent string is defined in header image.h */
3571fe7d938SSimon Glass 	p = IMAGE_INDENT_STRING;
35853fbb7e8SSimon Glass 
35953fbb7e8SSimon Glass 	/* Root node properties */
36053fbb7e8SSimon Glass 	ret = fit_get_desc(fit, 0, &desc);
36153fbb7e8SSimon Glass 	printf("%sFIT description: ", p);
36253fbb7e8SSimon Glass 	if (ret)
36353fbb7e8SSimon Glass 		printf("unavailable\n");
36453fbb7e8SSimon Glass 	else
36553fbb7e8SSimon Glass 		printf("%s\n", desc);
36653fbb7e8SSimon Glass 
36753fbb7e8SSimon Glass 	if (IMAGE_ENABLE_TIMESTAMP) {
36853fbb7e8SSimon Glass 		ret = fit_get_timestamp(fit, 0, &timestamp);
36953fbb7e8SSimon Glass 		printf("%sCreated:         ", p);
37053fbb7e8SSimon Glass 		if (ret)
37153fbb7e8SSimon Glass 			printf("unavailable\n");
37253fbb7e8SSimon Glass 		else
37353fbb7e8SSimon Glass 			genimg_print_time(timestamp);
37453fbb7e8SSimon Glass 	}
37553fbb7e8SSimon Glass 
37653fbb7e8SSimon Glass 	/* Find images parent node offset */
37753fbb7e8SSimon Glass 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
37853fbb7e8SSimon Glass 	if (images_noffset < 0) {
37953fbb7e8SSimon Glass 		printf("Can't find images parent node '%s' (%s)\n",
38053fbb7e8SSimon Glass 		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
38153fbb7e8SSimon Glass 		return;
38253fbb7e8SSimon Glass 	}
38353fbb7e8SSimon Glass 
38453fbb7e8SSimon Glass 	/* Process its subnodes, print out component images details */
38553fbb7e8SSimon Glass 	for (ndepth = 0, count = 0,
38653fbb7e8SSimon Glass 		noffset = fdt_next_node(fit, images_noffset, &ndepth);
38753fbb7e8SSimon Glass 	     (noffset >= 0) && (ndepth > 0);
38853fbb7e8SSimon Glass 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
38953fbb7e8SSimon Glass 		if (ndepth == 1) {
39053fbb7e8SSimon Glass 			/*
39153fbb7e8SSimon Glass 			 * Direct child node of the images parent node,
39253fbb7e8SSimon Glass 			 * i.e. component image node.
39353fbb7e8SSimon Glass 			 */
39453fbb7e8SSimon Glass 			printf("%s Image %u (%s)\n", p, count++,
39553fbb7e8SSimon Glass 			       fit_get_name(fit, noffset, NULL));
39653fbb7e8SSimon Glass 
39753fbb7e8SSimon Glass 			fit_image_print(fit, noffset, p);
39853fbb7e8SSimon Glass 		}
39953fbb7e8SSimon Glass 	}
40053fbb7e8SSimon Glass 
40153fbb7e8SSimon Glass 	/* Find configurations parent node offset */
40253fbb7e8SSimon Glass 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
40353fbb7e8SSimon Glass 	if (confs_noffset < 0) {
40453fbb7e8SSimon Glass 		debug("Can't get configurations parent node '%s' (%s)\n",
40553fbb7e8SSimon Glass 		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
40653fbb7e8SSimon Glass 		return;
40753fbb7e8SSimon Glass 	}
40853fbb7e8SSimon Glass 
40953fbb7e8SSimon Glass 	/* get default configuration unit name from default property */
41053fbb7e8SSimon Glass 	uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
41153fbb7e8SSimon Glass 	if (uname)
41253fbb7e8SSimon Glass 		printf("%s Default Configuration: '%s'\n", p, uname);
41353fbb7e8SSimon Glass 
41453fbb7e8SSimon Glass 	/* Process its subnodes, print out configurations details */
41553fbb7e8SSimon Glass 	for (ndepth = 0, count = 0,
41653fbb7e8SSimon Glass 		noffset = fdt_next_node(fit, confs_noffset, &ndepth);
41753fbb7e8SSimon Glass 	     (noffset >= 0) && (ndepth > 0);
41853fbb7e8SSimon Glass 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
41953fbb7e8SSimon Glass 		if (ndepth == 1) {
42053fbb7e8SSimon Glass 			/*
42153fbb7e8SSimon Glass 			 * Direct child node of the configurations parent node,
42253fbb7e8SSimon Glass 			 * i.e. configuration node.
42353fbb7e8SSimon Glass 			 */
42453fbb7e8SSimon Glass 			printf("%s Configuration %u (%s)\n", p, count++,
42553fbb7e8SSimon Glass 			       fit_get_name(fit, noffset, NULL));
42653fbb7e8SSimon Glass 
42753fbb7e8SSimon Glass 			fit_conf_print(fit, noffset, p);
42853fbb7e8SSimon Glass 		}
42953fbb7e8SSimon Glass 	}
43053fbb7e8SSimon Glass }
43153fbb7e8SSimon Glass 
43253fbb7e8SSimon Glass /**
43353fbb7e8SSimon Glass  * fit_image_print - prints out the FIT component image details
43453fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
43553fbb7e8SSimon Glass  * @image_noffset: offset of the component image node
43653fbb7e8SSimon Glass  * @p: pointer to prefix string
43753fbb7e8SSimon Glass  *
438e17adbb3SAndreas Dannenberg  * fit_image_print() lists all mandatory properties for the processed component
43953fbb7e8SSimon Glass  * image. If present, hash nodes are printed out as well. Load
44053fbb7e8SSimon Glass  * address for images of type firmware is also printed out. Since the load
44153fbb7e8SSimon Glass  * address is not mandatory for firmware images, it will be output as
44253fbb7e8SSimon Glass  * "unavailable" when not present.
44353fbb7e8SSimon Glass  *
44453fbb7e8SSimon Glass  * returns:
44553fbb7e8SSimon Glass  *     no returned results
44653fbb7e8SSimon Glass  */
fit_image_print(const void * fit,int image_noffset,const char * p)44753fbb7e8SSimon Glass void fit_image_print(const void *fit, int image_noffset, const char *p)
44853fbb7e8SSimon Glass {
44953fbb7e8SSimon Glass 	char *desc;
45053fbb7e8SSimon Glass 	uint8_t type, arch, os, comp;
45153fbb7e8SSimon Glass 	size_t size;
45253fbb7e8SSimon Glass 	ulong load, entry;
45353fbb7e8SSimon Glass 	const void *data;
45453fbb7e8SSimon Glass 	int noffset;
45553fbb7e8SSimon Glass 	int ndepth;
45653fbb7e8SSimon Glass 	int ret;
45753fbb7e8SSimon Glass 
45853fbb7e8SSimon Glass 	/* Mandatory properties */
45953fbb7e8SSimon Glass 	ret = fit_get_desc(fit, image_noffset, &desc);
46053fbb7e8SSimon Glass 	printf("%s  Description:  ", p);
46153fbb7e8SSimon Glass 	if (ret)
46253fbb7e8SSimon Glass 		printf("unavailable\n");
46353fbb7e8SSimon Glass 	else
46453fbb7e8SSimon Glass 		printf("%s\n", desc);
46553fbb7e8SSimon Glass 
4661fd1e2f6SSimon Glass 	if (IMAGE_ENABLE_TIMESTAMP) {
4671fd1e2f6SSimon Glass 		time_t timestamp;
4681fd1e2f6SSimon Glass 
4691fd1e2f6SSimon Glass 		ret = fit_get_timestamp(fit, 0, &timestamp);
4701fd1e2f6SSimon Glass 		printf("%s  Created:      ", p);
4711fd1e2f6SSimon Glass 		if (ret)
4721fd1e2f6SSimon Glass 			printf("unavailable\n");
4731fd1e2f6SSimon Glass 		else
4741fd1e2f6SSimon Glass 			genimg_print_time(timestamp);
4751fd1e2f6SSimon Glass 	}
4761fd1e2f6SSimon Glass 
47753fbb7e8SSimon Glass 	fit_image_get_type(fit, image_noffset, &type);
47853fbb7e8SSimon Glass 	printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
47953fbb7e8SSimon Glass 
48053fbb7e8SSimon Glass 	fit_image_get_comp(fit, image_noffset, &comp);
48153fbb7e8SSimon Glass 	printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
48253fbb7e8SSimon Glass 
483c3c86388SKelvin Cheung 	ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size);
48453fbb7e8SSimon Glass 
48553fbb7e8SSimon Glass #ifndef USE_HOSTCC
48653fbb7e8SSimon Glass 	printf("%s  Data Start:   ", p);
487c6ac13bdSSimon Glass 	if (ret) {
48853fbb7e8SSimon Glass 		printf("unavailable\n");
489c6ac13bdSSimon Glass 	} else {
490c6ac13bdSSimon Glass 		void *vdata = (void *)data;
491c6ac13bdSSimon Glass 
492c6ac13bdSSimon Glass 		printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
493c6ac13bdSSimon Glass 	}
49453fbb7e8SSimon Glass #endif
49553fbb7e8SSimon Glass 
49653fbb7e8SSimon Glass 	printf("%s  Data Size:    ", p);
49753fbb7e8SSimon Glass 	if (ret)
49853fbb7e8SSimon Glass 		printf("unavailable\n");
49953fbb7e8SSimon Glass 	else
50053fbb7e8SSimon Glass 		genimg_print_size(size);
50153fbb7e8SSimon Glass 
50253fbb7e8SSimon Glass 	/* Remaining, type dependent properties */
50353fbb7e8SSimon Glass 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
50453fbb7e8SSimon Glass 	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
50553fbb7e8SSimon Glass 	    (type == IH_TYPE_FLATDT)) {
50653fbb7e8SSimon Glass 		fit_image_get_arch(fit, image_noffset, &arch);
50753fbb7e8SSimon Glass 		printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
50853fbb7e8SSimon Glass 	}
50953fbb7e8SSimon Glass 
5106faf4622SMichal Simek 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) ||
5116faf4622SMichal Simek 	    (type == IH_TYPE_FIRMWARE)) {
51253fbb7e8SSimon Glass 		fit_image_get_os(fit, image_noffset, &os);
51353fbb7e8SSimon Glass 		printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
51453fbb7e8SSimon Glass 	}
51553fbb7e8SSimon Glass 
51653fbb7e8SSimon Glass 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
51762afc601SMichal Simek 	    (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) ||
51862afc601SMichal Simek 	    (type == IH_TYPE_FPGA)) {
51953fbb7e8SSimon Glass 		ret = fit_image_get_load(fit, image_noffset, &load);
52053fbb7e8SSimon Glass 		printf("%s  Load Address: ", p);
52153fbb7e8SSimon Glass 		if (ret)
52253fbb7e8SSimon Glass 			printf("unavailable\n");
52353fbb7e8SSimon Glass 		else
52453fbb7e8SSimon Glass 			printf("0x%08lx\n", load);
52553fbb7e8SSimon Glass 	}
52653fbb7e8SSimon Glass 
527169043d8SPantelis Antoniou 	/* optional load address for FDT */
528169043d8SPantelis Antoniou 	if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load))
529169043d8SPantelis Antoniou 		printf("%s  Load Address: 0x%08lx\n", p, load);
530169043d8SPantelis Antoniou 
53153fbb7e8SSimon Glass 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
53253fbb7e8SSimon Glass 	    (type == IH_TYPE_RAMDISK)) {
5336004765dSYork Sun 		ret = fit_image_get_entry(fit, image_noffset, &entry);
53453fbb7e8SSimon Glass 		printf("%s  Entry Point:  ", p);
53553fbb7e8SSimon Glass 		if (ret)
53653fbb7e8SSimon Glass 			printf("unavailable\n");
53753fbb7e8SSimon Glass 		else
53853fbb7e8SSimon Glass 			printf("0x%08lx\n", entry);
53953fbb7e8SSimon Glass 	}
54053fbb7e8SSimon Glass 
54153fbb7e8SSimon Glass 	/* Process all hash subnodes of the component image node */
54253fbb7e8SSimon Glass 	for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
54353fbb7e8SSimon Glass 	     (noffset >= 0) && (ndepth > 0);
54453fbb7e8SSimon Glass 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
54553fbb7e8SSimon Glass 		if (ndepth == 1) {
54653fbb7e8SSimon Glass 			/* Direct child node of the component image node */
547d8b75360SSimon Glass 			fit_image_print_verification_data(fit, noffset, p);
54853fbb7e8SSimon Glass 		}
54953fbb7e8SSimon Glass 	}
55053fbb7e8SSimon Glass }
551a3c43b12SMarek Vasut #else
fit_print_contents(const void * fit)552a3c43b12SMarek Vasut void fit_print_contents(const void *fit) { }
fit_image_print(const void * fit,int image_noffset,const char * p)553a3c43b12SMarek Vasut void fit_image_print(const void *fit, int image_noffset, const char *p) { }
554b527b9c6SMarek Vasut #endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT) */
55553fbb7e8SSimon Glass 
55653fbb7e8SSimon Glass /**
55753fbb7e8SSimon Glass  * fit_get_desc - get node description property
55853fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
55953fbb7e8SSimon Glass  * @noffset: node offset
560e17adbb3SAndreas Dannenberg  * @desc: double pointer to the char, will hold pointer to the description
56153fbb7e8SSimon Glass  *
56253fbb7e8SSimon Glass  * fit_get_desc() reads description property from a given node, if
563e17adbb3SAndreas Dannenberg  * description is found pointer to it is returned in third call argument.
56453fbb7e8SSimon Glass  *
56553fbb7e8SSimon Glass  * returns:
56653fbb7e8SSimon Glass  *     0, on success
56753fbb7e8SSimon Glass  *     -1, on failure
56853fbb7e8SSimon Glass  */
fit_get_desc(const void * fit,int noffset,char ** desc)56953fbb7e8SSimon Glass int fit_get_desc(const void *fit, int noffset, char **desc)
57053fbb7e8SSimon Glass {
57153fbb7e8SSimon Glass 	int len;
57253fbb7e8SSimon Glass 
57353fbb7e8SSimon Glass 	*desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
57453fbb7e8SSimon Glass 	if (*desc == NULL) {
57553fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
57653fbb7e8SSimon Glass 		return -1;
57753fbb7e8SSimon Glass 	}
57853fbb7e8SSimon Glass 
57953fbb7e8SSimon Glass 	return 0;
58053fbb7e8SSimon Glass }
58153fbb7e8SSimon Glass 
58253fbb7e8SSimon Glass /**
58353fbb7e8SSimon Glass  * fit_get_timestamp - get node timestamp property
58453fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
58553fbb7e8SSimon Glass  * @noffset: node offset
58653fbb7e8SSimon Glass  * @timestamp: pointer to the time_t, will hold read timestamp
58753fbb7e8SSimon Glass  *
588e17adbb3SAndreas Dannenberg  * fit_get_timestamp() reads timestamp property from given node, if timestamp
589e17adbb3SAndreas Dannenberg  * is found and has a correct size its value is returned in third call
59053fbb7e8SSimon Glass  * argument.
59153fbb7e8SSimon Glass  *
59253fbb7e8SSimon Glass  * returns:
59353fbb7e8SSimon Glass  *     0, on success
59453fbb7e8SSimon Glass  *     -1, on property read failure
59553fbb7e8SSimon Glass  *     -2, on wrong timestamp size
59653fbb7e8SSimon Glass  */
fit_get_timestamp(const void * fit,int noffset,time_t * timestamp)59753fbb7e8SSimon Glass int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
59853fbb7e8SSimon Glass {
59953fbb7e8SSimon Glass 	int len;
60053fbb7e8SSimon Glass 	const void *data;
60153fbb7e8SSimon Glass 
60253fbb7e8SSimon Glass 	data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
60353fbb7e8SSimon Glass 	if (data == NULL) {
60453fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
60553fbb7e8SSimon Glass 		return -1;
60653fbb7e8SSimon Glass 	}
60753fbb7e8SSimon Glass 	if (len != sizeof(uint32_t)) {
60853fbb7e8SSimon Glass 		debug("FIT timestamp with incorrect size of (%u)\n", len);
60953fbb7e8SSimon Glass 		return -2;
61053fbb7e8SSimon Glass 	}
61153fbb7e8SSimon Glass 
61253fbb7e8SSimon Glass 	*timestamp = uimage_to_cpu(*((uint32_t *)data));
61353fbb7e8SSimon Glass 	return 0;
61453fbb7e8SSimon Glass }
61553fbb7e8SSimon Glass 
61653fbb7e8SSimon Glass /**
61753fbb7e8SSimon Glass  * fit_image_get_node - get node offset for component image of a given unit name
61853fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
61953fbb7e8SSimon Glass  * @image_uname: component image node unit name
62053fbb7e8SSimon Glass  *
621e17adbb3SAndreas Dannenberg  * fit_image_get_node() finds a component image (within the '/images'
62253fbb7e8SSimon Glass  * node) of a provided unit name. If image is found its node offset is
62353fbb7e8SSimon Glass  * returned to the caller.
62453fbb7e8SSimon Glass  *
62553fbb7e8SSimon Glass  * returns:
62653fbb7e8SSimon Glass  *     image node offset when found (>=0)
62753fbb7e8SSimon Glass  *     negative number on failure (FDT_ERR_* code)
62853fbb7e8SSimon Glass  */
fit_image_get_node(const void * fit,const char * image_uname)62953fbb7e8SSimon Glass int fit_image_get_node(const void *fit, const char *image_uname)
63053fbb7e8SSimon Glass {
63153fbb7e8SSimon Glass 	int noffset, images_noffset;
63253fbb7e8SSimon Glass 
63353fbb7e8SSimon Glass 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
63453fbb7e8SSimon Glass 	if (images_noffset < 0) {
63553fbb7e8SSimon Glass 		debug("Can't find images parent node '%s' (%s)\n",
63653fbb7e8SSimon Glass 		      FIT_IMAGES_PATH, fdt_strerror(images_noffset));
63753fbb7e8SSimon Glass 		return images_noffset;
63853fbb7e8SSimon Glass 	}
63953fbb7e8SSimon Glass 
64053fbb7e8SSimon Glass 	noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
64153fbb7e8SSimon Glass 	if (noffset < 0) {
64253fbb7e8SSimon Glass 		debug("Can't get node offset for image unit name: '%s' (%s)\n",
64353fbb7e8SSimon Glass 		      image_uname, fdt_strerror(noffset));
64453fbb7e8SSimon Glass 	}
64553fbb7e8SSimon Glass 
64653fbb7e8SSimon Glass 	return noffset;
64753fbb7e8SSimon Glass }
64853fbb7e8SSimon Glass 
64953fbb7e8SSimon Glass /**
65053fbb7e8SSimon Glass  * fit_image_get_os - get os id for a given component image node
65153fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
65253fbb7e8SSimon Glass  * @noffset: component image node offset
65353fbb7e8SSimon Glass  * @os: pointer to the uint8_t, will hold os numeric id
65453fbb7e8SSimon Glass  *
65553fbb7e8SSimon Glass  * fit_image_get_os() finds os property in a given component image node.
65653fbb7e8SSimon Glass  * If the property is found, its (string) value is translated to the numeric
65753fbb7e8SSimon Glass  * id which is returned to the caller.
65853fbb7e8SSimon Glass  *
65953fbb7e8SSimon Glass  * returns:
66053fbb7e8SSimon Glass  *     0, on success
66153fbb7e8SSimon Glass  *     -1, on failure
66253fbb7e8SSimon Glass  */
fit_image_get_os(const void * fit,int noffset,uint8_t * os)66353fbb7e8SSimon Glass int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
66453fbb7e8SSimon Glass {
66553fbb7e8SSimon Glass 	int len;
66653fbb7e8SSimon Glass 	const void *data;
66753fbb7e8SSimon Glass 
66853fbb7e8SSimon Glass 	/* Get OS name from property data */
66953fbb7e8SSimon Glass 	data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
67053fbb7e8SSimon Glass 	if (data == NULL) {
67153fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_OS_PROP, len);
67253fbb7e8SSimon Glass 		*os = -1;
67353fbb7e8SSimon Glass 		return -1;
67453fbb7e8SSimon Glass 	}
67553fbb7e8SSimon Glass 
67653fbb7e8SSimon Glass 	/* Translate OS name to id */
67753fbb7e8SSimon Glass 	*os = genimg_get_os_id(data);
67853fbb7e8SSimon Glass 	return 0;
67953fbb7e8SSimon Glass }
68053fbb7e8SSimon Glass 
68153fbb7e8SSimon Glass /**
68253fbb7e8SSimon Glass  * fit_image_get_arch - get arch id for a given component image node
68353fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
68453fbb7e8SSimon Glass  * @noffset: component image node offset
68553fbb7e8SSimon Glass  * @arch: pointer to the uint8_t, will hold arch numeric id
68653fbb7e8SSimon Glass  *
68753fbb7e8SSimon Glass  * fit_image_get_arch() finds arch property in a given component image node.
68853fbb7e8SSimon Glass  * If the property is found, its (string) value is translated to the numeric
68953fbb7e8SSimon Glass  * id which is returned to the caller.
69053fbb7e8SSimon Glass  *
69153fbb7e8SSimon Glass  * returns:
69253fbb7e8SSimon Glass  *     0, on success
69353fbb7e8SSimon Glass  *     -1, on failure
69453fbb7e8SSimon Glass  */
fit_image_get_arch(const void * fit,int noffset,uint8_t * arch)69553fbb7e8SSimon Glass int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
69653fbb7e8SSimon Glass {
69753fbb7e8SSimon Glass 	int len;
69853fbb7e8SSimon Glass 	const void *data;
69953fbb7e8SSimon Glass 
70053fbb7e8SSimon Glass 	/* Get architecture name from property data */
70153fbb7e8SSimon Glass 	data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
70253fbb7e8SSimon Glass 	if (data == NULL) {
70353fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
70453fbb7e8SSimon Glass 		*arch = -1;
70553fbb7e8SSimon Glass 		return -1;
70653fbb7e8SSimon Glass 	}
70753fbb7e8SSimon Glass 
70853fbb7e8SSimon Glass 	/* Translate architecture name to id */
70953fbb7e8SSimon Glass 	*arch = genimg_get_arch_id(data);
71053fbb7e8SSimon Glass 	return 0;
71153fbb7e8SSimon Glass }
71253fbb7e8SSimon Glass 
71353fbb7e8SSimon Glass /**
71453fbb7e8SSimon Glass  * fit_image_get_type - get type id for a given component image node
71553fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
71653fbb7e8SSimon Glass  * @noffset: component image node offset
71753fbb7e8SSimon Glass  * @type: pointer to the uint8_t, will hold type numeric id
71853fbb7e8SSimon Glass  *
71953fbb7e8SSimon Glass  * fit_image_get_type() finds type property in a given component image node.
72053fbb7e8SSimon Glass  * If the property is found, its (string) value is translated to the numeric
72153fbb7e8SSimon Glass  * id which is returned to the caller.
72253fbb7e8SSimon Glass  *
72353fbb7e8SSimon Glass  * returns:
72453fbb7e8SSimon Glass  *     0, on success
72553fbb7e8SSimon Glass  *     -1, on failure
72653fbb7e8SSimon Glass  */
fit_image_get_type(const void * fit,int noffset,uint8_t * type)72753fbb7e8SSimon Glass int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
72853fbb7e8SSimon Glass {
72953fbb7e8SSimon Glass 	int len;
73053fbb7e8SSimon Glass 	const void *data;
73153fbb7e8SSimon Glass 
73253fbb7e8SSimon Glass 	/* Get image type name from property data */
73353fbb7e8SSimon Glass 	data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
73453fbb7e8SSimon Glass 	if (data == NULL) {
73553fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
73653fbb7e8SSimon Glass 		*type = -1;
73753fbb7e8SSimon Glass 		return -1;
73853fbb7e8SSimon Glass 	}
73953fbb7e8SSimon Glass 
74053fbb7e8SSimon Glass 	/* Translate image type name to id */
74153fbb7e8SSimon Glass 	*type = genimg_get_type_id(data);
74253fbb7e8SSimon Glass 	return 0;
74353fbb7e8SSimon Glass }
74453fbb7e8SSimon Glass 
74553fbb7e8SSimon Glass /**
74653fbb7e8SSimon Glass  * fit_image_get_comp - get comp id for a given component image node
74753fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
74853fbb7e8SSimon Glass  * @noffset: component image node offset
74953fbb7e8SSimon Glass  * @comp: pointer to the uint8_t, will hold comp numeric id
75053fbb7e8SSimon Glass  *
75153fbb7e8SSimon Glass  * fit_image_get_comp() finds comp property in a given component image node.
75253fbb7e8SSimon Glass  * If the property is found, its (string) value is translated to the numeric
75353fbb7e8SSimon Glass  * id which is returned to the caller.
75453fbb7e8SSimon Glass  *
75553fbb7e8SSimon Glass  * returns:
75653fbb7e8SSimon Glass  *     0, on success
75753fbb7e8SSimon Glass  *     -1, on failure
75853fbb7e8SSimon Glass  */
fit_image_get_comp(const void * fit,int noffset,uint8_t * comp)75953fbb7e8SSimon Glass int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
76053fbb7e8SSimon Glass {
76153fbb7e8SSimon Glass 	int len;
76253fbb7e8SSimon Glass 	const void *data;
76353fbb7e8SSimon Glass 
76453fbb7e8SSimon Glass 	/* Get compression name from property data */
76553fbb7e8SSimon Glass 	data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
76653fbb7e8SSimon Glass 	if (data == NULL) {
76753fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
76853fbb7e8SSimon Glass 		*comp = -1;
76953fbb7e8SSimon Glass 		return -1;
77053fbb7e8SSimon Glass 	}
77153fbb7e8SSimon Glass 
77253fbb7e8SSimon Glass 	/* Translate compression name to id */
77353fbb7e8SSimon Glass 	*comp = genimg_get_comp_id(data);
77453fbb7e8SSimon Glass 	return 0;
77553fbb7e8SSimon Glass }
77653fbb7e8SSimon Glass 
fit_image_get_address(const void * fit,int noffset,char * name,ulong * load)7776004765dSYork Sun static int fit_image_get_address(const void *fit, int noffset, char *name,
7786004765dSYork Sun 			  ulong *load)
7796004765dSYork Sun {
780c1913cb7SYork Sun 	int len, cell_len;
781c1913cb7SYork Sun 	const fdt32_t *cell;
782c1913cb7SYork Sun 	uint64_t load64 = 0;
7836004765dSYork Sun 
784c1913cb7SYork Sun 	cell = fdt_getprop(fit, noffset, name, &len);
785c1913cb7SYork Sun 	if (cell == NULL) {
7866004765dSYork Sun 		fit_get_debug(fit, noffset, name, len);
7876004765dSYork Sun 		return -1;
7886004765dSYork Sun 	}
7896004765dSYork Sun 
790c1913cb7SYork Sun 	if (len > sizeof(ulong)) {
791c1913cb7SYork Sun 		printf("Unsupported %s address size\n", name);
792c1913cb7SYork Sun 		return -1;
793c1913cb7SYork Sun 	}
794c1913cb7SYork Sun 
795c1913cb7SYork Sun 	cell_len = len >> 2;
796c1913cb7SYork Sun 	/* Use load64 to avoid compiling warning for 32-bit target */
797c1913cb7SYork Sun 	while (cell_len--) {
798c1913cb7SYork Sun 		load64 = (load64 << 32) | uimage_to_cpu(*cell);
799c1913cb7SYork Sun 		cell++;
800c1913cb7SYork Sun 	}
801c1913cb7SYork Sun 	*load = (ulong)load64;
8026004765dSYork Sun 
8036004765dSYork Sun 	return 0;
8046004765dSYork Sun }
80553fbb7e8SSimon Glass /**
80653fbb7e8SSimon Glass  * fit_image_get_load() - get load addr property for given component image node
80753fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
80853fbb7e8SSimon Glass  * @noffset: component image node offset
80953fbb7e8SSimon Glass  * @load: pointer to the uint32_t, will hold load address
81053fbb7e8SSimon Glass  *
81153fbb7e8SSimon Glass  * fit_image_get_load() finds load address property in a given component
81253fbb7e8SSimon Glass  * image node. If the property is found, its value is returned to the caller.
81353fbb7e8SSimon Glass  *
81453fbb7e8SSimon Glass  * returns:
81553fbb7e8SSimon Glass  *     0, on success
81653fbb7e8SSimon Glass  *     -1, on failure
81753fbb7e8SSimon Glass  */
fit_image_get_load(const void * fit,int noffset,ulong * load)81853fbb7e8SSimon Glass int fit_image_get_load(const void *fit, int noffset, ulong *load)
81953fbb7e8SSimon Glass {
8206004765dSYork Sun 	return fit_image_get_address(fit, noffset, FIT_LOAD_PROP, load);
82153fbb7e8SSimon Glass }
82253fbb7e8SSimon Glass 
82353fbb7e8SSimon Glass /**
82453fbb7e8SSimon Glass  * fit_image_get_entry() - get entry point address property
82553fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
82653fbb7e8SSimon Glass  * @noffset: component image node offset
82753fbb7e8SSimon Glass  * @entry: pointer to the uint32_t, will hold entry point address
82853fbb7e8SSimon Glass  *
82953fbb7e8SSimon Glass  * This gets the entry point address property for a given component image
83053fbb7e8SSimon Glass  * node.
83153fbb7e8SSimon Glass  *
83253fbb7e8SSimon Glass  * fit_image_get_entry() finds entry point address property in a given
83353fbb7e8SSimon Glass  * component image node.  If the property is found, its value is returned
83453fbb7e8SSimon Glass  * to the caller.
83553fbb7e8SSimon Glass  *
83653fbb7e8SSimon Glass  * returns:
83753fbb7e8SSimon Glass  *     0, on success
83853fbb7e8SSimon Glass  *     -1, on failure
83953fbb7e8SSimon Glass  */
fit_image_get_entry(const void * fit,int noffset,ulong * entry)84053fbb7e8SSimon Glass int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
84153fbb7e8SSimon Glass {
8426004765dSYork Sun 	return fit_image_get_address(fit, noffset, FIT_ENTRY_PROP, entry);
84353fbb7e8SSimon Glass }
84453fbb7e8SSimon Glass 
84553fbb7e8SSimon Glass /**
84653fbb7e8SSimon Glass  * fit_image_get_data - get data property and its size for a given component image node
84753fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
84853fbb7e8SSimon Glass  * @noffset: component image node offset
84953fbb7e8SSimon Glass  * @data: double pointer to void, will hold data property's data address
85053fbb7e8SSimon Glass  * @size: pointer to size_t, will hold data property's data size
85153fbb7e8SSimon Glass  *
85253fbb7e8SSimon Glass  * fit_image_get_data() finds data property in a given component image node.
85353fbb7e8SSimon Glass  * If the property is found its data start address and size are returned to
85453fbb7e8SSimon Glass  * the caller.
85553fbb7e8SSimon Glass  *
85653fbb7e8SSimon Glass  * returns:
85753fbb7e8SSimon Glass  *     0, on success
85853fbb7e8SSimon Glass  *     -1, on failure
85953fbb7e8SSimon Glass  */
fit_image_get_data(const void * fit,int noffset,const void ** data,size_t * size)86053fbb7e8SSimon Glass int fit_image_get_data(const void *fit, int noffset,
86153fbb7e8SSimon Glass 		const void **data, size_t *size)
86253fbb7e8SSimon Glass {
86353fbb7e8SSimon Glass 	int len;
86453fbb7e8SSimon Glass 
86553fbb7e8SSimon Glass 	*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
86653fbb7e8SSimon Glass 	if (*data == NULL) {
86753fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
86853fbb7e8SSimon Glass 		*size = 0;
86953fbb7e8SSimon Glass 		return -1;
87053fbb7e8SSimon Glass 	}
87153fbb7e8SSimon Glass 
87253fbb7e8SSimon Glass 	*size = len;
87353fbb7e8SSimon Glass 	return 0;
87453fbb7e8SSimon Glass }
87553fbb7e8SSimon Glass 
87653fbb7e8SSimon Glass /**
877db1b79b8Stomas.melin@vaisala.com  * Get 'data-offset' property from a given image node.
878db1b79b8Stomas.melin@vaisala.com  *
879db1b79b8Stomas.melin@vaisala.com  * @fit: pointer to the FIT image header
880db1b79b8Stomas.melin@vaisala.com  * @noffset: component image node offset
881db1b79b8Stomas.melin@vaisala.com  * @data_offset: holds the data-offset property
882db1b79b8Stomas.melin@vaisala.com  *
883db1b79b8Stomas.melin@vaisala.com  * returns:
884db1b79b8Stomas.melin@vaisala.com  *     0, on success
885db1b79b8Stomas.melin@vaisala.com  *     -ENOENT if the property could not be found
886db1b79b8Stomas.melin@vaisala.com  */
fit_image_get_data_offset(const void * fit,int noffset,int * data_offset)887db1b79b8Stomas.melin@vaisala.com int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset)
888db1b79b8Stomas.melin@vaisala.com {
889db1b79b8Stomas.melin@vaisala.com 	const fdt32_t *val;
890db1b79b8Stomas.melin@vaisala.com 
891db1b79b8Stomas.melin@vaisala.com 	val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
892db1b79b8Stomas.melin@vaisala.com 	if (!val)
893db1b79b8Stomas.melin@vaisala.com 		return -ENOENT;
894db1b79b8Stomas.melin@vaisala.com 
895db1b79b8Stomas.melin@vaisala.com 	*data_offset = fdt32_to_cpu(*val);
896db1b79b8Stomas.melin@vaisala.com 
897db1b79b8Stomas.melin@vaisala.com 	return 0;
898db1b79b8Stomas.melin@vaisala.com }
899db1b79b8Stomas.melin@vaisala.com 
900db1b79b8Stomas.melin@vaisala.com /**
901a1be94b6SPeng Fan  * Get 'data-position' property from a given image node.
902a1be94b6SPeng Fan  *
903a1be94b6SPeng Fan  * @fit: pointer to the FIT image header
904a1be94b6SPeng Fan  * @noffset: component image node offset
905a1be94b6SPeng Fan  * @data_position: holds the data-position property
906a1be94b6SPeng Fan  *
907a1be94b6SPeng Fan  * returns:
908a1be94b6SPeng Fan  *     0, on success
909a1be94b6SPeng Fan  *     -ENOENT if the property could not be found
910a1be94b6SPeng Fan  */
fit_image_get_data_position(const void * fit,int noffset,int * data_position)911a1be94b6SPeng Fan int fit_image_get_data_position(const void *fit, int noffset,
912a1be94b6SPeng Fan 				int *data_position)
913a1be94b6SPeng Fan {
914a1be94b6SPeng Fan 	const fdt32_t *val;
915a1be94b6SPeng Fan 
916a1be94b6SPeng Fan 	val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
917a1be94b6SPeng Fan 	if (!val)
918a1be94b6SPeng Fan 		return -ENOENT;
919a1be94b6SPeng Fan 
920a1be94b6SPeng Fan 	*data_position = fdt32_to_cpu(*val);
921a1be94b6SPeng Fan 
922a1be94b6SPeng Fan 	return 0;
923a1be94b6SPeng Fan }
924a1be94b6SPeng Fan 
925a1be94b6SPeng Fan /**
926db1b79b8Stomas.melin@vaisala.com  * Get 'data-size' property from a given image node.
927db1b79b8Stomas.melin@vaisala.com  *
928db1b79b8Stomas.melin@vaisala.com  * @fit: pointer to the FIT image header
929db1b79b8Stomas.melin@vaisala.com  * @noffset: component image node offset
930db1b79b8Stomas.melin@vaisala.com  * @data_size: holds the data-size property
931db1b79b8Stomas.melin@vaisala.com  *
932db1b79b8Stomas.melin@vaisala.com  * returns:
933db1b79b8Stomas.melin@vaisala.com  *     0, on success
934db1b79b8Stomas.melin@vaisala.com  *     -ENOENT if the property could not be found
935db1b79b8Stomas.melin@vaisala.com  */
fit_image_get_data_size(const void * fit,int noffset,int * data_size)936db1b79b8Stomas.melin@vaisala.com int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
937db1b79b8Stomas.melin@vaisala.com {
938db1b79b8Stomas.melin@vaisala.com 	const fdt32_t *val;
939db1b79b8Stomas.melin@vaisala.com 
940db1b79b8Stomas.melin@vaisala.com 	val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
941db1b79b8Stomas.melin@vaisala.com 	if (!val)
942db1b79b8Stomas.melin@vaisala.com 		return -ENOENT;
943db1b79b8Stomas.melin@vaisala.com 
944db1b79b8Stomas.melin@vaisala.com 	*data_size = fdt32_to_cpu(*val);
945db1b79b8Stomas.melin@vaisala.com 
946db1b79b8Stomas.melin@vaisala.com 	return 0;
947db1b79b8Stomas.melin@vaisala.com }
948db1b79b8Stomas.melin@vaisala.com 
949db1b79b8Stomas.melin@vaisala.com /**
950c3c86388SKelvin Cheung  * fit_image_get_data_and_size - get data and its size including
951c3c86388SKelvin Cheung  *				 both embedded and external data
952c3c86388SKelvin Cheung  * @fit: pointer to the FIT format image header
953c3c86388SKelvin Cheung  * @noffset: component image node offset
954c3c86388SKelvin Cheung  * @data: double pointer to void, will hold data property's data address
955c3c86388SKelvin Cheung  * @size: pointer to size_t, will hold data property's data size
956c3c86388SKelvin Cheung  *
957c3c86388SKelvin Cheung  * fit_image_get_data_and_size() finds data and its size including
958c3c86388SKelvin Cheung  * both embedded and external data. If the property is found
959c3c86388SKelvin Cheung  * its data start address and size are returned to the caller.
960c3c86388SKelvin Cheung  *
961c3c86388SKelvin Cheung  * returns:
962c3c86388SKelvin Cheung  *     0, on success
963c3c86388SKelvin Cheung  *     otherwise, on failure
964c3c86388SKelvin Cheung  */
fit_image_get_data_and_size(const void * fit,int noffset,const void ** data,size_t * size)965c3c86388SKelvin Cheung int fit_image_get_data_and_size(const void *fit, int noffset,
966c3c86388SKelvin Cheung 				const void **data, size_t *size)
967c3c86388SKelvin Cheung {
968c3c86388SKelvin Cheung 	bool external_data = false;
969c3c86388SKelvin Cheung 	int offset;
970c3c86388SKelvin Cheung 	int len;
971c3c86388SKelvin Cheung 	int ret;
972c3c86388SKelvin Cheung 
973c3c86388SKelvin Cheung 	if (!fit_image_get_data_position(fit, noffset, &offset)) {
974c3c86388SKelvin Cheung 		external_data = true;
975c3c86388SKelvin Cheung 	} else if (!fit_image_get_data_offset(fit, noffset, &offset)) {
976c3c86388SKelvin Cheung 		external_data = true;
977c3c86388SKelvin Cheung 		/*
978c3c86388SKelvin Cheung 		 * For FIT with external data, figure out where
979c3c86388SKelvin Cheung 		 * the external images start. This is the base
980c3c86388SKelvin Cheung 		 * for the data-offset properties in each image.
981c3c86388SKelvin Cheung 		 */
982c3c86388SKelvin Cheung 		offset += ((fdt_totalsize(fit) + 3) & ~3);
983c3c86388SKelvin Cheung 	}
984c3c86388SKelvin Cheung 
985c3c86388SKelvin Cheung 	if (external_data) {
986c3c86388SKelvin Cheung 		debug("External Data\n");
987c3c86388SKelvin Cheung 		ret = fit_image_get_data_size(fit, noffset, &len);
988c50c63b2SHeinrich Schuchardt 		if (!ret) {
989c3c86388SKelvin Cheung 			*data = fit + offset;
990c3c86388SKelvin Cheung 			*size = len;
991c50c63b2SHeinrich Schuchardt 		}
992c3c86388SKelvin Cheung 	} else {
993c3c86388SKelvin Cheung 		ret = fit_image_get_data(fit, noffset, data, size);
994c3c86388SKelvin Cheung 	}
995c3c86388SKelvin Cheung 
996c3c86388SKelvin Cheung 	return ret;
997c3c86388SKelvin Cheung }
998c3c86388SKelvin Cheung 
999c3c86388SKelvin Cheung /**
100053fbb7e8SSimon Glass  * fit_image_hash_get_algo - get hash algorithm name
100153fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
100253fbb7e8SSimon Glass  * @noffset: hash node offset
100353fbb7e8SSimon Glass  * @algo: double pointer to char, will hold pointer to the algorithm name
100453fbb7e8SSimon Glass  *
100553fbb7e8SSimon Glass  * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
100653fbb7e8SSimon Glass  * If the property is found its data start address is returned to the caller.
100753fbb7e8SSimon Glass  *
100853fbb7e8SSimon Glass  * returns:
100953fbb7e8SSimon Glass  *     0, on success
101053fbb7e8SSimon Glass  *     -1, on failure
101153fbb7e8SSimon Glass  */
fit_image_hash_get_algo(const void * fit,int noffset,char ** algo)101253fbb7e8SSimon Glass int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
101353fbb7e8SSimon Glass {
101453fbb7e8SSimon Glass 	int len;
101553fbb7e8SSimon Glass 
101653fbb7e8SSimon Glass 	*algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
101753fbb7e8SSimon Glass 	if (*algo == NULL) {
101853fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
101953fbb7e8SSimon Glass 		return -1;
102053fbb7e8SSimon Glass 	}
102153fbb7e8SSimon Glass 
102253fbb7e8SSimon Glass 	return 0;
102353fbb7e8SSimon Glass }
102453fbb7e8SSimon Glass 
102553fbb7e8SSimon Glass /**
102653fbb7e8SSimon Glass  * fit_image_hash_get_value - get hash value and length
102753fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
102853fbb7e8SSimon Glass  * @noffset: hash node offset
102953fbb7e8SSimon Glass  * @value: double pointer to uint8_t, will hold address of a hash value data
103053fbb7e8SSimon Glass  * @value_len: pointer to an int, will hold hash data length
103153fbb7e8SSimon Glass  *
103253fbb7e8SSimon Glass  * fit_image_hash_get_value() finds hash value property in a given hash node.
103353fbb7e8SSimon Glass  * If the property is found its data start address and size are returned to
103453fbb7e8SSimon Glass  * the caller.
103553fbb7e8SSimon Glass  *
103653fbb7e8SSimon Glass  * returns:
103753fbb7e8SSimon Glass  *     0, on success
103853fbb7e8SSimon Glass  *     -1, on failure
103953fbb7e8SSimon Glass  */
fit_image_hash_get_value(const void * fit,int noffset,uint8_t ** value,int * value_len)104053fbb7e8SSimon Glass int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
104153fbb7e8SSimon Glass 				int *value_len)
104253fbb7e8SSimon Glass {
104353fbb7e8SSimon Glass 	int len;
104453fbb7e8SSimon Glass 
104553fbb7e8SSimon Glass 	*value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
104653fbb7e8SSimon Glass 	if (*value == NULL) {
104753fbb7e8SSimon Glass 		fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
104853fbb7e8SSimon Glass 		*value_len = 0;
104953fbb7e8SSimon Glass 		return -1;
105053fbb7e8SSimon Glass 	}
105153fbb7e8SSimon Glass 
105253fbb7e8SSimon Glass 	*value_len = len;
105353fbb7e8SSimon Glass 	return 0;
105453fbb7e8SSimon Glass }
105553fbb7e8SSimon Glass 
105653fbb7e8SSimon Glass /**
105753fbb7e8SSimon Glass  * fit_image_hash_get_ignore - get hash ignore flag
105853fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
105953fbb7e8SSimon Glass  * @noffset: hash node offset
106053fbb7e8SSimon Glass  * @ignore: pointer to an int, will hold hash ignore flag
106153fbb7e8SSimon Glass  *
106253fbb7e8SSimon Glass  * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
106353fbb7e8SSimon Glass  * If the property is found and non-zero, the hash algorithm is not verified by
106453fbb7e8SSimon Glass  * u-boot automatically.
106553fbb7e8SSimon Glass  *
106653fbb7e8SSimon Glass  * returns:
106753fbb7e8SSimon Glass  *     0, on ignore not found
106853fbb7e8SSimon Glass  *     value, on ignore found
106953fbb7e8SSimon Glass  */
fit_image_hash_get_ignore(const void * fit,int noffset,int * ignore)1070ab9efc66SSimon Glass static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
107153fbb7e8SSimon Glass {
107253fbb7e8SSimon Glass 	int len;
107353fbb7e8SSimon Glass 	int *value;
107453fbb7e8SSimon Glass 
107553fbb7e8SSimon Glass 	value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
107653fbb7e8SSimon Glass 	if (value == NULL || len != sizeof(int))
107753fbb7e8SSimon Glass 		*ignore = 0;
107853fbb7e8SSimon Glass 	else
107953fbb7e8SSimon Glass 		*ignore = *value;
108053fbb7e8SSimon Glass 
108153fbb7e8SSimon Glass 	return 0;
108253fbb7e8SSimon Glass }
108353fbb7e8SSimon Glass 
fit_get_end(const void * fit)10847a80de46SSimon Glass ulong fit_get_end(const void *fit)
10857a80de46SSimon Glass {
10867a80de46SSimon Glass 	return map_to_sysmem((void *)(fit + fdt_totalsize(fit)));
10877a80de46SSimon Glass }
10887a80de46SSimon Glass 
108953fbb7e8SSimon Glass /**
109053fbb7e8SSimon Glass  * fit_set_timestamp - set node timestamp property
109153fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
109253fbb7e8SSimon Glass  * @noffset: node offset
109353fbb7e8SSimon Glass  * @timestamp: timestamp value to be set
109453fbb7e8SSimon Glass  *
109553fbb7e8SSimon Glass  * fit_set_timestamp() attempts to set timestamp property in the requested
109653fbb7e8SSimon Glass  * node and returns operation status to the caller.
109753fbb7e8SSimon Glass  *
109853fbb7e8SSimon Glass  * returns:
109953fbb7e8SSimon Glass  *     0, on success
11004f427a42SSimon Glass  *     -ENOSPC if no space in device tree, -1 for other error
110153fbb7e8SSimon Glass  */
fit_set_timestamp(void * fit,int noffset,time_t timestamp)110253fbb7e8SSimon Glass int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
110353fbb7e8SSimon Glass {
110453fbb7e8SSimon Glass 	uint32_t t;
110553fbb7e8SSimon Glass 	int ret;
110653fbb7e8SSimon Glass 
110753fbb7e8SSimon Glass 	t = cpu_to_uimage(timestamp);
110853fbb7e8SSimon Glass 	ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
110953fbb7e8SSimon Glass 				sizeof(uint32_t));
111053fbb7e8SSimon Glass 	if (ret) {
11118df81e17SSimon Glass 		debug("Can't set '%s' property for '%s' node (%s)\n",
111253fbb7e8SSimon Glass 		      FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
111353fbb7e8SSimon Glass 		      fdt_strerror(ret));
11144f427a42SSimon Glass 		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
111553fbb7e8SSimon Glass 	}
111653fbb7e8SSimon Glass 
111753fbb7e8SSimon Glass 	return 0;
111853fbb7e8SSimon Glass }
111953fbb7e8SSimon Glass 
112053fbb7e8SSimon Glass /**
112153fbb7e8SSimon Glass  * calculate_hash - calculate and return hash for provided input data
112253fbb7e8SSimon Glass  * @data: pointer to the input data
112353fbb7e8SSimon Glass  * @data_len: data length
112453fbb7e8SSimon Glass  * @algo: requested hash algorithm
112553fbb7e8SSimon Glass  * @value: pointer to the char, will hold hash value data (caller must
112653fbb7e8SSimon Glass  * allocate enough free space)
112753fbb7e8SSimon Glass  * value_len: length of the calculated hash
112853fbb7e8SSimon Glass  *
112953fbb7e8SSimon Glass  * calculate_hash() computes input data hash according to the requested
113053fbb7e8SSimon Glass  * algorithm.
113153fbb7e8SSimon Glass  * Resulting hash value is placed in caller provided 'value' buffer, length
113253fbb7e8SSimon Glass  * of the calculated hash is returned via value_len pointer argument.
113353fbb7e8SSimon Glass  *
113453fbb7e8SSimon Glass  * returns:
113553fbb7e8SSimon Glass  *     0, on success
113653fbb7e8SSimon Glass  *    -1, when algo is unsupported
113753fbb7e8SSimon Glass  */
calculate_hash(const void * data,int data_len,const char * algo_name,uint8_t * value,int * value_len)11388e7d5f47SJoel Stanley int calculate_hash(const void *data, int data_len, const char *algo_name,
113953fbb7e8SSimon Glass 			uint8_t *value, int *value_len)
114053fbb7e8SSimon Glass {
11418e7d5f47SJoel Stanley 	struct hash_algo *algo;
11428e7d5f47SJoel Stanley 
11438e7d5f47SJoel Stanley 	if (hash_lookup_algo(algo_name, &algo)) {
114453fbb7e8SSimon Glass 		debug("Unsupported hash alogrithm\n");
114553fbb7e8SSimon Glass 		return -1;
114653fbb7e8SSimon Glass 	}
11478e7d5f47SJoel Stanley 
11488e7d5f47SJoel Stanley 	algo->hash_func_ws(data, data_len, value, algo->chunk_size);
11498e7d5f47SJoel Stanley 	*value_len = algo->digest_size;
11508e7d5f47SJoel Stanley 
115153fbb7e8SSimon Glass 	return 0;
115253fbb7e8SSimon Glass }
115353fbb7e8SSimon Glass 
fit_image_check_hash(const void * fit,int noffset,const void * data,size_t size,char ** err_msgp)1154ab9efc66SSimon Glass static int fit_image_check_hash(const void *fit, int noffset, const void *data,
1155ab9efc66SSimon Glass 				size_t size, char **err_msgp)
1156ab9efc66SSimon Glass {
1157ab9efc66SSimon Glass 	uint8_t value[FIT_MAX_HASH_LEN];
1158ab9efc66SSimon Glass 	int value_len;
1159ab9efc66SSimon Glass 	char *algo;
1160ab9efc66SSimon Glass 	uint8_t *fit_value;
1161ab9efc66SSimon Glass 	int fit_value_len;
1162ab9efc66SSimon Glass 	int ignore;
1163ab9efc66SSimon Glass 
1164ab9efc66SSimon Glass 	*err_msgp = NULL;
1165ab9efc66SSimon Glass 
1166ab9efc66SSimon Glass 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
1167e754da2aSSimon Glass 		*err_msgp = "Can't get hash algo property";
1168ab9efc66SSimon Glass 		return -1;
1169ab9efc66SSimon Glass 	}
1170ab9efc66SSimon Glass 	printf("%s", algo);
1171ab9efc66SSimon Glass 
1172ab9efc66SSimon Glass 	if (IMAGE_ENABLE_IGNORE) {
1173ab9efc66SSimon Glass 		fit_image_hash_get_ignore(fit, noffset, &ignore);
1174ab9efc66SSimon Glass 		if (ignore) {
1175ab9efc66SSimon Glass 			printf("-skipped ");
1176ab9efc66SSimon Glass 			return 0;
1177ab9efc66SSimon Glass 		}
1178ab9efc66SSimon Glass 	}
1179ab9efc66SSimon Glass 
1180ab9efc66SSimon Glass 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
1181ab9efc66SSimon Glass 				     &fit_value_len)) {
1182e754da2aSSimon Glass 		*err_msgp = "Can't get hash value property";
1183ab9efc66SSimon Glass 		return -1;
1184ab9efc66SSimon Glass 	}
1185ab9efc66SSimon Glass 
1186ab9efc66SSimon Glass 	if (calculate_hash(data, size, algo, value, &value_len)) {
1187e754da2aSSimon Glass 		*err_msgp = "Unsupported hash algorithm";
1188ab9efc66SSimon Glass 		return -1;
1189ab9efc66SSimon Glass 	}
1190ab9efc66SSimon Glass 
1191ab9efc66SSimon Glass 	if (value_len != fit_value_len) {
1192e754da2aSSimon Glass 		*err_msgp = "Bad hash value len";
1193ab9efc66SSimon Glass 		return -1;
1194ab9efc66SSimon Glass 	} else if (memcmp(value, fit_value, value_len) != 0) {
1195e754da2aSSimon Glass 		*err_msgp = "Bad hash value";
1196ab9efc66SSimon Glass 		return -1;
1197ab9efc66SSimon Glass 	}
1198ab9efc66SSimon Glass 
1199ab9efc66SSimon Glass 	return 0;
1200ab9efc66SSimon Glass }
1201ab9efc66SSimon Glass 
fit_image_verify_with_data(const void * fit,int image_noffset,const void * data,size_t size)12025c643db4SJun Nie int fit_image_verify_with_data(const void *fit, int image_noffset,
12035c643db4SJun Nie 			       const void *data, size_t size)
120453fbb7e8SSimon Glass {
120556518e71SSimon Glass 	int		noffset = 0;
120653fbb7e8SSimon Glass 	char		*err_msg = "";
120756518e71SSimon Glass 	int verify_all = 1;
120856518e71SSimon Glass 	int ret;
120953fbb7e8SSimon Glass 
121056518e71SSimon Glass 	/* Verify all required signatures */
121156518e71SSimon Glass 	if (IMAGE_ENABLE_VERIFY &&
121256518e71SSimon Glass 	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
121356518e71SSimon Glass 					   gd_fdt_blob(), &verify_all)) {
121456518e71SSimon Glass 		err_msg = "Unable to verify required signature";
121556518e71SSimon Glass 		goto error;
121653fbb7e8SSimon Glass 	}
121753fbb7e8SSimon Glass 
121853fbb7e8SSimon Glass 	/* Process all hash subnodes of the component image node */
1219df87e6b1SSimon Glass 	fdt_for_each_subnode(noffset, fit, image_noffset) {
1220ab9efc66SSimon Glass 		const char *name = fit_get_name(fit, noffset, NULL);
122153fbb7e8SSimon Glass 
122253fbb7e8SSimon Glass 		/*
122353fbb7e8SSimon Glass 		 * Check subnode name, must be equal to "hash".
122453fbb7e8SSimon Glass 		 * Multiple hash nodes require unique unit node
1225b2267e8aSAndre Przywara 		 * names, e.g. hash-1, hash-2, etc.
122653fbb7e8SSimon Glass 		 */
1227ab9efc66SSimon Glass 		if (!strncmp(name, FIT_HASH_NODENAME,
1228ab9efc66SSimon Glass 			     strlen(FIT_HASH_NODENAME))) {
1229ab9efc66SSimon Glass 			if (fit_image_check_hash(fit, noffset, data, size,
1230ab9efc66SSimon Glass 						 &err_msg))
123153fbb7e8SSimon Glass 				goto error;
1232ab9efc66SSimon Glass 			puts("+ ");
123356518e71SSimon Glass 		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
123456518e71SSimon Glass 				!strncmp(name, FIT_SIG_NODENAME,
123556518e71SSimon Glass 					strlen(FIT_SIG_NODENAME))) {
123656518e71SSimon Glass 			ret = fit_image_check_sig(fit, noffset, data,
123756518e71SSimon Glass 							size, -1, &err_msg);
12382e33e761SSimon Glass 
12392e33e761SSimon Glass 			/*
12402e33e761SSimon Glass 			 * Show an indication on failure, but do not return
12412e33e761SSimon Glass 			 * an error. Only keys marked 'required' can cause
12422e33e761SSimon Glass 			 * an image validation failure. See the call to
12432e33e761SSimon Glass 			 * fit_image_verify_required_sigs() above.
12442e33e761SSimon Glass 			 */
12452e33e761SSimon Glass 			if (ret)
124656518e71SSimon Glass 				puts("- ");
124756518e71SSimon Glass 			else
124856518e71SSimon Glass 				puts("+ ");
124953fbb7e8SSimon Glass 		}
125053fbb7e8SSimon Glass 	}
125153fbb7e8SSimon Glass 
125253fbb7e8SSimon Glass 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
1253e754da2aSSimon Glass 		err_msg = "Corrupted or truncated tree";
125453fbb7e8SSimon Glass 		goto error;
125553fbb7e8SSimon Glass 	}
125653fbb7e8SSimon Glass 
125753fbb7e8SSimon Glass 	return 1;
125853fbb7e8SSimon Glass 
125953fbb7e8SSimon Glass error:
1260e754da2aSSimon Glass 	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
126153fbb7e8SSimon Glass 	       err_msg, fit_get_name(fit, noffset, NULL),
126253fbb7e8SSimon Glass 	       fit_get_name(fit, image_noffset, NULL));
126353fbb7e8SSimon Glass 	return 0;
126453fbb7e8SSimon Glass }
126553fbb7e8SSimon Glass 
126653fbb7e8SSimon Glass /**
12675c643db4SJun Nie  * fit_image_verify - verify data integrity
12685c643db4SJun Nie  * @fit: pointer to the FIT format image header
12695c643db4SJun Nie  * @image_noffset: component image node offset
12705c643db4SJun Nie  *
12715c643db4SJun Nie  * fit_image_verify() goes over component image hash nodes,
12725c643db4SJun Nie  * re-calculates each data hash and compares with the value stored in hash
12735c643db4SJun Nie  * node.
12745c643db4SJun Nie  *
12755c643db4SJun Nie  * returns:
12765c643db4SJun Nie  *     1, if all hashes are valid
12775c643db4SJun Nie  *     0, otherwise (or on error)
12785c643db4SJun Nie  */
fit_image_verify(const void * fit,int image_noffset)12795c643db4SJun Nie int fit_image_verify(const void *fit, int image_noffset)
12805c643db4SJun Nie {
12815c643db4SJun Nie 	const void	*data;
12825c643db4SJun Nie 	size_t		size;
12835c643db4SJun Nie 	int		noffset = 0;
12845c643db4SJun Nie 	char		*err_msg = "";
12855c643db4SJun Nie 
12865c643db4SJun Nie 	/* Get image data and data length */
1287c3c86388SKelvin Cheung 	if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) {
12885c643db4SJun Nie 		err_msg = "Can't get image data/size";
12895c643db4SJun Nie 		printf("error!\n%s for '%s' hash node in '%s' image node\n",
12905c643db4SJun Nie 		       err_msg, fit_get_name(fit, noffset, NULL),
12915c643db4SJun Nie 		       fit_get_name(fit, image_noffset, NULL));
12925c643db4SJun Nie 		return 0;
12935c643db4SJun Nie 	}
12945c643db4SJun Nie 
12955c643db4SJun Nie 	return fit_image_verify_with_data(fit, image_noffset, data, size);
12965c643db4SJun Nie }
12975c643db4SJun Nie 
12985c643db4SJun Nie /**
1299e17adbb3SAndreas Dannenberg  * fit_all_image_verify - verify data integrity for all images
130053fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
130153fbb7e8SSimon Glass  *
1302b8da8366SSimon Glass  * fit_all_image_verify() goes over all images in the FIT and
130353fbb7e8SSimon Glass  * for every images checks if all it's hashes are valid.
130453fbb7e8SSimon Glass  *
130553fbb7e8SSimon Glass  * returns:
130653fbb7e8SSimon Glass  *     1, if all hashes of all images are valid
130753fbb7e8SSimon Glass  *     0, otherwise (or on error)
130853fbb7e8SSimon Glass  */
fit_all_image_verify(const void * fit)1309b8da8366SSimon Glass int fit_all_image_verify(const void *fit)
131053fbb7e8SSimon Glass {
131153fbb7e8SSimon Glass 	int images_noffset;
131253fbb7e8SSimon Glass 	int noffset;
131353fbb7e8SSimon Glass 	int ndepth;
131453fbb7e8SSimon Glass 	int count;
131553fbb7e8SSimon Glass 
131653fbb7e8SSimon Glass 	/* Find images parent node offset */
131753fbb7e8SSimon Glass 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
131853fbb7e8SSimon Glass 	if (images_noffset < 0) {
131953fbb7e8SSimon Glass 		printf("Can't find images parent node '%s' (%s)\n",
132053fbb7e8SSimon Glass 		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
132153fbb7e8SSimon Glass 		return 0;
132253fbb7e8SSimon Glass 	}
132353fbb7e8SSimon Glass 
132453fbb7e8SSimon Glass 	/* Process all image subnodes, check hashes for each */
132553fbb7e8SSimon Glass 	printf("## Checking hash(es) for FIT Image at %08lx ...\n",
132653fbb7e8SSimon Glass 	       (ulong)fit);
132753fbb7e8SSimon Glass 	for (ndepth = 0, count = 0,
132853fbb7e8SSimon Glass 	     noffset = fdt_next_node(fit, images_noffset, &ndepth);
132953fbb7e8SSimon Glass 			(noffset >= 0) && (ndepth > 0);
133053fbb7e8SSimon Glass 			noffset = fdt_next_node(fit, noffset, &ndepth)) {
133153fbb7e8SSimon Glass 		if (ndepth == 1) {
133253fbb7e8SSimon Glass 			/*
133353fbb7e8SSimon Glass 			 * Direct child node of the images parent node,
133453fbb7e8SSimon Glass 			 * i.e. component image node.
133553fbb7e8SSimon Glass 			 */
133673223f0eSSimon Glass 			printf("   Hash(es) for Image %u (%s): ", count,
133753fbb7e8SSimon Glass 			       fit_get_name(fit, noffset, NULL));
133873223f0eSSimon Glass 			count++;
133953fbb7e8SSimon Glass 
1340b8da8366SSimon Glass 			if (!fit_image_verify(fit, noffset))
134153fbb7e8SSimon Glass 				return 0;
134253fbb7e8SSimon Glass 			printf("\n");
134353fbb7e8SSimon Glass 		}
134453fbb7e8SSimon Glass 	}
134553fbb7e8SSimon Glass 	return 1;
134653fbb7e8SSimon Glass }
134753fbb7e8SSimon Glass 
134853fbb7e8SSimon Glass /**
134953fbb7e8SSimon Glass  * fit_image_check_os - check whether image node is of a given os type
135053fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
135153fbb7e8SSimon Glass  * @noffset: component image node offset
135253fbb7e8SSimon Glass  * @os: requested image os
135353fbb7e8SSimon Glass  *
135453fbb7e8SSimon Glass  * fit_image_check_os() reads image os property and compares its numeric
135553fbb7e8SSimon Glass  * id with the requested os. Comparison result is returned to the caller.
135653fbb7e8SSimon Glass  *
135753fbb7e8SSimon Glass  * returns:
135853fbb7e8SSimon Glass  *     1 if image is of given os type
135953fbb7e8SSimon Glass  *     0 otherwise (or on error)
136053fbb7e8SSimon Glass  */
fit_image_check_os(const void * fit,int noffset,uint8_t os)136153fbb7e8SSimon Glass int fit_image_check_os(const void *fit, int noffset, uint8_t os)
136253fbb7e8SSimon Glass {
136353fbb7e8SSimon Glass 	uint8_t image_os;
136453fbb7e8SSimon Glass 
136553fbb7e8SSimon Glass 	if (fit_image_get_os(fit, noffset, &image_os))
136653fbb7e8SSimon Glass 		return 0;
136753fbb7e8SSimon Glass 	return (os == image_os);
136853fbb7e8SSimon Glass }
136953fbb7e8SSimon Glass 
137053fbb7e8SSimon Glass /**
137153fbb7e8SSimon Glass  * fit_image_check_arch - check whether image node is of a given arch
137253fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
137353fbb7e8SSimon Glass  * @noffset: component image node offset
137453fbb7e8SSimon Glass  * @arch: requested imagearch
137553fbb7e8SSimon Glass  *
137653fbb7e8SSimon Glass  * fit_image_check_arch() reads image arch property and compares its numeric
137753fbb7e8SSimon Glass  * id with the requested arch. Comparison result is returned to the caller.
137853fbb7e8SSimon Glass  *
137953fbb7e8SSimon Glass  * returns:
138053fbb7e8SSimon Glass  *     1 if image is of given arch
138153fbb7e8SSimon Glass  *     0 otherwise (or on error)
138253fbb7e8SSimon Glass  */
fit_image_check_arch(const void * fit,int noffset,uint8_t arch)138353fbb7e8SSimon Glass int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
138453fbb7e8SSimon Glass {
138553fbb7e8SSimon Glass 	uint8_t image_arch;
1386ec6617c3SAlison Wang 	int aarch32_support = 0;
1387ec6617c3SAlison Wang 
1388ec6617c3SAlison Wang #ifdef CONFIG_ARM64_SUPPORT_AARCH32
1389ec6617c3SAlison Wang 	aarch32_support = 1;
1390ec6617c3SAlison Wang #endif
139153fbb7e8SSimon Glass 
139253fbb7e8SSimon Glass 	if (fit_image_get_arch(fit, noffset, &image_arch))
139353fbb7e8SSimon Glass 		return 0;
13945bda35cfSSimon Glass 	return (arch == image_arch) ||
1395ec6617c3SAlison Wang 		(arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) ||
1396ec6617c3SAlison Wang 		(arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM &&
1397ec6617c3SAlison Wang 		 aarch32_support);
139853fbb7e8SSimon Glass }
139953fbb7e8SSimon Glass 
140053fbb7e8SSimon Glass /**
140153fbb7e8SSimon Glass  * fit_image_check_type - check whether image node is of a given type
140253fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
140353fbb7e8SSimon Glass  * @noffset: component image node offset
140453fbb7e8SSimon Glass  * @type: requested image type
140553fbb7e8SSimon Glass  *
140653fbb7e8SSimon Glass  * fit_image_check_type() reads image type property and compares its numeric
140753fbb7e8SSimon Glass  * id with the requested type. Comparison result is returned to the caller.
140853fbb7e8SSimon Glass  *
140953fbb7e8SSimon Glass  * returns:
141053fbb7e8SSimon Glass  *     1 if image is of given type
141153fbb7e8SSimon Glass  *     0 otherwise (or on error)
141253fbb7e8SSimon Glass  */
fit_image_check_type(const void * fit,int noffset,uint8_t type)141353fbb7e8SSimon Glass int fit_image_check_type(const void *fit, int noffset, uint8_t type)
141453fbb7e8SSimon Glass {
141553fbb7e8SSimon Glass 	uint8_t image_type;
141653fbb7e8SSimon Glass 
141753fbb7e8SSimon Glass 	if (fit_image_get_type(fit, noffset, &image_type))
141853fbb7e8SSimon Glass 		return 0;
141953fbb7e8SSimon Glass 	return (type == image_type);
142053fbb7e8SSimon Glass }
142153fbb7e8SSimon Glass 
142253fbb7e8SSimon Glass /**
142353fbb7e8SSimon Glass  * fit_image_check_comp - check whether image node uses given compression
142453fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
142553fbb7e8SSimon Glass  * @noffset: component image node offset
142653fbb7e8SSimon Glass  * @comp: requested image compression type
142753fbb7e8SSimon Glass  *
142853fbb7e8SSimon Glass  * fit_image_check_comp() reads image compression property and compares its
142953fbb7e8SSimon Glass  * numeric id with the requested compression type. Comparison result is
143053fbb7e8SSimon Glass  * returned to the caller.
143153fbb7e8SSimon Glass  *
143253fbb7e8SSimon Glass  * returns:
143353fbb7e8SSimon Glass  *     1 if image uses requested compression
143453fbb7e8SSimon Glass  *     0 otherwise (or on error)
143553fbb7e8SSimon Glass  */
fit_image_check_comp(const void * fit,int noffset,uint8_t comp)143653fbb7e8SSimon Glass int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
143753fbb7e8SSimon Glass {
143853fbb7e8SSimon Glass 	uint8_t image_comp;
143953fbb7e8SSimon Glass 
144053fbb7e8SSimon Glass 	if (fit_image_get_comp(fit, noffset, &image_comp))
144153fbb7e8SSimon Glass 		return 0;
144253fbb7e8SSimon Glass 	return (comp == image_comp);
144353fbb7e8SSimon Glass }
144453fbb7e8SSimon Glass 
144553fbb7e8SSimon Glass /**
144653fbb7e8SSimon Glass  * fit_check_format - sanity check FIT image format
144753fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
144853fbb7e8SSimon Glass  *
144953fbb7e8SSimon Glass  * fit_check_format() runs a basic sanity FIT image verification.
145053fbb7e8SSimon Glass  * Routine checks for mandatory properties, nodes, etc.
145153fbb7e8SSimon Glass  *
145253fbb7e8SSimon Glass  * returns:
145353fbb7e8SSimon Glass  *     1, on success
145453fbb7e8SSimon Glass  *     0, on failure
145553fbb7e8SSimon Glass  */
fit_check_format(const void * fit)145653fbb7e8SSimon Glass int fit_check_format(const void *fit)
145753fbb7e8SSimon Glass {
1458a7fc7ebfSHeinrich Schuchardt 	/* A FIT image must be a valid FDT */
1459a7fc7ebfSHeinrich Schuchardt 	if (fdt_check_header(fit)) {
1460a7fc7ebfSHeinrich Schuchardt 		debug("Wrong FIT format: not a flattened device tree\n");
1461a7fc7ebfSHeinrich Schuchardt 		return 0;
1462a7fc7ebfSHeinrich Schuchardt 	}
1463a7fc7ebfSHeinrich Schuchardt 
146453fbb7e8SSimon Glass 	/* mandatory / node 'description' property */
146553fbb7e8SSimon Glass 	if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
146653fbb7e8SSimon Glass 		debug("Wrong FIT format: no description\n");
146753fbb7e8SSimon Glass 		return 0;
146853fbb7e8SSimon Glass 	}
146953fbb7e8SSimon Glass 
147053fbb7e8SSimon Glass 	if (IMAGE_ENABLE_TIMESTAMP) {
147153fbb7e8SSimon Glass 		/* mandatory / node 'timestamp' property */
147253fbb7e8SSimon Glass 		if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
147353fbb7e8SSimon Glass 			debug("Wrong FIT format: no timestamp\n");
147453fbb7e8SSimon Glass 			return 0;
147553fbb7e8SSimon Glass 		}
147653fbb7e8SSimon Glass 	}
147753fbb7e8SSimon Glass 
147853fbb7e8SSimon Glass 	/* mandatory subimages parent '/images' node */
147953fbb7e8SSimon Glass 	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
148053fbb7e8SSimon Glass 		debug("Wrong FIT format: no images parent node\n");
148153fbb7e8SSimon Glass 		return 0;
148253fbb7e8SSimon Glass 	}
148353fbb7e8SSimon Glass 
148453fbb7e8SSimon Glass 	return 1;
148553fbb7e8SSimon Glass }
148653fbb7e8SSimon Glass 
148753fbb7e8SSimon Glass 
148853fbb7e8SSimon Glass /**
148953fbb7e8SSimon Glass  * fit_conf_find_compat
149053fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
149153fbb7e8SSimon Glass  * @fdt: pointer to the device tree to compare against
149253fbb7e8SSimon Glass  *
149353fbb7e8SSimon Glass  * fit_conf_find_compat() attempts to find the configuration whose fdt is the
149453fbb7e8SSimon Glass  * most compatible with the passed in device tree.
149553fbb7e8SSimon Glass  *
149653fbb7e8SSimon Glass  * Example:
149753fbb7e8SSimon Glass  *
149853fbb7e8SSimon Glass  * / o image-tree
149953fbb7e8SSimon Glass  *   |-o images
1500b2267e8aSAndre Przywara  *   | |-o fdt-1
1501b2267e8aSAndre Przywara  *   | |-o fdt-2
150253fbb7e8SSimon Glass  *   |
150353fbb7e8SSimon Glass  *   |-o configurations
1504b2267e8aSAndre Przywara  *     |-o config-1
1505b2267e8aSAndre Przywara  *     | |-fdt = fdt-1
150653fbb7e8SSimon Glass  *     |
1507b2267e8aSAndre Przywara  *     |-o config-2
1508b2267e8aSAndre Przywara  *       |-fdt = fdt-2
150953fbb7e8SSimon Glass  *
151053fbb7e8SSimon Glass  * / o U-Boot fdt
151153fbb7e8SSimon Glass  *   |-compatible = "foo,bar", "bim,bam"
151253fbb7e8SSimon Glass  *
151353fbb7e8SSimon Glass  * / o kernel fdt1
151453fbb7e8SSimon Glass  *   |-compatible = "foo,bar",
151553fbb7e8SSimon Glass  *
151653fbb7e8SSimon Glass  * / o kernel fdt2
151753fbb7e8SSimon Glass  *   |-compatible = "bim,bam", "baz,biz"
151853fbb7e8SSimon Glass  *
151953fbb7e8SSimon Glass  * Configuration 1 would be picked because the first string in U-Boot's
152053fbb7e8SSimon Glass  * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
152153fbb7e8SSimon Glass  * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
152253fbb7e8SSimon Glass  *
152353fbb7e8SSimon Glass  * returns:
152453fbb7e8SSimon Glass  *     offset to the configuration to use if one was found
152553fbb7e8SSimon Glass  *     -1 otherwise
152653fbb7e8SSimon Glass  */
fit_conf_find_compat(const void * fit,const void * fdt)152753fbb7e8SSimon Glass int fit_conf_find_compat(const void *fit, const void *fdt)
152853fbb7e8SSimon Glass {
152953fbb7e8SSimon Glass 	int ndepth = 0;
153053fbb7e8SSimon Glass 	int noffset, confs_noffset, images_noffset;
153153fbb7e8SSimon Glass 	const void *fdt_compat;
153253fbb7e8SSimon Glass 	int fdt_compat_len;
153353fbb7e8SSimon Glass 	int best_match_offset = 0;
153453fbb7e8SSimon Glass 	int best_match_pos = 0;
153553fbb7e8SSimon Glass 
153653fbb7e8SSimon Glass 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
153753fbb7e8SSimon Glass 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
153853fbb7e8SSimon Glass 	if (confs_noffset < 0 || images_noffset < 0) {
153953fbb7e8SSimon Glass 		debug("Can't find configurations or images nodes.\n");
154053fbb7e8SSimon Glass 		return -1;
154153fbb7e8SSimon Glass 	}
154253fbb7e8SSimon Glass 
154353fbb7e8SSimon Glass 	fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
154453fbb7e8SSimon Glass 	if (!fdt_compat) {
154553fbb7e8SSimon Glass 		debug("Fdt for comparison has no \"compatible\" property.\n");
154653fbb7e8SSimon Glass 		return -1;
154753fbb7e8SSimon Glass 	}
154853fbb7e8SSimon Glass 
154953fbb7e8SSimon Glass 	/*
155053fbb7e8SSimon Glass 	 * Loop over the configurations in the FIT image.
155153fbb7e8SSimon Glass 	 */
155253fbb7e8SSimon Glass 	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
155353fbb7e8SSimon Glass 			(noffset >= 0) && (ndepth > 0);
155453fbb7e8SSimon Glass 			noffset = fdt_next_node(fit, noffset, &ndepth)) {
155553fbb7e8SSimon Glass 		const void *kfdt;
155653fbb7e8SSimon Glass 		const char *kfdt_name;
155753fbb7e8SSimon Glass 		int kfdt_noffset;
155853fbb7e8SSimon Glass 		const char *cur_fdt_compat;
155953fbb7e8SSimon Glass 		int len;
156053fbb7e8SSimon Glass 		size_t size;
156153fbb7e8SSimon Glass 		int i;
156253fbb7e8SSimon Glass 
156353fbb7e8SSimon Glass 		if (ndepth > 1)
156453fbb7e8SSimon Glass 			continue;
156553fbb7e8SSimon Glass 
156653fbb7e8SSimon Glass 		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
156753fbb7e8SSimon Glass 		if (!kfdt_name) {
156853fbb7e8SSimon Glass 			debug("No fdt property found.\n");
156953fbb7e8SSimon Glass 			continue;
157053fbb7e8SSimon Glass 		}
157153fbb7e8SSimon Glass 		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
157253fbb7e8SSimon Glass 						  kfdt_name);
157353fbb7e8SSimon Glass 		if (kfdt_noffset < 0) {
157453fbb7e8SSimon Glass 			debug("No image node named \"%s\" found.\n",
157553fbb7e8SSimon Glass 			      kfdt_name);
157653fbb7e8SSimon Glass 			continue;
157753fbb7e8SSimon Glass 		}
157853fbb7e8SSimon Glass 		/*
157953fbb7e8SSimon Glass 		 * Get a pointer to this configuration's fdt.
158053fbb7e8SSimon Glass 		 */
158153fbb7e8SSimon Glass 		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
158253fbb7e8SSimon Glass 			debug("Failed to get fdt \"%s\".\n", kfdt_name);
158353fbb7e8SSimon Glass 			continue;
158453fbb7e8SSimon Glass 		}
158553fbb7e8SSimon Glass 
158653fbb7e8SSimon Glass 		len = fdt_compat_len;
158753fbb7e8SSimon Glass 		cur_fdt_compat = fdt_compat;
158853fbb7e8SSimon Glass 		/*
158953fbb7e8SSimon Glass 		 * Look for a match for each U-Boot compatibility string in
159053fbb7e8SSimon Glass 		 * turn in this configuration's fdt.
159153fbb7e8SSimon Glass 		 */
159253fbb7e8SSimon Glass 		for (i = 0; len > 0 &&
159353fbb7e8SSimon Glass 		     (!best_match_offset || best_match_pos > i); i++) {
159453fbb7e8SSimon Glass 			int cur_len = strlen(cur_fdt_compat) + 1;
159553fbb7e8SSimon Glass 
159653fbb7e8SSimon Glass 			if (!fdt_node_check_compatible(kfdt, 0,
159753fbb7e8SSimon Glass 						       cur_fdt_compat)) {
159853fbb7e8SSimon Glass 				best_match_offset = noffset;
159953fbb7e8SSimon Glass 				best_match_pos = i;
160053fbb7e8SSimon Glass 				break;
160153fbb7e8SSimon Glass 			}
160253fbb7e8SSimon Glass 			len -= cur_len;
160353fbb7e8SSimon Glass 			cur_fdt_compat += cur_len;
160453fbb7e8SSimon Glass 		}
160553fbb7e8SSimon Glass 	}
160653fbb7e8SSimon Glass 	if (!best_match_offset) {
160753fbb7e8SSimon Glass 		debug("No match found.\n");
160853fbb7e8SSimon Glass 		return -1;
160953fbb7e8SSimon Glass 	}
161053fbb7e8SSimon Glass 
161153fbb7e8SSimon Glass 	return best_match_offset;
161253fbb7e8SSimon Glass }
161353fbb7e8SSimon Glass 
161453fbb7e8SSimon Glass /**
161553fbb7e8SSimon Glass  * fit_conf_get_node - get node offset for configuration of a given unit name
161653fbb7e8SSimon Glass  * @fit: pointer to the FIT format image header
161753fbb7e8SSimon Glass  * @conf_uname: configuration node unit name
161853fbb7e8SSimon Glass  *
1619e17adbb3SAndreas Dannenberg  * fit_conf_get_node() finds a configuration (within the '/configurations'
1620e17adbb3SAndreas Dannenberg  * parent node) of a provided unit name. If configuration is found its node
162153fbb7e8SSimon Glass  * offset is returned to the caller.
162253fbb7e8SSimon Glass  *
162353fbb7e8SSimon Glass  * When NULL is provided in second argument fit_conf_get_node() will search
162453fbb7e8SSimon Glass  * for a default configuration node instead. Default configuration node unit
16251f8b546fSRobert P. J. Day  * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
162653fbb7e8SSimon Glass  * node.
162753fbb7e8SSimon Glass  *
162853fbb7e8SSimon Glass  * returns:
162953fbb7e8SSimon Glass  *     configuration node offset when found (>=0)
163053fbb7e8SSimon Glass  *     negative number on failure (FDT_ERR_* code)
163153fbb7e8SSimon Glass  */
fit_conf_get_node(const void * fit,const char * conf_uname)163253fbb7e8SSimon Glass int fit_conf_get_node(const void *fit, const char *conf_uname)
163353fbb7e8SSimon Glass {
163453fbb7e8SSimon Glass 	int noffset, confs_noffset;
163553fbb7e8SSimon Glass 	int len;
1636169043d8SPantelis Antoniou 	const char *s;
1637169043d8SPantelis Antoniou 	char *conf_uname_copy = NULL;
163853fbb7e8SSimon Glass 
163953fbb7e8SSimon Glass 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
164053fbb7e8SSimon Glass 	if (confs_noffset < 0) {
164153fbb7e8SSimon Glass 		debug("Can't find configurations parent node '%s' (%s)\n",
164253fbb7e8SSimon Glass 		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
164353fbb7e8SSimon Glass 		return confs_noffset;
164453fbb7e8SSimon Glass 	}
164553fbb7e8SSimon Glass 
164653fbb7e8SSimon Glass 	if (conf_uname == NULL) {
164753fbb7e8SSimon Glass 		/* get configuration unit name from the default property */
164853fbb7e8SSimon Glass 		debug("No configuration specified, trying default...\n");
164953fbb7e8SSimon Glass 		conf_uname = (char *)fdt_getprop(fit, confs_noffset,
165053fbb7e8SSimon Glass 						 FIT_DEFAULT_PROP, &len);
165153fbb7e8SSimon Glass 		if (conf_uname == NULL) {
165253fbb7e8SSimon Glass 			fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
165353fbb7e8SSimon Glass 				      len);
165453fbb7e8SSimon Glass 			return len;
165553fbb7e8SSimon Glass 		}
165653fbb7e8SSimon Glass 		debug("Found default configuration: '%s'\n", conf_uname);
165753fbb7e8SSimon Glass 	}
165853fbb7e8SSimon Glass 
1659169043d8SPantelis Antoniou 	s = strchr(conf_uname, '#');
1660169043d8SPantelis Antoniou 	if (s) {
1661169043d8SPantelis Antoniou 		len = s - conf_uname;
1662169043d8SPantelis Antoniou 		conf_uname_copy = malloc(len + 1);
1663169043d8SPantelis Antoniou 		if (!conf_uname_copy) {
1664169043d8SPantelis Antoniou 			debug("Can't allocate uname copy: '%s'\n",
1665169043d8SPantelis Antoniou 					conf_uname);
1666169043d8SPantelis Antoniou 			return -ENOMEM;
1667169043d8SPantelis Antoniou 		}
1668169043d8SPantelis Antoniou 		memcpy(conf_uname_copy, conf_uname, len);
1669169043d8SPantelis Antoniou 		conf_uname_copy[len] = '\0';
1670169043d8SPantelis Antoniou 		conf_uname = conf_uname_copy;
1671169043d8SPantelis Antoniou 	}
1672169043d8SPantelis Antoniou 
167353fbb7e8SSimon Glass 	noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
167453fbb7e8SSimon Glass 	if (noffset < 0) {
167553fbb7e8SSimon Glass 		debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
167653fbb7e8SSimon Glass 		      conf_uname, fdt_strerror(noffset));
167753fbb7e8SSimon Glass 	}
167853fbb7e8SSimon Glass 
1679169043d8SPantelis Antoniou 	if (conf_uname_copy)
1680169043d8SPantelis Antoniou 		free(conf_uname_copy);
1681169043d8SPantelis Antoniou 
168253fbb7e8SSimon Glass 	return noffset;
168353fbb7e8SSimon Glass }
168453fbb7e8SSimon Glass 
fit_conf_get_prop_node_count(const void * fit,int noffset,const char * prop_name)1685ad026adbSPantelis Antoniou int fit_conf_get_prop_node_count(const void *fit, int noffset,
168653fbb7e8SSimon Glass 		const char *prop_name)
168753fbb7e8SSimon Glass {
1688ad026adbSPantelis Antoniou 	return fdt_stringlist_count(fit, noffset, prop_name);
1689ad026adbSPantelis Antoniou }
1690ad026adbSPantelis Antoniou 
fit_conf_get_prop_node_index(const void * fit,int noffset,const char * prop_name,int index)1691ad026adbSPantelis Antoniou int fit_conf_get_prop_node_index(const void *fit, int noffset,
1692ad026adbSPantelis Antoniou 		const char *prop_name, int index)
1693ad026adbSPantelis Antoniou {
1694ad026adbSPantelis Antoniou 	const char *uname;
169553fbb7e8SSimon Glass 	int len;
169653fbb7e8SSimon Glass 
169753fbb7e8SSimon Glass 	/* get kernel image unit name from configuration kernel property */
1698ad026adbSPantelis Antoniou 	uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len);
169953fbb7e8SSimon Glass 	if (uname == NULL)
170053fbb7e8SSimon Glass 		return len;
170153fbb7e8SSimon Glass 
170253fbb7e8SSimon Glass 	return fit_image_get_node(fit, uname);
170353fbb7e8SSimon Glass }
170453fbb7e8SSimon Glass 
fit_conf_get_prop_node(const void * fit,int noffset,const char * prop_name)1705ad026adbSPantelis Antoniou int fit_conf_get_prop_node(const void *fit, int noffset,
1706ad026adbSPantelis Antoniou 		const char *prop_name)
1707ad026adbSPantelis Antoniou {
1708ad026adbSPantelis Antoniou 	return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
1709ad026adbSPantelis Antoniou }
1710ad026adbSPantelis Antoniou 
fit_image_select(const void * fit,int rd_noffset,int verify)1711718fecaeSJeroen Hofstee static int fit_image_select(const void *fit, int rd_noffset, int verify)
1712782cfbb2SSimon Glass {
1713782cfbb2SSimon Glass 	fit_image_print(fit, rd_noffset, "   ");
1714782cfbb2SSimon Glass 
1715782cfbb2SSimon Glass 	if (verify) {
1716782cfbb2SSimon Glass 		puts("   Verifying Hash Integrity ... ");
1717782cfbb2SSimon Glass 		if (!fit_image_verify(fit, rd_noffset)) {
1718782cfbb2SSimon Glass 			puts("Bad Data Hash\n");
1719782cfbb2SSimon Glass 			return -EACCES;
1720782cfbb2SSimon Glass 		}
1721782cfbb2SSimon Glass 		puts("OK\n");
1722782cfbb2SSimon Glass 	}
1723782cfbb2SSimon Glass 
1724782cfbb2SSimon Glass 	return 0;
1725782cfbb2SSimon Glass }
1726782cfbb2SSimon Glass 
fit_get_node_from_config(bootm_headers_t * images,const char * prop_name,ulong addr)1727782cfbb2SSimon Glass int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
1728782cfbb2SSimon Glass 			ulong addr)
1729782cfbb2SSimon Glass {
1730782cfbb2SSimon Glass 	int cfg_noffset;
1731782cfbb2SSimon Glass 	void *fit_hdr;
1732782cfbb2SSimon Glass 	int noffset;
1733782cfbb2SSimon Glass 
1734782cfbb2SSimon Glass 	debug("*  %s: using config '%s' from image at 0x%08lx\n",
1735782cfbb2SSimon Glass 	      prop_name, images->fit_uname_cfg, addr);
1736782cfbb2SSimon Glass 
1737782cfbb2SSimon Glass 	/* Check whether configuration has this property defined */
1738782cfbb2SSimon Glass 	fit_hdr = map_sysmem(addr, 0);
1739782cfbb2SSimon Glass 	cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
1740782cfbb2SSimon Glass 	if (cfg_noffset < 0) {
1741782cfbb2SSimon Glass 		debug("*  %s: no such config\n", prop_name);
1742bd86ef11SPaul Burton 		return -EINVAL;
1743782cfbb2SSimon Glass 	}
1744782cfbb2SSimon Glass 
1745782cfbb2SSimon Glass 	noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
1746782cfbb2SSimon Glass 	if (noffset < 0) {
1747782cfbb2SSimon Glass 		debug("*  %s: no '%s' in config\n", prop_name, prop_name);
1748bac17b78SJonathan Gray 		return -ENOENT;
1749782cfbb2SSimon Glass 	}
1750782cfbb2SSimon Glass 
1751782cfbb2SSimon Glass 	return noffset;
1752782cfbb2SSimon Glass }
1753782cfbb2SSimon Glass 
1754126cc864SSimon Glass /**
1755126cc864SSimon Glass  * fit_get_image_type_property() - get property name for IH_TYPE_...
1756126cc864SSimon Glass  *
1757126cc864SSimon Glass  * @return the properly name where we expect to find the image in the
1758126cc864SSimon Glass  * config node
1759126cc864SSimon Glass  */
fit_get_image_type_property(int type)1760126cc864SSimon Glass static const char *fit_get_image_type_property(int type)
1761126cc864SSimon Glass {
1762126cc864SSimon Glass 	/*
1763126cc864SSimon Glass 	 * This is sort-of available in the uimage_type[] table in image.c
1764e17adbb3SAndreas Dannenberg 	 * but we don't have access to the short name, and "fdt" is different
1765126cc864SSimon Glass 	 * anyway. So let's just keep it here.
1766126cc864SSimon Glass 	 */
1767126cc864SSimon Glass 	switch (type) {
1768126cc864SSimon Glass 	case IH_TYPE_FLATDT:
1769126cc864SSimon Glass 		return FIT_FDT_PROP;
1770126cc864SSimon Glass 	case IH_TYPE_KERNEL:
1771126cc864SSimon Glass 		return FIT_KERNEL_PROP;
1772126cc864SSimon Glass 	case IH_TYPE_RAMDISK:
1773126cc864SSimon Glass 		return FIT_RAMDISK_PROP;
177490268b87SSimon Glass 	case IH_TYPE_X86_SETUP:
177590268b87SSimon Glass 		return FIT_SETUP_PROP;
177684a07dbfSKarl Apsite 	case IH_TYPE_LOADABLE:
177784a07dbfSKarl Apsite 		return FIT_LOADABLE_PROP;
177862afc601SMichal Simek 	case IH_TYPE_FPGA:
177962afc601SMichal Simek 		return FIT_FPGA_PROP;
17800298d203SMarek Vasut 	case IH_TYPE_STANDALONE:
17810298d203SMarek Vasut 		return FIT_STANDALONE_PROP;
1782126cc864SSimon Glass 	}
1783126cc864SSimon Glass 
1784126cc864SSimon Glass 	return "unknown";
1785126cc864SSimon Glass }
1786126cc864SSimon Glass 
fit_image_load(bootm_headers_t * images,ulong addr,const char ** fit_unamep,const char ** fit_uname_configp,int arch,int image_type,int bootstage_id,enum fit_load_op load_op,ulong * datap,ulong * lenp)1787126cc864SSimon Glass int fit_image_load(bootm_headers_t *images, ulong addr,
1788f320a4d8SSimon Glass 		   const char **fit_unamep, const char **fit_uname_configp,
1789782cfbb2SSimon Glass 		   int arch, int image_type, int bootstage_id,
1790782cfbb2SSimon Glass 		   enum fit_load_op load_op, ulong *datap, ulong *lenp)
1791782cfbb2SSimon Glass {
1792782cfbb2SSimon Glass 	int cfg_noffset, noffset;
1793782cfbb2SSimon Glass 	const char *fit_uname;
1794f320a4d8SSimon Glass 	const char *fit_uname_config;
17957c3dc776SPantelis Antoniou 	const char *fit_base_uname_config;
1796782cfbb2SSimon Glass 	const void *fit;
1797782cfbb2SSimon Glass 	const void *buf;
1798782cfbb2SSimon Glass 	size_t size;
1799782cfbb2SSimon Glass 	int type_ok, os_ok;
1800782cfbb2SSimon Glass 	ulong load, data, len;
180138117231SMarek Vasut 	uint8_t os;
1802ec6617c3SAlison Wang #ifndef USE_HOSTCC
1803ec6617c3SAlison Wang 	uint8_t os_arch;
1804ec6617c3SAlison Wang #endif
1805126cc864SSimon Glass 	const char *prop_name;
1806782cfbb2SSimon Glass 	int ret;
1807782cfbb2SSimon Glass 
1808782cfbb2SSimon Glass 	fit = map_sysmem(addr, 0);
1809782cfbb2SSimon Glass 	fit_uname = fit_unamep ? *fit_unamep : NULL;
1810f320a4d8SSimon Glass 	fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
18117c3dc776SPantelis Antoniou 	fit_base_uname_config = NULL;
1812126cc864SSimon Glass 	prop_name = fit_get_image_type_property(image_type);
1813782cfbb2SSimon Glass 	printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
1814782cfbb2SSimon Glass 
1815782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
1816782cfbb2SSimon Glass 	if (!fit_check_format(fit)) {
1817782cfbb2SSimon Glass 		printf("Bad FIT %s image format!\n", prop_name);
1818782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
1819782cfbb2SSimon Glass 		return -ENOEXEC;
1820782cfbb2SSimon Glass 	}
1821782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
1822782cfbb2SSimon Glass 	if (fit_uname) {
1823f150c837SMasahiro Yamada 		/* get FIT component image node offset */
1824782cfbb2SSimon Glass 		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
1825782cfbb2SSimon Glass 		noffset = fit_image_get_node(fit, fit_uname);
1826782cfbb2SSimon Glass 	} else {
1827782cfbb2SSimon Glass 		/*
1828782cfbb2SSimon Glass 		 * no image node unit name, try to get config
1829782cfbb2SSimon Glass 		 * node first. If config unit node name is NULL
1830782cfbb2SSimon Glass 		 * fit_conf_get_node() will try to find default config node
1831782cfbb2SSimon Glass 		 */
1832782cfbb2SSimon Glass 		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
1833782cfbb2SSimon Glass 		if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) {
1834782cfbb2SSimon Glass 			cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
1835782cfbb2SSimon Glass 		} else {
1836782cfbb2SSimon Glass 			cfg_noffset = fit_conf_get_node(fit,
1837782cfbb2SSimon Glass 							fit_uname_config);
1838782cfbb2SSimon Glass 		}
1839782cfbb2SSimon Glass 		if (cfg_noffset < 0) {
1840782cfbb2SSimon Glass 			puts("Could not find configuration node\n");
1841782cfbb2SSimon Glass 			bootstage_error(bootstage_id +
1842782cfbb2SSimon Glass 					BOOTSTAGE_SUB_NO_UNIT_NAME);
1843782cfbb2SSimon Glass 			return -ENOENT;
1844782cfbb2SSimon Glass 		}
1845078e5586SMarek Vasut 
18467c3dc776SPantelis Antoniou 		fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
18477c3dc776SPantelis Antoniou 		printf("   Using '%s' configuration\n", fit_base_uname_config);
1848078e5586SMarek Vasut 		/* Remember this config */
1849078e5586SMarek Vasut 		if (image_type == IH_TYPE_KERNEL)
18507c3dc776SPantelis Antoniou 			images->fit_uname_cfg = fit_base_uname_config;
1851078e5586SMarek Vasut 
1852782cfbb2SSimon Glass 		if (IMAGE_ENABLE_VERIFY && images->verify) {
1853782cfbb2SSimon Glass 			puts("   Verifying Hash Integrity ... ");
185412df2abeSSimon Glass 			if (fit_config_verify(fit, cfg_noffset)) {
1855782cfbb2SSimon Glass 				puts("Bad Data Hash\n");
1856782cfbb2SSimon Glass 				bootstage_error(bootstage_id +
1857782cfbb2SSimon Glass 					BOOTSTAGE_SUB_HASH);
1858782cfbb2SSimon Glass 				return -EACCES;
1859782cfbb2SSimon Glass 			}
1860782cfbb2SSimon Glass 			puts("OK\n");
1861782cfbb2SSimon Glass 		}
1862078e5586SMarek Vasut 
1863782cfbb2SSimon Glass 		bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
1864782cfbb2SSimon Glass 
1865782cfbb2SSimon Glass 		noffset = fit_conf_get_prop_node(fit, cfg_noffset,
1866782cfbb2SSimon Glass 						 prop_name);
1867782cfbb2SSimon Glass 		fit_uname = fit_get_name(fit, noffset, NULL);
1868782cfbb2SSimon Glass 	}
1869782cfbb2SSimon Glass 	if (noffset < 0) {
1870d7d71113SSimon Glass 		printf("Could not find subimage node type '%s'\n", prop_name);
1871782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
1872782cfbb2SSimon Glass 		return -ENOENT;
1873782cfbb2SSimon Glass 	}
1874782cfbb2SSimon Glass 
1875782cfbb2SSimon Glass 	printf("   Trying '%s' %s subimage\n", fit_uname, prop_name);
1876782cfbb2SSimon Glass 
1877782cfbb2SSimon Glass 	ret = fit_image_select(fit, noffset, images->verify);
1878782cfbb2SSimon Glass 	if (ret) {
1879782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
1880782cfbb2SSimon Glass 		return ret;
1881782cfbb2SSimon Glass 	}
1882782cfbb2SSimon Glass 
1883782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
18845ba63dd4SSimon Glass #if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX)
1885782cfbb2SSimon Glass 	if (!fit_image_check_target_arch(fit, noffset)) {
1886782cfbb2SSimon Glass 		puts("Unsupported Architecture\n");
1887782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
1888782cfbb2SSimon Glass 		return -ENOEXEC;
1889782cfbb2SSimon Glass 	}
1890ce1400f6SSimon Glass #endif
1891ec6617c3SAlison Wang 
1892ec6617c3SAlison Wang #ifndef USE_HOSTCC
1893ec6617c3SAlison Wang 	fit_image_get_arch(fit, noffset, &os_arch);
1894ec6617c3SAlison Wang 	images->os.arch = os_arch;
1895ec6617c3SAlison Wang #endif
1896ec6617c3SAlison Wang 
1897782cfbb2SSimon Glass 	if (image_type == IH_TYPE_FLATDT &&
1898782cfbb2SSimon Glass 	    !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
1899782cfbb2SSimon Glass 		puts("FDT image is compressed");
1900782cfbb2SSimon Glass 		return -EPROTONOSUPPORT;
1901782cfbb2SSimon Glass 	}
1902782cfbb2SSimon Glass 
1903782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
1904782cfbb2SSimon Glass 	type_ok = fit_image_check_type(fit, noffset, image_type) ||
1905e8fb4358Smario.six@gdsys.cc 		  fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
1906782cfbb2SSimon Glass 		  (image_type == IH_TYPE_KERNEL &&
1907e8fb4358Smario.six@gdsys.cc 		   fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD));
190838117231SMarek Vasut 
1909950fe26dSAndreas Bießmann 	os_ok = image_type == IH_TYPE_FLATDT ||
1910950fe26dSAndreas Bießmann 		image_type == IH_TYPE_FPGA ||
191138117231SMarek Vasut 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
1912e8fb4358Smario.six@gdsys.cc 		fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
191338117231SMarek Vasut 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
191484a07dbfSKarl Apsite 
191584a07dbfSKarl Apsite 	/*
191684a07dbfSKarl Apsite 	 * If either of the checks fail, we should report an error, but
191784a07dbfSKarl Apsite 	 * if the image type is coming from the "loadables" field, we
191884a07dbfSKarl Apsite 	 * don't care what it is
191984a07dbfSKarl Apsite 	 */
192084a07dbfSKarl Apsite 	if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) {
192138117231SMarek Vasut 		fit_image_get_os(fit, noffset, &os);
192238117231SMarek Vasut 		printf("No %s %s %s Image\n",
192338117231SMarek Vasut 		       genimg_get_os_name(os),
192438117231SMarek Vasut 		       genimg_get_arch_name(arch),
1925782cfbb2SSimon Glass 		       genimg_get_type_name(image_type));
1926782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
1927782cfbb2SSimon Glass 		return -EIO;
1928782cfbb2SSimon Glass 	}
1929782cfbb2SSimon Glass 
1930782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
1931782cfbb2SSimon Glass 
1932782cfbb2SSimon Glass 	/* get image data address and length */
1933c3c86388SKelvin Cheung 	if (fit_image_get_data_and_size(fit, noffset, &buf, &size)) {
1934782cfbb2SSimon Glass 		printf("Could not find %s subimage data!\n", prop_name);
1935782cfbb2SSimon Glass 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
19362f998071SSimon Glass 		return -ENOENT;
1937782cfbb2SSimon Glass 	}
193844402fe7SAndrew F. Davis 
193944402fe7SAndrew F. Davis #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
194044402fe7SAndrew F. Davis 	/* perform any post-processing on the image data */
1941*b7d9107fSChia-Wei Wang 	board_fit_image_post_process(fit, noffset, (void **)&buf, &size);
194244402fe7SAndrew F. Davis #endif
194344402fe7SAndrew F. Davis 
1944782cfbb2SSimon Glass 	len = (ulong)size;
1945782cfbb2SSimon Glass 
1946782cfbb2SSimon Glass 	/* verify that image data is a proper FDT blob */
19472f0877c7SMasahiro Yamada 	if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
1948782cfbb2SSimon Glass 		puts("Subimage data is not a FDT");
1949782cfbb2SSimon Glass 		return -ENOEXEC;
1950782cfbb2SSimon Glass 	}
1951782cfbb2SSimon Glass 
1952782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
1953782cfbb2SSimon Glass 
1954782cfbb2SSimon Glass 	/*
1955782cfbb2SSimon Glass 	 * Work-around for eldk-4.2 which gives this warning if we try to
1956e3c83c0aSSimon Glass 	 * cast in the unmap_sysmem() call:
1957782cfbb2SSimon Glass 	 * warning: initialization discards qualifiers from pointer target type
1958782cfbb2SSimon Glass 	 */
1959782cfbb2SSimon Glass 	{
1960782cfbb2SSimon Glass 		void *vbuf = (void *)buf;
1961782cfbb2SSimon Glass 
1962782cfbb2SSimon Glass 		data = map_to_sysmem(vbuf);
1963782cfbb2SSimon Glass 	}
1964782cfbb2SSimon Glass 
1965782cfbb2SSimon Glass 	if (load_op == FIT_LOAD_IGNORED) {
1966782cfbb2SSimon Glass 		/* Don't load */
1967782cfbb2SSimon Glass 	} else if (fit_image_get_load(fit, noffset, &load)) {
1968782cfbb2SSimon Glass 		if (load_op == FIT_LOAD_REQUIRED) {
1969782cfbb2SSimon Glass 			printf("Can't get %s subimage load address!\n",
1970782cfbb2SSimon Glass 			       prop_name);
1971782cfbb2SSimon Glass 			bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
1972782cfbb2SSimon Glass 			return -EBADF;
1973782cfbb2SSimon Glass 		}
1974fe20a81aSSimon Glass 	} else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
1975782cfbb2SSimon Glass 		ulong image_start, image_end;
1976782cfbb2SSimon Glass 		ulong load_end;
1977782cfbb2SSimon Glass 		void *dst;
1978782cfbb2SSimon Glass 
1979782cfbb2SSimon Glass 		/*
1980782cfbb2SSimon Glass 		 * move image data to the load address,
1981782cfbb2SSimon Glass 		 * make sure we don't overwrite initial image
1982782cfbb2SSimon Glass 		 */
1983782cfbb2SSimon Glass 		image_start = addr;
1984782cfbb2SSimon Glass 		image_end = addr + fit_get_size(fit);
1985782cfbb2SSimon Glass 
1986782cfbb2SSimon Glass 		load_end = load + len;
1987782cfbb2SSimon Glass 		if (image_type != IH_TYPE_KERNEL &&
1988782cfbb2SSimon Glass 		    load < image_end && load_end > image_start) {
1989782cfbb2SSimon Glass 			printf("Error: %s overwritten\n", prop_name);
1990782cfbb2SSimon Glass 			return -EXDEV;
1991782cfbb2SSimon Glass 		}
1992782cfbb2SSimon Glass 
1993782cfbb2SSimon Glass 		printf("   Loading %s from 0x%08lx to 0x%08lx\n",
1994782cfbb2SSimon Glass 		       prop_name, data, load);
1995782cfbb2SSimon Glass 
1996782cfbb2SSimon Glass 		dst = map_sysmem(load, len);
1997782cfbb2SSimon Glass 		memmove(dst, buf, len);
1998782cfbb2SSimon Glass 		data = load;
1999782cfbb2SSimon Glass 	}
2000782cfbb2SSimon Glass 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
2001782cfbb2SSimon Glass 
2002782cfbb2SSimon Glass 	*datap = data;
2003782cfbb2SSimon Glass 	*lenp = len;
2004782cfbb2SSimon Glass 	if (fit_unamep)
2005782cfbb2SSimon Glass 		*fit_unamep = (char *)fit_uname;
2006f320a4d8SSimon Glass 	if (fit_uname_configp)
20077c3dc776SPantelis Antoniou 		*fit_uname_configp = (char *)(fit_uname_config ? :
20087c3dc776SPantelis Antoniou 					      fit_base_uname_config);
2009782cfbb2SSimon Glass 
2010782cfbb2SSimon Glass 	return noffset;
2011782cfbb2SSimon Glass }
201290268b87SSimon Glass 
boot_get_setup_fit(bootm_headers_t * images,uint8_t arch,ulong * setup_start,ulong * setup_len)201390268b87SSimon Glass int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
201490268b87SSimon Glass 			ulong *setup_start, ulong *setup_len)
201590268b87SSimon Glass {
201690268b87SSimon Glass 	int noffset;
201790268b87SSimon Glass 	ulong addr;
201890268b87SSimon Glass 	ulong len;
201990268b87SSimon Glass 	int ret;
202090268b87SSimon Glass 
202190268b87SSimon Glass 	addr = map_to_sysmem(images->fit_hdr_os);
202290268b87SSimon Glass 	noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr);
202390268b87SSimon Glass 	if (noffset < 0)
202490268b87SSimon Glass 		return noffset;
202590268b87SSimon Glass 
202690268b87SSimon Glass 	ret = fit_image_load(images, addr, NULL, NULL, arch,
202790268b87SSimon Glass 			     IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START,
202890268b87SSimon Glass 			     FIT_LOAD_REQUIRED, setup_start, &len);
202990268b87SSimon Glass 
203090268b87SSimon Glass 	return ret;
203190268b87SSimon Glass }
2032169043d8SPantelis Antoniou 
2033169043d8SPantelis Antoniou #ifndef USE_HOSTCC
boot_get_fdt_fit(bootm_headers_t * images,ulong addr,const char ** fit_unamep,const char ** fit_uname_configp,int arch,ulong * datap,ulong * lenp)2034169043d8SPantelis Antoniou int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
2035169043d8SPantelis Antoniou 		   const char **fit_unamep, const char **fit_uname_configp,
2036169043d8SPantelis Antoniou 		   int arch, ulong *datap, ulong *lenp)
2037169043d8SPantelis Antoniou {
2038169043d8SPantelis Antoniou 	int fdt_noffset, cfg_noffset, count;
2039169043d8SPantelis Antoniou 	const void *fit;
2040169043d8SPantelis Antoniou 	const char *fit_uname = NULL;
2041169043d8SPantelis Antoniou 	const char *fit_uname_config = NULL;
2042169043d8SPantelis Antoniou 	char *fit_uname_config_copy = NULL;
2043169043d8SPantelis Antoniou 	char *next_config = NULL;
2044169043d8SPantelis Antoniou 	ulong load, len;
2045169043d8SPantelis Antoniou #ifdef CONFIG_OF_LIBFDT_OVERLAY
2046169043d8SPantelis Antoniou 	ulong image_start, image_end;
2047169043d8SPantelis Antoniou 	ulong ovload, ovlen;
2048169043d8SPantelis Antoniou 	const char *uconfig;
2049169043d8SPantelis Antoniou 	const char *uname;
2050169043d8SPantelis Antoniou 	void *base, *ov;
2051169043d8SPantelis Antoniou 	int i, err, noffset, ov_noffset;
2052169043d8SPantelis Antoniou #endif
2053169043d8SPantelis Antoniou 
2054169043d8SPantelis Antoniou 	fit_uname = fit_unamep ? *fit_unamep : NULL;
2055169043d8SPantelis Antoniou 
2056169043d8SPantelis Antoniou 	if (fit_uname_configp && *fit_uname_configp) {
2057169043d8SPantelis Antoniou 		fit_uname_config_copy = strdup(*fit_uname_configp);
2058169043d8SPantelis Antoniou 		if (!fit_uname_config_copy)
2059169043d8SPantelis Antoniou 			return -ENOMEM;
2060169043d8SPantelis Antoniou 
2061169043d8SPantelis Antoniou 		next_config = strchr(fit_uname_config_copy, '#');
2062169043d8SPantelis Antoniou 		if (next_config)
2063169043d8SPantelis Antoniou 			*next_config++ = '\0';
2064169043d8SPantelis Antoniou 		if (next_config - 1 > fit_uname_config_copy)
2065169043d8SPantelis Antoniou 			fit_uname_config = fit_uname_config_copy;
2066169043d8SPantelis Antoniou 	}
2067169043d8SPantelis Antoniou 
2068169043d8SPantelis Antoniou 	fdt_noffset = fit_image_load(images,
2069169043d8SPantelis Antoniou 		addr, &fit_uname, &fit_uname_config,
2070169043d8SPantelis Antoniou 		arch, IH_TYPE_FLATDT,
2071169043d8SPantelis Antoniou 		BOOTSTAGE_ID_FIT_FDT_START,
2072169043d8SPantelis Antoniou 		FIT_LOAD_OPTIONAL, &load, &len);
2073169043d8SPantelis Antoniou 
2074169043d8SPantelis Antoniou 	if (fdt_noffset < 0)
2075169043d8SPantelis Antoniou 		goto out;
2076169043d8SPantelis Antoniou 
2077169043d8SPantelis Antoniou 	debug("fit_uname=%s, fit_uname_config=%s\n",
2078169043d8SPantelis Antoniou 			fit_uname ? fit_uname : "<NULL>",
2079169043d8SPantelis Antoniou 			fit_uname_config ? fit_uname_config : "<NULL>");
2080169043d8SPantelis Antoniou 
2081169043d8SPantelis Antoniou 	fit = map_sysmem(addr, 0);
2082169043d8SPantelis Antoniou 
2083169043d8SPantelis Antoniou 	cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
2084169043d8SPantelis Antoniou 
2085169043d8SPantelis Antoniou 	/* single blob, or error just return as well */
2086169043d8SPantelis Antoniou 	count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP);
2087169043d8SPantelis Antoniou 	if (count <= 1 && !next_config)
2088169043d8SPantelis Antoniou 		goto out;
2089169043d8SPantelis Antoniou 
2090169043d8SPantelis Antoniou 	/* we need to apply overlays */
2091169043d8SPantelis Antoniou 
2092169043d8SPantelis Antoniou #ifdef CONFIG_OF_LIBFDT_OVERLAY
2093169043d8SPantelis Antoniou 	image_start = addr;
2094169043d8SPantelis Antoniou 	image_end = addr + fit_get_size(fit);
2095169043d8SPantelis Antoniou 	/* verify that relocation took place by load address not being in fit */
2096169043d8SPantelis Antoniou 	if (load >= image_start && load < image_end) {
2097169043d8SPantelis Antoniou 		/* check is simplified; fit load checks for overlaps */
2098169043d8SPantelis Antoniou 		printf("Overlayed FDT requires relocation\n");
2099169043d8SPantelis Antoniou 		fdt_noffset = -EBADF;
2100169043d8SPantelis Antoniou 		goto out;
2101169043d8SPantelis Antoniou 	}
2102169043d8SPantelis Antoniou 
2103169043d8SPantelis Antoniou 	base = map_sysmem(load, len);
2104169043d8SPantelis Antoniou 
2105169043d8SPantelis Antoniou 	/* apply extra configs in FIT first, followed by args */
2106169043d8SPantelis Antoniou 	for (i = 1; ; i++) {
2107169043d8SPantelis Antoniou 		if (i < count) {
2108169043d8SPantelis Antoniou 			noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
2109169043d8SPantelis Antoniou 							       FIT_FDT_PROP, i);
2110169043d8SPantelis Antoniou 			uname = fit_get_name(fit, noffset, NULL);
2111169043d8SPantelis Antoniou 			uconfig = NULL;
2112169043d8SPantelis Antoniou 		} else {
2113169043d8SPantelis Antoniou 			if (!next_config)
2114169043d8SPantelis Antoniou 				break;
2115169043d8SPantelis Antoniou 			uconfig = next_config;
2116169043d8SPantelis Antoniou 			next_config = strchr(next_config, '#');
2117169043d8SPantelis Antoniou 			if (next_config)
2118169043d8SPantelis Antoniou 				*next_config++ = '\0';
2119169043d8SPantelis Antoniou 			uname = NULL;
2120169043d8SPantelis Antoniou 		}
2121169043d8SPantelis Antoniou 
2122169043d8SPantelis Antoniou 		debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig);
2123169043d8SPantelis Antoniou 
2124169043d8SPantelis Antoniou 		ov_noffset = fit_image_load(images,
2125169043d8SPantelis Antoniou 			addr, &uname, &uconfig,
2126169043d8SPantelis Antoniou 			arch, IH_TYPE_FLATDT,
2127169043d8SPantelis Antoniou 			BOOTSTAGE_ID_FIT_FDT_START,
2128169043d8SPantelis Antoniou 			FIT_LOAD_REQUIRED, &ovload, &ovlen);
2129169043d8SPantelis Antoniou 		if (ov_noffset < 0) {
2130169043d8SPantelis Antoniou 			printf("load of %s failed\n", uname);
2131169043d8SPantelis Antoniou 			continue;
2132169043d8SPantelis Antoniou 		}
2133169043d8SPantelis Antoniou 		debug("%s loaded at 0x%08lx len=0x%08lx\n",
2134169043d8SPantelis Antoniou 				uname, ovload, ovlen);
2135169043d8SPantelis Antoniou 		ov = map_sysmem(ovload, ovlen);
2136169043d8SPantelis Antoniou 
2137169043d8SPantelis Antoniou 		base = map_sysmem(load, len + ovlen);
2138169043d8SPantelis Antoniou 		err = fdt_open_into(base, base, len + ovlen);
2139169043d8SPantelis Antoniou 		if (err < 0) {
2140169043d8SPantelis Antoniou 			printf("failed on fdt_open_into\n");
2141169043d8SPantelis Antoniou 			fdt_noffset = err;
2142169043d8SPantelis Antoniou 			goto out;
2143169043d8SPantelis Antoniou 		}
2144169043d8SPantelis Antoniou 		/* the verbose method prints out messages on error */
2145169043d8SPantelis Antoniou 		err = fdt_overlay_apply_verbose(base, ov);
2146169043d8SPantelis Antoniou 		if (err < 0) {
2147169043d8SPantelis Antoniou 			fdt_noffset = err;
2148169043d8SPantelis Antoniou 			goto out;
2149169043d8SPantelis Antoniou 		}
2150169043d8SPantelis Antoniou 		fdt_pack(base);
2151169043d8SPantelis Antoniou 		len = fdt_totalsize(base);
2152169043d8SPantelis Antoniou 	}
2153169043d8SPantelis Antoniou #else
2154169043d8SPantelis Antoniou 	printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n");
2155169043d8SPantelis Antoniou 	fdt_noffset = -EBADF;
2156169043d8SPantelis Antoniou #endif
2157169043d8SPantelis Antoniou 
2158169043d8SPantelis Antoniou out:
2159169043d8SPantelis Antoniou 	if (datap)
2160169043d8SPantelis Antoniou 		*datap = load;
2161169043d8SPantelis Antoniou 	if (lenp)
2162169043d8SPantelis Antoniou 		*lenp = len;
2163169043d8SPantelis Antoniou 	if (fit_unamep)
2164169043d8SPantelis Antoniou 		*fit_unamep = fit_uname;
2165169043d8SPantelis Antoniou 	if (fit_uname_configp)
2166169043d8SPantelis Antoniou 		*fit_uname_configp = fit_uname_config;
2167169043d8SPantelis Antoniou 
2168169043d8SPantelis Antoniou 	if (fit_uname_config_copy)
2169169043d8SPantelis Antoniou 		free(fit_uname_config_copy);
2170169043d8SPantelis Antoniou 	return fdt_noffset;
2171169043d8SPantelis Antoniou }
2172169043d8SPantelis Antoniou #endif
2173