1
2
3
4
5
6
7
8
9#define pr_fmt(fmt) "OF: overlay: " fmt
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/of_fdt.h>
16#include <linux/string.h>
17#include <linux/ctype.h>
18#include <linux/errno.h>
19#include <linux/slab.h>
20#include <linux/libfdt.h>
21#include <linux/err.h>
22#include <linux/idr.h>
23
24#include "of_private.h"
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41struct target {
42 struct device_node *np;
43 bool in_livetree;
44};
45
46
47
48
49
50
51struct fragment {
52 struct device_node *overlay;
53 struct device_node *target;
54};
55
56
57
58
59
60
61
62
63
64
65
66
67struct overlay_changeset {
68 int id;
69 struct list_head ovcs_list;
70 const void *fdt;
71 struct device_node *overlay_tree;
72 int count;
73 struct fragment *fragments;
74 bool symbols_fragment;
75 struct of_changeset cset;
76};
77
78
79static int devicetree_state_flags;
80#define DTSF_APPLY_FAIL 0x01
81#define DTSF_REVERT_FAIL 0x02
82
83
84
85
86
87
88static int devicetree_corrupt(void)
89{
90 return devicetree_state_flags &
91 (DTSF_APPLY_FAIL | DTSF_REVERT_FAIL);
92}
93
94static int build_changeset_next_level(struct overlay_changeset *ovcs,
95 struct target *target, const struct device_node *overlay_node);
96
97
98
99
100
101
102
103
104
105
106static DEFINE_MUTEX(of_overlay_phandle_mutex);
107
108void of_overlay_mutex_lock(void)
109{
110 mutex_lock(&of_overlay_phandle_mutex);
111}
112
113void of_overlay_mutex_unlock(void)
114{
115 mutex_unlock(&of_overlay_phandle_mutex);
116}
117
118
119static LIST_HEAD(ovcs_list);
120static DEFINE_IDR(ovcs_idr);
121
122static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain);
123
124
125
126
127
128
129
130
131
132
133
134
135
136int of_overlay_notifier_register(struct notifier_block *nb)
137{
138 return blocking_notifier_chain_register(&overlay_notify_chain, nb);
139}
140EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
141
142
143
144
145
146int of_overlay_notifier_unregister(struct notifier_block *nb)
147{
148 return blocking_notifier_chain_unregister(&overlay_notify_chain, nb);
149}
150EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister);
151
152static char *of_overlay_action_name[] = {
153 "pre-apply",
154 "post-apply",
155 "pre-remove",
156 "post-remove",
157};
158
159static int overlay_notify(struct overlay_changeset *ovcs,
160 enum of_overlay_notify_action action)
161{
162 struct of_overlay_notify_data nd;
163 int i, ret;
164
165 for (i = 0; i < ovcs->count; i++) {
166 struct fragment *fragment = &ovcs->fragments[i];
167
168 nd.target = fragment->target;
169 nd.overlay = fragment->overlay;
170
171 ret = blocking_notifier_call_chain(&overlay_notify_chain,
172 action, &nd);
173 if (ret == NOTIFY_OK || ret == NOTIFY_STOP)
174 return 0;
175 if (ret) {
176 ret = notifier_to_errno(ret);
177 pr_err("overlay changeset %s notifier error %d, target: %pOF\n",
178 of_overlay_action_name[action], ret, nd.target);
179 return ret;
180 }
181 }
182
183 return 0;
184}
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199static struct property *dup_and_fixup_symbol_prop(
200 struct overlay_changeset *ovcs, const struct property *prop)
201{
202 struct fragment *fragment;
203 struct property *new_prop;
204 struct device_node *fragment_node;
205 struct device_node *overlay_node;
206 const char *path;
207 const char *path_tail;
208 const char *target_path;
209 int k;
210 int overlay_name_len;
211 int path_len;
212 int path_tail_len;
213 int target_path_len;
214
215 if (!prop->value)
216 return NULL;
217 if (strnlen(prop->value, prop->length) >= prop->length)
218 return NULL;
219 path = prop->value;
220 path_len = strlen(path);
221
222 if (path_len < 1)
223 return NULL;
224 fragment_node = __of_find_node_by_path(ovcs->overlay_tree, path + 1);
225 overlay_node = __of_find_node_by_path(fragment_node, "__overlay__/");
226 of_node_put(fragment_node);
227 of_node_put(overlay_node);
228
229 for (k = 0; k < ovcs->count; k++) {
230 fragment = &ovcs->fragments[k];
231 if (fragment->overlay == overlay_node)
232 break;
233 }
234 if (k >= ovcs->count)
235 return NULL;
236
237 overlay_name_len = snprintf(NULL, 0, "%pOF", fragment->overlay);
238
239 if (overlay_name_len > path_len)
240 return NULL;
241 path_tail = path + overlay_name_len;
242 path_tail_len = strlen(path_tail);
243
244 target_path = kasprintf(GFP_KERNEL, "%pOF", fragment->target);
245 if (!target_path)
246 return NULL;
247 target_path_len = strlen(target_path);
248
249 new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
250 if (!new_prop)
251 goto err_free_target_path;
252
253 new_prop->name = kstrdup(prop->name, GFP_KERNEL);
254 new_prop->length = target_path_len + path_tail_len + 1;
255 new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
256 if (!new_prop->name || !new_prop->value)
257 goto err_free_new_prop;
258
259 strcpy(new_prop->value, target_path);
260 strcpy(new_prop->value + target_path_len, path_tail);
261
262 of_property_set_flag(new_prop, OF_DYNAMIC);
263
264 kfree(target_path);
265
266 return new_prop;
267
268err_free_new_prop:
269 kfree(new_prop->name);
270 kfree(new_prop->value);
271 kfree(new_prop);
272err_free_target_path:
273 kfree(target_path);
274
275 return NULL;
276}
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304static int add_changeset_property(struct overlay_changeset *ovcs,
305 struct target *target, struct property *overlay_prop,
306 bool is_symbols_prop)
307{
308 struct property *new_prop = NULL, *prop;
309 int ret = 0;
310
311 if (target->in_livetree)
312 if (!of_prop_cmp(overlay_prop->name, "name") ||
313 !of_prop_cmp(overlay_prop->name, "phandle") ||
314 !of_prop_cmp(overlay_prop->name, "linux,phandle"))
315 return 0;
316
317 if (target->in_livetree)
318 prop = of_find_property(target->np, overlay_prop->name, NULL);
319 else
320 prop = NULL;
321
322 if (prop) {
323 if (!of_prop_cmp(prop->name, "#address-cells")) {
324 if (!of_prop_val_eq(prop, overlay_prop)) {
325 pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
326 target->np);
327 ret = -EINVAL;
328 }
329 return ret;
330
331 } else if (!of_prop_cmp(prop->name, "#size-cells")) {
332 if (!of_prop_val_eq(prop, overlay_prop)) {
333 pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
334 target->np);
335 ret = -EINVAL;
336 }
337 return ret;
338 }
339 }
340
341 if (is_symbols_prop) {
342 if (prop)
343 return -EINVAL;
344 new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop);
345 } else {
346 new_prop = __of_prop_dup(overlay_prop, GFP_KERNEL);
347 }
348
349 if (!new_prop)
350 return -ENOMEM;
351
352 if (!prop) {
353 if (!target->in_livetree) {
354 new_prop->next = target->np->deadprops;
355 target->np->deadprops = new_prop;
356 }
357 ret = of_changeset_add_property(&ovcs->cset, target->np,
358 new_prop);
359 } else {
360 ret = of_changeset_update_property(&ovcs->cset, target->np,
361 new_prop);
362 }
363
364 if (!of_node_check_flag(target->np, OF_OVERLAY))
365 pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
366 target->np, new_prop->name);
367
368 if (ret) {
369 kfree(new_prop->name);
370 kfree(new_prop->value);
371 kfree(new_prop);
372 }
373 return ret;
374}
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409static int add_changeset_node(struct overlay_changeset *ovcs,
410 struct target *target, struct device_node *node)
411{
412 const char *node_kbasename;
413 const __be32 *phandle;
414 struct device_node *tchild;
415 struct target target_child;
416 int ret = 0, size;
417
418 node_kbasename = kbasename(node->full_name);
419
420 for_each_child_of_node(target->np, tchild)
421 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
422 break;
423
424 if (!tchild) {
425 tchild = __of_node_dup(NULL, node_kbasename);
426 if (!tchild)
427 return -ENOMEM;
428
429 tchild->parent = target->np;
430 tchild->name = __of_get_property(node, "name", NULL);
431
432 if (!tchild->name)
433 tchild->name = "<NULL>";
434
435
436 phandle = __of_get_property(node, "phandle", &size);
437 if (phandle && (size == 4))
438 tchild->phandle = be32_to_cpup(phandle);
439
440 of_node_set_flag(tchild, OF_OVERLAY);
441
442 ret = of_changeset_attach_node(&ovcs->cset, tchild);
443 if (ret)
444 return ret;
445
446 target_child.np = tchild;
447 target_child.in_livetree = false;
448
449 ret = build_changeset_next_level(ovcs, &target_child, node);
450 of_node_put(tchild);
451 return ret;
452 }
453
454 if (node->phandle && tchild->phandle) {
455 ret = -EINVAL;
456 } else {
457 target_child.np = tchild;
458 target_child.in_livetree = target->in_livetree;
459 ret = build_changeset_next_level(ovcs, &target_child, node);
460 }
461 of_node_put(tchild);
462
463 return ret;
464}
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481static int build_changeset_next_level(struct overlay_changeset *ovcs,
482 struct target *target, const struct device_node *overlay_node)
483{
484 struct device_node *child;
485 struct property *prop;
486 int ret;
487
488 for_each_property_of_node(overlay_node, prop) {
489 ret = add_changeset_property(ovcs, target, prop, 0);
490 if (ret) {
491 pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
492 target->np, prop->name, ret);
493 return ret;
494 }
495 }
496
497 for_each_child_of_node(overlay_node, child) {
498 ret = add_changeset_node(ovcs, target, child);
499 if (ret) {
500 pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n",
501 target->np, child, ret);
502 of_node_put(child);
503 return ret;
504 }
505 }
506
507 return 0;
508}
509
510
511
512
513static int build_changeset_symbols_node(struct overlay_changeset *ovcs,
514 struct target *target,
515 const struct device_node *overlay_symbols_node)
516{
517 struct property *prop;
518 int ret;
519
520 for_each_property_of_node(overlay_symbols_node, prop) {
521 ret = add_changeset_property(ovcs, target, prop, 1);
522 if (ret) {
523 pr_debug("Failed to apply symbols prop @%pOF/%s, err=%d\n",
524 target->np, prop->name, ret);
525 return ret;
526 }
527 }
528
529 return 0;
530}
531
532static int find_dup_cset_node_entry(struct overlay_changeset *ovcs,
533 struct of_changeset_entry *ce_1)
534{
535 struct of_changeset_entry *ce_2;
536 char *fn_1, *fn_2;
537 int node_path_match;
538
539 if (ce_1->action != OF_RECONFIG_ATTACH_NODE &&
540 ce_1->action != OF_RECONFIG_DETACH_NODE)
541 return 0;
542
543 ce_2 = ce_1;
544 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
545 if ((ce_2->action != OF_RECONFIG_ATTACH_NODE &&
546 ce_2->action != OF_RECONFIG_DETACH_NODE) ||
547 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
548 continue;
549
550 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
551 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
552 node_path_match = !strcmp(fn_1, fn_2);
553 kfree(fn_1);
554 kfree(fn_2);
555 if (node_path_match) {
556 pr_err("ERROR: multiple fragments add and/or delete node %pOF\n",
557 ce_1->np);
558 return -EINVAL;
559 }
560 }
561
562 return 0;
563}
564
565static int find_dup_cset_prop(struct overlay_changeset *ovcs,
566 struct of_changeset_entry *ce_1)
567{
568 struct of_changeset_entry *ce_2;
569 char *fn_1, *fn_2;
570 int node_path_match;
571
572 if (ce_1->action != OF_RECONFIG_ADD_PROPERTY &&
573 ce_1->action != OF_RECONFIG_REMOVE_PROPERTY &&
574 ce_1->action != OF_RECONFIG_UPDATE_PROPERTY)
575 return 0;
576
577 ce_2 = ce_1;
578 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
579 if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY &&
580 ce_2->action != OF_RECONFIG_REMOVE_PROPERTY &&
581 ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) ||
582 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
583 continue;
584
585 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
586 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
587 node_path_match = !strcmp(fn_1, fn_2);
588 kfree(fn_1);
589 kfree(fn_2);
590 if (node_path_match &&
591 !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) {
592 pr_err("ERROR: multiple fragments add, update, and/or delete property %pOF/%s\n",
593 ce_1->np, ce_1->prop->name);
594 return -EINVAL;
595 }
596 }
597
598 return 0;
599}
600
601
602
603
604
605
606
607
608
609
610
611static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
612{
613 struct of_changeset_entry *ce_1;
614 int dup_entry = 0;
615
616 list_for_each_entry(ce_1, &ovcs->cset.entries, node) {
617 dup_entry |= find_dup_cset_node_entry(ovcs, ce_1);
618 dup_entry |= find_dup_cset_prop(ovcs, ce_1);
619 }
620
621 return dup_entry ? -EINVAL : 0;
622}
623
624
625
626
627
628
629
630
631
632
633
634
635
636static int build_changeset(struct overlay_changeset *ovcs)
637{
638 struct fragment *fragment;
639 struct target target;
640 int fragments_count, i, ret;
641
642
643
644
645
646 if (ovcs->symbols_fragment)
647 fragments_count = ovcs->count - 1;
648 else
649 fragments_count = ovcs->count;
650
651 for (i = 0; i < fragments_count; i++) {
652 fragment = &ovcs->fragments[i];
653
654 target.np = fragment->target;
655 target.in_livetree = true;
656 ret = build_changeset_next_level(ovcs, &target,
657 fragment->overlay);
658 if (ret) {
659 pr_debug("fragment apply failed '%pOF'\n",
660 fragment->target);
661 return ret;
662 }
663 }
664
665 if (ovcs->symbols_fragment) {
666 fragment = &ovcs->fragments[ovcs->count - 1];
667
668 target.np = fragment->target;
669 target.in_livetree = true;
670 ret = build_changeset_symbols_node(ovcs, &target,
671 fragment->overlay);
672 if (ret) {
673 pr_debug("symbols fragment apply failed '%pOF'\n",
674 fragment->target);
675 return ret;
676 }
677 }
678
679 return changeset_dup_entry_check(ovcs);
680}
681
682
683
684
685
686
687
688
689static struct device_node *find_target(struct device_node *info_node)
690{
691 struct device_node *node;
692 const char *path;
693 u32 val;
694 int ret;
695
696 ret = of_property_read_u32(info_node, "target", &val);
697 if (!ret) {
698 node = of_find_node_by_phandle(val);
699 if (!node)
700 pr_err("find target, node: %pOF, phandle 0x%x not found\n",
701 info_node, val);
702 return node;
703 }
704
705 ret = of_property_read_string(info_node, "target-path", &path);
706 if (!ret) {
707 node = of_find_node_by_path(path);
708 if (!node)
709 pr_err("find target, node: %pOF, path '%s' not found\n",
710 info_node, path);
711 return node;
712 }
713
714 pr_err("find target, node: %pOF, no target property\n", info_node);
715
716 return NULL;
717}
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732static int init_overlay_changeset(struct overlay_changeset *ovcs,
733 const void *fdt, struct device_node *tree)
734{
735 struct device_node *node, *overlay_node;
736 struct fragment *fragment;
737 struct fragment *fragments;
738 int cnt, id, ret;
739
740
741
742
743
744 if (!of_node_check_flag(tree, OF_DYNAMIC))
745 pr_debug("%s() tree is not dynamic\n", __func__);
746
747 if (!of_node_check_flag(tree, OF_DETACHED))
748 pr_debug("%s() tree is not detached\n", __func__);
749
750 if (!of_node_is_root(tree))
751 pr_debug("%s() tree is not root\n", __func__);
752
753 ovcs->overlay_tree = tree;
754 ovcs->fdt = fdt;
755
756 INIT_LIST_HEAD(&ovcs->ovcs_list);
757
758 of_changeset_init(&ovcs->cset);
759
760 id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
761 if (id <= 0)
762 return id;
763
764 cnt = 0;
765
766
767 for_each_child_of_node(tree, node) {
768 overlay_node = of_get_child_by_name(node, "__overlay__");
769 if (overlay_node) {
770 cnt++;
771 of_node_put(overlay_node);
772 }
773 }
774
775 node = of_get_child_by_name(tree, "__symbols__");
776 if (node) {
777 cnt++;
778 of_node_put(node);
779 }
780
781 fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
782 if (!fragments) {
783 ret = -ENOMEM;
784 goto err_free_idr;
785 }
786
787 cnt = 0;
788 for_each_child_of_node(tree, node) {
789 overlay_node = of_get_child_by_name(node, "__overlay__");
790 if (!overlay_node)
791 continue;
792
793 fragment = &fragments[cnt];
794 fragment->overlay = overlay_node;
795 fragment->target = find_target(node);
796 if (!fragment->target) {
797 of_node_put(fragment->overlay);
798 ret = -EINVAL;
799 goto err_free_fragments;
800 }
801
802 cnt++;
803 }
804
805
806
807
808
809 node = of_get_child_by_name(tree, "__symbols__");
810 if (node) {
811 ovcs->symbols_fragment = 1;
812 fragment = &fragments[cnt];
813 fragment->overlay = node;
814 fragment->target = of_find_node_by_path("/__symbols__");
815
816 if (!fragment->target) {
817 pr_err("symbols in overlay, but not in live tree\n");
818 ret = -EINVAL;
819 goto err_free_fragments;
820 }
821
822 cnt++;
823 }
824
825 if (!cnt) {
826 pr_err("no fragments or symbols in overlay\n");
827 ret = -EINVAL;
828 goto err_free_fragments;
829 }
830
831 ovcs->id = id;
832 ovcs->count = cnt;
833 ovcs->fragments = fragments;
834
835 return 0;
836
837err_free_fragments:
838 kfree(fragments);
839err_free_idr:
840 idr_remove(&ovcs_idr, id);
841
842 pr_err("%s() failed, ret = %d\n", __func__, ret);
843
844 return ret;
845}
846
847static void free_overlay_changeset(struct overlay_changeset *ovcs)
848{
849 int i;
850
851 if (ovcs->cset.entries.next)
852 of_changeset_destroy(&ovcs->cset);
853
854 if (ovcs->id)
855 idr_remove(&ovcs_idr, ovcs->id);
856
857 for (i = 0; i < ovcs->count; i++) {
858 of_node_put(ovcs->fragments[i].target);
859 of_node_put(ovcs->fragments[i].overlay);
860 }
861 kfree(ovcs->fragments);
862
863
864
865
866
867 kfree(ovcs->overlay_tree);
868 kfree(ovcs->fdt);
869 kfree(ovcs);
870}
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915static int of_overlay_apply(const void *fdt, struct device_node *tree,
916 int *ovcs_id)
917{
918 struct overlay_changeset *ovcs;
919 int ret = 0, ret_revert, ret_tmp;
920
921
922
923
924
925
926 if (devicetree_corrupt()) {
927 pr_err("devicetree state suspect, refuse to apply overlay\n");
928 kfree(fdt);
929 kfree(tree);
930 ret = -EBUSY;
931 goto out;
932 }
933
934 ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
935 if (!ovcs) {
936 kfree(fdt);
937 kfree(tree);
938 ret = -ENOMEM;
939 goto out;
940 }
941
942 of_overlay_mutex_lock();
943 mutex_lock(&of_mutex);
944
945 ret = of_resolve_phandles(tree);
946 if (ret)
947 goto err_free_tree;
948
949 ret = init_overlay_changeset(ovcs, fdt, tree);
950 if (ret)
951 goto err_free_tree;
952
953
954
955
956
957
958 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
959 if (ret) {
960 pr_err("overlay changeset pre-apply notify error %d\n", ret);
961 goto err_free_overlay_changeset;
962 }
963
964 ret = build_changeset(ovcs);
965 if (ret)
966 goto err_free_overlay_changeset;
967
968 ret_revert = 0;
969 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
970 if (ret) {
971 if (ret_revert) {
972 pr_debug("overlay changeset revert error %d\n",
973 ret_revert);
974 devicetree_state_flags |= DTSF_APPLY_FAIL;
975 }
976 goto err_free_overlay_changeset;
977 }
978
979 ret = __of_changeset_apply_notify(&ovcs->cset);
980 if (ret)
981 pr_err("overlay apply changeset entry notify error %d\n", ret);
982
983
984 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
985 *ovcs_id = ovcs->id;
986
987 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);
988 if (ret_tmp) {
989 pr_err("overlay changeset post-apply notify error %d\n",
990 ret_tmp);
991 if (!ret)
992 ret = ret_tmp;
993 }
994
995 goto out_unlock;
996
997err_free_tree:
998 kfree(fdt);
999 kfree(tree);
1000
1001err_free_overlay_changeset:
1002 free_overlay_changeset(ovcs);
1003
1004out_unlock:
1005 mutex_unlock(&of_mutex);
1006 of_overlay_mutex_unlock();
1007
1008out:
1009 pr_debug("%s() err=%d\n", __func__, ret);
1010
1011 return ret;
1012}
1013
1014int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
1015 int *ovcs_id)
1016{
1017 const void *new_fdt;
1018 int ret;
1019 u32 size;
1020 struct device_node *overlay_root;
1021
1022 *ovcs_id = 0;
1023 ret = 0;
1024
1025 if (overlay_fdt_size < sizeof(struct fdt_header) ||
1026 fdt_check_header(overlay_fdt)) {
1027 pr_err("Invalid overlay_fdt header\n");
1028 return -EINVAL;
1029 }
1030
1031 size = fdt_totalsize(overlay_fdt);
1032 if (overlay_fdt_size < size)
1033 return -EINVAL;
1034
1035
1036
1037
1038
1039 new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL);
1040 if (!new_fdt)
1041 return -ENOMEM;
1042
1043 of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root);
1044 if (!overlay_root) {
1045 pr_err("unable to unflatten overlay_fdt\n");
1046 ret = -EINVAL;
1047 goto out_free_new_fdt;
1048 }
1049
1050 ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
1051 if (ret < 0) {
1052
1053
1054
1055
1056
1057 goto out;
1058 }
1059
1060 return 0;
1061
1062
1063out_free_new_fdt:
1064 kfree(new_fdt);
1065
1066out:
1067 return ret;
1068}
1069EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
1070
1071
1072
1073
1074
1075
1076static int find_node(struct device_node *tree, struct device_node *np)
1077{
1078 struct device_node *child;
1079
1080 if (tree == np)
1081 return 1;
1082
1083 for_each_child_of_node(tree, child) {
1084 if (find_node(child, np)) {
1085 of_node_put(child);
1086 return 1;
1087 }
1088 }
1089
1090 return 0;
1091}
1092
1093
1094
1095
1096
1097
1098
1099static int node_overlaps_later_cs(struct overlay_changeset *remove_ovcs,
1100 struct device_node *remove_ce_node)
1101{
1102 struct overlay_changeset *ovcs;
1103 struct of_changeset_entry *ce;
1104
1105 list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) {
1106 if (ovcs == remove_ovcs)
1107 break;
1108
1109 list_for_each_entry(ce, &ovcs->cset.entries, node) {
1110 if (find_node(ce->np, remove_ce_node)) {
1111 pr_err("%s: #%d overlaps with #%d @%pOF\n",
1112 __func__, remove_ovcs->id, ovcs->id,
1113 remove_ce_node);
1114 return 1;
1115 }
1116 if (find_node(remove_ce_node, ce->np)) {
1117 pr_err("%s: #%d overlaps with #%d @%pOF\n",
1118 __func__, remove_ovcs->id, ovcs->id,
1119 remove_ce_node);
1120 return 1;
1121 }
1122 }
1123 }
1124
1125 return 0;
1126}
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
1139{
1140 struct of_changeset_entry *remove_ce;
1141
1142 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) {
1143 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) {
1144 pr_err("overlay #%d is not topmost\n", remove_ovcs->id);
1145 return 0;
1146 }
1147 }
1148
1149 return 1;
1150}
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186int of_overlay_remove(int *ovcs_id)
1187{
1188 struct overlay_changeset *ovcs;
1189 int ret, ret_apply, ret_tmp;
1190
1191 ret = 0;
1192
1193 if (devicetree_corrupt()) {
1194 pr_err("suspect devicetree state, refuse to remove overlay\n");
1195 ret = -EBUSY;
1196 goto out;
1197 }
1198
1199 mutex_lock(&of_mutex);
1200
1201 ovcs = idr_find(&ovcs_idr, *ovcs_id);
1202 if (!ovcs) {
1203 ret = -ENODEV;
1204 pr_err("remove: Could not find overlay #%d\n", *ovcs_id);
1205 goto out_unlock;
1206 }
1207
1208 if (!overlay_removal_is_ok(ovcs)) {
1209 ret = -EBUSY;
1210 goto out_unlock;
1211 }
1212
1213 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE);
1214 if (ret) {
1215 pr_err("overlay changeset pre-remove notify error %d\n", ret);
1216 goto out_unlock;
1217 }
1218
1219 list_del(&ovcs->ovcs_list);
1220
1221 ret_apply = 0;
1222 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
1223 if (ret) {
1224 if (ret_apply)
1225 devicetree_state_flags |= DTSF_REVERT_FAIL;
1226 goto out_unlock;
1227 }
1228
1229 ret = __of_changeset_revert_notify(&ovcs->cset);
1230 if (ret)
1231 pr_err("overlay remove changeset entry notify error %d\n", ret);
1232
1233
1234 *ovcs_id = 0;
1235
1236 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE);
1237 if (ret_tmp) {
1238 pr_err("overlay changeset post-remove notify error %d\n",
1239 ret_tmp);
1240 if (!ret)
1241 ret = ret_tmp;
1242 }
1243
1244 free_overlay_changeset(ovcs);
1245
1246out_unlock:
1247 mutex_unlock(&of_mutex);
1248
1249out:
1250 pr_debug("%s() err=%d\n", __func__, ret);
1251
1252 return ret;
1253}
1254EXPORT_SYMBOL_GPL(of_overlay_remove);
1255
1256
1257
1258
1259
1260
1261
1262
1263int of_overlay_remove_all(void)
1264{
1265 struct overlay_changeset *ovcs, *ovcs_n;
1266 int ret;
1267
1268
1269 list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) {
1270 ret = of_overlay_remove(&ovcs->id);
1271 if (ret)
1272 return ret;
1273 }
1274
1275 return 0;
1276}
1277EXPORT_SYMBOL_GPL(of_overlay_remove_all);
1278