0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "OF: resolver: " fmt
0010
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/string.h>
0016 #include <linux/ctype.h>
0017 #include <linux/errno.h>
0018 #include <linux/slab.h>
0019
0020 #include "of_private.h"
0021
0022 static phandle live_tree_max_phandle(void)
0023 {
0024 struct device_node *node;
0025 phandle phandle;
0026 unsigned long flags;
0027
0028 raw_spin_lock_irqsave(&devtree_lock, flags);
0029 phandle = 0;
0030 for_each_of_allnodes(node) {
0031 if (node->phandle != OF_PHANDLE_ILLEGAL &&
0032 node->phandle > phandle)
0033 phandle = node->phandle;
0034 }
0035 raw_spin_unlock_irqrestore(&devtree_lock, flags);
0036
0037 return phandle;
0038 }
0039
0040 static void adjust_overlay_phandles(struct device_node *overlay,
0041 int phandle_delta)
0042 {
0043 struct device_node *child;
0044 struct property *prop;
0045 phandle phandle;
0046
0047
0048 if (overlay->phandle != 0 && overlay->phandle != OF_PHANDLE_ILLEGAL)
0049 overlay->phandle += phandle_delta;
0050
0051
0052 for_each_property_of_node(overlay, prop) {
0053
0054 if (of_prop_cmp(prop->name, "phandle") &&
0055 of_prop_cmp(prop->name, "linux,phandle"))
0056 continue;
0057
0058 if (prop->length < 4)
0059 continue;
0060
0061 phandle = be32_to_cpup(prop->value);
0062 if (phandle == OF_PHANDLE_ILLEGAL)
0063 continue;
0064
0065 *(__be32 *)prop->value = cpu_to_be32(overlay->phandle);
0066 }
0067
0068 for_each_child_of_node(overlay, child)
0069 adjust_overlay_phandles(child, phandle_delta);
0070 }
0071
0072 static int update_usages_of_a_phandle_reference(struct device_node *overlay,
0073 struct property *prop_fixup, phandle phandle)
0074 {
0075 struct device_node *refnode;
0076 struct property *prop;
0077 char *value, *cur, *end, *node_path, *prop_name, *s;
0078 int offset, len;
0079 int err = 0;
0080
0081 value = kmemdup(prop_fixup->value, prop_fixup->length, GFP_KERNEL);
0082 if (!value)
0083 return -ENOMEM;
0084
0085
0086 end = value + prop_fixup->length;
0087 for (cur = value; cur < end; cur += len + 1) {
0088 len = strlen(cur);
0089
0090 node_path = cur;
0091 s = strchr(cur, ':');
0092 if (!s) {
0093 err = -EINVAL;
0094 goto err_fail;
0095 }
0096 *s++ = '\0';
0097
0098 prop_name = s;
0099 s = strchr(s, ':');
0100 if (!s) {
0101 err = -EINVAL;
0102 goto err_fail;
0103 }
0104 *s++ = '\0';
0105
0106 err = kstrtoint(s, 10, &offset);
0107 if (err)
0108 goto err_fail;
0109
0110 refnode = __of_find_node_by_full_path(of_node_get(overlay), node_path);
0111 if (!refnode)
0112 continue;
0113
0114 for_each_property_of_node(refnode, prop) {
0115 if (!of_prop_cmp(prop->name, prop_name))
0116 break;
0117 }
0118 of_node_put(refnode);
0119
0120 if (!prop) {
0121 err = -ENOENT;
0122 goto err_fail;
0123 }
0124
0125 if (offset < 0 || offset + sizeof(__be32) > prop->length) {
0126 err = -EINVAL;
0127 goto err_fail;
0128 }
0129
0130 *(__be32 *)(prop->value + offset) = cpu_to_be32(phandle);
0131 }
0132
0133 err_fail:
0134 kfree(value);
0135 return err;
0136 }
0137
0138
0139 static int node_name_cmp(const struct device_node *dn1,
0140 const struct device_node *dn2)
0141 {
0142 const char *n1 = kbasename(dn1->full_name);
0143 const char *n2 = kbasename(dn2->full_name);
0144
0145 return of_node_cmp(n1, n2);
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 static int adjust_local_phandle_references(struct device_node *local_fixups,
0160 struct device_node *overlay, int phandle_delta)
0161 {
0162 struct device_node *child, *overlay_child;
0163 struct property *prop_fix, *prop;
0164 int err, i, count;
0165 unsigned int off;
0166
0167 if (!local_fixups)
0168 return 0;
0169
0170 for_each_property_of_node(local_fixups, prop_fix) {
0171
0172
0173 if (!of_prop_cmp(prop_fix->name, "name") ||
0174 !of_prop_cmp(prop_fix->name, "phandle") ||
0175 !of_prop_cmp(prop_fix->name, "linux,phandle"))
0176 continue;
0177
0178 if ((prop_fix->length % 4) != 0 || prop_fix->length == 0)
0179 return -EINVAL;
0180 count = prop_fix->length / sizeof(__be32);
0181
0182 for_each_property_of_node(overlay, prop) {
0183 if (!of_prop_cmp(prop->name, prop_fix->name))
0184 break;
0185 }
0186
0187 if (!prop)
0188 return -EINVAL;
0189
0190 for (i = 0; i < count; i++) {
0191 off = be32_to_cpu(((__be32 *)prop_fix->value)[i]);
0192 if ((off + 4) > prop->length)
0193 return -EINVAL;
0194
0195 be32_add_cpu(prop->value + off, phandle_delta);
0196 }
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206 for_each_child_of_node(local_fixups, child) {
0207
0208 for_each_child_of_node(overlay, overlay_child)
0209 if (!node_name_cmp(child, overlay_child)) {
0210 of_node_put(overlay_child);
0211 break;
0212 }
0213
0214 if (!overlay_child) {
0215 of_node_put(child);
0216 return -EINVAL;
0217 }
0218
0219 err = adjust_local_phandle_references(child, overlay_child,
0220 phandle_delta);
0221 if (err) {
0222 of_node_put(child);
0223 return err;
0224 }
0225 }
0226
0227 return 0;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263 int of_resolve_phandles(struct device_node *overlay)
0264 {
0265 struct device_node *child, *local_fixups, *refnode;
0266 struct device_node *tree_symbols, *overlay_fixups;
0267 struct property *prop;
0268 const char *refpath;
0269 phandle phandle, phandle_delta;
0270 int err;
0271
0272 tree_symbols = NULL;
0273
0274 if (!overlay) {
0275 pr_err("null overlay\n");
0276 err = -EINVAL;
0277 goto out;
0278 }
0279
0280 if (!of_node_check_flag(overlay, OF_DETACHED)) {
0281 pr_err("overlay not detached\n");
0282 err = -EINVAL;
0283 goto out;
0284 }
0285
0286 phandle_delta = live_tree_max_phandle() + 1;
0287 adjust_overlay_phandles(overlay, phandle_delta);
0288
0289 for_each_child_of_node(overlay, local_fixups)
0290 if (of_node_name_eq(local_fixups, "__local_fixups__"))
0291 break;
0292
0293 err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
0294 if (err)
0295 goto out;
0296
0297 overlay_fixups = NULL;
0298
0299 for_each_child_of_node(overlay, child) {
0300 if (of_node_name_eq(child, "__fixups__"))
0301 overlay_fixups = child;
0302 }
0303
0304 if (!overlay_fixups) {
0305 err = 0;
0306 goto out;
0307 }
0308
0309 tree_symbols = of_find_node_by_path("/__symbols__");
0310 if (!tree_symbols) {
0311 pr_err("no symbols in root of device tree.\n");
0312 err = -EINVAL;
0313 goto out;
0314 }
0315
0316 for_each_property_of_node(overlay_fixups, prop) {
0317
0318
0319 if (!of_prop_cmp(prop->name, "name"))
0320 continue;
0321
0322 err = of_property_read_string(tree_symbols,
0323 prop->name, &refpath);
0324 if (err) {
0325 pr_err("node label '%s' not found in live devicetree symbols table\n",
0326 prop->name);
0327 goto out;
0328 }
0329
0330 refnode = of_find_node_by_path(refpath);
0331 if (!refnode) {
0332 err = -ENOENT;
0333 goto out;
0334 }
0335
0336 phandle = refnode->phandle;
0337 of_node_put(refnode);
0338
0339 err = update_usages_of_a_phandle_reference(overlay, prop, phandle);
0340 if (err)
0341 break;
0342 }
0343
0344 out:
0345 if (err)
0346 pr_err("overlay phandle fixup failed: %d\n", err);
0347 of_node_put(tree_symbols);
0348
0349 return err;
0350 }
0351 EXPORT_SYMBOL_GPL(of_resolve_phandles);