summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@sony.com>2018-10-04 23:35:14 -0400
committerFrank Rowand <frank.rowand@sony.com>2018-11-09 01:11:57 -0500
commitc168263b5a10d2434ad5051be8dda47baa34a98e (patch)
tree002503e24c65a82154652fc551e8a7a59d0680d2
parenta68238a19c3b24e43fd2327d102bcea0ccceb7d0 (diff)
of: overlay: check prevents multiple fragments add or delete same node
Multiple overlay fragments adding or deleting the same node is not supported. Replace code comment of such, with check to detect the attempt and fail the overlay apply. Devicetree unittest where multiple fragments added the same node was added in the previous patch in the series. After applying this patch the unittest messages will no longer include: Duplicate name in motor-1, renamed to "controller#1" OF: overlay: of_overlay_apply() err=0 ### dt-test ### of_overlay_fdt_apply() expected -22, ret=0, overlay_bad_add_dup_node ### dt-test ### FAIL of_unittest_overlay_high_level():2419 Adding overlay 'overlay_bad_add_dup_node' failed ... ### dt-test ### end of unittest - 210 passed, 1 failed but will instead include: OF: overlay: ERROR: multiple overlay fragments add and/or delete node /testcase-data-2/substation@100/motor-1/controller ... ### dt-test ### end of unittest - 211 passed, 0 failed Tested-by: Alan Tull <atull@kernel.org> Signed-off-by: Frank Rowand <frank.rowand@sony.com>
-rw-r--r--drivers/of/overlay.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index c8f88b0836a3..8af8115bd36e 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -392,14 +392,6 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
392 * a live devicetree created from Open Firmware. 392 * a live devicetree created from Open Firmware.
393 * 393 *
394 * NOTE_2: Multiple mods of created nodes not supported. 394 * NOTE_2: Multiple mods of created nodes not supported.
395 * If more than one fragment contains a node that does not already exist
396 * in the live tree, then for each fragment of_changeset_attach_node()
397 * will add a changeset entry to add the node. When the changeset is
398 * applied, __of_attach_node() will attach the node twice (once for
399 * each fragment). At this point the device tree will be corrupted.
400 *
401 * TODO: add integrity check to ensure that multiple fragments do not
402 * create the same node.
403 * 395 *
404 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if 396 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
405 * invalid @overlay. 397 * invalid @overlay.
@@ -517,6 +509,54 @@ static int build_changeset_symbols_node(struct overlay_changeset *ovcs,
517} 509}
518 510
519/** 511/**
512 * check_changeset_dup_add_node() - changeset validation: duplicate add node
513 * @ovcs: Overlay changeset
514 *
515 * Check changeset @ovcs->cset for multiple add node entries for the same
516 * node.
517 *
518 * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
519 * invalid overlay in @ovcs->fragments[].
520 */
521static int check_changeset_dup_add_node(struct overlay_changeset *ovcs)
522{
523 struct of_changeset_entry *ce_1, *ce_2;
524 char *fn_1, *fn_2;
525 int name_match;
526
527 list_for_each_entry(ce_1, &ovcs->cset.entries, node) {
528
529 if (ce_1->action == OF_RECONFIG_ATTACH_NODE ||
530 ce_1->action == OF_RECONFIG_DETACH_NODE) {
531
532 ce_2 = ce_1;
533 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
534 if (ce_2->action == OF_RECONFIG_ATTACH_NODE ||
535 ce_2->action == OF_RECONFIG_DETACH_NODE) {
536 /* inexpensive name compare */
537 if (!of_node_cmp(ce_1->np->full_name,
538 ce_2->np->full_name)) {
539 /* expensive full path name compare */
540 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
541 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
542 name_match = !strcmp(fn_1, fn_2);
543 kfree(fn_1);
544 kfree(fn_2);
545 if (name_match) {
546 pr_err("ERROR: multiple overlay fragments add and/or delete node %pOF\n",
547 ce_1->np);
548 return -EINVAL;
549 }
550 }
551 }
552 }
553 }
554 }
555
556 return 0;
557}
558
559/**
520 * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments 560 * build_changeset() - populate overlay changeset in @ovcs from @ovcs->fragments
521 * @ovcs: Overlay changeset 561 * @ovcs: Overlay changeset
522 * 562 *
@@ -571,7 +611,7 @@ static int build_changeset(struct overlay_changeset *ovcs)
571 } 611 }
572 } 612 }
573 613
574 return 0; 614 return check_changeset_dup_add_node(ovcs);
575} 615}
576 616
577/* 617/*