xref: /OK3568_Linux_fs/u-boot/common/image-fit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2013, Google Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * (C) Copyright 2008 Semihalf
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * (C) Copyright 2000-2006
7*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #ifdef USE_HOSTCC
13*4882a593Smuzhiyun #include "mkimage.h"
14*4882a593Smuzhiyun #include <time.h>
15*4882a593Smuzhiyun #else
16*4882a593Smuzhiyun #include <linux/compiler.h>
17*4882a593Smuzhiyun #include <linux/kconfig.h>
18*4882a593Smuzhiyun #include <common.h>
19*4882a593Smuzhiyun #include <errno.h>
20*4882a593Smuzhiyun #include <mapmem.h>
21*4882a593Smuzhiyun #include <asm/io.h>
22*4882a593Smuzhiyun #include <malloc.h>
23*4882a593Smuzhiyun #include <crypto.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
26*4882a593Smuzhiyun #endif /* !USE_HOSTCC*/
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <image.h>
29*4882a593Smuzhiyun #include <bootstage.h>
30*4882a593Smuzhiyun #include <u-boot/crc.h>
31*4882a593Smuzhiyun #include <u-boot/md5.h>
32*4882a593Smuzhiyun #include <u-boot/sha1.h>
33*4882a593Smuzhiyun #include <u-boot/sha256.h>
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define __round_mask(x, y) ((__typeof__(x))((y)-1))
36*4882a593Smuzhiyun #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /*****************************************************************************/
39*4882a593Smuzhiyun /* New uImage format routines */
40*4882a593Smuzhiyun /*****************************************************************************/
41*4882a593Smuzhiyun #ifndef USE_HOSTCC
fit_parse_spec(const char * spec,char sepc,ulong addr_curr,ulong * addr,const char ** name)42*4882a593Smuzhiyun static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
43*4882a593Smuzhiyun 		ulong *addr, const char **name)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	const char *sep;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	*addr = addr_curr;
48*4882a593Smuzhiyun 	*name = NULL;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	sep = strchr(spec, sepc);
51*4882a593Smuzhiyun 	if (sep) {
52*4882a593Smuzhiyun 		if (sep - spec > 0)
53*4882a593Smuzhiyun 			*addr = simple_strtoul(spec, NULL, 16);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 		*name = sep + 1;
56*4882a593Smuzhiyun 		return 1;
57*4882a593Smuzhiyun 	}
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	return 0;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun /**
63*4882a593Smuzhiyun  * fit_parse_conf - parse FIT configuration spec
64*4882a593Smuzhiyun  * @spec: input string, containing configuration spec
65*4882a593Smuzhiyun  * @add_curr: current image address (to be used as a possible default)
66*4882a593Smuzhiyun  * @addr: pointer to a ulong variable, will hold FIT image address of a given
67*4882a593Smuzhiyun  * configuration
68*4882a593Smuzhiyun  * @conf_name double pointer to a char, will hold pointer to a configuration
69*4882a593Smuzhiyun  * unit name
70*4882a593Smuzhiyun  *
71*4882a593Smuzhiyun  * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
72*4882a593Smuzhiyun  * where <addr> is a FIT image address that contains configuration
73*4882a593Smuzhiyun  * with a <conf> unit name.
74*4882a593Smuzhiyun  *
75*4882a593Smuzhiyun  * Address part is optional, and if omitted default add_curr will
76*4882a593Smuzhiyun  * be used instead.
77*4882a593Smuzhiyun  *
78*4882a593Smuzhiyun  * returns:
79*4882a593Smuzhiyun  *     1 if spec is a valid configuration string,
80*4882a593Smuzhiyun  *     addr and conf_name are set accordingly
81*4882a593Smuzhiyun  *     0 otherwise
82*4882a593Smuzhiyun  */
fit_parse_conf(const char * spec,ulong addr_curr,ulong * addr,const char ** conf_name)83*4882a593Smuzhiyun int fit_parse_conf(const char *spec, ulong addr_curr,
84*4882a593Smuzhiyun 		ulong *addr, const char **conf_name)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /**
90*4882a593Smuzhiyun  * fit_parse_subimage - parse FIT subimage spec
91*4882a593Smuzhiyun  * @spec: input string, containing subimage spec
92*4882a593Smuzhiyun  * @add_curr: current image address (to be used as a possible default)
93*4882a593Smuzhiyun  * @addr: pointer to a ulong variable, will hold FIT image address of a given
94*4882a593Smuzhiyun  * subimage
95*4882a593Smuzhiyun  * @image_name: double pointer to a char, will hold pointer to a subimage name
96*4882a593Smuzhiyun  *
97*4882a593Smuzhiyun  * fit_parse_subimage() expects subimage spec in the form of
98*4882a593Smuzhiyun  * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
99*4882a593Smuzhiyun  * subimage with a <subimg> unit name.
100*4882a593Smuzhiyun  *
101*4882a593Smuzhiyun  * Address part is optional, and if omitted default add_curr will
102*4882a593Smuzhiyun  * be used instead.
103*4882a593Smuzhiyun  *
104*4882a593Smuzhiyun  * returns:
105*4882a593Smuzhiyun  *     1 if spec is a valid subimage string,
106*4882a593Smuzhiyun  *     addr and image_name are set accordingly
107*4882a593Smuzhiyun  *     0 otherwise
108*4882a593Smuzhiyun  */
fit_parse_subimage(const char * spec,ulong addr_curr,ulong * addr,const char ** image_name)109*4882a593Smuzhiyun int fit_parse_subimage(const char *spec, ulong addr_curr,
110*4882a593Smuzhiyun 		ulong *addr, const char **image_name)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun #endif /* !USE_HOSTCC */
115*4882a593Smuzhiyun 
fit_get_debug(const void * fit,int noffset,char * prop_name,int err)116*4882a593Smuzhiyun static void fit_get_debug(const void *fit, int noffset,
117*4882a593Smuzhiyun 		char *prop_name, int err)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
120*4882a593Smuzhiyun 	      prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
121*4882a593Smuzhiyun 	      fdt_strerror(err));
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun  * fit_get_subimage_count - get component (sub-image) count
126*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
127*4882a593Smuzhiyun  * @images_noffset: offset of images node
128*4882a593Smuzhiyun  *
129*4882a593Smuzhiyun  * returns:
130*4882a593Smuzhiyun  *     number of image components
131*4882a593Smuzhiyun  */
fit_get_subimage_count(const void * fit,int images_noffset)132*4882a593Smuzhiyun int fit_get_subimage_count(const void *fit, int images_noffset)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	int noffset;
135*4882a593Smuzhiyun 	int ndepth;
136*4882a593Smuzhiyun 	int count = 0;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	/* Process its subnodes, print out component images details */
139*4882a593Smuzhiyun 	for (ndepth = 0, count = 0,
140*4882a593Smuzhiyun 		noffset = fdt_next_node(fit, images_noffset, &ndepth);
141*4882a593Smuzhiyun 	     (noffset >= 0) && (ndepth > 0);
142*4882a593Smuzhiyun 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
143*4882a593Smuzhiyun 		if (ndepth == 1) {
144*4882a593Smuzhiyun 			count++;
145*4882a593Smuzhiyun 		}
146*4882a593Smuzhiyun 	}
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	return count;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
152*4882a593Smuzhiyun /**
153*4882a593Smuzhiyun  * fit_print_contents - prints out the contents of the FIT format image
154*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
155*4882a593Smuzhiyun  * @p: pointer to prefix string
156*4882a593Smuzhiyun  *
157*4882a593Smuzhiyun  * fit_print_contents() formats a multi line FIT image contents description.
158*4882a593Smuzhiyun  * The routine prints out FIT image properties (root node level) followed by
159*4882a593Smuzhiyun  * the details of each component image.
160*4882a593Smuzhiyun  *
161*4882a593Smuzhiyun  * returns:
162*4882a593Smuzhiyun  *     no returned results
163*4882a593Smuzhiyun  */
fit_print_contents(const void * fit)164*4882a593Smuzhiyun void fit_print_contents(const void *fit)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	char *desc;
167*4882a593Smuzhiyun 	char *uname;
168*4882a593Smuzhiyun 	int images_noffset;
169*4882a593Smuzhiyun 	int confs_noffset;
170*4882a593Smuzhiyun 	int noffset;
171*4882a593Smuzhiyun 	int ndepth;
172*4882a593Smuzhiyun 	int count = 0;
173*4882a593Smuzhiyun 	int ret;
174*4882a593Smuzhiyun 	const char *p;
175*4882a593Smuzhiyun 	time_t timestamp;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	/* Indent string is defined in header image.h */
178*4882a593Smuzhiyun 	p = IMAGE_INDENT_STRING;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	/* Root node properties */
181*4882a593Smuzhiyun 	ret = fit_get_desc(fit, 0, &desc);
182*4882a593Smuzhiyun 	printf("%sFIT description: ", p);
183*4882a593Smuzhiyun 	if (ret)
184*4882a593Smuzhiyun 		printf("unavailable\n");
185*4882a593Smuzhiyun 	else
186*4882a593Smuzhiyun 		printf("%s\n", desc);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	if (IMAGE_ENABLE_TIMESTAMP) {
189*4882a593Smuzhiyun 		ret = fit_get_timestamp(fit, 0, &timestamp);
190*4882a593Smuzhiyun 		printf("%sCreated:         ", p);
191*4882a593Smuzhiyun 		if (ret)
192*4882a593Smuzhiyun 			printf("unavailable\n");
193*4882a593Smuzhiyun 		else
194*4882a593Smuzhiyun 			genimg_print_time(timestamp);
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* Find images parent node offset */
198*4882a593Smuzhiyun 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
199*4882a593Smuzhiyun 	if (images_noffset < 0) {
200*4882a593Smuzhiyun 		printf("Can't find images parent node '%s' (%s)\n",
201*4882a593Smuzhiyun 		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
202*4882a593Smuzhiyun 		return;
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* Process its subnodes, print out component images details */
206*4882a593Smuzhiyun 	for (ndepth = 0, count = 0,
207*4882a593Smuzhiyun 		noffset = fdt_next_node(fit, images_noffset, &ndepth);
208*4882a593Smuzhiyun 	     (noffset >= 0) && (ndepth > 0);
209*4882a593Smuzhiyun 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
210*4882a593Smuzhiyun 		if (ndepth == 1) {
211*4882a593Smuzhiyun 			/*
212*4882a593Smuzhiyun 			 * Direct child node of the images parent node,
213*4882a593Smuzhiyun 			 * i.e. component image node.
214*4882a593Smuzhiyun 			 */
215*4882a593Smuzhiyun 			printf("%s Image %u (%s)\n", p, count++,
216*4882a593Smuzhiyun 			       fit_get_name(fit, noffset, NULL));
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 			fit_image_print(fit, noffset, p);
219*4882a593Smuzhiyun 		}
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	/* Find configurations parent node offset */
223*4882a593Smuzhiyun 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
224*4882a593Smuzhiyun 	if (confs_noffset < 0) {
225*4882a593Smuzhiyun 		debug("Can't get configurations parent node '%s' (%s)\n",
226*4882a593Smuzhiyun 		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
227*4882a593Smuzhiyun 		return;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	/* get default configuration unit name from default property */
231*4882a593Smuzhiyun 	uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
232*4882a593Smuzhiyun 	if (uname)
233*4882a593Smuzhiyun 		printf("%s Default Configuration: '%s'\n", p, uname);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	/* Process its subnodes, print out configurations details */
236*4882a593Smuzhiyun 	for (ndepth = 0, count = 0,
237*4882a593Smuzhiyun 		noffset = fdt_next_node(fit, confs_noffset, &ndepth);
238*4882a593Smuzhiyun 	     (noffset >= 0) && (ndepth > 0);
239*4882a593Smuzhiyun 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
240*4882a593Smuzhiyun 		if (ndepth == 1) {
241*4882a593Smuzhiyun 			/*
242*4882a593Smuzhiyun 			 * Direct child node of the configurations parent node,
243*4882a593Smuzhiyun 			 * i.e. configuration node.
244*4882a593Smuzhiyun 			 */
245*4882a593Smuzhiyun 			printf("%s Configuration %u (%s)\n", p, count++,
246*4882a593Smuzhiyun 			       fit_get_name(fit, noffset, NULL));
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 			fit_conf_print(fit, noffset, p);
249*4882a593Smuzhiyun 		}
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /**
254*4882a593Smuzhiyun  * fit_image_print_data() - prints out the hash node details
255*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
256*4882a593Smuzhiyun  * @noffset: offset of the hash node
257*4882a593Smuzhiyun  * @p: pointer to prefix string
258*4882a593Smuzhiyun  * @type: Type of information to print ("hash" or "sign")
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  * fit_image_print_data() lists properties for the processed hash node
261*4882a593Smuzhiyun  *
262*4882a593Smuzhiyun  * This function avoid using puts() since it prints a newline on the host
263*4882a593Smuzhiyun  * but does not in U-Boot.
264*4882a593Smuzhiyun  *
265*4882a593Smuzhiyun  * returns:
266*4882a593Smuzhiyun  *     no returned results
267*4882a593Smuzhiyun  */
fit_image_print_data(const void * fit,int noffset,const char * p,const char * type)268*4882a593Smuzhiyun static void fit_image_print_data(const void *fit, int noffset, const char *p,
269*4882a593Smuzhiyun 				 const char *type)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun 	const char *keyname;
272*4882a593Smuzhiyun 	uint8_t *value;
273*4882a593Smuzhiyun 	int value_len;
274*4882a593Smuzhiyun 	char *algo;
275*4882a593Smuzhiyun 	int required;
276*4882a593Smuzhiyun 	int ret, i;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	debug("%s  %s node:    '%s'\n", p, type,
279*4882a593Smuzhiyun 	      fit_get_name(fit, noffset, NULL));
280*4882a593Smuzhiyun 	printf("%s  %s algo:    ", p, type);
281*4882a593Smuzhiyun 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
282*4882a593Smuzhiyun 		printf("invalid/unsupported\n");
283*4882a593Smuzhiyun 		return;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 	printf("%s", algo);
286*4882a593Smuzhiyun 	keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
287*4882a593Smuzhiyun 	required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
288*4882a593Smuzhiyun 	if (keyname)
289*4882a593Smuzhiyun 		printf(":%s", keyname);
290*4882a593Smuzhiyun 	if (required)
291*4882a593Smuzhiyun 		printf(" (required)");
292*4882a593Smuzhiyun 	printf("\n");
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	ret = fit_image_hash_get_value(fit, noffset, &value,
295*4882a593Smuzhiyun 					&value_len);
296*4882a593Smuzhiyun 	printf("%s  %s value:   ", p, type);
297*4882a593Smuzhiyun 	if (ret) {
298*4882a593Smuzhiyun 		printf("unavailable\n");
299*4882a593Smuzhiyun 	} else {
300*4882a593Smuzhiyun 		for (i = 0; i < value_len; i++)
301*4882a593Smuzhiyun 			printf("%02x", value[i]);
302*4882a593Smuzhiyun 		printf("\n");
303*4882a593Smuzhiyun 	}
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	debug("%s  %s len:     %d\n", p, type, value_len);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	/* Signatures have a time stamp */
308*4882a593Smuzhiyun 	if (IMAGE_ENABLE_TIMESTAMP && keyname) {
309*4882a593Smuzhiyun 		time_t timestamp;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 		printf("%s  Timestamp:    ", p);
312*4882a593Smuzhiyun 		if (fit_get_timestamp(fit, noffset, &timestamp))
313*4882a593Smuzhiyun 			printf("unavailable\n");
314*4882a593Smuzhiyun 		else
315*4882a593Smuzhiyun 			genimg_print_time(timestamp);
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun /**
320*4882a593Smuzhiyun  * fit_image_print_verification_data() - prints out the hash/signature details
321*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
322*4882a593Smuzhiyun  * @noffset: offset of the hash or signature node
323*4882a593Smuzhiyun  * @p: pointer to prefix string
324*4882a593Smuzhiyun  *
325*4882a593Smuzhiyun  * This lists properties for the processed hash node
326*4882a593Smuzhiyun  *
327*4882a593Smuzhiyun  * returns:
328*4882a593Smuzhiyun  *     no returned results
329*4882a593Smuzhiyun  */
fit_image_print_verification_data(const void * fit,int noffset,const char * p)330*4882a593Smuzhiyun static void fit_image_print_verification_data(const void *fit, int noffset,
331*4882a593Smuzhiyun 				       const char *p)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	const char *name;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	/*
336*4882a593Smuzhiyun 	 * Check subnode name, must be equal to "hash" or "signature".
337*4882a593Smuzhiyun 	 * Multiple hash/signature nodes require unique unit node
338*4882a593Smuzhiyun 	 * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
339*4882a593Smuzhiyun 	 */
340*4882a593Smuzhiyun 	name = fit_get_name(fit, noffset, NULL);
341*4882a593Smuzhiyun 	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
342*4882a593Smuzhiyun 		fit_image_print_data(fit, noffset, p, "Hash");
343*4882a593Smuzhiyun 	} else if (!strncmp(name, FIT_SIG_NODENAME,
344*4882a593Smuzhiyun 				strlen(FIT_SIG_NODENAME))) {
345*4882a593Smuzhiyun 		fit_image_print_data(fit, noffset, p, "Sign");
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun /**
350*4882a593Smuzhiyun  * fit_image_print - prints out the FIT component image details
351*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
352*4882a593Smuzhiyun  * @image_noffset: offset of the component image node
353*4882a593Smuzhiyun  * @p: pointer to prefix string
354*4882a593Smuzhiyun  *
355*4882a593Smuzhiyun  * fit_image_print() lists all mandatory properties for the processed component
356*4882a593Smuzhiyun  * image. If present, hash nodes are printed out as well. Load
357*4882a593Smuzhiyun  * address for images of type firmware is also printed out. Since the load
358*4882a593Smuzhiyun  * address is not mandatory for firmware images, it will be output as
359*4882a593Smuzhiyun  * "unavailable" when not present.
360*4882a593Smuzhiyun  *
361*4882a593Smuzhiyun  * returns:
362*4882a593Smuzhiyun  *     no returned results
363*4882a593Smuzhiyun  */
fit_image_print(const void * fit,int image_noffset,const char * p)364*4882a593Smuzhiyun void fit_image_print(const void *fit, int image_noffset, const char *p)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun 	char *desc;
367*4882a593Smuzhiyun 	uint8_t type, arch, os, comp;
368*4882a593Smuzhiyun 	size_t size;
369*4882a593Smuzhiyun 	ulong load, entry;
370*4882a593Smuzhiyun 	const void *data;
371*4882a593Smuzhiyun 	int noffset;
372*4882a593Smuzhiyun 	int ndepth;
373*4882a593Smuzhiyun 	int ret;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	/* Mandatory properties */
376*4882a593Smuzhiyun 	ret = fit_get_desc(fit, image_noffset, &desc);
377*4882a593Smuzhiyun 	printf("%s  Description:  ", p);
378*4882a593Smuzhiyun 	if (ret)
379*4882a593Smuzhiyun 		printf("unavailable\n");
380*4882a593Smuzhiyun 	else
381*4882a593Smuzhiyun 		printf("%s\n", desc);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (IMAGE_ENABLE_TIMESTAMP) {
384*4882a593Smuzhiyun 		time_t timestamp;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 		ret = fit_get_timestamp(fit, 0, &timestamp);
387*4882a593Smuzhiyun 		printf("%s  Created:      ", p);
388*4882a593Smuzhiyun 		if (ret)
389*4882a593Smuzhiyun 			printf("unavailable\n");
390*4882a593Smuzhiyun 		else
391*4882a593Smuzhiyun 			genimg_print_time(timestamp);
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	fit_image_get_type(fit, image_noffset, &type);
395*4882a593Smuzhiyun 	printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	fit_image_get_comp(fit, image_noffset, &comp);
398*4882a593Smuzhiyun 	printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	ret = fit_image_get_data(fit, image_noffset, &data, &size);
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun #ifndef USE_HOSTCC
403*4882a593Smuzhiyun 	printf("%s  Data Start:   ", p);
404*4882a593Smuzhiyun 	if (ret) {
405*4882a593Smuzhiyun 		printf("unavailable\n");
406*4882a593Smuzhiyun 	} else {
407*4882a593Smuzhiyun 		void *vdata = (void *)data;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 		printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
410*4882a593Smuzhiyun 	}
411*4882a593Smuzhiyun #endif
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	printf("%s  Data Size:    ", p);
414*4882a593Smuzhiyun 	if (ret)
415*4882a593Smuzhiyun 		printf("unavailable\n");
416*4882a593Smuzhiyun 	else
417*4882a593Smuzhiyun 		genimg_print_size(size);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	/* Remaining, type dependent properties */
420*4882a593Smuzhiyun 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
421*4882a593Smuzhiyun 	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
422*4882a593Smuzhiyun 	    (type == IH_TYPE_FLATDT)) {
423*4882a593Smuzhiyun 		fit_image_get_arch(fit, image_noffset, &arch);
424*4882a593Smuzhiyun 		printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
428*4882a593Smuzhiyun 		fit_image_get_os(fit, image_noffset, &os);
429*4882a593Smuzhiyun 		printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
433*4882a593Smuzhiyun 	    (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) ||
434*4882a593Smuzhiyun 	    (type == IH_TYPE_FPGA)) {
435*4882a593Smuzhiyun 		ret = fit_image_get_load(fit, image_noffset, &load);
436*4882a593Smuzhiyun 		printf("%s  Load Address: ", p);
437*4882a593Smuzhiyun 		if (ret)
438*4882a593Smuzhiyun 			printf("unavailable\n");
439*4882a593Smuzhiyun 		else
440*4882a593Smuzhiyun 			printf("0x%08lx\n", load);
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	/* optional load address for FDT */
444*4882a593Smuzhiyun 	if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load))
445*4882a593Smuzhiyun 		printf("%s  Load Address: 0x%08lx\n", p, load);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
448*4882a593Smuzhiyun 	    (type == IH_TYPE_RAMDISK)) {
449*4882a593Smuzhiyun 		ret = fit_image_get_entry(fit, image_noffset, &entry);
450*4882a593Smuzhiyun 		printf("%s  Entry Point:  ", p);
451*4882a593Smuzhiyun 		if (ret)
452*4882a593Smuzhiyun 			printf("unavailable\n");
453*4882a593Smuzhiyun 		else
454*4882a593Smuzhiyun 			printf("0x%08lx\n", entry);
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	/* Process all hash subnodes of the component image node */
458*4882a593Smuzhiyun 	for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
459*4882a593Smuzhiyun 	     (noffset >= 0) && (ndepth > 0);
460*4882a593Smuzhiyun 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
461*4882a593Smuzhiyun 		if (ndepth == 1) {
462*4882a593Smuzhiyun 			/* Direct child node of the component image node */
463*4882a593Smuzhiyun 			fit_image_print_verification_data(fit, noffset, p);
464*4882a593Smuzhiyun 		}
465*4882a593Smuzhiyun 	}
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun #endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) */
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun /**
471*4882a593Smuzhiyun  * fit_get_desc - get node description property
472*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
473*4882a593Smuzhiyun  * @noffset: node offset
474*4882a593Smuzhiyun  * @desc: double pointer to the char, will hold pointer to the description
475*4882a593Smuzhiyun  *
476*4882a593Smuzhiyun  * fit_get_desc() reads description property from a given node, if
477*4882a593Smuzhiyun  * description is found pointer to it is returned in third call argument.
478*4882a593Smuzhiyun  *
479*4882a593Smuzhiyun  * returns:
480*4882a593Smuzhiyun  *     0, on success
481*4882a593Smuzhiyun  *     -1, on failure
482*4882a593Smuzhiyun  */
fit_get_desc(const void * fit,int noffset,char ** desc)483*4882a593Smuzhiyun int fit_get_desc(const void *fit, int noffset, char **desc)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun 	int len;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	*desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
488*4882a593Smuzhiyun 	if (*desc == NULL) {
489*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
490*4882a593Smuzhiyun 		return -1;
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	return 0;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun /**
497*4882a593Smuzhiyun  * fit_get_timestamp - get node timestamp property
498*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
499*4882a593Smuzhiyun  * @noffset: node offset
500*4882a593Smuzhiyun  * @timestamp: pointer to the time_t, will hold read timestamp
501*4882a593Smuzhiyun  *
502*4882a593Smuzhiyun  * fit_get_timestamp() reads timestamp property from given node, if timestamp
503*4882a593Smuzhiyun  * is found and has a correct size its value is returned in third call
504*4882a593Smuzhiyun  * argument.
505*4882a593Smuzhiyun  *
506*4882a593Smuzhiyun  * returns:
507*4882a593Smuzhiyun  *     0, on success
508*4882a593Smuzhiyun  *     -1, on property read failure
509*4882a593Smuzhiyun  *     -2, on wrong timestamp size
510*4882a593Smuzhiyun  */
fit_get_timestamp(const void * fit,int noffset,time_t * timestamp)511*4882a593Smuzhiyun int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	int len;
514*4882a593Smuzhiyun 	const void *data;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
517*4882a593Smuzhiyun 	if (data == NULL) {
518*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
519*4882a593Smuzhiyun 		return -1;
520*4882a593Smuzhiyun 	}
521*4882a593Smuzhiyun 	if (len != sizeof(uint32_t)) {
522*4882a593Smuzhiyun 		debug("FIT timestamp with incorrect size of (%u)\n", len);
523*4882a593Smuzhiyun 		return -2;
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	*timestamp = uimage_to_cpu(*((uint32_t *)data));
527*4882a593Smuzhiyun 	return 0;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun /**
531*4882a593Smuzhiyun  * fit_get_totalsize - get node totalsize property.
532*4882a593Smuzhiyun  *
533*4882a593Smuzhiyun  * @fit: pointer to the FIT image header
534*4882a593Smuzhiyun  * @totalsize: holds the /totalsize property
535*4882a593Smuzhiyun  *
536*4882a593Smuzhiyun  * returns:
537*4882a593Smuzhiyun  *     0, on success
538*4882a593Smuzhiyun  *     -ENOENT if the property could not be found
539*4882a593Smuzhiyun  */
fit_get_totalsize(const void * fit,int * totalsize)540*4882a593Smuzhiyun int fit_get_totalsize(const void *fit, int *totalsize)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun 	const fdt32_t *val;
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	val = fdt_getprop(fit, 0, FIT_TOTALSIZE_PROP, NULL);
545*4882a593Smuzhiyun 	if (!val)
546*4882a593Smuzhiyun 		return -ENOENT;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	*totalsize = fdt32_to_cpu(*val);
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun /**
554*4882a593Smuzhiyun  * fit_image_get_node - get node offset for component image of a given unit name
555*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
556*4882a593Smuzhiyun  * @image_uname: component image node unit name
557*4882a593Smuzhiyun  *
558*4882a593Smuzhiyun  * fit_image_get_node() finds a component image (within the '/images'
559*4882a593Smuzhiyun  * node) of a provided unit name. If image is found its node offset is
560*4882a593Smuzhiyun  * returned to the caller.
561*4882a593Smuzhiyun  *
562*4882a593Smuzhiyun  * returns:
563*4882a593Smuzhiyun  *     image node offset when found (>=0)
564*4882a593Smuzhiyun  *     negative number on failure (FDT_ERR_* code)
565*4882a593Smuzhiyun  */
fit_image_get_node(const void * fit,const char * image_uname)566*4882a593Smuzhiyun int fit_image_get_node(const void *fit, const char *image_uname)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	int noffset, images_noffset;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
571*4882a593Smuzhiyun 	if (images_noffset < 0) {
572*4882a593Smuzhiyun 		debug("Can't find images parent node '%s' (%s)\n",
573*4882a593Smuzhiyun 		      FIT_IMAGES_PATH, fdt_strerror(images_noffset));
574*4882a593Smuzhiyun 		return images_noffset;
575*4882a593Smuzhiyun 	}
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
578*4882a593Smuzhiyun 	if (noffset < 0) {
579*4882a593Smuzhiyun 		debug("Can't get node offset for image unit name: '%s' (%s)\n",
580*4882a593Smuzhiyun 		      image_uname, fdt_strerror(noffset));
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	return noffset;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun /**
587*4882a593Smuzhiyun  * fit_image_get_os - get os id for a given component image node
588*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
589*4882a593Smuzhiyun  * @noffset: component image node offset
590*4882a593Smuzhiyun  * @os: pointer to the uint8_t, will hold os numeric id
591*4882a593Smuzhiyun  *
592*4882a593Smuzhiyun  * fit_image_get_os() finds os property in a given component image node.
593*4882a593Smuzhiyun  * If the property is found, its (string) value is translated to the numeric
594*4882a593Smuzhiyun  * id which is returned to the caller.
595*4882a593Smuzhiyun  *
596*4882a593Smuzhiyun  * returns:
597*4882a593Smuzhiyun  *     0, on success
598*4882a593Smuzhiyun  *     -1, on failure
599*4882a593Smuzhiyun  */
fit_image_get_os(const void * fit,int noffset,uint8_t * os)600*4882a593Smuzhiyun int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun 	int len;
603*4882a593Smuzhiyun 	const void *data;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	/* Get OS name from property data */
606*4882a593Smuzhiyun 	data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
607*4882a593Smuzhiyun 	if (data == NULL) {
608*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_OS_PROP, len);
609*4882a593Smuzhiyun 		*os = -1;
610*4882a593Smuzhiyun 		return -1;
611*4882a593Smuzhiyun 	}
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/* Translate OS name to id */
614*4882a593Smuzhiyun 	*os = genimg_get_os_id(data);
615*4882a593Smuzhiyun 	return 0;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun /**
619*4882a593Smuzhiyun  * fit_image_get_arch - get arch id for a given component image node
620*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
621*4882a593Smuzhiyun  * @noffset: component image node offset
622*4882a593Smuzhiyun  * @arch: pointer to the uint8_t, will hold arch numeric id
623*4882a593Smuzhiyun  *
624*4882a593Smuzhiyun  * fit_image_get_arch() finds arch property in a given component image node.
625*4882a593Smuzhiyun  * If the property is found, its (string) value is translated to the numeric
626*4882a593Smuzhiyun  * id which is returned to the caller.
627*4882a593Smuzhiyun  *
628*4882a593Smuzhiyun  * returns:
629*4882a593Smuzhiyun  *     0, on success
630*4882a593Smuzhiyun  *     -1, on failure
631*4882a593Smuzhiyun  */
fit_image_get_arch(const void * fit,int noffset,uint8_t * arch)632*4882a593Smuzhiyun int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun 	int len;
635*4882a593Smuzhiyun 	const void *data;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	/* Get architecture name from property data */
638*4882a593Smuzhiyun 	data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
639*4882a593Smuzhiyun 	if (data == NULL) {
640*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
641*4882a593Smuzhiyun 		*arch = -1;
642*4882a593Smuzhiyun 		return -1;
643*4882a593Smuzhiyun 	}
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	/* Translate architecture name to id */
646*4882a593Smuzhiyun 	*arch = genimg_get_arch_id(data);
647*4882a593Smuzhiyun 	return 0;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun /**
651*4882a593Smuzhiyun  * fit_image_get_type - get type id for a given component image node
652*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
653*4882a593Smuzhiyun  * @noffset: component image node offset
654*4882a593Smuzhiyun  * @type: pointer to the uint8_t, will hold type numeric id
655*4882a593Smuzhiyun  *
656*4882a593Smuzhiyun  * fit_image_get_type() finds type property in a given component image node.
657*4882a593Smuzhiyun  * If the property is found, its (string) value is translated to the numeric
658*4882a593Smuzhiyun  * id which is returned to the caller.
659*4882a593Smuzhiyun  *
660*4882a593Smuzhiyun  * returns:
661*4882a593Smuzhiyun  *     0, on success
662*4882a593Smuzhiyun  *     -1, on failure
663*4882a593Smuzhiyun  */
fit_image_get_type(const void * fit,int noffset,uint8_t * type)664*4882a593Smuzhiyun int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun 	int len;
667*4882a593Smuzhiyun 	const void *data;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	/* Get image type name from property data */
670*4882a593Smuzhiyun 	data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
671*4882a593Smuzhiyun 	if (data == NULL) {
672*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
673*4882a593Smuzhiyun 		*type = -1;
674*4882a593Smuzhiyun 		return -1;
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	/* Translate image type name to id */
678*4882a593Smuzhiyun 	*type = genimg_get_type_id(data);
679*4882a593Smuzhiyun 	return 0;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun /**
683*4882a593Smuzhiyun  * fit_image_get_comp - get comp id for a given component image node
684*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
685*4882a593Smuzhiyun  * @noffset: component image node offset
686*4882a593Smuzhiyun  * @comp: pointer to the uint8_t, will hold comp numeric id
687*4882a593Smuzhiyun  *
688*4882a593Smuzhiyun  * fit_image_get_comp() finds comp property in a given component image node.
689*4882a593Smuzhiyun  * If the property is found, its (string) value is translated to the numeric
690*4882a593Smuzhiyun  * id which is returned to the caller.
691*4882a593Smuzhiyun  *
692*4882a593Smuzhiyun  * returns:
693*4882a593Smuzhiyun  *     0, on success
694*4882a593Smuzhiyun  *     -1, on failure
695*4882a593Smuzhiyun  */
fit_image_get_comp(const void * fit,int noffset,uint8_t * comp)696*4882a593Smuzhiyun int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun 	int len;
699*4882a593Smuzhiyun 	const void *data;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	/* Get compression name from property data */
702*4882a593Smuzhiyun 	data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
703*4882a593Smuzhiyun 	if (data == NULL) {
704*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
705*4882a593Smuzhiyun 		*comp = -1;
706*4882a593Smuzhiyun 		return -1;
707*4882a593Smuzhiyun 	}
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	/* Translate compression name to id */
710*4882a593Smuzhiyun 	*comp = genimg_get_comp_id(data);
711*4882a593Smuzhiyun 	return 0;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
fit_image_is_preload(const void * fit,int noffset)714*4882a593Smuzhiyun bool fit_image_is_preload(const void *fit, int noffset)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	int len;
717*4882a593Smuzhiyun 	int *data;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	data = (int *)fdt_getprop(fit, noffset, FIT_PRE_LOAD_PROP, &len);
720*4882a593Smuzhiyun 	if (data == NULL || len != sizeof(int)) {
721*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_PRE_LOAD_PROP, len);
722*4882a593Smuzhiyun 		return false;
723*4882a593Smuzhiyun 	}
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	if (fdt32_to_cpu(*data) != 1)
726*4882a593Smuzhiyun 		return false;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	return true;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
fit_image_get_address(const void * fit,int noffset,char * name,ulong * load)731*4882a593Smuzhiyun static int fit_image_get_address(const void *fit, int noffset, char *name,
732*4882a593Smuzhiyun 			  ulong *load)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	int len, cell_len;
735*4882a593Smuzhiyun 	const fdt32_t *cell;
736*4882a593Smuzhiyun 	uint64_t load64 = 0;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	cell = fdt_getprop(fit, noffset, name, &len);
739*4882a593Smuzhiyun 	if (cell == NULL) {
740*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, name, len);
741*4882a593Smuzhiyun 		return -1;
742*4882a593Smuzhiyun 	}
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (len > sizeof(ulong)) {
745*4882a593Smuzhiyun 		printf("Unsupported %s address size\n", name);
746*4882a593Smuzhiyun 		return -1;
747*4882a593Smuzhiyun 	}
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	cell_len = len >> 2;
750*4882a593Smuzhiyun 	/* Use load64 to avoid compiling warning for 32-bit target */
751*4882a593Smuzhiyun 	while (cell_len--) {
752*4882a593Smuzhiyun 		load64 = (load64 << 32) | uimage_to_cpu(*cell);
753*4882a593Smuzhiyun 		cell++;
754*4882a593Smuzhiyun 	}
755*4882a593Smuzhiyun 	*load = (ulong)load64;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	return 0;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun 
fit_image_set_address(const void * fit,int noffset,char * name,ulong addr)760*4882a593Smuzhiyun static int fit_image_set_address(const void *fit, int noffset, char *name,
761*4882a593Smuzhiyun 				 ulong addr)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun 	int len, cell_len;
764*4882a593Smuzhiyun 	const fdt32_t *cell;
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	cell = fdt_getprop(fit, noffset, name, &len);
767*4882a593Smuzhiyun 	if (cell == NULL) {
768*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, name, len);
769*4882a593Smuzhiyun 		return -1;
770*4882a593Smuzhiyun 	}
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	if (len > sizeof(ulong)) {
773*4882a593Smuzhiyun 		printf("Unsupported %s address size\n", name);
774*4882a593Smuzhiyun 		return -1;
775*4882a593Smuzhiyun 	}
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	cell_len = len >> 2;
778*4882a593Smuzhiyun 	/* Use load64 to avoid compiling warning for 32-bit target */
779*4882a593Smuzhiyun 	while (cell_len--) {
780*4882a593Smuzhiyun 		*(fdt32_t *)cell = cpu_to_uimage(addr >> (32 * cell_len));
781*4882a593Smuzhiyun 		cell++;
782*4882a593Smuzhiyun 	}
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	return 0;
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun /**
788*4882a593Smuzhiyun  * fit_image_get_load() - get load addr property for given component image node
789*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
790*4882a593Smuzhiyun  * @noffset: component image node offset
791*4882a593Smuzhiyun  * @load: pointer to the uint32_t, will hold load address
792*4882a593Smuzhiyun  *
793*4882a593Smuzhiyun  * fit_image_get_load() finds load address property in a given component
794*4882a593Smuzhiyun  * image node. If the property is found, its value is returned to the caller.
795*4882a593Smuzhiyun  *
796*4882a593Smuzhiyun  * returns:
797*4882a593Smuzhiyun  *     0, on success
798*4882a593Smuzhiyun  *     -1, on failure
799*4882a593Smuzhiyun  */
fit_image_get_load(const void * fit,int noffset,ulong * load)800*4882a593Smuzhiyun int fit_image_get_load(const void *fit, int noffset, ulong *load)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun 	return fit_image_get_address(fit, noffset, FIT_LOAD_PROP, load);
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun /**
806*4882a593Smuzhiyun  * fit_image_get_comp_addr() - get compress addr property for given component image node
807*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
808*4882a593Smuzhiyun  * @noffset: component image node offset
809*4882a593Smuzhiyun  * @comp: pointer to the uint32_t, will hold load address
810*4882a593Smuzhiyun  *
811*4882a593Smuzhiyun  * fit_image_get_comp_addr() finds compress address property in a given component
812*4882a593Smuzhiyun  * image node. If the property is found, its value is returned to the caller.
813*4882a593Smuzhiyun  *
814*4882a593Smuzhiyun  * returns:
815*4882a593Smuzhiyun  *     0, on success
816*4882a593Smuzhiyun  *     -1, on failure
817*4882a593Smuzhiyun  */
fit_image_get_comp_addr(const void * fit,int noffset,ulong * comp)818*4882a593Smuzhiyun int fit_image_get_comp_addr(const void *fit, int noffset, ulong *comp)
819*4882a593Smuzhiyun {
820*4882a593Smuzhiyun 	return fit_image_get_address(fit, noffset, FIT_COMP_ADDR_PROP, comp);
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun /**
824*4882a593Smuzhiyun  * fit_image_set_load() - set load addr property for given component image node
825*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
826*4882a593Smuzhiyun  * @noffset: component image node offset
827*4882a593Smuzhiyun  * @load: uint32_t value, will hold load address
828*4882a593Smuzhiyun  *
829*4882a593Smuzhiyun  * fit_image_set_load() finds and set load address property in a given component
830*4882a593Smuzhiyun  * image node. If the property is found, its value is returned to the caller.
831*4882a593Smuzhiyun  *
832*4882a593Smuzhiyun  * returns:
833*4882a593Smuzhiyun  *     0, on success
834*4882a593Smuzhiyun  *     -1, on failure
835*4882a593Smuzhiyun  */
fit_image_set_load(const void * fit,int noffset,ulong load)836*4882a593Smuzhiyun int fit_image_set_load(const void *fit, int noffset, ulong load)
837*4882a593Smuzhiyun {
838*4882a593Smuzhiyun 	return fit_image_set_address(fit, noffset, FIT_LOAD_PROP, load);
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun /**
842*4882a593Smuzhiyun  * fit_image_get_entry() - get entry point address property
843*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
844*4882a593Smuzhiyun  * @noffset: component image node offset
845*4882a593Smuzhiyun  * @entry: pointer to the uint32_t, will hold entry point address
846*4882a593Smuzhiyun  *
847*4882a593Smuzhiyun  * This gets the entry point address property for a given component image
848*4882a593Smuzhiyun  * node.
849*4882a593Smuzhiyun  *
850*4882a593Smuzhiyun  * fit_image_get_entry() finds entry point address property in a given
851*4882a593Smuzhiyun  * component image node.  If the property is found, its value is returned
852*4882a593Smuzhiyun  * to the caller.
853*4882a593Smuzhiyun  *
854*4882a593Smuzhiyun  * returns:
855*4882a593Smuzhiyun  *     0, on success
856*4882a593Smuzhiyun  *     -1, on failure
857*4882a593Smuzhiyun  */
fit_image_get_entry(const void * fit,int noffset,ulong * entry)858*4882a593Smuzhiyun int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
859*4882a593Smuzhiyun {
860*4882a593Smuzhiyun 	return fit_image_get_address(fit, noffset, FIT_ENTRY_PROP, entry);
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun /**
864*4882a593Smuzhiyun  * fit_image_set_entry() - set entry point address property
865*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
866*4882a593Smuzhiyun  * @noffset: component image node offset
867*4882a593Smuzhiyun  * @entry: uint32_t value, will hold entry point address
868*4882a593Smuzhiyun  *
869*4882a593Smuzhiyun  * This sets the entry point address property for a given component image
870*4882a593Smuzhiyun  * node.
871*4882a593Smuzhiyun  *
872*4882a593Smuzhiyun  * fit_image_set_entry() finds and set entry point address property in a given
873*4882a593Smuzhiyun  * component image node.  If the property is found, its value is returned
874*4882a593Smuzhiyun  * to the caller.
875*4882a593Smuzhiyun  *
876*4882a593Smuzhiyun  * returns:
877*4882a593Smuzhiyun  *     0, on success
878*4882a593Smuzhiyun  *     -1, on failure
879*4882a593Smuzhiyun  */
fit_image_set_entry(const void * fit,int noffset,ulong entry)880*4882a593Smuzhiyun int fit_image_set_entry(const void *fit, int noffset, ulong entry)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun 	return fit_image_set_address(fit, noffset, FIT_ENTRY_PROP, entry);
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun /**
886*4882a593Smuzhiyun  * fit_image_get_data - get data property and its size for a given component image node
887*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
888*4882a593Smuzhiyun  * @noffset: component image node offset
889*4882a593Smuzhiyun  * @data: double pointer to void, will hold data property's data address
890*4882a593Smuzhiyun  * @size: pointer to size_t, will hold data property's data size
891*4882a593Smuzhiyun  *
892*4882a593Smuzhiyun  * fit_image_get_data() finds data property in a given component image node.
893*4882a593Smuzhiyun  * If the property is found its data start address and size are returned to
894*4882a593Smuzhiyun  * the caller.
895*4882a593Smuzhiyun  *
896*4882a593Smuzhiyun  * returns:
897*4882a593Smuzhiyun  *     0, on success
898*4882a593Smuzhiyun  *     -1, on failure
899*4882a593Smuzhiyun  */
fit_image_get_data(const void * fit,int noffset,const void ** data,size_t * size)900*4882a593Smuzhiyun int fit_image_get_data(const void *fit, int noffset,
901*4882a593Smuzhiyun 		const void **data, size_t *size)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun 	ulong data_off = 0;
904*4882a593Smuzhiyun 	ulong data_pos = 0;
905*4882a593Smuzhiyun 	int len;
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	/* data */
908*4882a593Smuzhiyun 	*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
909*4882a593Smuzhiyun 	if (*data) {
910*4882a593Smuzhiyun 		*size = len;
911*4882a593Smuzhiyun 		return 0;
912*4882a593Smuzhiyun 	}
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	/* data-size */
915*4882a593Smuzhiyun 	if (fit_image_get_data_size(fit, noffset, &len))
916*4882a593Smuzhiyun 		return -ENOENT;
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	/* data-offset */
919*4882a593Smuzhiyun 	if (!fit_image_get_data_offset(fit, noffset, (int *)&data_off)) {
920*4882a593Smuzhiyun 		data_off += (ulong)fit + FIT_ALIGN(fdt_totalsize(fit));
921*4882a593Smuzhiyun 		*data = (void *)data_off;
922*4882a593Smuzhiyun 		*size = len;
923*4882a593Smuzhiyun 		return 0;
924*4882a593Smuzhiyun 	}
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	/* data-position */
927*4882a593Smuzhiyun 	if (!fit_image_get_data_position(fit, noffset, (int *)&data_pos)) {
928*4882a593Smuzhiyun 		*data = (void *)(data_pos + (ulong)fit);
929*4882a593Smuzhiyun 		*size = len;
930*4882a593Smuzhiyun 		return 0;
931*4882a593Smuzhiyun 	}
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	*size = 0;
934*4882a593Smuzhiyun 	return -1;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun /**
938*4882a593Smuzhiyun  * Get 'data-offset' property from a given image node.
939*4882a593Smuzhiyun  *
940*4882a593Smuzhiyun  * @fit: pointer to the FIT image header
941*4882a593Smuzhiyun  * @noffset: component image node offset
942*4882a593Smuzhiyun  * @data_offset: holds the data-offset property
943*4882a593Smuzhiyun  *
944*4882a593Smuzhiyun  * returns:
945*4882a593Smuzhiyun  *     0, on success
946*4882a593Smuzhiyun  *     -ENOENT if the property could not be found
947*4882a593Smuzhiyun  */
fit_image_get_data_offset(const void * fit,int noffset,int * data_offset)948*4882a593Smuzhiyun int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset)
949*4882a593Smuzhiyun {
950*4882a593Smuzhiyun 	const fdt32_t *val;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL);
953*4882a593Smuzhiyun 	if (!val)
954*4882a593Smuzhiyun 		return -ENOENT;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	*data_offset = fdt32_to_cpu(*val);
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	return 0;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun /**
962*4882a593Smuzhiyun  * Get 'data-position' property from a given image node.
963*4882a593Smuzhiyun  *
964*4882a593Smuzhiyun  * @fit: pointer to the FIT image header
965*4882a593Smuzhiyun  * @noffset: component image node offset
966*4882a593Smuzhiyun  * @data_position: holds the data-position property
967*4882a593Smuzhiyun  *
968*4882a593Smuzhiyun  * returns:
969*4882a593Smuzhiyun  *     0, on success
970*4882a593Smuzhiyun  *     -ENOENT if the property could not be found
971*4882a593Smuzhiyun  */
fit_image_get_data_position(const void * fit,int noffset,int * data_position)972*4882a593Smuzhiyun int fit_image_get_data_position(const void *fit, int noffset,
973*4882a593Smuzhiyun 				int *data_position)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun 	const fdt32_t *val;
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun 	val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL);
978*4882a593Smuzhiyun 	if (!val)
979*4882a593Smuzhiyun 		return -ENOENT;
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	*data_position = fdt32_to_cpu(*val);
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	return 0;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun /**
987*4882a593Smuzhiyun  * Get 'data-size' property from a given image node.
988*4882a593Smuzhiyun  *
989*4882a593Smuzhiyun  * @fit: pointer to the FIT image header
990*4882a593Smuzhiyun  * @noffset: component image node offset
991*4882a593Smuzhiyun  * @data_size: holds the data-size property
992*4882a593Smuzhiyun  *
993*4882a593Smuzhiyun  * returns:
994*4882a593Smuzhiyun  *     0, on success
995*4882a593Smuzhiyun  *     -ENOENT if the property could not be found
996*4882a593Smuzhiyun  */
fit_image_get_data_size(const void * fit,int noffset,int * data_size)997*4882a593Smuzhiyun int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun 	const fdt32_t *val;
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun 	val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL);
1002*4882a593Smuzhiyun 	if (!val)
1003*4882a593Smuzhiyun 		return -ENOENT;
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	*data_size = fdt32_to_cpu(*val);
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 	return 0;
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun /**
1011*4882a593Smuzhiyun  * Get 'rollback-index' property from a given image node.
1012*4882a593Smuzhiyun  *
1013*4882a593Smuzhiyun  * @fit: pointer to the FIT image header
1014*4882a593Smuzhiyun  * @noffset: component image node offset
1015*4882a593Smuzhiyun  * @index: holds the rollback-index property
1016*4882a593Smuzhiyun  *
1017*4882a593Smuzhiyun  * returns:
1018*4882a593Smuzhiyun  *     0, on success
1019*4882a593Smuzhiyun  *     -ENOENT if the property could not be found
1020*4882a593Smuzhiyun  */
fit_image_get_rollback_index(const void * fit,int noffset,uint32_t * index)1021*4882a593Smuzhiyun int fit_image_get_rollback_index(const void *fit, int noffset, uint32_t *index)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun 	const fdt32_t *val;
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 	val = fdt_getprop(fit, noffset, FIT_ROLLBACK_PROP, NULL);
1026*4882a593Smuzhiyun 	if (!val)
1027*4882a593Smuzhiyun 		return -ENOENT;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	*index = fdt32_to_cpu(*val);
1030*4882a593Smuzhiyun 
1031*4882a593Smuzhiyun 	return 0;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun /**
1035*4882a593Smuzhiyun  * fit_image_hash_get_algo - get hash algorithm name
1036*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1037*4882a593Smuzhiyun  * @noffset: hash node offset
1038*4882a593Smuzhiyun  * @algo: double pointer to char, will hold pointer to the algorithm name
1039*4882a593Smuzhiyun  *
1040*4882a593Smuzhiyun  * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
1041*4882a593Smuzhiyun  * If the property is found its data start address is returned to the caller.
1042*4882a593Smuzhiyun  *
1043*4882a593Smuzhiyun  * returns:
1044*4882a593Smuzhiyun  *     0, on success
1045*4882a593Smuzhiyun  *     -1, on failure
1046*4882a593Smuzhiyun  */
fit_image_hash_get_algo(const void * fit,int noffset,char ** algo)1047*4882a593Smuzhiyun int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun 	int len;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	*algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
1052*4882a593Smuzhiyun 	if (*algo == NULL) {
1053*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
1054*4882a593Smuzhiyun 		return -1;
1055*4882a593Smuzhiyun 	}
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	return 0;
1058*4882a593Smuzhiyun }
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun /**
1061*4882a593Smuzhiyun  * fit_image_hash_get_value - get hash value and length
1062*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1063*4882a593Smuzhiyun  * @noffset: hash node offset
1064*4882a593Smuzhiyun  * @value: double pointer to uint8_t, will hold address of a hash value data
1065*4882a593Smuzhiyun  * @value_len: pointer to an int, will hold hash data length
1066*4882a593Smuzhiyun  *
1067*4882a593Smuzhiyun  * fit_image_hash_get_value() finds hash value property in a given hash node.
1068*4882a593Smuzhiyun  * If the property is found its data start address and size are returned to
1069*4882a593Smuzhiyun  * the caller.
1070*4882a593Smuzhiyun  *
1071*4882a593Smuzhiyun  * returns:
1072*4882a593Smuzhiyun  *     0, on success
1073*4882a593Smuzhiyun  *     -1, on failure
1074*4882a593Smuzhiyun  */
fit_image_hash_get_value(const void * fit,int noffset,uint8_t ** value,int * value_len)1075*4882a593Smuzhiyun int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
1076*4882a593Smuzhiyun 				int *value_len)
1077*4882a593Smuzhiyun {
1078*4882a593Smuzhiyun 	int len;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	*value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
1081*4882a593Smuzhiyun 	if (*value == NULL) {
1082*4882a593Smuzhiyun 		fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
1083*4882a593Smuzhiyun 		*value_len = 0;
1084*4882a593Smuzhiyun 		return -1;
1085*4882a593Smuzhiyun 	}
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	*value_len = len;
1088*4882a593Smuzhiyun 	return 0;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun /**
1092*4882a593Smuzhiyun  * fit_image_hash_get_ignore - get hash ignore flag
1093*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1094*4882a593Smuzhiyun  * @noffset: hash node offset
1095*4882a593Smuzhiyun  * @ignore: pointer to an int, will hold hash ignore flag
1096*4882a593Smuzhiyun  *
1097*4882a593Smuzhiyun  * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
1098*4882a593Smuzhiyun  * If the property is found and non-zero, the hash algorithm is not verified by
1099*4882a593Smuzhiyun  * u-boot automatically.
1100*4882a593Smuzhiyun  *
1101*4882a593Smuzhiyun  * returns:
1102*4882a593Smuzhiyun  *     0, on ignore not found
1103*4882a593Smuzhiyun  *     value, on ignore found
1104*4882a593Smuzhiyun  */
fit_image_hash_get_ignore(const void * fit,int noffset,int * ignore)1105*4882a593Smuzhiyun static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
1106*4882a593Smuzhiyun {
1107*4882a593Smuzhiyun 	int len;
1108*4882a593Smuzhiyun 	int *value;
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
1111*4882a593Smuzhiyun 	if (value == NULL || len != sizeof(int))
1112*4882a593Smuzhiyun 		*ignore = 0;
1113*4882a593Smuzhiyun 	else
1114*4882a593Smuzhiyun 		*ignore = *value;
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 	return 0;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun 
fit_get_end(const void * fit)1119*4882a593Smuzhiyun ulong fit_get_end(const void *fit)
1120*4882a593Smuzhiyun {
1121*4882a593Smuzhiyun 	return map_to_sysmem((void *)(fit + fdt_totalsize(fit)));
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun /**
1125*4882a593Smuzhiyun  * fit_set_timestamp - set node timestamp property
1126*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1127*4882a593Smuzhiyun  * @noffset: node offset
1128*4882a593Smuzhiyun  * @timestamp: timestamp value to be set
1129*4882a593Smuzhiyun  *
1130*4882a593Smuzhiyun  * fit_set_timestamp() attempts to set timestamp property in the requested
1131*4882a593Smuzhiyun  * node and returns operation status to the caller.
1132*4882a593Smuzhiyun  *
1133*4882a593Smuzhiyun  * returns:
1134*4882a593Smuzhiyun  *     0, on success
1135*4882a593Smuzhiyun  *     -ENOSPC if no space in device tree, -1 for other error
1136*4882a593Smuzhiyun  */
fit_set_timestamp(void * fit,int noffset,time_t timestamp)1137*4882a593Smuzhiyun int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
1138*4882a593Smuzhiyun {
1139*4882a593Smuzhiyun 	uint32_t t;
1140*4882a593Smuzhiyun 	int ret;
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun 	t = cpu_to_uimage(timestamp);
1143*4882a593Smuzhiyun 	ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
1144*4882a593Smuzhiyun 				sizeof(uint32_t));
1145*4882a593Smuzhiyun 	if (ret) {
1146*4882a593Smuzhiyun 		debug("Can't set '%s' property for '%s' node (%s)\n",
1147*4882a593Smuzhiyun 		      FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
1148*4882a593Smuzhiyun 		      fdt_strerror(ret));
1149*4882a593Smuzhiyun 		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
1150*4882a593Smuzhiyun 	}
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	return 0;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun 
fit_set_totalsize(void * fit,int noffset,int totalsize)1155*4882a593Smuzhiyun int fit_set_totalsize(void *fit, int noffset, int totalsize)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun 	uint32_t t;
1158*4882a593Smuzhiyun 	int ret;
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 	t = cpu_to_uimage(totalsize);
1161*4882a593Smuzhiyun 	ret = fdt_setprop(fit, noffset, FIT_TOTALSIZE_PROP, &t,
1162*4882a593Smuzhiyun 				sizeof(uint32_t));
1163*4882a593Smuzhiyun 	if (ret)
1164*4882a593Smuzhiyun 		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	return 0;
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun 
fit_set_version(void * fit,int noffset,int version)1169*4882a593Smuzhiyun int fit_set_version(void *fit, int noffset, int version)
1170*4882a593Smuzhiyun {
1171*4882a593Smuzhiyun 	uint32_t v;
1172*4882a593Smuzhiyun 	int ret;
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	v = cpu_to_uimage(version);
1175*4882a593Smuzhiyun 	ret = fdt_setprop(fit, noffset, FIT_VERSION_PROP, &v, sizeof(uint32_t));
1176*4882a593Smuzhiyun 	if (ret)
1177*4882a593Smuzhiyun 		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	return 0;
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun 
fit_calculate_hash(const void * data,int data_len,const char * algo,uint8_t * value,int * value_len)1182*4882a593Smuzhiyun int fit_calculate_hash(const void *data, int data_len,
1183*4882a593Smuzhiyun 		       const char *algo, uint8_t *value,
1184*4882a593Smuzhiyun 		       int *value_len)
1185*4882a593Smuzhiyun {
1186*4882a593Smuzhiyun 	if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
1187*4882a593Smuzhiyun 		*((uint32_t *)value) = crc32_wd(0, data, data_len,
1188*4882a593Smuzhiyun 							CHUNKSZ_CRC32);
1189*4882a593Smuzhiyun 		*((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
1190*4882a593Smuzhiyun 		*value_len = 4;
1191*4882a593Smuzhiyun #ifdef CONFIG_SHA1
1192*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
1193*4882a593Smuzhiyun 		sha1_csum_wd((unsigned char *)data, data_len,
1194*4882a593Smuzhiyun 			     (unsigned char *)value, CHUNKSZ_SHA1);
1195*4882a593Smuzhiyun 		*value_len = 20;
1196*4882a593Smuzhiyun #endif
1197*4882a593Smuzhiyun #ifdef CONFIG_SHA256
1198*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) {
1199*4882a593Smuzhiyun 		sha256_csum_wd((unsigned char *)data, data_len,
1200*4882a593Smuzhiyun 			       (unsigned char *)value, CHUNKSZ_SHA256);
1201*4882a593Smuzhiyun 		*value_len = SHA256_SUM_LEN;
1202*4882a593Smuzhiyun #endif
1203*4882a593Smuzhiyun #ifdef CONFIG_MD5
1204*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
1205*4882a593Smuzhiyun 		md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
1206*4882a593Smuzhiyun 		*value_len = 16;
1207*4882a593Smuzhiyun #endif
1208*4882a593Smuzhiyun 	} else {
1209*4882a593Smuzhiyun 		debug("Unsupported hash alogrithm\n");
1210*4882a593Smuzhiyun 		return -1;
1211*4882a593Smuzhiyun 	}
1212*4882a593Smuzhiyun 	return 0;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun #ifndef USE_HOSTCC
1216*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(FIT_HW_CRYPTO)
crypto_csum(u32 cap,const char * data,int len,u8 * output)1217*4882a593Smuzhiyun static int crypto_csum(u32 cap, const char *data, int len, u8 *output)
1218*4882a593Smuzhiyun {
1219*4882a593Smuzhiyun 	struct udevice *dev;
1220*4882a593Smuzhiyun 	sha_context csha_ctx;
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	dev = crypto_get_device(cap);
1223*4882a593Smuzhiyun 	if (!dev) {
1224*4882a593Smuzhiyun 		printf("Can't find expected crypto device\n");
1225*4882a593Smuzhiyun 		return -ENODEV;
1226*4882a593Smuzhiyun 	}
1227*4882a593Smuzhiyun 
1228*4882a593Smuzhiyun 	csha_ctx.algo = cap;
1229*4882a593Smuzhiyun 	csha_ctx.length = len;
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	return crypto_sha_csum(dev, &csha_ctx, (char *)data, len, output);
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun 
hw_fit_calculate_hash(const void * data,int data_len,const char * algo,uint8_t * value,int * value_len)1234*4882a593Smuzhiyun static int hw_fit_calculate_hash(const void *data, int data_len,
1235*4882a593Smuzhiyun 				 const char *algo, uint8_t *value,
1236*4882a593Smuzhiyun 				 int *value_len)
1237*4882a593Smuzhiyun {
1238*4882a593Smuzhiyun 	int ret = 0;
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
1241*4882a593Smuzhiyun 		*((uint32_t *)value) = crc32_wd(0, data, data_len,
1242*4882a593Smuzhiyun 							CHUNKSZ_CRC32);
1243*4882a593Smuzhiyun 		*((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
1244*4882a593Smuzhiyun 		*value_len = 4;
1245*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
1246*4882a593Smuzhiyun 		ret = crypto_csum(CRYPTO_SHA1, data, data_len, value);
1247*4882a593Smuzhiyun 		*value_len = 20;
1248*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) {
1249*4882a593Smuzhiyun 		ret = crypto_csum(CRYPTO_SHA256, data, data_len, value);
1250*4882a593Smuzhiyun 		*value_len = SHA256_SUM_LEN;
1251*4882a593Smuzhiyun 	} else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
1252*4882a593Smuzhiyun 		ret = crypto_csum(CRYPTO_MD5, data, data_len, value);
1253*4882a593Smuzhiyun 		*value_len = 16;
1254*4882a593Smuzhiyun 	} else {
1255*4882a593Smuzhiyun 		debug("Unsupported hash alogrithm\n");
1256*4882a593Smuzhiyun 		return -1;
1257*4882a593Smuzhiyun 	}
1258*4882a593Smuzhiyun 
1259*4882a593Smuzhiyun 	if (ret)
1260*4882a593Smuzhiyun 		printf("%s: algo %s failed, ret=%d\n", __func__, algo, ret);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	return ret;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun #endif
1265*4882a593Smuzhiyun #endif
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun /**
1268*4882a593Smuzhiyun  * calculate_hash - calculate and return hash for provided input data
1269*4882a593Smuzhiyun  * @data: pointer to the input data
1270*4882a593Smuzhiyun  * @data_len: data length
1271*4882a593Smuzhiyun  * @algo: requested hash algorithm
1272*4882a593Smuzhiyun  * @value: pointer to the char, will hold hash value data (caller must
1273*4882a593Smuzhiyun  * allocate enough free space)
1274*4882a593Smuzhiyun  * value_len: length of the calculated hash
1275*4882a593Smuzhiyun  *
1276*4882a593Smuzhiyun  * calculate_hash() computes input data hash according to the requested
1277*4882a593Smuzhiyun  * algorithm.
1278*4882a593Smuzhiyun  * Resulting hash value is placed in caller provided 'value' buffer, length
1279*4882a593Smuzhiyun  * of the calculated hash is returned via value_len pointer argument.
1280*4882a593Smuzhiyun  *
1281*4882a593Smuzhiyun  * returns:
1282*4882a593Smuzhiyun  *     0, on success
1283*4882a593Smuzhiyun  *    -1, when algo is unsupported
1284*4882a593Smuzhiyun  */
calculate_hash(const void * data,int data_len,const char * algo,uint8_t * value,int * value_len)1285*4882a593Smuzhiyun int calculate_hash(const void *data, int data_len, const char *algo,
1286*4882a593Smuzhiyun 		   uint8_t *value, int *value_len)
1287*4882a593Smuzhiyun {
1288*4882a593Smuzhiyun #if defined(USE_HOSTCC)
1289*4882a593Smuzhiyun 	return fit_calculate_hash(data, data_len, algo, value, value_len);
1290*4882a593Smuzhiyun #else
1291*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(FIT_HW_CRYPTO)
1292*4882a593Smuzhiyun 	return fit_calculate_hash(data, data_len, algo, value, value_len);
1293*4882a593Smuzhiyun #else
1294*4882a593Smuzhiyun 	return hw_fit_calculate_hash(data, data_len, algo, value, value_len);
1295*4882a593Smuzhiyun #endif
1296*4882a593Smuzhiyun #endif
1297*4882a593Smuzhiyun }
1298*4882a593Smuzhiyun 
fit_image_check_hash(const void * fit,int noffset,const void * data,size_t size,char ** err_msgp)1299*4882a593Smuzhiyun int fit_image_check_hash(const void *fit, int noffset, const void *data,
1300*4882a593Smuzhiyun 			 size_t size, char **err_msgp)
1301*4882a593Smuzhiyun {
1302*4882a593Smuzhiyun 	uint8_t value[FIT_MAX_HASH_LEN];
1303*4882a593Smuzhiyun 	int value_len;
1304*4882a593Smuzhiyun 	char *algo;
1305*4882a593Smuzhiyun 	uint8_t *fit_value;
1306*4882a593Smuzhiyun 	int fit_value_len;
1307*4882a593Smuzhiyun 	int ignore;
1308*4882a593Smuzhiyun 	int i;
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun 	*err_msgp = NULL;
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
1313*4882a593Smuzhiyun 		*err_msgp = "Can't get hash algo property";
1314*4882a593Smuzhiyun 		return -1;
1315*4882a593Smuzhiyun 	}
1316*4882a593Smuzhiyun 	printf("%s", algo);
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	if (IMAGE_ENABLE_IGNORE) {
1319*4882a593Smuzhiyun 		fit_image_hash_get_ignore(fit, noffset, &ignore);
1320*4882a593Smuzhiyun 		if (ignore) {
1321*4882a593Smuzhiyun 			printf("-skipped ");
1322*4882a593Smuzhiyun 			return 0;
1323*4882a593Smuzhiyun 		}
1324*4882a593Smuzhiyun 	}
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
1327*4882a593Smuzhiyun 				     &fit_value_len)) {
1328*4882a593Smuzhiyun 		*err_msgp = "Can't get hash value property";
1329*4882a593Smuzhiyun 		return -1;
1330*4882a593Smuzhiyun 	}
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 	if (calculate_hash(data, size, algo, value, &value_len)) {
1333*4882a593Smuzhiyun 		*err_msgp = "Unsupported hash algorithm";
1334*4882a593Smuzhiyun 		return -1;
1335*4882a593Smuzhiyun 	}
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 	if (value_len != fit_value_len) {
1338*4882a593Smuzhiyun 		*err_msgp = "Bad hash value len";
1339*4882a593Smuzhiyun 		return -1;
1340*4882a593Smuzhiyun 	} else if (memcmp(value, fit_value, value_len) != 0) {
1341*4882a593Smuzhiyun 		printf(" Bad hash: ");
1342*4882a593Smuzhiyun 		for (i = 0; i < value_len; i++)
1343*4882a593Smuzhiyun 			printf("%02x", value[i]);
1344*4882a593Smuzhiyun 		printf("\n");
1345*4882a593Smuzhiyun 
1346*4882a593Smuzhiyun 		*err_msgp = "Bad hash value";
1347*4882a593Smuzhiyun 		return -1;
1348*4882a593Smuzhiyun 	}
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
1351*4882a593Smuzhiyun 	printf("(");
1352*4882a593Smuzhiyun 	for (i = 0; i < 5; i++)
1353*4882a593Smuzhiyun 		printf("%02x", value[i]);
1354*4882a593Smuzhiyun 	printf("...) ");
1355*4882a593Smuzhiyun #endif
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun 	return 0;
1358*4882a593Smuzhiyun }
1359*4882a593Smuzhiyun 
fit_image_verify_with_data(const void * fit,int image_noffset,const void * data,size_t size)1360*4882a593Smuzhiyun int fit_image_verify_with_data(const void *fit, int image_noffset,
1361*4882a593Smuzhiyun 			       const void *data, size_t size)
1362*4882a593Smuzhiyun {
1363*4882a593Smuzhiyun 	int		noffset = 0;
1364*4882a593Smuzhiyun 	char		*err_msg = "";
1365*4882a593Smuzhiyun 	int verify_all = 1;
1366*4882a593Smuzhiyun 	int ret;
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 	/* Verify all required signatures */
1369*4882a593Smuzhiyun 	if (IMAGE_ENABLE_VERIFY &&
1370*4882a593Smuzhiyun 	    fit_image_verify_required_sigs(fit, image_noffset, data, size,
1371*4882a593Smuzhiyun 					   gd_fdt_blob(), &verify_all)) {
1372*4882a593Smuzhiyun 		err_msg = "Unable to verify required signature";
1373*4882a593Smuzhiyun 		goto error;
1374*4882a593Smuzhiyun 	}
1375*4882a593Smuzhiyun 
1376*4882a593Smuzhiyun 	/* Process all hash subnodes of the component image node */
1377*4882a593Smuzhiyun 	fdt_for_each_subnode(noffset, fit, image_noffset) {
1378*4882a593Smuzhiyun 		const char *name = fit_get_name(fit, noffset, NULL);
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 		/*
1381*4882a593Smuzhiyun 		 * Check subnode name, must be equal to "hash".
1382*4882a593Smuzhiyun 		 * Multiple hash nodes require unique unit node
1383*4882a593Smuzhiyun 		 * names, e.g. hash@1, hash@2, etc.
1384*4882a593Smuzhiyun 		 */
1385*4882a593Smuzhiyun 		if (!strncmp(name, FIT_HASH_NODENAME,
1386*4882a593Smuzhiyun 			     strlen(FIT_HASH_NODENAME))) {
1387*4882a593Smuzhiyun 			if (fit_image_check_hash(fit, noffset, data, size,
1388*4882a593Smuzhiyun 						 &err_msg))
1389*4882a593Smuzhiyun 				goto error;
1390*4882a593Smuzhiyun 			puts("+ ");
1391*4882a593Smuzhiyun 		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
1392*4882a593Smuzhiyun 				!strncmp(name, FIT_SIG_NODENAME,
1393*4882a593Smuzhiyun 					strlen(FIT_SIG_NODENAME))) {
1394*4882a593Smuzhiyun 			ret = fit_image_check_sig(fit, noffset, data,
1395*4882a593Smuzhiyun 							size, -1, &err_msg);
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 			/*
1398*4882a593Smuzhiyun 			 * Show an indication on failure, but do not return
1399*4882a593Smuzhiyun 			 * an error. Only keys marked 'required' can cause
1400*4882a593Smuzhiyun 			 * an image validation failure. See the call to
1401*4882a593Smuzhiyun 			 * fit_image_verify_required_sigs() above.
1402*4882a593Smuzhiyun 			 */
1403*4882a593Smuzhiyun 			if (ret)
1404*4882a593Smuzhiyun 				puts("- ");
1405*4882a593Smuzhiyun 			else
1406*4882a593Smuzhiyun 				puts("+ ");
1407*4882a593Smuzhiyun 		}
1408*4882a593Smuzhiyun 	}
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
1411*4882a593Smuzhiyun 		err_msg = "Corrupted or truncated tree";
1412*4882a593Smuzhiyun 		goto error;
1413*4882a593Smuzhiyun 	}
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun 	return 1; /* success */
1416*4882a593Smuzhiyun 
1417*4882a593Smuzhiyun error:
1418*4882a593Smuzhiyun 	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
1419*4882a593Smuzhiyun 	       err_msg, fit_get_name(fit, noffset, NULL),
1420*4882a593Smuzhiyun 	       fit_get_name(fit, image_noffset, NULL));
1421*4882a593Smuzhiyun 	return 0;
1422*4882a593Smuzhiyun }
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun /**
1425*4882a593Smuzhiyun  * fit_image_verify - verify data integrity
1426*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1427*4882a593Smuzhiyun  * @image_noffset: component image node offset
1428*4882a593Smuzhiyun  *
1429*4882a593Smuzhiyun  * fit_image_verify() goes over component image hash nodes,
1430*4882a593Smuzhiyun  * re-calculates each data hash and compares with the value stored in hash
1431*4882a593Smuzhiyun  * node.
1432*4882a593Smuzhiyun  *
1433*4882a593Smuzhiyun  * returns:
1434*4882a593Smuzhiyun  *     1, if all hashes are valid
1435*4882a593Smuzhiyun  *     0, otherwise (or on error)
1436*4882a593Smuzhiyun  */
fit_image_verify(const void * fit,int image_noffset)1437*4882a593Smuzhiyun int fit_image_verify(const void *fit, int image_noffset)
1438*4882a593Smuzhiyun {
1439*4882a593Smuzhiyun 	const void	*data;
1440*4882a593Smuzhiyun 	size_t		size;
1441*4882a593Smuzhiyun 	int		noffset = 0;
1442*4882a593Smuzhiyun 	char		*err_msg = "";
1443*4882a593Smuzhiyun 
1444*4882a593Smuzhiyun 	/* Get image data and data length */
1445*4882a593Smuzhiyun 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
1446*4882a593Smuzhiyun 		err_msg = "Can't get image data/size";
1447*4882a593Smuzhiyun 		printf("error!\n%s for '%s' hash node in '%s' image node\n",
1448*4882a593Smuzhiyun 		       err_msg, fit_get_name(fit, noffset, NULL),
1449*4882a593Smuzhiyun 		       fit_get_name(fit, image_noffset, NULL));
1450*4882a593Smuzhiyun 		return 0;
1451*4882a593Smuzhiyun 	}
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun 	return fit_image_verify_with_data(fit, image_noffset, data, size);
1454*4882a593Smuzhiyun }
1455*4882a593Smuzhiyun 
1456*4882a593Smuzhiyun /**
1457*4882a593Smuzhiyun  * fit_all_image_verify - verify data integrity for all images
1458*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1459*4882a593Smuzhiyun  *
1460*4882a593Smuzhiyun  * fit_all_image_verify() goes over all images in the FIT and
1461*4882a593Smuzhiyun  * for every images checks if all it's hashes are valid.
1462*4882a593Smuzhiyun  *
1463*4882a593Smuzhiyun  * returns:
1464*4882a593Smuzhiyun  *     1, if all hashes of all images are valid
1465*4882a593Smuzhiyun  *     0, otherwise (or on error)
1466*4882a593Smuzhiyun  */
fit_all_image_verify(const void * fit)1467*4882a593Smuzhiyun int fit_all_image_verify(const void *fit)
1468*4882a593Smuzhiyun {
1469*4882a593Smuzhiyun 	int images_noffset;
1470*4882a593Smuzhiyun 	int noffset;
1471*4882a593Smuzhiyun 	int ndepth;
1472*4882a593Smuzhiyun 	int count;
1473*4882a593Smuzhiyun 
1474*4882a593Smuzhiyun 	/* Find images parent node offset */
1475*4882a593Smuzhiyun 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1476*4882a593Smuzhiyun 	if (images_noffset < 0) {
1477*4882a593Smuzhiyun 		printf("Can't find images parent node '%s' (%s)\n",
1478*4882a593Smuzhiyun 		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1479*4882a593Smuzhiyun 		return 0;
1480*4882a593Smuzhiyun 	}
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	/* Process all image subnodes, check hashes for each */
1483*4882a593Smuzhiyun 	printf("## Checking hash(es) for FIT Image at %08lx ...\n",
1484*4882a593Smuzhiyun 	       (ulong)fit);
1485*4882a593Smuzhiyun 	for (ndepth = 0, count = 0,
1486*4882a593Smuzhiyun 	     noffset = fdt_next_node(fit, images_noffset, &ndepth);
1487*4882a593Smuzhiyun 			(noffset >= 0) && (ndepth > 0);
1488*4882a593Smuzhiyun 			noffset = fdt_next_node(fit, noffset, &ndepth)) {
1489*4882a593Smuzhiyun 		if (ndepth == 1) {
1490*4882a593Smuzhiyun 			/*
1491*4882a593Smuzhiyun 			 * Direct child node of the images parent node,
1492*4882a593Smuzhiyun 			 * i.e. component image node.
1493*4882a593Smuzhiyun 			 */
1494*4882a593Smuzhiyun 			printf("   Hash(es) for Image %u (%s): ", count,
1495*4882a593Smuzhiyun 			       fit_get_name(fit, noffset, NULL));
1496*4882a593Smuzhiyun 			count++;
1497*4882a593Smuzhiyun 
1498*4882a593Smuzhiyun 			if (!fit_image_verify(fit, noffset))
1499*4882a593Smuzhiyun 				return 0;
1500*4882a593Smuzhiyun 			printf("\n");
1501*4882a593Smuzhiyun 		}
1502*4882a593Smuzhiyun 	}
1503*4882a593Smuzhiyun 	return 1;
1504*4882a593Smuzhiyun }
1505*4882a593Smuzhiyun 
1506*4882a593Smuzhiyun /**
1507*4882a593Smuzhiyun  * fit_image_check_os - check whether image node is of a given os type
1508*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1509*4882a593Smuzhiyun  * @noffset: component image node offset
1510*4882a593Smuzhiyun  * @os: requested image os
1511*4882a593Smuzhiyun  *
1512*4882a593Smuzhiyun  * fit_image_check_os() reads image os property and compares its numeric
1513*4882a593Smuzhiyun  * id with the requested os. Comparison result is returned to the caller.
1514*4882a593Smuzhiyun  *
1515*4882a593Smuzhiyun  * returns:
1516*4882a593Smuzhiyun  *     1 if image is of given os type
1517*4882a593Smuzhiyun  *     0 otherwise (or on error)
1518*4882a593Smuzhiyun  */
fit_image_check_os(const void * fit,int noffset,uint8_t os)1519*4882a593Smuzhiyun int fit_image_check_os(const void *fit, int noffset, uint8_t os)
1520*4882a593Smuzhiyun {
1521*4882a593Smuzhiyun 	uint8_t image_os;
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun 	if (fit_image_get_os(fit, noffset, &image_os))
1524*4882a593Smuzhiyun 		return 0;
1525*4882a593Smuzhiyun 	return (os == image_os);
1526*4882a593Smuzhiyun }
1527*4882a593Smuzhiyun 
1528*4882a593Smuzhiyun /**
1529*4882a593Smuzhiyun  * fit_image_check_arch - check whether image node is of a given arch
1530*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1531*4882a593Smuzhiyun  * @noffset: component image node offset
1532*4882a593Smuzhiyun  * @arch: requested imagearch
1533*4882a593Smuzhiyun  *
1534*4882a593Smuzhiyun  * fit_image_check_arch() reads image arch property and compares its numeric
1535*4882a593Smuzhiyun  * id with the requested arch. Comparison result is returned to the caller.
1536*4882a593Smuzhiyun  *
1537*4882a593Smuzhiyun  * returns:
1538*4882a593Smuzhiyun  *     1 if image is of given arch
1539*4882a593Smuzhiyun  *     0 otherwise (or on error)
1540*4882a593Smuzhiyun  */
fit_image_check_arch(const void * fit,int noffset,uint8_t arch)1541*4882a593Smuzhiyun int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
1542*4882a593Smuzhiyun {
1543*4882a593Smuzhiyun 	uint8_t image_arch;
1544*4882a593Smuzhiyun 	int aarch32_support = 0;
1545*4882a593Smuzhiyun 
1546*4882a593Smuzhiyun #ifdef CONFIG_ARM64_SUPPORT_AARCH32
1547*4882a593Smuzhiyun 	aarch32_support = 1;
1548*4882a593Smuzhiyun #endif
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	if (fit_image_get_arch(fit, noffset, &image_arch))
1551*4882a593Smuzhiyun 		return 0;
1552*4882a593Smuzhiyun 	return (arch == image_arch) ||
1553*4882a593Smuzhiyun 		(arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) ||
1554*4882a593Smuzhiyun 		(arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM &&
1555*4882a593Smuzhiyun 		 aarch32_support);
1556*4882a593Smuzhiyun }
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun /**
1559*4882a593Smuzhiyun  * fit_image_check_type - check whether image node is of a given type
1560*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1561*4882a593Smuzhiyun  * @noffset: component image node offset
1562*4882a593Smuzhiyun  * @type: requested image type
1563*4882a593Smuzhiyun  *
1564*4882a593Smuzhiyun  * fit_image_check_type() reads image type property and compares its numeric
1565*4882a593Smuzhiyun  * id with the requested type. Comparison result is returned to the caller.
1566*4882a593Smuzhiyun  *
1567*4882a593Smuzhiyun  * returns:
1568*4882a593Smuzhiyun  *     1 if image is of given type
1569*4882a593Smuzhiyun  *     0 otherwise (or on error)
1570*4882a593Smuzhiyun  */
fit_image_check_type(const void * fit,int noffset,uint8_t type)1571*4882a593Smuzhiyun int fit_image_check_type(const void *fit, int noffset, uint8_t type)
1572*4882a593Smuzhiyun {
1573*4882a593Smuzhiyun 	uint8_t image_type;
1574*4882a593Smuzhiyun 
1575*4882a593Smuzhiyun 	if (fit_image_get_type(fit, noffset, &image_type))
1576*4882a593Smuzhiyun 		return 0;
1577*4882a593Smuzhiyun 	return (type == image_type);
1578*4882a593Smuzhiyun }
1579*4882a593Smuzhiyun 
1580*4882a593Smuzhiyun /**
1581*4882a593Smuzhiyun  * fit_image_check_comp - check whether image node uses given compression
1582*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1583*4882a593Smuzhiyun  * @noffset: component image node offset
1584*4882a593Smuzhiyun  * @comp: requested image compression type
1585*4882a593Smuzhiyun  *
1586*4882a593Smuzhiyun  * fit_image_check_comp() reads image compression property and compares its
1587*4882a593Smuzhiyun  * numeric id with the requested compression type. Comparison result is
1588*4882a593Smuzhiyun  * returned to the caller.
1589*4882a593Smuzhiyun  *
1590*4882a593Smuzhiyun  * returns:
1591*4882a593Smuzhiyun  *     1 if image uses requested compression
1592*4882a593Smuzhiyun  *     0 otherwise (or on error)
1593*4882a593Smuzhiyun  */
fit_image_check_comp(const void * fit,int noffset,uint8_t comp)1594*4882a593Smuzhiyun int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
1595*4882a593Smuzhiyun {
1596*4882a593Smuzhiyun 	uint8_t image_comp;
1597*4882a593Smuzhiyun 
1598*4882a593Smuzhiyun 	if (fit_image_get_comp(fit, noffset, &image_comp))
1599*4882a593Smuzhiyun 		return 0;
1600*4882a593Smuzhiyun 	return (comp == image_comp);
1601*4882a593Smuzhiyun }
1602*4882a593Smuzhiyun 
1603*4882a593Smuzhiyun /**
1604*4882a593Smuzhiyun  * fit_check_format - sanity check FIT image format
1605*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1606*4882a593Smuzhiyun  *
1607*4882a593Smuzhiyun  * fit_check_format() runs a basic sanity FIT image verification.
1608*4882a593Smuzhiyun  * Routine checks for mandatory properties, nodes, etc.
1609*4882a593Smuzhiyun  *
1610*4882a593Smuzhiyun  * returns:
1611*4882a593Smuzhiyun  *     1, on success
1612*4882a593Smuzhiyun  *     0, on failure
1613*4882a593Smuzhiyun  */
fit_check_format(const void * fit)1614*4882a593Smuzhiyun int fit_check_format(const void *fit)
1615*4882a593Smuzhiyun {
1616*4882a593Smuzhiyun 	/* mandatory / node 'description' property */
1617*4882a593Smuzhiyun 	if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
1618*4882a593Smuzhiyun 		debug("Wrong FIT format: no description\n");
1619*4882a593Smuzhiyun 		return 0;
1620*4882a593Smuzhiyun 	}
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 	if (IMAGE_ENABLE_TIMESTAMP) {
1623*4882a593Smuzhiyun 		/* mandatory / node 'timestamp' property */
1624*4882a593Smuzhiyun 		if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
1625*4882a593Smuzhiyun 			debug("Wrong FIT format: no timestamp\n");
1626*4882a593Smuzhiyun 			return 0;
1627*4882a593Smuzhiyun 		}
1628*4882a593Smuzhiyun 	}
1629*4882a593Smuzhiyun 
1630*4882a593Smuzhiyun 	/* mandatory subimages parent '/images' node */
1631*4882a593Smuzhiyun 	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
1632*4882a593Smuzhiyun 		debug("Wrong FIT format: no images parent node\n");
1633*4882a593Smuzhiyun 		return 0;
1634*4882a593Smuzhiyun 	}
1635*4882a593Smuzhiyun 
1636*4882a593Smuzhiyun 	return 1;
1637*4882a593Smuzhiyun }
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun 
1640*4882a593Smuzhiyun /**
1641*4882a593Smuzhiyun  * fit_conf_find_compat
1642*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1643*4882a593Smuzhiyun  * @fdt: pointer to the device tree to compare against
1644*4882a593Smuzhiyun  *
1645*4882a593Smuzhiyun  * fit_conf_find_compat() attempts to find the configuration whose fdt is the
1646*4882a593Smuzhiyun  * most compatible with the passed in device tree.
1647*4882a593Smuzhiyun  *
1648*4882a593Smuzhiyun  * Example:
1649*4882a593Smuzhiyun  *
1650*4882a593Smuzhiyun  * / o image-tree
1651*4882a593Smuzhiyun  *   |-o images
1652*4882a593Smuzhiyun  *   | |-o fdt@1
1653*4882a593Smuzhiyun  *   | |-o fdt@2
1654*4882a593Smuzhiyun  *   |
1655*4882a593Smuzhiyun  *   |-o configurations
1656*4882a593Smuzhiyun  *     |-o config@1
1657*4882a593Smuzhiyun  *     | |-fdt = fdt@1
1658*4882a593Smuzhiyun  *     |
1659*4882a593Smuzhiyun  *     |-o config@2
1660*4882a593Smuzhiyun  *       |-fdt = fdt@2
1661*4882a593Smuzhiyun  *
1662*4882a593Smuzhiyun  * / o U-Boot fdt
1663*4882a593Smuzhiyun  *   |-compatible = "foo,bar", "bim,bam"
1664*4882a593Smuzhiyun  *
1665*4882a593Smuzhiyun  * / o kernel fdt1
1666*4882a593Smuzhiyun  *   |-compatible = "foo,bar",
1667*4882a593Smuzhiyun  *
1668*4882a593Smuzhiyun  * / o kernel fdt2
1669*4882a593Smuzhiyun  *   |-compatible = "bim,bam", "baz,biz"
1670*4882a593Smuzhiyun  *
1671*4882a593Smuzhiyun  * Configuration 1 would be picked because the first string in U-Boot's
1672*4882a593Smuzhiyun  * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
1673*4882a593Smuzhiyun  * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
1674*4882a593Smuzhiyun  *
1675*4882a593Smuzhiyun  * returns:
1676*4882a593Smuzhiyun  *     offset to the configuration to use if one was found
1677*4882a593Smuzhiyun  *     -1 otherwise
1678*4882a593Smuzhiyun  */
fit_conf_find_compat(const void * fit,const void * fdt)1679*4882a593Smuzhiyun int fit_conf_find_compat(const void *fit, const void *fdt)
1680*4882a593Smuzhiyun {
1681*4882a593Smuzhiyun 	int ndepth = 0;
1682*4882a593Smuzhiyun 	int noffset, confs_noffset, images_noffset;
1683*4882a593Smuzhiyun 	const void *fdt_compat;
1684*4882a593Smuzhiyun 	int fdt_compat_len;
1685*4882a593Smuzhiyun 	int best_match_offset = 0;
1686*4882a593Smuzhiyun 	int best_match_pos = 0;
1687*4882a593Smuzhiyun 
1688*4882a593Smuzhiyun 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1689*4882a593Smuzhiyun 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1690*4882a593Smuzhiyun 	if (confs_noffset < 0 || images_noffset < 0) {
1691*4882a593Smuzhiyun 		debug("Can't find configurations or images nodes.\n");
1692*4882a593Smuzhiyun 		return -1;
1693*4882a593Smuzhiyun 	}
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun 	fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
1696*4882a593Smuzhiyun 	if (!fdt_compat) {
1697*4882a593Smuzhiyun 		debug("Fdt for comparison has no \"compatible\" property.\n");
1698*4882a593Smuzhiyun 		return -1;
1699*4882a593Smuzhiyun 	}
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun 	/*
1702*4882a593Smuzhiyun 	 * Loop over the configurations in the FIT image.
1703*4882a593Smuzhiyun 	 */
1704*4882a593Smuzhiyun 	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
1705*4882a593Smuzhiyun 			(noffset >= 0) && (ndepth > 0);
1706*4882a593Smuzhiyun 			noffset = fdt_next_node(fit, noffset, &ndepth)) {
1707*4882a593Smuzhiyun 		const void *kfdt;
1708*4882a593Smuzhiyun 		const char *kfdt_name;
1709*4882a593Smuzhiyun 		int kfdt_noffset;
1710*4882a593Smuzhiyun 		const char *cur_fdt_compat;
1711*4882a593Smuzhiyun 		int len;
1712*4882a593Smuzhiyun 		size_t size;
1713*4882a593Smuzhiyun 		int i;
1714*4882a593Smuzhiyun 
1715*4882a593Smuzhiyun 		if (ndepth > 1)
1716*4882a593Smuzhiyun 			continue;
1717*4882a593Smuzhiyun 
1718*4882a593Smuzhiyun 		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
1719*4882a593Smuzhiyun 		if (!kfdt_name) {
1720*4882a593Smuzhiyun 			debug("No fdt property found.\n");
1721*4882a593Smuzhiyun 			continue;
1722*4882a593Smuzhiyun 		}
1723*4882a593Smuzhiyun 		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
1724*4882a593Smuzhiyun 						  kfdt_name);
1725*4882a593Smuzhiyun 		if (kfdt_noffset < 0) {
1726*4882a593Smuzhiyun 			debug("No image node named \"%s\" found.\n",
1727*4882a593Smuzhiyun 			      kfdt_name);
1728*4882a593Smuzhiyun 			continue;
1729*4882a593Smuzhiyun 		}
1730*4882a593Smuzhiyun 		/*
1731*4882a593Smuzhiyun 		 * Get a pointer to this configuration's fdt.
1732*4882a593Smuzhiyun 		 */
1733*4882a593Smuzhiyun 		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
1734*4882a593Smuzhiyun 			debug("Failed to get fdt \"%s\".\n", kfdt_name);
1735*4882a593Smuzhiyun 			continue;
1736*4882a593Smuzhiyun 		}
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun 		len = fdt_compat_len;
1739*4882a593Smuzhiyun 		cur_fdt_compat = fdt_compat;
1740*4882a593Smuzhiyun 		/*
1741*4882a593Smuzhiyun 		 * Look for a match for each U-Boot compatibility string in
1742*4882a593Smuzhiyun 		 * turn in this configuration's fdt.
1743*4882a593Smuzhiyun 		 */
1744*4882a593Smuzhiyun 		for (i = 0; len > 0 &&
1745*4882a593Smuzhiyun 		     (!best_match_offset || best_match_pos > i); i++) {
1746*4882a593Smuzhiyun 			int cur_len = strlen(cur_fdt_compat) + 1;
1747*4882a593Smuzhiyun 
1748*4882a593Smuzhiyun 			if (!fdt_node_check_compatible(kfdt, 0,
1749*4882a593Smuzhiyun 						       cur_fdt_compat)) {
1750*4882a593Smuzhiyun 				best_match_offset = noffset;
1751*4882a593Smuzhiyun 				best_match_pos = i;
1752*4882a593Smuzhiyun 				break;
1753*4882a593Smuzhiyun 			}
1754*4882a593Smuzhiyun 			len -= cur_len;
1755*4882a593Smuzhiyun 			cur_fdt_compat += cur_len;
1756*4882a593Smuzhiyun 		}
1757*4882a593Smuzhiyun 	}
1758*4882a593Smuzhiyun 	if (!best_match_offset) {
1759*4882a593Smuzhiyun 		debug("No match found.\n");
1760*4882a593Smuzhiyun 		return -1;
1761*4882a593Smuzhiyun 	}
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun 	return best_match_offset;
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun 
1766*4882a593Smuzhiyun /**
1767*4882a593Smuzhiyun  * fit_conf_get_node - get node offset for configuration of a given unit name
1768*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1769*4882a593Smuzhiyun  * @conf_uname: configuration node unit name
1770*4882a593Smuzhiyun  *
1771*4882a593Smuzhiyun  * fit_conf_get_node() finds a configuration (within the '/configurations'
1772*4882a593Smuzhiyun  * parent node) of a provided unit name. If configuration is found its node
1773*4882a593Smuzhiyun  * offset is returned to the caller.
1774*4882a593Smuzhiyun  *
1775*4882a593Smuzhiyun  * When NULL is provided in second argument fit_conf_get_node() will search
1776*4882a593Smuzhiyun  * for a default configuration node instead. Default configuration node unit
1777*4882a593Smuzhiyun  * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
1778*4882a593Smuzhiyun  * node.
1779*4882a593Smuzhiyun  *
1780*4882a593Smuzhiyun  * returns:
1781*4882a593Smuzhiyun  *     configuration node offset when found (>=0)
1782*4882a593Smuzhiyun  *     negative number on failure (FDT_ERR_* code)
1783*4882a593Smuzhiyun  */
fit_conf_get_node(const void * fit,const char * conf_uname)1784*4882a593Smuzhiyun int fit_conf_get_node(const void *fit, const char *conf_uname)
1785*4882a593Smuzhiyun {
1786*4882a593Smuzhiyun 	int noffset, confs_noffset;
1787*4882a593Smuzhiyun 	int len;
1788*4882a593Smuzhiyun 	const char *s;
1789*4882a593Smuzhiyun 	char *conf_uname_copy = NULL;
1790*4882a593Smuzhiyun 
1791*4882a593Smuzhiyun 	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1792*4882a593Smuzhiyun 	if (confs_noffset < 0) {
1793*4882a593Smuzhiyun 		debug("Can't find configurations parent node '%s' (%s)\n",
1794*4882a593Smuzhiyun 		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1795*4882a593Smuzhiyun 		return confs_noffset;
1796*4882a593Smuzhiyun 	}
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	if (conf_uname == NULL) {
1799*4882a593Smuzhiyun 		/* get configuration unit name from the default property */
1800*4882a593Smuzhiyun 		debug("No configuration specified, trying default...\n");
1801*4882a593Smuzhiyun 		conf_uname = (char *)fdt_getprop(fit, confs_noffset,
1802*4882a593Smuzhiyun 						 FIT_DEFAULT_PROP, &len);
1803*4882a593Smuzhiyun 		if (conf_uname == NULL) {
1804*4882a593Smuzhiyun 			fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
1805*4882a593Smuzhiyun 				      len);
1806*4882a593Smuzhiyun 			return len;
1807*4882a593Smuzhiyun 		}
1808*4882a593Smuzhiyun 		debug("Found default configuration: '%s'\n", conf_uname);
1809*4882a593Smuzhiyun 	}
1810*4882a593Smuzhiyun 
1811*4882a593Smuzhiyun 	s = strchr(conf_uname, '#');
1812*4882a593Smuzhiyun 	if (s) {
1813*4882a593Smuzhiyun 		len = s - conf_uname;
1814*4882a593Smuzhiyun 		conf_uname_copy = malloc(len + 1);
1815*4882a593Smuzhiyun 		if (!conf_uname_copy) {
1816*4882a593Smuzhiyun 			debug("Can't allocate uname copy: '%s'\n",
1817*4882a593Smuzhiyun 					conf_uname);
1818*4882a593Smuzhiyun 			return -ENOMEM;
1819*4882a593Smuzhiyun 		}
1820*4882a593Smuzhiyun 		memcpy(conf_uname_copy, conf_uname, len);
1821*4882a593Smuzhiyun 		conf_uname_copy[len] = '\0';
1822*4882a593Smuzhiyun 		conf_uname = conf_uname_copy;
1823*4882a593Smuzhiyun 	}
1824*4882a593Smuzhiyun 
1825*4882a593Smuzhiyun 	noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
1826*4882a593Smuzhiyun 	if (noffset < 0) {
1827*4882a593Smuzhiyun 		debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
1828*4882a593Smuzhiyun 		      conf_uname, fdt_strerror(noffset));
1829*4882a593Smuzhiyun 	}
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 	if (conf_uname_copy)
1832*4882a593Smuzhiyun 		free(conf_uname_copy);
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun 	return noffset;
1835*4882a593Smuzhiyun }
1836*4882a593Smuzhiyun 
fit_conf_get_prop_node_count(const void * fit,int noffset,const char * prop_name)1837*4882a593Smuzhiyun int fit_conf_get_prop_node_count(const void *fit, int noffset,
1838*4882a593Smuzhiyun 		const char *prop_name)
1839*4882a593Smuzhiyun {
1840*4882a593Smuzhiyun 	return fdt_stringlist_count(fit, noffset, prop_name);
1841*4882a593Smuzhiyun }
1842*4882a593Smuzhiyun 
fit_conf_get_prop_node_index(const void * fit,int noffset,const char * prop_name,int index)1843*4882a593Smuzhiyun int fit_conf_get_prop_node_index(const void *fit, int noffset,
1844*4882a593Smuzhiyun 		const char *prop_name, int index)
1845*4882a593Smuzhiyun {
1846*4882a593Smuzhiyun 	const char *uname;
1847*4882a593Smuzhiyun 	int len;
1848*4882a593Smuzhiyun 
1849*4882a593Smuzhiyun 	/* get kernel image unit name from configuration kernel property */
1850*4882a593Smuzhiyun 	uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len);
1851*4882a593Smuzhiyun 	if (uname == NULL)
1852*4882a593Smuzhiyun 		return len;
1853*4882a593Smuzhiyun 
1854*4882a593Smuzhiyun 	return fit_image_get_node(fit, uname);
1855*4882a593Smuzhiyun }
1856*4882a593Smuzhiyun 
fit_conf_get_prop_node(const void * fit,int noffset,const char * prop_name)1857*4882a593Smuzhiyun int fit_conf_get_prop_node(const void *fit, int noffset,
1858*4882a593Smuzhiyun 		const char *prop_name)
1859*4882a593Smuzhiyun {
1860*4882a593Smuzhiyun 	return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
1861*4882a593Smuzhiyun }
1862*4882a593Smuzhiyun 
1863*4882a593Smuzhiyun /**
1864*4882a593Smuzhiyun  * fit_conf_print - prints out the FIT configuration details
1865*4882a593Smuzhiyun  * @fit: pointer to the FIT format image header
1866*4882a593Smuzhiyun  * @noffset: offset of the configuration node
1867*4882a593Smuzhiyun  * @p: pointer to prefix string
1868*4882a593Smuzhiyun  *
1869*4882a593Smuzhiyun  * fit_conf_print() lists all mandatory properties for the processed
1870*4882a593Smuzhiyun  * configuration node.
1871*4882a593Smuzhiyun  *
1872*4882a593Smuzhiyun  * returns:
1873*4882a593Smuzhiyun  *     no returned results
1874*4882a593Smuzhiyun  */
fit_conf_print(const void * fit,int noffset,const char * p)1875*4882a593Smuzhiyun void fit_conf_print(const void *fit, int noffset, const char *p)
1876*4882a593Smuzhiyun {
1877*4882a593Smuzhiyun 	char *desc;
1878*4882a593Smuzhiyun 	const char *uname;
1879*4882a593Smuzhiyun 	int ret;
1880*4882a593Smuzhiyun 	int fdt_index, loadables_index;
1881*4882a593Smuzhiyun 
1882*4882a593Smuzhiyun 	/* Mandatory properties */
1883*4882a593Smuzhiyun 	ret = fit_get_desc(fit, noffset, &desc);
1884*4882a593Smuzhiyun 	printf("%s  Description:  ", p);
1885*4882a593Smuzhiyun 	if (ret)
1886*4882a593Smuzhiyun 		printf("unavailable\n");
1887*4882a593Smuzhiyun 	else
1888*4882a593Smuzhiyun 		printf("%s\n", desc);
1889*4882a593Smuzhiyun 
1890*4882a593Smuzhiyun 	uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
1891*4882a593Smuzhiyun 	printf("%s  Kernel:       ", p);
1892*4882a593Smuzhiyun 	if (uname == NULL)
1893*4882a593Smuzhiyun 		printf("unavailable\n");
1894*4882a593Smuzhiyun 	else
1895*4882a593Smuzhiyun 		printf("%s\n", uname);
1896*4882a593Smuzhiyun 
1897*4882a593Smuzhiyun 	/* Optional properties */
1898*4882a593Smuzhiyun 	uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
1899*4882a593Smuzhiyun 	if (uname)
1900*4882a593Smuzhiyun 		printf("%s  Init Ramdisk: %s\n", p, uname);
1901*4882a593Smuzhiyun 
1902*4882a593Smuzhiyun 	uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL);
1903*4882a593Smuzhiyun 	if (uname)
1904*4882a593Smuzhiyun 		printf("%s  Firmware:     %s\n", p, uname);
1905*4882a593Smuzhiyun 
1906*4882a593Smuzhiyun 	for (fdt_index = 0;
1907*4882a593Smuzhiyun 	     uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
1908*4882a593Smuzhiyun 					fdt_index, NULL), uname;
1909*4882a593Smuzhiyun 	     fdt_index++) {
1910*4882a593Smuzhiyun 
1911*4882a593Smuzhiyun 		if (fdt_index == 0)
1912*4882a593Smuzhiyun 			printf("%s  FDT:          ", p);
1913*4882a593Smuzhiyun 		else
1914*4882a593Smuzhiyun 			printf("%s                ", p);
1915*4882a593Smuzhiyun 		printf("%s\n", uname);
1916*4882a593Smuzhiyun 	}
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun 	uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
1919*4882a593Smuzhiyun 	if (uname)
1920*4882a593Smuzhiyun 		printf("%s  FPGA:         %s\n", p, uname);
1921*4882a593Smuzhiyun 
1922*4882a593Smuzhiyun 	/* Print out all of the specified loadables */
1923*4882a593Smuzhiyun 	for (loadables_index = 0;
1924*4882a593Smuzhiyun 	     uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
1925*4882a593Smuzhiyun 					loadables_index, NULL), uname;
1926*4882a593Smuzhiyun 	     loadables_index++) {
1927*4882a593Smuzhiyun 		if (loadables_index == 0) {
1928*4882a593Smuzhiyun 			printf("%s  Loadables:    ", p);
1929*4882a593Smuzhiyun 		} else {
1930*4882a593Smuzhiyun 			printf("%s                ", p);
1931*4882a593Smuzhiyun 		}
1932*4882a593Smuzhiyun 		printf("%s\n", uname);
1933*4882a593Smuzhiyun 	}
1934*4882a593Smuzhiyun }
1935*4882a593Smuzhiyun 
fit_image_select(const void * fit,int rd_noffset,int verify)1936*4882a593Smuzhiyun static int fit_image_select(const void *fit, int rd_noffset, int verify)
1937*4882a593Smuzhiyun {
1938*4882a593Smuzhiyun #ifdef USE_HOSTCC
1939*4882a593Smuzhiyun 	fit_image_print(fit, rd_noffset, "   ");
1940*4882a593Smuzhiyun #else
1941*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(FIT_PRINT)
1942*4882a593Smuzhiyun 	fit_image_print(fit, rd_noffset, "   ");
1943*4882a593Smuzhiyun #endif
1944*4882a593Smuzhiyun #endif
1945*4882a593Smuzhiyun 	if (verify) {
1946*4882a593Smuzhiyun 		puts("   Verifying Hash Integrity ... ");
1947*4882a593Smuzhiyun 		if (!fit_image_verify(fit, rd_noffset)) {
1948*4882a593Smuzhiyun 			puts("Bad Data Hash\n");
1949*4882a593Smuzhiyun 			return -EACCES;
1950*4882a593Smuzhiyun 		}
1951*4882a593Smuzhiyun 		puts("OK\n");
1952*4882a593Smuzhiyun 	}
1953*4882a593Smuzhiyun 
1954*4882a593Smuzhiyun 	return 0;
1955*4882a593Smuzhiyun }
1956*4882a593Smuzhiyun 
fit_get_node_from_config(bootm_headers_t * images,const char * prop_name,ulong addr)1957*4882a593Smuzhiyun int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
1958*4882a593Smuzhiyun 			ulong addr)
1959*4882a593Smuzhiyun {
1960*4882a593Smuzhiyun 	int cfg_noffset;
1961*4882a593Smuzhiyun 	void *fit_hdr;
1962*4882a593Smuzhiyun 	int noffset;
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun 	debug("*  %s: using config '%s' from image at 0x%08lx\n",
1965*4882a593Smuzhiyun 	      prop_name, images->fit_uname_cfg, addr);
1966*4882a593Smuzhiyun 
1967*4882a593Smuzhiyun 	/* Check whether configuration has this property defined */
1968*4882a593Smuzhiyun 	fit_hdr = map_sysmem(addr, 0);
1969*4882a593Smuzhiyun 	cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
1970*4882a593Smuzhiyun 	if (cfg_noffset < 0) {
1971*4882a593Smuzhiyun 		debug("*  %s: no such config\n", prop_name);
1972*4882a593Smuzhiyun 		return -EINVAL;
1973*4882a593Smuzhiyun 	}
1974*4882a593Smuzhiyun 
1975*4882a593Smuzhiyun 	noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
1976*4882a593Smuzhiyun 	if (noffset < 0) {
1977*4882a593Smuzhiyun 		debug("*  %s: no '%s' in config\n", prop_name, prop_name);
1978*4882a593Smuzhiyun 		return -ENOENT;
1979*4882a593Smuzhiyun 	}
1980*4882a593Smuzhiyun 
1981*4882a593Smuzhiyun 	return noffset;
1982*4882a593Smuzhiyun }
1983*4882a593Smuzhiyun 
1984*4882a593Smuzhiyun /**
1985*4882a593Smuzhiyun  * fit_get_image_type_property() - get property name for IH_TYPE_...
1986*4882a593Smuzhiyun  *
1987*4882a593Smuzhiyun  * @return the properly name where we expect to find the image in the
1988*4882a593Smuzhiyun  * config node
1989*4882a593Smuzhiyun  */
fit_get_image_type_property(int type)1990*4882a593Smuzhiyun static const char *fit_get_image_type_property(int type)
1991*4882a593Smuzhiyun {
1992*4882a593Smuzhiyun 	/*
1993*4882a593Smuzhiyun 	 * This is sort-of available in the uimage_type[] table in image.c
1994*4882a593Smuzhiyun 	 * but we don't have access to the short name, and "fdt" is different
1995*4882a593Smuzhiyun 	 * anyway. So let's just keep it here.
1996*4882a593Smuzhiyun 	 */
1997*4882a593Smuzhiyun 	switch (type) {
1998*4882a593Smuzhiyun 	case IH_TYPE_FLATDT:
1999*4882a593Smuzhiyun 		return FIT_FDT_PROP;
2000*4882a593Smuzhiyun 	case IH_TYPE_KERNEL:
2001*4882a593Smuzhiyun 		return FIT_KERNEL_PROP;
2002*4882a593Smuzhiyun 	case IH_TYPE_RAMDISK:
2003*4882a593Smuzhiyun 		return FIT_RAMDISK_PROP;
2004*4882a593Smuzhiyun 	case IH_TYPE_FIRMWARE:
2005*4882a593Smuzhiyun 		return FIT_FIRMWARE_PROP;
2006*4882a593Smuzhiyun 	case IH_TYPE_X86_SETUP:
2007*4882a593Smuzhiyun 		return FIT_SETUP_PROP;
2008*4882a593Smuzhiyun 	case IH_TYPE_LOADABLE:
2009*4882a593Smuzhiyun 		return FIT_LOADABLE_PROP;
2010*4882a593Smuzhiyun 	case IH_TYPE_FPGA:
2011*4882a593Smuzhiyun 		return FIT_FPGA_PROP;
2012*4882a593Smuzhiyun 	case IH_TYPE_STANDALONE:
2013*4882a593Smuzhiyun 		return FIT_STANDALONE_PROP;
2014*4882a593Smuzhiyun 	}
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun 	return "unknown";
2017*4882a593Smuzhiyun }
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun #ifndef USE_HOSTCC
fit_board_verify_required_sigs(void)2020*4882a593Smuzhiyun __weak int fit_board_verify_required_sigs(void)
2021*4882a593Smuzhiyun {
2022*4882a593Smuzhiyun 	return 0;
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun #endif
2025*4882a593Smuzhiyun 
fit_image_load_index(bootm_headers_t * images,ulong addr,const char ** fit_unamep,const char ** fit_uname_configp,int arch,int image_type,int image_index,int bootstage_id,enum fit_load_op load_op,ulong * datap,ulong * lenp)2026*4882a593Smuzhiyun int fit_image_load_index(bootm_headers_t *images, ulong addr,
2027*4882a593Smuzhiyun 			 const char **fit_unamep, const char **fit_uname_configp,
2028*4882a593Smuzhiyun 			 int arch, int image_type, int image_index, int bootstage_id,
2029*4882a593Smuzhiyun 			 enum fit_load_op load_op, ulong *datap, ulong *lenp)
2030*4882a593Smuzhiyun {
2031*4882a593Smuzhiyun 	int cfg_noffset, noffset;
2032*4882a593Smuzhiyun 	const char *fit_uname;
2033*4882a593Smuzhiyun 	const char *fit_uname_config;
2034*4882a593Smuzhiyun 	const char *fit_base_uname_config;
2035*4882a593Smuzhiyun 	const void *fit;
2036*4882a593Smuzhiyun 	const void *buf;
2037*4882a593Smuzhiyun 	size_t size;
2038*4882a593Smuzhiyun 	int type_ok, os_ok;
2039*4882a593Smuzhiyun 	ulong load, data, len;
2040*4882a593Smuzhiyun 	uint8_t os;
2041*4882a593Smuzhiyun #ifndef USE_HOSTCC
2042*4882a593Smuzhiyun 	uint8_t os_arch;
2043*4882a593Smuzhiyun #endif
2044*4882a593Smuzhiyun 	const char *prop_name;
2045*4882a593Smuzhiyun 	int ret;
2046*4882a593Smuzhiyun 
2047*4882a593Smuzhiyun 	fit = map_sysmem(addr, 0);
2048*4882a593Smuzhiyun 	fit_uname = fit_unamep ? *fit_unamep : NULL;
2049*4882a593Smuzhiyun 	fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
2050*4882a593Smuzhiyun 	fit_base_uname_config = NULL;
2051*4882a593Smuzhiyun 	prop_name = fit_get_image_type_property(image_type);
2052*4882a593Smuzhiyun 	printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
2055*4882a593Smuzhiyun 	if (!fit_check_format(fit)) {
2056*4882a593Smuzhiyun 		printf("Bad FIT %s image format!\n", prop_name);
2057*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
2058*4882a593Smuzhiyun 		return -ENOEXEC;
2059*4882a593Smuzhiyun 	}
2060*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
2061*4882a593Smuzhiyun 	if (fit_uname) {
2062*4882a593Smuzhiyun 		/* get FIT component image node offset */
2063*4882a593Smuzhiyun 		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
2064*4882a593Smuzhiyun 		noffset = fit_image_get_node(fit, fit_uname);
2065*4882a593Smuzhiyun 	} else {
2066*4882a593Smuzhiyun 		/*
2067*4882a593Smuzhiyun 		 * no image node unit name, try to get config
2068*4882a593Smuzhiyun 		 * node first. If config unit node name is NULL
2069*4882a593Smuzhiyun 		 * fit_conf_get_node() will try to find default config node
2070*4882a593Smuzhiyun 		 */
2071*4882a593Smuzhiyun 		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
2072*4882a593Smuzhiyun 		if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) {
2073*4882a593Smuzhiyun 			cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
2074*4882a593Smuzhiyun 		} else {
2075*4882a593Smuzhiyun 			cfg_noffset = fit_conf_get_node(fit,
2076*4882a593Smuzhiyun 							fit_uname_config);
2077*4882a593Smuzhiyun 		}
2078*4882a593Smuzhiyun 		if (cfg_noffset < 0) {
2079*4882a593Smuzhiyun 			puts("Could not find configuration node\n");
2080*4882a593Smuzhiyun 			bootstage_error(bootstage_id +
2081*4882a593Smuzhiyun 					BOOTSTAGE_SUB_NO_UNIT_NAME);
2082*4882a593Smuzhiyun 			return -ENOENT;
2083*4882a593Smuzhiyun 		}
2084*4882a593Smuzhiyun 		fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
2085*4882a593Smuzhiyun 		printf("   Using '%s' configuration\n", fit_base_uname_config);
2086*4882a593Smuzhiyun 		if (image_type == IH_TYPE_KERNEL) {
2087*4882a593Smuzhiyun #ifndef USE_HOSTCC
2088*4882a593Smuzhiyun 			/* If board required sigs, check self */
2089*4882a593Smuzhiyun 			if (fit_board_verify_required_sigs() &&
2090*4882a593Smuzhiyun 			    !IS_ENABLED(CONFIG_FIT_SIGNATURE)) {
2091*4882a593Smuzhiyun 				printf("Verified-boot requires CONFIG_FIT_SIGNATURE enabled\n");
2092*4882a593Smuzhiyun 				hang();
2093*4882a593Smuzhiyun 			}
2094*4882a593Smuzhiyun #endif
2095*4882a593Smuzhiyun 			/* Remember (and possibly verify) this config */
2096*4882a593Smuzhiyun 			images->fit_uname_cfg = fit_base_uname_config;
2097*4882a593Smuzhiyun 			if (IMAGE_ENABLE_VERIFY) {
2098*4882a593Smuzhiyun 				puts("   Verifying Hash Integrity ... ");
2099*4882a593Smuzhiyun 				if (fit_config_verify(fit, cfg_noffset)) {
2100*4882a593Smuzhiyun 					puts("Bad Data Hash\n");
2101*4882a593Smuzhiyun 					bootstage_error(bootstage_id +
2102*4882a593Smuzhiyun 						BOOTSTAGE_SUB_HASH);
2103*4882a593Smuzhiyun 					return -EACCES;
2104*4882a593Smuzhiyun 				}
2105*4882a593Smuzhiyun 				puts("OK\n");
2106*4882a593Smuzhiyun 
2107*4882a593Smuzhiyun #ifdef CONFIG_FIT_ROLLBACK_PROTECT
2108*4882a593Smuzhiyun 				uint32_t this_index, min_index;
2109*4882a593Smuzhiyun 
2110*4882a593Smuzhiyun 				puts("   Verifying Rollback-index ... ");
2111*4882a593Smuzhiyun 				if (fit_rollback_index_verify(fit,
2112*4882a593Smuzhiyun 						FIT_ROLLBACK_INDEX,
2113*4882a593Smuzhiyun 						&this_index, &min_index)) {
2114*4882a593Smuzhiyun 					puts("Failed to get index\n");
2115*4882a593Smuzhiyun 					return ret;
2116*4882a593Smuzhiyun 				} else if (this_index < min_index) {
2117*4882a593Smuzhiyun 					printf("Reject index %d < %d(min)\n",
2118*4882a593Smuzhiyun 					       this_index, min_index);
2119*4882a593Smuzhiyun 					return -EINVAL;
2120*4882a593Smuzhiyun 				}
2121*4882a593Smuzhiyun 
2122*4882a593Smuzhiyun 				printf("%d >= %d(min), OK\n", this_index, min_index);
2123*4882a593Smuzhiyun #endif
2124*4882a593Smuzhiyun 			}
2125*4882a593Smuzhiyun 			bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
2126*4882a593Smuzhiyun 		}
2127*4882a593Smuzhiyun 
2128*4882a593Smuzhiyun 		noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
2129*4882a593Smuzhiyun 						       prop_name, image_index);
2130*4882a593Smuzhiyun 		fit_uname = fit_get_name(fit, noffset, NULL);
2131*4882a593Smuzhiyun 	}
2132*4882a593Smuzhiyun 	if (noffset < 0) {
2133*4882a593Smuzhiyun 		puts("Could not find subimage node\n");
2134*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
2135*4882a593Smuzhiyun 		return -ENOENT;
2136*4882a593Smuzhiyun 	}
2137*4882a593Smuzhiyun 
2138*4882a593Smuzhiyun 	printf("   Trying '%s' %s subimage\n", fit_uname, prop_name);
2139*4882a593Smuzhiyun 
2140*4882a593Smuzhiyun 	ret = fit_image_select(fit, noffset, images->verify);
2141*4882a593Smuzhiyun 	if (ret) {
2142*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
2143*4882a593Smuzhiyun 		return ret;
2144*4882a593Smuzhiyun 	}
2145*4882a593Smuzhiyun 
2146*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
2147*4882a593Smuzhiyun #if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX)
2148*4882a593Smuzhiyun 	if (!fit_image_check_target_arch(fit, noffset)) {
2149*4882a593Smuzhiyun 		puts("Unsupported Architecture\n");
2150*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
2151*4882a593Smuzhiyun 		return -ENOEXEC;
2152*4882a593Smuzhiyun 	}
2153*4882a593Smuzhiyun #endif
2154*4882a593Smuzhiyun 
2155*4882a593Smuzhiyun #ifndef USE_HOSTCC
2156*4882a593Smuzhiyun 	fit_image_get_arch(fit, noffset, &os_arch);
2157*4882a593Smuzhiyun 	images->os.arch = os_arch;
2158*4882a593Smuzhiyun #endif
2159*4882a593Smuzhiyun 
2160*4882a593Smuzhiyun 	if (image_type == IH_TYPE_FLATDT &&
2161*4882a593Smuzhiyun 	    !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
2162*4882a593Smuzhiyun 		puts("FDT image is compressed");
2163*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
2164*4882a593Smuzhiyun 	}
2165*4882a593Smuzhiyun 
2166*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
2167*4882a593Smuzhiyun 	type_ok = fit_image_check_type(fit, noffset, image_type) ||
2168*4882a593Smuzhiyun 		  fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
2169*4882a593Smuzhiyun 		  (image_type == IH_TYPE_KERNEL &&
2170*4882a593Smuzhiyun 		   fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD));
2171*4882a593Smuzhiyun 
2172*4882a593Smuzhiyun 	os_ok = image_type == IH_TYPE_FLATDT ||
2173*4882a593Smuzhiyun 		image_type == IH_TYPE_FPGA ||
2174*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
2175*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_ARM_TRUSTED_FIRMWARE) ||
2176*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_OP_TEE) ||
2177*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
2178*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_QNX) ||
2179*4882a593Smuzhiyun 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
2180*4882a593Smuzhiyun 
2181*4882a593Smuzhiyun 	/*
2182*4882a593Smuzhiyun 	 * If either of the checks fail, we should report an error, but
2183*4882a593Smuzhiyun 	 * if the image type is coming from the "loadables" field, we
2184*4882a593Smuzhiyun 	 * don't care what it is
2185*4882a593Smuzhiyun 	 */
2186*4882a593Smuzhiyun 	if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) {
2187*4882a593Smuzhiyun 		fit_image_get_os(fit, noffset, &os);
2188*4882a593Smuzhiyun 		printf("No %s %s %s Image\n",
2189*4882a593Smuzhiyun 		       genimg_get_os_name(os),
2190*4882a593Smuzhiyun 		       genimg_get_arch_name(arch),
2191*4882a593Smuzhiyun 		       genimg_get_type_name(image_type));
2192*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
2193*4882a593Smuzhiyun 		return -EIO;
2194*4882a593Smuzhiyun 	}
2195*4882a593Smuzhiyun 
2196*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
2197*4882a593Smuzhiyun 
2198*4882a593Smuzhiyun 	/* get image data address and length */
2199*4882a593Smuzhiyun 	if (fit_image_get_data(fit, noffset, &buf, &size)) {
2200*4882a593Smuzhiyun 		printf("Could not find %s subimage data!\n", prop_name);
2201*4882a593Smuzhiyun 		bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
2202*4882a593Smuzhiyun 		return -ENOENT;
2203*4882a593Smuzhiyun 	}
2204*4882a593Smuzhiyun 
2205*4882a593Smuzhiyun #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
2206*4882a593Smuzhiyun 	ret = fit_image_get_load(fit, noffset, &load);
2207*4882a593Smuzhiyun 	if (ret < 0)
2208*4882a593Smuzhiyun 		return ret;
2209*4882a593Smuzhiyun 
2210*4882a593Smuzhiyun 	/* perform any post-processing on the image data */
2211*4882a593Smuzhiyun 	board_fit_image_post_process((void *)fit, noffset,
2212*4882a593Smuzhiyun 				     &load, (ulong **)&buf, &size, NULL);
2213*4882a593Smuzhiyun #endif
2214*4882a593Smuzhiyun 
2215*4882a593Smuzhiyun 	len = (ulong)size;
2216*4882a593Smuzhiyun 
2217*4882a593Smuzhiyun 	/* verify that image data is a proper FDT blob */
2218*4882a593Smuzhiyun 	if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
2219*4882a593Smuzhiyun 		puts("Subimage data is not a FDT");
2220*4882a593Smuzhiyun 		return -ENOEXEC;
2221*4882a593Smuzhiyun 	}
2222*4882a593Smuzhiyun 
2223*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
2224*4882a593Smuzhiyun 
2225*4882a593Smuzhiyun 	/*
2226*4882a593Smuzhiyun 	 * Work-around for eldk-4.2 which gives this warning if we try to
2227*4882a593Smuzhiyun 	 * cast in the unmap_sysmem() call:
2228*4882a593Smuzhiyun 	 * warning: initialization discards qualifiers from pointer target type
2229*4882a593Smuzhiyun 	 */
2230*4882a593Smuzhiyun 	{
2231*4882a593Smuzhiyun 		void *vbuf = (void *)buf;
2232*4882a593Smuzhiyun 
2233*4882a593Smuzhiyun 		data = map_to_sysmem(vbuf);
2234*4882a593Smuzhiyun 	}
2235*4882a593Smuzhiyun 
2236*4882a593Smuzhiyun 	if (load_op == FIT_LOAD_IGNORED) {
2237*4882a593Smuzhiyun 		/* Don't load */
2238*4882a593Smuzhiyun 	} else if (fit_image_get_load(fit, noffset, &load)) {
2239*4882a593Smuzhiyun 		if (load_op == FIT_LOAD_REQUIRED) {
2240*4882a593Smuzhiyun 			printf("Can't get %s subimage load address!\n",
2241*4882a593Smuzhiyun 			       prop_name);
2242*4882a593Smuzhiyun 			bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
2243*4882a593Smuzhiyun 			return -EBADF;
2244*4882a593Smuzhiyun 		}
2245*4882a593Smuzhiyun 	} else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
2246*4882a593Smuzhiyun 		ulong image_start, image_end;
2247*4882a593Smuzhiyun 		ulong load_end;
2248*4882a593Smuzhiyun 		void *dst;
2249*4882a593Smuzhiyun 
2250*4882a593Smuzhiyun 		/*
2251*4882a593Smuzhiyun 		 * move image data to the load address,
2252*4882a593Smuzhiyun 		 * make sure we don't overwrite initial image
2253*4882a593Smuzhiyun 		 */
2254*4882a593Smuzhiyun 		image_start = addr;
2255*4882a593Smuzhiyun 		image_end = addr + fit_get_size(fit);
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun 		load_end = load + len;
2258*4882a593Smuzhiyun 		if (image_type != IH_TYPE_KERNEL &&
2259*4882a593Smuzhiyun 		    load < image_end && load_end > image_start) {
2260*4882a593Smuzhiyun 			printf("Error: %s overwritten\n", prop_name);
2261*4882a593Smuzhiyun 			return -EXDEV;
2262*4882a593Smuzhiyun 		}
2263*4882a593Smuzhiyun 
2264*4882a593Smuzhiyun 		printf("   Loading %s from 0x%08lx to 0x%08lx\n",
2265*4882a593Smuzhiyun 		       prop_name, data, load);
2266*4882a593Smuzhiyun 
2267*4882a593Smuzhiyun 		dst = map_sysmem(load, len);
2268*4882a593Smuzhiyun 		memmove(dst, buf, len);
2269*4882a593Smuzhiyun 		data = load;
2270*4882a593Smuzhiyun 	}
2271*4882a593Smuzhiyun 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
2272*4882a593Smuzhiyun 
2273*4882a593Smuzhiyun 	*datap = data;
2274*4882a593Smuzhiyun 	*lenp = len;
2275*4882a593Smuzhiyun 	if (fit_unamep)
2276*4882a593Smuzhiyun 		*fit_unamep = (char *)fit_uname;
2277*4882a593Smuzhiyun 	if (fit_uname_configp)
2278*4882a593Smuzhiyun 		*fit_uname_configp = (char *)(fit_uname_config ? :
2279*4882a593Smuzhiyun 					      fit_base_uname_config);
2280*4882a593Smuzhiyun 
2281*4882a593Smuzhiyun 	return noffset;
2282*4882a593Smuzhiyun }
2283*4882a593Smuzhiyun 
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)2284*4882a593Smuzhiyun int fit_image_load(bootm_headers_t *images, ulong addr,
2285*4882a593Smuzhiyun 		   const char **fit_unamep, const char **fit_uname_configp,
2286*4882a593Smuzhiyun 		   int arch, int image_type, int bootstage_id,
2287*4882a593Smuzhiyun 		   enum fit_load_op load_op, ulong *datap, ulong *lenp)
2288*4882a593Smuzhiyun {
2289*4882a593Smuzhiyun 	return fit_image_load_index(images, addr,fit_unamep, fit_uname_configp,
2290*4882a593Smuzhiyun 				    arch, image_type, 0, bootstage_id,
2291*4882a593Smuzhiyun 				    load_op, datap, lenp);
2292*4882a593Smuzhiyun }
2293*4882a593Smuzhiyun 
boot_get_setup_fit(bootm_headers_t * images,uint8_t arch,ulong * setup_start,ulong * setup_len)2294*4882a593Smuzhiyun int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
2295*4882a593Smuzhiyun 			ulong *setup_start, ulong *setup_len)
2296*4882a593Smuzhiyun {
2297*4882a593Smuzhiyun 	int noffset;
2298*4882a593Smuzhiyun 	ulong addr;
2299*4882a593Smuzhiyun 	ulong len;
2300*4882a593Smuzhiyun 	int ret;
2301*4882a593Smuzhiyun 
2302*4882a593Smuzhiyun 	addr = map_to_sysmem(images->fit_hdr_os);
2303*4882a593Smuzhiyun 	noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr);
2304*4882a593Smuzhiyun 	if (noffset < 0)
2305*4882a593Smuzhiyun 		return noffset;
2306*4882a593Smuzhiyun 
2307*4882a593Smuzhiyun 	ret = fit_image_load(images, addr, NULL, NULL, arch,
2308*4882a593Smuzhiyun 			     IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START,
2309*4882a593Smuzhiyun 			     FIT_LOAD_REQUIRED, setup_start, &len);
2310*4882a593Smuzhiyun 
2311*4882a593Smuzhiyun 	return ret;
2312*4882a593Smuzhiyun }
2313*4882a593Smuzhiyun 
2314*4882a593Smuzhiyun #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)2315*4882a593Smuzhiyun int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
2316*4882a593Smuzhiyun 		   const char **fit_unamep, const char **fit_uname_configp,
2317*4882a593Smuzhiyun 		   int arch, ulong *datap, ulong *lenp)
2318*4882a593Smuzhiyun {
2319*4882a593Smuzhiyun 	int fdt_noffset, cfg_noffset, count;
2320*4882a593Smuzhiyun 	const void *fit;
2321*4882a593Smuzhiyun 	const char *fit_uname = NULL;
2322*4882a593Smuzhiyun 	const char *fit_uname_config = NULL;
2323*4882a593Smuzhiyun 	char *fit_uname_config_copy = NULL;
2324*4882a593Smuzhiyun 	char *next_config = NULL;
2325*4882a593Smuzhiyun 	ulong load, len;
2326*4882a593Smuzhiyun #ifdef CONFIG_OF_LIBFDT_OVERLAY
2327*4882a593Smuzhiyun 	ulong image_start, image_end;
2328*4882a593Smuzhiyun 	ulong ovload, ovlen;
2329*4882a593Smuzhiyun 	const char *uconfig;
2330*4882a593Smuzhiyun 	const char *uname;
2331*4882a593Smuzhiyun 	void *base, *ov;
2332*4882a593Smuzhiyun 	int i, err, noffset, ov_noffset;
2333*4882a593Smuzhiyun #endif
2334*4882a593Smuzhiyun 
2335*4882a593Smuzhiyun 	fit_uname = fit_unamep ? *fit_unamep : NULL;
2336*4882a593Smuzhiyun 
2337*4882a593Smuzhiyun 	if (fit_uname_configp && *fit_uname_configp) {
2338*4882a593Smuzhiyun 		fit_uname_config_copy = strdup(*fit_uname_configp);
2339*4882a593Smuzhiyun 		if (!fit_uname_config_copy)
2340*4882a593Smuzhiyun 			return -ENOMEM;
2341*4882a593Smuzhiyun 
2342*4882a593Smuzhiyun 		next_config = strchr(fit_uname_config_copy, '#');
2343*4882a593Smuzhiyun 		if (next_config)
2344*4882a593Smuzhiyun 			*next_config++ = '\0';
2345*4882a593Smuzhiyun 		if (next_config - 1 > fit_uname_config_copy)
2346*4882a593Smuzhiyun 			fit_uname_config = fit_uname_config_copy;
2347*4882a593Smuzhiyun 	}
2348*4882a593Smuzhiyun 
2349*4882a593Smuzhiyun 	fdt_noffset = fit_image_load(images,
2350*4882a593Smuzhiyun 		addr, &fit_uname, &fit_uname_config,
2351*4882a593Smuzhiyun 		arch, IH_TYPE_FLATDT,
2352*4882a593Smuzhiyun 		BOOTSTAGE_ID_FIT_FDT_START,
2353*4882a593Smuzhiyun 		FIT_LOAD_OPTIONAL, &load, &len);
2354*4882a593Smuzhiyun 
2355*4882a593Smuzhiyun 	if (fdt_noffset < 0)
2356*4882a593Smuzhiyun 		goto out;
2357*4882a593Smuzhiyun 
2358*4882a593Smuzhiyun 	debug("fit_uname=%s, fit_uname_config=%s\n",
2359*4882a593Smuzhiyun 			fit_uname ? fit_uname : "<NULL>",
2360*4882a593Smuzhiyun 			fit_uname_config ? fit_uname_config : "<NULL>");
2361*4882a593Smuzhiyun 
2362*4882a593Smuzhiyun 	fit = map_sysmem(addr, 0);
2363*4882a593Smuzhiyun 
2364*4882a593Smuzhiyun 	cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
2365*4882a593Smuzhiyun 
2366*4882a593Smuzhiyun 	/* single blob, or error just return as well */
2367*4882a593Smuzhiyun 	count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP);
2368*4882a593Smuzhiyun 	if (count <= 1 && !next_config)
2369*4882a593Smuzhiyun 		goto out;
2370*4882a593Smuzhiyun 
2371*4882a593Smuzhiyun 	/* we need to apply overlays */
2372*4882a593Smuzhiyun 
2373*4882a593Smuzhiyun #ifdef CONFIG_OF_LIBFDT_OVERLAY
2374*4882a593Smuzhiyun 	image_start = addr;
2375*4882a593Smuzhiyun 	image_end = addr + fit_get_size(fit);
2376*4882a593Smuzhiyun 	/* verify that relocation took place by load address not being in fit */
2377*4882a593Smuzhiyun 	if (load >= image_start && load < image_end) {
2378*4882a593Smuzhiyun 		/* check is simplified; fit load checks for overlaps */
2379*4882a593Smuzhiyun 		printf("Overlayed FDT requires relocation\n");
2380*4882a593Smuzhiyun 		fdt_noffset = -EBADF;
2381*4882a593Smuzhiyun 		goto out;
2382*4882a593Smuzhiyun 	}
2383*4882a593Smuzhiyun 
2384*4882a593Smuzhiyun 	base = map_sysmem(load, len);
2385*4882a593Smuzhiyun 
2386*4882a593Smuzhiyun 	/* apply extra configs in FIT first, followed by args */
2387*4882a593Smuzhiyun 	for (i = 1; ; i++) {
2388*4882a593Smuzhiyun 		if (i < count) {
2389*4882a593Smuzhiyun 			noffset = fit_conf_get_prop_node_index(fit, cfg_noffset,
2390*4882a593Smuzhiyun 							       FIT_FDT_PROP, i);
2391*4882a593Smuzhiyun 			uname = fit_get_name(fit, noffset, NULL);
2392*4882a593Smuzhiyun 			uconfig = NULL;
2393*4882a593Smuzhiyun 		} else {
2394*4882a593Smuzhiyun 			if (!next_config)
2395*4882a593Smuzhiyun 				break;
2396*4882a593Smuzhiyun 			uconfig = next_config;
2397*4882a593Smuzhiyun 			next_config = strchr(next_config, '#');
2398*4882a593Smuzhiyun 			if (next_config)
2399*4882a593Smuzhiyun 				*next_config++ = '\0';
2400*4882a593Smuzhiyun 			uname = NULL;
2401*4882a593Smuzhiyun 		}
2402*4882a593Smuzhiyun 
2403*4882a593Smuzhiyun 		debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig);
2404*4882a593Smuzhiyun 
2405*4882a593Smuzhiyun 		ov_noffset = fit_image_load(images,
2406*4882a593Smuzhiyun 			addr, &uname, &uconfig,
2407*4882a593Smuzhiyun 			arch, IH_TYPE_FLATDT,
2408*4882a593Smuzhiyun 			BOOTSTAGE_ID_FIT_FDT_START,
2409*4882a593Smuzhiyun 			FIT_LOAD_REQUIRED, &ovload, &ovlen);
2410*4882a593Smuzhiyun 		if (ov_noffset < 0) {
2411*4882a593Smuzhiyun 			printf("load of %s failed\n", uname);
2412*4882a593Smuzhiyun 			continue;
2413*4882a593Smuzhiyun 		}
2414*4882a593Smuzhiyun 		debug("%s loaded at 0x%08lx len=0x%08lx\n",
2415*4882a593Smuzhiyun 				uname, ovload, ovlen);
2416*4882a593Smuzhiyun 		ov = map_sysmem(ovload, ovlen);
2417*4882a593Smuzhiyun 
2418*4882a593Smuzhiyun 		base = map_sysmem(load, len + ovlen);
2419*4882a593Smuzhiyun 		err = fdt_open_into(base, base, len + ovlen);
2420*4882a593Smuzhiyun 		if (err < 0) {
2421*4882a593Smuzhiyun 			printf("failed on fdt_open_into\n");
2422*4882a593Smuzhiyun 			fdt_noffset = err;
2423*4882a593Smuzhiyun 			goto out;
2424*4882a593Smuzhiyun 		}
2425*4882a593Smuzhiyun 		/* the verbose method prints out messages on error */
2426*4882a593Smuzhiyun 		err = fdt_overlay_apply_verbose(base, ov);
2427*4882a593Smuzhiyun 		if (err < 0) {
2428*4882a593Smuzhiyun 			fdt_noffset = err;
2429*4882a593Smuzhiyun 			goto out;
2430*4882a593Smuzhiyun 		}
2431*4882a593Smuzhiyun 		fdt_pack(base);
2432*4882a593Smuzhiyun 		len = fdt_totalsize(base);
2433*4882a593Smuzhiyun 	}
2434*4882a593Smuzhiyun #else
2435*4882a593Smuzhiyun 	printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n");
2436*4882a593Smuzhiyun 	fdt_noffset = -EBADF;
2437*4882a593Smuzhiyun #endif
2438*4882a593Smuzhiyun 
2439*4882a593Smuzhiyun out:
2440*4882a593Smuzhiyun 	if (datap)
2441*4882a593Smuzhiyun 		*datap = load;
2442*4882a593Smuzhiyun 	if (lenp)
2443*4882a593Smuzhiyun 		*lenp = len;
2444*4882a593Smuzhiyun 	if (fit_unamep)
2445*4882a593Smuzhiyun 		*fit_unamep = fit_uname;
2446*4882a593Smuzhiyun 	if (fit_uname_configp)
2447*4882a593Smuzhiyun 		*fit_uname_configp = fit_uname_config;
2448*4882a593Smuzhiyun 
2449*4882a593Smuzhiyun 	if (fit_uname_config_copy)
2450*4882a593Smuzhiyun 		free(fit_uname_config_copy);
2451*4882a593Smuzhiyun 	return fdt_noffset;
2452*4882a593Smuzhiyun }
2453*4882a593Smuzhiyun #endif
2454