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 return new_prop;
265
266err_free_new_prop:
267 kfree(new_prop->name);
268 kfree(new_prop->value);
269 kfree(new_prop);
270err_free_target_path:
271 kfree(target_path);
272
273 return NULL;
274}
275
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
302static int add_changeset_property(struct overlay_changeset *ovcs,
303 struct target *target, struct property *overlay_prop,
304 bool is_symbols_prop)
305{
306 struct property *new_prop = NULL, *prop;
307 int ret = 0;
308 bool check_for_non_overlay_node = false;
309
310 if (target->in_livetree)
311 if (!of_prop_cmp(overlay_prop->name, "name") ||
312 !of_prop_cmp(overlay_prop->name, "phandle") ||
313 !of_prop_cmp(overlay_prop->name, "linux,phandle"))
314 return 0;
315
316 if (target->in_livetree)
317 prop = of_find_property(target->np, overlay_prop->name, NULL);
318 else
319 prop = NULL;
320
321 if (is_symbols_prop) {
322 if (prop)
323 return -EINVAL;
324 new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop);
325 } else {
326 new_prop = __of_prop_dup(overlay_prop, GFP_KERNEL);
327 }
328
329 if (!new_prop)
330 return -ENOMEM;
331
332 if (!prop) {
333 check_for_non_overlay_node = true;
334 if (!target->in_livetree) {
335 new_prop->next = target->np->deadprops;
336 target->np->deadprops = new_prop;
337 }
338 ret = of_changeset_add_property(&ovcs->cset, target->np,
339 new_prop);
340 } else if (!of_prop_cmp(prop->name, "#address-cells")) {
341 if (!of_prop_val_eq(prop, new_prop)) {
342 pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
343 target->np);
344 ret = -EINVAL;
345 }
346 } else if (!of_prop_cmp(prop->name, "#size-cells")) {
347 if (!of_prop_val_eq(prop, new_prop)) {
348 pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
349 target->np);
350 ret = -EINVAL;
351 }
352 } else {
353 check_for_non_overlay_node = true;
354 ret = of_changeset_update_property(&ovcs->cset, target->np,
355 new_prop);
356 }
357
358 if (check_for_non_overlay_node &&
359 !of_node_check_flag(target->np, OF_OVERLAY))
360 pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
361 target->np, new_prop->name);
362
363 if (ret) {
364 kfree(new_prop->name);
365 kfree(new_prop->value);
366 kfree(new_prop);
367 }
368 return ret;
369}
370
371
372
373
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
404static int add_changeset_node(struct overlay_changeset *ovcs,
405 struct target *target, struct device_node *node)
406{
407 const char *node_kbasename;
408 const __be32 *phandle;
409 struct device_node *tchild;
410 struct target target_child;
411 int ret = 0, size;
412
413 node_kbasename = kbasename(node->full_name);
414
415 for_each_child_of_node(target->np, tchild)
416 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
417 break;
418
419 if (!tchild) {
420 tchild = __of_node_dup(NULL, node_kbasename);
421 if (!tchild)
422 return -ENOMEM;
423
424 tchild->parent = target->np;
425 tchild->name = __of_get_property(node, "name", NULL);
426
427 if (!tchild->name)
428 tchild->name = "<NULL>";
429
430
431 phandle = __of_get_property(node, "phandle", &size);
432 if (phandle && (size == 4))
433 tchild->phandle = be32_to_cpup(phandle);
434
435 of_node_set_flag(tchild, OF_OVERLAY);
436
437 ret = of_changeset_attach_node(&ovcs->cset, tchild);
438 if (ret)
439 return ret;
440
441 target_child.np = tchild;
442 target_child.in_livetree = false;
443
444 ret = build_changeset_next_level(ovcs, &target_child, node);
445 of_node_put(tchild);
446 return ret;
447 }
448
449 if (node->phandle && tchild->phandle) {
450 ret = -EINVAL;
451 } else {
452 target_child.np = tchild;
453 target_child.in_livetree = target->in_livetree;
454 ret = build_changeset_next_level(ovcs, &target_child, node);
455 }
456 of_node_put(tchild);
457
458 return ret;
459}
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476static int build_changeset_next_level(struct overlay_changeset *ovcs,
477 struct target *target, const struct device_node *overlay_node)
478{
479 struct device_node *child;
480 struct property *prop;
481 int ret;
482
483 for_each_property_of_node(overlay_node, prop) {
484 ret = add_changeset_property(ovcs, target, prop, 0);
485 if (ret) {
486 pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
487 target->np, prop->name, ret);
488 return ret;
489 }
490 }
491
492 for_each_child_of_node(overlay_node, child) {
493 ret = add_changeset_node(ovcs, target, child);
494 if (ret) {
495 pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n",
496 target->np, child, ret);
497 of_node_put(child);
498 return ret;
499 }
500 }
501
502 return 0;
503}
504
505
506
507
508static int build_changeset_symbols_node(struct overlay_changeset *ovcs,
509 struct target *target,
510 const struct device_node *overlay_symbols_node)
511{
512 struct property *prop;
513 int ret;
514
515 for_each_property_of_node(overlay_symbols_node, prop) {
516 ret = add_changeset_property(ovcs, target, prop, 1);
517 if (ret) {
518 pr_debug("Failed to apply symbols prop @%pOF/%s, err=%d\n",
519 target->np, prop->name, ret);
520 return ret;
521 }
522 }
523
524 return 0;
525}
526
527static int find_dup_cset_node_entry(struct overlay_changeset *ovcs,
528 struct of_changeset_entry *ce_1)
529{
530 struct of_changeset_entry *ce_2;
531 char *fn_1, *fn_2;
532 int node_path_match;
533
534 if (ce_1->action != OF_RECONFIG_ATTACH_NODE &&
535 ce_1->action != OF_RECONFIG_DETACH_NODE)
536 return 0;
537
538 ce_2 = ce_1;
539 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
540 if ((ce_2->action != OF_RECONFIG_ATTACH_NODE &&
541 ce_2->action != OF_RECONFIG_DETACH_NODE) ||
542 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
543 continue;
544
545 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
546 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
547 node_path_match = !strcmp(fn_1, fn_2);
548 kfree(fn_1);
549 kfree(fn_2);
550 if (node_path_match) {
551 pr_err("ERROR: multiple fragments add and/or delete node %pOF\n",
552 ce_1->np);
553 return -EINVAL;
554 }
555 }
556
557 return 0;
558}
559
560static int find_dup_cset_prop(struct overlay_changeset *ovcs,
561 struct of_changeset_entry *ce_1)
562{
563 struct of_changeset_entry *ce_2;
564 char *fn_1, *fn_2;
565 int node_path_match;
566
567 if (ce_1->action != OF_RECONFIG_ADD_PROPERTY &&
568 ce_1->action != OF_RECONFIG_REMOVE_PROPERTY &&
569 ce_1->action != OF_RECONFIG_UPDATE_PROPERTY)
570 return 0;
571
572 ce_2 = ce_1;
573 list_for_each_entry_continue(ce_2, &ovcs->cset.entries, node) {
574 if ((ce_2->action != OF_RECONFIG_ADD_PROPERTY &&
575 ce_2->action != OF_RECONFIG_REMOVE_PROPERTY &&
576 ce_2->action != OF_RECONFIG_UPDATE_PROPERTY) ||
577 of_node_cmp(ce_1->np->full_name, ce_2->np->full_name))
578 continue;
579
580 fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
581 fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
582 node_path_match = !strcmp(fn_1, fn_2);
583 kfree(fn_1);
584 kfree(fn_2);
585 if (node_path_match &&
586 !of_prop_cmp(ce_1->prop->name, ce_2->prop->name)) {
587 pr_err("ERROR: multiple fragments add, update, and/or delete property %pOF/%s\n",
588 ce_1->np, ce_1->prop->name);
589 return -EINVAL;
590 }
591 }
592
593 return 0;
594}
595
596
597
598
599
600
601
602
603
604
605
606static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
607{
608 struct of_changeset_entry *ce_1;
609 int dup_entry = 0;
610
611 list_for_each_entry(ce_1, &ovcs->cset.entries, node) {
612 dup_entry |= find_dup_cset_node_entry(ovcs, ce_1);
613 dup_entry |= find_dup_cset_prop(ovcs, ce_1);
614 }
615
616 return dup_entry ? -EINVAL : 0;
617}
618
619
620
621
622
623
624
625
626
627
628
629
630
631static int build_changeset(struct overlay_changeset *ovcs)
632{
633 struct fragment *fragment;
634 struct target target;
635 int fragments_count, i, ret;
636
637
638
639
640
641 if (ovcs->symbols_fragment)
642 fragments_count = ovcs->count - 1;
643 else
644 fragments_count = ovcs->count;
645
646 for (i = 0; i < fragments_count; i++) {
647 fragment = &ovcs->fragments[i];
648
649 target.np = fragment->target;
650 target.in_livetree = true;
651 ret = build_changeset_next_level(ovcs, &target,
652 fragment->overlay);
653 if (ret) {
654 pr_debug("fragment apply failed '%pOF'\n",
655 fragment->target);
656 return ret;
657 }
658 }
659
660 if (ovcs->symbols_fragment) {
661 fragment = &ovcs->fragments[ovcs->count - 1];
662
663 target.np = fragment->target;
664 target.in_livetree = true;
665 ret = build_changeset_symbols_node(ovcs, &target,
666 fragment->overlay);
667 if (ret) {
668 pr_debug("symbols fragment apply failed '%pOF'\n",
669 fragment->target);
670 return ret;
671 }
672 }
673
674 return changeset_dup_entry_check(ovcs);
675}
676
677
678
679
680
681
682
683
684static struct device_node *find_target(struct device_node *info_node)
685{
686 struct device_node *node;
687 const char *path;
688 u32 val;
689 int ret;
690
691 ret = of_property_read_u32(info_node, "target", &val);
692 if (!ret) {
693 node = of_find_node_by_phandle(val);
694 if (!node)
695 pr_err("find target, node: %pOF, phandle 0x%x not found\n",
696 info_node, val);
697 return node;
698 }
699
700 ret = of_property_read_string(info_node, "target-path", &path);
701 if (!ret) {
702 node = of_find_node_by_path(path);
703 if (!node)
704 pr_err("find target, node: %pOF, path '%s' not found\n",
705 info_node, path);
706 return node;
707 }
708
709 pr_err("find target, node: %pOF, no target property\n", info_node);
710
711 return NULL;
712}
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727static int init_overlay_changeset(struct overlay_changeset *ovcs,
728 const void *fdt, struct device_node *tree)
729{
730 struct device_node *node, *overlay_node;
731 struct fragment *fragment;
732 struct fragment *fragments;
733 int cnt, id, ret;
734
735
736
737
738
739 if (!of_node_check_flag(tree, OF_DYNAMIC))
740 pr_debug("%s() tree is not dynamic\n", __func__);
741
742 if (!of_node_check_flag(tree, OF_DETACHED))
743 pr_debug("%s() tree is not detached\n", __func__);
744
745 if (!of_node_is_root(tree))
746 pr_debug("%s() tree is not root\n", __func__);
747
748 ovcs->overlay_tree = tree;
749 ovcs->fdt = fdt;
750
751 INIT_LIST_HEAD(&ovcs->ovcs_list);
752
753 of_changeset_init(&ovcs->cset);
754
755 id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
756 if (id <= 0)
757 return id;
758
759 cnt = 0;
760
761
762 for_each_child_of_node(tree, node) {
763 overlay_node = of_get_child_by_name(node, "__overlay__");
764 if (overlay_node) {
765 cnt++;
766 of_node_put(overlay_node);
767 }
768 }
769
770 node = of_get_child_by_name(tree, "__symbols__");
771 if (node) {
772 cnt++;
773 of_node_put(node);
774 }
775
776 fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
777 if (!fragments) {
778 ret = -ENOMEM;
779 goto err_free_idr;
780 }
781
782 cnt = 0;
783 for_each_child_of_node(tree, node) {
784 overlay_node = of_get_child_by_name(node, "__overlay__");
785 if (!overlay_node)
786 continue;
787
788 fragment = &fragments[cnt];
789 fragment->overlay = overlay_node;
790 fragment->target = find_target(node);
791 if (!fragment->target) {
792 of_node_put(fragment->overlay);
793 ret = -EINVAL;
794 goto err_free_fragments;
795 }
796
797 cnt++;
798 }
799
800
801
802
803
804 node = of_get_child_by_name(tree, "__symbols__");
805 if (node) {
806 ovcs->symbols_fragment = 1;
807 fragment = &fragments[cnt];
808 fragment->overlay = node;
809 fragment->target = of_find_node_by_path("/__symbols__");
810
811 if (!fragment->target) {
812 pr_err("symbols in overlay, but not in live tree\n");
813 ret = -EINVAL;
814 goto err_free_fragments;
815 }
816
817 cnt++;
818 }
819
820 if (!cnt) {
821 pr_err("no fragments or symbols in overlay\n");
822 ret = -EINVAL;
823 goto err_free_fragments;
824 }
825
826 ovcs->id = id;
827 ovcs->count = cnt;
828 ovcs->fragments = fragments;
829
830 return 0;
831
832err_free_fragments:
833 kfree(fragments);
834err_free_idr:
835 idr_remove(&ovcs_idr, id);
836
837 pr_err("%s() failed, ret = %d\n", __func__, ret);
838
839 return ret;
840}
841
842static void free_overlay_changeset(struct overlay_changeset *ovcs)
843{
844 int i;
845
846 if (ovcs->cset.entries.next)
847 of_changeset_destroy(&ovcs->cset);
848
849 if (ovcs->id)
850 idr_remove(&ovcs_idr, ovcs->id);
851
852 for (i = 0; i < ovcs->count; i++) {
853 of_node_put(ovcs->fragments[i].target);
854 of_node_put(ovcs->fragments[i].overlay);
855 }
856 kfree(ovcs->fragments);
857
858
859
860
861
862 kfree(ovcs->overlay_tree);
863 kfree(ovcs->fdt);
864 kfree(ovcs);
865}
866
867
868
869
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
910static int of_overlay_apply(const void *fdt, struct device_node *tree,
911 int *ovcs_id)
912{
913 struct overlay_changeset *ovcs;
914 int ret = 0, ret_revert, ret_tmp;
915
916
917
918
919
920
921 if (devicetree_corrupt()) {
922 pr_err("devicetree state suspect, refuse to apply overlay\n");
923 kfree(fdt);
924 kfree(tree);
925 ret = -EBUSY;
926 goto out;
927 }
928
929 ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
930 if (!ovcs) {
931 kfree(fdt);
932 kfree(tree);
933 ret = -ENOMEM;
934 goto out;
935 }
936
937 of_overlay_mutex_lock();
938 mutex_lock(&of_mutex);
939
940 ret = of_resolve_phandles(tree);
941 if (ret)
942 goto err_free_tree;
943
944 ret = init_overlay_changeset(ovcs, fdt, tree);
945 if (ret)
946 goto err_free_tree;
947
948
949
950
951
952
953 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
954 if (ret) {
955 pr_err("overlay changeset pre-apply notify error %d\n", ret);
956 goto err_free_overlay_changeset;
957 }
958
959 ret = build_changeset(ovcs);
960 if (ret)
961 goto err_free_overlay_changeset;
962
963 ret_revert = 0;
964 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
965 if (ret) {
966 if (ret_revert) {
967 pr_debug("overlay changeset revert error %d\n",
968 ret_revert);
969 devicetree_state_flags |= DTSF_APPLY_FAIL;
970 }
971 goto err_free_overlay_changeset;
972 }
973
974 of_populate_phandle_cache();
975
976 ret = __of_changeset_apply_notify(&ovcs->cset);
977 if (ret)
978 pr_err("overlay apply changeset entry notify error %d\n", ret);
979
980
981 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
982 *ovcs_id = ovcs->id;
983
984 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);
985 if (ret_tmp) {
986 pr_err("overlay changeset post-apply notify error %d\n",
987 ret_tmp);
988 if (!ret)
989 ret = ret_tmp;
990 }
991
992 goto out_unlock;
993
994err_free_tree:
995 kfree(fdt);
996 kfree(tree);
997
998err_free_overlay_changeset:
999 free_overlay_changeset(ovcs);
1000
1001out_unlock:
1002 mutex_unlock(&of_mutex);
1003 of_overlay_mutex_unlock();
1004
1005out:
1006 pr_debug("%s() err=%d\n", __func__, ret);
1007
1008 return ret;
1009}
1010
1011int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
1012 int *ovcs_id)
1013{
1014 const void *new_fdt;
1015 int ret;
1016 u32 size;
1017 struct device_node *overlay_root;
1018
1019 *ovcs_id = 0;
1020 ret = 0;
1021
1022 if (overlay_fdt_size < sizeof(struct fdt_header) ||
1023 fdt_check_header(overlay_fdt)) {
1024 pr_err("Invalid overlay_fdt header\n");
1025 return -EINVAL;
1026 }
1027
1028 size = fdt_totalsize(overlay_fdt);
1029 if (overlay_fdt_size < size)
1030 return -EINVAL;
1031
1032
1033
1034
1035
1036 new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL);
1037 if (!new_fdt)
1038 return -ENOMEM;
1039
1040 of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root);
1041 if (!overlay_root) {
1042 pr_err("unable to unflatten overlay_fdt\n");
1043 ret = -EINVAL;
1044 goto out_free_new_fdt;
1045 }
1046
1047 ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
1048 if (ret < 0) {
1049
1050
1051
1052
1053
1054 goto out;
1055 }
1056
1057 return 0;
1058
1059
1060out_free_new_fdt:
1061 kfree(new_fdt);
1062
1063out:
1064 return ret;
1065}
1066EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
1067
1068
1069
1070
1071
1072
1073static int find_node(struct device_node *tree, struct device_node *np)
1074{
1075 struct device_node *child;
1076
1077 if (tree == np)
1078 return 1;
1079
1080 for_each_child_of_node(tree, child) {
1081 if (find_node(child, np)) {
1082 of_node_put(child);
1083 return 1;
1084 }
1085 }
1086
1087 return 0;
1088}
1089
1090
1091
1092
1093
1094
1095
1096static int node_overlaps_later_cs(struct overlay_changeset *remove_ovcs,
1097 struct device_node *remove_ce_node)
1098{
1099 struct overlay_changeset *ovcs;
1100 struct of_changeset_entry *ce;
1101
1102 list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) {
1103 if (ovcs == remove_ovcs)
1104 break;
1105
1106 list_for_each_entry(ce, &ovcs->cset.entries, node) {
1107 if (find_node(ce->np, remove_ce_node)) {
1108 pr_err("%s: #%d overlaps with #%d @%pOF\n",
1109 __func__, remove_ovcs->id, ovcs->id,
1110 remove_ce_node);
1111 return 1;
1112 }
1113 if (find_node(remove_ce_node, ce->np)) {
1114 pr_err("%s: #%d overlaps with #%d @%pOF\n",
1115 __func__, remove_ovcs->id, ovcs->id,
1116 remove_ce_node);
1117 return 1;
1118 }
1119 }
1120 }
1121
1122 return 0;
1123}
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
1136{
1137 struct of_changeset_entry *remove_ce;
1138
1139 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) {
1140 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) {
1141 pr_err("overlay #%d is not topmost\n", remove_ovcs->id);
1142 return 0;
1143 }
1144 }
1145
1146 return 1;
1147}
1148
1149
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
1183int of_overlay_remove(int *ovcs_id)
1184{
1185 struct overlay_changeset *ovcs;
1186 int ret, ret_apply, ret_tmp;
1187
1188 ret = 0;
1189
1190 if (devicetree_corrupt()) {
1191 pr_err("suspect devicetree state, refuse to remove overlay\n");
1192 ret = -EBUSY;
1193 goto out;
1194 }
1195
1196 mutex_lock(&of_mutex);
1197
1198 ovcs = idr_find(&ovcs_idr, *ovcs_id);
1199 if (!ovcs) {
1200 ret = -ENODEV;
1201 pr_err("remove: Could not find overlay #%d\n", *ovcs_id);
1202 goto out_unlock;
1203 }
1204
1205 if (!overlay_removal_is_ok(ovcs)) {
1206 ret = -EBUSY;
1207 goto out_unlock;
1208 }
1209
1210 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE);
1211 if (ret) {
1212 pr_err("overlay changeset pre-remove notify error %d\n", ret);
1213 goto out_unlock;
1214 }
1215
1216 list_del(&ovcs->ovcs_list);
1217
1218
1219
1220
1221
1222 of_free_phandle_cache();
1223
1224 ret_apply = 0;
1225 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
1226
1227 of_populate_phandle_cache();
1228
1229 if (ret) {
1230 if (ret_apply)
1231 devicetree_state_flags |= DTSF_REVERT_FAIL;
1232 goto out_unlock;
1233 }
1234
1235 ret = __of_changeset_revert_notify(&ovcs->cset);
1236 if (ret)
1237 pr_err("overlay remove changeset entry notify error %d\n", ret);
1238
1239
1240 *ovcs_id = 0;
1241
1242 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE);
1243 if (ret_tmp) {
1244 pr_err("overlay changeset post-remove notify error %d\n",
1245 ret_tmp);
1246 if (!ret)
1247 ret = ret_tmp;
1248 }
1249
1250 free_overlay_changeset(ovcs);
1251
1252out_unlock:
1253 mutex_unlock(&of_mutex);
1254
1255out:
1256 pr_debug("%s() err=%d\n", __func__, ret);
1257
1258 return ret;
1259}
1260EXPORT_SYMBOL_GPL(of_overlay_remove);
1261
1262
1263
1264
1265
1266
1267
1268
1269int of_overlay_remove_all(void)
1270{
1271 struct overlay_changeset *ovcs, *ovcs_n;
1272 int ret;
1273
1274
1275 list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) {
1276 ret = of_overlay_remove(&ovcs->id);
1277 if (ret)
1278 return ret;
1279 }
1280
1281 return 0;
1282}
1283EXPORT_SYMBOL_GPL(of_overlay_remove_all);
1284