X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=common%2Fimage-fit.c;h=a272ea2e83456d9a50018ffb1752b0e2016ddcf7;hp=7bf82d33cf7bce134b13613a445a5311e2988031;hb=0ce4af99c07acebf4fce9a91f1099d2460629293;hpb=c6ac13bdea0368cd8ce0478173467c032c9bacfb diff --git a/common/image-fit.c b/common/image-fit.c index 7bf82d33cf..a272ea2e83 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -6,23 +6,7 @@ * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #ifdef USE_HOSTCC @@ -37,9 +21,10 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include -#include #include #include +#include +#include /*****************************************************************************/ /* New uImage format routines */ @@ -74,7 +59,7 @@ static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr, * @conf_name double pointer to a char, will hold pointer to a configuration * unit name * - * fit_parse_conf() expects configuration spec in the for of []#, + * fit_parse_conf() expects configuration spec in the form of []#, * where is a FIT image address that contains configuration * with a unit name. * @@ -100,7 +85,7 @@ int fit_parse_conf(const char *spec, ulong addr_curr, * subimage * @image_name: double pointer to a char, will hold pointer to a subimage name * - * fit_parse_subimage() expects subimage spec in the for of + * fit_parse_subimage() expects subimage spec in the form of * []:, where is a FIT image address that contains * subimage with a unit name. * @@ -234,42 +219,45 @@ void fit_print_contents(const void *fit) * @fit: pointer to the FIT format image header * @noffset: offset of the hash node * @p: pointer to prefix string + * @type: Type of information to print ("hash" or "sign") * * fit_image_print_data() lists properies for the processed hash node * + * This function avoid using puts() since it prints a newline on the host + * but does not in U-Boot. + * * returns: * no returned results */ -static void fit_image_print_data(const void *fit, int noffset, const char *p) +static void fit_image_print_data(const void *fit, int noffset, const char *p, + const char *type) { - char *algo; + const char *keyname; uint8_t *value; int value_len; - int i, ret; - - /* - * Check subnode name, must be equal to "hash". - * Multiple hash nodes require unique unit node - * names, e.g. hash@1, hash@2, etc. - */ - if (strncmp(fit_get_name(fit, noffset, NULL), - FIT_HASH_NODENAME, - strlen(FIT_HASH_NODENAME)) != 0) - return; + char *algo; + int required; + int ret, i; - debug("%s Hash node: '%s'\n", p, + debug("%s %s node: '%s'\n", p, type, fit_get_name(fit, noffset, NULL)); - - printf("%s Hash algo: ", p); + printf("%s %s algo: ", p, type); if (fit_image_hash_get_algo(fit, noffset, &algo)) { printf("invalid/unsupported\n"); return; } - printf("%s\n", algo); + printf("%s", algo); + keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); + required = fdt_getprop(fit, noffset, "required", NULL) != NULL; + if (keyname) + printf(":%s", keyname); + if (required) + printf(" (required)"); + printf("\n"); ret = fit_image_hash_get_value(fit, noffset, &value, &value_len); - printf("%s Hash value: ", p); + printf("%s %s value: ", p, type); if (ret) { printf("unavailable\n"); } else { @@ -278,7 +266,18 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p) printf("\n"); } - debug("%s Hash len: %d\n", p, value_len); + debug("%s %s len: %d\n", p, type, value_len); + + /* Signatures have a time stamp */ + if (IMAGE_ENABLE_TIMESTAMP && keyname) { + time_t timestamp; + + printf("%s Timestamp: ", p); + if (fit_get_timestamp(fit, noffset, ×tamp)) + printf("unavailable\n"); + else + genimg_print_time(timestamp); + } } /** @@ -303,8 +302,12 @@ static void fit_image_print_verification_data(const void *fit, int noffset, * names, e.g. hash@1, hash@2, signature@1, signature@2, etc. */ name = fit_get_name(fit, noffset, NULL); - if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) - fit_image_print_data(fit, noffset, p); + if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) { + fit_image_print_data(fit, noffset, p, "Hash"); + } else if (!strncmp(name, FIT_SIG_NODENAME, + strlen(FIT_SIG_NODENAME))) { + fit_image_print_data(fit, noffset, p, "Sign"); + } } /** @@ -341,6 +344,17 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) else printf("%s\n", desc); + if (IMAGE_ENABLE_TIMESTAMP) { + time_t timestamp; + + ret = fit_get_timestamp(fit, 0, ×tamp); + printf("%s Created: ", p); + if (ret) + printf("unavailable\n"); + else + genimg_print_time(timestamp); + } + fit_image_get_type(fit, image_noffset, &type); printf("%s Type: %s\n", p, genimg_get_type_name(type)); @@ -819,7 +833,7 @@ static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) * * returns: * 0, on success - * -1, on property read failure + * -ENOSPC if no space in device tree, -1 for other error */ int fit_set_timestamp(void *fit, int noffset, time_t timestamp) { @@ -833,7 +847,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp) printf("Can't set '%s' property for '%s' node (%s)\n", FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), fdt_strerror(ret)); - return -1; + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1; } return 0; @@ -869,6 +883,10 @@ int calculate_hash(const void *data, int data_len, const char *algo, sha1_csum_wd((unsigned char *)data, data_len, (unsigned char *)value, CHUNKSZ_SHA1); *value_len = 20; + } else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) { + sha256_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA256); + *value_len = SHA256_SUM_LEN; } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) { md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); *value_len = 16; @@ -944,13 +962,23 @@ int fit_image_verify(const void *fit, int image_noffset) { const void *data; size_t size; - int noffset; + int noffset = 0; char *err_msg = ""; + int verify_all = 1; + int ret; /* Get image data and data length */ if (fit_image_get_data(fit, image_noffset, &data, &size)) { err_msg = "Can't get image data/size"; - return 0; + goto error; + } + + /* Verify all required signatures */ + if (IMAGE_ENABLE_VERIFY && + fit_image_verify_required_sigs(fit, image_noffset, data, size, + gd_fdt_blob(), &verify_all)) { + err_msg = "Unable to verify required signature"; + goto error; } /* Process all hash subnodes of the component image node */ @@ -970,6 +998,15 @@ int fit_image_verify(const void *fit, int image_noffset) &err_msg)) goto error; puts("+ "); + } else if (IMAGE_ENABLE_VERIFY && verify_all && + !strncmp(name, FIT_SIG_NODENAME, + strlen(FIT_SIG_NODENAME))) { + ret = fit_image_check_sig(fit, noffset, data, + size, -1, &err_msg); + if (ret) + puts("- "); + else + puts("+ "); } } @@ -1299,7 +1336,7 @@ int fit_conf_find_compat(const void *fit, const void *fdt) * * When NULL is provided in second argument fit_conf_get_node() will search * for a default configuration node instead. Default configuration node unit - * name is retrived from FIT_DEFAULT_PROP property of the '/configurations' + * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations' * node. * * returns: @@ -1397,7 +1434,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) printf("%s FDT: %s\n", p, uname); } -int fit_image_select(const void *fit, int rd_noffset, int verify) +static int fit_image_select(const void *fit, int rd_noffset, int verify) { fit_image_print(fit, rd_noffset, " "); @@ -1440,22 +1477,53 @@ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, return noffset; } -int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, - const char **fit_unamep, const char *fit_uname_config, +/** + * fit_get_image_type_property() - get property name for IH_TYPE_... + * + * @return the properly name where we expect to find the image in the + * config node + */ +static const char *fit_get_image_type_property(int type) +{ + /* + * This is sort-of available in the uimage_type[] table in image.c + * but we don't have access to the sohrt name, and "fdt" is different + * anyway. So let's just keep it here. + */ + switch (type) { + case IH_TYPE_FLATDT: + return FIT_FDT_PROP; + case IH_TYPE_KERNEL: + return FIT_KERNEL_PROP; + case IH_TYPE_RAMDISK: + return FIT_RAMDISK_PROP; + case IH_TYPE_X86_SETUP: + return FIT_SETUP_PROP; + } + + return "unknown"; +} + +int 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) { int cfg_noffset, noffset; const char *fit_uname; + const char *fit_uname_config; const void *fit; const void *buf; size_t size; int type_ok, os_ok; ulong load, data, len; + const char *prop_name; int ret; fit = map_sysmem(addr, 0); fit_uname = fit_unamep ? *fit_unamep : NULL; + fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; + prop_name = fit_get_image_type_property(image_type); printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); @@ -1466,7 +1534,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); if (fit_uname) { - /* get ramdisk component image node offset */ + /* get FIT component image node offset */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); noffset = fit_image_get_node(fit, fit_uname); } else { @@ -1495,7 +1563,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, images->fit_uname_cfg = fit_uname_config; if (IMAGE_ENABLE_VERIFY && images->verify) { puts(" Verifying Hash Integrity ... "); - if (!fit_config_verify(fit, cfg_noffset)) { + if (fit_config_verify(fit, cfg_noffset)) { puts("Bad Data Hash\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); @@ -1525,12 +1593,13 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); +#if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX) if (!fit_image_check_target_arch(fit, noffset)) { puts("Unsupported Architecture\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); return -ENOEXEC; } - +#endif if (image_type == IH_TYPE_FLATDT && !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { puts("FDT image is compressed"); @@ -1557,12 +1626,12 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, if (fit_image_get_data(fit, noffset, &buf, &size)) { printf("Could not find %s subimage data!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); - return -ENOMEDIUM; + return -ENOENT; } len = (ulong)size; /* verify that image data is a proper FDT blob */ - if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) { + if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) { puts("Subimage data is not a FDT"); return -ENOEXEC; } @@ -1571,7 +1640,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, /* * Work-around for eldk-4.2 which gives this warning if we try to - * case in the unmap_sysmem() call: + * cast in the unmap_sysmem() call: * warning: initialization discards qualifiers from pointer target type */ { @@ -1589,7 +1658,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); return -EBADF; } - } else { + } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { ulong image_start, image_end; ulong load_end; void *dst; @@ -1621,6 +1690,28 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr, *lenp = len; if (fit_unamep) *fit_unamep = (char *)fit_uname; + if (fit_uname_configp) + *fit_uname_configp = (char *)fit_uname_config; return noffset; } + +int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, + ulong *setup_start, ulong *setup_len) +{ + int noffset; + ulong addr; + ulong len; + int ret; + + addr = map_to_sysmem(images->fit_hdr_os); + noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr); + if (noffset < 0) + return noffset; + + ret = fit_image_load(images, addr, NULL, NULL, arch, + IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START, + FIT_LOAD_REQUIRED, setup_start, &len); + + return ret; +}