X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fimage-fit.c;h=030a3e579f5214fff809b15f398f1314e6153d8c;hb=43bf439472f0f47988ca642b293d2b7efe636f17;hp=e75cb649a49879875e0b21d9826bd265bbf68b5d;hpb=7c3dc776b91a683b2f7dd40ed91361124a3a91c0;p=u-boot diff --git a/common/image-fit.c b/common/image-fit.c index e75cb649a4..030a3e579f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -19,6 +19,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ @@ -329,7 +330,7 @@ static void fit_image_print_verification_data(const void *fit, int noffset, /* * Check subnode name, must be equal to "hash" or "signature". * Multiple hash/signature nodes require unique unit node - * names, e.g. hash@1, hash@2, signature@1, signature@2, etc. + * 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))) { @@ -418,7 +419,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) || + (type == IH_TYPE_FIRMWARE)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } @@ -434,6 +436,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } + /* optional load address for FDT */ + if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load)) + printf("%s Load Address: 0x%08lx\n", p, load); + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_entry(fit, image_noffset, &entry); @@ -801,6 +807,31 @@ int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset) return 0; } +/** + * Get 'data-position' property from a given image node. + * + * @fit: pointer to the FIT image header + * @noffset: component image node offset + * @data_position: holds the data-position property + * + * returns: + * 0, on success + * -ENOENT if the property could not be found + */ +int fit_image_get_data_position(const void *fit, int noffset, + int *data_position) +{ + const fdt32_t *val; + + val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL); + if (!val) + return -ENOENT; + + *data_position = fdt32_to_cpu(*val); + + return 0; +} + /** * Get 'data-size' property from a given image node. * @@ -1038,34 +1069,14 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data, return 0; } -/** - * fit_image_verify - verify data integrity - * @fit: pointer to the FIT format image header - * @image_noffset: component image node offset - * - * fit_image_verify() goes over component image hash nodes, - * re-calculates each data hash and compares with the value stored in hash - * node. - * - * returns: - * 1, if all hashes are valid - * 0, otherwise (or on error) - */ -int fit_image_verify(const void *fit, int image_noffset) +int fit_image_verify_with_data(const void *fit, int image_noffset, + const void *data, size_t size) { - const void *data; - size_t size; 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"; - goto error; - } - /* Verify all required signatures */ if (IMAGE_ENABLE_VERIFY && fit_image_verify_required_sigs(fit, image_noffset, data, size, @@ -1081,7 +1092,7 @@ int fit_image_verify(const void *fit, int image_noffset) /* * Check subnode name, must be equal to "hash". * Multiple hash nodes require unique unit node - * names, e.g. hash@1, hash@2, etc. + * names, e.g. hash-1, hash-2, etc. */ if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) { @@ -1122,6 +1133,38 @@ error: return 0; } +/** + * fit_image_verify - verify data integrity + * @fit: pointer to the FIT format image header + * @image_noffset: component image node offset + * + * fit_image_verify() goes over component image hash nodes, + * re-calculates each data hash and compares with the value stored in hash + * node. + * + * returns: + * 1, if all hashes are valid + * 0, otherwise (or on error) + */ +int fit_image_verify(const void *fit, int image_noffset) +{ + const void *data; + size_t size; + int noffset = 0; + char *err_msg = ""; + + /* Get image data and data length */ + if (fit_image_get_data(fit, image_noffset, &data, &size)) { + err_msg = "Can't get image data/size"; + printf("error!\n%s for '%s' hash node in '%s' image node\n", + err_msg, fit_get_name(fit, noffset, NULL), + fit_get_name(fit, image_noffset, NULL)); + return 0; + } + + return fit_image_verify_with_data(fit, image_noffset, data, size); +} + /** * fit_all_image_verify - verify data integrity for all images * @fit: pointer to the FIT format image header @@ -1318,15 +1361,15 @@ int fit_check_format(const void *fit) * * / o image-tree * |-o images - * | |-o fdt@1 - * | |-o fdt@2 + * | |-o fdt-1 + * | |-o fdt-2 * | * |-o configurations - * |-o config@1 - * | |-fdt = fdt@1 + * |-o config-1 + * | |-fdt = fdt-1 * | - * |-o config@2 - * |-fdt = fdt@2 + * |-o config-2 + * |-fdt = fdt-2 * * / o U-Boot fdt * |-compatible = "foo,bar", "bim,bam" @@ -1454,6 +1497,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) { int noffset, confs_noffset; int len; + const char *s; + char *conf_uname_copy = NULL; confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { @@ -1475,12 +1520,29 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) debug("Found default configuration: '%s'\n", conf_uname); } + s = strchr(conf_uname, '#'); + if (s) { + len = s - conf_uname; + conf_uname_copy = malloc(len + 1); + if (!conf_uname_copy) { + debug("Can't allocate uname copy: '%s'\n", + conf_uname); + return -ENOMEM; + } + memcpy(conf_uname_copy, conf_uname, len); + conf_uname_copy[len] = '\0'; + conf_uname = conf_uname_copy; + } + noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); if (noffset < 0) { debug("Can't get node offset for configuration unit name: '%s' (%s)\n", conf_uname, fdt_strerror(noffset)); } + if (conf_uname_copy) + free(conf_uname_copy); + return noffset; } @@ -1527,7 +1589,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) char *desc; const char *uname; int ret; - int loadables_index; + int fdt_index, loadables_index; /* Mandatory properties */ ret = fit_get_desc(fit, noffset, &desc); @@ -1549,9 +1611,21 @@ void fit_conf_print(const void *fit, int noffset, const char *p) if (uname) printf("%s Init Ramdisk: %s\n", p, uname); - uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); + uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL); if (uname) - printf("%s FDT: %s\n", p, uname); + printf("%s Firmware: %s\n", p, uname); + + for (fdt_index = 0; + uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP, + fdt_index, NULL), uname; + fdt_index++) { + + if (fdt_index == 0) + printf("%s FDT: ", p); + else + printf("%s ", p); + printf("%s\n", uname); + } uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL); if (uname) @@ -1888,3 +1962,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, return ret; } + +#ifndef USE_HOSTCC +int 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) +{ + int fdt_noffset, cfg_noffset, count; + const void *fit; + const char *fit_uname = NULL; + const char *fit_uname_config = NULL; + char *fit_uname_config_copy = NULL; + char *next_config = NULL; + ulong load, len; +#ifdef CONFIG_OF_LIBFDT_OVERLAY + ulong image_start, image_end; + ulong ovload, ovlen; + const char *uconfig; + const char *uname; + void *base, *ov; + int i, err, noffset, ov_noffset; +#endif + + fit_uname = fit_unamep ? *fit_unamep : NULL; + + if (fit_uname_configp && *fit_uname_configp) { + fit_uname_config_copy = strdup(*fit_uname_configp); + if (!fit_uname_config_copy) + return -ENOMEM; + + next_config = strchr(fit_uname_config_copy, '#'); + if (next_config) + *next_config++ = '\0'; + if (next_config - 1 > fit_uname_config_copy) + fit_uname_config = fit_uname_config_copy; + } + + fdt_noffset = fit_image_load(images, + addr, &fit_uname, &fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); + + if (fdt_noffset < 0) + goto out; + + debug("fit_uname=%s, fit_uname_config=%s\n", + fit_uname ? fit_uname : "", + fit_uname_config ? fit_uname_config : ""); + + fit = map_sysmem(addr, 0); + + cfg_noffset = fit_conf_get_node(fit, fit_uname_config); + + /* single blob, or error just return as well */ + count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP); + if (count <= 1 && !next_config) + goto out; + + /* we need to apply overlays */ + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + image_start = addr; + image_end = addr + fit_get_size(fit); + /* verify that relocation took place by load address not being in fit */ + if (load >= image_start && load < image_end) { + /* check is simplified; fit load checks for overlaps */ + printf("Overlayed FDT requires relocation\n"); + fdt_noffset = -EBADF; + goto out; + } + + base = map_sysmem(load, len); + + /* apply extra configs in FIT first, followed by args */ + for (i = 1; ; i++) { + if (i < count) { + noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, + FIT_FDT_PROP, i); + uname = fit_get_name(fit, noffset, NULL); + uconfig = NULL; + } else { + if (!next_config) + break; + uconfig = next_config; + next_config = strchr(next_config, '#'); + if (next_config) + *next_config++ = '\0'; + uname = NULL; + } + + debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig); + + ov_noffset = fit_image_load(images, + addr, &uname, &uconfig, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_REQUIRED, &ovload, &ovlen); + if (ov_noffset < 0) { + printf("load of %s failed\n", uname); + continue; + } + debug("%s loaded at 0x%08lx len=0x%08lx\n", + uname, ovload, ovlen); + ov = map_sysmem(ovload, ovlen); + + base = map_sysmem(load, len + ovlen); + err = fdt_open_into(base, base, len + ovlen); + if (err < 0) { + printf("failed on fdt_open_into\n"); + fdt_noffset = err; + goto out; + } + /* the verbose method prints out messages on error */ + err = fdt_overlay_apply_verbose(base, ov); + if (err < 0) { + fdt_noffset = err; + goto out; + } + fdt_pack(base); + len = fdt_totalsize(base); + } +#else + printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n"); + fdt_noffset = -EBADF; +#endif + +out: + if (datap) + *datap = load; + if (lenp) + *lenp = len; + if (fit_unamep) + *fit_unamep = fit_uname; + if (fit_uname_configp) + *fit_uname_configp = fit_uname_config; + + if (fit_uname_config_copy) + free(fit_uname_config_copy); + return fdt_noffset; +} +#endif