/** * fdt_find_or_add_subnode() - find or possibly add a subnode of a given node * * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * * fdt_subnode_offset() finds a subnode of the node with a given name. * If the subnode does not exist, it will be created. */ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name) { int offset; offset = fdt_subnode_offset(fdt, parentoffset, name); if (offset == -FDT_ERR_NOTFOUND) offset = fdt_add_subnode(fdt, parentoffset, name); if (offset < 0) printf("%s: %s: %s\n", __func__, name, fdt_strerror(offset)); return offset; }
/** * Decode the display controller information from the fdt. * * @param blob fdt blob * @param config structure to store fdt config into * @return 0 if ok, -ve on error */ static int tegra_display_decode_config(const void *blob, struct fdt_disp_config *config) { int node, rgb; int bpp, bit; /* TODO: Support multiple controllers */ node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_DC); if (node < 0) { debug("%s: Cannot find display controller node in fdt\n", __func__); return node; } config->disp = (struct disp_ctlr *)fdtdec_get_addr(blob, node, "reg"); if (!config->disp) { debug("%s: No display controller address\n", __func__); return -1; } rgb = fdt_subnode_offset(blob, node, "rgb"); config->panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); if (!config->panel_node < 0) { debug("%s: Cannot find panel information\n", __func__); return -1; } if (tegra_decode_panel(blob, config->panel_node, config)) { debug("%s: Failed to decode panel information\n", __func__); return -1; } bpp = fdtdec_get_int(blob, config->panel_node, "nvidia,bits-per-pixel", -1); bit = ffs(bpp) - 1; if (bpp == (1 << bit)) config->log2_bpp = bit; else config->log2_bpp = bpp; if (bpp == -1) { debug("%s: Pixel bpp parameters missing\n", __func__); return -FDT_ERR_NOTFOUND; } config->bpp = bpp; config->valid = 1; /* we have a valid configuration */ return 0; }
int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config) { int flash_node, node; node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC); if (node < 0) { debug("Failed to find chrome-ec node'\n"); return -1; } flash_node = fdt_subnode_offset(blob, node, "flash"); if (flash_node < 0) { debug("Failed to find flash node\n"); return -1; } if (fdtdec_read_fmap_entry(blob, flash_node, "flash", &config->flash)) { debug("Failed to decode flash node in chrome-ec'\n"); return -1; } config->flash_erase_value = fdtdec_get_int(blob, flash_node, "erase-value", -1); for (node = fdt_first_subnode(blob, flash_node); node >= 0; node = fdt_next_subnode(blob, node)) { const char *name = fdt_get_name(blob, node, NULL); enum ec_flash_region region; if (0 == strcmp(name, "ro")) { region = EC_FLASH_REGION_RO; } else if (0 == strcmp(name, "rw")) { region = EC_FLASH_REGION_RW; } else if (0 == strcmp(name, "wp-ro")) { region = EC_FLASH_REGION_WP_RO; } else { debug("Unknown EC flash region name '%s'\n", name); return -1; } if (fdtdec_read_fmap_entry(blob, node, "reg", &config->region[region])) { debug("Failed to decode flash region in chrome-ec'\n"); return -1; } } return 0; }
int main(int argc, char *argv[]) { const struct fdt_property *prop; void *fdt; int offset; int subnode1_offset; const void *val; int lenerr; test_init(argc, argv); fdt = load_blob_arg(argc, argv); prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_get_property(\"nonexistant-property\")", lenerr); val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr); check_error("fdt_getprop(\"nonexistant-property\"", lenerr); subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1"); if (subnode1_offset < 0) FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset)); val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr); check_error("fdt_getprop(\"prop-str\")", lenerr); offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode"); check_error("fdt_subnode_offset(\"nonexistant-subnode\")", offset); offset = fdt_subnode_offset(fdt, 0, "subsubnode"); check_error("fdt_subnode_offset(\"subsubnode\")", offset); offset = fdt_path_offset(fdt, "/nonexistant-subnode"); check_error("fdt_path_offset(\"/nonexistant-subnode\")", offset); PASS(); }
static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num) { int offs, node_offs, ret, i; uint32_t phandle; offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks"); if (offs < 0) { debug("Could not find cm_core_aon clocks node path offset : %s\n", fdt_strerror(offs)); return offs; } for (i = 0; i < num; i++) { node_offs = fdt_subnode_offset(fdt, offs, names[i]); if (node_offs < 0) { debug("Could not find clock sub-node %s: %s\n", names[i], fdt_strerror(node_offs)); return offs; } phandle = fdt_get_phandle(fdt, node_offs); if (!phandle) { debug("Could not find phandle for clock %s\n", names[i]); return -1; } ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks", phandle); if (ret < 0) { debug("Could not add assigned-clocks property to clock node %s: %s\n", names[i], fdt_strerror(ret)); return ret; } ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates", rates[i]); if (ret < 0) { debug("Could not add assigned-clock-rates property to clock node %s: %s\n", names[i], fdt_strerror(ret)); return ret; } } return 0; }
/* * Apply one overlay fragment */ static void fdt_apply_fragment(void *main_fdtp, void *overlay_fdtp, int fragment_o) { uint32_t target; const char *target_path; const void *val; int target_node_o, overlay_node_o; target_node_o = -1; val = fdt_getprop(overlay_fdtp, fragment_o, "target", NULL); if (val) { memcpy(&target, val, sizeof(target)); target = fdt32_to_cpu(target); target_node_o = fdt_node_offset_by_phandle(main_fdtp, target); if (target_node_o < 0) { printf("failed to find target %04x\n", target); return; } } if (target_node_o < 0) { target_path = fdt_getprop(overlay_fdtp, fragment_o, "target-path", NULL); if (target_path == NULL) return; target_node_o = fdt_path_offset(main_fdtp, target_path); if (target_node_o < 0) { printf("failed to find target-path %s\n", target_path); return; } } if (target_node_o < 0) return; overlay_node_o = fdt_subnode_offset(overlay_fdtp, fragment_o, "__overlay__"); if (overlay_node_o < 0) { printf("missing __overlay__ sub-node\n"); return; } fdt_overlay_node(main_fdtp, target_node_o, overlay_fdtp, overlay_node_o); }
/** * fit_image_get_node - get node offset for component image of a given unit name * @fit: pointer to the FIT format image header * @image_uname: component image node unit name * * fit_image_get_node() finds a component image (withing the '/images' * node) of a provided unit name. If image is found its node offset is * returned to the caller. * * returns: * image node offset when found (>=0) * negative number on failure (FDT_ERR_* code) */ int fit_image_get_node(const void *fit, const char *image_uname) { int noffset, images_noffset; images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { debug("Can't find images parent node '%s' (%s)\n", FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return images_noffset; } noffset = fdt_subnode_offset(fit, images_noffset, image_uname); if (noffset < 0) { debug("Can't get node offset for image unit name: '%s' (%s)\n", image_uname, fdt_strerror(noffset)); } return noffset; }
static int fdt_offset(const void *fit) { int images, node, fdt_len, fdt_node, fdt_offset; const char *fdt_name; node = fit_find_config_node(fit); if (node < 0) return node; images = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images < 0) { debug("%s: Cannot find /images node: %d\n", __func__, images); return -EINVAL; } fdt_name = fdt_getprop(fit, node, FIT_FDT_PROP, &fdt_len); if (!fdt_name) { debug("%s: Cannot find fdt name property: %d\n", __func__, fdt_len); return -EINVAL; } fdt_node = fdt_subnode_offset(fit, images, fdt_name); if (fdt_node < 0) { debug("%s: Cannot find fdt node '%s': %d\n", __func__, fdt_name, fdt_node); return -EINVAL; } fdt_offset = fdt_getprop_u32(fit, fdt_node, "data-offset"); if (fdt_offset == FDT_ERROR) return -ENOENT; fdt_len = fdt_getprop_u32(fit, fdt_node, "data-size"); if (fdt_len < 0) return fdt_len; return fdt_offset; }
/** * spl_fit_get_image_node(): By using the matching configuration subnode, * retrieve the name of an image, specified by a property name and an index * into that. * @fit: Pointer to the FDT blob. * @images: Offset of the /images subnode. * @type: Name of the property within the configuration subnode. * @index: Index into the list of strings in this property. * * Return: the node offset of the respective image node or a negative * error number. */ static int spl_fit_get_image_node(const void *fit, int images, const char *type, int index) { char *str; int err; int node; err = spl_fit_get_image_name(fit, images, type, index, &str); if (err) return err; debug("%s: '%s'\n", type, str); node = fdt_subnode_offset(fit, images, str); if (node < 0) { debug("cannot find image node '%s': %d\n", str, node); return -EINVAL; } return node; }
static int lp873x_bind(struct udevice *dev) { int regulators_node; const void *blob = gd->fdt_blob; int children; int node = dev->of_offset; regulators_node = fdt_subnode_offset(blob, node, "regulators"); if (regulators_node <= 0) { printf("%s: %s reg subnode not found!", __func__, dev->name); return -ENXIO; } children = pmic_bind_children(dev, regulators_node, pmic_children_info); if (!children) printf("%s: %s - no child found\n", __func__, dev->name); /* Always return success for this device */ return 0; }
static int mc_fixup_dpc_mac_addr(void *blob, int dpmac_id, struct eth_device *eth_dev) { int nodeoffset = fdt_path_offset(blob, "/board_info/ports"), noff; int err = 0; char mac_name[10]; const char link_type_mode[] = "MAC_LINK_TYPE_FIXED"; sprintf(mac_name, "mac@%d", dpmac_id); /* node not found - create it */ noff = fdt_subnode_offset(blob, nodeoffset, (const char *)mac_name); if (noff < 0) { err = fdt_increase_size(blob, 200); if (err) { printf("fdt_increase_size: err=%s\n", fdt_strerror(err)); return err; } noff = fdt_add_subnode(blob, nodeoffset, mac_name); if (noff < 0) { printf("fdt_add_subnode: err=%s\n", fdt_strerror(err)); return err; } /* add default property of fixed link */ err = fdt_appendprop_string(blob, noff, "link_type", link_type_mode); if (err) { printf("fdt_appendprop_string: err=%s\n", fdt_strerror(err)); return err; } } return mc_fixup_mac_addr(blob, noff, "port_mac_address", eth_dev, MC_FIXUP_DPC); }
static int s5m8767_bind(struct udevice *dev) { int node; const void *blob = gd->fdt_blob; int children; node = fdt_subnode_offset(blob, dev->of_offset, "regulators"); if (node <= 0) { debug("%s: %s regulators subnode not found!", __func__, dev->name); return -ENXIO; } debug("%s: '%s' - found regulators subnode\n", __func__, dev->name); children = pmic_bind_children(dev, node, pmic_children_info); if (!children) debug("%s: %s - no child found\n", __func__, dev->name); /* Always return success for this device */ return 0; }
int fit_image_verify_required_sigs(const void *fit, int image_noffset, const char *data, size_t size, const void *sig_blob, int *no_sigsp) { int verify_count = 0; int noffset; int sig_node; /* Work out what we need to verify */ *no_sigsp = 1; sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); if (sig_node < 0) { debug("%s: No signature node found: %s\n", __func__, fdt_strerror(sig_node)); return 0; } fdt_for_each_subnode(noffset, sig_blob, sig_node) { const char *required; int ret; required = fdt_getprop(sig_blob, noffset, "required", NULL); if (!required || strcmp(required, "image")) continue; ret = fit_image_verify_sig(fit, image_noffset, data, size, sig_blob, noffset); if (ret) { printf("Failed to verify required signature '%s'\n", fit_get_name(sig_blob, noffset, NULL)); return ret; } verify_count++; } if (verify_count) *no_sigsp = 0; return 0; }
/* * Overlay one node defined by <overlay_fdtp, overlay_o> over <main_fdtp, target_o> */ static void fdt_overlay_node(void *main_fdtp, int target_o, void *overlay_fdtp, int overlay_o) { int len, o, depth; const char *name; const void *val; int target_subnode_o; /* Overlay properties */ for (o = fdt_first_property_offset(overlay_fdtp, overlay_o); o >= 0; o = fdt_next_property_offset(overlay_fdtp, o)) { val = fdt_getprop_by_offset(overlay_fdtp, o, &name, &len); if (val) fdt_setprop(main_fdtp, target_o, name, val, len); } /* Now overlay nodes */ o = overlay_o; for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(overlay_fdtp, o, &depth)) { if (depth != 1) continue; /* Check if there is node with the same name */ name = fdt_get_name(overlay_fdtp, o, NULL); target_subnode_o = fdt_subnode_offset(main_fdtp, target_o, name); if (target_subnode_o < 0) { /* create new subnode and run merge recursively */ target_subnode_o = fdt_add_subnode(main_fdtp, target_o, name); if (target_subnode_o < 0) { printf("failed to create subnode \"%s\": %d\n", name, target_subnode_o); return; } } fdt_overlay_node(main_fdtp, target_subnode_o, overlay_fdtp, o); } }
int mrccache_get_region(struct udevice **devp, struct mrc_region *entry) { const void *blob = gd->fdt_blob; int node, mrc_node; u32 reg[2]; int ret; /* Find the flash chip within the SPI controller node */ node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); if (node < 0) return -ENOENT; if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2)) return -FDT_ERR_NOTFOUND; entry->base = reg[0]; /* Find the place where we put the MRC cache */ mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache"); if (mrc_node < 0) return -EPERM; if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2)) return -FDT_ERR_NOTFOUND; entry->offset = reg[0]; entry->length = reg[1]; if (devp) { ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, devp); debug("ret = %d\n", ret); if (ret) return ret; } return 0; }
static void compare_subnodes(const void *fdt1, int offset1, const void *fdt2, int offset2, int recurse) { int coffset1, coffset2, depth; for (depth = 0, coffset1 = offset1; (coffset1 >= 0) && (depth >= 0); coffset1 = fdt_next_node(fdt1, coffset1, &depth)) if (depth == 1) { const char *name = fdt_get_name(fdt1, coffset1, NULL); verbose_printf("Subnode %s\n", name); coffset2 = fdt_subnode_offset(fdt2, offset2, name); if (coffset2 == -FDT_ERR_NOTFOUND) MISMATCH("Subnode %s missing\n", name); else if (coffset2 < 0) FAIL("fdt_subnode_offset(): %s\n", fdt_strerror(coffset2)); if (recurse) compare_node(fdt1, coffset1, fdt2, coffset2); } }
/** * Modify the device tree to remove all unused interface types. */ int board_fixup_fdt(void) { const char *fdt_key; int val; int rc; val = pca953x_get_val(0, 0x20); if (val & 4) fdt_key = "2,sata"; else fdt_key = "2,pcie"; octeon_fdt_patch(working_fdt, fdt_key, NULL); if (val & 1) fdt_key = "0,xaui"; else fdt_key = "0,qsgmii"; debug("%s: Patching DLM 0 for %s\n", __func__, fdt_key); octeon_fdt_patch(working_fdt, fdt_key, NULL); if (val & 8) { debug("PCM mode detected, disabling SPI NOR\n"); octeon_fdt_patch(working_fdt, "0,pcm", "cavium,pcm-trim"); } else { debug("SPI NOR mode selected\n"); octeon_fdt_patch(working_fdt, "0,not-pcm", "cavium,pcm-trim"); } /* Check if we need to swap the MMC slots or not. */ if (val & 0x10) { int s0_offset, s1_offset, offset; debug("%s: Swapping mmc slots 0 and 1\n", __func__); /* Swap slot 0 and slot 1 in device tree */ offset = fdt_path_offset(gd->fdt_blob, "/soc/mmc"); if (offset < 0) { puts("Error accessing /soc/mmc in device tree\n"); return -1; } s0_offset = fdt_subnode_offset(gd->fdt_blob, offset, "mmc-slot@0"); s1_offset = fdt_subnode_offset(gd->fdt_blob, offset, "mmc-slot@1"); debug(" slot 0 offset: %d, slot 1 offset: %d\n", s0_offset, s1_offset); if (s0_offset < 0 || s1_offset < 0) { puts("Error accessing MMC in device tree\n"); return -1; } rc = fdt_setprop_inplace_u32(gd->fdt_blob, s0_offset, "reg", 1); rc |= fdt_setprop_inplace_u32(gd->fdt_blob, s1_offset, "reg", 0); if (rc) { puts("Error changing reg property in mmc slot\n"); return -1; } rc = fdt_set_name(gd->fdt_blob, s0_offset, "mmc-slot@1"); rc |= fdt_set_name(gd->fdt_blob, s1_offset, "mmc-slot@0"); if (rc) { puts("Error renaming MMC slot names\n"); return -1; } } return 0; }
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, unsigned long orig_fdt_size, void *fdt, int new_fdt_size, char *cmdline_ptr, u64 initrd_addr, u64 initrd_size, efi_memory_desc_t *memory_map, unsigned long map_size, unsigned long desc_size, u32 desc_ver) { int node, prev, num_rsv; int status; u32 fdt_val32; u64 fdt_val64; /* Do some checks on provided FDT, if it exists*/ if (orig_fdt) { if (fdt_check_header(orig_fdt)) { pr_efi_err(sys_table, "Device Tree header not valid!\n"); return EFI_LOAD_ERROR; } /* * We don't get the size of the FDT if we get if from a * configuration table. */ if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { pr_efi_err(sys_table, "Truncated device tree! foo!\n"); return EFI_LOAD_ERROR; } } if (orig_fdt) status = fdt_open_into(orig_fdt, fdt, new_fdt_size); else status = fdt_create_empty_tree(fdt, new_fdt_size); if (status != 0) goto fdt_set_fail; /* * Delete any memory nodes present. We must delete nodes which * early_init_dt_scan_memory may try to use. */ prev = 0; for (;;) { const char *type; int len; node = fdt_next_node(fdt, prev, NULL); if (node < 0) break; type = fdt_getprop(fdt, node, "device_type", &len); if (type && strncmp(type, "memory", len) == 0) { fdt_del_node(fdt, node); continue; } prev = node; } /* * Delete all memory reserve map entries. When booting via UEFI, * kernel will use the UEFI memory map to find reserved regions. */ num_rsv = fdt_num_mem_rsv(fdt); while (num_rsv-- > 0) fdt_del_mem_rsv(fdt, num_rsv); node = fdt_subnode_offset(fdt, 0, "chosen"); if (node < 0) { node = fdt_add_subnode(fdt, 0, "chosen"); if (node < 0) { status = node; /* node is error code when negative */ goto fdt_set_fail; } } if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) { status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, strlen(cmdline_ptr) + 1); if (status) goto fdt_set_fail; } /* Set initrd address/end in device tree, if present */ if (initrd_size != 0) { u64 initrd_image_end; u64 initrd_image_start = cpu_to_fdt64(initrd_addr); status = fdt_setprop(fdt, node, "linux,initrd-start", &initrd_image_start, sizeof(u64)); if (status) goto fdt_set_fail; initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); status = fdt_setprop(fdt, node, "linux,initrd-end", &initrd_image_end, sizeof(u64)); if (status) goto fdt_set_fail; } /* Add FDT entries for EFI runtime services in chosen node. */ node = fdt_subnode_offset(fdt, 0, "chosen"); fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); status = fdt_setprop(fdt, node, "linux,uefi-system-table", &fdt_val64, sizeof(fdt_val64)); if (status) goto fdt_set_fail; fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map); status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", &fdt_val64, sizeof(fdt_val64)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(map_size); status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(desc_size); status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(desc_ver); status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; /* * Add kernel version banner so stub/kernel match can be * verified. */ status = fdt_setprop_string(fdt, node, "linux,uefi-stub-kern-ver", linux_banner); if (status) goto fdt_set_fail; return EFI_SUCCESS; fdt_set_fail: if (status == -FDT_ERR_NOSPACE) return EFI_BUFFER_TOO_SMALL; return EFI_LOAD_ERROR; }
*gbe_0 = slave; } else { /* Slave devices to be registered */ slave_name = malloc(20); snprintf(slave_name, 20, "netcp@slave-%d", slave_no); ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name, slave, &sl_dev); if (ret) { error("ks2_net - not able to bind slave interfaces\n"); return ret; } } } sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports"); fdt_for_each_subnode(fdt, slave, sec_slave) { int slave_no; slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT); if (slave_no == -ENOENT) continue; /* Slave devices to be registered */ slave_name = malloc(20); snprintf(slave_name, 20, "netcp@slave-%d", slave_no); ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name, slave, &sl_dev); if (ret) { error("ks2_net - not able to bind slave interfaces\n"); return ret;
int rsa_add_verify_data(struct image_sign_info *info, void *keydest) { BIGNUM *modulus, *r_squared; uint64_t exponent; uint32_t n0_inv; int parent, node; char name[100]; int ret; int bits; RSA *rsa; debug("%s: Getting verification data\n", __func__); ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa); if (ret) return ret; ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared); if (ret) return ret; bits = BN_num_bits(modulus); parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME); if (parent == -FDT_ERR_NOTFOUND) { parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME); if (parent < 0) { ret = parent; if (ret != -FDT_ERR_NOSPACE) { fprintf(stderr, "Couldn't create signature node: %s\n", fdt_strerror(parent)); } } } if (ret) goto done; /* Either create or overwrite the named key node */ snprintf(name, sizeof(name), "key-%s", info->keyname); node = fdt_subnode_offset(keydest, parent, name); if (node == -FDT_ERR_NOTFOUND) { node = fdt_add_subnode(keydest, parent, name); if (node < 0) { ret = node; if (ret != -FDT_ERR_NOSPACE) { fprintf(stderr, "Could not create key subnode: %s\n", fdt_strerror(node)); } } } else if (node < 0) { fprintf(stderr, "Cannot select keys parent: %s\n", fdt_strerror(node)); ret = node; } if (!ret) { ret = fdt_setprop_string(keydest, node, "key-name-hint", info->keyname); } if (!ret) ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits); if (!ret) ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv); if (!ret) { ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent); } if (!ret) { ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus, bits); } if (!ret) { ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared, bits); } if (!ret) { ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP, info->name); } if (!ret && info->require_keys) { ret = fdt_setprop_string(keydest, node, "required", info->require_keys); } done: BN_free(modulus); BN_free(r_squared); if (ret) return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; return 0; }
/** * fit_conf_find_compat * @fit: pointer to the FIT format image header * @fdt: pointer to the device tree to compare against * * fit_conf_find_compat() attempts to find the configuration whose fdt is the * most compatible with the passed in device tree. * * Example: * * / o image-tree * |-o images * | |-o fdt@1 * | |-o fdt@2 * | * |-o configurations * |-o config@1 * | |-fdt = fdt@1 * | * |-o config@2 * |-fdt = fdt@2 * * / o U-Boot fdt * |-compatible = "foo,bar", "bim,bam" * * / o kernel fdt1 * |-compatible = "foo,bar", * * / o kernel fdt2 * |-compatible = "bim,bam", "baz,biz" * * Configuration 1 would be picked because the first string in U-Boot's * compatible list, "foo,bar", matches a compatible string in the root of fdt1. * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1. * * returns: * offset to the configuration to use if one was found * -1 otherwise */ int fit_conf_find_compat(const void *fit, const void *fdt) { int ndepth = 0; int noffset, confs_noffset, images_noffset; const void *fdt_compat; int fdt_compat_len; int best_match_offset = 0; int best_match_pos = 0; confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (confs_noffset < 0 || images_noffset < 0) { debug("Can't find configurations or images nodes.\n"); return -1; } fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len); if (!fdt_compat) { debug("Fdt for comparison has no \"compatible\" property.\n"); return -1; } /* * Loop over the configurations in the FIT image. */ for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { const void *kfdt; const char *kfdt_name; int kfdt_noffset; const char *cur_fdt_compat; int len; size_t size; int i; if (ndepth > 1) continue; kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); if (!kfdt_name) { debug("No fdt property found.\n"); continue; } kfdt_noffset = fdt_subnode_offset(fit, images_noffset, kfdt_name); if (kfdt_noffset < 0) { debug("No image node named \"%s\" found.\n", kfdt_name); continue; } /* * Get a pointer to this configuration's fdt. */ if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) { debug("Failed to get fdt \"%s\".\n", kfdt_name); continue; } len = fdt_compat_len; cur_fdt_compat = fdt_compat; /* * Look for a match for each U-Boot compatibility string in * turn in this configuration's fdt. */ for (i = 0; len > 0 && (!best_match_offset || best_match_pos > i); i++) { int cur_len = strlen(cur_fdt_compat) + 1; if (!fdt_node_check_compatible(kfdt, 0, cur_fdt_compat)) { best_match_offset = noffset; best_match_pos = i; break; } len -= cur_len; cur_fdt_compat += cur_len; } } if (!best_match_offset) { debug("No match found.\n"); return -1; } return best_match_offset; }
EFI_STATUS UpdateMemoryNode(VOID* Fdt) { INTN Error = 0; EFI_STATUS Status = EFI_SUCCESS; UINT32 Index = 0; UINT32 MemIndex; INTN node; struct fdt_property *m_prop; int m_oldlen; EFI_MEMORY_DESCRIPTOR *MemoryMap; EFI_MEMORY_DESCRIPTOR *MemoryMapPtr; EFI_MEMORY_DESCRIPTOR *MemoryMapPtrCurrent; UINTN MemoryMapSize; UINTN Pages0 = 0; UINTN Pages1 = 0; UINTN MapKey; UINTN DescriptorSize; UINT32 DescriptorVersion; PHY_MEM_REGION *mRegion; UINTN MemoryMapLastEndAddress ; UINTN MemoryMapcontinuousStartAddress ; UINTN MemoryMapCurrentStartAddress; BOOLEAN FindMemoryRegionFlag = FALSE; node = fdt_subnode_offset(Fdt, 0, "memory"); if (node < 0) { // Create the memory node node = fdt_add_subnode(Fdt, 0, "memory"); if(node < 0) { DEBUG((EFI_D_INFO, "[%a]:[%dL] fdt add subnode error\n", __FUNCTION__, __LINE__)); } } //find the memory node property m_prop = fdt_get_property_w(Fdt, node, "memory", &m_oldlen); if(m_prop) Error=fdt_delprop(Fdt, node, "reg"); if (Error) { DEBUG ((EFI_D_ERROR, "ERROR:fdt_delprop(): %a\n", fdt_strerror (Error))); Status = EFI_INVALID_PARAMETER; return Status; } MemoryMap = NULL; MemoryMapSize = 0; MemIndex = 0; Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion); if (Status == EFI_BUFFER_TOO_SMALL) { // The UEFI specification advises to allocate more memory for the MemoryMap buffer between successive // calls to GetMemoryMap(), since allocation of the new buffer may potentially increase memory map size. //DEBUG ((EFI_D_ERROR, "MemoryMapsize: 0x%lx\n",MemoryMapSize)); Pages0 = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; MemoryMap = AllocatePages (Pages0); if (MemoryMap == NULL) { Status = EFI_OUT_OF_RESOURCES; return Status; } Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion); } if(MemoryMap == NULL) { Status = EFI_OUT_OF_RESOURCES; //goto EXIT; return Status; } mRegion = NULL; Pages1 = EFI_SIZE_TO_PAGES (sizeof(PHY_MEM_REGION) *( MemoryMapSize / DescriptorSize)); mRegion = (PHY_MEM_REGION*)AllocatePages(Pages1); if (mRegion == NULL) { Status = EFI_OUT_OF_RESOURCES; return Status; } if (!EFI_ERROR(Status)) { MemoryMapPtr = MemoryMap; MemoryMapPtrCurrent = MemoryMapPtr; MemoryMapLastEndAddress = 0; MemoryMapcontinuousStartAddress = 0; MemoryMapCurrentStartAddress = 0; for ( Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) { MemoryMapPtrCurrent = (EFI_MEMORY_DESCRIPTOR*)((UINTN)MemoryMapPtr + Index*DescriptorSize); MemoryMapCurrentStartAddress = (UINTN)MemoryMapPtrCurrent->PhysicalStart; if (!IsMemMapRegion ((EFI_MEMORY_TYPE)MemoryMapPtrCurrent->Type)) { continue; } else { FindMemoryRegionFlag = TRUE; if(MemoryMapCurrentStartAddress != MemoryMapLastEndAddress) { mRegion[MemIndex].BaseHigh= cpu_to_fdt32(MemoryMapcontinuousStartAddress>>32); mRegion[MemIndex].BaseLow=cpu_to_fdt32(MemoryMapcontinuousStartAddress); mRegion[MemIndex].LengthHigh= cpu_to_fdt32((MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress)>>32); mRegion[MemIndex].LengthLow=cpu_to_fdt32(MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress); MemIndex+=1; MemoryMapcontinuousStartAddress=MemoryMapCurrentStartAddress; } } MemoryMapLastEndAddress = (UINTN)(MemoryMapPtrCurrent->PhysicalStart + MemoryMapPtrCurrent->NumberOfPages * EFI_PAGE_SIZE); }
static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp) { const char *name, *fdt_name; int conf, node, fdt_node; int len; *fdt_offsetp = 0; conf = fdt_path_offset(fdt, FIT_CONFS_PATH); if (conf < 0) { debug("%s: Cannot find /configurations node: %d\n", __func__, conf); return -EINVAL; } for (node = fdt_first_subnode(fdt, conf); node >= 0; node = fdt_next_subnode(fdt, node)) { name = fdt_getprop(fdt, node, "description", &len); if (!name) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("%s: Missing FDT description in DTB\n", __func__); #endif return -EINVAL; } if (board_fit_config_name_match(name)) continue; debug("Selecting config '%s'", name); fdt_name = fdt_getprop(fdt, node, FIT_FDT_PROP, &len); if (!fdt_name) { debug("%s: Cannot find fdt name property: %d\n", __func__, len); return -EINVAL; } debug(", fdt '%s'\n", fdt_name); fdt_node = fdt_subnode_offset(fdt, images, fdt_name); if (fdt_node < 0) { debug("%s: Cannot find fdt node '%s': %d\n", __func__, fdt_name, fdt_node); return -EINVAL; } *fdt_offsetp = fdt_getprop_u32(fdt, fdt_node, "data-offset"); len = fdt_getprop_u32(fdt, fdt_node, "data-size"); #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("FIT: Selected '%s'\n", name); #endif return len; } #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("No matching DT out of these options:\n"); for (node = fdt_first_subnode(fdt, conf); node >= 0; node = fdt_next_subnode(fdt, node)) { name = fdt_getprop(fdt, node, "name", &len); printf(" %s\n", name); } #endif return -ENOENT; }
void fsl_sgmii_riser_fdt_fixup(void *fdt) { struct eth_device *dev; int node; int mdio_node; int i = -1; int etsec_num = 0; node = fdt_path_offset(fdt, "/aliases"); if (node < 0) return; while ((dev = eth_get_dev_by_index(++i)) != NULL) { struct tsec_private *priv; int phy_node; int enet_node; uint32_t ph; char sgmii_phy[16]; char enet[16]; const char *model; const char *path; if (!strstr(dev->name, "eTSEC")) continue; priv = dev->priv; if (!(priv->flags & TSEC_SGMII)) { etsec_num++; continue; } mdio_node = fdt_node_offset_by_compatible(fdt, -1, "fsl,gianfar-mdio"); if (mdio_node < 0) return; sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num); phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy); if (phy_node < 0) continue; fdt_increase_size(fdt, 32); ph = fdt_create_phandle(fdt, phy_node); if (!ph) continue; sprintf(enet, "ethernet%d", etsec_num++); path = fdt_getprop(fdt, node, enet, NULL); if (!path) { debug("No alias for %s\n", enet); continue; } enet_node = fdt_path_offset(fdt, path); if (enet_node < 0) continue; model = fdt_getprop(fdt, enet_node, "model", NULL); /* * We only want to do this to eTSECs. On some platforms * there are more than one type of gianfar-style ethernet * controller, and as we are creating an implicit connection * between ethernet nodes and eTSEC devices, it is best to * make the connection use as much explicit information * as exists. */ if (!strstr(model, "TSEC")) continue; fdt_setprop(fdt, enet_node, "phy-handle", &ph, sizeof(ph)); fdt_setprop_string(fdt, enet_node, "phy-connection-type", phy_string_for_interface(PHY_INTERFACE_MODE_SGMII)); } }
int fdtdec_decode_display_timing(const void *blob, int parent, int index, struct display_timing *dt) { int i, node, timings_node; u32 val = 0; int ret = 0; timings_node = fdt_subnode_offset(blob, parent, "display-timings"); if (timings_node < 0) return timings_node; for (i = 0, node = fdt_first_subnode(blob, timings_node); node > 0 && i != index; node = fdt_next_subnode(blob, node)) i++; if (node < 0) return node; memset(dt, 0, sizeof(*dt)); ret |= decode_timing_property(blob, node, "hback-porch", &dt->hback_porch); ret |= decode_timing_property(blob, node, "hfront-porch", &dt->hfront_porch); ret |= decode_timing_property(blob, node, "hactive", &dt->hactive); ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len); ret |= decode_timing_property(blob, node, "vback-porch", &dt->vback_porch); ret |= decode_timing_property(blob, node, "vfront-porch", &dt->vfront_porch); ret |= decode_timing_property(blob, node, "vactive", &dt->vactive); ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len); ret |= decode_timing_property(blob, node, "clock-frequency", &dt->pixelclock); dt->flags = 0; val = fdtdec_get_int(blob, node, "vsync-active", -1); if (val != -1) { dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : DISPLAY_FLAGS_VSYNC_LOW; } val = fdtdec_get_int(blob, node, "hsync-active", -1); if (val != -1) { dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : DISPLAY_FLAGS_HSYNC_LOW; } val = fdtdec_get_int(blob, node, "de-active", -1); if (val != -1) { dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : DISPLAY_FLAGS_DE_LOW; } val = fdtdec_get_int(blob, node, "pixelclk-active", -1); if (val != -1) { dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : DISPLAY_FLAGS_PIXDATA_NEGEDGE; } if (fdtdec_get_bool(blob, node, "interlaced")) dt->flags |= DISPLAY_FLAGS_INTERLACED; if (fdtdec_get_bool(blob, node, "doublescan")) dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; if (fdtdec_get_bool(blob, node, "doubleclk")) dt->flags |= DISPLAY_FLAGS_DOUBLECLK; return 0; }
int fdt_fixup(void) { const char *env; char *ethstr; int chosen, err, eth_no, len; struct sys_info *si; env = NULL; eth_no = 0; ethstr = NULL; len = 0; if (!fdtp) { err = fdt_setup_fdtp(); if (err) { sprintf(command_errbuf, "Could not perform blob " "fixups. Error code: %d\n", err); return (err); } } /* Create /chosen node (if not exists) */ if ((chosen = fdt_subnode_offset(fdtp, 0, "chosen")) == -FDT_ERR_NOTFOUND) chosen = fdt_add_subnode(fdtp, 0, "chosen"); /* Value assigned to fixup-applied does not matter. */ if (fdt_getprop(fdtp, chosen, "fixup-applied", NULL)) return (CMD_OK); /* Acquire sys_info */ si = ub_get_sys_info(); while ((env = ub_env_enum(env)) != NULL) { if (strncmp(env, "eth", 3) == 0 && strncmp(env + (strlen(env) - 4), "addr", 4) == 0) { /* * Handle Ethernet addrs: parse uboot env eth%daddr */ if (!eth_no) { /* * Check how many chars we will need to store * maximal eth iface number. */ len = strlen(STRINGIFY(TMP_MAX_ETH)) + strlen("ethernet"); /* * Reserve mem for string "ethernet" and len * chars for iface no. */ ethstr = (char *)malloc(len * sizeof(char)); bzero(ethstr, len * sizeof(char)); strcpy(ethstr, "ethernet0"); } /* Modify blob */ fixup_ethernet(env, ethstr, ð_no, len); } else if (strcmp(env, "consoledev") == 0) fixup_stdout(env); } /* Modify cpu(s) and bus clock frequenties in /cpus node [Hz] */ fixup_cpubusfreqs(si->clk_cpu, si->clk_bus); /* Fixup memory regions */ fixup_memory(si); fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0); return (CMD_OK); }
static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) { struct tegra_lcd_priv *priv = dev_get_priv(dev); struct fdtdec_phandle_args args; const void *blob = gd->fdt_blob; int node = dev->of_offset; int front, back, ref; int panel_node; int rgb; int bpp, bit; int ret; priv->disp = (struct disp_ctlr *)dev_get_addr(dev); if (!priv->disp) { debug("%s: No display controller address\n", __func__); return -EINVAL; } rgb = fdt_subnode_offset(blob, node, "rgb"); panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); if (panel_node < 0) { debug("%s: Cannot find panel information\n", __func__); return -EINVAL; } priv->width = fdtdec_get_int(blob, panel_node, "xres", -1); priv->height = fdtdec_get_int(blob, panel_node, "yres", -1); priv->pixel_clock = fdtdec_get_int(blob, panel_node, "clock", 0); if (!priv->pixel_clock || priv->width == -1 || priv->height == -1) { debug("%s: Pixel parameters missing\n", __func__); return -EINVAL; } back = fdtdec_get_int(blob, panel_node, "left-margin", -1); front = fdtdec_get_int(blob, panel_node, "right-margin", -1); ref = fdtdec_get_int(blob, panel_node, "hsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Horizontal parameters missing\n", __func__); return -EINVAL; } /* Use a ref-to-sync of 1 always, and take this from the front porch */ priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; priv->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; priv->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; priv->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("horiz", priv->horiz_timing); back = fdtdec_get_int(blob, panel_node, "upper-margin", -1); front = fdtdec_get_int(blob, panel_node, "lower-margin", -1); ref = fdtdec_get_int(blob, panel_node, "vsync-len", -1); if ((back | front | ref) == -1) { debug("%s: Vertical parameters missing\n", __func__); return -EINVAL; } priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; priv->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; priv->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; priv->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; debug_timing("vert", priv->vert_timing); bpp = fdtdec_get_int(blob, panel_node, "nvidia,bits-per-pixel", -1); bit = ffs(bpp) - 1; if (bpp == (1 << bit)) priv->log2_bpp = bit; else priv->log2_bpp = bpp; if (bpp == -1) { debug("%s: Pixel bpp parameters missing\n", __func__); return -EINVAL; } if (fdtdec_parse_phandle_with_args(blob, panel_node, "nvidia,pwm", "#pwm-cells", 0, 0, &args)) { debug("%s: Unable to decode PWM\n", __func__); return -EINVAL; } ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); if (ret) { debug("%s: Unable to find PWM\n", __func__); return -EINVAL; } priv->pwm_channel = args.args[0]; priv->cache_type = fdtdec_get_int(blob, panel_node, "nvidia,cache-type", FDT_LCD_CACHE_WRITE_BACK_FLUSH); /* These GPIOs are all optional */ gpio_request_by_name_nodev(blob, panel_node, "nvidia,backlight-enable-gpios", 0, &priv->backlight_en, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,lvds-shutdown-gpios", 0, &priv->lvds_shutdown, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,backlight-vdd-gpios", 0, &priv->backlight_vdd, GPIOD_IS_OUT); gpio_request_by_name_nodev(blob, panel_node, "nvidia,panel-vdd-gpios", 0, &priv->panel_vdd, GPIOD_IS_OUT); if (fdtdec_get_int_array(blob, panel_node, "nvidia,panel-timings", priv->panel_timings, FDT_LCD_TIMINGS)) return -EINVAL; return 0; }
int board_prepare_usb(enum usb_init_type type) { static struct udevice *pmic_gpio; static struct gpio_desc hub_reset, usb_sel; int ret = 0, node; if (!pmic_gpio) { ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_gpios@c000", &pmic_gpio); if (ret < 0) { printf("Failed to find pm8916_gpios@c000 node.\n"); return ret; } } /* Try to request gpios needed to start usb host on dragonboard */ if (!dm_gpio_is_valid(&hub_reset)) { node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pmic_gpio), "usb_hub_reset_pm"); if (node < 0) { printf("Failed to find usb_hub_reset_pm dt node.\n"); return node; } ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, &hub_reset, 0); if (ret < 0) { printf("Failed to request usb_hub_reset_pm gpio.\n"); return ret; } } if (!dm_gpio_is_valid(&usb_sel)) { node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pmic_gpio), "usb_sw_sel_pm"); if (node < 0) { printf("Failed to find usb_sw_sel_pm dt node.\n"); return 0; } ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, &usb_sel, 0); if (ret < 0) { printf("Failed to request usb_sw_sel_pm gpio.\n"); return ret; } } if (type == USB_INIT_HOST) { /* Start USB Hub */ dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); mdelay(100); /* Switch usb to host connectors */ dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); mdelay(100); } else { /* Device */ /* Disable hub */ dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT); /* Switch back to device connector */ dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT); } return 0; }
int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len) { const void *blob = info->fdt_blob; /* Reserve memory for maximum checksum-length */ uint8_t hash[info->algo->checksum->pad_len]; int ndepth, noffset; int sig_node, node; char name[100]; int ret; /* * Verify that the checksum-length does not exceed the * rsa-signature-length */ if (info->algo->checksum->checksum_len > info->algo->checksum->pad_len) { debug("%s: invlaid checksum-algorithm %s for %s\n", __func__, info->algo->checksum->name, info->algo->name); return -EINVAL; } sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); if (sig_node < 0) { debug("%s: No signature node found\n", __func__); return -ENOENT; } /* Calculate checksum with checksum-algorithm */ ret = info->algo->checksum->calculate(info->algo->checksum->name, region, region_count, hash); if (ret < 0) { debug("%s: Error in checksum calculation\n", __func__); return -EINVAL; } /* See if we must use a particular key */ if (info->required_keynode != -1) { ret = rsa_verify_with_keynode(info, hash, sig, sig_len, info->required_keynode); if (!ret) return ret; } /* Look for a key that matches our hint */ snprintf(name, sizeof(name), "key-%s", info->keyname); node = fdt_subnode_offset(blob, sig_node, name); ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node); if (!ret) return ret; /* No luck, so try each of the keys in turn */ for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(info->fit, noffset, &ndepth)) { if (ndepth == 1 && noffset != node) { ret = rsa_verify_with_keynode(info, hash, sig, sig_len, noffset); if (!ret) break; } } return ret; }
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, unsigned long orig_fdt_size, void *fdt, int new_fdt_size, char *cmdline_ptr, u64 initrd_addr, u64 initrd_size, efi_memory_desc_t *memory_map, unsigned long map_size, unsigned long desc_size, u32 desc_ver) { int node, num_rsv; int status; u32 fdt_val32; u64 fdt_val64; /* Do some checks on provided FDT, if it exists*/ if (orig_fdt) { if (fdt_check_header(orig_fdt)) { pr_efi_err(sys_table, "Device Tree header not valid!\n"); return EFI_LOAD_ERROR; } /* * We don't get the size of the FDT if we get if from a * configuration table. */ if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { pr_efi_err(sys_table, "Truncated device tree! foo!\n"); return EFI_LOAD_ERROR; } } if (orig_fdt) status = fdt_open_into(orig_fdt, fdt, new_fdt_size); else status = fdt_create_empty_tree(fdt, new_fdt_size); if (status != 0) goto fdt_set_fail; /* * Delete all memory reserve map entries. When booting via UEFI, * kernel will use the UEFI memory map to find reserved regions. */ num_rsv = fdt_num_mem_rsv(fdt); while (num_rsv-- > 0) fdt_del_mem_rsv(fdt, num_rsv); node = fdt_subnode_offset(fdt, 0, "chosen"); if (node < 0) { node = fdt_add_subnode(fdt, 0, "chosen"); if (node < 0) { status = node; /* node is error code when negative */ goto fdt_set_fail; } } if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) { status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, strlen(cmdline_ptr) + 1); if (status) goto fdt_set_fail; } /* Set initrd address/end in device tree, if present */ if (initrd_size != 0) { u64 initrd_image_end; u64 initrd_image_start = cpu_to_fdt64(initrd_addr); status = fdt_setprop(fdt, node, "linux,initrd-start", &initrd_image_start, sizeof(u64)); if (status) goto fdt_set_fail; initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); status = fdt_setprop(fdt, node, "linux,initrd-end", &initrd_image_end, sizeof(u64)); if (status) goto fdt_set_fail; } /* Add FDT entries for EFI runtime services in chosen node. */ node = fdt_subnode_offset(fdt, 0, "chosen"); fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); status = fdt_setprop(fdt, node, "linux,uefi-system-table", &fdt_val64, sizeof(fdt_val64)); if (status) goto fdt_set_fail; fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map); status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", &fdt_val64, sizeof(fdt_val64)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(map_size); status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(desc_size); status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; fdt_val32 = cpu_to_fdt32(desc_ver); status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", &fdt_val32, sizeof(fdt_val32)); if (status) goto fdt_set_fail; if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { efi_status_t efi_status; efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64), (u8 *)&fdt_val64); if (efi_status == EFI_SUCCESS) { status = fdt_setprop(fdt, node, "kaslr-seed", &fdt_val64, sizeof(fdt_val64)); if (status) goto fdt_set_fail; } else if (efi_status != EFI_NOT_FOUND) { return efi_status; } } return EFI_SUCCESS; fdt_set_fail: if (status == -FDT_ERR_NOSPACE) return EFI_BUFFER_TOO_SMALL; return EFI_LOAD_ERROR; }