summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/cmd_fdt.c76
-rw-r--r--common/fdt_support.c183
2 files changed, 205 insertions, 54 deletions
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index f18c583..629c9b4 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -44,7 +44,7 @@ DECLARE_GLOBAL_DATA_PTR;
static int fdt_valid(void);
static int fdt_parse_prop(char *pathp, char *prop, char *newval,
char *data, int *len);
-static int fdt_print(char *pathp, char *prop, int depth);
+static int fdt_print(const char *pathp, char *prop, int depth);
/*
* Flattened Device Tree command, see the help for parameter definitions.
@@ -75,7 +75,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
/*
* Optional new length
*/
- len = simple_strtoul(argv[3], NULL, 16);
+ len = simple_strtoul(argv[3], NULL, 16);
if (len < fdt_totalsize(fdt)) {
printf ("New length %d < existing length %d, "
"ignoring.\n",
@@ -162,12 +162,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
pathp = argv[2];
nodep = argv[3];
- nodeoffset = fdt_find_node_by_path (fdt, pathp);
+ nodeoffset = fdt_path_offset (fdt, pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
- printf ("libfdt fdt_find_node_by_path() returned %s\n",
+ printf ("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return 1;
}
@@ -202,12 +202,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
prop = argv[3];
newval = argv[4];
- nodeoffset = fdt_find_node_by_path (fdt, pathp);
+ nodeoffset = fdt_path_offset (fdt, pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
- printf ("libfdt fdt_find_node_by_path() returned %s\n",
+ printf ("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return 1;
}
@@ -229,6 +229,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
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
@@ -241,7 +242,10 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
* Get the starting path. The root node is an oddball,
* the offset is zero and has no name.
*/
- pathp = argv[2];
+ if (argc == 2)
+ pathp = root;
+ else
+ pathp = argv[2];
if (argc > 3)
prop = argv[3];
else
@@ -262,12 +266,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
* Get the path. The root node is an oddball, the offset
* is zero and has no name.
*/
- nodeoffset = fdt_find_node_by_path (fdt, argv[2]);
+ nodeoffset = fdt_path_offset (fdt, argv[2]);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
- printf ("libfdt fdt_find_node_by_path() returned %s\n",
+ printf ("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return 1;
}
@@ -518,21 +522,21 @@ static void print_data(const void *data, int len)
switch (len) {
case 1: /* byte */
- printf("<%02x>", (*(u8 *) data) & 0xff);
+ printf("<0x%02x>", (*(u8 *) data) & 0xff);
break;
case 2: /* half-word */
- printf("<%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
+ printf("<0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
break;
case 4: /* word */
- printf("<%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+ printf("<0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
break;
case 8: /* double-word */
#if __WORDSIZE == 64
- printf("<%016llx>", be64_to_cpu(*(uint64_t *) data));
+ printf("<0x%016llx>", be64_to_cpu(*(uint64_t *) data));
#else
- printf("<%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+ printf("<0x%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
data += 4;
- printf("%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+ printf("0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
#endif
break;
default: /* anything else... hexdump */
@@ -551,25 +555,25 @@ static void print_data(const void *data, int len)
* Recursively print (a portion of) the fdt. The depth parameter
* determines how deeply nested the fdt is printed.
*/
-static int fdt_print(char *pathp, char *prop, int depth)
+static int fdt_print(const char *pathp, char *prop, int depth)
{
- 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";
- void *nodep; /* property node pointer */
+ const 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 */
+ const struct fdt_property *fdt_prop;
- nodeoffset = fdt_find_node_by_path (fdt, pathp);
+ nodeoffset = fdt_path_offset (fdt, pathp);
if (nodeoffset < 0) {
/*
* Not found or something else bad happened.
*/
- printf ("libfdt fdt_find_node_by_path() returned %s\n",
+ printf ("libfdt fdt_path_offset() returned %s\n",
fdt_strerror(nodeoffset));
return 1;
}
@@ -599,45 +603,52 @@ static int fdt_print(char *pathp, char *prop, int depth)
* 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);
+ tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
switch(tag) {
case FDT_BEGIN_NODE:
- if(level <= depth)
+ pathp = fdt_get_name(fdt, nodeoffset, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
printf("%s%s {\n",
&tabs[MAX_LEVEL - level], pathp);
+ }
level++;
- offstack[level] = nodeoffset;
if (level >= MAX_LEVEL) {
- printf("Aaaiii <splat> nested too deep. "
- "Aborting.\n");
+ printf("Nested too deep, aborting.\n");
return 1;
}
break;
case FDT_END_NODE:
level--;
- if(level <= depth)
+ 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);
+ fdt_prop = fdt_offset_ptr(fdt, nodeoffset,
+ sizeof(*fdt_prop));
+ pathp = fdt_string(fdt,
+ fdt32_to_cpu(fdt_prop->nameoff));
+ len = fdt32_to_cpu(fdt_prop->len);
+ nodep = fdt_prop->data;
if (len < 0) {
printf ("libfdt fdt_getprop(): %s\n",
fdt_strerror(len));
return 1;
} else if (len == 0) {
/* the property has no value */
- if(level <= depth)
+ if (level <= depth)
printf("%s%s;\n",
&tabs[MAX_LEVEL - level],
pathp);
} else {
- if(level <= depth) {
+ if (level <= depth) {
printf("%s%s=",
&tabs[MAX_LEVEL - level],
pathp);
@@ -647,11 +658,12 @@ static int fdt_print(char *pathp, char *prop, int depth)
}
break;
case FDT_NOP:
+ printf("/* NOP */\n", &tabs[MAX_LEVEL - level]);
break;
case FDT_END:
return 1;
default:
- if(level <= depth)
+ if (level <= depth)
printf("Unknown tag 0x%08X\n", tag);
return 1;
}
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 175d59e..c67bb3d 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -44,6 +44,32 @@ struct fdt_header *fdt;
/********************************************************************/
+/**
+ * fdt_find_and_setprop: Find a node and set it's property
+ *
+ * @fdt: ptr to device tree
+ * @node: path of node
+ * @prop: property name
+ * @val: ptr to new value
+ * @len: length of new property value
+ * @create: flag to create the property if it doesn't exist
+ *
+ * Convenience function to directly set a property given the path to the node.
+ */
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+ const void *val, int len, int create)
+{
+ int nodeoff = fdt_path_offset(fdt, node);
+
+ if (nodeoff < 0)
+ return nodeoff;
+
+ if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
+ return 0; /* create flag not set; so exit quietly */
+
+ return fdt_setprop(fdt, nodeoff, prop, val, len);
+}
+
int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
{
int nodeoffset;
@@ -58,34 +84,23 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
}
if (initrd_start && initrd_end) {
- struct fdt_reserve_entry re;
- int used;
- int total;
+ uint64_t addr, size;
+ int total = fdt_num_mem_rsv(fdt);
int j;
- err = fdt_num_reservemap(fdt, &used, &total);
- if (err < 0) {
- printf("fdt_chosen: %s\n", fdt_strerror(err));
- return err;
- }
- if (used >= total) {
- printf("WARNING: "
- "no room in the reserved map (%d of %d)\n",
- used, total);
- return -1;
- }
/*
* Look for an existing entry and update it. If we don't find
* the entry, we will j be the next available slot.
*/
- for (j = 0; j < used; j++) {
- err = fdt_get_reservemap(fdt, j, &re);
- if (re.address == initrd_start) {
+ for (j = 0; j < total; j++) {
+ err = fdt_get_mem_rsv(fdt, j, &addr, &size);
+ if (addr == initrd_start) {
+ fdt_del_mem_rsv(fdt, j);
break;
}
}
- err = fdt_replace_reservemap_entry(fdt, j,
- initrd_start, initrd_end - initrd_start + 1);
+
+ err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start + 1);
if (err < 0) {
printf("fdt_chosen: %s\n", fdt_strerror(err));
return err;
@@ -95,7 +110,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)
/*
* Find the "chosen" node.
*/
- nodeoffset = fdt_find_node_by_path (fdt, "/chosen");
+ nodeoffset = fdt_path_offset (fdt, "/chosen");
/*
* If we have a "chosen" node already the "force the writing"
@@ -182,7 +197,7 @@ int fdt_env(void *fdt)
* See if we already have a "u-boot-env" node, delete it if so.
* Then create a new empty node.
*/
- nodeoffset = fdt_find_node_by_path (fdt, "/u-boot-env");
+ nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
if (nodeoffset >= 0) {
err = fdt_del_node(fdt, nodeoffset);
if (err < 0) {
@@ -304,7 +319,7 @@ int fdt_bd_t(void *fdt)
* See if we already have a "bd_t" node, delete it if so.
* Then create a new empty node.
*/
- nodeoffset = fdt_find_node_by_path (fdt, "/bd_t");
+ nodeoffset = fdt_path_offset (fdt, "/bd_t");
if (nodeoffset >= 0) {
err = fdt_del_node(fdt, nodeoffset);
if (err < 0) {
@@ -348,4 +363,128 @@ int fdt_bd_t(void *fdt)
}
#endif /* ifdef CONFIG_OF_HAS_BD_T */
+void do_fixup_by_path(void *fdt, const char *path, const char *prop,
+ const void *val, int len, int create)
+{
+#if defined(DEBUG)
+ int i;
+ debug("Updating property '%s/%s' = ", node, prop);
+ for (i = 0; i < len; i++)
+ debug(" %.2x", *(u8*)(val+i));
+ debug("\n");
+#endif
+ int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create);
+ if (rc)
+ printf("Unable to update property %s:%s, err=%s\n",
+ path, prop, fdt_strerror(rc));
+}
+
+void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop,
+ u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
+}
+
+void do_fixup_by_prop(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, const void *val, int len,
+ int create)
+{
+ int off;
+#if defined(DEBUG)
+ int i;
+ debug("Updating property '%s/%s' = ", node, prop);
+ for (i = 0; i < len; i++)
+ debug(" %.2x", *(u8*)(val+i));
+ debug("\n");
+#endif
+ off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen);
+ }
+}
+
+void do_fixup_by_prop_u32(void *fdt,
+ const char *pname, const void *pval, int plen,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_prop(fdt, pname, pval, plen, prop, &val, 4, create);
+}
+
+void do_fixup_by_compat(void *fdt, const char *compat,
+ const char *prop, const void *val, int len, int create)
+{
+ int off = -1;
+#if defined(DEBUG)
+ int i;
+ debug("Updating property '%s/%s' = ", node, prop);
+ for (i = 0; i < len; i++)
+ debug(" %.2x", *(u8*)(val+i));
+ debug("\n");
+#endif
+ off = fdt_node_offset_by_compatible(fdt, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
+ fdt_setprop(fdt, off, prop, val, len);
+ off = fdt_node_offset_by_compatible(fdt, off, compat);
+ }
+}
+
+void do_fixup_by_compat_u32(void *fdt, const char *compat,
+ const char *prop, u32 val, int create)
+{
+ val = cpu_to_fdt32(val);
+ do_fixup_by_compat(fdt, compat, prop, &val, 4, create);
+}
+
+void fdt_fixup_ethernet(void *fdt, bd_t *bd)
+{
+ int node;
+ const char *path;
+
+ node = fdt_path_offset(fdt, "/aliases");
+ if (node >= 0) {
+#if defined(CONFIG_HAS_ETH0)
+ path = fdt_getprop(fdt, node, "ethernet0", NULL);
+ if (path) {
+ do_fixup_by_path(fdt, path, "mac-address",
+ bd->bi_enetaddr, 6, 0);
+ do_fixup_by_path(fdt, path, "local-mac-address",
+ bd->bi_enetaddr, 6, 1);
+ }
+#endif
+#if defined(CONFIG_HAS_ETH1)
+ path = fdt_getprop(fdt, node, "ethernet1", NULL);
+ if (path) {
+ do_fixup_by_path(fdt, path, "mac-address",
+ bd->bi_enet1addr, 6, 0);
+ do_fixup_by_path(fdt, path, "local-mac-address",
+ bd->bi_enet1addr, 6, 1);
+ }
+#endif
+#if defined(CONFIG_HAS_ETH2)
+ path = fdt_getprop(fdt, node, "ethernet2", NULL);
+ if (path) {
+ do_fixup_by_path(fdt, path, "mac-address",
+ bd->bi_enet2addr, 6, 0);
+ do_fixup_by_path(fdt, path, "local-mac-address",
+ bd->bi_enet2addr, 6, 1);
+ }
+#endif
+#if defined(CONFIG_HAS_ETH3)
+ path = fdt_getprop(fdt, node, "ethernet3", NULL);
+ if (path) {
+ do_fixup_by_path(fdt, path, "mac-address",
+ bd->bi_enet3addr, 6, 0);
+ do_fixup_by_path(fdt, path, "local-mac-address",
+ bd->bi_enet3addr, 6, 1);
+ }
+#endif
+ }
+}
+
#endif /* CONFIG_OF_LIBFDT */