in resolver.c [159:228]
static int adjust_local_phandle_references(struct device_node *local_fixups,
struct device_node *overlay, int phandle_delta)
{
struct device_node *child, *overlay_child;
struct property *prop_fix, *prop;
int err, i, count;
unsigned int off;
if (!local_fixups)
return 0;
for_each_property_of_node(local_fixups, prop_fix) {
/* skip properties added automatically */
if (!of_prop_cmp(prop_fix->name, "name") ||
!of_prop_cmp(prop_fix->name, "phandle") ||
!of_prop_cmp(prop_fix->name, "linux,phandle"))
continue;
if ((prop_fix->length % 4) != 0 || prop_fix->length == 0)
return -EINVAL;
count = prop_fix->length / sizeof(__be32);
for_each_property_of_node(overlay, prop) {
if (!of_prop_cmp(prop->name, prop_fix->name))
break;
}
if (!prop)
return -EINVAL;
for (i = 0; i < count; i++) {
off = be32_to_cpu(((__be32 *)prop_fix->value)[i]);
if ((off + 4) > prop->length)
return -EINVAL;
be32_add_cpu(prop->value + off, phandle_delta);
}
}
/*
* These nested loops recurse down two subtrees in parallel, where the
* node names in the two subtrees match.
*
* The roots of the subtrees are the overlay's __local_fixups__ node
* and the overlay's root node.
*/
for_each_child_of_node(local_fixups, child) {
for_each_child_of_node(overlay, overlay_child)
if (!node_name_cmp(child, overlay_child)) {
of_node_put(overlay_child);
break;
}
if (!overlay_child) {
of_node_put(child);
return -EINVAL;
}
err = adjust_local_phandle_references(child, overlay_child,
phandle_delta);
if (err) {
of_node_put(child);
return err;
}
}
return 0;
}