static int mc_fixup_dpc(u64 dpc_addr) { void *blob = (void *)dpc_addr; int nodeoffset; /* delete any existing ICID pools */ nodeoffset = fdt_path_offset(blob, "/resources/icid_pools"); if (fdt_del_node(blob, nodeoffset) < 0) printf("\nfsl-mc: WARNING: could not delete ICID pool\n"); /* add a new pool */ nodeoffset = fdt_path_offset(blob, "/resources"); if (nodeoffset < 0) { printf("\nfsl-mc: ERROR: DPC is missing /resources\n"); return -EINVAL; } nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pools"); nodeoffset = fdt_add_subnode(blob, nodeoffset, "icid_pool@0"); do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", "base_icid", FSL_DPAA2_STREAM_ID_START, 1); do_fixup_by_path_u32(blob, "/resources/icid_pools/icid_pool@0", "num", FSL_DPAA2_STREAM_ID_END - FSL_DPAA2_STREAM_ID_START + 1, 1); flush_dcache_range(dpc_addr, dpc_addr + fdt_totalsize(blob)); return 0; }
void ft_fixup_num_cores(void *blob) { int off, num_cores, del_cores; del_cores = 0; num_cores = cpu_numcores(); off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); /* if we find a cpu node outside of what we expect delete it * and reset the offset back to the start since we can't * trust the offsets anymore */ if (*reg > num_cores-1) { fdt_del_node(blob, off); del_cores++; off = -1; } off = fdt_node_offset_by_prop_value(blob, off, "device_type", "cpu", 4); } debug ("%x core system found\n", num_cores); debug ("deleted %d extra core entry entries from device tree\n", del_cores); }
void ft_fixup_num_cores(void *blob) { int off, num_cores, del_cores; del_cores = 0; num_cores = cpu_numcores(); off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); u32 phys_cpu_id = thread_to_core(*reg); if (!is_core_valid(phys_cpu_id) || is_core_disabled(phys_cpu_id)) { int ph = fdt_get_phandle(blob, off); /* Delete the cpu node once there are no cpu handles */ if (-FDT_ERR_NOTFOUND == ft_del_cpuhandle(blob, ph)) { fdt_del_node(blob, off); del_cores++; } /* either we deleted some cpu handles or the cpu node * so we reset the offset back to the start since we * can't trust the offsets anymore */ off = -1; } off = fdt_node_offset_by_prop_value(blob, off, "device_type", "cpu", 4); } debug ("%x core system found\n", num_cores); debug ("deleted %d extra core entry entries from device tree\n", del_cores); }
int fdt_bd_t(void *fdt) { bd_t *bd = gd->bd; int nodeoffset; int err; u32 tmp; /* used to set 32 bit integer properties */ int i; err = fdt_check_header(fdt); if (err < 0) { printf("fdt_bd_t: %s\n", fdt_strerror(err)); return err; } /* * See if we already have a "bd_t" node, delete it if so. * Then create a new empty node. */ nodeoffset = fdt_path_offset (fdt, "/bd_t"); if (nodeoffset >= 0) { err = fdt_del_node(fdt, nodeoffset); if (err < 0) { printf("fdt_bd_t: %s\n", fdt_strerror(err)); return err; } } /* * Create a new node "/bd_t" (offset 0 is root level) */ nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); if (nodeoffset < 0) { printf("WARNING: could not create /bd_t %s.\n", fdt_strerror(nodeoffset)); printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset)); return nodeoffset; } /* * Use the string/pointer structure to create the entries... */ for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { tmp = cpu_to_be32(getenv("bootargs")); err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp)); if (err < 0) printf("WARNING: could not set %s %s.\n", bd_map[i].name, fdt_strerror(err)); } /* * Add a couple of oddball entries... */ err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); if (err < 0) printf("WARNING: could not set enetaddr %s.\n", fdt_strerror(err)); err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); if (err < 0) printf("WARNING: could not set ethspeed %s.\n", fdt_strerror(err)); return 0; }
void fdt_del_spi_slic(void *blob) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compatible(blob, 0, "zarlink,le88266")) >= 0) { fdt_del_node(blob, nodeoff); } }
void fdt_del_tdm(void *blob) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compatible(blob, 0, "fsl,starlite-tdm")) >= 0) { fdt_del_node(blob, nodeoff); } }
void fdt_del_sdhc(void *blob) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compatible(blob, 0, "fsl,esdhc")) >= 0) { fdt_del_node(blob, nodeoff); } }
void fdt_del_flexcan(void *blob) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compatible(blob, 0, "fsl,p1010-flexcan")) >= 0) { fdt_del_node(blob, nodeoff); } }
void fdt_del_spi_flash(void *blob) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compatible(blob, 0, "spansion,s25sl12801")) >= 0) { fdt_del_node(blob, nodeoff); } }
void fdt_del_sec(void *blob, int offset) { int nodeoff = 0; while ((nodeoff = fdt_node_offset_by_compat_reg(blob, "fsl,sec-v6.0", CONFIG_SYS_CCSRBAR_PHYS + CONFIG_SYS_FSL_SEC_OFFSET + offset * 0x20000)) >= 0) { fdt_del_node(blob, nodeoff); offset++; } }
static int ft_hs_fixup_dram(void *fdt, bd_t *bd) { const char *path, *subpath; int offs; u32 sec_mem_start = CONFIG_TI_SECURE_EMIF_REGION_START; u32 sec_mem_size = CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE; fdt64_t temp[2]; /* If start address is zero, place at end of DRAM */ if (0 == sec_mem_start) sec_mem_start = (CONFIG_SYS_SDRAM_BASE + (omap_sdram_size() - sec_mem_size)); /* Delete any original secure_reserved node */ path = "/reserved-memory/secure_reserved"; offs = fdt_path_offset(fdt, path); if (offs >= 0) fdt_del_node(fdt, offs); /* Add new secure_reserved node */ path = "/reserved-memory"; offs = fdt_path_offset(fdt, path); if (offs < 0) { debug("Node %s not found\n", path); path = "/"; subpath = "reserved-memory"; fdt_path_offset(fdt, path); offs = fdt_add_subnode(fdt, offs, subpath); if (offs < 0) { printf("Could not create %s%s node.\n", path, subpath); return 1; } path = "/reserved-memory"; offs = fdt_path_offset(fdt, path); } subpath = "secure_reserved"; offs = fdt_add_subnode(fdt, offs, subpath); if (offs < 0) { printf("Could not create %s%s node.\n", path, subpath); return 1; } temp[0] = cpu_to_fdt64(((u64)sec_mem_start)); temp[1] = cpu_to_fdt64(((u64)sec_mem_size)); fdt_setprop_string(fdt, offs, "compatible", "ti,dra7-secure-memory"); fdt_setprop_string(fdt, offs, "status", "okay"); fdt_setprop(fdt, offs, "no-map", NULL, 0); fdt_setprop(fdt, offs, "reg", temp, sizeof(temp)); return 0; }
static void fdt_board_fixup_qe_pins(void *blob) { unsigned int oldbus; u8 val8; int node; fsl_lbc_t *lbc = LBC_BASE_ADDR; if (hwconfig("qe")) { /* For QE and eLBC pins multiplexing, * there is a PCA9555 device on P1025RDB. * It control the multiplex pins' functions, * and setting the PCA9555 can switch the * function between QE and eLBC. */ oldbus = i2c_get_bus_num(); i2c_set_bus_num(0); if (hwconfig("tdm")) val8 = PCA_IOPORT_QE_TDM_ENABLE; else val8 = PCA_IOPORT_QE_PIN_ENABLE; i2c_write(PCA_IOPORT_I2C_ADDR, PCA_IOPORT_CFG_CMD, 1, &val8, 1); i2c_write(PCA_IOPORT_I2C_ADDR, PCA_IOPORT_OUTPUT_CMD, 1, &val8, 1); i2c_set_bus_num(oldbus); /* if run QE TDM, Set ABSWP to implement * conversion of addresses in the eLBC. */ if (hwconfig("tdm")) { set_lbc_or(2, CONFIG_PMC_OR_PRELIM); set_lbc_br(2, CONFIG_PMC_BR_PRELIM); setbits_be32(&lbc->lbcr, CONFIG_SYS_LBC_LBCR); } } else { node = fdt_path_offset(blob, "/qe"); if (node >= 0) fdt_del_node(blob, node); } return; }
STATIC VOID DisableSmmu ( IN VOID *Fdt, IN CONST CHAR8 *IommuPropName, IN CONST CHAR8 *SmmuNodeName, IN CONST CHAR8 *DeviceNodeName ) { INT32 Node; INT32 Error; Node = fdt_path_offset (Fdt, DeviceNodeName); if (Node <= 0) { DEBUG ((DEBUG_WARN, "%a: Failed to find path %s: %a\n", __FUNCTION__, DeviceNodeName, fdt_strerror (Node))); return; } Error = fdt_delprop (Fdt, Node, IommuPropName); if (Error != 0) { DEBUG ((DEBUG_WARN, "%a: Failed to delete property %a: %a\n", __FUNCTION__, IommuPropName, fdt_strerror (Error))); return; } Node = fdt_path_offset (Fdt, SmmuNodeName); if (Node <= 0) { DEBUG ((DEBUG_WARN, "%a: Failed to find path %s: %a\n", __FUNCTION__, SmmuNodeName, fdt_strerror (Node))); return; } Error = fdt_del_node (Fdt, Node); if (Error != 0) { DEBUG ((DEBUG_WARN, "%a: Failed to delete node %a: %a\n", __FUNCTION__, SmmuNodeName, fdt_strerror (Error))); } }
/* * If a QE firmware has been uploaded, then add the 'firmware' node under * the 'qe' node. */ void fdt_fixup_qe_firmware(void *blob) { struct qe_firmware_info *qe_fw_info; int node, ret; qe_fw_info = qe_get_firmware_info(); if (!qe_fw_info) return; node = fdt_path_offset(blob, "/qe"); if (node < 0) return; /* We assume the node doesn't exist yet */ node = fdt_add_subnode(blob, node, "firmware"); if (node < 0) return; ret = fdt_setprop(blob, node, "extended-modes", &qe_fw_info->extended_modes, sizeof(u64)); if (ret < 0) goto error; ret = fdt_setprop_string(blob, node, "id", qe_fw_info->id); if (ret < 0) goto error; ret = fdt_setprop(blob, node, "virtual-traps", qe_fw_info->vtraps, sizeof(qe_fw_info->vtraps)); if (ret < 0) goto error; return; error: fdt_del_node(blob, node); }
/* Remove JR node used by SEC firmware */ void fdt_fixup_remove_jr(void *blob) { int jr_node, addr_cells, len; int crypto_node = fdt_path_offset(blob, "crypto"); u64 jr_offset, used_jr; fdt32_t *reg; used_jr = sec_firmware_used_jobring_offset(); fdt_support_default_count_cells(blob, crypto_node, &addr_cells, NULL); jr_node = fdt_node_offset_by_compatible(blob, crypto_node, "fsl,sec-v4.0-job-ring"); while (jr_node != -FDT_ERR_NOTFOUND) { reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len); jr_offset = fdt_read_number(reg, addr_cells); if (jr_offset == used_jr) { fdt_del_node(blob, jr_node); break; } jr_node = fdt_node_offset_by_compatible(blob, jr_node, "fsl,sec-v4.0-job-ring"); } }
void ft_fixup_cpu(void *blob) { int off; __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); fdt32_t *reg; int addr_cells; u64 val, core_id; size_t *boot_code_size = &(__secondary_boot_code_size); u32 mask = cpu_pos_mask(); int off_prev = -1; off = fdt_path_offset(blob, "/cpus"); if (off < 0) { puts("couldn't find /cpus node\n"); return; } fdt_support_default_count_cells(blob, off, &addr_cells, NULL); off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); if (reg) { core_id = fdt_read_number(reg, addr_cells); if (!test_bit(id_to_core(core_id), &mask)) { fdt_del_node(blob, off); off = off_prev; } } off_prev = off; off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type", "cpu", 4); } #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \ defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI) int node; u32 psci_ver; /* Check the psci version to determine if the psci is supported */ psci_ver = sec_firmware_support_psci_version(); if (psci_ver == 0xffffffff) { /* remove psci DT node */ node = fdt_path_offset(blob, "/psci"); if (node >= 0) goto remove_psci_node; node = fdt_node_offset_by_compatible(blob, -1, "arm,psci"); if (node >= 0) goto remove_psci_node; node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2"); if (node >= 0) goto remove_psci_node; node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0"); if (node >= 0) goto remove_psci_node; remove_psci_node: if (node >= 0) fdt_del_node(blob, node); } else { return; } #endif off = fdt_path_offset(blob, "/cpus"); if (off < 0) { puts("couldn't find /cpus node\n"); return; } fdt_support_default_count_cells(blob, off, &addr_cells, NULL); off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); if (reg) { core_id = fdt_read_number(reg, addr_cells); if (core_id == 0 || (is_core_online(core_id))) { val = spin_tbl_addr; val += id_to_core(core_id) * SPIN_TABLE_ELEM_SIZE; val = cpu_to_fdt64(val); fdt_setprop_string(blob, off, "enable-method", "spin-table"); fdt_setprop(blob, off, "cpu-release-addr", &val, sizeof(val)); } else { debug("skipping offline core\n"); } } else { puts("Warning: found cpu node without reg property\n"); } off = fdt_node_offset_by_prop_value(blob, off, "device_type", "cpu", 4); } fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, *boot_code_size); #if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD) efi_add_memory_map((uintptr_t)&secondary_boot_code, ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, EFI_RESERVED_MEMORY_TYPE, false); #endif }
/* * Flattened Device Tree command, see the help for parameter definitions. */ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (argc < 2) return CMD_RET_USAGE; /* * Set the address of the fdt */ if (strncmp(argv[1], "ad", 2) == 0) { unsigned long addr; int control = 0; struct fdt_header *blob; /* * Set the address [and length] of the fdt. */ argc -= 2; argv += 2; /* Temporary #ifdef - some archs don't have fdt_blob yet */ #ifdef CONFIG_OF_CONTROL if (argc && !strcmp(*argv, "-c")) { control = 1; argc--; argv++; } #endif if (argc == 0) { if (control) blob = (struct fdt_header *)gd->fdt_blob; else blob = working_fdt; if (!blob || !fdt_valid(&blob)) return 1; printf("The address of the fdt is %#08lx\n", control ? (ulong)map_to_sysmem(blob) : getenv_hex("fdtaddr", 0)); return 0; } addr = simple_strtoul(argv[0], NULL, 16); blob = map_sysmem(addr, 0); if (!fdt_valid(&blob)) return 1; if (control) gd->fdt_blob = blob; else set_working_fdt_addr(addr); if (argc >= 2) { int len; int err; /* * Optional new length */ len = simple_strtoul(argv[1], NULL, 16); if (len < fdt_totalsize(blob)) { printf ("New length %d < existing length %d, " "ignoring.\n", len, fdt_totalsize(blob)); } else { /* * Open in place with a new length. */ err = fdt_open_into(blob, blob, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); } } } return CMD_RET_SUCCESS; } if (!working_fdt) { puts( "No FDT memory address configured. Please configure\n" "the FDT address via \"fdt addr <address>\" command.\n" "Aborting!\n"); return CMD_RET_FAILURE; } /* * Move the working_fdt */ if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; if (argc < 4) return CMD_RET_USAGE; /* * Set the address and length of the fdt. */ working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid(&working_fdt)) return 1; newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); /* * If the user specifies a length, use that. Otherwise use the * current length. */ if (argc <= 4) { len = fdt_totalsize(working_fdt); } else { len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(working_fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", len, fdt_totalsize(working_fdt)); return 1; } } /* * Copy to the new location. */ err = fdt_open_into(working_fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } working_fdt = newaddr; /* * Make a new node */ } else if (strncmp(argv[1], "mk", 2) == 0) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ int err; /* * Parameters: Node path, new node to be appended to the path. */ if (argc < 4) return CMD_RET_USAGE; pathp = argv[2]; nodep = argv[3]; nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } err = fdt_add_subnode(working_fdt, nodeoffset, nodep); if (err < 0) { printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); return 1; } /* * Set the value of a property in the working_fdt. */ } else if (argv[1][0] == 's') { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */ static char data[SCRATCHPAD]; /* storage for the property */ int len; /* new length of the property */ int ret; /* return value */ /* * Parameters: Node path, property, optional value. */ if (argc < 4) return CMD_RET_USAGE; pathp = argv[2]; prop = argv[3]; if (argc == 4) { len = 0; } else { ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); if (ret != 0) return ret; } nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); return 1; } /******************************************************************** * Get the value of a property in the working_fdt. ********************************************************************/ } else if (argv[1][0] == 'g') { char *subcmd; /* sub-command */ char *pathp; /* path */ char *prop; /* property */ char *var; /* variable to store result */ int nodeoffset; /* node offset from libfdt */ const void *nodep; /* property node pointer */ int len = 0; /* new length of the property */ /* * Parameters: Node path, property, optional value. */ if (argc < 5) return CMD_RET_USAGE; subcmd = argv[2]; if (argc < 6 && subcmd[0] != 's') return CMD_RET_USAGE; var = argv[3]; pathp = argv[4]; prop = argv[5]; nodeoffset = fdt_path_offset(working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { int reqIndex = -1; int startDepth = fdt_node_depth( working_fdt, nodeoffset); int curDepth = startDepth; int curIndex = -1; int nextNodeOffset = fdt_next_node( working_fdt, nodeoffset, &curDepth); if (subcmd[0] == 'n') reqIndex = simple_strtoul(argv[5], NULL, 16); while (curDepth > startDepth) { if (curDepth == startDepth + 1) curIndex++; if (subcmd[0] == 'n' && curIndex == reqIndex) { const char *nodeName = fdt_get_name( working_fdt, nextNodeOffset, NULL); setenv(var, (char *)nodeName); return 0; } nextNodeOffset = fdt_next_node( working_fdt, nextNodeOffset, &curDepth); if (nextNodeOffset < 0) break; } if (subcmd[0] == 's') { /* get the num nodes at this level */ setenv_ulong(var, curIndex + 1); } else { /* node index not found */ printf("libfdt node not found\n"); return 1; } } else { nodep = fdt_getprop( working_fdt, nodeoffset, prop, &len); if (len == 0) { /* no property value */ setenv(var, ""); return 0; } else if (len > 0) { if (subcmd[0] == 'v') { int ret; ret = fdt_value_setenv(nodep, len, var); if (ret != 0) return ret; } else if (subcmd[0] == 'a') { /* Get address */ char buf[11]; sprintf(buf, "0x%p", nodep); setenv(var, buf); } else if (subcmd[0] == 's') { /* Get size */ char buf[11]; sprintf(buf, "0x%08X", len); setenv(var, buf); } else return CMD_RET_USAGE; return 0; } else { printf("libfdt fdt_getprop(): %s\n", fdt_strerror(len)); return 1; } } /* * Print (recursive) / List (single level) */ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ char *prop; /* property */ int ret; /* return value */ static char root[2] = "/"; /* * list is an alias for print, but limited to 1 level */ if (argv[1][0] == 'l') { depth = 1; } /* * Get the starting path. The root node is an oddball, * the offset is zero and has no name. */ if (argc == 2) pathp = root; else pathp = argv[2]; if (argc > 3) prop = argv[3]; else prop = NULL; ret = fdt_print(pathp, prop, depth); if (ret != 0) return ret; /* * Remove a property/node */ } else if (strncmp(argv[1], "rm", 2) == 0) { int nodeoffset; /* node offset from libfdt */ int err; /* * Get the path. The root node is an oddball, the offset * is zero and has no name. */ nodeoffset = fdt_path_offset (working_fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } /* * Do the delete. A fourth parameter means delete a property, * otherwise delete the node. */ if (argc > 3) { err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); return err; } } /* * Display header info */ } else if (argv[1][0] == 'h') { u32 version = fdt_version(working_fdt); printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), fdt_totalsize(working_fdt)); printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(working_fdt)); printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(working_fdt)); printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(working_fdt)); printf("version:\t\t%d\n", version); printf("last_comp_version:\t%d\n", fdt_last_comp_version(working_fdt)); if (version >= 2) printf("boot_cpuid_phys:\t0x%x\n", fdt_boot_cpuid_phys(working_fdt)); if (version >= 3) printf("size_dt_strings:\t0x%x\n", fdt_size_dt_strings(working_fdt)); if (version >= 17) printf("size_dt_struct:\t\t0x%x\n", fdt_size_dt_struct(working_fdt)); printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(working_fdt)); printf("\n"); /* * Set boot cpu id */ } else if (strncmp(argv[1], "boo", 3) == 0) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); fdt_set_boot_cpuid_phys(working_fdt, tmp); /* * memory command */ } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; addr = simple_strtoull(argv[2], NULL, 16); size = simple_strtoull(argv[3], NULL, 16); err = fdt_fixup_memory(working_fdt, addr, size); if (err < 0) return err; /* * mem reserve commands */ } else if (strncmp(argv[1], "rs", 2) == 0) { if (argv[2][0] == 'p') { uint64_t addr, size; int total = fdt_num_mem_rsv(working_fdt); int j, err; printf("index\t\t start\t\t size\n"); printf("-------------------------------" "-----------------\n"); for (j = 0; j < total; j++) { err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); if (err < 0) { printf("libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); return err; } printf(" %x\t%08x%08x\t%08x%08x\n", j, (u32)(addr >> 32), (u32)(addr & 0xffffffff), (u32)(size >> 32), (u32)(size & 0xffffffff)); } } else if (argv[2][0] == 'a') {
/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /******************************************************************** * Set the address of the fdt ********************************************************************/ if (argv[1][0] == 'a') { /* * Set the address [and length] of the fdt. */ if (argc == 2) { if (!fdt_valid()) { return 1; } printf("The address of the fdt is %p\n", working_fdt); return 0; } working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } if (argc >= 4) { int len; int err; /* * Optional new length */ len = simple_strtoul(argv[3], NULL, 16); if (len < fdt_totalsize(working_fdt)) { printf ("New length %d < existing length %d, " "ignoring.\n", len, fdt_totalsize(working_fdt)); } else { /* * Open in place with a new length. */ err = fdt_open_into(working_fdt, working_fdt, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); } } } /******************************************************************** * Move the working_fdt ********************************************************************/ } else if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /* * Set the address and length of the fdt. */ working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); /* * If the user specifies a length, use that. Otherwise use the * current length. */ if (argc <= 4) { len = fdt_totalsize(working_fdt); } else { len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(working_fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", len, fdt_totalsize(working_fdt)); return 1; } } /* * Copy to the new location. */ err = fdt_open_into(working_fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } working_fdt = newaddr; /******************************************************************** * Make a new node ********************************************************************/ } else if (strncmp(argv[1], "mk", 2) == 0) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ int err; /* * Parameters: Node path, new node to be appended to the path. */ if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } pathp = argv[2]; nodep = argv[3]; nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } err = fdt_add_subnode(working_fdt, nodeoffset, nodep); if (err < 0) { printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); return 1; } /******************************************************************** * Set the value of a property in the working_fdt. ********************************************************************/ } else if (argv[1][0] == 's') { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */ static char data[SCRATCHPAD]; /* storage for the property */ int len; /* new length of the property */ int ret; /* return value */ /* * Parameters: Node path, property, optional value. */ if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } pathp = argv[2]; prop = argv[3]; if (argc == 4) { len = 0; } else { ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); if (ret != 0) return ret; } nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); return 1; } /******************************************************************** * Print (recursive) / List (single level) ********************************************************************/ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ char *prop; /* property */ int ret; /* return value */ static char root[2] = "/"; /* * list is an alias for print, but limited to 1 level */ if (argv[1][0] == 'l') { depth = 1; } /* * Get the starting path. The root node is an oddball, * the offset is zero and has no name. */ if (argc == 2) pathp = root; else pathp = argv[2]; if (argc > 3) prop = argv[3]; else prop = NULL; ret = fdt_print(pathp, prop, depth); if (ret != 0) return ret; /******************************************************************** * Remove a property/node ********************************************************************/ } else if (strncmp(argv[1], "rm", 2) == 0) { int nodeoffset; /* node offset from libfdt */ int err; /* * Get the path. The root node is an oddball, the offset * is zero and has no name. */ nodeoffset = fdt_path_offset (working_fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } /* * Do the delete. A fourth parameter means delete a property, * otherwise delete the node. */ if (argc > 3) { err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); return err; } } /******************************************************************** * Display header info ********************************************************************/ } else if (argv[1][0] == 'h') { u32 version = fdt_version(working_fdt); printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), fdt_totalsize(working_fdt)); printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(working_fdt)); printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(working_fdt)); printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(working_fdt)); printf("version:\t\t%d\n", version); printf("last_comp_version:\t%d\n", fdt_last_comp_version(working_fdt)); if (version >= 2) printf("boot_cpuid_phys:\t0x%x\n", fdt_boot_cpuid_phys(working_fdt)); if (version >= 3) printf("size_dt_strings:\t0x%x\n", fdt_size_dt_strings(working_fdt)); if (version >= 17) printf("size_dt_struct:\t\t0x%x\n", fdt_size_dt_struct(working_fdt)); printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(working_fdt)); printf("\n"); /******************************************************************** * Set boot cpu id ********************************************************************/ } else if (strncmp(argv[1], "boo", 3) == 0) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); fdt_set_boot_cpuid_phys(working_fdt, tmp); /******************************************************************** * memory command ********************************************************************/ } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; #ifdef CFG_64BIT_STRTOUL addr = simple_strtoull(argv[2], NULL, 16); size = simple_strtoull(argv[3], NULL, 16); #else addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[3], NULL, 16); #endif err = fdt_fixup_memory(working_fdt, addr, size); if (err < 0) return err; /******************************************************************** * mem reserve commands ********************************************************************/ } else if (strncmp(argv[1], "rs", 2) == 0) { if (argv[2][0] == 'p') { uint64_t addr, size; int total = fdt_num_mem_rsv(working_fdt); int j, err; printf("index\t\t start\t\t size\n"); printf("-------------------------------" "-----------------\n"); for (j = 0; j < total; j++) { err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); if (err < 0) { printf("libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); return err; } printf(" %x\t%08x%08x\t%08x%08x\n", j, (u32)(addr >> 32), (u32)(addr & 0xffffffff), (u32)(size >> 32), (u32)(size & 0xffffffff)); } } else if (argv[2][0] == 'a') {
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; }
/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /******************************************************************** * Set the address of the fdt ********************************************************************/ if (argv[1][0] == 'a') { /* * Set the address [and length] of the fdt. */ fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } if (argc >= 4) { int len; int err; /* * Optional new length */ len = simple_strtoul(argv[3], NULL, 16); if (len < fdt_totalsize(fdt)) { printf ("New length %d < existing length %d, " "ignoring.\n", len, fdt_totalsize(fdt)); } else { /* * Open in place with a new length. */ err = fdt_open_into(fdt, fdt, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); } } } /******************************************************************** * Move the fdt ********************************************************************/ } else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) { struct fdt_header *newaddr; int len; int err; if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /* * Set the address and length of the fdt. */ fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); /* * If the user specifies a length, use that. Otherwise use the * current length. */ if (argc <= 4) { len = fdt_totalsize(fdt); } else { len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", len, fdt_totalsize(fdt)); return 1; } } /* * Copy to the new location. */ err = fdt_open_into(fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } fdt = newaddr; /******************************************************************** * Make a new node ********************************************************************/ } else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ int err; /* * Parameters: Node path, new node to be appended to the path. */ if (argc < 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } pathp = argv[2]; nodep = argv[3]; nodeoffset = fdt_path_offset (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } err = fdt_add_subnode(fdt, nodeoffset, nodep); if (err < 0) { printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); return 1; } /******************************************************************** * Set the value of a property in the fdt. ********************************************************************/ } else if (argv[1][0] == 's') { char *pathp; /* path */ char *prop; /* property */ char *newval; /* value from the user (as a string) */ int nodeoffset; /* node offset from libfdt */ static char data[SCRATCHPAD]; /* storage for the property */ int len; /* new length of the property */ int ret; /* return value */ /* * Parameters: Node path, property, value. */ if (argc < 5) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } pathp = argv[2]; prop = argv[3]; newval = argv[4]; nodeoffset = fdt_path_offset (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } ret = fdt_parse_prop(pathp, prop, newval, data, &len); if (ret != 0) return ret; ret = fdt_setprop(fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); return 1; } /******************************************************************** * Print (recursive) / List (single level) ********************************************************************/ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) { int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ char *prop; /* property */ int ret; /* return value */ static char root[2] = "/"; /* * list is an alias for print, but limited to 1 level */ if (argv[1][0] == 'l') { depth = 1; } /* * Get the starting path. The root node is an oddball, * the offset is zero and has no name. */ if (argc == 2) pathp = root; else pathp = argv[2]; if (argc > 3) prop = argv[3]; else prop = NULL; ret = fdt_print(pathp, prop, depth); if (ret != 0) return ret; /******************************************************************** * Remove a property/node ********************************************************************/ } else if (argv[1][0] == 'r') { int nodeoffset; /* node offset from libfdt */ int err; /* * Get the path. The root node is an oddball, the offset * is zero and has no name. */ nodeoffset = fdt_path_offset (fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset)); return 1; } /* * Do the delete. A fourth parameter means delete a property, * otherwise delete the node. */ if (argc > 3) { err = fdt_delprop(fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); return err; } } } #ifdef CONFIG_OF_BOARD_SETUP /* Call the board-specific fixup routine */ else if (argv[1][0] == 'b') ft_board_setup(fdt, gd->bd); #endif /* Create a chosen node */ else if (argv[1][0] == 'c') fdt_chosen(fdt, 0, 0, 1); #ifdef CONFIG_OF_HAS_UBOOT_ENV /* Create a u-boot-env node */ else if (argv[1][0] == 'e') fdt_env(fdt); #endif #ifdef CONFIG_OF_HAS_BD_T /* Create a bd_t node */ else if (argv[1][0] == 'b') fdt_bd_t(fdt); #endif else { /* Unrecognized command */ printf ("Usage:\n%s\n", cmdtp->usage); return 1; } return 0; }
/* * update crypto node properties to a specified revision of the SEC * called with sec_rev == 0 if not on an E processor */ #if CONFIG_SYS_FSL_SEC_COMPAT == 2 /* SEC 2.x/3.x */ void fdt_fixup_crypto_node(void *blob, int sec_rev) { const struct sec_rev_prop { u32 sec_rev; u32 num_channels; u32 channel_fifo_len; u32 exec_units_mask; u32 descriptor_types_mask; } sec_rev_prop_list [] = { { 0x0200, 4, 24, 0x07e, 0x01010ebf }, /* SEC 2.0 */ { 0x0201, 4, 24, 0x0fe, 0x012b0ebf }, /* SEC 2.1 */ { 0x0202, 1, 24, 0x04c, 0x0122003f }, /* SEC 2.2 */ { 0x0204, 4, 24, 0x07e, 0x012b0ebf }, /* SEC 2.4 */ { 0x0300, 4, 24, 0x9fe, 0x03ab0ebf }, /* SEC 3.0 */ { 0x0301, 4, 24, 0xbfe, 0x03ab0ebf }, /* SEC 3.1 */ { 0x0303, 4, 24, 0x97c, 0x03a30abf }, /* SEC 3.3 */ }; char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) * sizeof("fsl,secX.Y")]; int crypto_node, sec_idx, err; char *p; u32 val; /* locate crypto node based on lowest common compatible */ crypto_node = fdt_node_offset_by_compatible(blob, -1, "fsl,sec2.0"); if (crypto_node == -FDT_ERR_NOTFOUND) return; /* delete it if not on an E-processor */ if (crypto_node > 0 && !sec_rev) { fdt_del_node(blob, crypto_node); return; } /* else we got called for possible uprev */ for (sec_idx = 0; sec_idx < ARRAY_SIZE(sec_rev_prop_list); sec_idx++) if (sec_rev_prop_list[sec_idx].sec_rev == sec_rev) break; if (sec_idx == ARRAY_SIZE(sec_rev_prop_list)) { puts("warning: unknown SEC revision number\n"); return; } val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].num_channels); err = fdt_setprop(blob, crypto_node, "fsl,num-channels", &val, 4); if (err < 0) printf("WARNING: could not set crypto property: %s\n", fdt_strerror(err)); val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].descriptor_types_mask); err = fdt_setprop(blob, crypto_node, "fsl,descriptor-types-mask", &val, 4); if (err < 0) printf("WARNING: could not set crypto property: %s\n", fdt_strerror(err)); val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].exec_units_mask); err = fdt_setprop(blob, crypto_node, "fsl,exec-units-mask", &val, 4); if (err < 0) printf("WARNING: could not set crypto property: %s\n", fdt_strerror(err)); val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].channel_fifo_len); err = fdt_setprop(blob, crypto_node, "fsl,channel-fifo-len", &val, 4); if (err < 0) printf("WARNING: could not set crypto property: %s\n", fdt_strerror(err)); val = 0; while (sec_idx >= 0) { p = compat_strlist + val; val += sprintf(p, "fsl,sec%d.%d", (sec_rev_prop_list[sec_idx].sec_rev & 0xff00) >> 8, sec_rev_prop_list[sec_idx].sec_rev & 0x00ff) + 1; sec_idx--; } err = fdt_setprop(blob, crypto_node, "compatible", &compat_strlist, val); if (err < 0) printf("WARNING: could not set crypto property: %s\n", fdt_strerror(err)); }
int ft_board_setup(void *blob, bd_t *bd) { phys_addr_t base; phys_size_t size; #if defined(CONFIG_TARGET_P1020RDB_PD) || defined(CONFIG_TARGET_P1020RDB_PC) const char *soc_usb_compat = "fsl-usb2-dr"; int usb_err, usb1_off, usb2_off; #endif #if defined(CONFIG_SDCARD) || defined(CONFIG_SPIFLASH) int err; #endif ft_cpu_setup(blob, bd); base = env_get_bootm_low(); size = env_get_bootm_size(); fdt_fixup_memory(blob, (u64)base, (u64)size); FT_FSL_PCI_SETUP; #ifdef CONFIG_QE do_fixup_by_compat(blob, "fsl,qe", "status", "okay", sizeof("okay"), 0); #if defined(CONFIG_TARGET_P1025RDB) || defined(CONFIG_TARGET_P1021RDB) fdt_board_fixup_qe_pins(blob); #endif #endif #if defined(CONFIG_HAS_FSL_DR_USB) fsl_fdt_fixup_dr_usb(blob, bd); #endif #if defined(CONFIG_SDCARD) || defined(CONFIG_SPIFLASH) /* Delete eLBC node as it is muxed with USB2 controller */ if (hwconfig("usb2")) { const char *soc_elbc_compat = "fsl,p1020-elbc"; int off = fdt_node_offset_by_compatible(blob, -1, soc_elbc_compat); if (off < 0) { printf("WARNING: could not find compatible node %s\n", soc_elbc_compat); return off; } err = fdt_del_node(blob, off); if (err < 0) { printf("WARNING: could not remove %s\n", soc_elbc_compat); return err; } return 0; } #endif #if defined(CONFIG_TARGET_P1020RDB_PD) || defined(CONFIG_TARGET_P1020RDB_PC) /* Delete USB2 node as it is muxed with eLBC */ usb1_off = fdt_node_offset_by_compatible(blob, -1, soc_usb_compat); if (usb1_off < 0) { printf("WARNING: could not find compatible node %s\n", soc_usb_compat); return usb1_off; } usb2_off = fdt_node_offset_by_compatible(blob, usb1_off, soc_usb_compat); if (usb2_off < 0) { printf("WARNING: could not find compatible node %s\n", soc_usb_compat); return usb2_off; } usb_err = fdt_del_node(blob, usb2_off); if (usb_err < 0) { printf("WARNING: could not remove %s\n", soc_usb_compat); return usb_err; } #endif return 0; }
/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { char op; if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /* * Figure out which subcommand was given */ op = argv[1][0]; /******************************************************************** * Set the address of the fdt ********************************************************************/ if (op == 'a') { /* * Set the address [and length] of the fdt. */ fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } if (argc >= 4) { int len; int err; /* * Optional new length */ len = simple_strtoul(argv[3], NULL, 16); if (len < fdt_totalsize(fdt)) { printf ("New length %d < existing length %d, ignoring.\n", len, fdt_totalsize(fdt)); } else { /* * Open in place with a new length. */ err = fdt_open_into(fdt, fdt, len); if (err != 0) { printf ("libfdt: %s\n", fdt_strerror(err)); } } } /******************************************************************** * Move the fdt ********************************************************************/ } else if (op == 'm' && argv[1][1] == 'o') { struct fdt_header *newaddr; int len; int err; if (argc != 5) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /* * Set the address and length of the fdt. */ fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16); len = simple_strtoul(argv[4], NULL, 16); if (len < fdt_totalsize(fdt)) { printf ("New length %d < existing length %d, aborting.\n", len, fdt_totalsize(fdt)); return 1; } /* * Copy to the new location. */ err = fdt_open_into(fdt, newaddr, len); if (err != 0) { printf ("libfdt: %s\n", fdt_strerror(err)); return 1; } fdt = newaddr; /******************************************************************** * mknode ********************************************************************/ } else if (op == 'm' && argv[1][1] == 'k') { char *pathp = argv[2]; char *node = argv[3]; int nodeoffset; if (argc != 4) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } /* * See if the node already exists */ if (strcmp(pathp, "/") == 0) nodeoffset = 0; else nodeoffset = fdt_path_offset (fdt, pathp); if (nodeoffset < 0) { printf("parent node %s doesn't exist\n", pathp); return 1; } /* * Create the new node */ nodeoffset = fdt_add_subnode(fdt, nodeoffset, node); if (nodeoffset < 0) { printf("libfdt: %s\n", fdt_strerror(nodeoffset)); return 1; } /******************************************************************** * Set the value of a node in the fdt. ********************************************************************/ } else if (op == 's') { char *pathp; /* path */ char *prop; /* property */ struct fdt_property *nodep; /* node struct pointer */ char *newval; /* value from the user (as a string) */ char *vp; /* temporary value pointer */ char *cp; /* temporary char pointer */ int nodeoffset; /* node offset from libfdt */ int len; /* new length of the property */ int oldlen; /* original length of the property */ unsigned long tmp; /* holds converted values */ int ret; /* return value */ /* * Parameters: Node path, property, value. */ if (argc < 5) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } pathp = argv[2]; prop = argv[3]; newval = argv[4]; if (strcmp(pathp, "/") == 0) { nodeoffset = 0; } else { nodeoffset = fdt_path_offset (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt: %s\n", fdt_strerror(nodeoffset)); return 1; } } nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen); if (oldlen == 0) { /* * The specified property has no value */ printf("%s has no value, cannot set one (yet).\n", prop); return 1; } else { /* * Convert the new property */ vp = data; if (*newval == '<') { /* * Bigger values than bytes. */ len = 0; newval++; while ((*newval != '>') && (*newval != '\0')) { cp = newval; tmp = simple_strtoul(cp, &newval, 16); if ((newval - cp) <= 2) { *vp = tmp & 0xFF; vp += 1; len += 1; } else if ((newval - cp) <= 4) { *(uint16_t *)vp = __cpu_to_be16(tmp); vp += 2; len += 2; } else if ((newval - cp) <= 8) { *(uint32_t *)vp = __cpu_to_be32(tmp); vp += 4; len += 4; } else { printf("Sorry, I could not convert \"%s\"\n", cp); return 1; } while (*newval == ' ') newval++; } if (*newval != '>') { printf("Unexpected character '%c'\n", *newval); return 1; } } else if (*newval == '[') { /* * Byte stream. Convert the values. */ len = 0; newval++; while ((*newval != ']') && (*newval != '\0')) { tmp = simple_strtoul(newval, &newval, 16); *vp++ = tmp & 0xFF; len++; while (*newval == ' ') newval++; } if (*newval != ']') { printf("Unexpected character '%c'\n", *newval); return 1; } } else { /* * Assume it is a string. Copy it into our data area for * convenience (including the terminating '\0'). */ len = strlen(newval) + 1; strcpy(data, newval); } ret = fdt_setprop(fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt %s\n", fdt_strerror(ret)); return 1; } } /******************************************************************** * Print (recursive) / List (single level) ********************************************************************/ } else if ((op == 'p') || (op == 'l')) { /* * Recursively print (a portion of) the fdt. */ static int offstack[MAX_LEVEL]; static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; int depth = MAX_LEVEL; /* how deep to print */ char *pathp; /* path */ char *prop; /* property */ void *nodep; /* property node pointer */ int nodeoffset; /* node offset from libfdt */ int nextoffset; /* next node offset from libfdt */ uint32_t tag; /* tag */ int len; /* length of the property */ int level = 0; /* keep track of nesting level */ /* * list is an alias for print, but limited to 1 level */ if (op == 'l') { depth = 1; } /* * Get the starting path. The root node is an oddball, * the offset is zero and has no name. */ pathp = argv[2]; if (argc > 3) prop = argv[3]; else prop = NULL; if (strcmp(pathp, "/") == 0) { nodeoffset = 0; printf("/"); } else { nodeoffset = fdt_path_offset (fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt %s\n", fdt_strerror(nodeoffset)); return 1; } } /* * The user passed in a property as well as node path. Print only * the given property and then return. */ if (prop) { nodep = fdt_getprop (fdt, nodeoffset, prop, &len); if (len == 0) { printf("%s %s\n", pathp, prop); /* no property value */ return 0; } else if (len > 0) { printf("%s=", prop); print_data (nodep, len); printf("\n"); return 0; } else { printf ("libfdt %s\n", fdt_strerror(len)); return 1; } } /* * The user passed in a node path and no property, print the node * and all subnodes. */ offstack[0] = nodeoffset; while(level >= 0) { tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp); switch(tag) { case FDT_BEGIN_NODE: if(level <= depth) printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp); level++; offstack[level] = nodeoffset; if (level >= MAX_LEVEL) { printf("Aaaiii <splat> nested too deep.\n"); return 1; } break; case FDT_END_NODE: level--; if(level <= depth) printf("%s};\n", &tabs[MAX_LEVEL - level]); if (level == 0) { level = -1; /* exit the loop */ } break; case FDT_PROP: nodep = fdt_getprop (fdt, offstack[level], pathp, &len); if (len < 0) { printf ("libfdt %s\n", fdt_strerror(len)); return 1; } else if (len == 0) { /* the property has no value */ if(level <= depth) printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp); } else { if(level <= depth) { printf("%s%s=", &tabs[MAX_LEVEL - level], pathp); print_data (nodep, len); printf(";\n"); } } break; case FDT_NOP: break; case FDT_END: return 1; default: if(level <= depth) printf("Unknown tag 0x%08X\n", tag); return 1; } nodeoffset = nextoffset; } /******************************************************************** * Remove a property/node ********************************************************************/ } else if (op == 'r') { int nodeoffset; /* node offset from libfdt */ int err; /* * Get the path. The root node is an oddball, the offset * is zero and has no name. */ if (strcmp(argv[2], "/") == 0) { nodeoffset = 0; } else { nodeoffset = fdt_path_offset (fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. */ printf ("libfdt %s\n", fdt_strerror(nodeoffset)); return 1; } } /* * Do the delete. A fourth parameter means delete a property, * otherwise delete the node. */ if (argc > 3) { err = fdt_delprop(fdt, nodeoffset, argv[3]); if (err < 0) { printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); return err; } } else { err = fdt_del_node(fdt, nodeoffset); if (err < 0) { printf("fdt_del_node libfdt: %s\n", fdt_strerror(err)); return err; } } /******************************************************************** * Create a chosen node ********************************************************************/ } else if (op == 'c') { fdt_chosen(fdt, 0, 0, 1); #ifdef CONFIG_OF_HAS_UBOOT_ENV /******************************************************************** * Create a u-boot-env node ********************************************************************/ } else if (op == 'e') { fdt_env(fdt); #endif #ifdef CONFIG_OF_HAS_BD_T /******************************************************************** * Create a bd_t node ********************************************************************/ } else if (op == 'b') { fdt_bd_t(fdt); #endif /******************************************************************** * Unrecognized command ********************************************************************/ } else { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } return 0; }
void ft_board_setup(void *blob, bd_t *bd) { const char *soc_usb_compat = "fsl-usb2-dr"; int err, usb1_off, usb2_off; phys_addr_t base; phys_size_t size; ft_cpu_setup(blob, bd); base = getenv_bootm_low(); size = getenv_bootm_size(); #if defined(CONFIG_PCI) ft_pci_board_setup(blob); #endif /* #if defined(CONFIG_PCI) */ fdt_fixup_memory(blob, (u64)base, (u64)size); #if defined(CONFIG_HAS_FSL_DR_USB) fdt_fixup_dr_usb(blob, bd); #endif #if defined(CONFIG_SDCARD) || defined(CONFIG_SPIFLASH) /* Delete eLBC node as it is muxed with USB2 controller */ if (hwconfig("usb2")) { const char *soc_elbc_compat = "fsl,p1020-elbc"; int off = fdt_node_offset_by_compatible(blob, -1, soc_elbc_compat); if (off < 0) { printf("WARNING: could not find compatible node" " %s: %s.\n", soc_elbc_compat, fdt_strerror(off)); return; } err = fdt_del_node(blob, off); if (err < 0) { printf("WARNING: could not remove %s: %s.\n", soc_elbc_compat, fdt_strerror(err)); } return; } #endif /* Delete USB2 node as it is muxed with eLBC */ usb1_off = fdt_node_offset_by_compatible(blob, -1, soc_usb_compat); if (usb1_off < 0) { printf("WARNING: could not find compatible node" " %s: %s.\n", soc_usb_compat, fdt_strerror(usb1_off)); return; } usb2_off = fdt_node_offset_by_compatible(blob, usb1_off, soc_usb_compat); if (usb2_off < 0) { printf("WARNING: could not find compatible node" " %s: %s.\n", soc_usb_compat, fdt_strerror(usb2_off)); return; } err = fdt_del_node(blob, usb2_off); if (err < 0) printf("WARNING: could not remove %s: %s.\n", soc_usb_compat, fdt_strerror(err)); }
int fdt_env(void *fdt) { int nodeoffset; int err; int k, nxt; int i; static char tmpenv[256]; err = fdt_check_header(fdt); if (err < 0) { printf("fdt_env: %s\n", fdt_strerror(err)); return err; } /* * See if we already have a "u-boot-env" node, delete it if so. * Then create a new empty node. */ nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); if (nodeoffset >= 0) { err = fdt_del_node(fdt, nodeoffset); if (err < 0) { printf("fdt_env: %s\n", fdt_strerror(err)); return err; } } /* * Create a new node "/u-boot-env" (offset 0 is root level) */ nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); if (nodeoffset < 0) { printf("WARNING: could not create /u-boot-env %s.\n", fdt_strerror(nodeoffset)); return nodeoffset; } for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { char *s, *lval, *rval; /* * Find the end of the name=definition */ for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) ; s = tmpenv; for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) *s++ = env_get_char(k); *s++ = '\0'; lval = tmpenv; /* * Find the first '=': it separates the name from the value */ s = strchr(tmpenv, '='); if (s != NULL) { *s++ = '\0'; rval = s; } else continue; err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); if (err < 0) { printf("WARNING: could not set %s %s.\n", lval, fdt_strerror(err)); return err; } } return 0; }
static int fdt_wrapper_del_node(const void *devp) { return fdt_del_node(fdt, devp_offset(devp)); }