aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/device.c38
-rw-r--r--core/test/run-device.c35
-rw-r--r--include/device.h4
3 files changed, 75 insertions, 2 deletions
diff --git a/core/device.c b/core/device.c
index df0f4e9..fc1db56 100644
--- a/core/device.c
+++ b/core/device.c
@@ -1069,3 +1069,41 @@ bool dt_node_is_enabled(struct dt_node *node)
return p->len > 1 && p->prop[0] == 'o' && p->prop[1] == 'k';
}
+
+/*
+ * Function to fixup the phandle in the subtree.
+ */
+void dt_adjust_subtree_phandle(struct dt_node *dev,
+ const char** (get_properties_to_fix)(struct dt_node *n))
+{
+ struct dt_node *node;
+ struct dt_property *prop;
+ u32 phandle, max_phandle = 0, import_phandle = new_phandle();
+ const char **name;
+
+ dt_for_each_node(dev, node) {
+ const char **props_to_update;
+ node->phandle += import_phandle;
+
+ /*
+ * calculate max_phandle(new_tree), needed to update
+ * last_phandle.
+ */
+ if (node->phandle >= max_phandle)
+ max_phandle = node->phandle;
+
+ props_to_update = get_properties_to_fix(node);
+ if (!props_to_update)
+ continue;
+ for (name = props_to_update; *name != NULL; name++) {
+ prop = __dt_find_property(node, *name);
+ if (!prop)
+ continue;
+ phandle = dt_prop_get_u32(node, *name);
+ phandle += import_phandle;
+ memcpy((char *)&prop->prop, &phandle, prop->len);
+ }
+ }
+
+ set_last_phandle(max_phandle);
+}
diff --git a/core/test/run-device.c b/core/test/run-device.c
index 5939afc..1a4cb1e 100644
--- a/core/test/run-device.c
+++ b/core/test/run-device.c
@@ -33,6 +33,8 @@ static inline bool fake_is_rodata(const void *p)
#include "../device.c"
#include <assert.h>
#include "../../test/dt_common.c"
+const char *prop_to_fix[] = {"something", NULL};
+const char **props_to_fix(struct dt_node *node);
static void check_path(const struct dt_node *node, const char * expected_path)
{
@@ -87,18 +89,29 @@ static bool is_sorted(const struct dt_node *root)
return true;
}
+/*handler for phandle fixup test */
+const char **props_to_fix(struct dt_node *node)
+{
+ const struct dt_property *prop;
+
+ prop = dt_find_property(node, "something");
+ if (prop)
+ return prop_to_fix;
+
+ return NULL;
+}
int main(void)
{
struct dt_node *root, *c1, *c2, *gc1, *gc2, *gc3, *ggc1, *ggc2;
struct dt_node *addrs, *addr1, *addr2;
- struct dt_node *i;
+ struct dt_node *i, *subtree, *ev1, *ut1, *ut2;
const struct dt_property *p;
struct dt_property *p2;
unsigned int n;
char *s;
size_t sz;
- u32 phandle;
+ u32 phandle, ev1_ph, new_prop_ph;
root = dt_new_root("");
assert(!list_top(&root->properties, struct dt_property, list));
@@ -412,6 +425,24 @@ int main(void)
dt_free(root);
+ /* phandle fixup test */
+ subtree = dt_new_root("subtree");
+ ev1 = dt_new(subtree, "ev@1");
+ ev1_ph = ev1->phandle;
+ dt_new(ev1,"a@1");
+ dt_new(ev1,"a@2");
+ dt_new(ev1,"a@3");
+ ut1 = dt_new(subtree, "ut@1");
+ dt_add_property(ut1, "something", (const void *)&ev1->phandle, 4);
+ ut2 = dt_new(subtree, "ut@2");
+ dt_add_property(ut2, "something", (const void *)&ev1->phandle, 4);
+
+ dt_adjust_subtree_phandle(subtree, props_to_fix);
+ assert(!(ev1->phandle == ev1_ph));
+ new_prop_ph = dt_prop_get_u32(ut1, "something");
+ assert(!(new_prop_ph == ev1_ph));
+ new_prop_ph = dt_prop_get_u32(ut2, "something");
+ assert(!(new_prop_ph == ev1_ph));
return 0;
}
diff --git a/include/device.h b/include/device.h
index c51b3ee..1e5875d 100644
--- a/include/device.h
+++ b/include/device.h
@@ -268,4 +268,8 @@ struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name,
uint64_t addr);
+/* phandle fixup helper */
+void dt_adjust_subtree_phandle(struct dt_node *subtree,
+ const char** (get_properties_to_fix)(struct dt_node *n));
+
#endif /* __DEVICE_H */