Skip to content

Commit d1651b0

Browse files
frowandrobherring
authored andcommitted
of: overlay: add overlay symbols to live device tree
Add overlay __symbols__ properties to live tree when an overlay is added to the live tree so that the symbols are available to subsequent overlays. Expected test result is new __symbols__ entries for labels from the overlay after this commit. Before this commit: Console error message near end of unittest: ### dt-test ### FAIL of_unittest_overlay_high_level():2296 Adding overlay 'overlay_bad_symbol' failed ### dt-test ### end of unittest - 190 passed, 1 failed The new unittest "fails" because the expected result of loading the new overlay is an error instead of success. $ # node hvac-medium-2 exists because the overlay loaded $ # since the duplicate symbol was not detected $ cd /proc/device-tree/testcase-data-2/substation@100/ $ ls compatible hvac-medium-2 motor-8 reg hvac-large-1 linux,phandle name status hvac-medium-1 motor-1 phandle $ cd /proc/device-tree/__symbols__/ $ ls electric_1 lights_1 name rides_1 spin_ctrl_2 hvac_1 lights_2 retail_1 spin_ctrl_1 After this commit: Previous console error message no longer occurs, but expected error occurs: OF: overlay: Failed to apply prop @/__symbols__/hvac_1 OF: overlay: apply failed '/__symbols__' ### dt-test ### end of unittest - 191 passed, 0 failed $ # node hvac-medium-2 does not exist because the overlay $ # properly failed to load due to the duplicate symbol $ cd /proc/device-tree/testcase-data-2/substation@100/ $ ls compatible hvac-medium-1 motor-1 name reg hvac-large-1 linux,phandle motor-8 phandle status $ cd /proc/device-tree/__symbols__/ $ ls electric_1 lights_1 retail_1 ride_200_right spin_ctrl_2 hvac_1 lights_2 ride_200 rides_1 hvac_2 name ride_200_left spin_ctrl_1 $ cat ride_200; echo /testcase-data-2/fairway-1/ride@200 $ cat ride_200_left ; echo /testcase-data-2/fairway-1/ride@200/track@10 $ cat ride_200_right ; echo /testcase-data-2/fairway-1/ride@200/track@20 Signed-off-by: Frank Rowand <[email protected]> Signed-off-by: Rob Herring <[email protected]>
1 parent c1cd1e0 commit d1651b0

File tree

1 file changed

+107
-9
lines changed

1 file changed

+107
-9
lines changed

drivers/of/overlay.c

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
struct of_overlay_info {
3636
struct device_node *target;
3737
struct device_node *overlay;
38+
bool is_symbols_node;
3839
};
3940

4041
/**
@@ -55,7 +56,8 @@ struct of_overlay {
5556
};
5657

5758
static int of_overlay_apply_one(struct of_overlay *ov,
58-
struct device_node *target, const struct device_node *overlay);
59+
struct device_node *target, const struct device_node *overlay,
60+
bool is_symbols_node);
5961

6062
static BLOCKING_NOTIFIER_HEAD(of_overlay_chain);
6163

@@ -92,10 +94,74 @@ static int of_overlay_notify(struct of_overlay *ov,
9294
return 0;
9395
}
9496

97+
static struct property *dup_and_fixup_symbol_prop(struct of_overlay *ov,
98+
const struct property *prop)
99+
{
100+
struct of_overlay_info *ovinfo;
101+
struct property *new;
102+
const char *overlay_name;
103+
char *label_path;
104+
char *symbol_path;
105+
const char *target_path;
106+
int k;
107+
int label_path_len;
108+
int overlay_name_len;
109+
int target_path_len;
110+
111+
if (!prop->value)
112+
return NULL;
113+
symbol_path = prop->value;
114+
115+
new = kzalloc(sizeof(*new), GFP_KERNEL);
116+
if (!new)
117+
return NULL;
118+
119+
for (k = 0; k < ov->count; k++) {
120+
ovinfo = &ov->ovinfo_tab[k];
121+
overlay_name = ovinfo->overlay->full_name;
122+
overlay_name_len = strlen(overlay_name);
123+
if (!strncasecmp(symbol_path, overlay_name, overlay_name_len))
124+
break;
125+
}
126+
127+
if (k >= ov->count)
128+
goto err_free;
129+
130+
target_path = ovinfo->target->full_name;
131+
target_path_len = strlen(target_path);
132+
133+
label_path = symbol_path + overlay_name_len;
134+
label_path_len = strlen(label_path);
135+
136+
new->name = kstrdup(prop->name, GFP_KERNEL);
137+
new->length = target_path_len + label_path_len + 1;
138+
new->value = kzalloc(new->length, GFP_KERNEL);
139+
140+
if (!new->name || !new->value)
141+
goto err_free;
142+
143+
strcpy(new->value, target_path);
144+
strcpy(new->value + target_path_len, label_path);
145+
146+
/* mark the property as dynamic */
147+
of_property_set_flag(new, OF_DYNAMIC);
148+
149+
return new;
150+
151+
err_free:
152+
kfree(new->name);
153+
kfree(new->value);
154+
kfree(new);
155+
return NULL;
156+
157+
158+
}
159+
95160
static int of_overlay_apply_single_property(struct of_overlay *ov,
96-
struct device_node *target, struct property *prop)
161+
struct device_node *target, struct property *prop,
162+
bool is_symbols_node)
97163
{
98-
struct property *propn, *tprop;
164+
struct property *propn = NULL, *tprop;
99165

100166
/* NOTE: Multiple changes of single properties not supported */
101167
tprop = of_find_property(target, prop->name, NULL);
@@ -106,7 +172,15 @@ static int of_overlay_apply_single_property(struct of_overlay *ov,
106172
of_prop_cmp(prop->name, "linux,phandle") == 0)
107173
return 0;
108174

109-
propn = __of_prop_dup(prop, GFP_KERNEL);
175+
if (is_symbols_node) {
176+
/* changing a property in __symbols__ node not allowed */
177+
if (tprop)
178+
return -EINVAL;
179+
propn = dup_and_fixup_symbol_prop(ov, prop);
180+
} else {
181+
propn = __of_prop_dup(prop, GFP_KERNEL);
182+
}
183+
110184
if (propn == NULL)
111185
return -ENOMEM;
112186

@@ -140,7 +214,7 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
140214
return -EINVAL;
141215

142216
/* apply overlay recursively */
143-
ret = of_overlay_apply_one(ov, tchild, child);
217+
ret = of_overlay_apply_one(ov, tchild, child, 0);
144218
of_node_put(tchild);
145219
} else {
146220
/* create empty tree as a target */
@@ -155,7 +229,7 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
155229
if (ret)
156230
return ret;
157231

158-
ret = of_overlay_apply_one(ov, tchild, child);
232+
ret = of_overlay_apply_one(ov, tchild, child, 0);
159233
if (ret)
160234
return ret;
161235
}
@@ -171,21 +245,27 @@ static int of_overlay_apply_single_device_node(struct of_overlay *ov,
171245
* by using the changeset.
172246
*/
173247
static int of_overlay_apply_one(struct of_overlay *ov,
174-
struct device_node *target, const struct device_node *overlay)
248+
struct device_node *target, const struct device_node *overlay,
249+
bool is_symbols_node)
175250
{
176251
struct device_node *child;
177252
struct property *prop;
178253
int ret;
179254

180255
for_each_property_of_node(overlay, prop) {
181-
ret = of_overlay_apply_single_property(ov, target, prop);
256+
ret = of_overlay_apply_single_property(ov, target, prop,
257+
is_symbols_node);
182258
if (ret) {
183259
pr_err("Failed to apply prop @%pOF/%s\n",
184260
target, prop->name);
185261
return ret;
186262
}
187263
}
188264

265+
/* do not allow symbols node to have any children */
266+
if (is_symbols_node)
267+
return 0;
268+
189269
for_each_child_of_node(overlay, child) {
190270
ret = of_overlay_apply_single_device_node(ov, target, child);
191271
if (ret != 0) {
@@ -216,7 +296,8 @@ static int of_overlay_apply(struct of_overlay *ov)
216296
for (i = 0; i < ov->count; i++) {
217297
struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i];
218298

219-
err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay);
299+
err = of_overlay_apply_one(ov, ovinfo->target, ovinfo->overlay,
300+
ovinfo->is_symbols_node);
220301
if (err != 0) {
221302
pr_err("apply failed '%pOF'\n", ovinfo->target);
222303
return err;
@@ -314,6 +395,9 @@ static int of_build_overlay_info(struct of_overlay *ov,
314395
for_each_child_of_node(tree, node)
315396
cnt++;
316397

398+
if (of_get_child_by_name(tree, "__symbols__"))
399+
cnt++;
400+
317401
ovinfo = kcalloc(cnt, sizeof(*ovinfo), GFP_KERNEL);
318402
if (ovinfo == NULL)
319403
return -ENOMEM;
@@ -325,6 +409,20 @@ static int of_build_overlay_info(struct of_overlay *ov,
325409
cnt++;
326410
}
327411

412+
node = of_get_child_by_name(tree, "__symbols__");
413+
if (node) {
414+
ovinfo[cnt].overlay = node;
415+
ovinfo[cnt].target = of_find_node_by_path("/__symbols__");
416+
ovinfo[cnt].is_symbols_node = 1;
417+
418+
if (!ovinfo[cnt].target) {
419+
pr_err("no symbols in root of device tree.\n");
420+
return -EINVAL;
421+
}
422+
423+
cnt++;
424+
}
425+
328426
/* if nothing filled, return error */
329427
if (cnt == 0) {
330428
kfree(ovinfo);

0 commit comments

Comments
 (0)