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