int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { int pdepth = 0, p = 0; int offset, depth, namelen; const char *name; FDT_CHECK_HEADER(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { while (pdepth > depth) { do { p--; } while (buf[p-1] != '/'); pdepth--; } if (pdepth >= depth) { name = fdt_get_name(fdt, offset, &namelen); if (!name) return namelen; if ((p + namelen + 1) <= buflen) { memcpy(buf + p, name, namelen); p += namelen; buf[p++] = '/'; pdepth++; } } if (offset == nodeoffset) { if (pdepth < (depth + 1)) return -FDT_ERR_NOSPACE; if (p > 1) /* special case so that root path is "/", not "" */ p--; buf[p] = '\0'; return 0; } } if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) return -FDT_ERR_BADOFFSET; else if (offset == -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; return offset; /* error from fdt_next_node() */ }
/** * fit_all_image_verify - verify data intergity for all images * @fit: pointer to the FIT format image header * * fit_all_image_verify() goes over all images in the FIT and * for every images checks if all it's hashes are valid. * * returns: * 1, if all hashes of all images are valid * 0, otherwise (or on error) */ int fit_all_image_verify(const void *fit) { int images_noffset; int noffset; int ndepth; int count; /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { printf("Can't find images parent node '%s' (%s)\n", FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return 0; } /* Process all image subnodes, check hashes for each */ printf("## Checking hash(es) for FIT Image at %08lx ...\n", (ulong)fit); for (ndepth = 0, count = 0, noffset = fdt_next_node(fit, images_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* * Direct child node of the images parent node, * i.e. component image node. */ printf(" Hash(es) for Image %u (%s): ", count, fit_get_name(fit, noffset, NULL)); count++; if (!fit_image_verify(fit, noffset)) return 0; printf("\n"); } } return 1; }
int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) { int offset, err; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if * that didn't find what we want, we scan over them again * making our way to the next node. Still it's the easiest to * implement approach; performance can come later. */ for (offset = fdt_next_node(fdt, startoffset, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { err = fdt_node_check_compatible(fdt, offset, compatible); if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) return err; else if (err == 0) return offset; } return offset; /* error from fdt_next_node() */ }
int fdtdec_next_compatible_subnode(const void *blob, int node, enum fdt_compat_id id, int *depthp) { do { node = fdt_next_node(blob, node, depthp); } while (*depthp > 1); /* If this is a direct subnode, and compatible, return it */ if (*depthp == 1 && 0 == fdt_node_check_compatible( blob, node, compat_names[id])) return node; return -FDT_ERR_NOTFOUND; }
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in * fdt_get_phandle(), then if that didn't find what * we want, we scan over them again making our way to the next * node. Still it's the easiest to implement approach; * performance can come later. */ for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { if (fdt_get_phandle(fdt, offset) == phandle) return offset; } return offset; /* error from fdt_next_node() */ }
void * fdt_find_node(char *name) { void *node = fdt_next_node(0); const char *p = name; if (!tree_inited) return NULL; if (*p != '/') return NULL; while (*p) { void *child; const char *q; while (*p == '/') p++; if (*p == 0) return node; q = strchr(p, '/'); if (q == NULL) q = p + strlen(p); for (child = fdt_child_node(node); child; child = fdt_next_node(child)) { if (strncmp(p, fdt_node_name(child), q - p) == 0) { node = child; break; } } p = q; } return node; }
/* * Apply all fragments to main DTB */ static int fdt_overlay_apply_fragments(void *main_fdtp, void *overlay_fdtp) { int o, depth; o = fdt_path_offset(overlay_fdtp, "/"); for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(overlay_fdtp, o, &depth)) { if (depth != 1) continue; fdt_apply_fragment(main_fdtp, overlay_fdtp, o); } return (0); }
int fdt_next_subnode(const void *fdt, int offset) { int depth = 1; /* * With respect to the parent, the depth of the next subnode will be * the same as the last. */ do { offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth < 1) return -FDT_ERR_NOTFOUND; } while (depth > 1); return offset; }
void fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq) { int lo, o = 0, o2, maxo = 0, depth; const uint32_t zero = 0; /* We want to modify every subnode of /cpus */ o = fdt_path_offset(fdtp, "/cpus"); if (o < 0) return; /* maxo should contain offset of node next to /cpus */ depth = 0; maxo = o; while (depth != -1) maxo = fdt_next_node(fdtp, maxo, &depth); /* Find CPU frequency properties */ o = fdt_node_offset_by_prop_value(fdtp, o, "clock-frequency", &zero, sizeof(uint32_t)); o2 = fdt_node_offset_by_prop_value(fdtp, o, "bus-frequency", &zero, sizeof(uint32_t)); lo = MIN(o, o2); while (o != -FDT_ERR_NOTFOUND && o2 != -FDT_ERR_NOTFOUND) { o = fdt_node_offset_by_prop_value(fdtp, lo, "clock-frequency", &zero, sizeof(uint32_t)); o2 = fdt_node_offset_by_prop_value(fdtp, lo, "bus-frequency", &zero, sizeof(uint32_t)); /* We're only interested in /cpus subnode(s) */ if (lo > maxo) break; fdt_setprop_inplace_cell(fdtp, lo, "clock-frequency", (uint32_t)cpufreq); fdt_setprop_inplace_cell(fdtp, lo, "bus-frequency", (uint32_t)busfreq); lo = MIN(o, o2); } }
/* * Get max phandle */ static uint32_t fdt_max_phandle(void *fdtp) { int o, depth; uint32_t max_phandle, phandle; depth = 1; o = fdt_path_offset(fdtp, "/"); max_phandle = fdt_get_phandle(fdtp, o); for (depth = 0; (o >= 0) && (depth >= 0); o = fdt_next_node(fdtp, o, &depth)) { phandle = fdt_get_phandle(fdtp, o); if (max_phandle < phandle) max_phandle = phandle; } return max_phandle; }
int dm_test_main(const char *test_name) { struct dm_test *tests = ll_entry_start(struct dm_test, dm_test); const int n_ents = ll_entry_count(struct dm_test, dm_test); struct dm_test_state *dms = &global_test_state; struct dm_test *test; /* * If we have no device tree, or it only has a root node, then these * tests clearly aren't going to work... */ if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { puts("Please run with test device tree:\n" " dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb\n" " ./u-boot -d test/dm/test.dtb\n"); ut_assert(gd->fdt_blob); } if (!test_name) printf("Running %d driver model tests\n", n_ents); for (test = tests; test < tests + n_ents; test++) { if (test_name && strcmp(test_name, test->name)) continue; printf("Test: %s\n", test->name); ut_assertok(dm_test_init(dms)); dms->start = mallinfo(); if (test->flags & DM_TESTF_SCAN_PDATA) ut_assertok(dm_scan_platdata(false)); if (test->flags & DM_TESTF_PROBE_TEST) ut_assertok(do_autoprobe(dms)); if (test->flags & DM_TESTF_SCAN_FDT) ut_assertok(dm_scan_fdt(gd->fdt_blob, false)); if (test->func(dms)) break; ut_assertok(dm_test_destroy(dms)); } printf("Failures: %d\n", dms->fail_count); return 0; }
int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { int depth; FDT_CHECK_HEADER(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); offset = fdt_next_node(fdt, offset, &depth)) if ((depth == 1) && _fdt_nodename_eq(fdt, offset, name, namelen)) return offset; if (depth < 0) return -FDT_ERR_NOTFOUND; return offset; /* error */ }
static int dt_add_psci_cpu_enable_methods(void *fdt) { int offs = 0; while (1) { offs = fdt_next_node(fdt, offs, NULL); if (offs < 0) break; if (fdt_getprop(fdt, offs, "enable-method", NULL)) continue; /* already set */ if (check_node_compat_prefix(fdt, offs, "arm,cortex-a")) continue; /* no compatible */ if (fdt_setprop_string(fdt, offs, "enable-method", "psci")) return -1; /* Need to restart scanning as offsets may have changed */ offs = 0; } return 0; }
/** * Find EMC tables for the given ram code. * * The tegra EMC binding has two options, one using the ram code and one not. * We detect which is in use by looking for the nvidia,use-ram-code property. * If this is not present, then the EMC tables are directly below 'node', * otherwise we select the correct emc-tables subnode based on the 'ram_code' * value. * * @param blob Device tree blob * @param node EMC node (nvidia,tegra20-emc compatible string) * @param ram_code RAM code to select (0-3, or -1 if unknown) * @return 0 if ok, otherwise a -ve ERR_ code (see enum above) */ static int find_emc_tables(const void *blob, int node, int ram_code) { int need_ram_code; int depth; int offset; /* If we are using RAM codes, scan through the tables for our code */ need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code"); if (!need_ram_code) return node; if (ram_code == -1) { debug("%s: RAM code required but not supplied\n", __func__); return ERR_NO_RAM_CODE; } offset = node; depth = 0; do { /* * Sadly there is no compatible string so we cannot use * fdtdec_next_compatible_subnode(). */ offset = fdt_next_node(blob, offset, &depth); if (depth <= 0) break; /* Make sure this is a direct subnode */ if (depth != 1) continue; if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL))) continue; if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1) == ram_code) return offset; } while (1); debug("%s: Could not find tables for RAM code %d\n", __func__, ram_code); return ERR_RAM_CODE_NOT_FOUND; }
int __octeon_spi_board_initialize(void) { int i; int nodeoffset, next_nodeoffset; const void *nodep; u32 *pgpio_handle; int gpio_offset; int phandle; int max_spi = 2; u32 tag; int level = 0; debug("%s: Entry\n", __func__); if (!octeon_has_feature(OCTEON_FEATURE_SPI)) return -1; nodeoffset = fdt_path_offset(gd->fdt_blob, "/soc/spi"); if (nodeoffset < 0) { debug("SPI interface not found in device tree\n"); return -1; } if (fdt_node_check_compatible(gd->fdt_blob, nodeoffset, "cavium,octeon-3010-spi")) { puts("Incompatible SPI interface type\n"); return -1; } while ((next_nodeoffset = fdt_next_node(gd->fdt_blob, nodeoffset, &level)) > 0) { if (level < 0) break; if (level > 1) continue; if (fdt_node_check_compatible(gd->fdt_blob, next_nodeoffset, "spi-flash")) { } } }
/* * 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); } }
/** * device_tree_for_each_node - iterate over all device tree nodes * @fdt: flat device tree. * @func: function to call for each node. * @data: data to pass to @func. * * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. * * Returns 0 if all nodes were iterated over successfully. If @func * returns a value different from 0, that value is returned immediately. */ int __init device_tree_for_each_node(const void *fdt, device_tree_node_func func, void *data) { int node; int depth; u32 address_cells[DEVICE_TREE_MAX_DEPTH]; u32 size_cells[DEVICE_TREE_MAX_DEPTH]; int ret; for ( node = 0, depth = 0; node >=0 && depth >= 0; node = fdt_next_node(fdt, node, &depth) ) { const char *name = fdt_get_name(fdt, node, NULL); u32 as, ss; if ( depth >= DEVICE_TREE_MAX_DEPTH ) { printk("Warning: device tree node `%s' is nested too deep\n", name); continue; } as = depth > 0 ? address_cells[depth-1] : 0; ss = depth > 0 ? size_cells[depth-1] : 0; address_cells[depth] = device_tree_get_u32(fdt, node, "#address-cells", as); size_cells[depth] = device_tree_get_u32(fdt, node, "#size-cells", ss); ret = func(fdt, node, name, depth, as, ss, data); if ( ret != 0 ) 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); } }
/* * 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') {
static int ait_menu_check_image(void) { char *s; unsigned long fit_addr; void *addr; int format; char *desc; char *subtype; int images_noffset; int noffset; int ndepth; int count = 0; int ret; int i; int found_uboot = -1; int found_ramdisk = -1; memset(imgs, 0, sizeof(imgs)); s = getenv("fit_addr_r"); fit_addr = s ? (unsigned long)simple_strtol(s, NULL, 16) : \ CONFIG_BOARD_IMG_ADDR_R; addr = (void *)fit_addr; /* check if it is a FIT image */ format = genimg_get_format(addr); if (format != IMAGE_FORMAT_FIT) return -EINVAL; if (!fit_check_format(addr)) return -EINVAL; /* print the FIT description */ ret = fit_get_desc(addr, 0, &desc); printf("FIT description: "); if (ret) printf("unavailable\n"); else printf("%s\n", desc); /* find images */ images_noffset = fdt_path_offset(addr, FIT_IMAGES_PATH); if (images_noffset < 0) { printf("Can't find images parent node '%s' (%s)\n", FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return -EINVAL; } /* Process its subnodes, print out component images details */ for (ndepth = 0, count = 0, noffset = fdt_next_node(addr, images_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(addr, noffset, &ndepth)) { if (ndepth == 1) { /* * Direct child node of the images parent node, * i.e. component image node. */ printf("Image %u (%s)\n", count, fit_get_name(addr, noffset, NULL)); fit_image_print(addr, noffset, ""); fit_image_get_type(addr, noffset, &imgs[count].type); /* Mandatory properties */ ret = fit_get_desc(addr, noffset, &desc); printf("Description: "); if (ret) printf("unavailable\n"); else printf("%s\n", desc); ret = fit_get_subtype(addr, noffset, &subtype); printf("Subtype: "); if (ret) { printf("unavailable\n"); } else { imgs[count].subtype = ait_subtype_nr(subtype); printf("%s %d\n", subtype, imgs[count].subtype); } sprintf(imgs[count].desc, "%s", desc); ret = fit_image_get_data(addr, noffset, &imgs[count].data, &imgs[count].size); printf("Data Size: "); if (ret) printf("unavailable\n"); else genimg_print_size(imgs[count].size); printf("Data @ %p\n", imgs[count].data); count++; } } for (i = 0; i < count; i++) { if (imgs[i].subtype == FIT_SUBTYPE_UBOOT_IMAGE) found_uboot = i; if (imgs[i].type == IH_TYPE_RAMDISK) { found_ramdisk = i; imgs[i].subtype = FIT_SUBTYPE_RAMDISK_IMAGE; } } /* dvn_* env var update, if the FIT descriptors are different */ if (found_uboot >= 0) { s = getenv("dvn_boot_vers"); if (s) { ret = strcmp(s, imgs[found_uboot].desc); if (ret != 0) { setenv("x_dvn_boot_vers", imgs[found_uboot].desc); } else { found_uboot = -1; printf("no new uboot version\n"); } } else { setenv("dvn_boot_vers", imgs[found_uboot].desc); } } if (found_ramdisk >= 0) { s = getenv("dvn_app_vers"); if (s) { ret = strcmp(s, imgs[found_ramdisk].desc); if (ret != 0) { setenv("x_dvn_app_vers", imgs[found_ramdisk].desc); } else { found_ramdisk = -1; printf("no new ramdisk version\n"); } } else { setenv("dvn_app_vers", imgs[found_ramdisk].desc); } } if ((found_uboot == -1) && (found_ramdisk == -1)) return -EINVAL; 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; }
/** * unflatten_dt_node - Alloc and populate a device_node from the flat tree * @blob: The parent device tree blob * @mem: Memory chunk to use for allocating device nodes and properties * @p: pointer to node in flat tree * @dad: Parent struct device_node * @allnextpp: pointer to ->allnext from last allocated device_node * @fpsize: Size of the node path up at the current depth. */ static void * unflatten_dt_node(void *blob, void *mem, int *poffset, struct device_node *dad, struct device_node ***allnextpp, unsigned long fpsize) { const __be32 *p; struct device_node *np; struct property *pp, **prev_pp = NULL; const char *pathp; unsigned int l, allocl; static int depth = 0; int old_depth; int offset; int has_name = 0; int new_format = 0; pathp = fdt_get_name(blob, *poffset, &l); if (!pathp) return mem; allocl = l++; /* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild * it later. We detect this because the first character of the name is * not '/'. */ if ((*pathp) != '/') { new_format = 1; if (fpsize == 0) { /* root node: special case. fpsize accounts for path * plus terminating zero. root node only has '/', so * fpsize should be 2, but we want to avoid the first * level nodes to have two '/' so we use fpsize 1 here */ fpsize = 1; allocl = 2; l = 1; pathp = ""; } else { /* account for '/' and path size minus terminal 0 * already in 'l' */ fpsize += l; allocl = fpsize; } } np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node)); if (allnextpp) { char *fn; of_node_init(np); np->full_name = fn = ((char *)np) + sizeof(*np); if (new_format) { /* rebuild full path for new format */ if (dad && dad->parent) { strcpy(fn, dad->full_name); #ifdef DEBUG if ((strlen(fn) + l + 1) != allocl) { pr_debug("%s: p: %d, l: %d, a: %d\n", pathp, (int)strlen(fn), l, allocl); } #endif fn += strlen(fn); } *(fn++) = '/'; } memcpy(fn, pathp, l); prev_pp = &np->properties; **allnextpp = np; *allnextpp = &np->allnext; if (dad != NULL) { np->parent = dad; /* we temporarily use the next field as `last_child'*/ if (dad->next == NULL) dad->child = np; else dad->next->sibling = np; dad->next = np; } } /* process properties */ for (offset = fdt_first_property_offset(blob, *poffset); (offset >= 0); (offset = fdt_next_property_offset(blob, offset))) { const char *pname; u32 sz; if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) { offset = -FDT_ERR_INTERNAL; break; } if (pname == NULL) { pr_info("Can't find property name in list !\n"); break; } if (strcmp(pname, "name") == 0) has_name = 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); if (allnextpp) { /* We accept flattened tree phandles either in * ePAPR-style "phandle" properties, or the * legacy "linux,phandle" properties. If both * appear and have different values, things * will get weird. Don't do that. */ if ((strcmp(pname, "phandle") == 0) || (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) np->phandle = be32_to_cpup(p); } /* And we process the "ibm,phandle" property * used in pSeries dynamic device tree * stuff */ if (strcmp(pname, "ibm,phandle") == 0) np->phandle = be32_to_cpup(p); pp->name = (char *)pname; pp->length = sz; pp->value = (__be32 *)p; *prev_pp = pp; prev_pp = &pp->next; } } /* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent */ if (!has_name) { const char *p1 = pathp, *ps = pathp, *pa = NULL; int sz; while (*p1) { if ((*p1) == '@') pa = p1; if ((*p1) == '/') ps = p1 + 1; p1++; } if (pa < ps) pa = p1; sz = (pa - ps) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, __alignof__(struct property)); if (allnextpp) { pp->name = "name"; pp->length = sz; pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; pr_debug("fixed up name for %s -> %s\n", pathp, (char *)pp->value); } } if (allnextpp) { *prev_pp = NULL; np->name = of_get_property(np, "name", NULL); np->type = of_get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; if (!np->type) np->type = "<NULL>"; } old_depth = depth; *poffset = fdt_next_node(blob, *poffset, &depth); if (depth < 0) depth = 0; while (*poffset > 0 && depth > old_depth) mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp, fpsize); if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND) pr_err("unflatten: error %d processing FDT\n", *poffset); return mem; }
/** * fit_print_contents - prints out the contents of the FIT format image * @fit: pointer to the FIT format image header * @p: pointer to prefix string * * fit_print_contents() formats a multi line FIT image contents description. * The routine prints out FIT image properties (root node level) follwed by * the details of each component image. * * returns: * no returned results */ void fit_print_contents(const void *fit) { char *desc; char *uname; int images_noffset; int confs_noffset; int noffset; int ndepth; int count = 0; int ret; const char *p; time_t timestamp; /* Indent string is defined in header image.h */ p = IMAGE_INDENT_STRING; /* Root node properties */ ret = fit_get_desc(fit, 0, &desc); printf("%sFIT description: ", p); if (ret) printf("unavailable\n"); else printf("%s\n", desc); if (IMAGE_ENABLE_TIMESTAMP) { ret = fit_get_timestamp(fit, 0, ×tamp); printf("%sCreated: ", p); if (ret) printf("unavailable\n"); else genimg_print_time(timestamp); } /* Find images parent node offset */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images_noffset < 0) { printf("Can't find images parent node '%s' (%s)\n", FIT_IMAGES_PATH, fdt_strerror(images_noffset)); return; } /* Process its subnodes, print out component images details */ for (ndepth = 0, count = 0, noffset = fdt_next_node(fit, images_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* * Direct child node of the images parent node, * i.e. component image node. */ printf("%s Image %u (%s)\n", p, count++, fit_get_name(fit, noffset, NULL)); fit_image_print(fit, noffset, p); } } /* Find configurations parent node offset */ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { debug("Can't get configurations parent node '%s' (%s)\n", FIT_CONFS_PATH, fdt_strerror(confs_noffset)); return; } /* get default configuration unit name from default property */ uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL); if (uname) printf("%s Default Configuration: '%s'\n", p, uname); /* Process its subnodes, print out configurations details */ for (ndepth = 0, count = 0, noffset = fdt_next_node(fit, confs_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* * Direct child node of the configurations parent node, * i.e. configuration node. */ printf("%s Configuration %u (%s)\n", p, count++, fit_get_name(fit, noffset, NULL)); fit_conf_print(fit, noffset, p); } } }
static int dm_test_main(const char *test_name) { struct unit_test *tests = ll_entry_start(struct unit_test, dm_test); const int n_ents = ll_entry_count(struct unit_test, dm_test); struct unit_test_state *uts = &global_dm_test_state; struct unit_test *test; int run_count; uts->priv = &_global_priv_dm_test_state; uts->fail_count = 0; /* * If we have no device tree, or it only has a root node, then these * tests clearly aren't going to work... */ if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { puts("Please run with test device tree:\n" " ./u-boot -d arch/sandbox/dts/test.dtb\n"); ut_assert(gd->fdt_blob); } if (!test_name) printf("Running %d driver model tests\n", n_ents); run_count = 0; #ifdef CONFIG_OF_LIVE uts->of_root = gd->of_root; #endif for (test = tests; test < tests + n_ents; test++) { const char *name = test->name; int runs; /* All tests have this prefix */ if (!strncmp(name, "dm_test_", 8)) name += 8; if (test_name && strcmp(test_name, name)) continue; /* Run with the live tree if possible */ runs = 0; if (IS_ENABLED(CONFIG_OF_LIVE)) { if (!(test->flags & DM_TESTF_FLAT_TREE)) { ut_assertok(dm_do_test(uts, test, true)); runs++; } } /* * Run with the flat tree if we couldn't run it with live tree, * or it is a core test. */ if (!(test->flags & DM_TESTF_LIVE_TREE) && (!runs || dm_test_run_on_flattree(test))) { ut_assertok(dm_do_test(uts, test, false)); runs++; } run_count += runs; } if (test_name && !run_count) printf("Test '%s' not found\n", test_name); else printf("Failures: %d\n", uts->fail_count); gd->dm_root = NULL; ut_assertok(dm_init(false)); dm_scan_platdata(false); dm_scan_fdt(gd->fdt_blob, false); return uts->fail_count ? CMD_RET_FAILURE : 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; }
/** Initialize the system (or sometimes called permanent) memory This memory is generally represented by the DRAM. This function is called from InitializeMemory() in MemoryInitPeim, in the PEI phase. **/ VOID ArmPlatformInitializeSystemMemory ( VOID ) { VOID *DeviceTreeBase; INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize; CONST CHAR8 *Type; INT32 Len; CONST UINT64 *RegProp; NewBase = 0; NewSize = 0; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL); // // Make sure we have a valid device tree blob // ASSERT (fdt_check_header (DeviceTreeBase) == 0); // // Look for a memory node // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } // // Check for memory node // Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len); if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) { // // Get the 'reg' property of this node. For now, we will assume // two 8 byte quantities for base and size, respectively. // RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (RegProp != 0 && Len == (2 * sizeof (UINT64))) { NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1)); // // Make sure the start of DRAM matches our expectation // ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase); PcdSet64 (PcdSystemMemorySize, NewSize); DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n", __FUNCTION__, NewBase, NewBase + NewSize - 1)); } else { DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); } break; } } // // We need to make sure that the machine we are running on has at least // 128 MB of memory configured, and is currently executing this binary from // NOR flash. This prevents a device tree image in DRAM from getting // clobbered when our caller installs permanent PEI RAM, before we have a // chance of marking its location as reserved or copy it to a freshly // allocated block in the permanent PEI RAM in the platform PEIM. // ASSERT (NewSize >= SIZE_128MB); ASSERT ( (((UINT64)PcdGet64 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) || ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize))); }
/** * fit_image_print - prints out the FIT component image details * @fit: pointer to the FIT format image header * @image_noffset: offset of the component image node * @p: pointer to prefix string * * fit_image_print() lists all mandatory properies for the processed component * image. If present, hash nodes are printed out as well. Load * address for images of type firmware is also printed out. Since the load * address is not mandatory for firmware images, it will be output as * "unavailable" when not present. * * returns: * no returned results */ void fit_image_print(const void *fit, int image_noffset, const char *p) { char *desc; uint8_t type, arch, os, comp; size_t size; ulong load, entry; const void *data; int noffset; int ndepth; int ret; /* Mandatory properties */ ret = fit_get_desc(fit, image_noffset, &desc); printf("%s Description: ", p); if (ret) printf("unavailable\n"); else printf("%s\n", desc); fit_image_get_type(fit, image_noffset, &type); printf("%s Type: %s\n", p, genimg_get_type_name(type)); fit_image_get_comp(fit, image_noffset, &comp); printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); ret = fit_image_get_data(fit, image_noffset, &data, &size); #ifndef USE_HOSTCC printf("%s Data Start: ", p); if (ret) { printf("unavailable\n"); } else { void *vdata = (void *)data; printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); } #endif printf("%s Data Size: ", p); if (ret) printf("unavailable\n"); else genimg_print_size(size); /* Remaining, type dependent properties */ if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_FLATDT)) { fit_image_get_arch(fit, image_noffset, &arch); printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) printf("unavailable\n"); else printf("0x%08lx\n", load); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) printf("unavailable\n"); else printf("0x%08lx\n", entry); } /* Process all hash subnodes of the component image node */ for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* Direct child node of the component image node */ fit_image_print_verification_data(fit, noffset, p); } } }
int update_tftp(ulong addr, char *interface, char *devstring) { char *filename, *env_addr, *fit_image_name; ulong update_addr, update_fladdr, update_size; int images_noffset, ndepth, noffset; bool update_tftp_dfu; int ret = 0; void *fit; if (interface == NULL && devstring == NULL) { update_tftp_dfu = false; } else if (interface && devstring) { update_tftp_dfu = true; } else { error("Interface: %s and devstring: %s not supported!\n", interface, devstring); return -EINVAL; } /* use already present image */ if (addr) goto got_update_file; printf("Auto-update from TFTP: "); /* get the file name of the update file */ filename = getenv(UPDATE_FILE_ENV); if (filename == NULL) { printf("failed, env. variable '%s' not found\n", UPDATE_FILE_ENV); return 1; } printf("trying update file '%s'\n", filename); /* get load address of downloaded update file */ if ((env_addr = getenv("loadaddr")) != NULL) addr = simple_strtoul(env_addr, NULL, 16); else addr = CONFIG_UPDATE_LOAD_ADDR; if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX, CONFIG_UPDATE_TFTP_CNT_MAX, addr)) { printf("Can't load update file, aborting auto-update\n"); return 1; } got_update_file: fit = (void *)addr; if (!fit_check_format((void *)fit)) { printf("Bad FIT format of the update file, aborting " "auto-update\n"); return 1; } /* process updates */ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); ndepth = 0; noffset = fdt_next_node(fit, images_noffset, &ndepth); while (noffset >= 0 && ndepth > 0) { if (ndepth != 1) goto next_node; fit_image_name = (char *)fit_get_name(fit, noffset, NULL); printf("Processing update '%s' :", fit_image_name); if (!fit_image_verify(fit, noffset)) { printf("Error: invalid update hash, aborting\n"); ret = 1; goto next_node; } printf("\n"); if (update_fit_getparams(fit, noffset, &update_addr, &update_fladdr, &update_size)) { printf("Error: can't get update parameteres, " "aborting\n"); ret = 1; goto next_node; } if (!update_tftp_dfu) { if (update_flash(update_addr, update_fladdr, update_size)) { printf("Error: can't flash update, aborting\n"); ret = 1; goto next_node; } } else if (fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE)) { ret = dfu_tftp_write(fit_image_name, update_addr, update_size, interface, devstring); if (ret) return ret; } next_node: noffset = fdt_next_node(fit, noffset, &ndepth); } return ret; }
STATIC UINT64 SerialPortGetBaseAddress ( VOID ) { UINT64 BaudRate; UINT32 ReceiveFifoDepth; EFI_PARITY_TYPE Parity; UINT8 DataBits; EFI_STOP_BITS_TYPE StopBits; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 Len; CONST CHAR8 *Compatible; CONST CHAR8 *NodeStatus; CONST CHAR8 *CompatibleItem; CONST UINT64 *RegProperty; UINTN UartBase; RETURN_STATUS Status; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { return 0; } // // Enumerate all FDT nodes looking for a PL011 and capture its base address // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); if (Compatible == NULL) { continue; } // // Iterate over the NULL-separated items in the compatible string // for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len; CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) { if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) { NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len); if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) { continue; } RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (Len != 16) { return 0; } UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty)); BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate); ReceiveFifoDepth = 0; // Use the default value for Fifo depth Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits); Status = PL011UartInitializePort ( UartBase, FixedPcdGet32 (PL011UartClkInHz), &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits ); if (!EFI_ERROR (Status)) { return UartBase; } } } } 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; }