* Apply a device tree overlay to a base device tree. This will * destroy/incorporate the overlay data, so it should not be freed or reused. * See dtc.git/Documentation/dt-object-internal.txt for overlay format details. * * @param tree Unflattened base device tree to add the overlay into. * @param overlay Unflattened overlay device tree to apply to the base. * * @return 0 on success, -1 on
| 2077 | * @return 0 on success, -1 on error. |
| 2078 | */ |
| 2079 | int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) |
| 2080 | { |
| 2081 | /* |
| 2082 | * First, we need to make sure phandles inside the overlay don't clash |
| 2083 | * with those in the base tree. We just define the highest phandle value |
| 2084 | * in the base tree as the "phandle offset" for this overlay and |
| 2085 | * increment all phandles in it by that value. |
| 2086 | */ |
| 2087 | uint32_t phandle_base = tree->max_phandle; |
| 2088 | uint32_t new_max = dt_adjust_all_phandles(overlay->root, phandle_base); |
| 2089 | if (!new_max) { |
| 2090 | printk(BIOS_ERR, "invalid phandles in overlay\n"); |
| 2091 | return -1; |
| 2092 | } |
| 2093 | tree->max_phandle = new_max; |
| 2094 | |
| 2095 | /* Now that we changed phandles in the overlay, we need to update any |
| 2096 | nodes referring to them. Those are listed in /__local_fixups__. */ |
| 2097 | struct device_tree_node *local_fixups = dt_find_node_by_path(overlay, |
| 2098 | "/__local_fixups__", NULL, NULL, 0); |
| 2099 | if (local_fixups && dt_fixup_locals(overlay->root, local_fixups, |
| 2100 | phandle_base) < 0) { |
| 2101 | printk(BIOS_ERR, "invalid local fixups in overlay\n"); |
| 2102 | return -1; |
| 2103 | } |
| 2104 | |
| 2105 | /* |
| 2106 | * Besides local phandle references (from nodes within the overlay to |
| 2107 | * other nodes within the overlay), the overlay may also contain phandle |
| 2108 | * references to the base tree. These are stored with invalid values and |
| 2109 | * must be updated now. /__symbols__ contains a list of all labels in |
| 2110 | * the base tree, and /__fixups__ describes all nodes in the overlay |
| 2111 | * that contain external phandle references. |
| 2112 | * We also take this opportunity to update all /fragment@X/__overlay__/ |
| 2113 | * prefixes in the overlay's /__symbols__ node to the correct path that |
| 2114 | * the fragment will be placed in later, since this is the only step |
| 2115 | * where we have all necessary information for that easily available. |
| 2116 | */ |
| 2117 | struct device_tree_node *symbols = dt_find_node_by_path(tree, |
| 2118 | "/__symbols__", NULL, NULL, 0); |
| 2119 | struct device_tree_node *fixups = dt_find_node_by_path(overlay, |
| 2120 | "/__fixups__", NULL, NULL, 0); |
| 2121 | struct device_tree_node *overlay_symbols = dt_find_node_by_path(overlay, |
| 2122 | "/__symbols__", NULL, NULL, 0); |
| 2123 | if (fixups && dt_fixup_all_externals(tree, symbols, overlay, |
| 2124 | fixups, overlay_symbols) < 0) { |
| 2125 | printk(BIOS_ERR, "cannot match external fixups from overlay\n"); |
| 2126 | return -1; |
| 2127 | } |
| 2128 | |
| 2129 | /* After all this fixing up, we can finally merge overlay into the tree |
| 2130 | (one fragment at a time, because for some reason it's split up). */ |
| 2131 | struct device_tree_node *fragment; |
| 2132 | list_for_each(fragment, overlay->root->children, list_node) |
| 2133 | if (dt_import_fragment(tree, fragment, overlay_symbols) < 0) { |
| 2134 | printk(BIOS_ERR, "bad DT fragment '%s'\n", |
| 2135 | fragment->name); |
| 2136 | return -1; |