static int adjust_local_phandle_references()

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;
}