if (node == NULL)
return NULL;
- /* check */
if (of_node_cmp(node->full_name, full_name) == 0)
return of_node_get(node);
phandle phandle;
unsigned long flags;
- /* now search recursively */
raw_spin_lock_irqsave(&devtree_lock, flags);
phandle = 0;
for_each_of_allnodes(node) {
/*
* Adjust a subtree's phandle values by a given delta.
- * Makes sure not to just adjust the device node's phandle value,
- * but modify the phandle properties values as well.
*/
static void __of_adjust_tree_phandles(struct device_node *node,
int phandle_delta)
struct property *prop;
phandle phandle;
- /* first adjust the node's phandle direct value */
if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL)
node->phandle += phandle_delta;
- /* now adjust phandle & linux,phandle values */
for_each_property_of_node(node, prop) {
- /* only look for these two */
if (of_prop_cmp(prop->name, "phandle") != 0 &&
of_prop_cmp(prop->name, "linux,phandle") != 0)
continue;
- /* must be big enough */
if (prop->length < 4)
continue;
- /* read phandle value */
phandle = be32_to_cpup(prop->value);
- if (phandle == OF_PHANDLE_ILLEGAL) /* unresolved */
+ if (phandle == OF_PHANDLE_ILLEGAL)
continue;
- /* adjust */
*(uint32_t *)prop->value = cpu_to_be32(node->phandle);
}
- /* now do the children recursively */
for_each_child_of_node(node, child)
__of_adjust_tree_phandles(child, phandle_delta);
}
int offset, propcurlen;
int err = 0;
- /* make a copy */
propval = kmalloc(rprop->length, GFP_KERNEL);
if (!propval) {
pr_err("%s: Could not copy value of '%s'\n",
goto err_fail;
}
- /* look into the resolve node for the full path */
refnode = __of_find_node_by_full_name(node, nodestr);
if (!refnode) {
pr_warn("%s: Could not find refnode '%s'\n",
continue;
}
- /* now find the property */
for_each_property_of_node(refnode, sprop) {
if (of_prop_cmp(sprop->name, propstr) == 0)
break;
}
count = rprop->length / sizeof(__be32);
- /* now find the target property */
for_each_property_of_node(target, sprop) {
if (of_prop_cmp(sprop->name, rprop->name) == 0)
break;
for (i = 0; i < count; i++) {
off = be32_to_cpu(((__be32 *)rprop->value)[i]);
- /* make sure the offset doesn't overstep (even wrap) */
if (off >= sprop->length ||
(off + 4) > sprop->length) {
pr_err("%s: Illegal property '%s' @%s\n",
}
if (phandle_delta) {
- /* adjust */
phandle = be32_to_cpu(*(__be32 *)(sprop->value + off));
phandle += phandle_delta;
*(__be32 *)(sprop->value + off) = cpu_to_be32(phandle);
if (resolve && !of_node_check_flag(resolve, OF_DETACHED))
pr_err("%s: node %s not detached\n", __func__,
resolve->full_name);
- /* the resolve node must exist, and be detached */
if (!resolve || !of_node_check_flag(resolve, OF_DETACHED))
return -EINVAL;
- /* first we need to adjust the phandles */
phandle_delta = of_get_tree_max_phandle() + 1;
__of_adjust_tree_phandles(resolve, phandle_delta);
- /* locate the local fixups */
childroot = NULL;
for_each_child_of_node(resolve, childroot)
if (of_node_cmp(childroot->name, "__local_fixups__") == 0)
break;
if (childroot != NULL) {
- /* resolve root is guaranteed to be the '/' */
err = __of_adjust_tree_phandle_references(childroot,
resolve, 0);
if (err != 0)
resolve_sym = NULL;
resolve_fix = NULL;
- /* this may fail (if no fixups are required) */
root_sym = of_find_node_by_path("/__symbols__");
- /* locate the symbols & fixups nodes on resolve */
for_each_child_of_node(resolve, child) {
if (!resolve_sym &&
of_node_cmp(child->name, "__fixups__") == 0)
resolve_fix = child;
- /* both found, don't bother anymore */
if (resolve_sym && resolve_fix)
break;
}
- /* we do allow for the case where no fixups are needed */
if (!resolve_fix) {
- err = 0; /* no error */
+ err = 0;
goto out;
}
- /* we need to fixup, but no root symbols... */
if (!root_sym) {
pr_err("%s: no symbols in root of device tree.\n", __func__);
err = -EINVAL;
}
out:
- /* NULL is handled by of_node_put as NOP */
of_node_put(root_sym);
return err;