in overlay.c [732:846]
static int init_overlay_changeset(struct overlay_changeset *ovcs,
const void *fdt, struct device_node *tree)
{
struct device_node *node, *overlay_node;
struct fragment *fragment;
struct fragment *fragments;
int cnt, id, ret;
/*
* Warn for some issues. Can not return -EINVAL for these until
* of_unittest_apply_overlay() is fixed to pass these checks.
*/
if (!of_node_check_flag(tree, OF_DYNAMIC))
pr_debug("%s() tree is not dynamic\n", __func__);
if (!of_node_check_flag(tree, OF_DETACHED))
pr_debug("%s() tree is not detached\n", __func__);
if (!of_node_is_root(tree))
pr_debug("%s() tree is not root\n", __func__);
ovcs->overlay_tree = tree;
ovcs->fdt = fdt;
INIT_LIST_HEAD(&ovcs->ovcs_list);
of_changeset_init(&ovcs->cset);
id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
if (id <= 0)
return id;
cnt = 0;
/* fragment nodes */
for_each_child_of_node(tree, node) {
overlay_node = of_get_child_by_name(node, "__overlay__");
if (overlay_node) {
cnt++;
of_node_put(overlay_node);
}
}
node = of_get_child_by_name(tree, "__symbols__");
if (node) {
cnt++;
of_node_put(node);
}
fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
if (!fragments) {
ret = -ENOMEM;
goto err_free_idr;
}
cnt = 0;
for_each_child_of_node(tree, node) {
overlay_node = of_get_child_by_name(node, "__overlay__");
if (!overlay_node)
continue;
fragment = &fragments[cnt];
fragment->overlay = overlay_node;
fragment->target = find_target(node);
if (!fragment->target) {
of_node_put(fragment->overlay);
ret = -EINVAL;
of_node_put(node);
goto err_free_fragments;
}
cnt++;
}
/*
* if there is a symbols fragment in ovcs->fragments[i] it is
* the final element in the array
*/
node = of_get_child_by_name(tree, "__symbols__");
if (node) {
ovcs->symbols_fragment = 1;
fragment = &fragments[cnt];
fragment->overlay = node;
fragment->target = of_find_node_by_path("/__symbols__");
if (!fragment->target) {
pr_err("symbols in overlay, but not in live tree\n");
ret = -EINVAL;
goto err_free_fragments;
}
cnt++;
}
if (!cnt) {
pr_err("no fragments or symbols in overlay\n");
ret = -EINVAL;
goto err_free_fragments;
}
ovcs->id = id;
ovcs->count = cnt;
ovcs->fragments = fragments;
return 0;
err_free_fragments:
kfree(fragments);
err_free_idr:
idr_remove(&ovcs_idr, id);
pr_err("%s() failed, ret = %d\n", __func__, ret);
return ret;
}