int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, ulong addr) { int cfg_noffset; void *fit_hdr; int noffset; debug("* %s: using config '%s' from image at 0x%08lx\n", prop_name, images->fit_uname_cfg, addr); /* Check whether configuration has this property defined */ fit_hdr = map_sysmem(addr, 0); cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); if (cfg_noffset < 0) { debug("* %s: no such config\n", prop_name); return -ENOENT; } noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); if (noffset < 0) { debug("* %s: no '%s' in config\n", prop_name, prop_name); return -ENOLINK; } return noffset; }
static int sec_firmware_get_data(const void *sec_firmware_img, const void **data, size_t *size) { int conf_node_off, fw_node_off; char *conf_node_name = NULL; char *desc; int ret; conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name); if (conf_node_off < 0) { printf("SEC Firmware: %s: no such config\n", conf_node_name); return -ENOENT; } fw_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off, SEC_FIRMWARE_FIT_IMAGE); if (fw_node_off < 0) { printf("SEC Firmware: No '%s' in config\n", SEC_FIRMWARE_FIT_IMAGE); return -ENOLINK; } /* Verify secure firmware image */ if (!(fit_image_verify(sec_firmware_img, fw_node_off))) { printf("SEC Firmware: Bad firmware image (bad CRC)\n"); return -EINVAL; } if (fit_image_get_data(sec_firmware_img, fw_node_off, data, size)) { printf("SEC Firmware: Can't get %s subimage data/size", SEC_FIRMWARE_FIT_IMAGE); return -ENOENT; } ret = fit_get_desc(sec_firmware_img, fw_node_off, &desc); if (ret) printf("SEC Firmware: Can't get description\n"); else printf("%s\n", desc); return ret; }
/* * Get PFE firmware from FIT image * * @param data pointer to PFE firmware * @param size pointer to size of the firmware * @param fw_name pfe firmware name, either class or tmu * * @return 0 on success, a negative value on error */ static int pfe_get_fw(const void **data, size_t *size, char *fw_name) { int conf_node_off, fw_node_off; char *conf_node_name = NULL; char *desc; int ret = 0; conf_node_name = PFE_FIRMEWARE_FIT_CNF_NAME; conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name); if (conf_node_off < 0) { printf("PFE Firmware: %s: no such config\n", conf_node_name); return -ENOENT; } fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off, fw_name); if (fw_node_off < 0) { printf("PFE Firmware: No '%s' in config\n", fw_name); return -ENOLINK; } if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) { printf("PFE Firmware: Bad firmware image (bad CRC)\n"); return -EINVAL; } if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) { printf("PFE Firmware: Can't get %s subimage data/size", fw_name); return -ENOENT; } ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc); if (ret) printf("PFE Firmware: Can't get description\n"); else printf("%s\n", desc); return ret; }
int fit_image_load(bootm_headers_t *images, const char *prop_name, 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; int ret; fit = map_sysmem(addr, 0); fit_uname = fit_unamep ? *fit_unamep : NULL; fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); if (!fit_check_format(fit)) { printf("Bad FIT %s image format!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); return -ENOEXEC; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); if (fit_uname) { /* get ramdisk component image node offset */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); noffset = fit_image_get_node(fit, fit_uname); } else { /* * no image node unit name, try to get config * node first. If config unit node name is NULL * fit_conf_get_node() will try to find default config node */ bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) { cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); } else { cfg_noffset = fit_conf_get_node(fit, fit_uname_config); } if (cfg_noffset < 0) { puts("Could not find configuration node\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); return -ENOENT; } fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); printf(" Using '%s' configuration\n", fit_uname_config); if (image_type == IH_TYPE_KERNEL) { /* Remember (and possibly verify) this config */ images->fit_uname_cfg = fit_uname_config; if (IMAGE_ENABLE_VERIFY && images->verify) { puts(" Verifying Hash Integrity ... "); if (!fit_config_verify(fit, cfg_noffset)) { puts("Bad Data Hash\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); return -EACCES; } puts("OK\n"); } bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); } noffset = fit_conf_get_prop_node(fit, cfg_noffset, prop_name); fit_uname = fit_get_name(fit, noffset, NULL); } if (noffset < 0) { puts("Could not find subimage node\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); return -ENOENT; } printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); ret = fit_image_select(fit, noffset, images->verify); if (ret) { bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); return ret; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); if (!fit_image_check_target_arch(fit, noffset)) { puts("Unsupported Architecture\n"); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); return -ENOEXEC; } if (image_type == IH_TYPE_FLATDT && !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { puts("FDT image is compressed"); return -EPROTONOSUPPORT; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); type_ok = fit_image_check_type(fit, noffset, image_type) || (image_type == IH_TYPE_KERNEL && fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); os_ok = image_type == IH_TYPE_FLATDT || fit_image_check_os(fit, noffset, IH_OS_LINUX); if (!type_ok || !os_ok) { printf("No Linux %s %s Image\n", genimg_get_arch_name(arch), genimg_get_type_name(image_type)); bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); return -EIO; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); /* get image data address and length */ 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 -ENOENT; } len = (ulong)size; /* verify that image data is a proper FDT blob */ if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) { puts("Subimage data is not a FDT"); return -ENOEXEC; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); /* * Work-around for eldk-4.2 which gives this warning if we try to * case in the unmap_sysmem() call: * warning: initialization discards qualifiers from pointer target type */ { void *vbuf = (void *)buf; data = map_to_sysmem(vbuf); } if (load_op == FIT_LOAD_IGNORED) { /* Don't load */ } else if (fit_image_get_load(fit, noffset, &load)) { if (load_op == FIT_LOAD_REQUIRED) { printf("Can't get %s subimage load address!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); return -EBADF; } } else { ulong image_start, image_end; ulong load_end; void *dst; /* * move image data to the load address, * make sure we don't overwrite initial image */ image_start = addr; image_end = addr + fit_get_size(fit); load_end = load + len; if (image_type != IH_TYPE_KERNEL && load < image_end && load_end > image_start) { printf("Error: %s overwritten\n", prop_name); return -EXDEV; } printf(" Loading %s from 0x%08lx to 0x%08lx\n", prop_name, data, load); dst = map_sysmem(load, len); memmove(dst, buf, len); data = load; } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); *datap = data; *lenp = len; if (fit_unamep) *fit_unamep = (char *)fit_uname; if (fit_uname_configp) *fit_uname_configp = (char *)fit_uname_config; return noffset; }
static int fit_config_get_hash_list(void *fit, int conf_noffset, int sig_offset, struct strlist *node_inc) { int allow_missing; const char *prop, *iname, *end; const char *conf_name, *sig_name; char name[200], path[200]; int image_count; int ret, len; conf_name = fit_get_name(fit, conf_noffset, NULL); sig_name = fit_get_name(fit, sig_offset, NULL); /* * Build a list of nodes we need to hash. We always need the root * node and the configuration. */ strlist_init(node_inc); snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); if (strlist_add(node_inc, "/") || strlist_add(node_inc, name)) goto err_mem; /* Get a list of images that we intend to sign */ prop = fit_config_get_image_list(fit, sig_offset, &len, &allow_missing); if (!prop) return 0; /* Locate the images */ end = prop + len; image_count = 0; for (iname = prop; iname < end; iname += strlen(iname) + 1) { int noffset; int image_noffset; int hash_count; image_noffset = fit_conf_get_prop_node(fit, conf_noffset, iname); if (image_noffset < 0) { printf("Failed to find image '%s' in configuration '%s/%s'\n", iname, conf_name, sig_name); if (allow_missing) continue; return -ENOENT; } ret = fdt_get_path(fit, image_noffset, path, sizeof(path)); if (ret < 0) goto err_path; if (strlist_add(node_inc, path)) goto err_mem; snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); /* Add all this image's hashes */ hash_count = 0; for (noffset = fdt_first_subnode(fit, image_noffset); noffset >= 0; noffset = fdt_next_subnode(fit, noffset)) { const char *name = fit_get_name(fit, noffset, NULL); if (strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) continue; ret = fdt_get_path(fit, noffset, path, sizeof(path)); if (ret < 0) goto err_path; if (strlist_add(node_inc, path)) goto err_mem; hash_count++; } if (!hash_count) { printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", conf_name, sig_name, iname); return -ENOMSG; } image_count++; } if (!image_count) { printf("Failed to find any images for configuration '%s/%s'\n", conf_name, sig_name); return -ENOMSG; } return 0; err_mem: printf("Out of memory processing configuration '%s/%s'\n", conf_name, sig_name); return -ENOMEM; err_path: printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n", iname, conf_name, sig_name, fdt_strerror(ret)); return -ENOENT; }