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 of_node_put(node);
800 goto err_free_fragments;
801 }
802
803 cnt++;
804 }
805
806
807
808
809
810 node = of_get_child_by_name(tree, "__symbols__");
811 if (node) {
812 ovcs->symbols_fragment = 1;
813 fragment = &fragments[cnt];
814 fragment->overlay = node;
815 fragment->target = of_find_node_by_path("/__symbols__");
816
817 if (!fragment->target) {
818 pr_err("symbols in overlay, but not in live tree\n");
819 ret = -EINVAL;
820 goto err_free_fragments;
821 }
822
823 cnt++;
824 }
825
826 if (!cnt) {
827 pr_err("no fragments or symbols in overlay\n");
828 ret = -EINVAL;
829 goto err_free_fragments;
830 }
831
832 ovcs->id = id;
833 ovcs->count = cnt;
834 ovcs->fragments = fragments;
835
836 return 0;
837
838err_free_fragments:
839 kfree(fragments);
840err_free_idr:
841 idr_remove(&ovcs_idr, id);
842
843 pr_err("%s() failed, ret = %d\n", __func__, ret);
844
845 return ret;
846}
847
848static void free_overlay_changeset(struct overlay_changeset *ovcs)
849{
850 int i;
851
852 if (ovcs->cset.entries.next)
853 of_changeset_destroy(&ovcs->cset);
854
855 if (ovcs->id)
856 idr_remove(&ovcs_idr, ovcs->id);
857
858 for (i = 0; i < ovcs->count; i++) {
859 of_node_put(ovcs->fragments[i].target);
860 of_node_put(ovcs->fragments[i].overlay);
861 }
862 kfree(ovcs->fragments);
863
864
865
866
867
868 kfree(ovcs->overlay_tree);
869 kfree(ovcs->fdt);
870 kfree(ovcs);
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
915
916static int of_overlay_apply(const void *fdt, struct device_node *tree,
917 int *ovcs_id)
918{
919 struct overlay_changeset *ovcs;
920 int ret = 0, ret_revert, ret_tmp;
921
922
923
924
925
926
927 if (devicetree_corrupt()) {
928 pr_err("devicetree state suspect, refuse to apply overlay\n");
929 kfree(fdt);
930 kfree(tree);
931 ret = -EBUSY;
932 goto out;
933 }
934
935 ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
936 if (!ovcs) {
937 kfree(fdt);
938 kfree(tree);
939 ret = -ENOMEM;
940 goto out;
941 }
942
943 of_overlay_mutex_lock();
944 mutex_lock(&of_mutex);
945
946 ret = of_resolve_phandles(tree);
947 if (ret)
948 goto err_free_tree;
949
950 ret = init_overlay_changeset(ovcs, fdt, tree);
951 if (ret)
952 goto err_free_tree;
953
954
955
956
957
958
959
960
961 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
962 if (ret) {
963 pr_err("overlay changeset pre-apply notify error %d\n", ret);
964 goto err_free_overlay_changeset;
965 }
966
967 ret = build_changeset(ovcs);
968 if (ret)
969 goto err_free_overlay_changeset;
970
971 ret_revert = 0;
972 ret = __of_changeset_apply_entries(&ovcs->cset, &ret_revert);
973 if (ret) {
974 if (ret_revert) {
975 pr_debug("overlay changeset revert error %d\n",
976 ret_revert);
977 devicetree_state_flags |= DTSF_APPLY_FAIL;
978 }
979 goto err_free_overlay_changeset;
980 }
981
982 ret = __of_changeset_apply_notify(&ovcs->cset);
983 if (ret)
984 pr_err("overlay apply changeset entry notify error %d\n", ret);
985
986
987 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
988 *ovcs_id = ovcs->id;
989
990 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);
991 if (ret_tmp) {
992 pr_err("overlay changeset post-apply notify error %d\n",
993 ret_tmp);
994 if (!ret)
995 ret = ret_tmp;
996 }
997
998 goto out_unlock;
999
1000err_free_tree:
1001 kfree(fdt);
1002 kfree(tree);
1003
1004err_free_overlay_changeset:
1005 free_overlay_changeset(ovcs);
1006
1007out_unlock:
1008 mutex_unlock(&of_mutex);
1009 of_overlay_mutex_unlock();
1010
1011out:
1012 pr_debug("%s() err=%d\n", __func__, ret);
1013
1014 return ret;
1015}
1016
1017int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
1018 int *ovcs_id)
1019{
1020 void *new_fdt;
1021 void *new_fdt_align;
1022 int ret;
1023 u32 size;
1024 struct device_node *overlay_root = NULL;
1025
1026 *ovcs_id = 0;
1027
1028 if (overlay_fdt_size < sizeof(struct fdt_header) ||
1029 fdt_check_header(overlay_fdt)) {
1030 pr_err("Invalid overlay_fdt header\n");
1031 return -EINVAL;
1032 }
1033
1034 size = fdt_totalsize(overlay_fdt);
1035 if (overlay_fdt_size < size)
1036 return -EINVAL;
1037
1038
1039
1040
1041
1042 new_fdt = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL);
1043 if (!new_fdt)
1044 return -ENOMEM;
1045
1046 new_fdt_align = PTR_ALIGN(new_fdt, FDT_ALIGN_SIZE);
1047 memcpy(new_fdt_align, overlay_fdt, size);
1048
1049 of_fdt_unflatten_tree(new_fdt_align, NULL, &overlay_root);
1050 if (!overlay_root) {
1051 pr_err("unable to unflatten overlay_fdt\n");
1052 ret = -EINVAL;
1053 goto out_free_new_fdt;
1054 }
1055
1056 ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
1057 if (ret < 0) {
1058
1059
1060
1061
1062
1063 goto out;
1064 }
1065
1066 return 0;
1067
1068
1069out_free_new_fdt:
1070 kfree(new_fdt);
1071
1072out:
1073 return ret;
1074}
1075EXPORT_SYMBOL_GPL(of_overlay_fdt_apply);
1076
1077
1078
1079
1080
1081
1082static int find_node(struct device_node *tree, struct device_node *np)
1083{
1084 struct device_node *child;
1085
1086 if (tree == np)
1087 return 1;
1088
1089 for_each_child_of_node(tree, child) {
1090 if (find_node(child, np)) {
1091 of_node_put(child);
1092 return 1;
1093 }
1094 }
1095
1096 return 0;
1097}
1098
1099
1100
1101
1102
1103
1104
1105static int node_overlaps_later_cs(struct overlay_changeset *remove_ovcs,
1106 struct device_node *remove_ce_node)
1107{
1108 struct overlay_changeset *ovcs;
1109 struct of_changeset_entry *ce;
1110
1111 list_for_each_entry_reverse(ovcs, &ovcs_list, ovcs_list) {
1112 if (ovcs == remove_ovcs)
1113 break;
1114
1115 list_for_each_entry(ce, &ovcs->cset.entries, node) {
1116 if (find_node(ce->np, remove_ce_node)) {
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 if (find_node(remove_ce_node, ce->np)) {
1123 pr_err("%s: #%d overlaps with #%d @%pOF\n",
1124 __func__, remove_ovcs->id, ovcs->id,
1125 remove_ce_node);
1126 return 1;
1127 }
1128 }
1129 }
1130
1131 return 0;
1132}
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
1145{
1146 struct of_changeset_entry *remove_ce;
1147
1148 list_for_each_entry(remove_ce, &remove_ovcs->cset.entries, node) {
1149 if (node_overlaps_later_cs(remove_ovcs, remove_ce->np)) {
1150 pr_err("overlay #%d is not topmost\n", remove_ovcs->id);
1151 return 0;
1152 }
1153 }
1154
1155 return 1;
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
1186
1187
1188
1189
1190
1191
1192int of_overlay_remove(int *ovcs_id)
1193{
1194 struct overlay_changeset *ovcs;
1195 int ret, ret_apply, ret_tmp;
1196
1197 if (devicetree_corrupt()) {
1198 pr_err("suspect devicetree state, refuse to remove overlay\n");
1199 ret = -EBUSY;
1200 goto out;
1201 }
1202
1203 mutex_lock(&of_mutex);
1204
1205 ovcs = idr_find(&ovcs_idr, *ovcs_id);
1206 if (!ovcs) {
1207 ret = -ENODEV;
1208 pr_err("remove: Could not find overlay #%d\n", *ovcs_id);
1209 goto out_unlock;
1210 }
1211
1212 if (!overlay_removal_is_ok(ovcs)) {
1213 ret = -EBUSY;
1214 goto out_unlock;
1215 }
1216
1217 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE);
1218 if (ret) {
1219 pr_err("overlay changeset pre-remove notify error %d\n", ret);
1220 goto out_unlock;
1221 }
1222
1223 list_del(&ovcs->ovcs_list);
1224
1225 ret_apply = 0;
1226 ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
1227 if (ret) {
1228 if (ret_apply)
1229 devicetree_state_flags |= DTSF_REVERT_FAIL;
1230 goto out_unlock;
1231 }
1232
1233 ret = __of_changeset_revert_notify(&ovcs->cset);
1234 if (ret)
1235 pr_err("overlay remove changeset entry notify error %d\n", ret);
1236
1237
1238 *ovcs_id = 0;
1239
1240 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE);
1241 if (ret_tmp) {
1242 pr_err("overlay changeset post-remove notify error %d\n",
1243 ret_tmp);
1244 if (!ret)
1245 ret = ret_tmp;
1246 }
1247
1248 free_overlay_changeset(ovcs);
1249
1250out_unlock:
1251 mutex_unlock(&of_mutex);
1252
1253out:
1254 pr_debug("%s() err=%d\n", __func__, ret);
1255
1256 return ret;
1257}
1258EXPORT_SYMBOL_GPL(of_overlay_remove);
1259
1260
1261
1262
1263
1264
1265
1266
1267int of_overlay_remove_all(void)
1268{
1269 struct overlay_changeset *ovcs, *ovcs_n;
1270 int ret;
1271
1272
1273 list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) {
1274 ret = of_overlay_remove(&ovcs->id);
1275 if (ret)
1276 return ret;
1277 }
1278
1279 return 0;
1280}
1281EXPORT_SYMBOL_GPL(of_overlay_remove_all);
1282