Compare commits
619 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
9197f1ccd9 | |
![]() |
e1284ee5dc | |
![]() |
cba90ce820 | |
![]() |
763c6ab418 | |
![]() |
739403f222 | |
![]() |
1c6c51e51b | |
![]() |
617f3d9b60 | |
![]() |
04f948e83f | |
![]() |
e896802631 | |
![]() |
2ad738722b | |
![]() |
4132ac08ba | |
![]() |
33e66ec845 | |
![]() |
a0dd7b6081 | |
![]() |
5b71660724 | |
![]() |
52f07dcca4 | |
![]() |
9cabae6b03 | |
![]() |
605dc044c3 | |
![]() |
7da5d106c7 | |
![]() |
53c63dd421 | |
![]() |
84d9dd2fcb | |
![]() |
97011d1f4e | |
![]() |
b841391bbd | |
![]() |
e0b7749c26 | |
![]() |
ecb21febfd | |
![]() |
7ebfcac852 | |
![]() |
f4c53f4ebf | |
![]() |
205fbef17b | |
![]() |
da85f91931 | |
![]() |
dd1b3e532d | |
![]() |
1ccd232709 | |
![]() |
ce1d858888 | |
![]() |
915daadbb6 | |
![]() |
4ea851f5a4 | |
![]() |
175d2a564c | |
![]() |
18f4f305fd | |
![]() |
267efc7d46 | |
![]() |
755db11535 | |
![]() |
bdca861200 | |
![]() |
0f69cedc08 | |
![]() |
56b2b30c5b | |
![]() |
1e8c5f60e1 | |
![]() |
6f183c7d92 | |
![]() |
66c7d0e6f4 | |
![]() |
9a969f3b70 | |
![]() |
4292b072a2 | |
![]() |
1c745a9bd1 | |
![]() |
b3bbee6b12 | |
![]() |
d1656730ab | |
![]() |
b75515af45 | |
![]() |
2d10aa2afe | |
![]() |
48795c82bd | |
![]() |
838f11e830 | |
![]() |
d1e2384185 | |
![]() |
18aa49a9f6 | |
![]() |
f9968fa069 | |
![]() |
9b5f65fb3d | |
![]() |
99031e3a4a | |
![]() |
3d5e376925 | |
![]() |
e277553b98 | |
![]() |
7e5a889840 | |
![]() |
78b6a85c11 | |
![]() |
3501d373f0 | |
![]() |
bcd02b5234 | |
![]() |
84b056a89d | |
![]() |
1df7b047fe | |
![]() |
61e88fdcec | |
![]() |
49d3089446 | |
![]() |
d54aaf9367 | |
![]() |
ab86f1e9fd | |
![]() |
7b8a30ecea | |
![]() |
ff4f17eb58 | |
![]() |
9e313b14e6 | |
![]() |
d598fc3648 | |
![]() |
b98239da2f | |
![]() |
c17d76ab5e | |
![]() |
ae26223a05 | |
![]() |
4dd831affd | |
![]() |
e6d2942008 | |
![]() |
855c934e26 | |
![]() |
4fd3f4f0a9 | |
![]() |
9ca7d62dbf | |
![]() |
bb51223083 | |
![]() |
e81900635c | |
![]() |
8221238569 | |
![]() |
1fad065080 | |
![]() |
b0aacd0a77 | |
![]() |
ae97d97458 | |
![]() |
057a7dbbb7 | |
![]() |
92b5d4e916 | |
![]() |
417e3299db | |
![]() |
5e6cefa17e | |
![]() |
24f60011fd | |
![]() |
da39ee0e68 | |
![]() |
a669223f7a | |
![]() |
3fbfdd08af | |
![]() |
dcef5f834e | |
![]() |
0b8026ff25 | |
![]() |
95c74d71f0 | |
![]() |
2283dd78ef | |
![]() |
79b9e326a1 | |
![]() |
52157f13ef | |
![]() |
d774337275 | |
![]() |
ad8bf9f9aa | |
![]() |
6c5e189fb9 | |
![]() |
a3dc9f006a | |
![]() |
35019949c4 | |
![]() |
cd3e2304f4 | |
![]() |
0f58645677 | |
![]() |
38165954c1 | |
![]() |
5e98b59793 | |
![]() |
d030a893be | |
![]() |
8d8372b137 | |
![]() |
761114effa | |
![]() |
bf6377a98d | |
![]() |
4c68e4b16b | |
![]() |
bdc5c8793a | |
![]() |
f088e381f2 | |
![]() |
6df5328a90 | |
![]() |
ccf1f62d59 | |
![]() |
71a8b8ef0a | |
![]() |
589d8c7653 | |
![]() |
e8364666d5 | |
![]() |
3b02a94b48 | |
![]() |
d4888958d6 | |
![]() |
ea3b9a1d2c | |
![]() |
b2b9671583 | |
![]() |
ab481e4830 | |
![]() |
c88038c9b8 | |
![]() |
0ac8b30ba5 | |
![]() |
f1657b2fb5 | |
![]() |
44bb89cafd | |
![]() |
60bcf1cde1 | |
![]() |
a6f997bc77 | |
![]() |
18f5ec12a1 | |
![]() |
df09327928 | |
![]() |
129bb4b78b | |
![]() |
390f481521 | |
![]() |
9f8b382ed4 | |
![]() |
2cdf93a6d4 | |
![]() |
72fc810c30 | |
![]() |
083ab26da8 | |
![]() |
6f8b28f496 | |
![]() |
fd68bb8c56 | |
![]() |
4718189c4c | |
![]() |
0b842c3c81 | |
![]() |
9cceabea1e | |
![]() |
0d56145938 | |
![]() |
61fa22b05f | |
![]() |
7a1d72a788 | |
![]() |
ee57999386 | |
![]() |
44c9b73801 | |
![]() |
5b60f5104f | |
![]() |
32174a66ef | |
![]() |
64a907f08b | |
![]() |
e3cde0613b | |
![]() |
4182182110 | |
![]() |
71c19f20b3 | |
![]() |
039a99414e | |
![]() |
9b62ec84bb | |
![]() |
3f29d6d85c | |
![]() |
2022bb1087 | |
![]() |
abbd523bae | |
![]() |
a41509bea3 | |
![]() |
2cd89f862c | |
![]() |
55778a03df | |
![]() |
73590342fc | |
![]() |
035fb90d53 | |
![]() |
98a07006c4 | |
![]() |
a036cc7b0c | |
![]() |
c6e92108bc | |
![]() |
e37c25677d | |
![]() |
50454658f2 | |
![]() |
e64a204196 | |
![]() |
f508c83fe6 | |
![]() |
c2ccf8a77d | |
![]() |
90b9d9de42 | |
![]() |
0ee1d479b2 | |
![]() |
b33a73c62c | |
![]() |
7ad60734b1 | |
![]() |
fd9b8c96c7 | |
![]() |
fda71da26e | |
![]() |
c7c7f17a83 | |
![]() |
01f23ffe16 | |
![]() |
ed310803ea | |
![]() |
c001fc01a4 | |
![]() |
26c54f840d | |
![]() |
ec7986e682 | |
![]() |
651410e54c | |
![]() |
4048aed12b | |
![]() |
ff5afb96d0 | |
![]() |
ca72944343 | |
![]() |
c0c2e115f8 | |
![]() |
cd5f69cbc0 | |
![]() |
a04f690250 | |
![]() |
83102717d7 | |
![]() |
d152126bb0 | |
![]() |
17739b7ef5 | |
![]() |
45f3d1a095 | |
![]() |
c19a4bafa5 | |
![]() |
1cc41b1c96 | |
![]() |
db72398cd4 | |
![]() |
383e148b70 | |
![]() |
23b56cb7e1 | |
![]() |
69a760747d | |
![]() |
0b106a77db | |
![]() |
c691776ddb | |
![]() |
5216f3f1bb | |
![]() |
4eda2590f4 | |
![]() |
0a3a9d3449 | |
![]() |
8fd24744e3 | |
![]() |
d8d1a9a778 | |
![]() |
52a16fd728 | |
![]() |
37fd700685 | |
![]() |
e33ce1d6a8 | |
![]() |
d24cc189dc | |
![]() |
ff3a30c115 | |
![]() |
5eb5927d81 | |
![]() |
0869f82691 | |
![]() |
69595a167f | |
![]() |
72d09e2682 | |
![]() |
b587787ef3 | |
![]() |
69bed6c241 | |
![]() |
9102211855 | |
![]() |
d966f08fcd | |
![]() |
ecfb438c07 | |
![]() |
5bec74a6d1 | |
![]() |
24e7f511fd | |
![]() |
b6910bec11 | |
![]() |
21d61d18f9 | |
![]() |
4c2ef8f4d1 | |
![]() |
e59ca36fb7 | |
![]() |
0c3fd9b6ac | |
![]() |
6b3081abc4 | |
![]() |
2dffc192a7 | |
![]() |
61e513439e | |
![]() |
c8bddd1060 | |
![]() |
ad4abfadb6 | |
![]() |
09c6a6e887 | |
![]() |
9bb9b8d0b4 | |
![]() |
b07b62ee33 | |
![]() |
a2def54799 | |
![]() |
4ca61f84dc | |
![]() |
34d708249a | |
![]() |
8e7ff260f7 | |
![]() |
88875268c0 | |
![]() |
9d2279e7e6 | |
![]() |
f527c867a8 | |
![]() |
183df9e9c2 | |
![]() |
0db6d09584 | |
![]() |
307afa1a7b | |
![]() |
ca16a723fa | |
![]() |
64990a272e | |
![]() |
163f0469bf | |
![]() |
3b01518e68 | |
![]() |
f7e5737f26 | |
![]() |
7cd5d5fe43 | |
![]() |
a7c4040993 | |
![]() |
bab85e48a6 | |
![]() |
f8b4609882 | |
![]() |
30a56bce4f | |
![]() |
5e735860c4 | |
![]() |
67849a3279 | |
![]() |
05874d0821 | |
![]() |
3bc3a6b9fe | |
![]() |
e1147b159e | |
![]() |
04cf1fdc0f | |
![]() |
b30013edb8 | |
![]() |
cbca977ea1 | |
![]() |
73e0f143b7 | |
![]() |
6c2be7d853 | |
![]() |
82525f41d5 | |
![]() |
fb1f65f158 | |
![]() |
f28aa27100 | |
![]() |
3d7c6f4419 | |
![]() |
10f682788c | |
![]() |
07158f4cf2 | |
![]() |
ce9e1f25a7 | |
![]() |
faa76fc10b | |
![]() |
54dca09853 | |
![]() |
f8e11e6162 | |
![]() |
0c43d4d7bf | |
![]() |
442ea3dd15 | |
![]() |
ca19c3db2b | |
![]() |
7bb86f1c09 | |
![]() |
3d522abc75 | |
![]() |
808cdaaf52 | |
![]() |
3e3138b4a9 | |
![]() |
9d7888cbf1 | |
![]() |
8259d59f59 | |
![]() |
fdabcf2980 | |
![]() |
2478b1652c | |
![]() |
f68bfc2668 | |
![]() |
7be250b4d0 | |
![]() |
81e0919a3e | |
![]() |
85e5d83984 | |
![]() |
b28464a550 | |
![]() |
87a656ae5f | |
![]() |
73d6e9ecb4 | |
![]() |
2525da3dba | |
![]() |
62cb4ad286 | |
![]() |
1f9a417508 | |
![]() |
c5995ddf4c | |
![]() |
e4ce227e89 | |
![]() |
9b75292c33 | |
![]() |
6c253afd07 | |
![]() |
95ec8ef706 | |
![]() |
2b5f62d109 | |
![]() |
76b43dcbd1 | |
![]() |
e5c92a4780 | |
![]() |
e5cc26b68b | |
![]() |
28fd7590aa | |
![]() |
fc207c3234 | |
![]() |
0f61c72ded | |
![]() |
f270f45fd5 | |
![]() |
c18bae9a4c | |
![]() |
fc03c4a2e0 | |
![]() |
77563ae72b | |
![]() |
57bc6327b8 | |
![]() |
464962489d | |
![]() |
0c5326cb28 | |
![]() |
cc6a5a0715 | |
![]() |
0e9225eb0d | |
![]() |
cab09eedd6 | |
![]() |
0eb1cb0b53 | |
![]() |
c40aeb60b4 | |
![]() |
9f86aff444 | |
![]() |
34c82275ba | |
![]() |
743000931b | |
![]() |
adcd676491 | |
![]() |
d9c55f855b | |
![]() |
7a22132c79 | |
![]() |
dbe80d577e | |
![]() |
af57d440d8 | |
![]() |
6ce585ac15 | |
![]() |
7150286225 | |
![]() |
fdf3f6d897 | |
![]() |
430419c281 | |
![]() |
588a29ff2e | |
![]() |
bc876708ab | |
![]() |
4c3c4ccb99 | |
![]() |
aa522da9ff | |
![]() |
0d0d0fa51b | |
![]() |
4605eb047b | |
![]() |
18d7b2f4ee | |
![]() |
67f790c1ad | |
![]() |
b111122ea5 | |
![]() |
60e0db3d65 | |
![]() |
95ce19c140 | |
![]() |
5345db19f6 | |
![]() |
b8d6eca782 | |
![]() |
184f510994 | |
![]() |
812b1956a0 | |
![]() |
5c715a4477 | |
![]() |
b993534748 | |
![]() |
d6de81b81b | |
![]() |
1c17714dbb | |
![]() |
ad57e4574a | |
![]() |
bbe3b36f54 | |
![]() |
6c2e61f083 | |
![]() |
297f5abb36 | |
![]() |
702c1b6c0e | |
![]() |
4097bbffcf | |
![]() |
94f87cd5b7 | |
![]() |
c4ffc05574 | |
![]() |
a5ac29baac | |
![]() |
7fb0f4db2e | |
![]() |
acfe84f2c4 | |
![]() |
87963ee206 | |
![]() |
825146d13d | |
![]() |
25bb080c18 | |
![]() |
243176c4ce | |
![]() |
ce01b21098 | |
![]() |
fbb62754ce | |
![]() |
228a44cce8 | |
![]() |
8f69567622 | |
![]() |
5c3513f689 | |
![]() |
00f9febf9c | |
![]() |
c5d45188f9 | |
![]() |
6ef8fcd05b | |
![]() |
26ee65a16c | |
![]() |
cca6546244 | |
![]() |
730875016a | |
![]() |
7dfb61ba96 | |
![]() |
2bc5b66d7f | |
![]() |
7fcf8208b8 | |
![]() |
ae795b2db7 | |
![]() |
eac2ad495b | |
![]() |
f67b471355 | |
![]() |
54ea41c224 | |
![]() |
4762ad051e | |
![]() |
d37f6b2010 | |
![]() |
a4b1a307ff | |
![]() |
625dd8aaf2 | |
![]() |
364631626b | |
![]() |
cb0f454f73 | |
![]() |
4b68c6b360 | |
![]() |
78e113e81c | |
![]() |
ea7a8f6dad | |
![]() |
5aafd7ca43 | |
![]() |
7cbc550f90 | |
![]() |
f267e674d1 | |
![]() |
3616b9a811 | |
![]() |
2bdbd07a12 | |
![]() |
a1eff70c02 | |
![]() |
82a52ce457 | |
![]() |
607b8586b3 | |
![]() |
f9c0a425b6 | |
![]() |
5182b5e6f2 | |
![]() |
d45bf1f5f2 | |
![]() |
99284c4db9 | |
![]() |
a4629cfaed | |
![]() |
08380fc43a | |
![]() |
8113c00b99 | |
![]() |
11738cf01f | |
![]() |
86a288a736 | |
![]() |
5667e7ef9a | |
![]() |
8e20ccf52f | |
![]() |
ca930e20bb | |
![]() |
43366bb4ee | |
![]() |
5062516fb8 | |
![]() |
a3143fafbf | |
![]() |
403cc79f06 | |
![]() |
baa1d2cf78 | |
![]() |
ff2ad38f6a | |
![]() |
aa7254d9cb | |
![]() |
49903aed77 | |
![]() |
da2b691ccf | |
![]() |
8f8b77a0d6 | |
![]() |
522d81d572 | |
![]() |
e45198c983 | |
![]() |
0fcffda15e | |
![]() |
1e4a0928f3 | |
![]() |
ca399b1495 | |
![]() |
98972f1b3e | |
![]() |
7ba2be6cda | |
![]() |
7691f9d393 | |
![]() |
855b9963de | |
![]() |
47cafbeeb9 | |
![]() |
dd695d6afb | |
![]() |
59327523d0 | |
![]() |
e84742aa7b | |
![]() |
8c59a97ce0 | |
![]() |
d448f9a5fd | |
![]() |
c86da84d30 | |
![]() |
361b5e7d80 | |
![]() |
bfbfab047e | |
![]() |
9005f4108e | |
![]() |
b94c056b13 | |
![]() |
fd06c54d47 | |
![]() |
c3f50c9a86 | |
![]() |
0ac9fdee37 | |
![]() |
0fd1c8c783 | |
![]() |
04853cad18 | |
![]() |
9619c8619c | |
![]() |
ac68ff92ae | |
![]() |
90a190eb04 | |
![]() |
53a1bd5469 | |
![]() |
88f18909db | |
![]() |
85bce8b2f0 | |
![]() |
57f7f9e7bc | |
![]() |
c12b2b0c20 | |
![]() |
3fe0eeda0b | |
![]() |
853649acce | |
![]() |
9b0e4fe260 | |
![]() |
1087504bb3 | |
![]() |
c72fa777e6 | |
![]() |
32b9c61307 | |
![]() |
6dcb8ba408 | |
![]() |
42607f21d4 | |
![]() |
9d78c33bf8 | |
![]() |
b770f3d1c1 | |
![]() |
2f0d07e678 | |
![]() |
354d3dc559 | |
![]() |
3c374d46ac | |
![]() |
49d32ce40b | |
![]() |
481246a0c1 | |
![]() |
9aafa33d99 | |
![]() |
5a598671fd | |
![]() |
483e170625 | |
![]() |
29bb05aa42 | |
![]() |
582a7159a5 | |
![]() |
f0f8c91698 | |
![]() |
64a69d1239 | |
![]() |
4d09a83420 | |
![]() |
e617cbe1bd | |
![]() |
180a939240 | |
![]() |
b9af3b3965 | |
![]() |
4b8fcc3d01 | |
![]() |
c14223fb22 | |
![]() |
5b67d2b955 | |
![]() |
e2556aaeb5 | |
![]() |
fb9c6abdda | |
![]() |
0112fda03b | |
![]() |
6473a21d8b | |
![]() |
d5db5382c5 | |
![]() |
719d582e98 | |
![]() |
70166d62a2 | |
![]() |
eb890c0f77 | |
![]() |
899d6fad93 | |
![]() |
04b5b4062c | |
![]() |
44d3efedc8 | |
![]() |
f0be81bd8d | |
![]() |
24b1f3f064 | |
![]() |
84e414b0b5 | |
![]() |
4038fd9005 | |
![]() |
e1f139ea49 | |
![]() |
f4eba68d89 | |
![]() |
46df1fb1b2 | |
![]() |
14a3002a1a | |
![]() |
02c5fe9deb | |
![]() |
df536831d0 | |
![]() |
2347c96edc | |
![]() |
8f1b35f883 | |
![]() |
afbddcd418 | |
![]() |
119e273003 | |
![]() |
aadd0b65c9 | |
![]() |
88960e3989 | |
![]() |
f1879e1a50 | |
![]() |
37dea76e97 | |
![]() |
65893da4ae | |
![]() |
962a45ca03 | |
![]() |
cd6ea1b2be | |
![]() |
51b3a16338 | |
![]() |
333d533a8f | |
![]() |
e54388015a | |
![]() |
a1fe86f380 | |
![]() |
c8d5472de3 | |
![]() |
c81d389a10 | |
![]() |
e671852042 | |
![]() |
d0c44ebe3f | |
![]() |
18a3d84bb8 | |
![]() |
8fe94fd6f1 | |
![]() |
6c57308196 | |
![]() |
a384191eba | |
![]() |
b260c4f610 | |
![]() |
fe667e382b | |
![]() |
7975f64222 | |
![]() |
fca296445e | |
![]() |
cc392f0890 | |
![]() |
bba26a5291 | |
![]() |
c8f8194d76 | |
![]() |
c8b38f65fd | |
![]() |
3b62fdaebf | |
![]() |
2d45d1c5c6 | |
![]() |
2e6fe5a107 | |
![]() |
b0ae9e4b0c | |
![]() |
c1e55a5513 | |
![]() |
f8872e29ce | |
![]() |
48c91c08bc | |
![]() |
b1a60033c1 | |
![]() |
737b2df39c | |
![]() |
497432fd21 | |
![]() |
22a65c5331 | |
![]() |
c575d8059f | |
![]() |
b6a6f9490d | |
![]() |
8c1eb1526d | |
![]() |
ee3d26f696 | |
![]() |
c1e7738988 | |
![]() |
b3bbac02d5 | |
![]() |
fe50bd1ecc | |
![]() |
62d812308d | |
![]() |
5bed86aee9 | |
![]() |
46f31b65b3 | |
![]() |
a3ae437236 | |
![]() |
a198af8034 | |
![]() |
b9eba92ea5 | |
![]() |
155faf6cc2 | |
![]() |
50e5cd07f3 | |
![]() |
ab78860f09 | |
![]() |
36f511fb11 | |
![]() |
1bb00655d3 | |
![]() |
a33c2247ac | |
![]() |
0016f8c2aa | |
![]() |
e3b9a9588a | |
![]() |
42409146f2 | |
![]() |
aae22722fc | |
![]() |
13ce6e1c2f | |
![]() |
d990b80138 | |
![]() |
51f56dedf8 | |
![]() |
21a2bc896e | |
![]() |
2a42b14d0d | |
![]() |
a10cb3c818 | |
![]() |
548aea2c43 | |
![]() |
c2258841a7 | |
![]() |
9067ee4be0 | |
![]() |
e56f2b07be | |
![]() |
896f1c1332 | |
![]() |
90db6d9989 | |
![]() |
e20d9658cd | |
![]() |
b04a2cf088 | |
![]() |
1c5170d3a4 | |
![]() |
580a9f6c28 | |
![]() |
ab15256d8d | |
![]() |
9f2e3a3a1f | |
![]() |
e91c652af2 | |
![]() |
8a892fd85d | |
![]() |
741cdff85d | |
![]() |
14c4171f4f | |
![]() |
89a5062ab2 | |
![]() |
4e0e0d0497 | |
![]() |
6afd7d9688 | |
![]() |
756ffc4f52 | |
![]() |
8cb3896358 | |
![]() |
b40aa8359a | |
![]() |
12cfb740cc | |
![]() |
50f2507016 | |
![]() |
cdbb2b6c7a | |
![]() |
4c15d5da17 | |
![]() |
33c3985226 | |
![]() |
558cd81bdd | |
![]() |
c17a811c62 | |
![]() |
194d5caaef | |
![]() |
d922ecdd01 | |
![]() |
921cc17fec | |
![]() |
9ffdf60bf4 | |
![]() |
881012e443 | |
![]() |
bad5b28049 | |
![]() |
672ac09ea0 | |
![]() |
49300f2ade |
|
@ -0,0 +1,39 @@
|
||||||
|
# FreeBSD build with multiple versions
|
||||||
|
freebsd_versions_task:
|
||||||
|
name: FreeBSD $FREEBSD_VERSION make build
|
||||||
|
freebsd_instance:
|
||||||
|
image_family: $FREEBSD_IMAGE
|
||||||
|
matrix:
|
||||||
|
- env:
|
||||||
|
FREEBSD_VERSION: "13.5"
|
||||||
|
FREEBSD_IMAGE: freebsd-13-5
|
||||||
|
- env:
|
||||||
|
FREEBSD_VERSION: "14.3"
|
||||||
|
FREEBSD_IMAGE: freebsd-14-3
|
||||||
|
install_script:
|
||||||
|
- pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf
|
||||||
|
build_script:
|
||||||
|
- gmake
|
||||||
|
check_script:
|
||||||
|
- gmake check
|
||||||
|
|
||||||
|
# FreeBSD meson builds with multiple versions
|
||||||
|
freebsd_meson_versions_task:
|
||||||
|
name: FreeBSD $FREEBSD_VERSION meson build
|
||||||
|
freebsd_instance:
|
||||||
|
image_family: $FREEBSD_IMAGE
|
||||||
|
matrix:
|
||||||
|
- env:
|
||||||
|
FREEBSD_VERSION: "13.5"
|
||||||
|
FREEBSD_IMAGE: freebsd-13-5
|
||||||
|
- env:
|
||||||
|
FREEBSD_VERSION: "14.3"
|
||||||
|
FREEBSD_IMAGE: freebsd-14-3
|
||||||
|
install_script:
|
||||||
|
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
|
||||||
|
setup_script:
|
||||||
|
- meson setup -D python=enabled -D yaml=enabled build
|
||||||
|
build_script:
|
||||||
|
- meson compile -C build
|
||||||
|
test_script:
|
||||||
|
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
|
@ -0,0 +1,135 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
#
|
||||||
|
# clang-format configuration file. Intended for clang-format >= 11.
|
||||||
|
#
|
||||||
|
# For more information, see:
|
||||||
|
#
|
||||||
|
# Documentation/dev-tools/clang-format.rst
|
||||||
|
# https://clang.llvm.org/docs/ClangFormat.html
|
||||||
|
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
|
#
|
||||||
|
---
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 8
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: false
|
||||||
|
|
||||||
|
# Taken from:
|
||||||
|
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \
|
||||||
|
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||||
|
# | LC_ALL=C sort -u
|
||||||
|
ForEachMacros:
|
||||||
|
- 'fdt_for_each_property_offset'
|
||||||
|
- 'fdt_for_each_subnode'
|
||||||
|
- 'for_each_child'
|
||||||
|
- 'for_each_child_withdel'
|
||||||
|
- 'for_each_label'
|
||||||
|
- 'for_each_label_withdel'
|
||||||
|
- 'for_each_marker'
|
||||||
|
- 'for_each_marker_of_type'
|
||||||
|
- 'for_each_property'
|
||||||
|
- 'for_each_property_withdel'
|
||||||
|
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 8
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 8
|
||||||
|
ObjCSpaceAfterProperty: true
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
|
||||||
|
# Taken from git's rules
|
||||||
|
PenaltyBreakAssignment: 10
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 30
|
||||||
|
PenaltyBreakComment: 10
|
||||||
|
PenaltyBreakFirstLessLess: 0
|
||||||
|
PenaltyBreakString: 10
|
||||||
|
PenaltyExcessCharacter: 100
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: false
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: false
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp03
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Always
|
||||||
|
...
|
|
@ -0,0 +1,33 @@
|
||||||
|
# EditorConfig is a file format and collection of text editor plugins
|
||||||
|
# for maintaining consistent coding styles between different editors
|
||||||
|
# and IDEs. Most popular editors support this either natively or via
|
||||||
|
# plugin.
|
||||||
|
#
|
||||||
|
# Check https://editorconfig.org for details.
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[Makefile*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
file_type_emacs = makefile
|
||||||
|
|
||||||
|
[*.[ch]]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[meson.build]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.lds]
|
||||||
|
indent_style = tab
|
|
@ -0,0 +1,114 @@
|
||||||
|
---
|
||||||
|
name: Build test
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
|
||||||
|
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-make:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
||||||
|
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
./scripts/install-deps.sh
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
|
||||||
|
- name: Run check
|
||||||
|
run: |
|
||||||
|
make check
|
||||||
|
|
||||||
|
build-meson:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
||||||
|
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
./scripts/install-deps.sh
|
||||||
|
|
||||||
|
- name: Setup
|
||||||
|
run: meson setup -D python=enabled -D yaml=enabled build
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: meson compile -C build
|
||||||
|
|
||||||
|
- name: Run check
|
||||||
|
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { sys: mingw32 }
|
||||||
|
- { sys: mingw64 }
|
||||||
|
- { sys: ucrt64 }
|
||||||
|
- { sys: clang64 }
|
||||||
|
name: ${{ matrix.sys }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup MSYS2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: ${{matrix.sys}}
|
||||||
|
update: true
|
||||||
|
install: >-
|
||||||
|
git
|
||||||
|
flex
|
||||||
|
bison
|
||||||
|
pacboy: >-
|
||||||
|
toolchain:p
|
||||||
|
meson:p
|
||||||
|
ninja:p
|
||||||
|
libyaml:p
|
||||||
|
swig:p
|
||||||
|
python-setuptools-scm:p
|
||||||
|
|
||||||
|
- name: '🚧 Build'
|
||||||
|
run: |
|
||||||
|
meson setup -Dtools=true -Dtests=false build
|
||||||
|
meson compile -C build
|
|
@ -3,15 +3,28 @@
|
||||||
*.a
|
*.a
|
||||||
*.patch
|
*.patch
|
||||||
*.so
|
*.so
|
||||||
|
*.so.*
|
||||||
*~
|
*~
|
||||||
|
*.bak
|
||||||
*.tab.[ch]
|
*.tab.[ch]
|
||||||
lex.yy.c
|
lex.yy.c
|
||||||
*.lex.c
|
*.lex.c
|
||||||
|
.*.swp
|
||||||
/dtc
|
/dtc
|
||||||
/fdtdump
|
/fdtdump
|
||||||
/convert-dtsv0
|
/convert-dtsv0
|
||||||
/version_gen.h
|
/version_gen.h
|
||||||
/fdtget
|
/fdtget
|
||||||
/fdtput
|
/fdtput
|
||||||
|
/fdtoverlay
|
||||||
/patches
|
/patches
|
||||||
/.pc
|
/.pc
|
||||||
|
|
||||||
|
# cscope files
|
||||||
|
cscope.*
|
||||||
|
ncscope.*
|
||||||
|
|
||||||
|
.eggs/
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
variables:
|
||||||
|
GIT_DEPTH: 1
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci"
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
|
||||||
|
# Linux builds with make
|
||||||
|
.build-make-template: &build-make-template
|
||||||
|
stage: build
|
||||||
|
before_script:
|
||||||
|
- ./scripts/install-deps.sh
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
interruptible: true
|
||||||
|
|
||||||
|
build-make-alpine:
|
||||||
|
<<: *build-make-template
|
||||||
|
image: alpine:latest
|
||||||
|
|
||||||
|
build-make-archlinux:
|
||||||
|
<<: *build-make-template
|
||||||
|
image: archlinux:latest
|
||||||
|
|
||||||
|
build-make-fedora:
|
||||||
|
<<: *build-make-template
|
||||||
|
image: fedora:latest
|
||||||
|
|
||||||
|
build-make-ubuntu:
|
||||||
|
<<: *build-make-template
|
||||||
|
image: ubuntu:latest
|
||||||
|
|
||||||
|
# Linux builds with meson
|
||||||
|
.build-meson-template: &build-meson-template
|
||||||
|
stage: build
|
||||||
|
before_script:
|
||||||
|
- ./scripts/install-deps.sh
|
||||||
|
script:
|
||||||
|
- meson setup -D python=enabled -D yaml=enabled build
|
||||||
|
- meson compile -C build
|
||||||
|
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
||||||
|
interruptible: true
|
||||||
|
|
||||||
|
build-meson-alpine:
|
||||||
|
<<: *build-meson-template
|
||||||
|
image: alpine:latest
|
||||||
|
|
||||||
|
build-meson-archlinux:
|
||||||
|
<<: *build-meson-template
|
||||||
|
image: archlinux:latest
|
||||||
|
|
||||||
|
build-meson-fedora:
|
||||||
|
<<: *build-meson-template
|
||||||
|
image: fedora:latest
|
||||||
|
|
||||||
|
build-meson-ubuntu:
|
||||||
|
<<: *build-meson-template
|
||||||
|
image: ubuntu:latest
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# The first profile is the default
|
|
||||||
[gitpublishprofile "rhel"]
|
|
||||||
base = rhel7/master-1.4.3
|
|
||||||
prefix = RHEL-7.4 dtc PATCH
|
|
||||||
to = rhvirt-patches@redhat.com
|
|
||||||
suppresscc = all
|
|
||||||
message = True
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
language: c
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make
|
|
||||||
- make check
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
Valid-License-Identifier: BSD-2-Clause
|
||||||
|
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
|
||||||
|
Usage-Guide:
|
||||||
|
To use the BSD 2-clause "Simplified" License put the following SPDX
|
||||||
|
tag/value pair into a comment according to the placement guidelines in
|
||||||
|
the licensing rules documentation:
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
License-Text:
|
||||||
|
|
||||||
|
Copyright (c) <year> <owner> . All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Contributing to dtc or libfdt
|
||||||
|
|
||||||
|
There are two ways to submit changes for dtc or libfdt:
|
||||||
|
|
||||||
|
* Post patches directly to the
|
||||||
|
[devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
|
||||||
|
mailing list.
|
||||||
|
* Submit pull requests via
|
||||||
|
[Github](https://github.com/dgibson/dtc/pulls)
|
||||||
|
|
||||||
|
## Adding a new function to libfdt.h
|
||||||
|
|
||||||
|
The shared library uses `libfdt/version.lds` to list the exported
|
||||||
|
functions, so add your new function there. Check that your function
|
||||||
|
works with pylibfdt. If it cannot be supported, put the declaration in
|
||||||
|
`libfdt.h` behind `#ifndef SWIG` so that swig ignores it.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Test files are kept in the `tests/` directory. Use `make check` to build and run
|
||||||
|
all tests.
|
||||||
|
|
||||||
|
If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled
|
||||||
|
and checked against a binary tree from assembler macros in `trees.S`. So
|
||||||
|
if you change that file you must change `tree.S` also.
|
||||||
|
|
||||||
|
## Developer's Certificate of Origin
|
||||||
|
|
||||||
|
Like many other projects, dtc and libfdt have adopted the "Developer's
|
||||||
|
Certificate of Origin" (Signed-off-by) process created by the Linux
|
||||||
|
kernel community to improve tracking of who did what. Here's how it
|
||||||
|
works (this is a very slight modification of the description from
|
||||||
|
`Documentation/process/submitting-patches.rst` in the kernel tree):
|
||||||
|
|
||||||
|
The sign-off is a simple line at the end of the explanation for the
|
||||||
|
patch, which certifies that you wrote it or otherwise have the right
|
||||||
|
to pass it on as an open-source patch. The rules are pretty simple:
|
||||||
|
if you can certify the below:
|
||||||
|
|
||||||
|
Developer's Certificate of Origin 1.1
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the open source license
|
||||||
|
indicated in the file; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best
|
||||||
|
of my knowledge, is covered under an appropriate open source
|
||||||
|
license and I have the right under that license to submit that
|
||||||
|
work with modifications, whether created in whole or in part
|
||||||
|
by me, under the same open source license (unless I am
|
||||||
|
permitted to submit under a different license), as indicated
|
||||||
|
in the file; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
|
it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution
|
||||||
|
are public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license(s) involved.
|
||||||
|
|
||||||
|
then you just add a line saying::
|
||||||
|
|
||||||
|
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||||
|
|
||||||
|
using your real name (sorry, no pseudonyms or anonymous
|
||||||
|
contributions.) This will be done for you automatically if you use
|
||||||
|
`git commit -s`. Reverts should also include "Signed-off-by". `git
|
||||||
|
revert -s` does that for you.
|
||||||
|
|
||||||
|
Any further SoBs (Signed-off-by:'s) following the author's SoB are
|
||||||
|
from people handling and transporting the patch, but were not involved
|
||||||
|
in its development. SoB chains should reflect the **real** route a
|
||||||
|
patch took as it was propagated to the maintainers, with the first SoB
|
||||||
|
entry signalling primary authorship of a single author.
|
|
@ -6,7 +6,7 @@ the hardware capabilities. This is insufficient for platforms
|
||||||
that need to dynamically insert Device Tree fragments into the
|
that need to dynamically insert Device Tree fragments into the
|
||||||
live tree.
|
live tree.
|
||||||
|
|
||||||
This document explains the the Device Tree object format and
|
This document explains the Device Tree object format and
|
||||||
modifications made to the Device Tree compiler, which make it possible.
|
modifications made to the Device Tree compiler, which make it possible.
|
||||||
|
|
||||||
1. Simplified Problem Definition
|
1. Simplified Problem Definition
|
||||||
|
@ -35,7 +35,7 @@ We have a number of peripherals that after probing (using some undefined method)
|
||||||
should result in different Device Tree configuration.
|
should result in different Device Tree configuration.
|
||||||
|
|
||||||
We cannot boot with this static tree because due to the configuration of the
|
We cannot boot with this static tree because due to the configuration of the
|
||||||
foo platform there exist multiple conficting peripherals DT fragments.
|
foo platform there exist multiple conflicting peripherals DT fragments.
|
||||||
|
|
||||||
So for the bar peripheral we would have this:
|
So for the bar peripheral we would have this:
|
||||||
|
|
||||||
|
|
|
@ -37,15 +37,14 @@ The upstream repository is here:
|
||||||
git://git.kernel.org/pub/scm/utils/dtc/dtc.git
|
git://git.kernel.org/pub/scm/utils/dtc/dtc.git
|
||||||
https://git.kernel.org/pub/scm/utils/dtc/dtc.git
|
https://git.kernel.org/pub/scm/utils/dtc/dtc.git
|
||||||
|
|
||||||
The gitweb interface for the upstream respository is:
|
The gitweb interface for the upstream repository is:
|
||||||
|
|
||||||
https://git.kernel.org/cgit/utils/dtc/dtc.git/
|
https://git.kernel.org/cgit/utils/dtc/dtc.git/
|
||||||
|
|
||||||
1.1) Submitting Patches
|
1.1) Submitting Patches
|
||||||
|
|
||||||
Patches should be sent to the maintainers:
|
Patches should be sent to the maintainer:
|
||||||
David Gibson <david@gibson.dropbear.id.au>
|
David Gibson <david@gibson.dropbear.id.au>
|
||||||
Jon Loeliger <jdl@jdl.com>
|
|
||||||
and CCed to <devicetree-compiler@vger.kernel.org>.
|
and CCed to <devicetree-compiler@vger.kernel.org>.
|
||||||
|
|
||||||
2) Description
|
2) Description
|
||||||
|
@ -78,6 +77,9 @@ The currently supported Output Formats are:
|
||||||
then simply be added to your Makefile. Additionally, the
|
then simply be added to your Makefile. Additionally, the
|
||||||
assembly file exports some symbols that can be used.
|
assembly file exports some symbols that can be used.
|
||||||
|
|
||||||
|
- "yaml": DT encoded in YAML format. This representation is an
|
||||||
|
intermediate format used for validation tools.
|
||||||
|
|
||||||
|
|
||||||
3) Command Line
|
3) Command Line
|
||||||
|
|
||||||
|
@ -120,12 +122,24 @@ Options:
|
||||||
Relevant for dtb and asm output only.
|
Relevant for dtb and asm output only.
|
||||||
|
|
||||||
-@
|
-@
|
||||||
Generates a __symbols__ node at the root node of the resulting blob
|
Generates a __symbols__ node at the root node. This node contains a
|
||||||
for any node labels used, and for any local references using phandles
|
property for each label. The property's name is the label name and the
|
||||||
it also generates a __local_fixups__ node that tracks them.
|
value is the path of the labeled node.
|
||||||
|
|
||||||
When using the /plugin/ tag all unresolved label references to
|
-L
|
||||||
be tracked in the __fixups__ node, making dynamic resolution possible.
|
Possibly generates a __local_fixups__ and a __fixups__ node at the root node.
|
||||||
|
For each property that contains a phandle reference using a locally
|
||||||
|
defined phandle, the __local_fixups__ node contains a property (at path
|
||||||
|
/__local_fixups__/$a if $a is the path of the node). Its value is a list
|
||||||
|
of offsets that are phandle values. If there are no such properties, no
|
||||||
|
__local_fixups__ node is generated.
|
||||||
|
For each undefined label used in at least one reference, the __fixups__
|
||||||
|
node contains a property. Its name is the label name, its value is a
|
||||||
|
list of locations where the label is used in a reference in the format
|
||||||
|
"path:property:offset". If there is no undefined label, no __fixups__
|
||||||
|
nodes is generated.
|
||||||
|
Enabled by default for compiling overlays (i.e. dts files with a
|
||||||
|
/plugin/ tag).
|
||||||
|
|
||||||
-A
|
-A
|
||||||
Generate automatically aliases for all node labels. This is similar to
|
Generate automatically aliases for all node labels. This is similar to
|
||||||
|
@ -231,7 +245,7 @@ For example:
|
||||||
"childnode at address". It in turn has a string property
|
"childnode at address". It in turn has a string property
|
||||||
called "childprop".
|
called "childprop".
|
||||||
|
|
||||||
childnode@addresss {
|
childnode@address {
|
||||||
childprop = "hello\n";
|
childprop = "hello\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -250,7 +264,7 @@ Labels may be applied to nodes or properties. Labels appear
|
||||||
before a node name, and are referenced using an ampersand: &label.
|
before a node name, and are referenced using an ampersand: &label.
|
||||||
Absolute node path names are also allowed in node references.
|
Absolute node path names are also allowed in node references.
|
||||||
|
|
||||||
In this exmaple, a node is labled "mpic" and then referenced:
|
In this example, a node is labeled "mpic" and then referenced:
|
||||||
|
|
||||||
mpic: interrupt-controller@40000 {
|
mpic: interrupt-controller@40000 {
|
||||||
...
|
...
|
||||||
|
@ -261,7 +275,7 @@ In this exmaple, a node is labled "mpic" and then referenced:
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
And used in properties, lables may appear before or after any value:
|
And used in properties, labels may appear before or after any value:
|
||||||
|
|
||||||
randomnode {
|
randomnode {
|
||||||
prop: string = data: "mystring\n" data_end: ;
|
prop: string = data: "mystring\n" data_end: ;
|
||||||
|
@ -415,7 +429,7 @@ value of r3.
|
||||||
among others, by kexec. If you are on an SMP system, this value
|
among others, by kexec. If you are on an SMP system, this value
|
||||||
should match the content of the "reg" property of the CPU node in
|
should match the content of the "reg" property of the CPU node in
|
||||||
the device-tree corresponding to the CPU calling the kernel entry
|
the device-tree corresponding to the CPU calling the kernel entry
|
||||||
point (see further chapters for more informations on the required
|
point (see further chapters for more information on the required
|
||||||
device-tree contents)
|
device-tree contents)
|
||||||
|
|
||||||
- size_dt_strings
|
- size_dt_strings
|
||||||
|
@ -581,7 +595,7 @@ looks like in practice.
|
||||||
|
|
||||||
This tree is almost a minimal tree. It pretty much contains the
|
This tree is almost a minimal tree. It pretty much contains the
|
||||||
minimal set of required nodes and properties to boot a linux kernel;
|
minimal set of required nodes and properties to boot a linux kernel;
|
||||||
that is, some basic model informations at the root, the CPUs, and the
|
that is, some basic model information at the root, the CPUs, and the
|
||||||
physical memory layout. It also includes misc information passed
|
physical memory layout. It also includes misc information passed
|
||||||
through /chosen, like in this example, the platform type (mandatory)
|
through /chosen, like in this example, the platform type (mandatory)
|
||||||
and the kernel command line arguments (optional).
|
and the kernel command line arguments (optional).
|
||||||
|
@ -674,4 +688,86 @@ The fdtdump program prints a readable version of a flat device tree file.
|
||||||
|
|
||||||
The syntax of the fdtdump command line is:
|
The syntax of the fdtdump command line is:
|
||||||
|
|
||||||
fdtdump <DTB-file-name>
|
fdtdump [options] <DTB-file-name>
|
||||||
|
|
||||||
|
Where options are:
|
||||||
|
-d,--debug Dump debug information while decoding the file
|
||||||
|
-s,--scan Scan for an embedded fdt in given file
|
||||||
|
|
||||||
|
3) fdtoverlay -- Flat Device Tree overlay applicator
|
||||||
|
|
||||||
|
The fdtoverlay applies an arbitrary number of FDT overlays to a base FDT blob
|
||||||
|
to a given output file.
|
||||||
|
|
||||||
|
The syntax of the fdtoverlay command line is:
|
||||||
|
|
||||||
|
fdtoverlay -i <base-blob> -o <output-blob> <overlay-blob0> [<overlay-blob1> ...]
|
||||||
|
|
||||||
|
Where options are:
|
||||||
|
-i, --input Input base DT blob
|
||||||
|
-o, --output Output DT blob
|
||||||
|
-v, --verbose Verbose message output
|
||||||
|
|
||||||
|
4 ) fdtget -- Read properties from device tree
|
||||||
|
|
||||||
|
This command can be used to obtain individual values from the device tree in a
|
||||||
|
nicely formatted way. You can specify multiple nodes to display (when using -p)
|
||||||
|
or multiple node/property pairs (when not using -p). For the latter, each
|
||||||
|
property is displayed on its own line, with a space between each cell within
|
||||||
|
the property.
|
||||||
|
|
||||||
|
The syntax of the fdtget command is:
|
||||||
|
|
||||||
|
fdtget <options> <dt file> [<node> <property>]...
|
||||||
|
fdtget -p <options> <dt file> [<node> ]...
|
||||||
|
|
||||||
|
where options are:
|
||||||
|
|
||||||
|
<type> s=string, i=int, u=unsigned, x=hex, r=raw
|
||||||
|
Optional modifier prefix:
|
||||||
|
hh or b=byte, h=2 byte, l=4 byte (default)
|
||||||
|
|
||||||
|
Options: -[t:pld:hV]
|
||||||
|
-t, --type <arg> Type of data
|
||||||
|
-p, --properties List properties for each node
|
||||||
|
-l, --list List subnodes for each node
|
||||||
|
-d, --default <arg> Default value to display when the property is missing
|
||||||
|
-h, --help Print this help and exit
|
||||||
|
-V, --version Print version and exit
|
||||||
|
|
||||||
|
If -t is not provided, fdtget will try to figure out the type, trying to detect
|
||||||
|
strings, string lists and the size of each value in the property. This is
|
||||||
|
similar to how fdtdump works, and uses the same heuristics.
|
||||||
|
|
||||||
|
|
||||||
|
5 ) fdtput - Write properties to a device tree
|
||||||
|
|
||||||
|
The syntax of the fdtput command is:
|
||||||
|
|
||||||
|
fdtput <options> <dt file> <node> <property> [<value>...]
|
||||||
|
fdtput -c <options> <dt file> [<node>...]
|
||||||
|
fdtput -r <options> <dt file> [<node>...]
|
||||||
|
fdtput -d <options> <dt file> <node> [<property>...]
|
||||||
|
|
||||||
|
Options are:
|
||||||
|
|
||||||
|
<type> s=string, i=int, u=unsigned, x=hex
|
||||||
|
Optional modifier prefix:
|
||||||
|
hh or b=byte, h=2 byte, l=4 byte (default)
|
||||||
|
|
||||||
|
-c, --create Create nodes if they don't already exist
|
||||||
|
-r, --remove Delete nodes (and any subnodes) if they already exist
|
||||||
|
-d, --delete Delete properties if they already exist
|
||||||
|
-p, --auto-path Automatically create nodes as needed for the node path
|
||||||
|
-t, --type <arg> Type of data
|
||||||
|
-v, --verbose Display each value decoded from command line
|
||||||
|
-h, --help Print this help and exit
|
||||||
|
-V, --version Print version and exit
|
||||||
|
|
||||||
|
The option determines which usage is selected and therefore the operation that
|
||||||
|
is performed. The first usage adds or updates properties; the rest are used to
|
||||||
|
create/delete nodes and delete properties.
|
||||||
|
|
||||||
|
For the first usage, the command line arguments are joined together into a
|
||||||
|
single value which is written to the property. The -t option is required so
|
||||||
|
that fdtput knows how to decode its arguments.
|
||||||
|
|
25
GPL
25
GPL
|
@ -1,8 +1,8 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||||
General Public License applies to most of the Free Software
|
General Public License applies to most of the Free Software
|
||||||
Foundation's software and to any other program whose authors commit to
|
Foundation's software and to any other program whose authors commit to
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
your programs, too.
|
your programs, too.
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||||
License. (Exception: if the Program itself is interactive but
|
License. (Exception: if the Program itself is interactive but
|
||||||
does not normally print such an announcement, your work based on
|
does not normally print such an announcement, your work based on
|
||||||
the Program is not required to print an announcement.)
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
These requirements apply to the modified work as a whole. If
|
||||||
identifiable sections of that work are not derived from the Program,
|
identifiable sections of that work are not derived from the Program,
|
||||||
and can be reasonably considered independent and separate works in
|
and can be reasonably considered independent and separate works in
|
||||||
|
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||||
access to copy the source code from the same place counts as
|
access to copy the source code from the same place counts as
|
||||||
distribution of the source code, even though third parties are not
|
distribution of the source code, even though third parties are not
|
||||||
compelled to copy the source along with the object code.
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
except as expressly provided under this License. Any attempt
|
except as expressly provided under this License. Any attempt
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
@ -225,7 +225,7 @@ impose that choice.
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
This section is intended to make thoroughly clear what is believed to
|
||||||
be a consequence of the rest of this License.
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
original copyright holder who places the Program under this License
|
original copyright holder who places the Program under this License
|
||||||
|
@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License along
|
||||||
along with this program; if not, write to the Free Software
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||||
This General Public License does not permit incorporating your program into
|
This General Public License does not permit incorporating your program into
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
consider it more useful to permit linking proprietary applications with the
|
consider it more useful to permit linking proprietary applications with the
|
||||||
library. If this is what you want to do, use the GNU Library General
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License.
|
Public License instead of this License.
|
||||||
|
|
153
Makefile
153
Makefile
|
@ -1,29 +1,45 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#
|
#
|
||||||
# Device Tree Compiler
|
# Device Tree Compiler
|
||||||
#
|
#
|
||||||
|
|
||||||
|
$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com))
|
||||||
|
$(warning )
|
||||||
|
$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Version information will be constructed in this order:
|
# Version information will be constructed in this order:
|
||||||
# EXTRAVERSION might be "-rc", for example.
|
# DTC_VERSION release version as MAJOR.MINOR.PATCH
|
||||||
# LOCAL_VERSION is likely from command line.
|
# LOCAL_VERSION is likely from command line.
|
||||||
# CONFIG_LOCALVERSION from some future config system.
|
# CONFIG_LOCALVERSION from some future config system.
|
||||||
#
|
#
|
||||||
VERSION = 1
|
DTC_VERSION = $(shell cat VERSION.txt)
|
||||||
PATCHLEVEL = 4
|
|
||||||
SUBLEVEL = 3
|
|
||||||
EXTRAVERSION =
|
|
||||||
LOCAL_VERSION =
|
LOCAL_VERSION =
|
||||||
CONFIG_LOCALVERSION =
|
CONFIG_LOCALVERSION =
|
||||||
|
|
||||||
CPPFLAGS = -I libfdt -I .
|
# Control the assumptions made (e.g. risking security issues) in the code.
|
||||||
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
|
# See libfdt_internal.h for details
|
||||||
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
|
ASSUME_MASK ?= 0
|
||||||
CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
|
|
||||||
|
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
|
||||||
|
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
|
||||||
|
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \
|
||||||
|
-Wwrite-strings
|
||||||
|
ifeq ($(shell $(CC) --version | grep -q gcc && echo gcc),gcc)
|
||||||
|
WARNINGS += -Wsuggest-attribute=format
|
||||||
|
endif
|
||||||
|
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
|
||||||
|
|
||||||
BISON = bison
|
BISON = bison
|
||||||
LEX = flex
|
LEX = flex
|
||||||
|
SWIG = swig
|
||||||
|
PKG_CONFIG ?= pkg-config
|
||||||
|
|
||||||
INSTALL = /usr/bin/install
|
INSTALL = install
|
||||||
|
INSTALL_PROGRAM = $(INSTALL)
|
||||||
|
INSTALL_LIB = $(INSTALL)
|
||||||
|
INSTALL_DATA = $(INSTALL) -m 644
|
||||||
|
INSTALL_SCRIPT = $(INSTALL)
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
PREFIX = $(HOME)
|
PREFIX = $(HOME)
|
||||||
BINDIR = $(PREFIX)/bin
|
BINDIR = $(PREFIX)/bin
|
||||||
|
@ -31,14 +47,45 @@ LIBDIR = $(PREFIX)/lib
|
||||||
INCLUDEDIR = $(PREFIX)/include
|
INCLUDEDIR = $(PREFIX)/include
|
||||||
|
|
||||||
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
||||||
sed -e 's/\(cygwin\).*/cygwin/')
|
sed -e 's/\(cygwin\|msys\).*/\1/')
|
||||||
|
|
||||||
|
NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
|
||||||
|
ifeq ($(NO_VALGRIND),1)
|
||||||
|
CPPFLAGS += -DNO_VALGRIND
|
||||||
|
else
|
||||||
|
CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# libyaml before version 0.2.3 expects non-const string parameters. Supporting
|
||||||
|
# both variants would require either cpp magic or passing
|
||||||
|
# -Wno-error=discarded-qualifiers to the compiler. For the sake of simplicity
|
||||||
|
# just support libyaml >= 0.2.3.
|
||||||
|
NO_YAML := $(shell $(PKG_CONFIG) --atleast-version 0.2.3 yaml-0.1; echo $$?)
|
||||||
|
ifeq ($(NO_YAML),1)
|
||||||
|
CFLAGS += -DNO_YAML
|
||||||
|
else
|
||||||
|
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
|
||||||
|
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y)
|
||||||
|
|
||||||
ifeq ($(HOSTOS),darwin)
|
ifeq ($(HOSTOS),darwin)
|
||||||
SHAREDLIB_EXT = dylib
|
SHAREDLIB_EXT = dylib
|
||||||
SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl,
|
SHAREDLIB_CFLAGS = -fPIC
|
||||||
|
SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
|
||||||
|
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
|
||||||
|
SHAREDLIB_EXT = so
|
||||||
|
SHAREDLIB_CFLAGS =
|
||||||
|
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,
|
||||||
else
|
else
|
||||||
SHAREDLIB_EXT = so
|
SHAREDLIB_EXT = so
|
||||||
SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
SHAREDLIB_CFLAGS = -fPIC
|
||||||
|
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname,
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(HAS_VERSION_SCRIPT),y)
|
||||||
|
SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -63,7 +110,6 @@ endif
|
||||||
# Rules for versioning
|
# Rules for versioning
|
||||||
#
|
#
|
||||||
|
|
||||||
DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
|
||||||
VERSION_FILE = version_gen.h
|
VERSION_FILE = version_gen.h
|
||||||
|
|
||||||
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
||||||
|
@ -112,18 +158,21 @@ BIN += dtc
|
||||||
BIN += fdtdump
|
BIN += fdtdump
|
||||||
BIN += fdtget
|
BIN += fdtget
|
||||||
BIN += fdtput
|
BIN += fdtput
|
||||||
|
BIN += fdtoverlay
|
||||||
|
|
||||||
SCRIPTS = dtdiff
|
SCRIPTS = dtdiff
|
||||||
|
|
||||||
all: $(BIN) libfdt
|
all: $(BIN) libfdt
|
||||||
|
|
||||||
|
|
||||||
ifneq ($(DEPTARGETS),)
|
ifneq ($(DEPTARGETS),)
|
||||||
|
ifneq ($(MAKECMDGOALS),libfdt)
|
||||||
-include $(DTC_OBJS:%.o=%.d)
|
-include $(DTC_OBJS:%.o=%.d)
|
||||||
-include $(CONVERT_OBJS:%.o=%.d)
|
-include $(CONVERT_OBJS:%.o=%.d)
|
||||||
-include $(FDTDUMP_OBJS:%.o=%.d)
|
-include $(FDTDUMP_OBJS:%.o=%.d)
|
||||||
-include $(FDTGET_OBJS:%.o=%.d)
|
-include $(FDTGET_OBJS:%.o=%.d)
|
||||||
-include $(FDTPUT_OBJS:%.o=%.d)
|
-include $(FDTPUT_OBJS:%.o=%.d)
|
||||||
|
-include $(FDTOVERLAY_OBJS:%.o=%.d)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,28 +180,35 @@ endif
|
||||||
#
|
#
|
||||||
# Rules for libfdt
|
# Rules for libfdt
|
||||||
#
|
#
|
||||||
LIBFDT_objdir = libfdt
|
LIBFDT_dir = libfdt
|
||||||
LIBFDT_srcdir = libfdt
|
LIBFDT_archive = $(LIBFDT_dir)/libfdt.a
|
||||||
LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a
|
LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
|
||||||
LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
|
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
|
||||||
LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES))
|
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
|
||||||
LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION))
|
|
||||||
|
|
||||||
include $(LIBFDT_srcdir)/Makefile.libfdt
|
ifeq ($(STATIC_BUILD),1)
|
||||||
|
CFLAGS += -static
|
||||||
|
LIBFDT_dep = $(LIBFDT_archive)
|
||||||
|
else
|
||||||
|
LIBFDT_dep = $(LIBFDT_lib)
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(LIBFDT_dir)/Makefile.libfdt
|
||||||
|
|
||||||
.PHONY: libfdt
|
.PHONY: libfdt
|
||||||
libfdt: $(LIBFDT_archive) $(LIBFDT_lib)
|
libfdt: $(LIBFDT_archive) $(LIBFDT_lib)
|
||||||
|
|
||||||
$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
|
$(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
|
||||||
$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
|
|
||||||
|
|
||||||
libfdt_clean:
|
$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
|
||||||
@$(VECHO) CLEAN "(libfdt)"
|
@$(VECHO) LD $@
|
||||||
rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES))
|
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \
|
||||||
rm -f $(LIBFDT_objdir)/*.so
|
$(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
|
||||||
|
ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname)
|
||||||
|
ln -sf $(LIBFDT_soname) $(LIBFDT_dir)/$(LIBFDT_so)
|
||||||
|
|
||||||
ifneq ($(DEPTARGETS),)
|
ifneq ($(DEPTARGETS),)
|
||||||
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d)
|
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# This stops make from generating the lex and bison output during
|
# This stops make from generating the lex and bison output during
|
||||||
|
@ -163,20 +219,21 @@ endif
|
||||||
install-bin: all $(SCRIPTS)
|
install-bin: all $(SCRIPTS)
|
||||||
@$(VECHO) INSTALL-BIN
|
@$(VECHO) INSTALL-BIN
|
||||||
$(INSTALL) -d $(DESTDIR)$(BINDIR)
|
$(INSTALL) -d $(DESTDIR)$(BINDIR)
|
||||||
$(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR)
|
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
install-lib: all
|
install-lib: libfdt
|
||||||
@$(VECHO) INSTALL-LIB
|
@$(VECHO) INSTALL-LIB
|
||||||
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
|
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
|
||||||
$(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
|
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
|
||||||
ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname)
|
ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname)
|
||||||
ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT)
|
ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT)
|
||||||
$(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
|
$(INSTALL_DATA) $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
|
||||||
|
|
||||||
install-includes:
|
install-includes:
|
||||||
@$(VECHO) INSTALL-INC
|
@$(VECHO) INSTALL-INC
|
||||||
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
|
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
|
||||||
$(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
|
$(INSTALL_DATA) $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
|
||||||
|
|
||||||
install: install-bin install-lib install-includes
|
install: install-bin install-lib install-includes
|
||||||
|
|
||||||
|
@ -192,9 +249,11 @@ convert-dtsv0: $(CONVERT_OBJS)
|
||||||
|
|
||||||
fdtdump: $(FDTDUMP_OBJS)
|
fdtdump: $(FDTDUMP_OBJS)
|
||||||
|
|
||||||
fdtget: $(FDTGET_OBJS) $(LIBFDT_archive)
|
fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
|
||||||
|
|
||||||
fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive)
|
fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
|
||||||
|
|
||||||
|
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
|
||||||
|
|
||||||
dist:
|
dist:
|
||||||
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
||||||
|
@ -202,6 +261,7 @@ dist:
|
||||||
cat ../dtc-$(dtc_version).tar | \
|
cat ../dtc-$(dtc_version).tar | \
|
||||||
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Release signing and uploading
|
# Release signing and uploading
|
||||||
# This is for maintainer convenience, don't try this at home.
|
# This is for maintainer convenience, don't try this at home.
|
||||||
|
@ -234,8 +294,11 @@ TESTS_BIN += convert-dtsv0
|
||||||
TESTS_BIN += fdtput
|
TESTS_BIN += fdtput
|
||||||
TESTS_BIN += fdtget
|
TESTS_BIN += fdtget
|
||||||
TESTS_BIN += fdtdump
|
TESTS_BIN += fdtdump
|
||||||
|
TESTS_BIN += fdtoverlay
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),libfdt)
|
||||||
include tests/Makefile.tests
|
include tests/Makefile.tests
|
||||||
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clean rules
|
# Clean rules
|
||||||
|
@ -255,7 +318,7 @@ clean: libfdt_clean tests_clean
|
||||||
#
|
#
|
||||||
%: %.o
|
%: %.o
|
||||||
@$(VECHO) LD $@
|
@$(VECHO) LD $@
|
||||||
$(LINK.c) -o $@ $^
|
$(LINK.c) -o $@ $^ $(LDLIBS_$*)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
@$(VECHO) CC $@
|
@$(VECHO) CC $@
|
||||||
|
@ -263,11 +326,11 @@ clean: libfdt_clean tests_clean
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
@$(VECHO) AS $@
|
@$(VECHO) AS $@
|
||||||
$(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $<
|
$(CC) $(CPPFLAGS) $(AFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
%.d: %.c
|
%.d: %.c
|
||||||
@$(VECHO) DEP $<
|
@$(VECHO) DEP $<
|
||||||
$(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG -MT "$*.o $@" $< > $@
|
||||||
|
|
||||||
%.d: %.S
|
%.d: %.S
|
||||||
@$(VECHO) DEP $<
|
@$(VECHO) DEP $<
|
||||||
|
@ -285,16 +348,16 @@ clean: libfdt_clean tests_clean
|
||||||
@$(VECHO) AR $@
|
@$(VECHO) AR $@
|
||||||
$(AR) $(ARFLAGS) $@ $^
|
$(AR) $(ARFLAGS) $@ $^
|
||||||
|
|
||||||
$(LIBFDT_lib):
|
|
||||||
@$(VECHO) LD $@
|
|
||||||
$(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^
|
|
||||||
|
|
||||||
%.lex.c: %.l
|
%.lex.c: %.l
|
||||||
@$(VECHO) LEX $@
|
@$(VECHO) LEX $@
|
||||||
$(LEX) -o$@ $<
|
$(LEX) -o$@ $<
|
||||||
|
|
||||||
%.tab.c %.tab.h %.output: %.y
|
%.tab.c %.tab.h: %.y
|
||||||
@$(VECHO) BISON $@
|
@$(VECHO) BISON $@
|
||||||
$(BISON) -d $<
|
$(BISON) -b $(basename $(basename $@)) -d $<
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
|
ifeq ($(MAKE_RESTARTS),10)
|
||||||
|
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
|
||||||
|
endif
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#
|
#
|
||||||
# This is not a complete Makefile of itself.
|
# This is not a complete Makefile of itself.
|
||||||
# Instead, it is designed to be easily embeddable
|
# Instead, it is designed to be easily embeddable
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Makefile.dtc
|
# Makefile.dtc
|
||||||
#
|
#
|
||||||
# This is not a complete Makefile of itself. Instead, it is designed to
|
# This is not a complete Makefile of itself. Instead, it is designed to
|
||||||
|
@ -14,5 +15,9 @@ DTC_SRCS = \
|
||||||
treesource.c \
|
treesource.c \
|
||||||
util.c
|
util.c
|
||||||
|
|
||||||
|
ifneq ($(NO_YAML),1)
|
||||||
|
DTC_SRCS += yamltree.c
|
||||||
|
endif
|
||||||
|
|
||||||
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
|
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
|
||||||
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
|
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#
|
#
|
||||||
# This is not a complete Makefile of itself. Instead, it is designed to
|
# This is not a complete Makefile of itself. Instead, it is designed to
|
||||||
# be easily embeddable into other systems of Makefiles.
|
# be easily embeddable into other systems of Makefiles.
|
||||||
|
@ -22,3 +23,9 @@ FDTPUT_SRCS = \
|
||||||
util.c
|
util.c
|
||||||
|
|
||||||
FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)
|
FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)
|
||||||
|
|
||||||
|
FDTOVERLAY_SRCS = \
|
||||||
|
fdtoverlay.c \
|
||||||
|
util.c
|
||||||
|
|
||||||
|
FDTOVERLAY_OBJS = $(FDTOVERLAY_SRCS:%.c=%.o)
|
||||||
|
|
16
README
16
README
|
@ -1,16 +0,0 @@
|
||||||
The source tree contains the Device Tree Compiler (dtc) toolchain for
|
|
||||||
working with device tree source and binary files and also libfdt, a
|
|
||||||
utility library for reading and manipulating the binary format.
|
|
||||||
|
|
||||||
DTC and LIBFDT are maintained by:
|
|
||||||
|
|
||||||
David Gibson <david@gibson.dropbear.id.au>
|
|
||||||
Jon Loeliger <jdl@jdl.com>
|
|
||||||
|
|
||||||
Mailing list
|
|
||||||
------------
|
|
||||||
The following list is for discussion about dtc and libfdt implementation
|
|
||||||
mailto:devicetree-compiler@vger.kernel.org
|
|
||||||
|
|
||||||
Core device tree bindings are discussed on the devicetree-spec list:
|
|
||||||
mailto:devicetree-spec@vger.kernel.org
|
|
|
@ -4,11 +4,11 @@ Licensing and contribution policy of dtc and libfdt
|
||||||
This dtc package contains two pieces of software: dtc itself, and
|
This dtc package contains two pieces of software: dtc itself, and
|
||||||
libfdt which comprises the files in the libfdt/ subdirectory. These
|
libfdt which comprises the files in the libfdt/ subdirectory. These
|
||||||
two pieces of software, although closely related, are quite distinct.
|
two pieces of software, although closely related, are quite distinct.
|
||||||
dtc does not incoporate or rely on libfdt for its operation, nor vice
|
dtc does not incorporate or rely on libfdt for its operation, nor vice
|
||||||
versa. It is important that these two pieces of software have
|
versa. It is important that these two pieces of software have
|
||||||
different license conditions.
|
different license conditions.
|
||||||
|
|
||||||
As the copyright banners in each source file attest, dtc is licensed
|
As SPDX license tags in each source file attest, dtc is licensed
|
||||||
under the GNU GPL. The full text of the GPL can be found in the file
|
under the GNU GPL. The full text of the GPL can be found in the file
|
||||||
entitled 'GPL' which should be included in this package. dtc code,
|
entitled 'GPL' which should be included in this package. dtc code,
|
||||||
therefore, may not be incorporated into works which do not have a GPL
|
therefore, may not be incorporated into works which do not have a GPL
|
||||||
|
@ -16,10 +16,10 @@ compatible license.
|
||||||
|
|
||||||
libfdt, however, is GPL/BSD dual-licensed. That is, it may be used
|
libfdt, however, is GPL/BSD dual-licensed. That is, it may be used
|
||||||
either under the terms of the GPL, or under the terms of the 2-clause
|
either under the terms of the GPL, or under the terms of the 2-clause
|
||||||
BSD license (aka the ISC license). The full terms of that license are
|
BSD license (aka the ISC license). The full terms of that license can
|
||||||
given in the copyright banners of each of the libfdt source files.
|
be found are in the file entitled 'BSD-2-Clause'. This is, in
|
||||||
This is, in practice, equivalent to being BSD licensed, since the
|
practice, equivalent to being BSD licensed, since the terms of the BSD
|
||||||
terms of the BSD license are strictly more permissive than the GPL.
|
license are strictly more permissive than the GPL.
|
||||||
|
|
||||||
I made the decision to license libfdt in this way because I want to
|
I made the decision to license libfdt in this way because I want to
|
||||||
encourage widespread and correct usage of flattened device trees,
|
encourage widespread and correct usage of flattened device trees,
|
||||||
|
@ -28,12 +28,12 @@ tools. Allowing libfdt to be used under the terms of the BSD license
|
||||||
makes that it easier for vendors or authors of such software to do so.
|
makes that it easier for vendors or authors of such software to do so.
|
||||||
|
|
||||||
This does mean that libfdt code could be "stolen" - say, included in a
|
This does mean that libfdt code could be "stolen" - say, included in a
|
||||||
proprietary fimware and extended without contributing those extensions
|
proprietary firmware and extended without contributing those extensions
|
||||||
back to the libfdt mainline. While I hope that doesn't happen, I
|
back to the libfdt mainline. While I hope that doesn't happen, I
|
||||||
believe the goal of allowing libfdt to be widely used is more
|
believe the goal of allowing libfdt to be widely used is more
|
||||||
important than avoiding that. libfdt is quite small, and hardly
|
important than avoiding that. libfdt is quite small, and hardly
|
||||||
rocket science; so the incentive for such impolite behaviour is small,
|
rocket science; so the incentive for such impolite behaviour is small,
|
||||||
and the inconvenience caused therby is not dire.
|
and the inconvenience caused thereby is not dire.
|
||||||
|
|
||||||
Licenses such as the LGPL which would allow code to be used in non-GPL
|
Licenses such as the LGPL which would allow code to be used in non-GPL
|
||||||
software, but also require contributions to be returned were
|
software, but also require contributions to be returned were
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
# Device Tree Compiler and libfdt
|
||||||
|
|
||||||
|
The source tree contains the Device Tree Compiler (dtc) toolchain for
|
||||||
|
working with device tree source and binary files and also libfdt, a
|
||||||
|
utility library for reading and manipulating the binary format.
|
||||||
|
|
||||||
|
dtc and libfdt are maintained by:
|
||||||
|
|
||||||
|
* [David Gibson `<david@gibson.dropbear.id.au>`](mailto:david@gibson.dropbear.id.au)
|
||||||
|
|
||||||
|
## Python library
|
||||||
|
|
||||||
|
A Python library wrapping libfdt is also available. To build this you
|
||||||
|
will need to install `swig` and Python development files. On Debian
|
||||||
|
distributions:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt-get install swig python3-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The library provides an `Fdt` class which you can use like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ PYTHONPATH=../pylibfdt python3
|
||||||
|
>>> import libfdt
|
||||||
|
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
|
||||||
|
>>> node = fdt.path_offset('/subnode@1')
|
||||||
|
>>> print(node)
|
||||||
|
124
|
||||||
|
>>> prop_offset = fdt.first_property_offset(node)
|
||||||
|
>>> prop = fdt.get_property_by_offset(prop_offset)
|
||||||
|
>>> print('%s=%s' % (prop.name, prop.as_str()))
|
||||||
|
compatible=subnode1
|
||||||
|
>>> node2 = fdt.path_offset('/')
|
||||||
|
>>> print(fdt.getprop(node2, 'compatible').as_str())
|
||||||
|
test_tree1
|
||||||
|
```
|
||||||
|
|
||||||
|
You will find tests in `tests/pylibfdt_tests.py` showing how to use each
|
||||||
|
method. Help is available using the Python help command, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd pylibfdt
|
||||||
|
$ python3 -c "import libfdt; help(libfdt)"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you add new features, please check code coverage:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt-get install python3-coverage
|
||||||
|
$ cd tests
|
||||||
|
# It's just 'coverage' on most other distributions
|
||||||
|
$ python3-coverage run pylibfdt_tests.py
|
||||||
|
$ python3-coverage html
|
||||||
|
# Open 'htmlcov/index.html' in your browser
|
||||||
|
```
|
||||||
|
|
||||||
|
The library can be installed with pip from a local source tree:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pip install . [--user|--prefix=/path/to/install_dir]
|
||||||
|
```
|
||||||
|
|
||||||
|
Or directly from a remote git repo:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
|
||||||
|
```
|
||||||
|
|
||||||
|
The install depends on libfdt shared library being installed on the
|
||||||
|
host system first. Generally, using `--user` or `--prefix` is not
|
||||||
|
necessary and pip will use the default location for the Python
|
||||||
|
installation which varies if the user is root or not.
|
||||||
|
|
||||||
|
You can also install everything via make if you like, but pip is
|
||||||
|
recommended.
|
||||||
|
|
||||||
|
To install both libfdt and pylibfdt you can use:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make install [PREFIX=/path/to/install_dir]
|
||||||
|
```
|
||||||
|
|
||||||
|
To disable building the python library, even if swig and Python are available,
|
||||||
|
use:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make NO_PYTHON=1
|
||||||
|
```
|
||||||
|
|
||||||
|
More work remains to support all of libfdt, including access to numeric
|
||||||
|
values.
|
||||||
|
|
||||||
|
## Mailing lists
|
||||||
|
|
||||||
|
* The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
|
||||||
|
list is for discussion about dtc and libfdt implementation.
|
||||||
|
* Core device tree bindings are discussed on the
|
||||||
|
[devicetree-spec](mailto:devicetree-spec@vger.kernel.org) list.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
1.7.2
|
|
@ -1,20 +1,6 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005, 2008.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005, 2008.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%option noyywrap nounput noinput never-interactive
|
%option noyywrap nounput noinput never-interactive
|
||||||
|
@ -49,7 +35,7 @@ static int saw_hyphen; /* = 0 */
|
||||||
static unsigned long long last_val;
|
static unsigned long long last_val;
|
||||||
static char *last_name; /* = NULL */
|
static char *last_name; /* = NULL */
|
||||||
|
|
||||||
const struct {
|
static const struct {
|
||||||
const char *pattern;
|
const char *pattern;
|
||||||
int obase, width;
|
int obase, width;
|
||||||
} guess_table[] = {
|
} guess_table[] = {
|
||||||
|
@ -108,7 +94,7 @@ const struct {
|
||||||
<INITIAL>[0-9a-fA-F]+ {
|
<INITIAL>[0-9a-fA-F]+ {
|
||||||
unsigned long long val;
|
unsigned long long val;
|
||||||
int obase = 16, width = 0;
|
int obase = 16, width = 0;
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
val = strtoull(yytext, NULL, cbase);
|
val = strtoull(yytext, NULL, cbase);
|
||||||
|
|
||||||
|
|
90
data.c
90
data.c
|
@ -1,21 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
@ -36,10 +21,10 @@ void data_free(struct data d)
|
||||||
free(d.val);
|
free(d.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data data_grow_for(struct data d, int xlen)
|
struct data data_grow_for(struct data d, unsigned int xlen)
|
||||||
{
|
{
|
||||||
struct data nd;
|
struct data nd;
|
||||||
int newsize;
|
unsigned int newsize;
|
||||||
|
|
||||||
if (xlen == 0)
|
if (xlen == 0)
|
||||||
return d;
|
return d;
|
||||||
|
@ -74,7 +59,8 @@ struct data data_copy_escape_string(const char *s, int len)
|
||||||
struct data d;
|
struct data d;
|
||||||
char *q;
|
char *q;
|
||||||
|
|
||||||
d = data_grow_for(empty_data, len + 1);
|
d = data_add_marker(empty_data, TYPE_STRING, NULL);
|
||||||
|
d = data_grow_for(d, len + 1);
|
||||||
|
|
||||||
q = d.val;
|
q = d.val;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
|
@ -94,10 +80,11 @@ struct data data_copy_file(FILE *f, size_t maxlen)
|
||||||
{
|
{
|
||||||
struct data d = empty_data;
|
struct data d = empty_data;
|
||||||
|
|
||||||
|
d = data_add_marker(d, TYPE_NONE, NULL);
|
||||||
while (!feof(f) && (d.len < maxlen)) {
|
while (!feof(f) && (d.len < maxlen)) {
|
||||||
size_t chunksize, ret;
|
size_t chunksize, ret;
|
||||||
|
|
||||||
if (maxlen == -1)
|
if (maxlen == (size_t)-1)
|
||||||
chunksize = 4096;
|
chunksize = 4096;
|
||||||
else
|
else
|
||||||
chunksize = maxlen - d.len;
|
chunksize = maxlen - d.len;
|
||||||
|
@ -171,9 +158,9 @@ struct data data_merge(struct data d1, struct data d2)
|
||||||
struct data data_append_integer(struct data d, uint64_t value, int bits)
|
struct data data_append_integer(struct data d, uint64_t value, int bits)
|
||||||
{
|
{
|
||||||
uint8_t value_8;
|
uint8_t value_8;
|
||||||
uint16_t value_16;
|
fdt16_t value_16;
|
||||||
uint32_t value_32;
|
fdt32_t value_32;
|
||||||
uint64_t value_64;
|
fdt64_t value_64;
|
||||||
|
|
||||||
switch (bits) {
|
switch (bits) {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -197,14 +184,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
|
struct data data_append_re(struct data d, uint64_t address, uint64_t size)
|
||||||
{
|
{
|
||||||
struct fdt_reserve_entry bere;
|
struct fdt_reserve_entry re;
|
||||||
|
|
||||||
bere.address = cpu_to_fdt64(re->address);
|
re.address = cpu_to_fdt64(address);
|
||||||
bere.size = cpu_to_fdt64(re->size);
|
re.size = cpu_to_fdt64(size);
|
||||||
|
|
||||||
return data_append_data(d, &bere, sizeof(bere));
|
return data_append_data(d, &re, sizeof(re));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct data data_append_cell(struct data d, cell_t word)
|
struct data data_append_cell(struct data d, cell_t word)
|
||||||
|
@ -241,11 +228,7 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
|
||||||
{
|
{
|
||||||
struct marker *m;
|
struct marker *m;
|
||||||
|
|
||||||
m = xmalloc(sizeof(*m));
|
m = alloc_marker(d.len, type, ref);
|
||||||
m->offset = d.len;
|
|
||||||
m->type = type;
|
|
||||||
m->ref = ref;
|
|
||||||
m->next = NULL;
|
|
||||||
|
|
||||||
return data_append_markers(d, m);
|
return data_append_markers(d, m);
|
||||||
}
|
}
|
||||||
|
@ -267,3 +250,44 @@ bool data_is_one_string(struct data d)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct data data_insert_data(struct data d, struct marker *m, struct data old)
|
||||||
|
{
|
||||||
|
unsigned int offset = m->offset;
|
||||||
|
struct marker *next = m->next;
|
||||||
|
struct marker *marker;
|
||||||
|
struct data new_data;
|
||||||
|
char *ref;
|
||||||
|
|
||||||
|
new_data = data_insert_at_marker(d, m, old.val, old.len);
|
||||||
|
|
||||||
|
/* Copy all markers from old value */
|
||||||
|
marker = old.markers;
|
||||||
|
for_each_marker(marker) {
|
||||||
|
ref = NULL;
|
||||||
|
|
||||||
|
if (marker->ref)
|
||||||
|
ref = xstrdup(marker->ref);
|
||||||
|
|
||||||
|
m->next = alloc_marker(marker->offset + offset, marker->type,
|
||||||
|
ref);
|
||||||
|
m = m->next;
|
||||||
|
}
|
||||||
|
m->next = next;
|
||||||
|
|
||||||
|
return new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct marker *alloc_marker(unsigned int offset, enum markertype type,
|
||||||
|
char *ref)
|
||||||
|
{
|
||||||
|
struct marker *m;
|
||||||
|
|
||||||
|
m = xmalloc(sizeof(*m));
|
||||||
|
m->offset = offset;
|
||||||
|
m->type = type;
|
||||||
|
m->ref = ref;
|
||||||
|
m->next = NULL;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
55
dtc-lexer.l
55
dtc-lexer.l
|
@ -1,21 +1,6 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%option noyywrap nounput noinput never-interactive
|
%option noyywrap nounput noinput never-interactive
|
||||||
|
@ -38,7 +23,6 @@ LINECOMMENT "//".*\n
|
||||||
#include "srcpos.h"
|
#include "srcpos.h"
|
||||||
#include "dtc-parser.tab.h"
|
#include "dtc-parser.tab.h"
|
||||||
|
|
||||||
YYLTYPE yylloc;
|
|
||||||
extern bool treesource_error;
|
extern bool treesource_error;
|
||||||
|
|
||||||
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
|
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
|
||||||
|
@ -62,12 +46,7 @@ static int dts_version = 1;
|
||||||
|
|
||||||
static void push_input_file(const char *filename);
|
static void push_input_file(const char *filename);
|
||||||
static bool pop_input_file(void);
|
static bool pop_input_file(void);
|
||||||
#ifdef __GNUC__
|
static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||||
static void lexical_error(const char *fmt, ...)
|
|
||||||
__attribute__((format (printf, 1, 2)));
|
|
||||||
#else
|
|
||||||
static void lexical_error(const char *fmt, ...);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -78,7 +57,7 @@ static void lexical_error(const char *fmt, ...);
|
||||||
push_input_file(name);
|
push_input_file(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
|
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
|
||||||
char *line, *fnstart, *fnend;
|
char *line, *fnstart, *fnend;
|
||||||
struct data fn;
|
struct data fn;
|
||||||
/* skip text before line # */
|
/* skip text before line # */
|
||||||
|
@ -158,6 +137,13 @@ static void lexical_error(const char *fmt, ...);
|
||||||
return DT_DEL_NODE;
|
return DT_DEL_NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<*>"/omit-if-no-ref/" {
|
||||||
|
DPRINT("Keyword: /omit-if-no-ref/\n");
|
||||||
|
DPRINT("<PROPNODENAME>\n");
|
||||||
|
BEGIN(PROPNODENAME);
|
||||||
|
return DT_OMIT_NO_REF;
|
||||||
|
}
|
||||||
|
|
||||||
<*>{LABEL}: {
|
<*>{LABEL}: {
|
||||||
DPRINT("Label: %s\n", yytext);
|
DPRINT("Label: %s\n", yytext);
|
||||||
yylval.labelref = xstrdup(yytext);
|
yylval.labelref = xstrdup(yytext);
|
||||||
|
@ -165,6 +151,21 @@ static void lexical_error(const char *fmt, ...);
|
||||||
return DT_LABEL;
|
return DT_LABEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<V1>{LABEL} {
|
||||||
|
/* Missed includes or macro definitions while
|
||||||
|
* preprocessing can lead to unexpected identifiers in
|
||||||
|
* the input. Report a slightly more informative error
|
||||||
|
* in this case */
|
||||||
|
|
||||||
|
lexical_error("Unexpected '%s'", yytext);
|
||||||
|
|
||||||
|
/* Treat it as a literal which often generates further
|
||||||
|
* useful error messages */
|
||||||
|
|
||||||
|
yylval.integer = 0;
|
||||||
|
return DT_LITERAL;
|
||||||
|
}
|
||||||
|
|
||||||
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
|
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
|
||||||
char *e;
|
char *e;
|
||||||
DPRINT("Integer Literal: '%s'\n", yytext);
|
DPRINT("Integer Literal: '%s'\n", yytext);
|
||||||
|
@ -211,14 +212,14 @@ static void lexical_error(const char *fmt, ...);
|
||||||
<*>\&{LABEL} { /* label reference */
|
<*>\&{LABEL} { /* label reference */
|
||||||
DPRINT("Ref: %s\n", yytext+1);
|
DPRINT("Ref: %s\n", yytext+1);
|
||||||
yylval.labelref = xstrdup(yytext+1);
|
yylval.labelref = xstrdup(yytext+1);
|
||||||
return DT_REF;
|
return DT_LABEL_REF;
|
||||||
}
|
}
|
||||||
|
|
||||||
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
|
<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
|
||||||
yytext[yyleng-1] = '\0';
|
yytext[yyleng-1] = '\0';
|
||||||
DPRINT("Ref: %s\n", yytext+2);
|
DPRINT("Ref: %s\n", yytext+2);
|
||||||
yylval.labelref = xstrdup(yytext+2);
|
yylval.labelref = xstrdup(yytext+2);
|
||||||
return DT_REF;
|
return DT_PATH_REF;
|
||||||
}
|
}
|
||||||
|
|
||||||
<BYTESTRING>[0-9a-fA-F]{2} {
|
<BYTESTRING>[0-9a-fA-F]{2} {
|
||||||
|
|
154
dtc-parser.y
154
dtc-parser.y
|
@ -1,22 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
%locations
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -32,8 +19,16 @@ extern void yyerror(char const *s);
|
||||||
treesource_error = true; \
|
treesource_error = true; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define YYERROR_CALL(msg) yyerror(msg)
|
||||||
|
|
||||||
extern struct dt_info *parser_output;
|
extern struct dt_info *parser_output;
|
||||||
extern bool treesource_error;
|
extern bool treesource_error;
|
||||||
|
|
||||||
|
static bool is_ref_relative(const char *ref)
|
||||||
|
{
|
||||||
|
return ref[0] != '/' && strchr(&ref[1], '/');
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
@ -63,13 +58,15 @@ extern bool treesource_error;
|
||||||
%token DT_BITS
|
%token DT_BITS
|
||||||
%token DT_DEL_PROP
|
%token DT_DEL_PROP
|
||||||
%token DT_DEL_NODE
|
%token DT_DEL_NODE
|
||||||
|
%token DT_OMIT_NO_REF
|
||||||
%token <propnodename> DT_PROPNODENAME
|
%token <propnodename> DT_PROPNODENAME
|
||||||
%token <integer> DT_LITERAL
|
%token <integer> DT_LITERAL
|
||||||
%token <integer> DT_CHAR_LITERAL
|
%token <integer> DT_CHAR_LITERAL
|
||||||
%token <byte> DT_BYTE
|
%token <byte> DT_BYTE
|
||||||
%token <data> DT_STRING
|
%token <data> DT_STRING
|
||||||
%token <labelref> DT_LABEL
|
%token <labelref> DT_LABEL
|
||||||
%token <labelref> DT_REF
|
%token <labelref> DT_LABEL_REF
|
||||||
|
%token <labelref> DT_PATH_REF
|
||||||
%token DT_INCBIN
|
%token DT_INCBIN
|
||||||
|
|
||||||
%type <data> propdata
|
%type <data> propdata
|
||||||
|
@ -82,6 +79,7 @@ extern bool treesource_error;
|
||||||
%type <data> bytestring
|
%type <data> bytestring
|
||||||
%type <prop> propdef
|
%type <prop> propdef
|
||||||
%type <proplist> proplist
|
%type <proplist> proplist
|
||||||
|
%type <labelref> dt_ref
|
||||||
|
|
||||||
%type <node> devicetree
|
%type <node> devicetree
|
||||||
%type <node> nodedef
|
%type <node> nodedef
|
||||||
|
@ -157,6 +155,8 @@ memreserve:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
dt_ref: DT_LABEL_REF | DT_PATH_REF;
|
||||||
|
|
||||||
devicetree:
|
devicetree:
|
||||||
'/' nodedef
|
'/' nodedef
|
||||||
{
|
{
|
||||||
|
@ -166,11 +166,29 @@ devicetree:
|
||||||
{
|
{
|
||||||
$$ = merge_nodes($1, $3);
|
$$ = merge_nodes($1, $3);
|
||||||
}
|
}
|
||||||
|
| dt_ref nodedef
|
||||||
| devicetree DT_LABEL DT_REF nodedef
|
{
|
||||||
|
/*
|
||||||
|
* We rely on the rule being always:
|
||||||
|
* versioninfo plugindecl memreserves devicetree
|
||||||
|
* so $-1 is what we want (plugindecl)
|
||||||
|
*/
|
||||||
|
if (!($<flags>-1 & DTSF_PLUGIN))
|
||||||
|
ERROR(&@2, "Label or path %s not found", $1);
|
||||||
|
else if (is_ref_relative($1))
|
||||||
|
ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
|
||||||
|
$$ = add_orphan_node(
|
||||||
|
name_node(build_node(NULL, NULL, NULL),
|
||||||
|
""),
|
||||||
|
$2, $1);
|
||||||
|
}
|
||||||
|
| devicetree DT_LABEL dt_ref nodedef
|
||||||
{
|
{
|
||||||
struct node *target = get_node_by_ref($1, $3);
|
struct node *target = get_node_by_ref($1, $3);
|
||||||
|
|
||||||
|
if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
|
||||||
|
ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
add_label(&target->labels, $2);
|
add_label(&target->labels, $2);
|
||||||
merge_nodes(target, $4);
|
merge_nodes(target, $4);
|
||||||
|
@ -178,17 +196,47 @@ devicetree:
|
||||||
ERROR(&@3, "Label or path %s not found", $3);
|
ERROR(&@3, "Label or path %s not found", $3);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| devicetree DT_REF nodedef
|
| devicetree DT_PATH_REF nodedef
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* We rely on the rule being always:
|
||||||
|
* versioninfo plugindecl memreserves devicetree
|
||||||
|
* so $-1 is what we want (plugindecl)
|
||||||
|
*/
|
||||||
|
if ($<flags>-1 & DTSF_PLUGIN) {
|
||||||
|
if (is_ref_relative($2))
|
||||||
|
ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
|
||||||
|
add_orphan_node($1, $3, $2);
|
||||||
|
} else {
|
||||||
struct node *target = get_node_by_ref($1, $2);
|
struct node *target = get_node_by_ref($1, $2);
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
merge_nodes(target, $3);
|
merge_nodes(target, $3);
|
||||||
else
|
else
|
||||||
ERROR(&@2, "Label or path %s not found", $2);
|
ERROR(&@2, "Label or path %s not found", $2);
|
||||||
|
}
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
| devicetree DT_DEL_NODE DT_REF ';'
|
| devicetree DT_LABEL_REF nodedef
|
||||||
|
{
|
||||||
|
struct node *target = get_node_by_ref($1, $2);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
merge_nodes(target, $3);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We rely on the rule being always:
|
||||||
|
* versioninfo plugindecl memreserves devicetree
|
||||||
|
* so $-1 is what we want (plugindecl)
|
||||||
|
*/
|
||||||
|
if ($<flags>-1 & DTSF_PLUGIN)
|
||||||
|
add_orphan_node($1, $3, $2);
|
||||||
|
else
|
||||||
|
ERROR(&@2, "Label or path %s not found", $2);
|
||||||
|
}
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
| devicetree DT_DEL_NODE dt_ref ';'
|
||||||
{
|
{
|
||||||
struct node *target = get_node_by_ref($1, $3);
|
struct node *target = get_node_by_ref($1, $3);
|
||||||
|
|
||||||
|
@ -198,6 +246,18 @@ devicetree:
|
||||||
ERROR(&@3, "Label or path %s not found", $3);
|
ERROR(&@3, "Label or path %s not found", $3);
|
||||||
|
|
||||||
|
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
| devicetree DT_OMIT_NO_REF dt_ref ';'
|
||||||
|
{
|
||||||
|
struct node *target = get_node_by_ref($1, $3);
|
||||||
|
|
||||||
|
if (target)
|
||||||
|
omit_node_if_unused(target);
|
||||||
|
else
|
||||||
|
ERROR(&@3, "Label or path %s not found", $3);
|
||||||
|
|
||||||
|
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -205,7 +265,7 @@ devicetree:
|
||||||
nodedef:
|
nodedef:
|
||||||
'{' proplist subnodes '}' ';'
|
'{' proplist subnodes '}' ';'
|
||||||
{
|
{
|
||||||
$$ = build_node($2, $3);
|
$$ = build_node($2, $3, &@$);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -223,15 +283,18 @@ proplist:
|
||||||
propdef:
|
propdef:
|
||||||
DT_PROPNODENAME '=' propdata ';'
|
DT_PROPNODENAME '=' propdata ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($1, $3);
|
$$ = build_property($1, $3, &@$);
|
||||||
|
free($1);
|
||||||
}
|
}
|
||||||
| DT_PROPNODENAME ';'
|
| DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($1, empty_data);
|
$$ = build_property($1, empty_data, &@$);
|
||||||
|
free($1);
|
||||||
}
|
}
|
||||||
| DT_DEL_PROP DT_PROPNODENAME ';'
|
| DT_DEL_PROP DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = build_property_delete($2);
|
$$ = build_property_delete($2);
|
||||||
|
free($2);
|
||||||
}
|
}
|
||||||
| DT_LABEL propdef
|
| DT_LABEL propdef
|
||||||
{
|
{
|
||||||
|
@ -253,8 +316,9 @@ propdata:
|
||||||
{
|
{
|
||||||
$$ = data_merge($1, $3);
|
$$ = data_merge($1, $3);
|
||||||
}
|
}
|
||||||
| propdataprefix DT_REF
|
| propdataprefix dt_ref
|
||||||
{
|
{
|
||||||
|
$1 = data_add_marker($1, TYPE_STRING, $2);
|
||||||
$$ = data_add_marker($1, REF_PATH, $2);
|
$$ = data_add_marker($1, REF_PATH, $2);
|
||||||
}
|
}
|
||||||
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
|
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
|
||||||
|
@ -308,22 +372,27 @@ arrayprefix:
|
||||||
DT_BITS DT_LITERAL '<'
|
DT_BITS DT_LITERAL '<'
|
||||||
{
|
{
|
||||||
unsigned long long bits;
|
unsigned long long bits;
|
||||||
|
enum markertype type = TYPE_UINT32;
|
||||||
|
|
||||||
bits = $2;
|
bits = $2;
|
||||||
|
|
||||||
if ((bits != 8) && (bits != 16) &&
|
switch (bits) {
|
||||||
(bits != 32) && (bits != 64)) {
|
case 8: type = TYPE_UINT8; break;
|
||||||
|
case 16: type = TYPE_UINT16; break;
|
||||||
|
case 32: type = TYPE_UINT32; break;
|
||||||
|
case 64: type = TYPE_UINT64; break;
|
||||||
|
default:
|
||||||
ERROR(&@2, "Array elements must be"
|
ERROR(&@2, "Array elements must be"
|
||||||
" 8, 16, 32 or 64-bits");
|
" 8, 16, 32 or 64-bits");
|
||||||
bits = 32;
|
bits = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
$$.data = empty_data;
|
$$.data = data_add_marker(empty_data, type, NULL);
|
||||||
$$.bits = bits;
|
$$.bits = bits;
|
||||||
}
|
}
|
||||||
| '<'
|
| '<'
|
||||||
{
|
{
|
||||||
$$.data = empty_data;
|
$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
|
||||||
$$.bits = 32;
|
$$.bits = 32;
|
||||||
}
|
}
|
||||||
| arrayprefix integer_prim
|
| arrayprefix integer_prim
|
||||||
|
@ -338,14 +407,19 @@ arrayprefix:
|
||||||
* within the mask to one (i.e. | in the
|
* within the mask to one (i.e. | in the
|
||||||
* mask), all bits are one.
|
* mask), all bits are one.
|
||||||
*/
|
*/
|
||||||
if (($2 > mask) && (($2 | mask) != -1ULL))
|
if (($2 > mask) && (($2 | mask) != -1ULL)) {
|
||||||
ERROR(&@2, "Value out of range for"
|
char *loc = srcpos_string(&@2);
|
||||||
" %d-bit array element", $1.bits);
|
fprintf(stderr,
|
||||||
|
"WARNING: %s: Value 0x%016" PRIx64
|
||||||
|
" truncated to 0x%0*" PRIx64 "\n",
|
||||||
|
loc, $2, $1.bits / 4, ($2 & mask));
|
||||||
|
free(loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$$.data = data_append_integer($1.data, $2, $1.bits);
|
$$.data = data_append_integer($1.data, $2, $1.bits);
|
||||||
}
|
}
|
||||||
| arrayprefix DT_REF
|
| arrayprefix dt_ref
|
||||||
{
|
{
|
||||||
uint64_t val = ~0ULL >> (64 - $1.bits);
|
uint64_t val = ~0ULL >> (64 - $1.bits);
|
||||||
|
|
||||||
|
@ -423,8 +497,8 @@ integer_rela:
|
||||||
;
|
;
|
||||||
|
|
||||||
integer_shift:
|
integer_shift:
|
||||||
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
|
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
|
||||||
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
|
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
|
||||||
| integer_add
|
| integer_add
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -467,7 +541,7 @@ integer_unary:
|
||||||
bytestring:
|
bytestring:
|
||||||
/* empty */
|
/* empty */
|
||||||
{
|
{
|
||||||
$$ = empty_data;
|
$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
|
||||||
}
|
}
|
||||||
| bytestring DT_BYTE
|
| bytestring DT_BYTE
|
||||||
{
|
{
|
||||||
|
@ -499,10 +573,16 @@ subnode:
|
||||||
DT_PROPNODENAME nodedef
|
DT_PROPNODENAME nodedef
|
||||||
{
|
{
|
||||||
$$ = name_node($2, $1);
|
$$ = name_node($2, $1);
|
||||||
|
free($1);
|
||||||
}
|
}
|
||||||
| DT_DEL_NODE DT_PROPNODENAME ';'
|
| DT_DEL_NODE DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = name_node(build_node_delete(), $2);
|
$$ = name_node(build_node_delete(&@$), $2);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
| DT_OMIT_NO_REF subnode
|
||||||
|
{
|
||||||
|
$$ = omit_node_if_unused($2);
|
||||||
}
|
}
|
||||||
| DT_LABEL subnode
|
| DT_LABEL subnode
|
||||||
{
|
{
|
||||||
|
|
72
dtc.c
72
dtc.c
|
@ -1,21 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -27,14 +12,16 @@
|
||||||
* Command line options
|
* Command line options
|
||||||
*/
|
*/
|
||||||
int quiet; /* Level of quietness */
|
int quiet; /* Level of quietness */
|
||||||
int reservenum; /* Number of memory reservation slots */
|
unsigned int reservenum;/* Number of memory reservation slots */
|
||||||
int minsize; /* Minimum blob size */
|
int minsize; /* Minimum blob size */
|
||||||
int padsize; /* Additional padding to blob */
|
int padsize; /* Additional padding to blob */
|
||||||
int alignsize; /* Additional padding to blob accroding to the alignsize */
|
int alignsize; /* Additional padding to blob according to the alignsize */
|
||||||
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
|
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
|
||||||
int generate_symbols; /* enable symbols & fixup support */
|
int generate_symbols; /* enable symbols & fixup support */
|
||||||
int generate_fixups; /* suppress generation of fixups on symbol support */
|
int generate_fixups; /* suppress generation of fixups on symbol support */
|
||||||
int auto_label_aliases; /* auto generate labels -> aliases */
|
int auto_label_aliases; /* auto generate labels -> aliases */
|
||||||
|
int annotate; /* Level of annotation: 1 for input source location
|
||||||
|
>1 for full input source location. */
|
||||||
|
|
||||||
static int is_power_of_2(int x)
|
static int is_power_of_2(int x)
|
||||||
{
|
{
|
||||||
|
@ -59,10 +46,8 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usage related data. */
|
/* Usage related data. */
|
||||||
#define FDT_VERSION(version) _FDT_VERSION(version)
|
|
||||||
#define _FDT_VERSION(version) #version
|
|
||||||
static const char usage_synopsis[] = "dtc [options] <input file>";
|
static const char usage_synopsis[] = "dtc [options] <input file>";
|
||||||
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
|
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";
|
||||||
static struct option const usage_long_opts[] = {
|
static struct option const usage_long_opts[] = {
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
{"quiet", no_argument, NULL, 'q'},
|
||||||
{"in-format", a_argument, NULL, 'I'},
|
{"in-format", a_argument, NULL, 'I'},
|
||||||
|
@ -82,7 +67,9 @@ static struct option const usage_long_opts[] = {
|
||||||
{"warning", a_argument, NULL, 'W'},
|
{"warning", a_argument, NULL, 'W'},
|
||||||
{"error", a_argument, NULL, 'E'},
|
{"error", a_argument, NULL, 'E'},
|
||||||
{"symbols", no_argument, NULL, '@'},
|
{"symbols", no_argument, NULL, '@'},
|
||||||
|
{"local-fixups", no_argument, NULL, 'L'},
|
||||||
{"auto-alias", no_argument, NULL, 'A'},
|
{"auto-alias", no_argument, NULL, 'A'},
|
||||||
|
{"annotate", no_argument, NULL, 'T'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
{NULL, no_argument, NULL, 0x0},
|
{NULL, no_argument, NULL, 0x0},
|
||||||
|
@ -97,8 +84,11 @@ static const char * const usage_opts_help[] = {
|
||||||
"\n\tOutput formats are:\n"
|
"\n\tOutput formats are:\n"
|
||||||
"\t\tdts - device tree source text\n"
|
"\t\tdts - device tree source text\n"
|
||||||
"\t\tdtb - device tree blob\n"
|
"\t\tdtb - device tree blob\n"
|
||||||
|
#ifndef NO_YAML
|
||||||
|
"\t\tyaml - device tree encoded as YAML\n"
|
||||||
|
#endif
|
||||||
"\t\tasm - assembler source",
|
"\t\tasm - assembler source",
|
||||||
"\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
||||||
"\n\tOutput dependency file",
|
"\n\tOutput dependency file",
|
||||||
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
|
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
|
||||||
"\n\tMake the blob at least <bytes> long (extra space)",
|
"\n\tMake the blob at least <bytes> long (extra space)",
|
||||||
|
@ -115,7 +105,9 @@ static const char * const usage_opts_help[] = {
|
||||||
"\n\tEnable/disable warnings (prefix with \"no-\")",
|
"\n\tEnable/disable warnings (prefix with \"no-\")",
|
||||||
"\n\tEnable/disable errors (prefix with \"no-\")",
|
"\n\tEnable/disable errors (prefix with \"no-\")",
|
||||||
"\n\tEnable generation of symbols",
|
"\n\tEnable generation of symbols",
|
||||||
|
"\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node",
|
||||||
"\n\tEnable auto-alias of labels",
|
"\n\tEnable auto-alias of labels",
|
||||||
|
"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
|
||||||
"\n\tPrint this help and exit",
|
"\n\tPrint this help and exit",
|
||||||
"\n\tPrint version and exit",
|
"\n\tPrint version and exit",
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -130,6 +122,10 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
|
||||||
return fallback;
|
return fallback;
|
||||||
if (!strcasecmp(s, ".dts"))
|
if (!strcasecmp(s, ".dts"))
|
||||||
return "dts";
|
return "dts";
|
||||||
|
if (!strcasecmp(s, ".yaml"))
|
||||||
|
return "yaml";
|
||||||
|
if (!strcasecmp(s, ".dtbo"))
|
||||||
|
return "dtb";
|
||||||
if (!strcasecmp(s, ".dtb"))
|
if (!strcasecmp(s, ".dtb"))
|
||||||
return "dtb";
|
return "dtb";
|
||||||
return fallback;
|
return fallback;
|
||||||
|
@ -138,7 +134,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
|
||||||
static const char *guess_input_format(const char *fname, const char *fallback)
|
static const char *guess_input_format(const char *fname, const char *fallback)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
uint32_t magic;
|
fdt32_t magic;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (stat(fname, &statbuf) != 0)
|
if (stat(fname, &statbuf) != 0)
|
||||||
|
@ -159,8 +155,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
magic = fdt32_to_cpu(magic);
|
if (fdt32_to_cpu(magic) == FDT_MAGIC)
|
||||||
if (magic == FDT_MAGIC)
|
|
||||||
return "dtb";
|
return "dtb";
|
||||||
|
|
||||||
return guess_type_by_name(fname, fallback);
|
return guess_type_by_name(fname, fallback);
|
||||||
|
@ -204,7 +199,7 @@ int main(int argc, char *argv[])
|
||||||
depname = optarg;
|
depname = optarg;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
reservenum = strtol(optarg, NULL, 0);
|
reservenum = strtoul(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
minsize = strtol(optarg, NULL, 0);
|
minsize = strtol(optarg, NULL, 0);
|
||||||
|
@ -259,9 +254,17 @@ int main(int argc, char *argv[])
|
||||||
case '@':
|
case '@':
|
||||||
generate_symbols = 1;
|
generate_symbols = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
generate_fixups = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
auto_label_aliases = 1;
|
auto_label_aliases = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
annotate++;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(NULL);
|
usage(NULL);
|
||||||
|
@ -286,7 +289,9 @@ int main(int argc, char *argv[])
|
||||||
if (!depfile)
|
if (!depfile)
|
||||||
die("Couldn't open dependency file %s: %s\n", depname,
|
die("Couldn't open dependency file %s: %s\n", depname,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
fprintf(depfile, "%s:", outname);
|
|
||||||
|
fprint_path_escaped(depfile, outname);
|
||||||
|
fputc(':', depfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inform == NULL)
|
if (inform == NULL)
|
||||||
|
@ -300,6 +305,8 @@ int main(int argc, char *argv[])
|
||||||
outform = "dts";
|
outform = "dts";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
|
||||||
|
die("--annotate requires -I dts -O dts\n");
|
||||||
if (streq(inform, "dts"))
|
if (streq(inform, "dts"))
|
||||||
dti = dt_from_source(arg);
|
dti = dt_from_source(arg);
|
||||||
else if (streq(inform, "fs"))
|
else if (streq(inform, "fs"))
|
||||||
|
@ -320,13 +327,14 @@ int main(int argc, char *argv[])
|
||||||
dti->boot_cpuid_phys = cmdline_boot_cpuid;
|
dti->boot_cpuid_phys = cmdline_boot_cpuid;
|
||||||
|
|
||||||
fill_fullpaths(dti->dt, "");
|
fill_fullpaths(dti->dt, "");
|
||||||
process_checks(force, dti);
|
|
||||||
|
|
||||||
/* on a plugin, generate by default */
|
/* on a plugin, generate by default */
|
||||||
if (dti->dtsflags & DTSF_PLUGIN) {
|
if (dti->dtsflags & DTSF_PLUGIN) {
|
||||||
generate_fixups = 1;
|
generate_fixups = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_checks(force, dti);
|
||||||
|
|
||||||
if (auto_label_aliases)
|
if (auto_label_aliases)
|
||||||
generate_label_tree(dti, "aliases", false);
|
generate_label_tree(dti, "aliases", false);
|
||||||
|
|
||||||
|
@ -352,6 +360,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (streq(outform, "dts")) {
|
if (streq(outform, "dts")) {
|
||||||
dt_to_source(outf, dti);
|
dt_to_source(outf, dti);
|
||||||
|
#ifndef NO_YAML
|
||||||
|
} else if (streq(outform, "yaml")) {
|
||||||
|
if (!streq(inform, "dts"))
|
||||||
|
die("YAML output format requires dts input format\n");
|
||||||
|
dt_to_yaml(outf, dti);
|
||||||
|
#endif
|
||||||
} else if (streq(outform, "dtb")) {
|
} else if (streq(outform, "dtb")) {
|
||||||
dt_to_blob(outf, dti, outversion);
|
dt_to_blob(outf, dti, outversion);
|
||||||
} else if (streq(outform, "asm")) {
|
} else if (streq(outform, "asm")) {
|
||||||
|
|
160
dtc.h
160
dtc.h
|
@ -1,24 +1,9 @@
|
||||||
#ifndef _DTC_H
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
#define _DTC_H
|
#ifndef DTC_H
|
||||||
|
#define DTC_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -31,6 +16,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <libfdt_env.h>
|
#include <libfdt_env.h>
|
||||||
#include <fdt.h>
|
#include <fdt.h>
|
||||||
|
@ -43,21 +29,21 @@
|
||||||
#define debug(...)
|
#define debug(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_FDT_VERSION 17
|
#define DEFAULT_FDT_VERSION 17
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Command line options
|
* Command line options
|
||||||
*/
|
*/
|
||||||
extern int quiet; /* Level of quietness */
|
extern int quiet; /* Level of quietness */
|
||||||
extern int reservenum; /* Number of memory reservation slots */
|
extern unsigned int reservenum; /* Number of memory reservation slots */
|
||||||
extern int minsize; /* Minimum blob size */
|
extern int minsize; /* Minimum blob size */
|
||||||
extern int padsize; /* Additional padding to blob */
|
extern int padsize; /* Additional padding to blob */
|
||||||
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
|
extern int alignsize; /* Additional padding to blob according to the alignsize */
|
||||||
extern int phandle_format; /* Use linux,phandle or phandle properties */
|
extern int phandle_format; /* Use linux,phandle or phandle properties */
|
||||||
extern int generate_symbols; /* generate symbols for nodes with labels */
|
extern int generate_symbols; /* generate symbols for nodes with labels */
|
||||||
extern int generate_fixups; /* generate fixups */
|
extern int generate_fixups; /* generate fixups */
|
||||||
extern int auto_label_aliases; /* auto generate labels -> aliases */
|
extern int auto_label_aliases; /* auto generate labels -> aliases */
|
||||||
|
extern int annotate; /* annotate .dts with input source location */
|
||||||
|
|
||||||
#define PHANDLE_LEGACY 0x1
|
#define PHANDLE_LEGACY 0x1
|
||||||
#define PHANDLE_EPAPR 0x2
|
#define PHANDLE_EPAPR 0x2
|
||||||
|
@ -65,28 +51,88 @@ extern int auto_label_aliases; /* auto generate labels -> aliases */
|
||||||
|
|
||||||
typedef uint32_t cell_t;
|
typedef uint32_t cell_t;
|
||||||
|
|
||||||
|
static inline bool phandle_is_valid(cell_t phandle)
|
||||||
|
{
|
||||||
|
return phandle != 0 && phandle != ~0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t dtb_ld16(const void *p)
|
||||||
|
{
|
||||||
|
const uint8_t *bp = (const uint8_t *)p;
|
||||||
|
|
||||||
|
return ((uint16_t)bp[0] << 8)
|
||||||
|
| bp[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t dtb_ld32(const void *p)
|
||||||
|
{
|
||||||
|
const uint8_t *bp = (const uint8_t *)p;
|
||||||
|
|
||||||
|
return ((uint32_t)bp[0] << 24)
|
||||||
|
| ((uint32_t)bp[1] << 16)
|
||||||
|
| ((uint32_t)bp[2] << 8)
|
||||||
|
| bp[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t dtb_ld64(const void *p)
|
||||||
|
{
|
||||||
|
const uint8_t *bp = (const uint8_t *)p;
|
||||||
|
|
||||||
|
return ((uint64_t)bp[0] << 56)
|
||||||
|
| ((uint64_t)bp[1] << 48)
|
||||||
|
| ((uint64_t)bp[2] << 40)
|
||||||
|
| ((uint64_t)bp[3] << 32)
|
||||||
|
| ((uint64_t)bp[4] << 24)
|
||||||
|
| ((uint64_t)bp[5] << 16)
|
||||||
|
| ((uint64_t)bp[6] << 8)
|
||||||
|
| bp[7];
|
||||||
|
}
|
||||||
|
|
||||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||||
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
||||||
|
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
||||||
|
static inline bool strends(const char *str, const char *suffix)
|
||||||
|
{
|
||||||
|
unsigned int len, suffix_len;
|
||||||
|
|
||||||
|
len = strlen(str);
|
||||||
|
suffix_len = strlen(suffix);
|
||||||
|
if (len < suffix_len)
|
||||||
|
return false;
|
||||||
|
return streq(str + len - suffix_len, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
|
|
||||||
/* Data blobs */
|
/* Data blobs */
|
||||||
enum markertype {
|
enum markertype {
|
||||||
|
TYPE_NONE,
|
||||||
REF_PHANDLE,
|
REF_PHANDLE,
|
||||||
REF_PATH,
|
REF_PATH,
|
||||||
LABEL,
|
LABEL,
|
||||||
|
TYPE_UINT8,
|
||||||
|
TYPE_UINT16,
|
||||||
|
TYPE_UINT32,
|
||||||
|
TYPE_UINT64,
|
||||||
|
TYPE_STRING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline bool is_type_marker(enum markertype type)
|
||||||
|
{
|
||||||
|
return type >= TYPE_UINT8;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const char *markername(enum markertype markertype);
|
||||||
|
|
||||||
struct marker {
|
struct marker {
|
||||||
enum markertype type;
|
enum markertype type;
|
||||||
int offset;
|
unsigned int offset;
|
||||||
char *ref;
|
char *ref;
|
||||||
struct marker *next;
|
struct marker *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
int len;
|
unsigned int len;
|
||||||
char *val;
|
char *val;
|
||||||
struct marker *markers;
|
struct marker *markers;
|
||||||
};
|
};
|
||||||
|
@ -100,9 +146,26 @@ struct data {
|
||||||
for_each_marker(m) \
|
for_each_marker(m) \
|
||||||
if ((m)->type == (t))
|
if ((m)->type == (t))
|
||||||
|
|
||||||
|
static inline struct marker *next_type_marker(struct marker *m)
|
||||||
|
{
|
||||||
|
for_each_marker(m)
|
||||||
|
if (is_type_marker(m->type))
|
||||||
|
break;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t type_marker_length(struct marker *m)
|
||||||
|
{
|
||||||
|
struct marker *next = next_type_marker(m->next);
|
||||||
|
|
||||||
|
if (next)
|
||||||
|
return next->offset - m->offset;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void data_free(struct data d);
|
void data_free(struct data d);
|
||||||
|
|
||||||
struct data data_grow_for(struct data d, int xlen);
|
struct data data_grow_for(struct data d, unsigned int xlen);
|
||||||
|
|
||||||
struct data data_copy_mem(const char *mem, int len);
|
struct data data_copy_mem(const char *mem, int len);
|
||||||
struct data data_copy_escape_string(const char *s, int len);
|
struct data data_copy_escape_string(const char *s, int len);
|
||||||
|
@ -114,12 +177,15 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
|
||||||
struct data data_merge(struct data d1, struct data d2);
|
struct data data_merge(struct data d1, struct data d2);
|
||||||
struct data data_append_cell(struct data d, cell_t word);
|
struct data data_append_cell(struct data d, cell_t word);
|
||||||
struct data data_append_integer(struct data d, uint64_t word, int bits);
|
struct data data_append_integer(struct data d, uint64_t word, int bits);
|
||||||
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
|
struct data data_append_re(struct data d, uint64_t address, uint64_t size);
|
||||||
struct data data_append_addr(struct data d, uint64_t addr);
|
struct data data_append_addr(struct data d, uint64_t addr);
|
||||||
struct data data_append_byte(struct data d, uint8_t byte);
|
struct data data_append_byte(struct data d, uint8_t byte);
|
||||||
struct data data_append_zeroes(struct data d, int len);
|
struct data data_append_zeroes(struct data d, int len);
|
||||||
struct data data_append_align(struct data d, int align);
|
struct data data_append_align(struct data d, int align);
|
||||||
|
struct data data_insert_data(struct data d, struct marker *m, struct data old);
|
||||||
|
|
||||||
|
struct marker *alloc_marker(unsigned int offset, enum markertype type,
|
||||||
|
char *ref);
|
||||||
struct data data_add_marker(struct data d, enum markertype type, char *ref);
|
struct data data_add_marker(struct data d, enum markertype type, char *ref);
|
||||||
|
|
||||||
bool data_is_one_string(struct data d);
|
bool data_is_one_string(struct data d);
|
||||||
|
@ -136,6 +202,10 @@ struct label {
|
||||||
struct label *next;
|
struct label *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bus_type {
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
struct property {
|
struct property {
|
||||||
bool deleted;
|
bool deleted;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -144,6 +214,7 @@ struct property {
|
||||||
struct property *next;
|
struct property *next;
|
||||||
|
|
||||||
struct label *labels;
|
struct label *labels;
|
||||||
|
struct srcpos *srcpos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
@ -162,6 +233,10 @@ struct node {
|
||||||
int addr_cells, size_cells;
|
int addr_cells, size_cells;
|
||||||
|
|
||||||
struct label *labels;
|
struct label *labels;
|
||||||
|
const struct bus_type *bus;
|
||||||
|
struct srcpos *srcpos;
|
||||||
|
|
||||||
|
bool omit_if_unused, is_referenced;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define for_each_label_withdel(l0, l) \
|
#define for_each_label_withdel(l0, l) \
|
||||||
|
@ -188,16 +263,21 @@ struct node {
|
||||||
void add_label(struct label **labels, char *label);
|
void add_label(struct label **labels, char *label);
|
||||||
void delete_labels(struct label **labels);
|
void delete_labels(struct label **labels);
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val);
|
struct property *build_property(const char *name, struct data val,
|
||||||
struct property *build_property_delete(char *name);
|
struct srcpos *srcpos);
|
||||||
|
struct property *build_property_delete(const char *name);
|
||||||
struct property *chain_property(struct property *first, struct property *list);
|
struct property *chain_property(struct property *first, struct property *list);
|
||||||
struct property *reverse_properties(struct property *first);
|
struct property *reverse_properties(struct property *first);
|
||||||
|
|
||||||
struct node *build_node(struct property *proplist, struct node *children);
|
struct node *build_node(struct property *proplist, struct node *children,
|
||||||
struct node *build_node_delete(void);
|
struct srcpos *srcpos);
|
||||||
struct node *name_node(struct node *node, char *name);
|
struct node *build_node_delete(struct srcpos *srcpos);
|
||||||
|
struct node *name_node(struct node *node, const char *name);
|
||||||
|
struct node *omit_node_if_unused(struct node *node);
|
||||||
|
struct node *reference_node(struct node *node);
|
||||||
struct node *chain_node(struct node *first, struct node *list);
|
struct node *chain_node(struct node *first, struct node *list);
|
||||||
struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
||||||
|
struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
||||||
|
|
||||||
void add_property(struct node *node, struct property *prop);
|
void add_property(struct node *node, struct property *prop);
|
||||||
void delete_property_by_name(struct node *node, char *name);
|
void delete_property_by_name(struct node *node, char *name);
|
||||||
|
@ -206,11 +286,13 @@ void add_child(struct node *parent, struct node *child);
|
||||||
void delete_node_by_name(struct node *parent, char *name);
|
void delete_node_by_name(struct node *parent, char *name);
|
||||||
void delete_node(struct node *node);
|
void delete_node(struct node *node);
|
||||||
void append_to_property(struct node *node,
|
void append_to_property(struct node *node,
|
||||||
char *name, const void *data, int len);
|
char *name, const void *data, int len,
|
||||||
|
enum markertype type);
|
||||||
|
|
||||||
const char *get_unitname(struct node *node);
|
const char *get_unitname(struct node *node);
|
||||||
struct property *get_property(struct node *node, const char *propname);
|
struct property *get_property(struct node *node, const char *propname);
|
||||||
cell_t propval_cell(struct property *prop);
|
cell_t propval_cell(struct property *prop);
|
||||||
|
cell_t propval_cell_n(struct property *prop, unsigned int n);
|
||||||
struct property *get_property_by_label(struct node *tree, const char *label,
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
||||||
struct node **node);
|
struct node **node);
|
||||||
struct marker *get_marker_label(struct node *tree, const char *label,
|
struct marker *get_marker_label(struct node *tree, const char *label,
|
||||||
|
@ -227,7 +309,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
|
||||||
/* Boot info (tree plus memreserve information */
|
/* Boot info (tree plus memreserve information */
|
||||||
|
|
||||||
struct reserve_info {
|
struct reserve_info {
|
||||||
struct fdt_reserve_entry re;
|
uint64_t address, size;
|
||||||
|
|
||||||
struct reserve_info *next;
|
struct reserve_info *next;
|
||||||
|
|
||||||
|
@ -257,9 +339,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
|
||||||
struct reserve_info *reservelist,
|
struct reserve_info *reservelist,
|
||||||
struct node *tree, uint32_t boot_cpuid_phys);
|
struct node *tree, uint32_t boot_cpuid_phys);
|
||||||
void sort_tree(struct dt_info *dti);
|
void sort_tree(struct dt_info *dti);
|
||||||
void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
|
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
|
||||||
void generate_fixups_tree(struct dt_info *dti, char *name);
|
void generate_fixups_tree(struct dt_info *dti, const char *name);
|
||||||
void generate_local_fixups_tree(struct dt_info *dti, char *name);
|
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
|
||||||
|
|
||||||
/* Checks */
|
/* Checks */
|
||||||
|
|
||||||
|
@ -278,8 +360,12 @@ struct dt_info *dt_from_blob(const char *fname);
|
||||||
void dt_to_source(FILE *f, struct dt_info *dti);
|
void dt_to_source(FILE *f, struct dt_info *dti);
|
||||||
struct dt_info *dt_from_source(const char *f);
|
struct dt_info *dt_from_source(const char *f);
|
||||||
|
|
||||||
|
/* YAML source */
|
||||||
|
|
||||||
|
void dt_to_yaml(FILE *f, struct dt_info *dti);
|
||||||
|
|
||||||
/* FS trees */
|
/* FS trees */
|
||||||
|
|
||||||
struct dt_info *dt_from_fs(const char *dirname);
|
struct dt_info *dt_from_fs(const char *dirname);
|
||||||
|
|
||||||
#endif /* _DTC_H */
|
#endif /* DTC_H */
|
||||||
|
|
3
dtdiff
3
dtdiff
|
@ -1,4 +1,5 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
# This script uses the bash <(...) extension.
|
# This script uses the bash <(...) extension.
|
||||||
# If you want to change this to work with a generic /bin/sh, make sure
|
# If you want to change this to work with a generic /bin/sh, make sure
|
||||||
|
@ -16,7 +17,7 @@ source_and_sort () {
|
||||||
*.dts)
|
*.dts)
|
||||||
IFORMAT=dts
|
IFORMAT=dts
|
||||||
;;
|
;;
|
||||||
*.dtb)
|
*.dtb|*.dtbo)
|
||||||
IFORMAT=dtb
|
IFORMAT=dtb
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
62
fdtdump.c
62
fdtdump.c
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
|
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
#include <libfdt_env.h>
|
#include <libfdt_env.h>
|
||||||
|
@ -16,11 +18,11 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define FDT_MAGIC_SIZE 4
|
#define FDT_MAGIC_SIZE 4
|
||||||
#define MAX_VERSION 17
|
#define MAX_VERSION 17U
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||||
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
|
#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
|
||||||
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
|
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
|
||||||
|
|
||||||
static const char *tagname(uint32_t tag)
|
static const char *tagname(uint32_t tag)
|
||||||
{
|
{
|
||||||
|
@ -65,23 +67,24 @@ static void dump_blob(void *blob, bool debug)
|
||||||
shift = 4;
|
shift = 4;
|
||||||
|
|
||||||
printf("/dts-v1/;\n");
|
printf("/dts-v1/;\n");
|
||||||
printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
|
printf("// magic:\t\t0x%"PRIx32"\n", fdt32_to_cpu(bph->magic));
|
||||||
printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
|
printf("// totalsize:\t\t0x%"PRIx32" (%"PRIu32")\n",
|
||||||
printf("// off_dt_struct:\t0x%x\n", off_dt);
|
totalsize, totalsize);
|
||||||
printf("// off_dt_strings:\t0x%x\n", off_str);
|
printf("// off_dt_struct:\t0x%"PRIx32"\n", off_dt);
|
||||||
printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
|
printf("// off_dt_strings:\t0x%"PRIx32"\n", off_str);
|
||||||
printf("// version:\t\t%d\n", version);
|
printf("// off_mem_rsvmap:\t0x%"PRIx32"\n", off_mem_rsvmap);
|
||||||
printf("// last_comp_version:\t%d\n",
|
printf("// version:\t\t%"PRIu32"\n", version);
|
||||||
|
printf("// last_comp_version:\t%"PRIu32"\n",
|
||||||
fdt32_to_cpu(bph->last_comp_version));
|
fdt32_to_cpu(bph->last_comp_version));
|
||||||
if (version >= 2)
|
if (version >= 2)
|
||||||
printf("// boot_cpuid_phys:\t0x%x\n",
|
printf("// boot_cpuid_phys:\t0x%"PRIx32"\n",
|
||||||
fdt32_to_cpu(bph->boot_cpuid_phys));
|
fdt32_to_cpu(bph->boot_cpuid_phys));
|
||||||
|
|
||||||
if (version >= 3)
|
if (version >= 3)
|
||||||
printf("// size_dt_strings:\t0x%x\n",
|
printf("// size_dt_strings:\t0x%"PRIx32"\n",
|
||||||
fdt32_to_cpu(bph->size_dt_strings));
|
fdt32_to_cpu(bph->size_dt_strings));
|
||||||
if (version >= 17)
|
if (version >= 17)
|
||||||
printf("// size_dt_struct:\t0x%x\n",
|
printf("// size_dt_struct:\t0x%"PRIx32"\n",
|
||||||
fdt32_to_cpu(bph->size_dt_struct));
|
fdt32_to_cpu(bph->size_dt_struct));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
@ -91,14 +94,14 @@ static void dump_blob(void *blob, bool debug)
|
||||||
if (addr == 0 && size == 0)
|
if (addr == 0 && size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
printf("/memreserve/ %#llx %#llx;\n",
|
printf("/memreserve/ %#"PRIx64" %#"PRIx64";\n",
|
||||||
(unsigned long long)addr, (unsigned long long)size);
|
addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = p_struct;
|
p = p_struct;
|
||||||
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
|
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
|
||||||
|
|
||||||
dumpf("%04zx: tag: 0x%08x (%s)\n",
|
dumpf("%04"PRIxPTR": tag: 0x%08"PRIx32" (%s)\n",
|
||||||
(uintptr_t)p - blob_off - 4, tag, tagname(tag));
|
(uintptr_t)p - blob_off - 4, tag, tagname(tag));
|
||||||
|
|
||||||
if (tag == FDT_BEGIN_NODE) {
|
if (tag == FDT_BEGIN_NODE) {
|
||||||
|
@ -127,7 +130,7 @@ static void dump_blob(void *blob, bool debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag != FDT_PROP) {
|
if (tag != FDT_PROP) {
|
||||||
fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
|
fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sz = fdt32_to_cpu(GET_CELL(p));
|
sz = fdt32_to_cpu(GET_CELL(p));
|
||||||
|
@ -138,8 +141,8 @@ static void dump_blob(void *blob, bool debug)
|
||||||
|
|
||||||
p = PALIGN(p + sz, 4);
|
p = PALIGN(p + sz, 4);
|
||||||
|
|
||||||
dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
|
dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s);
|
||||||
dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
|
dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off);
|
||||||
printf("%*s%s", depth * shift, "", s);
|
printf("%*s%s", depth * shift, "", s);
|
||||||
utilfdt_print_data(t, sz);
|
utilfdt_print_data(t, sz);
|
||||||
printf(";\n");
|
printf(";\n");
|
||||||
|
@ -160,12 +163,12 @@ static const char * const usage_opts_help[] = {
|
||||||
USAGE_COMMON_OPTS_HELP
|
USAGE_COMMON_OPTS_HELP
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool valid_header(char *p, off_t len)
|
static bool valid_header(char *p, size_t len)
|
||||||
{
|
{
|
||||||
if (len < sizeof(struct fdt_header) ||
|
if (len < sizeof(struct fdt_header) ||
|
||||||
fdt_magic(p) != FDT_MAGIC ||
|
fdt_magic(p) != FDT_MAGIC ||
|
||||||
fdt_version(p) > MAX_VERSION ||
|
fdt_version(p) > MAX_VERSION ||
|
||||||
fdt_last_comp_version(p) >= MAX_VERSION ||
|
fdt_last_comp_version(p) > MAX_VERSION ||
|
||||||
fdt_totalsize(p) >= len ||
|
fdt_totalsize(p) >= len ||
|
||||||
fdt_off_dt_struct(p) >= len ||
|
fdt_off_dt_struct(p) >= len ||
|
||||||
fdt_off_dt_strings(p) >= len)
|
fdt_off_dt_strings(p) >= len)
|
||||||
|
@ -181,8 +184,13 @@ int main(int argc, char *argv[])
|
||||||
char *buf;
|
char *buf;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
bool scan = false;
|
bool scan = false;
|
||||||
off_t len;
|
size_t len;
|
||||||
|
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"**** fdtdump is a low-level debugging tool, not meant for general use.\n"
|
||||||
|
"**** If you want to decompile a dtb, you probably want\n"
|
||||||
|
"**** dtc -I dtb -O dts <filename>\n\n"
|
||||||
|
);
|
||||||
while ((opt = util_getopt_long()) != EOF) {
|
while ((opt = util_getopt_long()) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case_USAGE_COMMON_FLAGS
|
case_USAGE_COMMON_FLAGS
|
||||||
|
@ -199,7 +207,7 @@ int main(int argc, char *argv[])
|
||||||
usage("missing input filename");
|
usage("missing input filename");
|
||||||
file = argv[optind];
|
file = argv[optind];
|
||||||
|
|
||||||
buf = utilfdt_read_len(file, &len);
|
buf = utilfdt_read(file, &len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
die("could not read: %s\n", file);
|
die("could not read: %s\n", file);
|
||||||
|
|
||||||
|
@ -209,7 +217,7 @@ int main(int argc, char *argv[])
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
char *endp = buf + len;
|
char *endp = buf + len;
|
||||||
|
|
||||||
fdt_set_magic(smagic, FDT_MAGIC);
|
fdt32_st(smagic, FDT_MAGIC);
|
||||||
|
|
||||||
/* poor man's memmem */
|
/* poor man's memmem */
|
||||||
while ((endp - p) >= FDT_MAGIC_SIZE) {
|
while ((endp - p) >= FDT_MAGIC_SIZE) {
|
||||||
|
@ -222,14 +230,14 @@ int main(int argc, char *argv[])
|
||||||
if (valid_header(p, this_len))
|
if (valid_header(p, this_len))
|
||||||
break;
|
break;
|
||||||
if (debug)
|
if (debug)
|
||||||
printf("%s: skipping fdt magic at offset %#zx\n",
|
printf("%s: skipping fdt magic at offset %#tx\n",
|
||||||
file, p - buf);
|
file, p - buf);
|
||||||
}
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (!p || endp - p < sizeof(struct fdt_header))
|
if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
|
||||||
die("%s: could not locate fdt magic\n", file);
|
die("%s: could not locate fdt magic\n", file);
|
||||||
printf("%s: found fdt at offset %#zx\n", file, p - buf);
|
printf("%s: found fdt at offset %#tx\n", file, p - buf);
|
||||||
buf = p;
|
buf = p;
|
||||||
} else if (!valid_header(buf, len))
|
} else if (!valid_header(buf, len))
|
||||||
die("%s: header is not valid\n", file);
|
die("%s: header is not valid\n", file);
|
||||||
|
|
84
fdtget.c
84
fdtget.c
|
@ -1,3 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -6,21 +7,6 @@
|
||||||
* Based on code written by:
|
* Based on code written by:
|
||||||
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
|
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
|
||||||
* Matthew McClintock <msm@freescale.com>
|
* Matthew McClintock <msm@freescale.com>
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
||||||
* MA 02111-1307 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -53,6 +39,43 @@ static void report_error(const char *where, int err)
|
||||||
fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
|
fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a list of cells in the requested format
|
||||||
|
*
|
||||||
|
* @param disp Display information / options
|
||||||
|
* @param data Data to display
|
||||||
|
* @param len Maximum length of buffer
|
||||||
|
* @param size Data size to use for display (e.g. 4 for 32-bit)
|
||||||
|
* @return 0 if ok, -1 on error
|
||||||
|
*/
|
||||||
|
static int show_cell_list(struct display_info *disp, const char *data, int len,
|
||||||
|
int size)
|
||||||
|
{
|
||||||
|
const uint8_t *p = (const uint8_t *)data;
|
||||||
|
char fmt[3];
|
||||||
|
int value;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fmt[0] = '%';
|
||||||
|
fmt[1] = disp->type ? disp->type : 'd';
|
||||||
|
fmt[2] = '\0';
|
||||||
|
for (i = 0; i < len; i += size, p += size) {
|
||||||
|
if (i)
|
||||||
|
printf(" ");
|
||||||
|
switch (size) {
|
||||||
|
case 4: value = fdt32_ld((const fdt32_t *)p); break;
|
||||||
|
case 2: value = fdt16_ld((const fdt16_t *)p); break;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
value = *p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(fmt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays data of a given length according to selected options
|
* Displays data of a given length according to selected options
|
||||||
*
|
*
|
||||||
|
@ -66,17 +89,19 @@ static void report_error(const char *where, int err)
|
||||||
*/
|
*/
|
||||||
static int show_data(struct display_info *disp, const char *data, int len)
|
static int show_data(struct display_info *disp, const char *data, int len)
|
||||||
{
|
{
|
||||||
int i, size;
|
int size;
|
||||||
const uint8_t *p = (const uint8_t *)data;
|
|
||||||
const char *s;
|
const char *s;
|
||||||
int value;
|
|
||||||
int is_string;
|
int is_string;
|
||||||
char fmt[3];
|
|
||||||
|
|
||||||
/* no data, don't print */
|
/* no data, don't print */
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (disp->type == 'r') {
|
||||||
|
fwrite(data, 1, len, stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
is_string = (disp->type) == 's' ||
|
is_string = (disp->type) == 's' ||
|
||||||
(!disp->type && util_is_printable_string(data, len));
|
(!disp->type && util_is_printable_string(data, len));
|
||||||
if (is_string) {
|
if (is_string) {
|
||||||
|
@ -99,17 +124,8 @@ static int show_data(struct display_info *disp, const char *data, int len)
|
||||||
"selected data size\n");
|
"selected data size\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fmt[0] = '%';
|
|
||||||
fmt[1] = disp->type ? disp->type : 'd';
|
return show_cell_list(disp, data, len, size);
|
||||||
fmt[2] = '\0';
|
|
||||||
for (i = 0; i < len; i += size, p += size) {
|
|
||||||
if (i)
|
|
||||||
printf(" ");
|
|
||||||
value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
|
|
||||||
size == 2 ? (*p << 8) | p[1] : *p;
|
|
||||||
printf(fmt, value);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,7 +137,6 @@ static int show_data(struct display_info *disp, const char *data, int len)
|
||||||
*/
|
*/
|
||||||
static int list_properties(const void *blob, int node)
|
static int list_properties(const void *blob, int node)
|
||||||
{
|
{
|
||||||
const struct fdt_property *data;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
int prop;
|
int prop;
|
||||||
|
|
||||||
|
@ -130,8 +145,7 @@ static int list_properties(const void *blob, int node)
|
||||||
/* Stop silently when there are no more properties */
|
/* Stop silently when there are no more properties */
|
||||||
if (prop < 0)
|
if (prop < 0)
|
||||||
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
|
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
|
||||||
data = fdt_get_property_by_offset(blob, prop, NULL);
|
fdt_getprop_by_offset(blob, prop, &name, NULL);
|
||||||
name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
|
|
||||||
if (name)
|
if (name)
|
||||||
puts(name);
|
puts(name);
|
||||||
prop = fdt_next_property_offset(blob, prop);
|
prop = fdt_next_property_offset(blob, prop);
|
||||||
|
@ -245,7 +259,7 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
|
||||||
* @param filename Filename of blob file
|
* @param filename Filename of blob file
|
||||||
* @param arg List of arguments to process
|
* @param arg List of arguments to process
|
||||||
* @param arg_count Number of arguments
|
* @param arg_count Number of arguments
|
||||||
* @param return 0 if ok, -ve on error
|
* @return 0 if ok, -ve on error
|
||||||
*/
|
*/
|
||||||
static int do_fdtget(struct display_info *disp, const char *filename,
|
static int do_fdtget(struct display_info *disp, const char *filename,
|
||||||
char **arg, int arg_count, int args_per_step)
|
char **arg, int arg_count, int args_per_step)
|
||||||
|
@ -254,7 +268,7 @@ static int do_fdtget(struct display_info *disp, const char *filename,
|
||||||
const char *prop;
|
const char *prop;
|
||||||
int i, node;
|
int i, node;
|
||||||
|
|
||||||
blob = utilfdt_read(filename);
|
blob = utilfdt_read(filename, NULL);
|
||||||
if (!blob)
|
if (!blob)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Pantelis Antoniou <pantelis.antoniou@konsulko.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BUF_INCREMENT 65536
|
||||||
|
|
||||||
|
/* Usage related data. */
|
||||||
|
static const char usage_synopsis[] =
|
||||||
|
"apply a number of overlays to a base blob\n"
|
||||||
|
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
|
||||||
|
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
|
||||||
|
static struct option const usage_long_opts[] = {
|
||||||
|
{"input", required_argument, NULL, 'i'},
|
||||||
|
{"output", required_argument, NULL, 'o'},
|
||||||
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
USAGE_COMMON_LONG_OPTS,
|
||||||
|
};
|
||||||
|
static const char * const usage_opts_help[] = {
|
||||||
|
"Input base DT blob",
|
||||||
|
"Output DT blob",
|
||||||
|
"Verbose messages",
|
||||||
|
USAGE_COMMON_OPTS_HELP
|
||||||
|
};
|
||||||
|
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
static void *apply_one(char *base, const char *overlay, size_t *buf_len,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
char *tmp = NULL;
|
||||||
|
char *tmpo;
|
||||||
|
int ret;
|
||||||
|
bool has_symbols;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We take copies first, because a failed apply can trash
|
||||||
|
* both the base blob and the overlay
|
||||||
|
*/
|
||||||
|
tmpo = xmalloc(fdt_totalsize(overlay));
|
||||||
|
|
||||||
|
do {
|
||||||
|
tmp = xrealloc(tmp, *buf_len);
|
||||||
|
ret = fdt_open_into(base, tmp, *buf_len);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nFailed to make temporary copy: %s\n",
|
||||||
|
fdt_strerror(ret));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ret = fdt_path_offset(tmp, "/__symbols__");
|
||||||
|
has_symbols = ret >= 0;
|
||||||
|
|
||||||
|
memcpy(tmpo, overlay, fdt_totalsize(overlay));
|
||||||
|
|
||||||
|
ret = fdt_overlay_apply(tmp, tmpo);
|
||||||
|
if (ret == -FDT_ERR_NOSPACE) {
|
||||||
|
*buf_len += BUF_INCREMENT;
|
||||||
|
}
|
||||||
|
} while (ret == -FDT_ERR_NOSPACE);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "\nFailed to apply '%s': %s\n",
|
||||||
|
name, fdt_strerror(ret));
|
||||||
|
if (!has_symbols) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"base blob does not have a '/__symbols__' node, "
|
||||||
|
"make sure you have compiled the base blob with '-@' option\n");
|
||||||
|
}
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(base);
|
||||||
|
free(tmpo);
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(tmpo);
|
||||||
|
if (tmp)
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static int do_fdtoverlay(const char *input_filename,
|
||||||
|
const char *output_filename,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *blob = NULL;
|
||||||
|
char **ovblob = NULL;
|
||||||
|
size_t buf_len;
|
||||||
|
int i, ret = -1;
|
||||||
|
|
||||||
|
blob = utilfdt_read(input_filename, &buf_len);
|
||||||
|
if (!blob) {
|
||||||
|
fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
if (fdt_totalsize(blob) > buf_len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
|
||||||
|
(unsigned long)buf_len, fdt_totalsize(blob));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate blob pointer array */
|
||||||
|
ovblob = xmalloc(sizeof(*ovblob) * argc);
|
||||||
|
memset(ovblob, 0, sizeof(*ovblob) * argc);
|
||||||
|
|
||||||
|
/* read and keep track of the overlay blobs */
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
size_t ov_len;
|
||||||
|
ovblob[i] = utilfdt_read(argv[i], &ov_len);
|
||||||
|
if (!ovblob[i]) {
|
||||||
|
fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
if (fdt_totalsize(ovblob[i]) > ov_len) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
|
||||||
|
argv[i], (unsigned long)ov_len,
|
||||||
|
fdt_totalsize(ovblob[i]));
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_len = fdt_totalsize(blob);
|
||||||
|
|
||||||
|
/* apply the overlays in sequence */
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
|
||||||
|
if (!blob)
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_pack(blob);
|
||||||
|
ret = utilfdt_write(output_filename, blob);
|
||||||
|
if (ret)
|
||||||
|
fprintf(stderr, "\nFailed to write '%s'\n",
|
||||||
|
output_filename);
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
if (ovblob) {
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
if (ovblob[i])
|
||||||
|
free(ovblob[i]);
|
||||||
|
}
|
||||||
|
free(ovblob);
|
||||||
|
}
|
||||||
|
free(blob);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int opt, i;
|
||||||
|
char *input_filename = NULL;
|
||||||
|
char *output_filename = NULL;
|
||||||
|
|
||||||
|
while ((opt = util_getopt_long()) != EOF) {
|
||||||
|
switch (opt) {
|
||||||
|
case_USAGE_COMMON_FLAGS
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
input_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
output_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!input_filename)
|
||||||
|
usage("missing input file");
|
||||||
|
|
||||||
|
if (!output_filename)
|
||||||
|
usage("missing output file");
|
||||||
|
|
||||||
|
argv += optind;
|
||||||
|
argc -= optind;
|
||||||
|
|
||||||
|
if (argc <= 0)
|
||||||
|
usage("missing overlay file(s)");
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
printf("input = %s\n", input_filename);
|
||||||
|
printf("output = %s\n", output_filename);
|
||||||
|
for (i = 0; i < argc; i++)
|
||||||
|
printf("overlay[%d] = %s\n", i, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_fdtoverlay(input_filename, output_filename, argc, argv))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
68
fdtput.c
68
fdtput.c
|
@ -1,20 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
||||||
* MA 02111-1307 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -23,6 +9,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
@ -67,7 +54,7 @@ static void report_error(const char *name, int namelen, int err)
|
||||||
* @param arg List of arguments from command line
|
* @param arg List of arguments from command line
|
||||||
* @param arg_count Number of arguments (may be 0)
|
* @param arg_count Number of arguments (may be 0)
|
||||||
* @param valuep Returns buffer containing value
|
* @param valuep Returns buffer containing value
|
||||||
* @param *value_len Returns length of value encoded
|
* @param value_len Returns length of value encoded
|
||||||
*/
|
*/
|
||||||
static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
char **valuep, int *value_len)
|
char **valuep, int *value_len)
|
||||||
|
@ -78,16 +65,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
int len; /* length of this cell/string/byte */
|
int len; /* length of this cell/string/byte */
|
||||||
int ival;
|
int ival;
|
||||||
int upto; /* the number of bytes we have written to buf */
|
int upto; /* the number of bytes we have written to buf */
|
||||||
char fmt[3];
|
|
||||||
|
|
||||||
upto = 0;
|
upto = 0;
|
||||||
|
|
||||||
if (disp->verbose)
|
if (disp->verbose)
|
||||||
fprintf(stderr, "Decoding value:\n");
|
fprintf(stderr, "Decoding value:\n");
|
||||||
|
|
||||||
fmt[0] = '%';
|
|
||||||
fmt[1] = disp->type ? disp->type : 'd';
|
|
||||||
fmt[2] = '\0';
|
|
||||||
for (; arg_count > 0; arg++, arg_count--, upto += len) {
|
for (; arg_count > 0; arg++, arg_count--, upto += len) {
|
||||||
/* assume integer unless told otherwise */
|
/* assume integer unless told otherwise */
|
||||||
if (disp->type == 's')
|
if (disp->type == 's')
|
||||||
|
@ -107,8 +90,35 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
if (disp->verbose)
|
if (disp->verbose)
|
||||||
fprintf(stderr, "\tstring: '%s'\n", ptr);
|
fprintf(stderr, "\tstring: '%s'\n", ptr);
|
||||||
} else {
|
} else {
|
||||||
int *iptr = (int *)ptr;
|
fdt32_t *iptr = (fdt32_t *)ptr;
|
||||||
sscanf(*arg, fmt, &ival);
|
char *endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
switch (disp->type) {
|
||||||
|
case 'x':
|
||||||
|
ival = strtoul(*arg, &endptr, 16);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
ival = strtoul(*arg, &endptr, 8);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
ival = strtol(*arg, &endptr, 0);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
ival = strtoul(*arg, &endptr, 0);
|
||||||
|
break;
|
||||||
|
default: /* 0 or 'd' */
|
||||||
|
ival = strtol(*arg, &endptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*endptr != '\0' || errno) {
|
||||||
|
if (disp->verbose) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldn't parse \"%s\" as an integer\n",
|
||||||
|
*arg);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (len == 4)
|
if (len == 4)
|
||||||
*iptr = cpu_to_fdt32(ival);
|
*iptr = cpu_to_fdt32(ival);
|
||||||
else
|
else
|
||||||
|
@ -130,7 +140,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
|
|
||||||
#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
|
#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
|
||||||
|
|
||||||
static char *_realloc_fdt(char *fdt, int delta)
|
static char *realloc_fdt(char *fdt, int delta)
|
||||||
{
|
{
|
||||||
int new_sz = fdt_totalsize(fdt) + delta;
|
int new_sz = fdt_totalsize(fdt) + delta;
|
||||||
fdt = xrealloc(fdt, new_sz);
|
fdt = xrealloc(fdt, new_sz);
|
||||||
|
@ -144,7 +154,7 @@ static char *realloc_node(char *fdt, const char *name)
|
||||||
/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
|
/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
|
||||||
delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
|
delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
|
||||||
+ FDT_TAGSIZE;
|
+ FDT_TAGSIZE;
|
||||||
return _realloc_fdt(fdt, delta);
|
return realloc_fdt(fdt, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *realloc_property(char *fdt, int nodeoffset,
|
static char *realloc_property(char *fdt, int nodeoffset,
|
||||||
|
@ -161,7 +171,7 @@ static char *realloc_property(char *fdt, int nodeoffset,
|
||||||
/* actual value in off_struct */
|
/* actual value in off_struct */
|
||||||
delta += ALIGN(newlen) - ALIGN(oldlen);
|
delta += ALIGN(newlen) - ALIGN(oldlen);
|
||||||
|
|
||||||
return _realloc_fdt(fdt, delta);
|
return realloc_fdt(fdt, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int store_key_value(char **blob, const char *node_name,
|
static int store_key_value(char **blob, const char *node_name,
|
||||||
|
@ -333,7 +343,7 @@ static int do_fdtput(struct display_info *disp, const char *filename,
|
||||||
char *node;
|
char *node;
|
||||||
int len, ret = 0;
|
int len, ret = 0;
|
||||||
|
|
||||||
blob = utilfdt_read(filename);
|
blob = utilfdt_read(filename, NULL);
|
||||||
if (!blob)
|
if (!blob)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -403,8 +413,8 @@ static struct option const usage_long_opts[] = {
|
||||||
USAGE_COMMON_LONG_OPTS,
|
USAGE_COMMON_LONG_OPTS,
|
||||||
};
|
};
|
||||||
static const char * const usage_opts_help[] = {
|
static const char * const usage_opts_help[] = {
|
||||||
"Create nodes if they don't already exist",
|
"Create nodes",
|
||||||
"Delete nodes (and any subnodes) if they already exist",
|
"Delete nodes (and any subnodes)",
|
||||||
"Delete properties if they already exist",
|
"Delete properties if they already exist",
|
||||||
"Automatically create nodes as needed for the node path",
|
"Automatically create nodes as needed for the node path",
|
||||||
"Type of data",
|
"Type of data",
|
||||||
|
@ -447,6 +457,8 @@ int main(int argc, char *argv[])
|
||||||
if (utilfdt_decode_type(optarg, &disp.type,
|
if (utilfdt_decode_type(optarg, &disp.type,
|
||||||
&disp.size))
|
&disp.size))
|
||||||
usage("Invalid type string");
|
usage("Invalid type string");
|
||||||
|
if (disp.type == 'r')
|
||||||
|
usage("Unsupported raw data type");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
|
|
123
flattree.c
123
flattree.c
|
@ -1,21 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
@ -49,7 +34,7 @@ static struct version_info {
|
||||||
|
|
||||||
struct emitter {
|
struct emitter {
|
||||||
void (*cell)(void *, cell_t);
|
void (*cell)(void *, cell_t);
|
||||||
void (*string)(void *, char *, int);
|
void (*string)(void *, const char *, int);
|
||||||
void (*align)(void *, int);
|
void (*align)(void *, int);
|
||||||
void (*data)(void *, struct data);
|
void (*data)(void *, struct data);
|
||||||
void (*beginnode)(void *, struct label *labels);
|
void (*beginnode)(void *, struct label *labels);
|
||||||
|
@ -64,7 +49,7 @@ static void bin_emit_cell(void *e, cell_t val)
|
||||||
*dtbuf = data_append_cell(*dtbuf, val);
|
*dtbuf = data_append_cell(*dtbuf, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_string(void *e, char *str, int len)
|
static void bin_emit_string(void *e, const char *str, int len)
|
||||||
{
|
{
|
||||||
struct data *dtbuf = e;
|
struct data *dtbuf = e;
|
||||||
|
|
||||||
|
@ -139,27 +124,20 @@ static void asm_emit_cell(void *e, cell_t val)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
|
fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
|
||||||
|
"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
|
||||||
(val >> 24) & 0xff, (val >> 16) & 0xff,
|
(val >> 24) & 0xff, (val >> 16) & 0xff,
|
||||||
(val >> 8) & 0xff, val & 0xff);
|
(val >> 8) & 0xff, val & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_string(void *e, char *str, int len)
|
static void asm_emit_string(void *e, const char *str, int len)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
char c = 0;
|
|
||||||
|
|
||||||
if (len != 0) {
|
if (len != 0)
|
||||||
/* XXX: ewww */
|
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
|
||||||
c = str[len];
|
else
|
||||||
str[len] = '\0';
|
fprintf(f, "\t.asciz\t\"%s\"\n", str);
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(f, "\t.string\t\"%s\"\n", str);
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
str[len] = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_align(void *e, int a)
|
static void asm_emit_align(void *e, int a)
|
||||||
|
@ -172,14 +150,14 @@ static void asm_emit_align(void *e, int a)
|
||||||
static void asm_emit_data(void *e, struct data d)
|
static void asm_emit_data(void *e, struct data d)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
int off = 0;
|
unsigned int off = 0;
|
||||||
struct marker *m = d.markers;
|
struct marker *m = d.markers;
|
||||||
|
|
||||||
for_each_marker_of_type(m, LABEL)
|
for_each_marker_of_type(m, LABEL)
|
||||||
emit_offset_label(f, m->ref, m->offset);
|
emit_offset_label(f, m->ref, m->offset);
|
||||||
|
|
||||||
while ((d.len - off) >= sizeof(uint32_t)) {
|
while ((d.len - off) >= sizeof(uint32_t)) {
|
||||||
asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));
|
asm_emit_cell(e, dtb_ld32(d.val + off));
|
||||||
off += sizeof(uint32_t);
|
off += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +220,7 @@ static struct emitter asm_emitter = {
|
||||||
|
|
||||||
static int stringtable_insert(struct data *d, const char *str)
|
static int stringtable_insert(struct data *d, const char *str)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* FIXME: do this more efficiently? */
|
/* FIXME: do this more efficiently? */
|
||||||
|
|
||||||
|
@ -318,17 +296,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
||||||
{
|
{
|
||||||
struct reserve_info *re;
|
struct reserve_info *re;
|
||||||
struct data d = empty_data;
|
struct data d = empty_data;
|
||||||
static struct fdt_reserve_entry null_re = {0,0};
|
unsigned int j;
|
||||||
int j;
|
|
||||||
|
|
||||||
for (re = reservelist; re; re = re->next) {
|
for (re = reservelist; re; re = re->next) {
|
||||||
d = data_append_re(d, &re->re);
|
d = data_append_re(d, re->address, re->size);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Add additional reserved slots if the user asked for them.
|
* Add additional reserved slots if the user asked for them.
|
||||||
*/
|
*/
|
||||||
for (j = 0; j < reservenum; j++) {
|
for (j = 0; j < reservenum; j++) {
|
||||||
d = data_append_re(d, &null_re);
|
d = data_append_re(d, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
|
@ -369,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
|
||||||
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
|
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
int i;
|
unsigned int i;
|
||||||
struct data blob = empty_data;
|
struct data blob = empty_data;
|
||||||
struct data reservebuf = empty_data;
|
struct data reservebuf = empty_data;
|
||||||
struct data dtbuf = empty_data;
|
struct data dtbuf = empty_data;
|
||||||
|
@ -402,7 +379,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
|
||||||
padlen = 0;
|
padlen = 0;
|
||||||
if (quiet < 1)
|
if (quiet < 1)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Warning: blob size %d >= minimum size %d\n",
|
"Warning: blob size %"PRIu32" >= minimum size %d\n",
|
||||||
fdt32_to_cpu(fdt.totalsize), minsize);
|
fdt32_to_cpu(fdt.totalsize), minsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
|
|
||||||
while (p < (strbuf.val + strbuf.len)) {
|
while (p < (strbuf.val + strbuf.len)) {
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
fprintf(f, "\t.string \"%s\"\n", p);
|
fprintf(f, "\t.asciz \"%s\"\n", p);
|
||||||
p += len+1;
|
p += len+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +447,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
int i;
|
unsigned int i;
|
||||||
struct data strbuf = empty_data;
|
struct data strbuf = empty_data;
|
||||||
struct reserve_info *re;
|
struct reserve_info *re;
|
||||||
const char *symprefix = "dt";
|
const char *symprefix = "dt";
|
||||||
|
@ -526,7 +503,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
* Reserve map entries.
|
* Reserve map entries.
|
||||||
* Align the reserve map to a doubleword boundary.
|
* Align the reserve map to a doubleword boundary.
|
||||||
* Each entry is an (address, size) pair of u64 values.
|
* Each entry is an (address, size) pair of u64 values.
|
||||||
* Always supply a zero-sized temination entry.
|
* Always supply a zero-sized termination entry.
|
||||||
*/
|
*/
|
||||||
asm_emit_align(f, 8);
|
asm_emit_align(f, 8);
|
||||||
emit_label(f, symprefix, "reserve_map");
|
emit_label(f, symprefix, "reserve_map");
|
||||||
|
@ -534,7 +511,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
fprintf(f, "/* Memory reserve map from source file */\n");
|
fprintf(f, "/* Memory reserve map from source file */\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use .long on high and low halfs of u64s to avoid .quad
|
* Use .long on high and low halves of u64s to avoid .quad
|
||||||
* as it appears .quad isn't available in some assemblers.
|
* as it appears .quad isn't available in some assemblers.
|
||||||
*/
|
*/
|
||||||
for (re = dti->reservelist; re; re = re->next) {
|
for (re = dti->reservelist; re; re = re->next) {
|
||||||
|
@ -544,11 +521,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
fprintf(f, "\t.globl\t%s\n", l->label);
|
fprintf(f, "\t.globl\t%s\n", l->label);
|
||||||
fprintf(f, "%s:\n", l->label);
|
fprintf(f, "%s:\n", l->label);
|
||||||
}
|
}
|
||||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
|
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
|
||||||
ASM_EMIT_BELONG(f, "0x%08x",
|
ASM_EMIT_BELONG(f, "0x%08x",
|
||||||
(unsigned int)(re->re.address & 0xffffffff));
|
(unsigned int)(re->address & 0xffffffff));
|
||||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
|
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
|
||||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
|
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
|
||||||
}
|
}
|
||||||
for (i = 0; i < reservenum; i++) {
|
for (i = 0; i < reservenum; i++) {
|
||||||
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
|
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
|
||||||
|
@ -609,7 +586,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
|
||||||
|
|
||||||
static uint32_t flat_read_word(struct inbuf *inb)
|
static uint32_t flat_read_word(struct inbuf *inb)
|
||||||
{
|
{
|
||||||
uint32_t val;
|
fdt32_t val;
|
||||||
|
|
||||||
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
|
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
|
||||||
|
|
||||||
|
@ -627,11 +604,11 @@ static void flat_realign(struct inbuf *inb, int align)
|
||||||
die("Premature end of data parsing flat device tree\n");
|
die("Premature end of data parsing flat device tree\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *flat_read_string(struct inbuf *inb)
|
static const char *flat_read_string(struct inbuf *inb)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
const char *p = inb->ptr;
|
const char *p = inb->ptr;
|
||||||
char *str;
|
const char *str;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (p >= inb->limit)
|
if (p >= inb->limit)
|
||||||
|
@ -639,7 +616,7 @@ static char *flat_read_string(struct inbuf *inb)
|
||||||
len++;
|
len++;
|
||||||
} while ((*p++) != '\0');
|
} while ((*p++) != '\0');
|
||||||
|
|
||||||
str = xstrdup(inb->ptr);
|
str = inb->ptr;
|
||||||
|
|
||||||
inb->ptr += len;
|
inb->ptr += len;
|
||||||
|
|
||||||
|
@ -701,7 +678,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
|
||||||
|
|
||||||
val = flat_read_data(dtbuf, proplen);
|
val = flat_read_data(dtbuf, proplen);
|
||||||
|
|
||||||
return build_property(name, val);
|
return build_property(name, val, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -718,13 +695,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||||
* First pass, count entries.
|
* First pass, count entries.
|
||||||
*/
|
*/
|
||||||
while (1) {
|
while (1) {
|
||||||
|
uint64_t address, size;
|
||||||
|
|
||||||
flat_read_chunk(inb, &re, sizeof(re));
|
flat_read_chunk(inb, &re, sizeof(re));
|
||||||
re.address = fdt64_to_cpu(re.address);
|
address = fdt64_to_cpu(re.address);
|
||||||
re.size = fdt64_to_cpu(re.size);
|
size = fdt64_to_cpu(re.size);
|
||||||
if (re.size == 0)
|
if (size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
new = build_reserve_entry(re.address, re.size);
|
new = build_reserve_entry(address, size);
|
||||||
reservelist = add_reserve_entry(reservelist, new);
|
reservelist = add_reserve_entry(reservelist, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,13 +711,13 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *nodename_from_path(const char *ppath, const char *cpath)
|
static const char *nodename_from_path(const char *ppath, const char *cpath)
|
||||||
{
|
{
|
||||||
int plen;
|
int plen;
|
||||||
|
|
||||||
plen = strlen(ppath);
|
plen = strlen(ppath);
|
||||||
|
|
||||||
if (!strneq(ppath, cpath, plen))
|
if (!strstarts(cpath, ppath))
|
||||||
die("Path \"%s\" is not valid as a child of \"%s\"\n",
|
die("Path \"%s\" is not valid as a child of \"%s\"\n",
|
||||||
cpath, ppath);
|
cpath, ppath);
|
||||||
|
|
||||||
|
@ -746,7 +725,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
|
||||||
if (!streq(ppath, "/"))
|
if (!streq(ppath, "/"))
|
||||||
plen++;
|
plen++;
|
||||||
|
|
||||||
return xstrdup(cpath + plen);
|
return cpath + plen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct node *unflatten_tree(struct inbuf *dtbuf,
|
static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
|
@ -754,17 +733,18 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
const char *parent_flatname, int flags)
|
const char *parent_flatname, int flags)
|
||||||
{
|
{
|
||||||
struct node *node;
|
struct node *node;
|
||||||
char *flatname;
|
const char *flatname;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
node = build_node(NULL, NULL);
|
node = build_node(NULL, NULL, NULL);
|
||||||
|
|
||||||
flatname = flat_read_string(dtbuf);
|
flatname = flat_read_string(dtbuf);
|
||||||
|
|
||||||
if (flags & FTF_FULLPATH)
|
if (flags & FTF_FULLPATH)
|
||||||
node->name = nodename_from_path(parent_flatname, flatname);
|
node->name = xstrdup(nodename_from_path(parent_flatname,
|
||||||
|
flatname));
|
||||||
else
|
else
|
||||||
node->name = flatname;
|
node->name = xstrdup(flatname);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
@ -806,10 +786,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
}
|
}
|
||||||
} while (val != FDT_END_NODE);
|
} while (val != FDT_END_NODE);
|
||||||
|
|
||||||
if (node->name != flatname) {
|
|
||||||
free(flatname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,6 +793,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
struct dt_info *dt_from_blob(const char *fname)
|
struct dt_info *dt_from_blob(const char *fname)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
fdt32_t magic_buf, totalsize_buf;
|
||||||
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
|
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
|
||||||
uint32_t off_dt, off_str, off_mem_rsvmap;
|
uint32_t off_dt, off_str, off_mem_rsvmap;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -833,7 +810,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||||
|
|
||||||
f = srcfile_relative_open(fname, NULL);
|
f = srcfile_relative_open(fname, NULL);
|
||||||
|
|
||||||
rc = fread(&magic, sizeof(magic), 1, f);
|
rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
|
||||||
if (ferror(f))
|
if (ferror(f))
|
||||||
die("Error reading DT blob magic number: %s\n",
|
die("Error reading DT blob magic number: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -844,11 +821,11 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||||
die("Mysterious short read reading magic number\n");
|
die("Mysterious short read reading magic number\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
magic = fdt32_to_cpu(magic);
|
magic = fdt32_to_cpu(magic_buf);
|
||||||
if (magic != FDT_MAGIC)
|
if (magic != FDT_MAGIC)
|
||||||
die("Blob has incorrect magic number\n");
|
die("Blob has incorrect magic number\n");
|
||||||
|
|
||||||
rc = fread(&totalsize, sizeof(totalsize), 1, f);
|
rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
|
||||||
if (ferror(f))
|
if (ferror(f))
|
||||||
die("Error reading DT blob size: %s\n", strerror(errno));
|
die("Error reading DT blob size: %s\n", strerror(errno));
|
||||||
if (rc < 1) {
|
if (rc < 1) {
|
||||||
|
@ -858,7 +835,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||||
die("Mysterious short read reading blob size\n");
|
die("Mysterious short read reading blob size\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
totalsize = fdt32_to_cpu(totalsize);
|
totalsize = fdt32_to_cpu(totalsize_buf);
|
||||||
if (totalsize < FDT_V1_SIZE)
|
if (totalsize < FDT_V1_SIZE)
|
||||||
die("DT blob size (%d) is too small\n", totalsize);
|
die("DT blob size (%d) is too small\n", totalsize);
|
||||||
|
|
||||||
|
|
26
fstree.c
26
fstree.c
|
@ -1,21 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
@ -34,7 +19,7 @@ static struct node *read_fstree(const char *dirname)
|
||||||
if (!d)
|
if (!d)
|
||||||
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
|
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
|
||||||
|
|
||||||
tree = build_node(NULL, NULL);
|
tree = build_node(NULL, NULL, NULL);
|
||||||
|
|
||||||
while ((de = readdir(d)) != NULL) {
|
while ((de = readdir(d)) != NULL) {
|
||||||
char *tmpname;
|
char *tmpname;
|
||||||
|
@ -45,7 +30,7 @@ static struct node *read_fstree(const char *dirname)
|
||||||
|
|
||||||
tmpname = join_path(dirname, de->d_name);
|
tmpname = join_path(dirname, de->d_name);
|
||||||
|
|
||||||
if (lstat(tmpname, &st) < 0)
|
if (stat(tmpname, &st) < 0)
|
||||||
die("stat(%s): %s\n", tmpname, strerror(errno));
|
die("stat(%s): %s\n", tmpname, strerror(errno));
|
||||||
|
|
||||||
if (S_ISREG(st.st_mode)) {
|
if (S_ISREG(st.st_mode)) {
|
||||||
|
@ -58,9 +43,10 @@ static struct node *read_fstree(const char *dirname)
|
||||||
"WARNING: Cannot open %s: %s\n",
|
"WARNING: Cannot open %s: %s\n",
|
||||||
tmpname, strerror(errno));
|
tmpname, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
prop = build_property(xstrdup(de->d_name),
|
prop = build_property(de->d_name,
|
||||||
data_copy_file(pfile,
|
data_copy_file(pfile,
|
||||||
st.st_size));
|
st.st_size),
|
||||||
|
NULL);
|
||||||
add_property(tree, prop);
|
add_property(tree, prop);
|
||||||
fclose(pfile);
|
fclose(pfile);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
libfdt.so.1
|
|
@ -1,11 +1,22 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
# Makefile.libfdt
|
# Makefile.libfdt
|
||||||
#
|
#
|
||||||
# This is not a complete Makefile of itself. Instead, it is designed to
|
# This is not a complete Makefile of itself. Instead, it is designed to
|
||||||
# be easily embeddable into other systems of Makefiles.
|
# be easily embeddable into other systems of Makefiles.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
LIBFDT_so = libfdt.$(SHAREDLIB_EXT)
|
||||||
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
|
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
|
||||||
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
|
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
|
||||||
LIBFDT_VERSION = version.lds
|
LIBFDT_VERSION = version.lds
|
||||||
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
|
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
|
||||||
fdt_addresses.c fdt_overlay.c
|
fdt_addresses.c fdt_overlay.c fdt_check.c
|
||||||
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
|
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
|
||||||
|
LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION)
|
||||||
|
|
||||||
|
libfdt_clean:
|
||||||
|
@$(VECHO) CLEAN "(libfdt)"
|
||||||
|
rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
|
||||||
|
rm -f $(LIBFDT_dir)/$(LIBFDT_so)
|
||||||
|
rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
|
||||||
|
rm -f $(LIBFDT_dir)/$(LIBFDT_LIB)
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
- Tree traversal functions
|
- Tree traversal functions
|
||||||
- Graft function
|
- Graft function
|
||||||
- Complete libfdt.h documenting comments
|
|
||||||
|
|
234
libfdt/fdt.c
234
libfdt/fdt.c
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -55,52 +10,165 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
int fdt_check_header(const void *fdt)
|
/*
|
||||||
|
* Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
|
||||||
|
* that the given buffer contains what appears to be a flattened
|
||||||
|
* device tree with sane information in its header.
|
||||||
|
*/
|
||||||
|
int32_t fdt_ro_probe_(const void *fdt)
|
||||||
{
|
{
|
||||||
|
uint32_t totalsize = fdt_totalsize(fdt);
|
||||||
|
|
||||||
|
if (can_assume(VALID_DTB))
|
||||||
|
return totalsize;
|
||||||
|
|
||||||
|
/* The device tree must be at an 8-byte aligned address */
|
||||||
|
if ((uintptr_t)fdt & 7)
|
||||||
|
return -FDT_ERR_ALIGNMENT;
|
||||||
|
|
||||||
if (fdt_magic(fdt) == FDT_MAGIC) {
|
if (fdt_magic(fdt) == FDT_MAGIC) {
|
||||||
/* Complete tree */
|
/* Complete tree */
|
||||||
|
if (!can_assume(LATEST)) {
|
||||||
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|
||||||
return -FDT_ERR_BADVERSION;
|
return -FDT_ERR_BADVERSION;
|
||||||
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
|
if (fdt_last_comp_version(fdt) >
|
||||||
|
FDT_LAST_SUPPORTED_VERSION)
|
||||||
return -FDT_ERR_BADVERSION;
|
return -FDT_ERR_BADVERSION;
|
||||||
|
}
|
||||||
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
|
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
|
||||||
/* Unfinished sequential-write blob */
|
/* Unfinished sequential-write blob */
|
||||||
if (fdt_size_dt_struct(fdt) == 0)
|
if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
|
||||||
return -FDT_ERR_BADSTATE;
|
return -FDT_ERR_BADSTATE;
|
||||||
} else {
|
} else {
|
||||||
return -FDT_ERR_BADMAGIC;
|
return -FDT_ERR_BADMAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (totalsize < INT32_MAX)
|
||||||
|
return totalsize;
|
||||||
|
else
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
|
||||||
|
{
|
||||||
|
return (off >= hdrsize) && (off <= totalsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_block_(uint32_t hdrsize, uint32_t totalsize,
|
||||||
|
uint32_t base, uint32_t size)
|
||||||
|
{
|
||||||
|
if (!check_off_(hdrsize, totalsize, base))
|
||||||
|
return 0; /* block start out of bounds */
|
||||||
|
if ((base + size) < base)
|
||||||
|
return 0; /* overflow */
|
||||||
|
if (!check_off_(hdrsize, totalsize, base + size))
|
||||||
|
return 0; /* block end out of bounds */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fdt_header_size_(uint32_t version)
|
||||||
|
{
|
||||||
|
if (version <= 1)
|
||||||
|
return FDT_V1_SIZE;
|
||||||
|
else if (version <= 2)
|
||||||
|
return FDT_V2_SIZE;
|
||||||
|
else if (version <= 3)
|
||||||
|
return FDT_V3_SIZE;
|
||||||
|
else if (version <= 16)
|
||||||
|
return FDT_V16_SIZE;
|
||||||
|
else
|
||||||
|
return FDT_V17_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fdt_header_size(const void *fdt)
|
||||||
|
{
|
||||||
|
return can_assume(LATEST) ? FDT_V17_SIZE :
|
||||||
|
fdt_header_size_(fdt_version(fdt));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_check_header(const void *fdt)
|
||||||
|
{
|
||||||
|
size_t hdrsize;
|
||||||
|
|
||||||
|
/* The device tree must be at an 8-byte aligned address */
|
||||||
|
if ((uintptr_t)fdt & 7)
|
||||||
|
return -FDT_ERR_ALIGNMENT;
|
||||||
|
|
||||||
|
if (fdt_magic(fdt) != FDT_MAGIC)
|
||||||
|
return -FDT_ERR_BADMAGIC;
|
||||||
|
if (!can_assume(LATEST)) {
|
||||||
|
if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|
||||||
|
|| (fdt_last_comp_version(fdt) >
|
||||||
|
FDT_LAST_SUPPORTED_VERSION))
|
||||||
|
return -FDT_ERR_BADVERSION;
|
||||||
|
if (fdt_version(fdt) < fdt_last_comp_version(fdt))
|
||||||
|
return -FDT_ERR_BADVERSION;
|
||||||
|
}
|
||||||
|
hdrsize = fdt_header_size(fdt);
|
||||||
|
if (!can_assume(VALID_DTB)) {
|
||||||
|
if ((fdt_totalsize(fdt) < hdrsize)
|
||||||
|
|| (fdt_totalsize(fdt) > INT_MAX))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
|
||||||
|
/* Bounds check memrsv block */
|
||||||
|
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
||||||
|
fdt_off_mem_rsvmap(fdt)))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
|
||||||
|
/* Bounds check structure block */
|
||||||
|
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
|
||||||
|
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
||||||
|
fdt_off_dt_struct(fdt)))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
} else {
|
||||||
|
if (!check_block_(hdrsize, fdt_totalsize(fdt),
|
||||||
|
fdt_off_dt_struct(fdt),
|
||||||
|
fdt_size_dt_struct(fdt)))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bounds check strings block */
|
||||||
|
if (!check_block_(hdrsize, fdt_totalsize(fdt),
|
||||||
|
fdt_off_dt_strings(fdt),
|
||||||
|
fdt_size_dt_strings(fdt)))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
|
unsigned int uoffset = offset;
|
||||||
|
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
|
||||||
|
|
||||||
if ((absoffset < offset)
|
if (offset < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT))
|
||||||
|
if ((absoffset < uoffset)
|
||||||
|| ((absoffset + len) < absoffset)
|
|| ((absoffset + len) < absoffset)
|
||||||
|| (absoffset + len) > fdt_totalsize(fdt))
|
|| (absoffset + len) > fdt_totalsize(fdt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (fdt_version(fdt) >= 0x11)
|
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
|
||||||
if (((offset + len) < offset)
|
if (((uoffset + len) < uoffset)
|
||||||
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return _fdt_offset_ptr(fdt, offset);
|
return fdt_offset_ptr_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
{
|
{
|
||||||
const fdt32_t *tagp, *lenp;
|
const fdt32_t *tagp, *lenp;
|
||||||
uint32_t tag;
|
uint32_t tag, len, sum;
|
||||||
int offset = startoffset;
|
int offset = startoffset;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
*nextoffset = -FDT_ERR_TRUNCATED;
|
*nextoffset = -FDT_ERR_TRUNCATED;
|
||||||
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
|
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
|
||||||
if (!tagp)
|
if (!can_assume(VALID_DTB) && !tagp)
|
||||||
return FDT_END; /* premature end */
|
return FDT_END; /* premature end */
|
||||||
tag = fdt32_to_cpu(*tagp);
|
tag = fdt32_to_cpu(*tagp);
|
||||||
offset += FDT_TAGSIZE;
|
offset += FDT_TAGSIZE;
|
||||||
|
@ -112,17 +180,28 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
do {
|
do {
|
||||||
p = fdt_offset_ptr(fdt, offset++, 1);
|
p = fdt_offset_ptr(fdt, offset++, 1);
|
||||||
} while (p && (*p != '\0'));
|
} while (p && (*p != '\0'));
|
||||||
if (!p)
|
if (!can_assume(VALID_DTB) && !p)
|
||||||
return FDT_END; /* premature end */
|
return FDT_END; /* premature end */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FDT_PROP:
|
case FDT_PROP:
|
||||||
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
|
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
|
||||||
if (!lenp)
|
if (!can_assume(VALID_DTB) && !lenp)
|
||||||
return FDT_END; /* premature end */
|
return FDT_END; /* premature end */
|
||||||
|
|
||||||
|
len = fdt32_to_cpu(*lenp);
|
||||||
|
sum = len + offset;
|
||||||
|
if (!can_assume(VALID_DTB) &&
|
||||||
|
(INT_MAX <= sum || sum < (uint32_t) offset))
|
||||||
|
return FDT_END; /* premature end */
|
||||||
|
|
||||||
/* skip-name offset, length and value */
|
/* skip-name offset, length and value */
|
||||||
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
|
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
|
||||||
+ fdt32_to_cpu(*lenp);
|
|
||||||
|
if (!can_assume(LATEST) &&
|
||||||
|
fdt_version(fdt) < 0x10 && len >= 8 &&
|
||||||
|
((offset - len) % 8) != 0)
|
||||||
|
offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FDT_END:
|
case FDT_END:
|
||||||
|
@ -141,19 +220,25 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_node_offset(const void *fdt, int offset)
|
int fdt_check_node_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
if (!can_assume(VALID_INPUT)
|
||||||
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
|
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
|
||||||
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
|
if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_prop_offset(const void *fdt, int offset)
|
int fdt_check_prop_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
if (!can_assume(VALID_INPUT)
|
||||||
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
|
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
|
||||||
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
|
if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -165,7 +250,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
|
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
|
if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -227,23 +312,26 @@ int fdt_next_subnode(const void *fdt, int offset)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
|
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
|
||||||
|
int slen)
|
||||||
{
|
{
|
||||||
int len = strlen(s) + 1;
|
const char *last = strtab + tabsize - (slen + 1);
|
||||||
const char *last = strtab + tabsize - len;
|
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = strtab; p <= last; p++)
|
for (p = strtab; p <= last; p++)
|
||||||
if (memcmp(p, s, len) == 0)
|
if (memcmp(p, s, slen) == 0 && p[slen] == '\0')
|
||||||
return p;
|
return p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_move(const void *fdt, void *buf, int bufsize)
|
int fdt_move(const void *fdt, void *buf, int bufsize)
|
||||||
{
|
{
|
||||||
FDT_CHECK_HEADER(fdt);
|
if (!can_assume(VALID_INPUT) && bufsize < 0)
|
||||||
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
if (fdt_totalsize(fdt) > bufsize)
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
|
if (fdt_totalsize(fdt) > (unsigned int)bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
memmove(buf, fdt, fdt_totalsize(fdt));
|
memmove(buf, fdt, fdt_totalsize(fdt));
|
||||||
|
|
61
libfdt/fdt.h
61
libfdt/fdt.h
|
@ -1,58 +1,13 @@
|
||||||
#ifndef _FDT_H
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
||||||
#define _FDT_H
|
#ifndef FDT_H
|
||||||
|
#define FDT_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
struct fdt_header {
|
struct fdt_header {
|
||||||
fdt32_t magic; /* magic word FDT_MAGIC */
|
fdt32_t magic; /* magic word FDT_MAGIC */
|
||||||
|
@ -80,17 +35,17 @@ struct fdt_reserve_entry {
|
||||||
|
|
||||||
struct fdt_node_header {
|
struct fdt_node_header {
|
||||||
fdt32_t tag;
|
fdt32_t tag;
|
||||||
char name[0];
|
char name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fdt_property {
|
struct fdt_property {
|
||||||
fdt32_t tag;
|
fdt32_t tag;
|
||||||
fdt32_t len;
|
fdt32_t len;
|
||||||
fdt32_t nameoff;
|
fdt32_t nameoff;
|
||||||
char data[0];
|
char data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY */
|
#endif /* !__ASSEMBLER__ */
|
||||||
|
|
||||||
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
||||||
#define FDT_TAGSIZE sizeof(fdt32_t)
|
#define FDT_TAGSIZE sizeof(fdt32_t)
|
||||||
|
@ -108,4 +63,4 @@ struct fdt_property {
|
||||||
#define FDT_V16_SIZE FDT_V3_SIZE
|
#define FDT_V16_SIZE FDT_V3_SIZE
|
||||||
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
||||||
|
|
||||||
#endif /* _FDT_H */
|
#endif /* FDT_H */
|
||||||
|
|
|
@ -1,52 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
|
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
|
||||||
*
|
* Copyright (C) 2018 embedded brains GmbH
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -55,42 +11,91 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
int fdt_address_cells(const void *fdt, int nodeoffset)
|
static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
|
||||||
{
|
{
|
||||||
const fdt32_t *ac;
|
const fdt32_t *c;
|
||||||
int val;
|
uint32_t val;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
|
c = fdt_getprop(fdt, nodeoffset, name, &len);
|
||||||
if (!ac)
|
if (!c)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
if (len != sizeof(*c))
|
||||||
|
return -FDT_ERR_BADNCELLS;
|
||||||
|
|
||||||
|
val = fdt32_to_cpu(*c);
|
||||||
|
if (val > FDT_MAX_NCELLS)
|
||||||
|
return -FDT_ERR_BADNCELLS;
|
||||||
|
|
||||||
|
return (int)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_address_cells(const void *fdt, int nodeoffset)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
val = fdt_cells(fdt, nodeoffset, "#address-cells");
|
||||||
|
if (val == 0)
|
||||||
|
return -FDT_ERR_BADNCELLS;
|
||||||
|
if (val == -FDT_ERR_NOTFOUND)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (len != sizeof(*ac))
|
|
||||||
return -FDT_ERR_BADNCELLS;
|
|
||||||
|
|
||||||
val = fdt32_to_cpu(*ac);
|
|
||||||
if ((val <= 0) || (val > FDT_MAX_NCELLS))
|
|
||||||
return -FDT_ERR_BADNCELLS;
|
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_size_cells(const void *fdt, int nodeoffset)
|
int fdt_size_cells(const void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
const fdt32_t *sc;
|
|
||||||
int val;
|
int val;
|
||||||
int len;
|
|
||||||
|
|
||||||
sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
|
|
||||||
if (!sc)
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
if (len != sizeof(*sc))
|
|
||||||
return -FDT_ERR_BADNCELLS;
|
|
||||||
|
|
||||||
val = fdt32_to_cpu(*sc);
|
|
||||||
if ((val < 0) || (val > FDT_MAX_NCELLS))
|
|
||||||
return -FDT_ERR_BADNCELLS;
|
|
||||||
|
|
||||||
|
val = fdt_cells(fdt, nodeoffset, "#size-cells");
|
||||||
|
if (val == -FDT_ERR_NOTFOUND)
|
||||||
|
return 1;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function assumes that [address|size]_cells is 1 or 2 */
|
||||||
|
int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
|
||||||
|
const char *name, uint64_t addr, uint64_t size)
|
||||||
|
{
|
||||||
|
int addr_cells, size_cells, ret;
|
||||||
|
uint8_t data[sizeof(fdt64_t) * 2], *prop;
|
||||||
|
|
||||||
|
ret = fdt_address_cells(fdt, parent);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
addr_cells = ret;
|
||||||
|
|
||||||
|
ret = fdt_size_cells(fdt, parent);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
size_cells = ret;
|
||||||
|
|
||||||
|
/* check validity of address */
|
||||||
|
prop = data;
|
||||||
|
if (addr_cells == 1) {
|
||||||
|
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
|
||||||
|
return -FDT_ERR_BADVALUE;
|
||||||
|
|
||||||
|
fdt32_st(prop, (uint32_t)addr);
|
||||||
|
} else if (addr_cells == 2) {
|
||||||
|
fdt64_st(prop, addr);
|
||||||
|
} else {
|
||||||
|
return -FDT_ERR_BADNCELLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check validity of size */
|
||||||
|
prop += addr_cells * sizeof(fdt32_t);
|
||||||
|
if (size_cells == 1) {
|
||||||
|
if (size > UINT32_MAX)
|
||||||
|
return -FDT_ERR_BADVALUE;
|
||||||
|
|
||||||
|
fdt32_st(prop, (uint32_t)size);
|
||||||
|
} else if (size_cells == 2) {
|
||||||
|
fdt64_st(prop, size);
|
||||||
|
} else {
|
||||||
|
return -FDT_ERR_BADNCELLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdt_appendprop(fdt, nodeoffset, name, data,
|
||||||
|
(addr_cells + size_cells) * sizeof(fdt32_t));
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
|
*/
|
||||||
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
#include <fdt.h>
|
||||||
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
|
int fdt_check_full(const void *fdt, size_t bufsize)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
int num_memrsv;
|
||||||
|
int offset, nextoffset = 0;
|
||||||
|
uint32_t tag;
|
||||||
|
unsigned int depth = 0;
|
||||||
|
const void *prop;
|
||||||
|
const char *propname;
|
||||||
|
bool expect_end = false;
|
||||||
|
|
||||||
|
if (bufsize < FDT_V1_SIZE)
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
if (bufsize < fdt_header_size(fdt))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
err = fdt_check_header(fdt);
|
||||||
|
if (err != 0)
|
||||||
|
return err;
|
||||||
|
if (bufsize < fdt_totalsize(fdt))
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
|
||||||
|
num_memrsv = fdt_num_mem_rsv(fdt);
|
||||||
|
if (num_memrsv < 0)
|
||||||
|
return num_memrsv;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
offset = nextoffset;
|
||||||
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
||||||
|
|
||||||
|
if (nextoffset < 0)
|
||||||
|
return nextoffset;
|
||||||
|
|
||||||
|
/* If we see two root nodes, something is wrong */
|
||||||
|
if (expect_end && tag != FDT_END)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
|
||||||
|
switch (tag) {
|
||||||
|
case FDT_NOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_END:
|
||||||
|
if (depth != 0)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case FDT_BEGIN_NODE:
|
||||||
|
depth++;
|
||||||
|
if (depth > INT_MAX)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
|
||||||
|
/* The root node must have an empty name */
|
||||||
|
if (depth == 1) {
|
||||||
|
const char *name;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
name = fdt_get_name(fdt, offset, &len);
|
||||||
|
if (!name)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
if (*name || len)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_END_NODE:
|
||||||
|
if (depth == 0)
|
||||||
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
depth--;
|
||||||
|
if (depth == 0)
|
||||||
|
expect_end = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FDT_PROP:
|
||||||
|
prop = fdt_getprop_by_offset(fdt, offset, &propname,
|
||||||
|
&err);
|
||||||
|
if (!prop)
|
||||||
|
return err;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -FDT_ERR_INTERNAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2012 David Gibson, IBM Corporation.
|
* Copyright (C) 2012 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -81,4 +36,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
|
||||||
|
|
||||||
return fdt_open_into(buf, buf, bufsize);
|
return fdt_open_into(buf, buf, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Copyright (C) 2016 Free Electrons
|
||||||
|
* Copyright (C) 2016 NextThing Co.
|
||||||
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
#include <fdt.h>
|
#include <fdt.h>
|
||||||
|
@ -21,51 +27,42 @@
|
||||||
*/
|
*/
|
||||||
static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
|
static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
|
||||||
{
|
{
|
||||||
const uint32_t *val;
|
const fdt32_t *val;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
val = fdt_getprop(fdto, fragment, "target", &len);
|
val = fdt_getprop(fdto, fragment, "target", &len);
|
||||||
if (!val)
|
if (!val)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((len != sizeof(*val)) || (*val == (uint32_t)-1))
|
if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
|
||||||
return (uint32_t)-1;
|
return (uint32_t)-1;
|
||||||
|
|
||||||
return fdt32_to_cpu(*val);
|
return fdt32_to_cpu(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
|
||||||
* overlay_get_target - retrieves the offset of a fragment's target
|
int fragment_offset, char const **pathp)
|
||||||
* @fdt: Base device tree blob
|
|
||||||
* @fdto: Device tree overlay blob
|
|
||||||
* @fragment: node offset of the fragment in the overlay
|
|
||||||
*
|
|
||||||
* overlay_get_target() retrieves the target offset in the base
|
|
||||||
* device tree of a fragment, no matter how the actual targetting is
|
|
||||||
* done (through a phandle or a path)
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* the targetted node offset in the base device tree
|
|
||||||
* Negative error code on error
|
|
||||||
*/
|
|
||||||
static int overlay_get_target(const void *fdt, const void *fdto,
|
|
||||||
int fragment)
|
|
||||||
{
|
{
|
||||||
uint32_t phandle;
|
uint32_t phandle;
|
||||||
const char *path;
|
const char *path = NULL;
|
||||||
int path_len;
|
int path_len = 0, ret;
|
||||||
|
|
||||||
/* Try first to do a phandle based lookup */
|
/* Try first to do a phandle based lookup */
|
||||||
phandle = overlay_get_target_phandle(fdto, fragment);
|
phandle = overlay_get_target_phandle(fdto, fragment_offset);
|
||||||
if (phandle == (uint32_t)-1)
|
if (phandle == (uint32_t)-1)
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
if (phandle)
|
/* no phandle, try path */
|
||||||
return fdt_node_offset_by_phandle(fdt, phandle);
|
if (!phandle) {
|
||||||
|
|
||||||
/* And then a path based lookup */
|
/* And then a path based lookup */
|
||||||
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
|
path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
|
||||||
if (!path) {
|
if (path)
|
||||||
|
ret = fdt_path_offset(fdt, path);
|
||||||
|
else
|
||||||
|
ret = path_len;
|
||||||
|
} else
|
||||||
|
ret = fdt_node_offset_by_phandle(fdt, phandle);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we haven't found either a target or a
|
* If we haven't found either a target or a
|
||||||
* target-path property in a node that contains a
|
* target-path property in a node that contains a
|
||||||
|
@ -73,13 +70,18 @@ static int overlay_get_target(const void *fdt, const void *fdto,
|
||||||
* otherwise), consider it a improperly written
|
* otherwise), consider it a improperly written
|
||||||
* overlay
|
* overlay
|
||||||
*/
|
*/
|
||||||
if (path_len == -FDT_ERR_NOTFOUND)
|
if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
ret = -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
return path_len;
|
/* return on error */
|
||||||
}
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return fdt_path_offset(fdt, path);
|
/* return pointer to path (if available) */
|
||||||
|
if (pathp)
|
||||||
|
*pathp = path ? path : NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,26 +101,22 @@ static int overlay_get_target(const void *fdt, const void *fdto,
|
||||||
static int overlay_phandle_add_offset(void *fdt, int node,
|
static int overlay_phandle_add_offset(void *fdt, int node,
|
||||||
const char *name, uint32_t delta)
|
const char *name, uint32_t delta)
|
||||||
{
|
{
|
||||||
const uint32_t *val;
|
fdt32_t *valp, val;
|
||||||
uint32_t adj_val;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
val = fdt_getprop(fdt, node, name, &len);
|
valp = fdt_getprop_w(fdt, node, name, &len);
|
||||||
if (!val)
|
if (!valp)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
if (len != sizeof(*val))
|
if (len != sizeof(val))
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
adj_val = fdt32_to_cpu(*val);
|
val = fdt32_ld(valp);
|
||||||
if ((adj_val + delta) < adj_val)
|
if (val + delta < val || val + delta == (uint32_t)-1)
|
||||||
return -FDT_ERR_NOPHANDLES;
|
return -FDT_ERR_NOPHANDLES;
|
||||||
|
|
||||||
adj_val += delta;
|
fdt32_st(valp, val + delta);
|
||||||
if (adj_val == (uint32_t)-1)
|
return 0;
|
||||||
return -FDT_ERR_NOPHANDLES;
|
|
||||||
|
|
||||||
return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -210,9 +208,9 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
||||||
const uint32_t *fixup_val;
|
const fdt32_t *fixup_val;
|
||||||
const char *tree_val;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
char *tree_val;
|
||||||
int fixup_len;
|
int fixup_len;
|
||||||
int tree_len;
|
int tree_len;
|
||||||
int i;
|
int i;
|
||||||
|
@ -224,8 +222,9 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
|
|
||||||
if (fixup_len % sizeof(uint32_t))
|
if (fixup_len % sizeof(uint32_t))
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
fixup_len /= sizeof(uint32_t);
|
||||||
|
|
||||||
tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
|
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
|
||||||
if (!tree_val) {
|
if (!tree_val) {
|
||||||
if (tree_len == -FDT_ERR_NOTFOUND)
|
if (tree_len == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
@ -233,35 +232,16 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
return tree_len;
|
return tree_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
|
for (i = 0; i < fixup_len; i++) {
|
||||||
uint32_t adj_val, poffset;
|
fdt32_t *refp;
|
||||||
|
|
||||||
poffset = fdt32_to_cpu(fixup_val[i]);
|
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* phandles to fixup can be unaligned.
|
* phandles to fixup can be unaligned, so use
|
||||||
*
|
* fdt32_{ld,st}() to read/write them.
|
||||||
* Use a memcpy for the architectures that do
|
|
||||||
* not support unaligned accesses.
|
|
||||||
*/
|
*/
|
||||||
memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
|
fdt32_st(refp, fdt32_ld(refp) + delta);
|
||||||
|
|
||||||
adj_val = fdt32_to_cpu(adj_val);
|
|
||||||
adj_val += delta;
|
|
||||||
adj_val = cpu_to_fdt32(adj_val);
|
|
||||||
|
|
||||||
ret = fdt_setprop_inplace_namelen_partial(fdto,
|
|
||||||
tree_node,
|
|
||||||
name,
|
|
||||||
strlen(name),
|
|
||||||
poffset,
|
|
||||||
&adj_val,
|
|
||||||
sizeof(adj_val));
|
|
||||||
if (ret == -FDT_ERR_NOSPACE)
|
|
||||||
return -FDT_ERR_BADOVERLAY;
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +252,7 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
|
|
||||||
tree_child = fdt_subnode_offset(fdto, tree_node,
|
tree_child = fdt_subnode_offset(fdto, tree_node,
|
||||||
fixup_child_name);
|
fixup_child_name);
|
||||||
if (ret == -FDT_ERR_NOTFOUND)
|
if (tree_child == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
if (tree_child < 0)
|
if (tree_child < 0)
|
||||||
return tree_child;
|
return tree_child;
|
||||||
|
@ -327,7 +307,6 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
|
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
|
||||||
* @fdt: Base Device Tree blob
|
|
||||||
* @fdto: Device tree overlay blob
|
* @fdto: Device tree overlay blob
|
||||||
* @symbols_off: Node offset of the symbols node in the base device tree
|
* @symbols_off: Node offset of the symbols node in the base device tree
|
||||||
* @path: Path to a node holding a phandle in the overlay
|
* @path: Path to a node holding a phandle in the overlay
|
||||||
|
@ -335,7 +314,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
* @name: Name of the property holding the phandle reference in the overlay
|
* @name: Name of the property holding the phandle reference in the overlay
|
||||||
* @name_len: number of name characters to consider
|
* @name_len: number of name characters to consider
|
||||||
* @poffset: Offset within the overlay property where the phandle is stored
|
* @poffset: Offset within the overlay property where the phandle is stored
|
||||||
* @label: Label of the node referenced by the phandle
|
* @phandle: Phandle referencing the node
|
||||||
*
|
*
|
||||||
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
|
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
|
||||||
* a node in the base device tree.
|
* a node in the base device tree.
|
||||||
|
@ -348,44 +327,29 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
* 0 on success
|
* 0 on success
|
||||||
* Negative error code on failure
|
* Negative error code on failure
|
||||||
*/
|
*/
|
||||||
static int overlay_fixup_one_phandle(void *fdt, void *fdto,
|
static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
|
||||||
int symbols_off,
|
|
||||||
const char *path, uint32_t path_len,
|
const char *path, uint32_t path_len,
|
||||||
const char *name, uint32_t name_len,
|
const char *name, uint32_t name_len,
|
||||||
int poffset, const char *label)
|
int poffset, uint32_t phandle)
|
||||||
{
|
{
|
||||||
const char *symbol_path;
|
fdt32_t phandle_prop;
|
||||||
uint32_t phandle;
|
int fixup_off;
|
||||||
int symbol_off, fixup_off;
|
|
||||||
int prop_len;
|
|
||||||
|
|
||||||
if (symbols_off < 0)
|
if (symbols_off < 0)
|
||||||
return symbols_off;
|
return symbols_off;
|
||||||
|
|
||||||
symbol_path = fdt_getprop(fdt, symbols_off, label,
|
|
||||||
&prop_len);
|
|
||||||
if (!symbol_path)
|
|
||||||
return prop_len;
|
|
||||||
|
|
||||||
symbol_off = fdt_path_offset(fdt, symbol_path);
|
|
||||||
if (symbol_off < 0)
|
|
||||||
return symbol_off;
|
|
||||||
|
|
||||||
phandle = fdt_get_phandle(fdt, symbol_off);
|
|
||||||
if (!phandle)
|
|
||||||
return -FDT_ERR_NOTFOUND;
|
|
||||||
|
|
||||||
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
|
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
|
||||||
if (fixup_off == -FDT_ERR_NOTFOUND)
|
if (fixup_off == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
if (fixup_off < 0)
|
if (fixup_off < 0)
|
||||||
return fixup_off;
|
return fixup_off;
|
||||||
|
|
||||||
phandle = cpu_to_fdt32(phandle);
|
phandle_prop = cpu_to_fdt32(phandle);
|
||||||
return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
|
return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
|
||||||
name, name_len, poffset,
|
name, name_len, poffset,
|
||||||
&phandle, sizeof(phandle));
|
&phandle_prop,
|
||||||
};
|
sizeof(phandle_prop));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overlay_fixup_phandle - Set an overlay phandle to the base one
|
* overlay_fixup_phandle - Set an overlay phandle to the base one
|
||||||
|
@ -412,6 +376,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
const char *value;
|
const char *value;
|
||||||
const char *label;
|
const char *label;
|
||||||
int len;
|
int len;
|
||||||
|
const char *symbol_path;
|
||||||
|
int prop_len;
|
||||||
|
int symbol_off;
|
||||||
|
uint32_t phandle;
|
||||||
|
|
||||||
value = fdt_getprop_by_offset(fdto, property,
|
value = fdt_getprop_by_offset(fdto, property,
|
||||||
&label, &len);
|
&label, &len);
|
||||||
|
@ -422,6 +390,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
|
||||||
|
if (!symbol_path)
|
||||||
|
return prop_len;
|
||||||
|
|
||||||
|
symbol_off = fdt_path_offset(fdt, symbol_path);
|
||||||
|
if (symbol_off < 0)
|
||||||
|
return symbol_off;
|
||||||
|
|
||||||
|
phandle = fdt_get_phandle(fdt, symbol_off);
|
||||||
|
if (!phandle)
|
||||||
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const char *path, *name, *fixup_end;
|
const char *path, *name, *fixup_end;
|
||||||
const char *fixup_str = value;
|
const char *fixup_str = value;
|
||||||
|
@ -461,9 +441,9 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
if ((*endptr != '\0') || (endptr <= (sep + 1)))
|
if ((*endptr != '\0') || (endptr <= (sep + 1)))
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
|
ret = overlay_fixup_one_phandle(fdto, symbols_off,
|
||||||
path, path_len, name, name_len,
|
path, path_len, name, name_len,
|
||||||
poffset, label);
|
poffset, phandle);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
|
@ -516,6 +496,255 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_adjust_local_conflicting_phandle: Changes a phandle value
|
||||||
|
* @fdto: Device tree overlay
|
||||||
|
* @node: The node the phandle is set for
|
||||||
|
* @fdt_phandle: The new value for the phandle
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
|
||||||
|
uint32_t fdt_phandle)
|
||||||
|
{
|
||||||
|
const fdt32_t *php;
|
||||||
|
int len, ret;
|
||||||
|
|
||||||
|
php = fdt_getprop(fdto, node, "phandle", &len);
|
||||||
|
if (php && len == sizeof(*php)) {
|
||||||
|
ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
php = fdt_getprop(fdto, node, "linux,phandle", &len);
|
||||||
|
if (php && len == sizeof(*php)) {
|
||||||
|
ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_update_node_conflicting_references - Recursively replace phandle values
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
* @tree_node: Node to recurse into
|
||||||
|
* @fixup_node: Node offset of the matching local fixups node
|
||||||
|
* @fdt_phandle: Value to replace phandles with
|
||||||
|
* @fdto_phandle: Value to be replaced
|
||||||
|
*
|
||||||
|
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
|
||||||
|
int fixup_node,
|
||||||
|
uint32_t fdt_phandle,
|
||||||
|
uint32_t fdto_phandle)
|
||||||
|
{
|
||||||
|
int fixup_prop;
|
||||||
|
int fixup_child;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
||||||
|
const fdt32_t *fixup_val;
|
||||||
|
const char *name;
|
||||||
|
char *tree_val;
|
||||||
|
int fixup_len;
|
||||||
|
int tree_len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
|
||||||
|
&name, &fixup_len);
|
||||||
|
if (!fixup_val)
|
||||||
|
return fixup_len;
|
||||||
|
|
||||||
|
if (fixup_len % sizeof(uint32_t))
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
fixup_len /= sizeof(uint32_t);
|
||||||
|
|
||||||
|
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
|
||||||
|
if (!tree_val) {
|
||||||
|
if (tree_len == -FDT_ERR_NOTFOUND)
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
|
return tree_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < fixup_len; i++) {
|
||||||
|
fdt32_t *refp;
|
||||||
|
uint32_t valp;
|
||||||
|
|
||||||
|
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
|
||||||
|
valp = fdt32_ld(refp);
|
||||||
|
|
||||||
|
if (valp == fdto_phandle)
|
||||||
|
fdt32_st(refp, fdt_phandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
|
||||||
|
const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
|
||||||
|
int tree_child;
|
||||||
|
|
||||||
|
tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
|
||||||
|
|
||||||
|
if (tree_child == -FDT_ERR_NOTFOUND)
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
if (tree_child < 0)
|
||||||
|
return tree_child;
|
||||||
|
|
||||||
|
ret = overlay_update_node_conflicting_references(fdto, tree_child,
|
||||||
|
fixup_child,
|
||||||
|
fdt_phandle,
|
||||||
|
fdto_phandle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_update_local_conflicting_references - Recursively replace phandle values
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
* @fdt_phandle: Value to replace phandles with
|
||||||
|
* @fdto_phandle: Value to be replaced
|
||||||
|
*
|
||||||
|
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_update_local_conflicting_references(void *fdto,
|
||||||
|
uint32_t fdt_phandle,
|
||||||
|
uint32_t fdto_phandle)
|
||||||
|
{
|
||||||
|
int fixups;
|
||||||
|
|
||||||
|
fixups = fdt_path_offset(fdto, "/__local_fixups__");
|
||||||
|
if (fixups == -FDT_ERR_NOTFOUND)
|
||||||
|
return 0;
|
||||||
|
if (fixups < 0)
|
||||||
|
return fixups;
|
||||||
|
|
||||||
|
return overlay_update_node_conflicting_references(fdto, 0, fixups,
|
||||||
|
fdt_phandle,
|
||||||
|
fdto_phandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
|
||||||
|
* @fdt: Base Device tree blob
|
||||||
|
* @fdtnode: Node in fdt that is checked for an overwrite
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
* @fdtonode: Node in fdto matching @fdtnode
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
|
||||||
|
void *fdto, int fdtonode)
|
||||||
|
{
|
||||||
|
uint32_t fdt_phandle, fdto_phandle;
|
||||||
|
int fdtochild;
|
||||||
|
|
||||||
|
fdt_phandle = fdt_get_phandle(fdt, fdtnode);
|
||||||
|
fdto_phandle = fdt_get_phandle(fdto, fdtonode);
|
||||||
|
|
||||||
|
if (fdt_phandle && fdto_phandle) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
|
||||||
|
fdt_phandle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = overlay_update_local_conflicting_references(fdto,
|
||||||
|
fdt_phandle,
|
||||||
|
fdto_phandle);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
|
||||||
|
const char *name = fdt_get_name(fdto, fdtochild, NULL);
|
||||||
|
int fdtchild;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
|
||||||
|
if (fdtchild == -FDT_ERR_NOTFOUND)
|
||||||
|
/*
|
||||||
|
* no further overwrites possible here as this node is
|
||||||
|
* new
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
|
||||||
|
fdto, fdtochild);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
|
||||||
|
* @fdt: Base Device Tree blob
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
*
|
||||||
|
* Checks recursively if applying fdto overwrites phandle values in the base
|
||||||
|
* dtb. When such a phandle is found, the fdto is changed to use the fdt's
|
||||||
|
* phandle value to not break references in the base.
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
|
||||||
|
{
|
||||||
|
int fragment;
|
||||||
|
|
||||||
|
fdt_for_each_subnode(fragment, fdto, 0) {
|
||||||
|
int overlay;
|
||||||
|
int target;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
|
||||||
|
if (overlay == -FDT_ERR_NOTFOUND)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (overlay < 0)
|
||||||
|
return overlay;
|
||||||
|
|
||||||
|
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
|
||||||
|
if (target == -FDT_ERR_NOTFOUND)
|
||||||
|
/*
|
||||||
|
* The subtree doesn't exist in the base, so nothing
|
||||||
|
* will be overwritten.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
else if (target < 0)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
ret = overlay_prevent_phandle_overwrite_node(fdt, target,
|
||||||
|
fdto, overlay);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overlay_apply_node - Merges a node into the base device tree
|
* overlay_apply_node - Merges a node into the base device tree
|
||||||
* @fdt: Base Device Tree blob
|
* @fdt: Base Device Tree blob
|
||||||
|
@ -589,7 +818,7 @@ static int overlay_apply_node(void *fdt, int target,
|
||||||
*
|
*
|
||||||
* overlay_merge() merges an overlay into its base device tree.
|
* overlay_merge() merges an overlay into its base device tree.
|
||||||
*
|
*
|
||||||
* This is the final step in the device tree overlay application
|
* This is the next to last step in the device tree overlay application
|
||||||
* process, when all the phandles have been adjusted and resolved and
|
* process, when all the phandles have been adjusted and resolved and
|
||||||
* you just have to merge overlay into the base device tree.
|
* you just have to merge overlay into the base device tree.
|
||||||
*
|
*
|
||||||
|
@ -617,7 +846,7 @@ static int overlay_merge(void *fdt, void *fdto)
|
||||||
if (overlay < 0)
|
if (overlay < 0)
|
||||||
return overlay;
|
return overlay;
|
||||||
|
|
||||||
target = overlay_get_target(fdt, fdto, fragment);
|
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
|
||||||
if (target < 0)
|
if (target < 0)
|
||||||
return target;
|
return target;
|
||||||
|
|
||||||
|
@ -629,30 +858,225 @@ static int overlay_merge(void *fdt, void *fdto)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_path_len(const void *fdt, int nodeoffset)
|
||||||
|
{
|
||||||
|
int len = 0, namelen;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
name = fdt_get_name(fdt, nodeoffset, &namelen);
|
||||||
|
if (!name)
|
||||||
|
return namelen;
|
||||||
|
|
||||||
|
/* root? we're done */
|
||||||
|
if (namelen == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nodeoffset = fdt_parent_offset(fdt, nodeoffset);
|
||||||
|
if (nodeoffset < 0)
|
||||||
|
return nodeoffset;
|
||||||
|
len += namelen + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in case of root pretend it's "/" */
|
||||||
|
if (len == 0)
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* overlay_symbol_update - Update the symbols of base tree after a merge
|
||||||
|
* @fdt: Base Device Tree blob
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
*
|
||||||
|
* overlay_symbol_update() updates the symbols of the base tree with the
|
||||||
|
* symbols of the applied overlay
|
||||||
|
*
|
||||||
|
* This is the last step in the device tree overlay application
|
||||||
|
* process, allowing the reference of overlay symbols by subsequent
|
||||||
|
* overlay operations.
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* 0 on success
|
||||||
|
* Negative error code on failure
|
||||||
|
*/
|
||||||
|
static int overlay_symbol_update(void *fdt, void *fdto)
|
||||||
|
{
|
||||||
|
int root_sym, ov_sym, prop, path_len, fragment, target;
|
||||||
|
int len, frag_name_len, ret, rel_path_len;
|
||||||
|
const char *s, *e;
|
||||||
|
const char *path;
|
||||||
|
const char *name;
|
||||||
|
const char *frag_name;
|
||||||
|
const char *rel_path;
|
||||||
|
const char *target_path;
|
||||||
|
char *buf;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
|
||||||
|
|
||||||
|
/* if no overlay symbols exist no problem */
|
||||||
|
if (ov_sym < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
|
||||||
|
|
||||||
|
/* it no root symbols exist we should create them */
|
||||||
|
if (root_sym == -FDT_ERR_NOTFOUND)
|
||||||
|
root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
|
||||||
|
|
||||||
|
/* any error is fatal now */
|
||||||
|
if (root_sym < 0)
|
||||||
|
return root_sym;
|
||||||
|
|
||||||
|
/* iterate over each overlay symbol */
|
||||||
|
fdt_for_each_property_offset(prop, fdto, ov_sym) {
|
||||||
|
path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
|
||||||
|
if (!path)
|
||||||
|
return path_len;
|
||||||
|
|
||||||
|
/* verify it's a string property (terminated by a single \0) */
|
||||||
|
if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
|
||||||
|
return -FDT_ERR_BADVALUE;
|
||||||
|
|
||||||
|
/* keep end marker to avoid strlen() */
|
||||||
|
e = path + path_len;
|
||||||
|
|
||||||
|
if (*path != '/')
|
||||||
|
return -FDT_ERR_BADVALUE;
|
||||||
|
|
||||||
|
/* get fragment name first */
|
||||||
|
s = strchr(path + 1, '/');
|
||||||
|
if (!s) {
|
||||||
|
/* Symbol refers to something that won't end
|
||||||
|
* up in the target tree */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag_name = path + 1;
|
||||||
|
frag_name_len = s - path - 1;
|
||||||
|
|
||||||
|
/* verify format; safe since "s" lies in \0 terminated prop */
|
||||||
|
len = sizeof("/__overlay__/") - 1;
|
||||||
|
if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
|
||||||
|
/* /<fragment-name>/__overlay__/<relative-subnode-path> */
|
||||||
|
rel_path = s + len;
|
||||||
|
rel_path_len = e - rel_path - 1;
|
||||||
|
} else if ((e - s) == len
|
||||||
|
&& (memcmp(s, "/__overlay__", len - 1) == 0)) {
|
||||||
|
/* /<fragment-name>/__overlay__ */
|
||||||
|
rel_path = "";
|
||||||
|
rel_path_len = 0;
|
||||||
|
} else {
|
||||||
|
/* Symbol refers to something that won't end
|
||||||
|
* up in the target tree */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the fragment index in which the symbol lies */
|
||||||
|
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
|
||||||
|
frag_name_len);
|
||||||
|
/* not found? */
|
||||||
|
if (ret < 0)
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
fragment = ret;
|
||||||
|
|
||||||
|
/* an __overlay__ subnode must exist */
|
||||||
|
ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
|
||||||
|
if (ret < 0)
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
|
/* get the target of the fragment */
|
||||||
|
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
target = ret;
|
||||||
|
|
||||||
|
/* if we have a target path use */
|
||||||
|
if (!target_path) {
|
||||||
|
ret = get_path_len(fdt, target);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
len = ret;
|
||||||
|
} else {
|
||||||
|
len = strlen(target_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fdt_setprop_placeholder(fdt, root_sym, name,
|
||||||
|
len + (len > 1) + rel_path_len + 1, &p);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!target_path) {
|
||||||
|
/* again in case setprop_placeholder changed it */
|
||||||
|
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
target = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = p;
|
||||||
|
if (len > 1) { /* target is not root */
|
||||||
|
if (!target_path) {
|
||||||
|
ret = fdt_get_path(fdt, target, buf, len + 1);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
} else
|
||||||
|
memcpy(buf, target_path, len + 1);
|
||||||
|
|
||||||
|
} else
|
||||||
|
len--;
|
||||||
|
|
||||||
|
buf[len] = '/';
|
||||||
|
memcpy(buf + len + 1, rel_path, rel_path_len);
|
||||||
|
buf[len + 1 + rel_path_len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fdt_overlay_apply(void *fdt, void *fdto)
|
int fdt_overlay_apply(void *fdt, void *fdto)
|
||||||
{
|
{
|
||||||
uint32_t delta = fdt_get_max_phandle(fdt);
|
uint32_t delta;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
FDT_CHECK_HEADER(fdto);
|
FDT_RO_PROBE(fdto);
|
||||||
|
|
||||||
|
ret = fdt_find_max_phandle(fdt, &delta);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Increase all phandles in the fdto by delta */
|
||||||
ret = overlay_adjust_local_phandles(fdto, delta);
|
ret = overlay_adjust_local_phandles(fdto, delta);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Adapt the phandle values in fdto to the above increase */
|
||||||
ret = overlay_update_local_references(fdto, delta);
|
ret = overlay_update_local_references(fdto, delta);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Update fdto's phandles using symbols from fdt */
|
||||||
ret = overlay_fixup_phandles(fdt, fdto);
|
ret = overlay_fixup_phandles(fdt, fdto);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* Don't overwrite phandles in fdt */
|
||||||
|
ret = overlay_prevent_phandle_overwrite(fdt, fdto);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
ret = overlay_merge(fdt, fdto);
|
ret = overlay_merge(fdt, fdto);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
ret = overlay_symbol_update(fdt, fdto);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The overlay has been damaged, erase its magic.
|
* The overlay has been damaged, erase its magic.
|
||||||
*/
|
*/
|
||||||
|
|
413
libfdt/fdt_ro.c
413
libfdt/fdt_ro.c
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -55,12 +10,13 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_nodename_eq(const void *fdt, int offset,
|
static int fdt_nodename_eq_(const void *fdt, int offset,
|
||||||
const char *s, int len)
|
const char *s, int len)
|
||||||
{
|
{
|
||||||
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
int olen;
|
||||||
|
const char *p = fdt_get_name(fdt, offset, &olen);
|
||||||
|
|
||||||
if (! p)
|
if (!p || olen < len)
|
||||||
/* short match */
|
/* short match */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -75,63 +31,174 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
|
||||||
|
{
|
||||||
|
int32_t totalsize;
|
||||||
|
uint32_t absoffset;
|
||||||
|
size_t len;
|
||||||
|
int err;
|
||||||
|
const char *s, *n;
|
||||||
|
|
||||||
|
if (can_assume(VALID_INPUT)) {
|
||||||
|
s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
|
||||||
|
|
||||||
|
if (lenp)
|
||||||
|
*lenp = strlen(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
totalsize = fdt_ro_probe_(fdt);
|
||||||
|
err = totalsize;
|
||||||
|
if (totalsize < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
err = -FDT_ERR_BADOFFSET;
|
||||||
|
absoffset = stroffset + fdt_off_dt_strings(fdt);
|
||||||
|
if (absoffset >= (unsigned)totalsize)
|
||||||
|
goto fail;
|
||||||
|
len = totalsize - absoffset;
|
||||||
|
|
||||||
|
if (fdt_magic(fdt) == FDT_MAGIC) {
|
||||||
|
if (stroffset < 0)
|
||||||
|
goto fail;
|
||||||
|
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
||||||
|
if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
|
||||||
|
goto fail;
|
||||||
|
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
|
||||||
|
len = fdt_size_dt_strings(fdt) - stroffset;
|
||||||
|
}
|
||||||
|
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
|
||||||
|
unsigned int sw_stroffset = -stroffset;
|
||||||
|
|
||||||
|
if ((stroffset >= 0) ||
|
||||||
|
(sw_stroffset > fdt_size_dt_strings(fdt)))
|
||||||
|
goto fail;
|
||||||
|
if (sw_stroffset < len)
|
||||||
|
len = sw_stroffset;
|
||||||
|
} else {
|
||||||
|
err = -FDT_ERR_INTERNAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = (const char *)fdt + absoffset;
|
||||||
|
n = memchr(s, '\0', len);
|
||||||
|
if (!n) {
|
||||||
|
/* missing terminating NULL */
|
||||||
|
err = -FDT_ERR_TRUNCATED;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lenp)
|
||||||
|
*lenp = n - s;
|
||||||
|
return s;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (lenp)
|
||||||
|
*lenp = err;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const char *fdt_string(const void *fdt, int stroffset)
|
const char *fdt_string(const void *fdt, int stroffset)
|
||||||
{
|
{
|
||||||
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
|
return fdt_get_string(fdt, stroffset, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_string_eq(const void *fdt, int stroffset,
|
static int fdt_string_eq_(const void *fdt, int stroffset,
|
||||||
const char *s, int len)
|
const char *s, int len)
|
||||||
{
|
{
|
||||||
const char *p = fdt_string(fdt, stroffset);
|
int slen;
|
||||||
|
const char *p = fdt_get_string(fdt, stroffset, &slen);
|
||||||
|
|
||||||
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
|
return p && (slen == len) && (memcmp(p, s, len) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fdt_get_max_phandle(const void *fdt)
|
int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
|
||||||
{
|
{
|
||||||
uint32_t max_phandle = 0;
|
uint32_t max = 0;
|
||||||
int offset;
|
int offset = -1;
|
||||||
|
|
||||||
for (offset = fdt_next_node(fdt, -1, NULL);;
|
while (true) {
|
||||||
offset = fdt_next_node(fdt, offset, NULL)) {
|
uint32_t value;
|
||||||
uint32_t phandle;
|
|
||||||
|
|
||||||
|
offset = fdt_next_node(fdt, offset, NULL);
|
||||||
|
if (offset < 0) {
|
||||||
if (offset == -FDT_ERR_NOTFOUND)
|
if (offset == -FDT_ERR_NOTFOUND)
|
||||||
return max_phandle;
|
break;
|
||||||
|
|
||||||
if (offset < 0)
|
return offset;
|
||||||
return (uint32_t)-1;
|
|
||||||
|
|
||||||
phandle = fdt_get_phandle(fdt, offset);
|
|
||||||
if (phandle == (uint32_t)-1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (phandle > max_phandle)
|
|
||||||
max_phandle = phandle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value = fdt_get_phandle(fdt, offset);
|
||||||
|
|
||||||
|
if (value > max)
|
||||||
|
max = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phandle)
|
||||||
|
*phandle = max;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
|
||||||
|
{
|
||||||
|
uint32_t max;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fdt_find_max_phandle(fdt, &max);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (max == FDT_MAX_PHANDLE)
|
||||||
|
return -FDT_ERR_NOPHANDLES;
|
||||||
|
|
||||||
|
if (phandle)
|
||||||
|
*phandle = max + 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
|
||||||
|
{
|
||||||
|
unsigned int offset = n * sizeof(struct fdt_reserve_entry);
|
||||||
|
unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT)) {
|
||||||
|
if (absoffset < fdt_off_mem_rsvmap(fdt))
|
||||||
|
return NULL;
|
||||||
|
if (absoffset > fdt_totalsize(fdt) -
|
||||||
|
sizeof(struct fdt_reserve_entry))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return fdt_mem_rsv_(fdt, n);
|
||||||
|
}
|
||||||
|
|
||||||
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
||||||
{
|
{
|
||||||
FDT_CHECK_HEADER(fdt);
|
const struct fdt_reserve_entry *re;
|
||||||
*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
|
|
||||||
*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
|
FDT_RO_PROBE(fdt);
|
||||||
|
re = fdt_mem_rsv(fdt, n);
|
||||||
|
if (!can_assume(VALID_INPUT) && !re)
|
||||||
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
|
*address = fdt64_ld_(&re->address);
|
||||||
|
*size = fdt64_ld_(&re->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_num_mem_rsv(const void *fdt)
|
int fdt_num_mem_rsv(const void *fdt)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i;
|
||||||
|
const struct fdt_reserve_entry *re;
|
||||||
|
|
||||||
while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
|
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
||||||
i++;
|
if (fdt64_ld_(&re->size) == 0)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
}
|
||||||
|
|
||||||
static int _nextprop(const void *fdt, int offset)
|
static int nextprop_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
int nextoffset;
|
int nextoffset;
|
||||||
|
@ -160,13 +227,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
|
||||||
{
|
{
|
||||||
int depth;
|
int depth;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
for (depth = 0;
|
for (depth = 0;
|
||||||
(offset >= 0) && (depth >= 0);
|
(offset >= 0) && (depth >= 0);
|
||||||
offset = fdt_next_node(fdt, offset, &depth))
|
offset = fdt_next_node(fdt, offset, &depth))
|
||||||
if ((depth == 1)
|
if ((depth == 1)
|
||||||
&& _fdt_nodename_eq(fdt, offset, name, namelen))
|
&& fdt_nodename_eq_(fdt, offset, name, namelen))
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
if (depth < 0)
|
if (depth < 0)
|
||||||
|
@ -186,7 +253,10 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
|
||||||
const char *p = path;
|
const char *p = path;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT) && namelen <= 0)
|
||||||
|
return -FDT_ERR_BADPATH;
|
||||||
|
|
||||||
/* see if we have an alias */
|
/* see if we have an alias */
|
||||||
if (*path != '/') {
|
if (*path != '/') {
|
||||||
|
@ -232,17 +302,35 @@ int fdt_path_offset(const void *fdt, const char *path)
|
||||||
|
|
||||||
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
||||||
{
|
{
|
||||||
const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
|
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
|
||||||
|
const char *nameptr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (((err = fdt_check_header(fdt)) != 0)
|
if (((err = fdt_ro_probe_(fdt)) < 0)
|
||||||
|| ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
|
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (len)
|
nameptr = nh->name;
|
||||||
*len = strlen(nh->name);
|
|
||||||
|
|
||||||
return nh->name;
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
|
||||||
|
/*
|
||||||
|
* For old FDT versions, match the naming conventions of V16:
|
||||||
|
* give only the leaf name (after all /). The actual tree
|
||||||
|
* contents are loosely checked.
|
||||||
|
*/
|
||||||
|
const char *leaf;
|
||||||
|
leaf = strrchr(nameptr, '/');
|
||||||
|
if (leaf == NULL) {
|
||||||
|
err = -FDT_ERR_BADSTRUCTURE;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
nameptr = leaf+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
*len = strlen(nameptr);
|
||||||
|
|
||||||
|
return nameptr;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (len)
|
if (len)
|
||||||
|
@ -254,65 +342,107 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
return _nextprop(fdt, offset);
|
return nextprop_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_next_property_offset(const void *fdt, int offset)
|
int fdt_next_property_offset(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
|
if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
return _nextprop(fdt, offset);
|
return nextprop_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
||||||
int offset,
|
int offset,
|
||||||
int *lenp)
|
int *lenp)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
|
if (!can_assume(VALID_INPUT) &&
|
||||||
|
(err = fdt_check_prop_offset_(fdt, offset)) < 0) {
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = err;
|
*lenp = err;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop = _fdt_offset_ptr(fdt, offset);
|
prop = fdt_offset_ptr_(fdt, offset);
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = fdt32_to_cpu(prop->len);
|
*lenp = fdt32_ld_(&prop->len);
|
||||||
|
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
||||||
|
int offset,
|
||||||
|
int *lenp)
|
||||||
|
{
|
||||||
|
/* Prior to version 16, properties may need realignment
|
||||||
|
* and this API does not work. fdt_getprop_*() will, however. */
|
||||||
|
|
||||||
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = -FDT_ERR_BADVERSION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdt_get_property_by_offset_(fdt, offset, lenp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
||||||
int offset,
|
int offset,
|
||||||
const char *name,
|
const char *name,
|
||||||
int namelen, int *lenp)
|
int namelen,
|
||||||
|
int *lenp,
|
||||||
|
int *poffset)
|
||||||
{
|
{
|
||||||
for (offset = fdt_first_property_offset(fdt, offset);
|
for (offset = fdt_first_property_offset(fdt, offset);
|
||||||
(offset >= 0);
|
(offset >= 0);
|
||||||
(offset = fdt_next_property_offset(fdt, offset))) {
|
(offset = fdt_next_property_offset(fdt, offset))) {
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
|
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
|
||||||
|
if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
|
||||||
offset = -FDT_ERR_INTERNAL;
|
offset = -FDT_ERR_INTERNAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
|
if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
|
||||||
name, namelen))
|
name, namelen)) {
|
||||||
|
if (poffset)
|
||||||
|
*poffset = offset;
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = offset;
|
*lenp = offset;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
||||||
|
int offset,
|
||||||
|
const char *name,
|
||||||
|
int namelen, int *lenp)
|
||||||
|
{
|
||||||
|
/* Prior to version 16, properties may need realignment
|
||||||
|
* and this API does not work. fdt_getprop_*() will, however. */
|
||||||
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = -FDT_ERR_BADVERSION;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const struct fdt_property *fdt_get_property(const void *fdt,
|
const struct fdt_property *fdt_get_property(const void *fdt,
|
||||||
int nodeoffset,
|
int nodeoffset,
|
||||||
const char *name, int *lenp)
|
const char *name, int *lenp)
|
||||||
|
@ -324,12 +454,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
|
||||||
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
||||||
const char *name, int namelen, int *lenp)
|
const char *name, int namelen, int *lenp)
|
||||||
{
|
{
|
||||||
|
int poffset;
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
|
||||||
|
&poffset);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Handle realignment */
|
||||||
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
||||||
|
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
|
||||||
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,11 +474,31 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
||||||
{
|
{
|
||||||
const struct fdt_property *prop;
|
const struct fdt_property *prop;
|
||||||
|
|
||||||
prop = fdt_get_property_by_offset(fdt, offset, lenp);
|
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (namep)
|
if (namep) {
|
||||||
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
const char *name;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT)) {
|
||||||
|
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
|
||||||
|
&namelen);
|
||||||
|
*namep = name;
|
||||||
|
if (!name) {
|
||||||
|
if (lenp)
|
||||||
|
*lenp = namelen;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle realignment */
|
||||||
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
||||||
|
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
|
||||||
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,19 +522,34 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fdt32_to_cpu(*php);
|
return fdt32_ld_(php);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
|
||||||
|
const char *propname, int propnamelen,
|
||||||
|
int *lenp)
|
||||||
|
{
|
||||||
|
int offset = fdt_path_offset(fdt, path);
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fdt_get_alias_namelen(const void *fdt,
|
const char *fdt_get_alias_namelen(const void *fdt,
|
||||||
const char *name, int namelen)
|
const char *name, int namelen)
|
||||||
{
|
{
|
||||||
int aliasoffset;
|
int len;
|
||||||
|
const char *alias;
|
||||||
|
|
||||||
aliasoffset = fdt_path_offset(fdt, "/aliases");
|
alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
|
||||||
if (aliasoffset < 0)
|
|
||||||
|
if (!can_assume(VALID_DTB) &&
|
||||||
|
!(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
|
return alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fdt_get_alias(const void *fdt, const char *name)
|
const char *fdt_get_alias(const void *fdt, const char *name)
|
||||||
|
@ -386,13 +557,24 @@ const char *fdt_get_alias(const void *fdt, const char *name)
|
||||||
return fdt_get_alias_namelen(fdt, name, strlen(name));
|
return fdt_get_alias_namelen(fdt, name, strlen(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *fdt_get_symbol_namelen(const void *fdt,
|
||||||
|
const char *name, int namelen)
|
||||||
|
{
|
||||||
|
return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fdt_get_symbol(const void *fdt, const char *name)
|
||||||
|
{
|
||||||
|
return fdt_get_symbol_namelen(fdt, name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
|
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
int pdepth = 0, p = 0;
|
int pdepth = 0, p = 0;
|
||||||
int offset, depth, namelen;
|
int offset, depth, namelen;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
if (buflen < 2)
|
if (buflen < 2)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
@ -444,7 +626,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
|
||||||
int offset, depth;
|
int offset, depth;
|
||||||
int supernodeoffset = -FDT_ERR_INTERNAL;
|
int supernodeoffset = -FDT_ERR_INTERNAL;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
if (supernodedepth < 0)
|
if (supernodedepth < 0)
|
||||||
return -FDT_ERR_NOTFOUND;
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
@ -466,10 +648,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT)) {
|
||||||
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
|
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
else if (offset == -FDT_ERR_BADOFFSET)
|
else if (offset == -FDT_ERR_BADOFFSET)
|
||||||
return -FDT_ERR_BADSTRUCTURE;
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
|
}
|
||||||
|
|
||||||
return offset; /* error from fdt_next_node() */
|
return offset; /* error from fdt_next_node() */
|
||||||
}
|
}
|
||||||
|
@ -481,7 +665,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
|
||||||
|
|
||||||
err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
|
err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
|
||||||
if (err)
|
if (err)
|
||||||
return (err < 0) ? err : -FDT_ERR_INTERNAL;
|
return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
|
||||||
|
-FDT_ERR_INTERNAL;
|
||||||
return nodedepth;
|
return nodedepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +688,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
|
||||||
const void *val;
|
const void *val;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
/* FIXME: The algorithm here is pretty horrible: we scan each
|
/* FIXME: The algorithm here is pretty horrible: we scan each
|
||||||
* property of a node in fdt_getprop(), then if that didn't
|
* property of a node in fdt_getprop(), then if that didn't
|
||||||
|
@ -526,10 +711,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if ((phandle == 0) || (phandle == -1))
|
if ((phandle == 0) || (phandle == ~0U))
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
/* FIXME: The algorithm here is pretty horrible: we
|
/* FIXME: The algorithm here is pretty horrible: we
|
||||||
* potentially scan each property of a node in
|
* potentially scan each property of a node in
|
||||||
|
@ -682,7 +867,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
||||||
{
|
{
|
||||||
int offset, err;
|
int offset, err;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
/* FIXME: The algorithm here is pretty horrible: we scan each
|
/* FIXME: The algorithm here is pretty horrible: we scan each
|
||||||
* property of a node in fdt_node_check_compatible(), then if
|
* property of a node in fdt_node_check_compatible(), then if
|
||||||
|
|
262
libfdt/fdt_rw.c
262
libfdt/fdt_rw.c
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -55,7 +10,7 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_blocks_misordered(const void *fdt,
|
static int fdt_blocks_misordered_(const void *fdt,
|
||||||
int mem_rsv_size, int struct_size)
|
int mem_rsv_size, int struct_size)
|
||||||
{
|
{
|
||||||
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|
||||||
|
@ -67,54 +22,57 @@ static int _fdt_blocks_misordered(const void *fdt,
|
||||||
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
|
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_rw_check_header(void *fdt)
|
static int fdt_rw_probe_(void *fdt)
|
||||||
{
|
{
|
||||||
FDT_CHECK_HEADER(fdt);
|
if (can_assume(VALID_DTB))
|
||||||
|
return 0;
|
||||||
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
if (fdt_version(fdt) < 17)
|
if (!can_assume(LATEST) && fdt_version(fdt) < 17)
|
||||||
return -FDT_ERR_BADVERSION;
|
return -FDT_ERR_BADVERSION;
|
||||||
if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
|
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
|
||||||
fdt_size_dt_struct(fdt)))
|
fdt_size_dt_struct(fdt)))
|
||||||
return -FDT_ERR_BADLAYOUT;
|
return -FDT_ERR_BADLAYOUT;
|
||||||
if (fdt_version(fdt) > 17)
|
if (!can_assume(LATEST) && fdt_version(fdt) > 17)
|
||||||
fdt_set_version(fdt, 17);
|
fdt_set_version(fdt, 17);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FDT_RW_CHECK_HEADER(fdt) \
|
#define FDT_RW_PROBE(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int __err; \
|
int err_; \
|
||||||
if ((__err = _fdt_rw_check_header(fdt)) != 0) \
|
if ((err_ = fdt_rw_probe_(fdt)) != 0) \
|
||||||
return __err; \
|
return err_; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _fdt_data_size(void *fdt)
|
static inline unsigned int fdt_data_size_(void *fdt)
|
||||||
{
|
{
|
||||||
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
|
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
|
||||||
{
|
{
|
||||||
char *p = splicepoint;
|
char *p = splicepoint;
|
||||||
char *end = (char *)fdt + _fdt_data_size(fdt);
|
unsigned int dsize = fdt_data_size_(fdt);
|
||||||
|
size_t soff = p - (char *)fdt;
|
||||||
|
|
||||||
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
|
if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
|
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
memmove(p + newlen, p + oldlen, end - p - oldlen);
|
memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
|
||||||
int oldn, int newn)
|
int oldn, int newn)
|
||||||
{
|
{
|
||||||
int delta = (newn - oldn) * sizeof(*p);
|
int delta = (newn - oldn) * sizeof(*p);
|
||||||
int err;
|
int err;
|
||||||
err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
|
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
|
||||||
|
@ -122,13 +80,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_struct(void *fdt, void *p,
|
static int fdt_splice_struct_(void *fdt, void *p,
|
||||||
int oldlen, int newlen)
|
int oldlen, int newlen)
|
||||||
{
|
{
|
||||||
int delta = newlen - oldlen;
|
int delta = newlen - oldlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
|
if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
||||||
|
@ -136,38 +94,63 @@ static int _fdt_splice_struct(void *fdt, void *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_splice_string(void *fdt, int newlen)
|
/* Must only be used to roll back in case of error */
|
||||||
|
static void fdt_del_last_string_(void *fdt, const char *s)
|
||||||
|
{
|
||||||
|
int newlen = strlen(s) + 1;
|
||||||
|
|
||||||
|
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fdt_splice_string_(void *fdt, int newlen)
|
||||||
{
|
{
|
||||||
void *p = (char *)fdt
|
void *p = (char *)fdt
|
||||||
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if ((err = _fdt_splice(fdt, p, 0, newlen)))
|
if ((err = fdt_splice_(fdt, p, 0, newlen)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_find_add_string(void *fdt, const char *s)
|
/**
|
||||||
|
* fdt_find_add_string_() - Find or allocate a string
|
||||||
|
*
|
||||||
|
* @fdt: pointer to the device tree to check/adjust
|
||||||
|
* @s: string to find/add
|
||||||
|
* @allocated: Set to 0 if the string was found, 1 if not found and so
|
||||||
|
* allocated. Ignored if can_assume(NO_ROLLBACK)
|
||||||
|
* @return offset of string in the string table (whether found or added)
|
||||||
|
*/
|
||||||
|
static int fdt_find_add_string_(void *fdt, const char *s, int slen,
|
||||||
|
int *allocated)
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
||||||
const char *p;
|
const char *p;
|
||||||
char *new;
|
char *new;
|
||||||
int len = strlen(s) + 1;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
|
if (!can_assume(NO_ROLLBACK))
|
||||||
|
*allocated = 0;
|
||||||
|
|
||||||
|
p = fdt_find_string_len_(strtab, fdt_size_dt_strings(fdt), s, slen);
|
||||||
if (p)
|
if (p)
|
||||||
/* found it */
|
/* found it */
|
||||||
return (p - strtab);
|
return (p - strtab);
|
||||||
|
|
||||||
new = strtab + fdt_size_dt_strings(fdt);
|
new = strtab + fdt_size_dt_strings(fdt);
|
||||||
err = _fdt_splice_string(fdt, len);
|
err = fdt_splice_string_(fdt, slen + 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
memcpy(new, s, len);
|
if (!can_assume(NO_ROLLBACK))
|
||||||
|
*allocated = 1;
|
||||||
|
|
||||||
|
memcpy(new, s, slen);
|
||||||
|
new[slen] = '\0';
|
||||||
|
|
||||||
return (new - strtab);
|
return (new - strtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,10 +159,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
struct fdt_reserve_entry *re;
|
struct fdt_reserve_entry *re;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
|
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
|
||||||
err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
|
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -190,27 +173,29 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
||||||
|
|
||||||
int fdt_del_mem_rsv(void *fdt, int n)
|
int fdt_del_mem_rsv(void *fdt, int n)
|
||||||
{
|
{
|
||||||
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
|
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
if (n >= fdt_num_mem_rsv(fdt))
|
if (n >= fdt_num_mem_rsv(fdt))
|
||||||
return -FDT_ERR_NOTFOUND;
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
|
||||||
return _fdt_splice_mem_rsv(fdt, re, 1, 0);
|
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
static int fdt_resize_property_(void *fdt, int nodeoffset,
|
||||||
|
const char *name, int namelen,
|
||||||
int len, struct fdt_property **prop)
|
int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int oldlen;
|
int oldlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
*prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen,
|
||||||
if (! (*prop))
|
&oldlen);
|
||||||
|
if (!*prop)
|
||||||
return oldlen;
|
return oldlen;
|
||||||
|
|
||||||
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
||||||
FDT_TAGALIGN(len))))
|
FDT_TAGALIGN(len))))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -218,27 +203,32 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
|
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
int len, struct fdt_property **prop)
|
int namelen, int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int proplen;
|
int proplen;
|
||||||
int nextoffset;
|
int nextoffset;
|
||||||
int namestroff;
|
int namestroff;
|
||||||
int err;
|
int err;
|
||||||
|
int allocated;
|
||||||
|
|
||||||
if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
namestroff = _fdt_find_add_string(fdt, name);
|
namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
|
||||||
if (namestroff < 0)
|
if (namestroff < 0)
|
||||||
return namestroff;
|
return namestroff;
|
||||||
|
|
||||||
*prop = _fdt_offset_ptr_w(fdt, nextoffset);
|
*prop = fdt_offset_ptr_w_(fdt, nextoffset);
|
||||||
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
|
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, *prop, 0, proplen);
|
err = fdt_splice_struct_(fdt, *prop, 0, proplen);
|
||||||
if (err)
|
if (err) {
|
||||||
|
/* Delete the string if we failed to add it */
|
||||||
|
if (!can_assume(NO_ROLLBACK) && allocated)
|
||||||
|
fdt_del_last_string_(fdt, name);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
(*prop)->tag = cpu_to_fdt32(FDT_PROP);
|
(*prop)->tag = cpu_to_fdt32(FDT_PROP);
|
||||||
(*prop)->nameoff = cpu_to_fdt32(namestroff);
|
(*prop)->nameoff = cpu_to_fdt32(namestroff);
|
||||||
|
@ -252,7 +242,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||||
int oldlen, newlen;
|
int oldlen, newlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
|
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
|
||||||
if (!namep)
|
if (!namep)
|
||||||
|
@ -260,7 +250,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||||
|
|
||||||
newlen = strlen(name);
|
newlen = strlen(name);
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
||||||
FDT_TAGALIGN(newlen+1));
|
FDT_TAGALIGN(newlen+1));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -269,22 +259,38 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
const void *val, int len)
|
int namelen, int len, void **prop_data)
|
||||||
{
|
{
|
||||||
struct fdt_property *prop;
|
struct fdt_property *prop;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop);
|
||||||
if (err == -FDT_ERR_NOTFOUND)
|
if (err == -FDT_ERR_NOTFOUND)
|
||||||
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_add_property_(fdt, nodeoffset, name, namelen, len,
|
||||||
|
&prop);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
*prop_data = prop->data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
|
int namelen, const void *val, int len)
|
||||||
|
{
|
||||||
|
void *prop_data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
|
||||||
|
len, &prop_data);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
memcpy(prop->data, val, len);
|
memcpy(prop_data, val, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,12 +300,12 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
struct fdt_property *prop;
|
struct fdt_property *prop;
|
||||||
int err, oldlen, newlen;
|
int err, oldlen, newlen;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||||
if (prop) {
|
if (prop) {
|
||||||
newlen = len + oldlen;
|
newlen = len + oldlen;
|
||||||
err = _fdt_splice_struct(fdt, prop->data,
|
err = fdt_splice_struct_(fdt, prop->data,
|
||||||
FDT_TAGALIGN(oldlen),
|
FDT_TAGALIGN(oldlen),
|
||||||
FDT_TAGALIGN(newlen));
|
FDT_TAGALIGN(newlen));
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -307,7 +313,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
prop->len = cpu_to_fdt32(newlen);
|
prop->len = cpu_to_fdt32(newlen);
|
||||||
memcpy(prop->data + oldlen, val, len);
|
memcpy(prop->data + oldlen, val, len);
|
||||||
} else {
|
} else {
|
||||||
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
|
||||||
|
len, &prop);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
memcpy(prop->data, val, len);
|
memcpy(prop->data, val, len);
|
||||||
|
@ -320,14 +327,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
||||||
struct fdt_property *prop;
|
struct fdt_property *prop;
|
||||||
int len, proplen;
|
int len, proplen;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
||||||
return _fdt_splice_struct(fdt, prop, proplen, 0);
|
return fdt_splice_struct_(fdt, prop, proplen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
|
@ -340,7 +347,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
fdt32_t *endtag;
|
fdt32_t *endtag;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
|
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
|
@ -349,16 +356,19 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
/* Try to place the new node after the parent's properties */
|
/* Try to place the new node after the parent's properties */
|
||||||
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
|
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
|
||||||
|
/* the fdt_subnode_offset_namelen() should ensure this never hits */
|
||||||
|
if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
|
||||||
|
return -FDT_ERR_INTERNAL;
|
||||||
do {
|
do {
|
||||||
offset = nextoffset;
|
offset = nextoffset;
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
||||||
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
|
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
|
||||||
|
|
||||||
nh = _fdt_offset_ptr_w(fdt, offset);
|
nh = fdt_offset_ptr_w_(fdt, offset);
|
||||||
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
|
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
|
||||||
|
|
||||||
err = _fdt_splice_struct(fdt, nh, 0, nodelen);
|
err = fdt_splice_struct_(fdt, nh, 0, nodelen);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -380,18 +390,20 @@ int fdt_del_node(void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
int endoffset;
|
int endoffset;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
||||||
if (endoffset < 0)
|
if (endoffset < 0)
|
||||||
return endoffset;
|
return endoffset;
|
||||||
|
|
||||||
return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
|
return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
|
||||||
endoffset - nodeoffset, 0);
|
endoffset - nodeoffset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fdt_packblocks(const char *old, char *new,
|
static void fdt_packblocks_(const char *old, char *new,
|
||||||
int mem_rsv_size, int struct_size)
|
int mem_rsv_size,
|
||||||
|
int struct_size,
|
||||||
|
int strings_size)
|
||||||
{
|
{
|
||||||
int mem_rsv_off, struct_off, strings_off;
|
int mem_rsv_off, struct_off, strings_off;
|
||||||
|
|
||||||
|
@ -406,8 +418,7 @@ static void _fdt_packblocks(const char *old, char *new,
|
||||||
fdt_set_off_dt_struct(new, struct_off);
|
fdt_set_off_dt_struct(new, struct_off);
|
||||||
fdt_set_size_dt_struct(new, struct_size);
|
fdt_set_size_dt_struct(new, struct_size);
|
||||||
|
|
||||||
memmove(new + strings_off, old + fdt_off_dt_strings(old),
|
memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
|
||||||
fdt_size_dt_strings(old));
|
|
||||||
fdt_set_off_dt_strings(new, strings_off);
|
fdt_set_off_dt_strings(new, strings_off);
|
||||||
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
|
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
|
||||||
}
|
}
|
||||||
|
@ -421,22 +432,25 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
const char *fdtend = fdtstart + fdt_totalsize(fdt);
|
const char *fdtend = fdtstart + fdt_totalsize(fdt);
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
FDT_CHECK_HEADER(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
||||||
* sizeof(struct fdt_reserve_entry);
|
* sizeof(struct fdt_reserve_entry);
|
||||||
|
|
||||||
if (fdt_version(fdt) >= 17) {
|
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
||||||
struct_size = fdt_size_dt_struct(fdt);
|
struct_size = fdt_size_dt_struct(fdt);
|
||||||
} else {
|
} else if (fdt_version(fdt) == 16) {
|
||||||
struct_size = 0;
|
struct_size = 0;
|
||||||
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
|
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
|
||||||
;
|
;
|
||||||
if (struct_size < 0)
|
if (struct_size < 0)
|
||||||
return struct_size;
|
return struct_size;
|
||||||
|
} else {
|
||||||
|
return -FDT_ERR_BADVERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
|
if (can_assume(LIBFDT_ORDER) ||
|
||||||
|
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
|
||||||
/* no further work necessary */
|
/* no further work necessary */
|
||||||
err = fdt_move(fdt, buf, bufsize);
|
err = fdt_move(fdt, buf, bufsize);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -464,7 +478,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
|
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
|
||||||
|
fdt_size_dt_strings(fdt));
|
||||||
memmove(buf, tmp, newsize);
|
memmove(buf, tmp, newsize);
|
||||||
|
|
||||||
fdt_set_magic(buf, FDT_MAGIC);
|
fdt_set_magic(buf, FDT_MAGIC);
|
||||||
|
@ -480,12 +495,13 @@ int fdt_pack(void *fdt)
|
||||||
{
|
{
|
||||||
int mem_rsv_size;
|
int mem_rsv_size;
|
||||||
|
|
||||||
FDT_RW_CHECK_HEADER(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
||||||
* sizeof(struct fdt_reserve_entry);
|
* sizeof(struct fdt_reserve_entry);
|
||||||
_fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
|
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
|
||||||
fdt_set_totalsize(fdt, _fdt_data_size(fdt));
|
fdt_size_dt_strings(fdt));
|
||||||
|
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
@ -82,8 +38,10 @@ static struct fdt_errtabent fdt_errtable[] = {
|
||||||
FDT_ERRTABENT(FDT_ERR_BADVALUE),
|
FDT_ERRTABENT(FDT_ERR_BADVALUE),
|
||||||
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
|
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
|
||||||
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
|
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
|
||||||
|
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
|
||||||
|
FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
|
||||||
};
|
};
|
||||||
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
|
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
|
||||||
|
|
||||||
const char *fdt_strerror(int errval)
|
const char *fdt_strerror(int errval)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +49,7 @@ const char *fdt_strerror(int errval)
|
||||||
return "<valid offset/length>";
|
return "<valid offset/length>";
|
||||||
else if (errval == 0)
|
else if (errval == 0)
|
||||||
return "<no error>";
|
return "<no error>";
|
||||||
else if (errval > -FDT_ERRTABSIZE) {
|
else if (-errval < FDT_ERRTABSIZE) {
|
||||||
const char *s = fdt_errtable[-errval].str;
|
const char *s = fdt_errtable[-errval].str;
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
|
|
312
libfdt/fdt_sw.c
312
libfdt/fdt_sw.c
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -55,25 +10,91 @@
|
||||||
|
|
||||||
#include "libfdt_internal.h"
|
#include "libfdt_internal.h"
|
||||||
|
|
||||||
static int _fdt_sw_check_header(void *fdt)
|
static int fdt_sw_probe_(void *fdt)
|
||||||
{
|
{
|
||||||
if (fdt_magic(fdt) != FDT_SW_MAGIC)
|
if (!can_assume(VALID_INPUT)) {
|
||||||
|
if (fdt_magic(fdt) == FDT_MAGIC)
|
||||||
|
return -FDT_ERR_BADSTATE;
|
||||||
|
else if (fdt_magic(fdt) != FDT_SW_MAGIC)
|
||||||
return -FDT_ERR_BADMAGIC;
|
return -FDT_ERR_BADMAGIC;
|
||||||
/* FIXME: should check more details about the header state */
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FDT_SW_CHECK_HEADER(fdt) \
|
#define FDT_SW_PROBE(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int err; \
|
int err; \
|
||||||
if ((err = _fdt_sw_check_header(fdt)) != 0) \
|
if ((err = fdt_sw_probe_(fdt)) != 0) \
|
||||||
return err; \
|
return err; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *_fdt_grab_space(void *fdt, size_t len)
|
/* 'memrsv' state: Initial state after fdt_create()
|
||||||
|
*
|
||||||
|
* Allowed functions:
|
||||||
|
* fdt_add_reservemap_entry()
|
||||||
|
* fdt_finish_reservemap() [moves to 'struct' state]
|
||||||
|
*/
|
||||||
|
static int fdt_sw_probe_memrsv_(void *fdt)
|
||||||
{
|
{
|
||||||
int offset = fdt_size_dt_struct(fdt);
|
int err = fdt_sw_probe_(fdt);
|
||||||
int spaceleft;
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
|
||||||
|
return -FDT_ERR_BADSTATE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FDT_SW_PROBE_MEMRSV(fdt) \
|
||||||
|
{ \
|
||||||
|
int err; \
|
||||||
|
if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
|
||||||
|
return err; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'struct' state: Enter this state after fdt_finish_reservemap()
|
||||||
|
*
|
||||||
|
* Allowed functions:
|
||||||
|
* fdt_begin_node()
|
||||||
|
* fdt_end_node()
|
||||||
|
* fdt_property*()
|
||||||
|
* fdt_finish() [moves to 'complete' state]
|
||||||
|
*/
|
||||||
|
static int fdt_sw_probe_struct_(void *fdt)
|
||||||
|
{
|
||||||
|
int err = fdt_sw_probe_(fdt);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!can_assume(VALID_INPUT) &&
|
||||||
|
fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
|
||||||
|
return -FDT_ERR_BADSTATE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FDT_SW_PROBE_STRUCT(fdt) \
|
||||||
|
{ \
|
||||||
|
int err; \
|
||||||
|
if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
|
||||||
|
return err; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t sw_flags(void *fdt)
|
||||||
|
{
|
||||||
|
/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
|
||||||
|
return fdt_last_comp_version(fdt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 'complete' state: Enter this state after fdt_finish()
|
||||||
|
*
|
||||||
|
* Allowed functions: none
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void *fdt_grab_space_(void *fdt, size_t len)
|
||||||
|
{
|
||||||
|
unsigned int offset = fdt_size_dt_struct(fdt);
|
||||||
|
unsigned int spaceleft;
|
||||||
|
|
||||||
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
|
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
|
||||||
- fdt_size_dt_strings(fdt);
|
- fdt_size_dt_strings(fdt);
|
||||||
|
@ -82,29 +103,46 @@ static void *_fdt_grab_space(void *fdt, size_t len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fdt_set_size_dt_struct(fdt, offset + len);
|
fdt_set_size_dt_struct(fdt, offset + len);
|
||||||
return _fdt_offset_ptr_w(fdt, offset);
|
return fdt_offset_ptr_w_(fdt, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
|
||||||
|
{
|
||||||
|
const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
|
||||||
|
sizeof(struct fdt_reserve_entry));
|
||||||
|
void *fdt = buf;
|
||||||
|
|
||||||
|
if (bufsize < hdrsize)
|
||||||
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
if (flags & ~FDT_CREATE_FLAGS_ALL)
|
||||||
|
return -FDT_ERR_BADFLAGS;
|
||||||
|
|
||||||
|
memset(buf, 0, bufsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* magic and last_comp_version keep intermediate state during the fdt
|
||||||
|
* creation process, which is replaced with the proper FDT format by
|
||||||
|
* fdt_finish().
|
||||||
|
*
|
||||||
|
* flags should be accessed with sw_flags().
|
||||||
|
*/
|
||||||
|
fdt_set_magic(fdt, FDT_SW_MAGIC);
|
||||||
|
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
|
||||||
|
fdt_set_last_comp_version(fdt, flags);
|
||||||
|
|
||||||
|
fdt_set_totalsize(fdt, bufsize);
|
||||||
|
|
||||||
|
fdt_set_off_mem_rsvmap(fdt, hdrsize);
|
||||||
|
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
|
||||||
|
fdt_set_off_dt_strings(fdt, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_create(void *buf, int bufsize)
|
int fdt_create(void *buf, int bufsize)
|
||||||
{
|
{
|
||||||
void *fdt = buf;
|
return fdt_create_with_flags(buf, bufsize, 0);
|
||||||
|
|
||||||
if (bufsize < sizeof(struct fdt_header))
|
|
||||||
return -FDT_ERR_NOSPACE;
|
|
||||||
|
|
||||||
memset(buf, 0, bufsize);
|
|
||||||
|
|
||||||
fdt_set_magic(fdt, FDT_SW_MAGIC);
|
|
||||||
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
|
|
||||||
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
|
|
||||||
fdt_set_totalsize(fdt, bufsize);
|
|
||||||
|
|
||||||
fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
|
|
||||||
sizeof(struct fdt_reserve_entry)));
|
|
||||||
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
|
|
||||||
fdt_set_off_dt_strings(fdt, bufsize);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_resize(void *fdt, void *buf, int bufsize)
|
int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||||
|
@ -112,12 +150,19 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||||
size_t headsize, tailsize;
|
size_t headsize, tailsize;
|
||||||
char *oldtail, *newtail;
|
char *oldtail, *newtail;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE(fdt);
|
||||||
|
|
||||||
headsize = fdt_off_dt_struct(fdt);
|
if (bufsize < 0)
|
||||||
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
|
||||||
tailsize = fdt_size_dt_strings(fdt);
|
tailsize = fdt_size_dt_strings(fdt);
|
||||||
|
|
||||||
if ((headsize + tailsize) > bufsize)
|
if (!can_assume(VALID_DTB) &&
|
||||||
|
headsize + tailsize > fdt_totalsize(fdt))
|
||||||
|
return -FDT_ERR_INTERNAL;
|
||||||
|
|
||||||
|
if ((headsize + tailsize) > (unsigned)bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
||||||
|
@ -133,8 +178,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||||
memmove(buf, fdt, headsize);
|
memmove(buf, fdt, headsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt_set_off_dt_strings(buf, bufsize);
|
|
||||||
fdt_set_totalsize(buf, bufsize);
|
fdt_set_totalsize(buf, bufsize);
|
||||||
|
if (fdt_off_dt_strings(buf))
|
||||||
|
fdt_set_off_dt_strings(buf, bufsize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -144,10 +190,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
|
||||||
struct fdt_reserve_entry *re;
|
struct fdt_reserve_entry *re;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE_MEMRSV(fdt);
|
||||||
|
|
||||||
if (fdt_size_dt_struct(fdt))
|
|
||||||
return -FDT_ERR_BADSTATE;
|
|
||||||
|
|
||||||
offset = fdt_off_dt_struct(fdt);
|
offset = fdt_off_dt_struct(fdt);
|
||||||
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
|
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
|
||||||
|
@ -164,17 +207,24 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
|
||||||
|
|
||||||
int fdt_finish_reservemap(void *fdt)
|
int fdt_finish_reservemap(void *fdt)
|
||||||
{
|
{
|
||||||
return fdt_add_reservemap_entry(fdt, 0, 0);
|
int err = fdt_add_reservemap_entry(fdt, 0, 0);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_begin_node(void *fdt, const char *name)
|
int fdt_begin_node(void *fdt, const char *name)
|
||||||
{
|
{
|
||||||
struct fdt_node_header *nh;
|
struct fdt_node_header *nh;
|
||||||
int namelen = strlen(name) + 1;
|
int namelen;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE_STRUCT(fdt);
|
||||||
|
|
||||||
nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
namelen = strlen(name) + 1;
|
||||||
|
nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
||||||
if (! nh)
|
if (! nh)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
@ -187,9 +237,9 @@ int fdt_end_node(void *fdt)
|
||||||
{
|
{
|
||||||
fdt32_t *en;
|
fdt32_t *en;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE_STRUCT(fdt);
|
||||||
|
|
||||||
en = _fdt_grab_space(fdt, FDT_TAGSIZE);
|
en = fdt_grab_space_(fdt, FDT_TAGSIZE);
|
||||||
if (! en)
|
if (! en)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
|
@ -197,48 +247,90 @@ int fdt_end_node(void *fdt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fdt_find_add_string(void *fdt, const char *s)
|
static int fdt_add_string_(void *fdt, const char *s)
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
||||||
const char *p;
|
unsigned int strtabsize = fdt_size_dt_strings(fdt);
|
||||||
|
unsigned int len = strlen(s) + 1;
|
||||||
|
unsigned int struct_top, offset;
|
||||||
|
|
||||||
|
offset = strtabsize + len;
|
||||||
|
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
|
||||||
|
if (fdt_totalsize(fdt) - offset < struct_top)
|
||||||
|
return 0; /* no more room :( */
|
||||||
|
|
||||||
|
memcpy(strtab - offset, s, len);
|
||||||
|
fdt_set_size_dt_strings(fdt, strtabsize + len);
|
||||||
|
return -offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must only be used to roll back in case of error */
|
||||||
|
static void fdt_del_last_string_(void *fdt, const char *s)
|
||||||
|
{
|
||||||
int strtabsize = fdt_size_dt_strings(fdt);
|
int strtabsize = fdt_size_dt_strings(fdt);
|
||||||
int len = strlen(s) + 1;
|
int len = strlen(s) + 1;
|
||||||
int struct_top, offset;
|
|
||||||
|
|
||||||
p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
|
fdt_set_size_dt_strings(fdt, strtabsize - len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
|
||||||
|
{
|
||||||
|
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
||||||
|
int strtabsize = fdt_size_dt_strings(fdt);
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
*allocated = 0;
|
||||||
|
|
||||||
|
p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
|
||||||
if (p)
|
if (p)
|
||||||
return p - strtab;
|
return p - strtab;
|
||||||
|
|
||||||
/* Add it */
|
*allocated = 1;
|
||||||
offset = -strtabsize - len;
|
|
||||||
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
|
|
||||||
if (fdt_totalsize(fdt) + offset < struct_top)
|
|
||||||
return 0; /* no more room :( */
|
|
||||||
|
|
||||||
memcpy(strtab + offset, s, len);
|
return fdt_add_string_(fdt, s);
|
||||||
fdt_set_size_dt_strings(fdt, strtabsize + len);
|
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_property(void *fdt, const char *name, const void *val, int len)
|
int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
||||||
{
|
{
|
||||||
struct fdt_property *prop;
|
struct fdt_property *prop;
|
||||||
int nameoff;
|
int nameoff;
|
||||||
|
int allocated;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE_STRUCT(fdt);
|
||||||
|
|
||||||
nameoff = _fdt_find_add_string(fdt, name);
|
/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
|
||||||
|
if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
|
||||||
|
allocated = 1;
|
||||||
|
nameoff = fdt_add_string_(fdt, name);
|
||||||
|
} else {
|
||||||
|
nameoff = fdt_find_add_string_(fdt, name, &allocated);
|
||||||
|
}
|
||||||
if (nameoff == 0)
|
if (nameoff == 0)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
||||||
if (! prop)
|
if (! prop) {
|
||||||
|
if (allocated)
|
||||||
|
fdt_del_last_string_(fdt, name);
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
}
|
||||||
|
|
||||||
prop->tag = cpu_to_fdt32(FDT_PROP);
|
prop->tag = cpu_to_fdt32(FDT_PROP);
|
||||||
prop->nameoff = cpu_to_fdt32(nameoff);
|
prop->nameoff = cpu_to_fdt32(nameoff);
|
||||||
prop->len = cpu_to_fdt32(len);
|
prop->len = cpu_to_fdt32(len);
|
||||||
memcpy(prop->data, val, len);
|
*valp = prop->data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_property(void *fdt, const char *name, const void *val, int len)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
memcpy(ptr, val, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,10 +342,10 @@ int fdt_finish(void *fdt)
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
int offset, nextoffset;
|
int offset, nextoffset;
|
||||||
|
|
||||||
FDT_SW_CHECK_HEADER(fdt);
|
FDT_SW_PROBE_STRUCT(fdt);
|
||||||
|
|
||||||
/* Add terminator */
|
/* Add terminator */
|
||||||
end = _fdt_grab_space(fdt, sizeof(*end));
|
end = fdt_grab_space_(fdt, sizeof(*end));
|
||||||
if (! end)
|
if (! end)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
*end = cpu_to_fdt32(FDT_END);
|
*end = cpu_to_fdt32(FDT_END);
|
||||||
|
@ -269,7 +361,7 @@ int fdt_finish(void *fdt)
|
||||||
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
|
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
|
||||||
if (tag == FDT_PROP) {
|
if (tag == FDT_PROP) {
|
||||||
struct fdt_property *prop =
|
struct fdt_property *prop =
|
||||||
_fdt_offset_ptr_w(fdt, offset);
|
fdt_offset_ptr_w_(fdt, offset);
|
||||||
int nameoff;
|
int nameoff;
|
||||||
|
|
||||||
nameoff = fdt32_to_cpu(prop->nameoff);
|
nameoff = fdt32_to_cpu(prop->nameoff);
|
||||||
|
@ -283,6 +375,10 @@ int fdt_finish(void *fdt)
|
||||||
|
|
||||||
/* Finally, adjust the header */
|
/* Finally, adjust the header */
|
||||||
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
|
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
|
||||||
|
|
||||||
|
/* And fix up fields that were keeping intermediate state. */
|
||||||
|
fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
|
||||||
fdt_set_magic(fdt, FDT_MAGIC);
|
fdt_set_magic(fdt, FDT_MAGIC);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,7 @@
|
||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include "libfdt_env.h"
|
#include "libfdt_env.h"
|
||||||
|
|
||||||
|
@ -68,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
||||||
if (!propval)
|
if (!propval)
|
||||||
return proplen;
|
return proplen;
|
||||||
|
|
||||||
if (proplen < (len + idx))
|
if ((unsigned)proplen < (len + idx))
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
memcpy((char *)propval + idx, val, len);
|
memcpy((char *)propval + idx, val, len);
|
||||||
|
@ -93,7 +48,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||||
val, len);
|
val, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _fdt_nop_region(void *start, int len)
|
static void fdt_nop_region_(void *start, int len)
|
||||||
{
|
{
|
||||||
fdt32_t *p;
|
fdt32_t *p;
|
||||||
|
|
||||||
|
@ -110,12 +65,12 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
_fdt_nop_region(prop, len + sizeof(*prop));
|
fdt_nop_region_(prop, len + sizeof(*prop));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_node_end_offset(void *fdt, int offset)
|
int fdt_node_end_offset_(void *fdt, int offset)
|
||||||
{
|
{
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
|
||||||
|
@ -129,11 +84,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
|
||||||
{
|
{
|
||||||
int endoffset;
|
int endoffset;
|
||||||
|
|
||||||
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
||||||
if (endoffset < 0)
|
if (endoffset < 0)
|
||||||
return endoffset;
|
return endoffset;
|
||||||
|
|
||||||
_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
||||||
endoffset - nodeoffset);
|
endoffset - nodeoffset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
937
libfdt/libfdt.h
937
libfdt/libfdt.h
File diff suppressed because it is too large
Load Diff
|
@ -1,73 +1,30 @@
|
||||||
#ifndef _LIBFDT_ENV_H
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
||||||
#define _LIBFDT_ENV_H
|
#ifndef LIBFDT_ENV_H
|
||||||
|
#define LIBFDT_ENV_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#ifdef __CHECKER__
|
#ifdef __CHECKER__
|
||||||
#define __force __attribute__((force))
|
#define FDT_FORCE __attribute__((force))
|
||||||
#define __bitwise __attribute__((bitwise))
|
#define FDT_BITWISE __attribute__((bitwise))
|
||||||
#else
|
#else
|
||||||
#define __force
|
#define FDT_FORCE
|
||||||
#define __bitwise
|
#define FDT_BITWISE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef uint16_t __bitwise fdt16_t;
|
typedef uint16_t FDT_BITWISE fdt16_t;
|
||||||
typedef uint32_t __bitwise fdt32_t;
|
typedef uint32_t FDT_BITWISE fdt32_t;
|
||||||
typedef uint64_t __bitwise fdt64_t;
|
typedef uint64_t FDT_BITWISE fdt64_t;
|
||||||
|
|
||||||
#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
|
#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
|
||||||
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
|
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
|
||||||
|
@ -80,33 +37,60 @@ typedef uint64_t __bitwise fdt64_t;
|
||||||
|
|
||||||
static inline uint16_t fdt16_to_cpu(fdt16_t x)
|
static inline uint16_t fdt16_to_cpu(fdt16_t x)
|
||||||
{
|
{
|
||||||
return (__force uint16_t)CPU_TO_FDT16(x);
|
return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
|
||||||
}
|
}
|
||||||
static inline fdt16_t cpu_to_fdt16(uint16_t x)
|
static inline fdt16_t cpu_to_fdt16(uint16_t x)
|
||||||
{
|
{
|
||||||
return (__force fdt16_t)CPU_TO_FDT16(x);
|
return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t fdt32_to_cpu(fdt32_t x)
|
static inline uint32_t fdt32_to_cpu(fdt32_t x)
|
||||||
{
|
{
|
||||||
return (__force uint32_t)CPU_TO_FDT32(x);
|
return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
|
||||||
}
|
}
|
||||||
static inline fdt32_t cpu_to_fdt32(uint32_t x)
|
static inline fdt32_t cpu_to_fdt32(uint32_t x)
|
||||||
{
|
{
|
||||||
return (__force fdt32_t)CPU_TO_FDT32(x);
|
return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t fdt64_to_cpu(fdt64_t x)
|
static inline uint64_t fdt64_to_cpu(fdt64_t x)
|
||||||
{
|
{
|
||||||
return (__force uint64_t)CPU_TO_FDT64(x);
|
return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
|
||||||
}
|
}
|
||||||
static inline fdt64_t cpu_to_fdt64(uint64_t x)
|
static inline fdt64_t cpu_to_fdt64(uint64_t x)
|
||||||
{
|
{
|
||||||
return (__force fdt64_t)CPU_TO_FDT64(x);
|
return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
|
||||||
}
|
}
|
||||||
#undef CPU_TO_FDT64
|
#undef CPU_TO_FDT64
|
||||||
#undef CPU_TO_FDT32
|
#undef CPU_TO_FDT32
|
||||||
#undef CPU_TO_FDT16
|
#undef CPU_TO_FDT16
|
||||||
#undef EXTRACT_BYTE
|
#undef EXTRACT_BYTE
|
||||||
|
|
||||||
#endif /* _LIBFDT_ENV_H */
|
#ifdef __APPLE__
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
|
||||||
|
/* strnlen() is not available on Mac OS < 10.7 */
|
||||||
|
# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
|
||||||
|
MAC_OS_X_VERSION_10_7)
|
||||||
|
|
||||||
|
#define strnlen fdt_strnlen
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fdt_strnlen: returns the length of a string or max_count - which ever is
|
||||||
|
* smallest.
|
||||||
|
* Input 1 string: the string whose size is to be determined
|
||||||
|
* Input 2 max_count: the maximum value returned by this function
|
||||||
|
* Output: length of the string or max_count (the smallest of the two)
|
||||||
|
*/
|
||||||
|
static inline size_t fdt_strnlen(const char *string, size_t max_count)
|
||||||
|
{
|
||||||
|
const char *p = memchr(string, 0, max_count);
|
||||||
|
return p ? p - string : max_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
|
||||||
|
MAC_OS_X_VERSION_10_7) */
|
||||||
|
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
#endif /* LIBFDT_ENV_H */
|
||||||
|
|
|
@ -1,83 +1,47 @@
|
||||||
#ifndef _LIBFDT_INTERNAL_H
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
||||||
#define _LIBFDT_INTERNAL_H
|
#ifndef LIBFDT_INTERNAL_H
|
||||||
|
#define LIBFDT_INTERNAL_H
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* libfdt is dual licensed: you can use it either under the terms of
|
|
||||||
* the GPL, or the BSD license, at your option.
|
|
||||||
*
|
|
||||||
* a) This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this library; if not, write to the Free
|
|
||||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Alternatively,
|
|
||||||
*
|
|
||||||
* b) Redistribution and use in source and binary forms, with or
|
|
||||||
* without modification, are permitted provided that the following
|
|
||||||
* conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above
|
|
||||||
* copyright notice, this list of conditions and the following
|
|
||||||
* disclaimer in the documentation and/or other materials
|
|
||||||
* provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
||||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
#include <fdt.h>
|
#include <fdt.h>
|
||||||
|
|
||||||
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
|
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
|
||||||
|
|
||||||
#define FDT_CHECK_HEADER(fdt) \
|
int32_t fdt_ro_probe_(const void *fdt);
|
||||||
|
#define FDT_RO_PROBE(fdt) \
|
||||||
{ \
|
{ \
|
||||||
int __err; \
|
int32_t totalsize_; \
|
||||||
if ((__err = fdt_check_header(fdt)) != 0) \
|
if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
|
||||||
return __err; \
|
return totalsize_; \
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fdt_check_node_offset(const void *fdt, int offset);
|
int fdt_check_node_offset_(const void *fdt, int offset);
|
||||||
int _fdt_check_prop_offset(const void *fdt, int offset);
|
int fdt_check_prop_offset_(const void *fdt, int offset);
|
||||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
|
|
||||||
int _fdt_node_end_offset(void *fdt, int nodeoffset);
|
|
||||||
|
|
||||||
static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
|
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
|
||||||
|
int s_len);
|
||||||
|
static inline const char *fdt_find_string_(const char *strtab, int tabsize,
|
||||||
|
const char *s)
|
||||||
|
{
|
||||||
|
return fdt_find_string_len_(strtab, tabsize, s, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_node_end_offset_(void *fdt, int nodeoffset);
|
||||||
|
|
||||||
|
static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
|
static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
|
||||||
{
|
{
|
||||||
return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
|
return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
|
static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
|
||||||
{
|
{
|
||||||
const struct fdt_reserve_entry *rsv_table =
|
const struct fdt_reserve_entry *rsv_table =
|
||||||
(const struct fdt_reserve_entry *)
|
(const struct fdt_reserve_entry *)
|
||||||
|
@ -85,11 +49,152 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
|
||||||
|
|
||||||
return rsv_table + n;
|
return rsv_table + n;
|
||||||
}
|
}
|
||||||
static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
|
static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
|
||||||
{
|
{
|
||||||
return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
|
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal helpers to access structural elements of the device tree
|
||||||
|
* blob (rather than for example reading integers from within property
|
||||||
|
* values). We assume that we are either given a naturally aligned
|
||||||
|
* address for the platform or if we are not, we are on a platform
|
||||||
|
* where unaligned memory reads will be handled in a graceful manner.
|
||||||
|
* If not the external helpers fdtXX_ld() from libfdt.h can be used
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
static inline uint32_t fdt32_ld_(const fdt32_t *p)
|
||||||
|
{
|
||||||
|
return fdt32_to_cpu(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint64_t fdt64_ld_(const fdt64_t *p)
|
||||||
|
{
|
||||||
|
return fdt64_to_cpu(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
||||||
|
|
||||||
#endif /* _LIBFDT_INTERNAL_H */
|
/**********************************************************************/
|
||||||
|
/* Checking controls */
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef FDT_ASSUME_MASK
|
||||||
|
#define FDT_ASSUME_MASK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines assumptions which can be enabled. Each of these can be enabled
|
||||||
|
* individually. For maximum safety, don't enable any assumptions!
|
||||||
|
*
|
||||||
|
* For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
|
||||||
|
* You should have another method of validating the device tree, such as a
|
||||||
|
* signature or hash check before using libfdt.
|
||||||
|
*
|
||||||
|
* For situations where security is not a concern it may be safe to enable
|
||||||
|
* ASSUME_SANE.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
/*
|
||||||
|
* This does essentially no checks. Only the latest device-tree
|
||||||
|
* version is correctly handled. Inconsistencies or errors in the device
|
||||||
|
* tree may cause undefined behaviour or crashes. Invalid parameters
|
||||||
|
* passed to libfdt may do the same.
|
||||||
|
*
|
||||||
|
* If an error occurs when modifying the tree it may leave the tree in
|
||||||
|
* an intermediate (but valid) state. As an example, adding a property
|
||||||
|
* where there is insufficient space may result in the property name
|
||||||
|
* being added to the string table even though the property itself is
|
||||||
|
* not added to the struct section.
|
||||||
|
*
|
||||||
|
* Only use this if you have a fully validated device tree with
|
||||||
|
* the latest supported version and wish to minimise code size.
|
||||||
|
*/
|
||||||
|
ASSUME_PERFECT = 0xff,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This assumes that the device tree is sane. i.e. header metadata
|
||||||
|
* and basic hierarchy are correct.
|
||||||
|
*
|
||||||
|
* With this assumption enabled, normal device trees produced by libfdt
|
||||||
|
* and the compiler should be handled safely. Malicious device trees and
|
||||||
|
* complete garbage may cause libfdt to behave badly or crash. Truncated
|
||||||
|
* device trees (e.g. those only partially loaded) can also cause
|
||||||
|
* problems.
|
||||||
|
*
|
||||||
|
* Note: Only checks that relate exclusively to the device tree itself
|
||||||
|
* (not the parameters passed to libfdt) are disabled by this
|
||||||
|
* assumption. This includes checking headers, tags and the like.
|
||||||
|
*/
|
||||||
|
ASSUME_VALID_DTB = 1 << 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This builds on ASSUME_VALID_DTB and further assumes that libfdt
|
||||||
|
* functions are called with valid parameters, i.e. not trigger
|
||||||
|
* FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
|
||||||
|
* extensive checking of parameters and the device tree, making various
|
||||||
|
* assumptions about correctness.
|
||||||
|
*
|
||||||
|
* It doesn't make sense to enable this assumption unless
|
||||||
|
* ASSUME_VALID_DTB is also enabled.
|
||||||
|
*/
|
||||||
|
ASSUME_VALID_INPUT = 1 << 1,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This disables checks for device-tree version and removes all code
|
||||||
|
* which handles older versions.
|
||||||
|
*
|
||||||
|
* Only enable this if you know you have a device tree with the latest
|
||||||
|
* version.
|
||||||
|
*/
|
||||||
|
ASSUME_LATEST = 1 << 2,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This assumes that it is OK for a failed addition to the device tree,
|
||||||
|
* due to lack of space or some other problem, to skip any rollback
|
||||||
|
* steps (such as dropping the property name from the string table).
|
||||||
|
* This is safe to enable in most circumstances, even though it may
|
||||||
|
* leave the tree in a sub-optimal state.
|
||||||
|
*/
|
||||||
|
ASSUME_NO_ROLLBACK = 1 << 3,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This assumes that the device tree components appear in a 'convenient'
|
||||||
|
* order, i.e. the memory reservation block first, then the structure
|
||||||
|
* block and finally the string block.
|
||||||
|
*
|
||||||
|
* This order is not specified by the device-tree specification,
|
||||||
|
* but is expected by libfdt. The device-tree compiler always created
|
||||||
|
* device trees with this order.
|
||||||
|
*
|
||||||
|
* This assumption disables a check in fdt_open_into() and removes the
|
||||||
|
* ability to fix the problem there. This is safe if you know that the
|
||||||
|
* device tree is correctly ordered. See fdt_blocks_misordered_().
|
||||||
|
*/
|
||||||
|
ASSUME_LIBFDT_ORDER = 1 << 4,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This assumes that libfdt itself does not have any internal bugs. It
|
||||||
|
* drops certain checks that should never be needed unless libfdt has an
|
||||||
|
* undiscovered bug.
|
||||||
|
*
|
||||||
|
* This can generally be considered safe to enable.
|
||||||
|
*/
|
||||||
|
ASSUME_LIBFDT_FLAWLESS = 1 << 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can_assume_() - check if a particular assumption is enabled
|
||||||
|
*
|
||||||
|
* @mask: Mask to check (ASSUME_...)
|
||||||
|
* @return true if that assumption is enabled, else false
|
||||||
|
*/
|
||||||
|
static inline bool can_assume_(int mask)
|
||||||
|
{
|
||||||
|
return FDT_ASSUME_MASK & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** helper macros for checking assumptions */
|
||||||
|
#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)
|
||||||
|
|
||||||
|
#endif /* LIBFDT_INTERNAL_H */
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
|
||||||
|
if not cc.has_link_argument(version_script)
|
||||||
|
version_script = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
sources = files(
|
||||||
|
'fdt.c',
|
||||||
|
'fdt_addresses.c',
|
||||||
|
'fdt_check.c',
|
||||||
|
'fdt_empty_tree.c',
|
||||||
|
'fdt_overlay.c',
|
||||||
|
'fdt_ro.c',
|
||||||
|
'fdt_rw.c',
|
||||||
|
'fdt_strerror.c',
|
||||||
|
'fdt_sw.c',
|
||||||
|
'fdt_wip.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
link_args = []
|
||||||
|
if cc.has_link_argument('-Wl,--no-undefined')
|
||||||
|
link_args += '-Wl,--no-undefined'
|
||||||
|
else
|
||||||
|
# -undefined error is the equivalent of --no-undefined for the macOS linker,
|
||||||
|
# but -undefined would also be understood as a valid argument for GNU ld!
|
||||||
|
link_args += cc.get_supported_link_arguments('-Wl,-undefined,error')
|
||||||
|
endif
|
||||||
|
|
||||||
|
link_args += version_script
|
||||||
|
libfdt = library(
|
||||||
|
'fdt', sources,
|
||||||
|
version: meson.project_version(),
|
||||||
|
link_args: link_args,
|
||||||
|
link_depends: 'version.lds',
|
||||||
|
install: get_option('default_library') != 'static' or not wheel_only,
|
||||||
|
)
|
||||||
|
|
||||||
|
libfdt_inc = include_directories('.')
|
||||||
|
|
||||||
|
libfdt_dep = declare_dependency(
|
||||||
|
include_directories: libfdt_inc,
|
||||||
|
link_with: libfdt,
|
||||||
|
)
|
||||||
|
meson.override_dependency('libfdt', libfdt_dep)
|
||||||
|
|
||||||
|
if not wheel_only
|
||||||
|
install_headers(
|
||||||
|
files(
|
||||||
|
'fdt.h',
|
||||||
|
'libfdt.h',
|
||||||
|
'libfdt_env.h',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
pkgconfig = import('pkgconfig')
|
||||||
|
|
||||||
|
pkgconfig.generate(
|
||||||
|
libraries: libfdt,
|
||||||
|
version: meson.project_version(),
|
||||||
|
filebase: 'libfdt',
|
||||||
|
name: 'libfdt',
|
||||||
|
description: 'Flat Device Tree manipulation',
|
||||||
|
)
|
||||||
|
endif
|
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"bomFormat": "CycloneDX",
|
||||||
|
"specVersion": "1.6",
|
||||||
|
"version": 1,
|
||||||
|
"metadata": {
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "@VCS_SBOM_AUTHORS@"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "library",
|
||||||
|
"bom-ref": "pkg:github/dgibson/libfdt@@VCS_TAG@",
|
||||||
|
"cpe": "cpe:2.3:a:dgibson:libfdt:@VCS_TAG@:*:*:*:*:*:*:*",
|
||||||
|
"name": "libfdt",
|
||||||
|
"version": "@VCS_VERSION@",
|
||||||
|
"description": "Utility library for reading and manipulating the FDT binary format",
|
||||||
|
"supplier": {
|
||||||
|
"name": "libfdt developers"
|
||||||
|
},
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"license": {
|
||||||
|
"id": "BSD-2-Clause"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"license": {
|
||||||
|
"id": "GPL-2.0-or-later"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"externalReferences": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/dgibson/dtc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
|
||||||
LIBFDT_1.2 {
|
LIBFDT_1.2 {
|
||||||
global:
|
global:
|
||||||
fdt_next_node;
|
fdt_next_node;
|
||||||
|
@ -19,6 +20,7 @@ LIBFDT_1.2 {
|
||||||
fdt_get_alias_namelen;
|
fdt_get_alias_namelen;
|
||||||
fdt_get_alias;
|
fdt_get_alias;
|
||||||
fdt_get_path;
|
fdt_get_path;
|
||||||
|
fdt_header_size;
|
||||||
fdt_supernode_atdepth_offset;
|
fdt_supernode_atdepth_offset;
|
||||||
fdt_node_depth;
|
fdt_node_depth;
|
||||||
fdt_parent_offset;
|
fdt_parent_offset;
|
||||||
|
@ -41,6 +43,7 @@ LIBFDT_1.2 {
|
||||||
fdt_add_mem_rsv;
|
fdt_add_mem_rsv;
|
||||||
fdt_del_mem_rsv;
|
fdt_del_mem_rsv;
|
||||||
fdt_set_name;
|
fdt_set_name;
|
||||||
|
fdt_setprop_namelen;
|
||||||
fdt_setprop;
|
fdt_setprop;
|
||||||
fdt_delprop;
|
fdt_delprop;
|
||||||
fdt_add_subnode_namelen;
|
fdt_add_subnode_namelen;
|
||||||
|
@ -60,9 +63,25 @@ LIBFDT_1.2 {
|
||||||
fdt_address_cells;
|
fdt_address_cells;
|
||||||
fdt_size_cells;
|
fdt_size_cells;
|
||||||
fdt_stringlist_contains;
|
fdt_stringlist_contains;
|
||||||
|
fdt_stringlist_count;
|
||||||
|
fdt_stringlist_search;
|
||||||
|
fdt_stringlist_get;
|
||||||
fdt_resize;
|
fdt_resize;
|
||||||
fdt_overlay_apply;
|
fdt_overlay_apply;
|
||||||
|
fdt_get_string;
|
||||||
|
fdt_find_max_phandle;
|
||||||
|
fdt_generate_phandle;
|
||||||
|
fdt_check_full;
|
||||||
|
fdt_setprop_placeholder_namelen;
|
||||||
|
fdt_setprop_placeholder;
|
||||||
|
fdt_property_placeholder;
|
||||||
|
fdt_header_size_;
|
||||||
|
fdt_appendprop_addrrange;
|
||||||
|
fdt_setprop_inplace_namelen_partial;
|
||||||
|
fdt_create_with_flags;
|
||||||
|
fdt_overlay_target_offset;
|
||||||
|
fdt_get_symbol;
|
||||||
|
fdt_get_symbol_namelen;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
327
livetree.c
327
livetree.c
|
@ -1,24 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
||||||
*
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
#include "srcpos.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tree building functions
|
* Tree building functions
|
||||||
|
@ -50,25 +36,27 @@ void delete_labels(struct label **labels)
|
||||||
label->deleted = 1;
|
label->deleted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val)
|
struct property *build_property(const char *name, struct data val,
|
||||||
|
struct srcpos *srcpos)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->name = name;
|
new->name = xstrdup(name);
|
||||||
new->val = val;
|
new->val = val;
|
||||||
|
new->srcpos = srcpos_copy(srcpos);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *build_property_delete(char *name)
|
struct property *build_property_delete(const char *name)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->name = name;
|
new->name = xstrdup(name);
|
||||||
new->deleted = 1;
|
new->deleted = 1;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
|
@ -97,7 +85,8 @@ struct property *reverse_properties(struct property *first)
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *build_node(struct property *proplist, struct node *children)
|
struct node *build_node(struct property *proplist, struct node *children,
|
||||||
|
struct srcpos *srcpos)
|
||||||
{
|
{
|
||||||
struct node *new = xmalloc(sizeof(*new));
|
struct node *new = xmalloc(sizeof(*new));
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
@ -106,6 +95,7 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||||
|
|
||||||
new->proplist = reverse_properties(proplist);
|
new->proplist = reverse_properties(proplist);
|
||||||
new->children = children;
|
new->children = children;
|
||||||
|
new->srcpos = srcpos_copy(srcpos);
|
||||||
|
|
||||||
for_each_child(new, child) {
|
for_each_child(new, child) {
|
||||||
child->parent = new;
|
child->parent = new;
|
||||||
|
@ -114,22 +104,37 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *build_node_delete(void)
|
struct node *build_node_delete(struct srcpos *srcpos)
|
||||||
{
|
{
|
||||||
struct node *new = xmalloc(sizeof(*new));
|
struct node *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->deleted = 1;
|
new->deleted = 1;
|
||||||
|
new->srcpos = srcpos_copy(srcpos);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *name_node(struct node *node, char *name)
|
struct node *name_node(struct node *node, const char *name)
|
||||||
{
|
{
|
||||||
assert(node->name == NULL);
|
assert(node->name == NULL);
|
||||||
|
|
||||||
node->name = name;
|
node->name = xstrdup(name);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node *omit_node_if_unused(struct node *node)
|
||||||
|
{
|
||||||
|
node->omit_if_unused = 1;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node *reference_node(struct node *node)
|
||||||
|
{
|
||||||
|
node->is_referenced = 1;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -169,6 +174,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||||
|
|
||||||
old_prop->val = new_prop->val;
|
old_prop->val = new_prop->val;
|
||||||
old_prop->deleted = 0;
|
old_prop->deleted = 0;
|
||||||
|
srcpos_free(old_prop->srcpos);
|
||||||
|
old_prop->srcpos = new_prop->srcpos;
|
||||||
free(new_prop);
|
free(new_prop);
|
||||||
new_prop = NULL;
|
new_prop = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -209,6 +216,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||||
add_child(old_node, new_child);
|
add_child(old_node, new_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
|
||||||
|
|
||||||
/* The new node contents are now merged into the old node. Free
|
/* The new node contents are now merged into the old node. Free
|
||||||
* the new node. */
|
* the new node. */
|
||||||
free(new_node);
|
free(new_node);
|
||||||
|
@ -216,6 +225,37 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||||
return old_node;
|
return old_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
||||||
|
{
|
||||||
|
static unsigned int next_orphan_fragment = 0;
|
||||||
|
struct node *node;
|
||||||
|
struct property *p;
|
||||||
|
struct data d = empty_data;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if (ref[0] == '/') {
|
||||||
|
d = data_add_marker(d, TYPE_STRING, ref);
|
||||||
|
d = data_append_data(d, ref, strlen(ref) + 1);
|
||||||
|
|
||||||
|
p = build_property("target-path", d, NULL);
|
||||||
|
} else {
|
||||||
|
d = data_add_marker(d, REF_PHANDLE, ref);
|
||||||
|
d = data_append_integer(d, 0xffffffff, 32);
|
||||||
|
|
||||||
|
p = build_property("target", d, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
xasprintf(&name, "fragment@%u",
|
||||||
|
next_orphan_fragment++);
|
||||||
|
name_node(new_node, "__overlay__");
|
||||||
|
node = build_node(p, new_node, NULL);
|
||||||
|
name_node(node, name);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
add_child(dt, node);
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
struct node *chain_node(struct node *first, struct node *list)
|
struct node *chain_node(struct node *first, struct node *list)
|
||||||
{
|
{
|
||||||
assert(first->next_sibling == NULL);
|
assert(first->next_sibling == NULL);
|
||||||
|
@ -297,20 +337,76 @@ void delete_node(struct node *node)
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_to_property(struct node *node,
|
void append_to_property(struct node *node,
|
||||||
char *name, const void *data, int len)
|
char *name, const void *data, int len,
|
||||||
|
enum markertype type)
|
||||||
|
{
|
||||||
|
struct property *p;
|
||||||
|
|
||||||
|
p = get_property(node, name);
|
||||||
|
if (!p) {
|
||||||
|
p = build_property(name, empty_data, NULL);
|
||||||
|
add_property(node, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->val = data_add_marker(p->val, type, name);
|
||||||
|
p->val = data_append_data(p->val, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int append_unique_str_to_property(struct node *node,
|
||||||
|
char *name, const char *data, int len)
|
||||||
{
|
{
|
||||||
struct data d;
|
|
||||||
struct property *p;
|
struct property *p;
|
||||||
|
|
||||||
p = get_property(node, name);
|
p = get_property(node, name);
|
||||||
if (p) {
|
if (p) {
|
||||||
d = data_append_data(p->val, data, len);
|
const char *s;
|
||||||
p->val = d;
|
|
||||||
|
if (p->val.len && p->val.val[p->val.len - 1] != '\0')
|
||||||
|
/* The current content doesn't look like a string */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
|
||||||
|
if (strcmp(data, s) == 0)
|
||||||
|
/* data already contained in node.name */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
d = data_append_data(empty_data, data, len);
|
p = build_property(name, empty_data, NULL);
|
||||||
p = build_property(name, d);
|
|
||||||
add_property(node, p);
|
add_property(node, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p->val = data_add_marker(p->val, TYPE_STRING, name);
|
||||||
|
p->val = data_append_data(p->val, data, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
|
||||||
|
{
|
||||||
|
struct property *p;
|
||||||
|
|
||||||
|
p = get_property(node, name);
|
||||||
|
if (p) {
|
||||||
|
const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;
|
||||||
|
|
||||||
|
if (p->val.len % 4 != 0)
|
||||||
|
/* The current content doesn't look like a u32 array */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (v = (const void *)p->val.val; v < val_end; v++) {
|
||||||
|
if (*v == value)
|
||||||
|
/* value already contained */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p = build_property(name, empty_data, NULL);
|
||||||
|
add_property(node, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->val = data_add_marker(p->val, TYPE_UINT32, name);
|
||||||
|
p->val = data_append_data(p->val, &value, 4);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
||||||
|
@ -319,8 +415,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->re.address = address;
|
new->address = address;
|
||||||
new->re.size = size;
|
new->size = size;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
@ -393,7 +489,13 @@ struct property *get_property(struct node *node, const char *propname)
|
||||||
cell_t propval_cell(struct property *prop)
|
cell_t propval_cell(struct property *prop)
|
||||||
{
|
{
|
||||||
assert(prop->val.len == sizeof(cell_t));
|
assert(prop->val.len == sizeof(cell_t));
|
||||||
return fdt32_to_cpu(*((cell_t *)prop->val.val));
|
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
|
||||||
|
}
|
||||||
|
|
||||||
|
cell_t propval_cell_n(struct property *prop, unsigned int n)
|
||||||
|
{
|
||||||
|
assert(prop->val.len / sizeof(cell_t) > n);
|
||||||
|
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *get_property_by_label(struct node *tree, const char *label,
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
||||||
|
@ -455,7 +557,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
|
||||||
for_each_child(node, child)
|
for_each_child(node, child)
|
||||||
if (streq(child->name, nodename))
|
if (streq(child->name, nodename) && !child->deleted)
|
||||||
return child;
|
return child;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -478,7 +580,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
||||||
p = strchr(path, '/');
|
p = strchr(path, '/');
|
||||||
|
|
||||||
for_each_child(tree, child) {
|
for_each_child(tree, child) {
|
||||||
if (p && strneq(path, child->name, p-path))
|
if (p && strprefixeq(path, (size_t)(p - path), child->name))
|
||||||
return get_node_by_path(child, p+1);
|
return get_node_by_path(child, p+1);
|
||||||
else if (!p && streq(path, child->name))
|
else if (!p && streq(path, child->name))
|
||||||
return child;
|
return child;
|
||||||
|
@ -511,7 +613,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
||||||
{
|
{
|
||||||
struct node *child, *node;
|
struct node *child, *node;
|
||||||
|
|
||||||
assert((phandle != 0) && (phandle != -1));
|
if (!phandle_is_valid(phandle)) {
|
||||||
|
assert(generate_fixups);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (tree->phandle == phandle) {
|
if (tree->phandle == phandle) {
|
||||||
if (tree->deleted)
|
if (tree->deleted)
|
||||||
|
@ -530,19 +635,62 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
||||||
|
|
||||||
struct node *get_node_by_ref(struct node *tree, const char *ref)
|
struct node *get_node_by_ref(struct node *tree, const char *ref)
|
||||||
{
|
{
|
||||||
|
struct node *target = tree;
|
||||||
|
const char *label = NULL, *path = NULL;
|
||||||
|
|
||||||
if (streq(ref, "/"))
|
if (streq(ref, "/"))
|
||||||
return tree;
|
return tree;
|
||||||
else if (ref[0] == '/')
|
|
||||||
return get_node_by_path(tree, ref);
|
if (ref[0] == '/')
|
||||||
|
path = ref;
|
||||||
else
|
else
|
||||||
return get_node_by_label(tree, ref);
|
label = ref;
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
const char *slash = strchr(label, '/');
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (slash) {
|
||||||
|
buf = xstrndup(label, slash - label);
|
||||||
|
label = buf;
|
||||||
|
path = slash + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
target = get_node_by_label(tree, label);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
target = get_node_by_path(target, path);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_phandle_property(struct node *node,
|
||||||
|
const char *name, int format)
|
||||||
|
{
|
||||||
|
struct data d;
|
||||||
|
|
||||||
|
if (!(phandle_format & format))
|
||||||
|
return;
|
||||||
|
if (get_property(node, name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
d = data_add_marker(empty_data, TYPE_UINT32, NULL);
|
||||||
|
d = data_append_cell(d, node->phandle);
|
||||||
|
|
||||||
|
add_property(node, build_property(name, d, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t get_node_phandle(struct node *root, struct node *node)
|
cell_t get_node_phandle(struct node *root, struct node *node)
|
||||||
{
|
{
|
||||||
static cell_t phandle = 1; /* FIXME: ick, static local */
|
static cell_t phandle = 1; /* FIXME: ick, static local */
|
||||||
|
|
||||||
if ((node->phandle != 0) && (node->phandle != -1))
|
if (phandle_is_valid(node->phandle))
|
||||||
return node->phandle;
|
return node->phandle;
|
||||||
|
|
||||||
while (get_node_by_phandle(root, phandle))
|
while (get_node_by_phandle(root, phandle))
|
||||||
|
@ -550,17 +698,8 @@ cell_t get_node_phandle(struct node *root, struct node *node)
|
||||||
|
|
||||||
node->phandle = phandle;
|
node->phandle = phandle;
|
||||||
|
|
||||||
if (!get_property(node, "linux,phandle")
|
add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
|
||||||
&& (phandle_format & PHANDLE_LEGACY))
|
add_phandle_property(node, "phandle", PHANDLE_EPAPR);
|
||||||
add_property(node,
|
|
||||||
build_property("linux,phandle",
|
|
||||||
data_append_cell(empty_data, phandle)));
|
|
||||||
|
|
||||||
if (!get_property(node, "phandle")
|
|
||||||
&& (phandle_format & PHANDLE_EPAPR))
|
|
||||||
add_property(node,
|
|
||||||
build_property("phandle",
|
|
||||||
data_append_cell(empty_data, phandle)));
|
|
||||||
|
|
||||||
/* If the node *does* have a phandle property, we must
|
/* If the node *does* have a phandle property, we must
|
||||||
* be dealing with a self-referencing phandle, which will be
|
* be dealing with a self-referencing phandle, which will be
|
||||||
|
@ -599,13 +738,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
|
||||||
a = *((const struct reserve_info * const *)ax);
|
a = *((const struct reserve_info * const *)ax);
|
||||||
b = *((const struct reserve_info * const *)bx);
|
b = *((const struct reserve_info * const *)bx);
|
||||||
|
|
||||||
if (a->re.address < b->re.address)
|
if (a->address < b->address)
|
||||||
return -1;
|
return -1;
|
||||||
else if (a->re.address > b->re.address)
|
else if (a->address > b->address)
|
||||||
return 1;
|
return 1;
|
||||||
else if (a->re.size < b->re.size)
|
else if (a->size < b->size)
|
||||||
return -1;
|
return -1;
|
||||||
else if (a->re.size > b->re.size)
|
else if (a->size > b->size)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -730,18 +869,18 @@ void sort_tree(struct dt_info *dti)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utility helper to avoid code duplication */
|
/* utility helper to avoid code duplication */
|
||||||
static struct node *build_and_name_child_node(struct node *parent, char *name)
|
static struct node *build_and_name_child_node(struct node *parent, const char *name)
|
||||||
{
|
{
|
||||||
struct node *node;
|
struct node *node;
|
||||||
|
|
||||||
node = build_node(NULL, NULL);
|
node = build_node(NULL, NULL, NULL);
|
||||||
name_node(node, xstrdup(name));
|
name_node(node, name);
|
||||||
add_child(parent, node);
|
add_child(parent, node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct node *build_root_node(struct node *dt, char *name)
|
static struct node *build_root_node(struct node *dt, const char *name)
|
||||||
{
|
{
|
||||||
struct node *an;
|
struct node *an;
|
||||||
|
|
||||||
|
@ -795,8 +934,9 @@ static void generate_label_tree_internal(struct dt_info *dti,
|
||||||
|
|
||||||
/* insert it */
|
/* insert it */
|
||||||
p = build_property(l->label,
|
p = build_property(l->label,
|
||||||
data_copy_mem(node->fullpath,
|
data_copy_escape_string(node->fullpath,
|
||||||
strlen(node->fullpath) + 1));
|
strlen(node->fullpath)),
|
||||||
|
NULL);
|
||||||
add_property(an, p);
|
add_property(an, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,27 +971,36 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
|
static int add_fixup_entry(struct dt_info *dti, struct node *fn,
|
||||||
struct node *node, struct property *prop,
|
struct node *node, struct property *prop,
|
||||||
struct marker *m)
|
struct marker *m)
|
||||||
{
|
{
|
||||||
char *entry;
|
char *entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* m->ref can only be a REF_PHANDLE, but check anyway */
|
/* m->ref can only be a REF_PHANDLE, but check anyway */
|
||||||
assert(m->type == REF_PHANDLE);
|
assert(m->type == REF_PHANDLE);
|
||||||
|
|
||||||
|
/* The format only permits fixups for references to label, not
|
||||||
|
* references to path */
|
||||||
|
if (strchr(m->ref, '/'))
|
||||||
|
die("Can't generate fixup for reference to path &{%s}\n",
|
||||||
|
m->ref);
|
||||||
|
|
||||||
/* there shouldn't be any ':' in the arguments */
|
/* there shouldn't be any ':' in the arguments */
|
||||||
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
|
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
|
||||||
die("arguments should not contain ':'\n");
|
die("arguments should not contain ':'\n");
|
||||||
|
|
||||||
xasprintf(&entry, "%s:%s:%u",
|
xasprintf(&entry, "%s:%s:%u",
|
||||||
node->fullpath, prop->name, m->offset);
|
node->fullpath, prop->name, m->offset);
|
||||||
append_to_property(fn, m->ref, entry, strlen(entry) + 1);
|
ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
|
||||||
|
|
||||||
free(entry);
|
free(entry);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generate_fixups_tree_internal(struct dt_info *dti,
|
static int generate_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct node *fn,
|
struct node *fn,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -860,18 +1009,23 @@ static void generate_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct marker *m;
|
struct marker *m;
|
||||||
struct node *refnode;
|
struct node *refnode;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
m = prop->val.markers;
|
m = prop->val.markers;
|
||||||
for_each_marker_of_type(m, REF_PHANDLE) {
|
for_each_marker_of_type(m, REF_PHANDLE) {
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (!refnode)
|
if (!refnode)
|
||||||
add_fixup_entry(dti, fn, node, prop, m);
|
if (add_fixup_entry(dti, fn, node, prop, m))
|
||||||
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child(node, c)
|
for_each_child(node, c)
|
||||||
generate_fixups_tree_internal(dti, fn, c);
|
if (generate_fixups_tree_internal(dti, fn, c))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
|
@ -896,17 +1050,17 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_local_fixup_entry(struct dt_info *dti,
|
static int add_local_fixup_entry(struct dt_info *dti,
|
||||||
struct node *lfn, struct node *node,
|
struct node *lfn, struct node *node,
|
||||||
struct property *prop, struct marker *m,
|
struct property *prop, struct marker *m,
|
||||||
struct node *refnode)
|
struct node *refnode)
|
||||||
{
|
{
|
||||||
struct node *wn, *nwn; /* local fixup node, walk node, new */
|
struct node *wn, *nwn; /* local fixup node, walk node, new */
|
||||||
uint32_t value_32;
|
fdt32_t value_32;
|
||||||
char **compp;
|
char **compp;
|
||||||
int i, depth;
|
int i, depth;
|
||||||
|
|
||||||
/* walk back retreiving depth */
|
/* walk back retrieving depth */
|
||||||
depth = 0;
|
depth = 0;
|
||||||
for (wn = node; wn; wn = wn->parent)
|
for (wn = node; wn; wn = wn->parent)
|
||||||
depth++;
|
depth++;
|
||||||
|
@ -921,18 +1075,16 @@ static void add_local_fixup_entry(struct dt_info *dti,
|
||||||
/* walk the path components creating nodes if they don't exist */
|
/* walk the path components creating nodes if they don't exist */
|
||||||
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
|
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
|
||||||
/* if no node exists, create it */
|
/* if no node exists, create it */
|
||||||
nwn = get_subnode(wn, compp[i]);
|
nwn = build_root_node(wn, compp[i]);
|
||||||
if (!nwn)
|
|
||||||
nwn = build_and_name_child_node(wn, compp[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(compp);
|
free(compp);
|
||||||
|
|
||||||
value_32 = cpu_to_fdt32(m->offset);
|
value_32 = cpu_to_fdt32(m->offset);
|
||||||
append_to_property(wn, prop->name, &value_32, sizeof(value_32));
|
return append_unique_u32_to_property(wn, prop->name, value_32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generate_local_fixups_tree_internal(struct dt_info *dti,
|
static int generate_local_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct node *lfn,
|
struct node *lfn,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -941,21 +1093,26 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct marker *m;
|
struct marker *m;
|
||||||
struct node *refnode;
|
struct node *refnode;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
m = prop->val.markers;
|
m = prop->val.markers;
|
||||||
for_each_marker_of_type(m, REF_PHANDLE) {
|
for_each_marker_of_type(m, REF_PHANDLE) {
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (refnode)
|
if (refnode)
|
||||||
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
|
if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
|
||||||
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child(node, c)
|
for_each_child(node, c)
|
||||||
generate_local_fixups_tree_internal(dti, lfn, c);
|
if (generate_local_fixups_tree_internal(dti, lfn, c))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
|
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
|
||||||
{
|
{
|
||||||
if (!any_label_tree(dti, dti->dt))
|
if (!any_label_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
|
@ -963,18 +1120,22 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
|
||||||
dti->dt, allocph);
|
dti->dt, allocph);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_fixups_tree(struct dt_info *dti, char *name)
|
void generate_fixups_tree(struct dt_info *dti, const char *name)
|
||||||
{
|
{
|
||||||
if (!any_fixup_tree(dti, dti->dt))
|
if (!any_fixup_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
|
if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
|
||||||
dti->dt);
|
fprintf(stderr,
|
||||||
|
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
|
||||||
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_local_fixups_tree(struct dt_info *dti, char *name)
|
void generate_local_fixups_tree(struct dt_info *dti, const char *name)
|
||||||
{
|
{
|
||||||
if (!any_local_fixup_tree(dti, dti->dt))
|
if (!any_local_fixup_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
|
if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
|
||||||
dti->dt);
|
fprintf(stderr,
|
||||||
|
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
|
||||||
|
name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
project('dtc', 'c',
|
||||||
|
version: files('VERSION.txt'),
|
||||||
|
license: ['GPL2+', 'BSD-2'],
|
||||||
|
default_options: ['werror=true', 'default_library=both'],
|
||||||
|
meson_version: '>=0.57.0'
|
||||||
|
)
|
||||||
|
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
|
||||||
|
add_project_arguments(
|
||||||
|
cc.get_supported_arguments([
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wcast-qual',
|
||||||
|
'-Wnested-externs',
|
||||||
|
'-Wstrict-prototypes',
|
||||||
|
'-Wmissing-prototypes',
|
||||||
|
'-Wredundant-decls',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wsuggest-attribute=format',
|
||||||
|
'-Wwrite-strings',
|
||||||
|
]),
|
||||||
|
language: 'c'
|
||||||
|
)
|
||||||
|
|
||||||
|
add_project_arguments(
|
||||||
|
'-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
|
||||||
|
language: 'c'
|
||||||
|
)
|
||||||
|
|
||||||
|
yamltree = 'yamltree.c'
|
||||||
|
yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'))
|
||||||
|
if not yaml.found()
|
||||||
|
add_project_arguments('-DNO_YAML', language: 'c')
|
||||||
|
yamltree = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
valgrind = dependency('valgrind', required: get_option('valgrind'))
|
||||||
|
if not valgrind.found()
|
||||||
|
add_project_arguments('-DNO_VALGRIND', language: 'c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
py = import('python')
|
||||||
|
py = py.find_installation(required: get_option('python'))
|
||||||
|
swig = find_program('swig', required: get_option('python'))
|
||||||
|
pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false
|
||||||
|
wheel_only = get_option('wheel-only')
|
||||||
|
|
||||||
|
version_gen_h = vcs_tag(
|
||||||
|
command: ['git', 'describe', '--dirty=+'],
|
||||||
|
input: 'version_gen.h.in',
|
||||||
|
output: 'version_gen.h',
|
||||||
|
)
|
||||||
|
|
||||||
|
subdir('libfdt')
|
||||||
|
|
||||||
|
dtc_tools = []
|
||||||
|
util_dep = declare_dependency(
|
||||||
|
sources: ['util.c', version_gen_h],
|
||||||
|
include_directories: '.',
|
||||||
|
dependencies: libfdt_dep
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_option('tools') and not wheel_only
|
||||||
|
flex = find_program('flex', required: true)
|
||||||
|
bison = find_program('bison', required: true)
|
||||||
|
|
||||||
|
lgen = generator(
|
||||||
|
flex,
|
||||||
|
output: '@PLAINNAME@.lex.c',
|
||||||
|
arguments: ['-o', '@OUTPUT@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
pgen = generator(
|
||||||
|
bison,
|
||||||
|
output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
|
||||||
|
arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
if cc.check_header('fnmatch.h')
|
||||||
|
dtc_tools += executable(
|
||||||
|
'convert-dtsv0',
|
||||||
|
[
|
||||||
|
lgen.process('convert-dtsv0-lexer.l'),
|
||||||
|
'srcpos.c',
|
||||||
|
],
|
||||||
|
dependencies: util_dep,
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
|
dtc_tools += executable(
|
||||||
|
'dtc',
|
||||||
|
[
|
||||||
|
lgen.process('dtc-lexer.l'),
|
||||||
|
pgen.process('dtc-parser.y'),
|
||||||
|
'checks.c',
|
||||||
|
'data.c',
|
||||||
|
'dtc.c',
|
||||||
|
'flattree.c',
|
||||||
|
'fstree.c',
|
||||||
|
'livetree.c',
|
||||||
|
'srcpos.c',
|
||||||
|
'treesource.c',
|
||||||
|
yamltree,
|
||||||
|
],
|
||||||
|
dependencies: [util_dep, yaml],
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
|
||||||
|
dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'dtdiff',
|
||||||
|
install_dir: get_option('bindir'),
|
||||||
|
install_mode: 'rwxr-xr-x',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach e: dtc_tools
|
||||||
|
meson.override_find_program(e.name(), e)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
if pylibfdt_enabled
|
||||||
|
subdir('pylibfdt')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('tests')
|
||||||
|
subdir('tests')
|
||||||
|
endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
option('tools', type: 'boolean', value: true,
|
||||||
|
description: 'Build tools')
|
||||||
|
option('assume-mask', type: 'integer', value: 0,
|
||||||
|
description: 'Control the assumptions made (e.g. risking security issues) in the code.')
|
||||||
|
option('yaml', type: 'feature', value: 'auto',
|
||||||
|
description: 'YAML support')
|
||||||
|
option('valgrind', type: 'feature', value: 'auto',
|
||||||
|
description: 'Valgrind support')
|
||||||
|
option('python', type: 'feature', value: 'auto',
|
||||||
|
description: 'Build pylibfdt Python library')
|
||||||
|
option('tests', type: 'boolean', value: true,
|
||||||
|
description: 'Build tests')
|
||||||
|
option('wheel-only', type: 'boolean', value: false,
|
||||||
|
description: 'building from meson-python')
|
|
@ -0,0 +1,3 @@
|
||||||
|
libfdt.py
|
||||||
|
*.pyc
|
||||||
|
libfdt_wrap.c
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
||||||
|
libfdt_c = custom_target(
|
||||||
|
'swig',
|
||||||
|
input: 'libfdt.i',
|
||||||
|
output: ['libfdt.c', 'libfdt.py'],
|
||||||
|
install: true,
|
||||||
|
install_dir: [false, py.get_install_dir(pure: false)],
|
||||||
|
command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
|
nowarn_gen = cc.get_supported_arguments(
|
||||||
|
'-Wno-cast-qual',
|
||||||
|
'-Wno-missing-prototypes',
|
||||||
|
'-Wno-redundant-decls',
|
||||||
|
)
|
||||||
|
pylibfdt = py.extension_module(
|
||||||
|
'_libfdt',
|
||||||
|
libfdt_c,
|
||||||
|
c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen,
|
||||||
|
dependencies: [libfdt_dep, py.dependency()],
|
||||||
|
install: true,
|
||||||
|
)
|
|
@ -0,0 +1,33 @@
|
||||||
|
[build-system]
|
||||||
|
build-backend = 'mesonpy'
|
||||||
|
requires = ['meson-python']
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = 'libfdt'
|
||||||
|
authors = [
|
||||||
|
{name = 'Simon Glass', email = 'sjg@chromium.org'},
|
||||||
|
]
|
||||||
|
classifiers = [
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'License :: OSI Approved :: BSD License',
|
||||||
|
'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
|
||||||
|
'Operating System :: OS Independent',
|
||||||
|
]
|
||||||
|
description = 'Python binding for libfdt'
|
||||||
|
readme = 'README.md'
|
||||||
|
requires-python = '>=3.8'
|
||||||
|
dynamic = ['version']
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git'
|
||||||
|
|
||||||
|
# These arguments are applied only when building a redistributable binary wheel
|
||||||
|
# for uploading to PyPI. We don't want to install libraries (or headers /
|
||||||
|
# pkgconfig files / executables) that clash with system C installs, so we
|
||||||
|
# disable everything other than the python bindings themselves, and build the
|
||||||
|
# python C-API extension using static linkage to avoid juggling "libdir" /
|
||||||
|
# LD_LIBRARY_PATH / RPATH around. When building both the C library and the
|
||||||
|
# python bindings for a distro, `meson setup` will still default to shared
|
||||||
|
# libraries.
|
||||||
|
[tool.meson-python.args]
|
||||||
|
setup = ['-Ddefault_library=static', '-Dwheel-only=true']
|
|
@ -1 +0,0 @@
|
||||||
v*.tar.gz
|
|
|
@ -1,67 +0,0 @@
|
||||||
include Makefile.common
|
|
||||||
|
|
||||||
REDHAT:=$(shell pwd)
|
|
||||||
SCRIPTS:=$(REDHAT)/scripts
|
|
||||||
RPMBUILD:=$(REDHAT)/rpmbuild
|
|
||||||
|
|
||||||
# Hide command calls without debug option
|
|
||||||
ifeq ($(DEBUG),1)
|
|
||||||
DS=
|
|
||||||
else
|
|
||||||
DS=@
|
|
||||||
endif
|
|
||||||
|
|
||||||
BREW_OPTIONS:=$(BREW_FLAGS) --scratch
|
|
||||||
|
|
||||||
# Hide progress bar in scripts
|
|
||||||
ifeq ($(NOPROGRESS),1)
|
|
||||||
BREW_OPTIONS:=$(BREW_OPTIONS) --noprogress
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Do not wait for build finish
|
|
||||||
ifeq ($(NOWAIT),1)
|
|
||||||
BREW_OPTIONS:=$(BREW_OPTIONS) --nowait
|
|
||||||
endif
|
|
||||||
|
|
||||||
# create an empty localversion file if you don't want a local buildid
|
|
||||||
ifneq ($(NOLOCALVERSION),1)
|
|
||||||
ifeq ($(LOCALVERSION),)
|
|
||||||
LOCALVERSION=$(shell cat ../localversion 2>/dev/null)
|
|
||||||
endif
|
|
||||||
ifeq ($(LOCALVERSION),)
|
|
||||||
LOCALVERSION:=.test
|
|
||||||
else
|
|
||||||
LOCALVERSION:=.$(LOCALVERSION)
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
LOCALVERSION:=
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: rh-brew rh-srpm rh-prep rh-help rh-clean-sources
|
|
||||||
all: rh-help
|
|
||||||
|
|
||||||
rh-clean-sources:
|
|
||||||
$(DS)for i in $(RPMBUILD)/SOURCES/*; do \
|
|
||||||
rm -f $$i; \
|
|
||||||
done; \
|
|
||||||
|
|
||||||
rh-prep: rh-clean-sources
|
|
||||||
$(DS)if [ -n "$(SOURCES_FILELIST)" ]; then \
|
|
||||||
echo "Copying Sources: $(SOURCES_FILELIST)"; \
|
|
||||||
cp $(SOURCES_FILELIST) $(RPMBUILD)/SOURCES; \
|
|
||||||
fi
|
|
||||||
$(DS)$(SCRIPTS)/process-patches.sh "$(SCRIPTS)" "$(NAME)" "$(VERSION)" "$(RELEASE)" "$(DATE)" "$(COMMIT)" "$(TARFILE)" "$(TARURL)" "$(SPECFILE)" "$(BUILD_DIR)" "$(MARKER)" "$(LOCALVERSION)" "$(RHEV)" "$(ZRELEASE)"
|
|
||||||
|
|
||||||
rh-srpm: rh-prep
|
|
||||||
$(DS)rpmbuild --define "_sourcedir $(RPMBUILD)/SOURCES" --define "_builddir $(RPMBUILD)/BUILD" --define "_srcrpmdir $(RPMBUILD)/SRPMS" --define "_rpmdir $(RPMBUILD)/RPMS" --define "_specdir $(RPMBUILD)/SPECS" --define "dist $(DIST)" --nodeps -bs $(RPMBUILD)/SPECS/$(SPECFILE)
|
|
||||||
|
|
||||||
rh-brew: rh-srpm
|
|
||||||
@echo "Build $(SRPM_NAME)$(LOCALVERSION).src.rpm as $(BUILD_TARGET)"
|
|
||||||
$(DS)brew build $(BREW_OPTIONS) $(BUILD_TARGET) $(RPMBUILD)/SRPMS/$(SRPM_NAME)$(LOCALVERSION).src.rpm
|
|
||||||
|
|
||||||
rh-help:
|
|
||||||
@echo "rh-brew: Build package on brew"
|
|
||||||
@echo "rh-srpm: Prepare srpm package"
|
|
||||||
@echo "rh-prep: Prepare sources and spec file in rpmbuild/"
|
|
||||||
@echo "rh-help: Print this help"
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
UNAME:=dtc
|
|
||||||
NAME:=dtc
|
|
||||||
RHEV:=0
|
|
||||||
VERSION:=1.4.3
|
|
||||||
DATE:=
|
|
||||||
COMMIT:=
|
|
||||||
RELEASE:=1
|
|
||||||
ZRELEASE:=
|
|
||||||
RELEASE_SEPARATOR:=-
|
|
||||||
|
|
||||||
TARFILE:=v$(VERSION).tar.gz
|
|
||||||
TARURL:=https://github.com/dgibson/dtc/archive/v1.4.3.tar.gz
|
|
||||||
TARSHA1:=cef129e4444a52dcd704c08c6375fa3894954048
|
|
||||||
MARKER:=fa8bc7f928ac25f23532afc8beb2073efc8fb063
|
|
||||||
SOURCES_FILELIST:=
|
|
||||||
|
|
||||||
SPECFILE:=$(NAME).spec
|
|
||||||
DIST:=.el7
|
|
||||||
BUILD_TARGET:=rhel-7.3-candidate
|
|
||||||
|
|
||||||
ifeq ($(RHEV),1)
|
|
||||||
NAME_SUFFIX:=-rhev
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(VERSION),)
|
|
||||||
BUILD_DIR:=$(UNAME)-$(VERSION)
|
|
||||||
SRPM_NAME:=$(NAME)$(NAME_SUFFIX)-$(VERSION)$(RELEASE_SEPARATOR)$(RELEASE)$(DIST)
|
|
||||||
else
|
|
||||||
BUILD_DIR:=$(UNAME)-$(GITCOMMIT
|
|
||||||
SRPM_NAME:=$(NAME)$(NAME_SUFFIX)-$(DATE)-$(RELEASE).git$(COMMIT)$(DIST)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(ZRELEASE),)
|
|
||||||
SRPM_NAME:=$(SRPM_NAME).$(ZRELEASE)
|
|
||||||
endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
Name: dtc
|
|
||||||
Version: %%VERSION%%
|
|
||||||
Release: %%RELEASE%%%{?dist}%%ZRELEASE%%%%LOCALVERSION%%
|
|
||||||
Summary: Device Tree Compiler
|
|
||||||
Group: Development/Tools
|
|
||||||
License: GPLv2+
|
|
||||||
URL: https://github.com/dgibson/dtc
|
|
||||||
Source: https://github.com/dgibson/dtc/archive/v%{version}.tar.gz
|
|
||||||
|
|
||||||
%%PATCHLIST%%
|
|
||||||
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|
||||||
|
|
||||||
BuildRequires: flex, bison
|
|
||||||
ExclusiveArch: %{power64} aarch64
|
|
||||||
|
|
||||||
%description
|
|
||||||
The Device Tree Compiler generates flattened Open Firmware style device trees
|
|
||||||
for use with PowerPC machines that lack an Open Firmware implementation
|
|
||||||
|
|
||||||
%package -n libfdt
|
|
||||||
Summary: Device tree library
|
|
||||||
Group: Development/Libraries
|
|
||||||
|
|
||||||
%description -n libfdt
|
|
||||||
libfdt is a library to process Open Firmware style device trees on various
|
|
||||||
architectures.
|
|
||||||
|
|
||||||
%package -n libfdt-devel
|
|
||||||
Summary: Development headers for device tree library
|
|
||||||
Group: Development/Libraries
|
|
||||||
Requires: libfdt = %{version}-%{release}
|
|
||||||
|
|
||||||
%description -n libfdt-devel
|
|
||||||
This package provides development files for libfdt
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup -q -n dtc-%{version}
|
|
||||||
|
|
||||||
%%PATCHAPPLY%%
|
|
||||||
|
|
||||||
%build
|
|
||||||
make %{?_smp_mflags}
|
|
||||||
|
|
||||||
%install
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
make install DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr LIBDIR=%{_libdir}
|
|
||||||
rm -rf $RPM_BUILD_ROOT/%{_libdir}/*.a
|
|
||||||
|
|
||||||
# we don't want or need ftdump, so drop
|
|
||||||
rm -f $RPM_BUILD_ROOT/%{_bindir}/ftdump
|
|
||||||
|
|
||||||
%clean
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root,-)
|
|
||||||
%doc GPL
|
|
||||||
%{_bindir}/*
|
|
||||||
|
|
||||||
%files -n libfdt
|
|
||||||
%defattr(-,root,root,-)
|
|
||||||
%doc GPL
|
|
||||||
%{_libdir}/libfdt-%{version}.so
|
|
||||||
%{_libdir}/libfdt.so.*
|
|
||||||
|
|
||||||
%files -n libfdt-devel
|
|
||||||
%defattr(-,root,root,-)
|
|
||||||
%{_libdir}/libfdt.so
|
|
||||||
%{_includedir}/*
|
|
||||||
|
|
||||||
%post -n libfdt -p /sbin/ldconfig
|
|
||||||
|
|
||||||
%postun -n libfdt -p /sbin/ldconfig
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Mon Mar 06 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.3-1
|
|
||||||
- Rebase to 1.4.3 [bz#1427157]
|
|
||||||
- Resolves: bz#1427157
|
|
||||||
(package libfdt 1.4.3, when available)
|
|
||||||
|
|
||||||
* Tue Aug 19 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.0-2
|
|
||||||
- Update power macro for ppc64le
|
|
||||||
|
|
||||||
* Fri Jul 25 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.0-1
|
|
||||||
- Initial version
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def filter_file(inf):
|
|
||||||
ts_chunkstart = re.compile("diff --git ")
|
|
||||||
ts_redhat = re.compile(".*\/redhat\/")
|
|
||||||
ts_gitfile = re.compile(".*\/\.git")
|
|
||||||
skip = False
|
|
||||||
f = open(inf,"r")
|
|
||||||
for line in f.readlines():
|
|
||||||
if ts_chunkstart.match(line) is not None:
|
|
||||||
if ts_redhat.match(line) is not None or ts_gitfile.match(line) is not None:
|
|
||||||
skip = True
|
|
||||||
else:
|
|
||||||
skip = False
|
|
||||||
if skip == False:
|
|
||||||
sys.stdout.write(line)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print("Usage: %s <filename>" % sys.argv[0])
|
|
||||||
exit(1)
|
|
||||||
filter_file(sys.argv[1])
|
|
||||||
|
|
|
@ -1,327 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# See $desc, below, for program description
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# Author(s):
|
|
||||||
# Jeff Cody <jcody@redhat.com>
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of the GNU General Public License as published by the Free Software
|
|
||||||
# Foundation; under version 2 of the license
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
# details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along with
|
|
||||||
# this program; if not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
|
|
||||||
#
|
|
||||||
|
|
||||||
set -C -u -e
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
desc="
|
|
||||||
$0 compares the commits in a specified git range, with the corresponding
|
|
||||||
upstream commit. This assumes that you have both the downstream and
|
|
||||||
upstream repositories added as remotes in your git repo.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
$0 -r qemu-kvm-0.12.1.2-2.370.el6..my_feature_branch -u v1.5.0
|
|
||||||
|
|
||||||
Ouput key:
|
|
||||||
[----] Indicates the patches upstream and downstream are identical
|
|
||||||
[####] Indicates the number of differences (#### is substituted)
|
|
||||||
[down] Indicates the patch only exists downstream"
|
|
||||||
|
|
||||||
def_upstream="v1.7.0"
|
|
||||||
def_diffprog=meld
|
|
||||||
def_range="HEAD^!"
|
|
||||||
def_color='y'
|
|
||||||
def_pause='y'
|
|
||||||
def_sensitivity=0
|
|
||||||
def_summary='n'
|
|
||||||
|
|
||||||
upstream=`git config backport-diff.upstream || true`
|
|
||||||
diffprog=`git config backport-diff.diffprog || true`
|
|
||||||
range=`git config backport-diff.range || true`
|
|
||||||
color=`git config backport-diff.color || true`
|
|
||||||
pause=`git config backport-diff.pause || true`
|
|
||||||
sensitivity=`git config backport-diff.sensitivity || true`
|
|
||||||
summary=`git config backport-diff.summary || true`
|
|
||||||
|
|
||||||
if [[ -z "$upstream" ]]
|
|
||||||
then
|
|
||||||
upstream=$def_upstream
|
|
||||||
git config backport-diff.upstream $upstream || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$diffprog" ]]
|
|
||||||
then
|
|
||||||
diffprog=$def_diffprog
|
|
||||||
git config backport-diff.diffprog $diffprog || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$range" ]]
|
|
||||||
then
|
|
||||||
range=$def_range
|
|
||||||
git config backport-diff.range $range || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$color" ]]
|
|
||||||
then
|
|
||||||
color=$def_color
|
|
||||||
git config backport-diff.color $color || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$pause" ]]
|
|
||||||
then
|
|
||||||
pause=$def_pause
|
|
||||||
git config backport-diff.pause $pause || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$sensitivity" ]]
|
|
||||||
then
|
|
||||||
sensitivity=$def_sensitivity
|
|
||||||
git config backport-diff.sensitivity $sensitivity || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$summary" ]]
|
|
||||||
then
|
|
||||||
summary=$def_summary
|
|
||||||
git config backport-diff.summary $summary || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo ""
|
|
||||||
echo "$0 [OPTIONS]"
|
|
||||||
echo "$desc"
|
|
||||||
echo ""
|
|
||||||
echo "OPTIONS:"
|
|
||||||
echo " -r git range
|
|
||||||
optional; default is '$range'
|
|
||||||
"
|
|
||||||
echo " -u upstream git tag / branch / id
|
|
||||||
optional; default is '$upstream'
|
|
||||||
"
|
|
||||||
echo " -n do not use colors
|
|
||||||
"
|
|
||||||
echo " -d diff program to use
|
|
||||||
optional; default is '$diffprog'
|
|
||||||
"
|
|
||||||
echo " -p do not pause when viewing diffs
|
|
||||||
"
|
|
||||||
echo " -s sensitivity level of diff compares
|
|
||||||
0: only show functional code differences
|
|
||||||
1: show (0) + contextual differences
|
|
||||||
2+: offer to compare all patches, regardless of any differences
|
|
||||||
"
|
|
||||||
echo " -S summary only (no diff viewing)
|
|
||||||
"
|
|
||||||
echo " -h help"
|
|
||||||
echo ""
|
|
||||||
echo "You can set each of the default options using git-config:"
|
|
||||||
echo " git config backport-diff.upstream"
|
|
||||||
echo " git config backport-diff.diffprog"
|
|
||||||
echo " git config backport-diff.range"
|
|
||||||
echo " git config backport-diff.color"
|
|
||||||
echo " git config backport-diff.pause"
|
|
||||||
echo " git config backport-diff.summary"
|
|
||||||
}
|
|
||||||
|
|
||||||
while getopts ":r:u:nd:phs:S" opt
|
|
||||||
do
|
|
||||||
case $opt in
|
|
||||||
r) range=$OPTARG
|
|
||||||
;;
|
|
||||||
u) upstream=$OPTARG
|
|
||||||
;;
|
|
||||||
n) color='n'
|
|
||||||
;;
|
|
||||||
d) diffprog=$OPTARG
|
|
||||||
;;
|
|
||||||
p) pause='n'
|
|
||||||
;;
|
|
||||||
s) sensitivity=$OPTARG
|
|
||||||
if ! [[ "$sensitivity" =~ ^[0-9]+$ ]]
|
|
||||||
then
|
|
||||||
echo "Invalid argument for -s" >&2
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
S) summary='y'
|
|
||||||
;;
|
|
||||||
h) usage
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
\?) echo "Unknown option: -$OPTARG" >&2
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $color == 'y' ]]
|
|
||||||
then
|
|
||||||
bold=$(tput bold)
|
|
||||||
color1=$(tput setaf 1)
|
|
||||||
color2=$(tput setaf 2)
|
|
||||||
color3=$(tput setaf 3)
|
|
||||||
color4=$(tput setaf 4)
|
|
||||||
color5=$(tput setaf 5)
|
|
||||||
color6=$(tput setaf 6)
|
|
||||||
color7=$(tput setaf 7)
|
|
||||||
reset=$(tput sgr0)
|
|
||||||
else
|
|
||||||
bold=
|
|
||||||
color1=
|
|
||||||
color2=
|
|
||||||
color3=
|
|
||||||
color4=
|
|
||||||
color5=
|
|
||||||
color6=
|
|
||||||
color7=
|
|
||||||
reset=
|
|
||||||
fi
|
|
||||||
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo $reset
|
|
||||||
}
|
|
||||||
|
|
||||||
total=`git rev-list "$range" |wc -l`
|
|
||||||
|
|
||||||
# verify the upstream exists
|
|
||||||
upstream_valid='n'
|
|
||||||
# branch
|
|
||||||
if git show-ref --quiet --verify refs/heads/${upstream}
|
|
||||||
then
|
|
||||||
upstream_valid='y'
|
|
||||||
# tag
|
|
||||||
elif git show-ref --quiet --verify refs/tags/${upstream}
|
|
||||||
then
|
|
||||||
upstream_valid='y'
|
|
||||||
# remote branch
|
|
||||||
elif git show-ref --quiet --verify refs/remotes/${upstream}
|
|
||||||
then
|
|
||||||
upstream_valid='y'
|
|
||||||
# commit id
|
|
||||||
elif git rev-list --max-count=1 --quiet $upstream >/dev/null 2>&1
|
|
||||||
then
|
|
||||||
upstream_valid='y'
|
|
||||||
fi
|
|
||||||
|
|
||||||
numdiff=0
|
|
||||||
label=
|
|
||||||
subjlist=
|
|
||||||
cnt=0
|
|
||||||
compare_git()
|
|
||||||
{
|
|
||||||
echo "Key:"
|
|
||||||
printf "[----] : patches are identical\n"
|
|
||||||
printf "[${bold}####${reset}] : number of functional differences between upstream/downstream patch\n"
|
|
||||||
printf "[${bold}${color1}down${reset}] : patch is downstream-only\n"
|
|
||||||
printf "The flags [${bold}FC${reset}] indicate (F)unctional and (C)ontextual differences, respectively\n\n"
|
|
||||||
# don't pipe the git job into read, to avoid subshells
|
|
||||||
while read hashsubj
|
|
||||||
do
|
|
||||||
let cnt=$cnt+1;
|
|
||||||
subj=${hashsubj:40}
|
|
||||||
downhash=${hashsubj:0:40}
|
|
||||||
# A little bit hackish, but find the match by looking at upstream
|
|
||||||
# subject lines, and using the last one. Not all backports contain
|
|
||||||
# the phrase "cherry-pick", so we can't really try and find the
|
|
||||||
# upstream hash from that...
|
|
||||||
uphash=`git log $upstream --pretty=format:"%H" --fixed-strings --grep="${subj}" |tail -n 1`
|
|
||||||
if [[ -n "$uphash" ]]
|
|
||||||
then
|
|
||||||
numdiff=`diff -u <(git diff $uphash^! |egrep ^[-+])\
|
|
||||||
<(git diff $downhash^! |egrep ^[-+])\
|
|
||||||
| egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true`
|
|
||||||
# for contextual diff checking, we will ignore hashes and line number offsets
|
|
||||||
condiff=`diff -u <(git diff $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
|
|
||||||
<(git diff $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
|
|
||||||
| egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true`
|
|
||||||
f="-"
|
|
||||||
c="-"
|
|
||||||
if [[ $sensitivity -gt 1 ]]
|
|
||||||
then
|
|
||||||
showdiff=1
|
|
||||||
else
|
|
||||||
showdiff=0
|
|
||||||
fi
|
|
||||||
if [[ $condiff -ne 0 ]]
|
|
||||||
then
|
|
||||||
c=${bold}C${reset}
|
|
||||||
if [[ $sensitivity -gt 0 ]]
|
|
||||||
then
|
|
||||||
showdiff=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [[ $numdiff -ne 0 ]]
|
|
||||||
then
|
|
||||||
f=${bold}F${reset}
|
|
||||||
showdiff=1
|
|
||||||
printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$subj"
|
|
||||||
else
|
|
||||||
printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$subj"
|
|
||||||
fi
|
|
||||||
if [[ $showdiff -eq 1 ]]
|
|
||||||
then
|
|
||||||
if [[ $diffprog == "meld" ]]
|
|
||||||
then
|
|
||||||
label="--label=\"Patch #$cnt: $subj\" --label=\" \""
|
|
||||||
fi
|
|
||||||
subjlist[$cnt]=$subj
|
|
||||||
exe[$cnt]="${label} <(git show $uphash^!) <(git show $downhash^!) 2>/dev/null"
|
|
||||||
shortexe[$cnt]="<(git show ${uphash:0:7}^\!) <(git show ${downhash:0:7}^\!)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$subj"
|
|
||||||
fi
|
|
||||||
done < <(git log --pretty=tformat:"%H%s" --reverse $range)
|
|
||||||
}
|
|
||||||
|
|
||||||
show_diff()
|
|
||||||
{
|
|
||||||
echo "Do you want to view the diffs using ${bold}${diffprog}${reset}? y/[n]: "
|
|
||||||
read -n 1 view
|
|
||||||
echo ""
|
|
||||||
if [[ "$view" == "y" ]]
|
|
||||||
then
|
|
||||||
for idx in ${!exe[*]}
|
|
||||||
do
|
|
||||||
if [[ $pause == 'y' ]]
|
|
||||||
then
|
|
||||||
echo "Press [Enter] to view diff(diff) of ${idx}/${total}: ${bold}${color4}${subjlist[$idx]}${reset}"
|
|
||||||
read
|
|
||||||
else
|
|
||||||
echo "Viewing diff(diff) of ${idx}/${total}: ${bold}${color4}${subjlist[$idx]}${reset}"
|
|
||||||
fi
|
|
||||||
eval ${diffprog} ${exe[$idx]} || true
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $upstream_valid != 'y' ]]
|
|
||||||
then
|
|
||||||
echo "Upstream $upstream is not valid (does not exist)!"
|
|
||||||
echo "Do you need to add the remote upstream repo?"
|
|
||||||
exit 2
|
|
||||||
fi >&2
|
|
||||||
|
|
||||||
compare_git
|
|
||||||
|
|
||||||
if [[ $summary != 'y' ]]
|
|
||||||
then
|
|
||||||
show_diff
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${!shortexe[*]} != '' ]]
|
|
||||||
then
|
|
||||||
echo ""
|
|
||||||
echo "To view diffs later, you may run:"
|
|
||||||
for idx in ${!shortexe[*]}
|
|
||||||
do
|
|
||||||
printf "%03d/$total: '${diffprog} ${shortexe[$idx]}'\n" $idx
|
|
||||||
done
|
|
||||||
fi
|
|
|
@ -1,215 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# See $desc, below, for program description
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# Author(s):
|
|
||||||
# Jeff Cody <jcody@redhat.com>
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of the GNU General Public License as published by the Free Software
|
|
||||||
# Foundation; under version 2 of the license
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
# details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along with
|
|
||||||
# this program; if not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
|
|
||||||
#
|
|
||||||
|
|
||||||
set -C -u -e
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
desc="
|
|
||||||
$0 iterates through a git commit range, and performs the
|
|
||||||
following on each commit:
|
|
||||||
- git checkout
|
|
||||||
- make clean
|
|
||||||
- configure
|
|
||||||
- make
|
|
||||||
|
|
||||||
It will also optionally perform a git-reset and git-clean between
|
|
||||||
checkouts, if requested via the '-f' option.
|
|
||||||
|
|
||||||
The script will exit and report on first error on any of the above steps,
|
|
||||||
(except no error checking is performed on 'make clean')
|
|
||||||
|
|
||||||
NOTE: While executing, the script will checkout out each commit
|
|
||||||
in the range in the current git tree. On exit, the HEAD
|
|
||||||
at the time the script was called is checked out"
|
|
||||||
|
|
||||||
|
|
||||||
# default range is the last commit
|
|
||||||
def_range="HEAD^!"
|
|
||||||
def_config_opt="--target-list=x86_64-softmmu"
|
|
||||||
# you may want to have make perform multiple jobs, e.g. -j4
|
|
||||||
# this is ommitted as the default in case the project makefile
|
|
||||||
# is not safe for parallel make processes
|
|
||||||
def_make_opt=""
|
|
||||||
def_log="output-$$.log"
|
|
||||||
def_logdir=""
|
|
||||||
force_clean='n'
|
|
||||||
|
|
||||||
logfile=$def_log
|
|
||||||
range=`git config compile-check.range || true`
|
|
||||||
config_opt=`git config compile-check.configopt || true`
|
|
||||||
make_opt=`git config compile-check.makeopt || true`
|
|
||||||
logdir=`git config compile-check.logdir || true`
|
|
||||||
|
|
||||||
if [[ -z "$range" ]]
|
|
||||||
then
|
|
||||||
range=$def_range
|
|
||||||
git config compile-check.range $range || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$config_opt" ]]
|
|
||||||
then
|
|
||||||
config_opt=$def_config_opt
|
|
||||||
git config compile-check.configopt $config_opt || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$make_opt" ]]
|
|
||||||
then
|
|
||||||
make_opt=$def_make_opt
|
|
||||||
git config compile-check.makeopt $make_opt || true
|
|
||||||
fi
|
|
||||||
if [[ -z "$logdir" ]]
|
|
||||||
then
|
|
||||||
logdir=$def_logdir
|
|
||||||
git config compile-check.logdir $logdir || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo ""
|
|
||||||
echo "$0 [OPTIONS]"
|
|
||||||
echo "$desc"
|
|
||||||
echo ""
|
|
||||||
echo "OPTIONS:"
|
|
||||||
echo " -r git range
|
|
||||||
optional; default is '$range'
|
|
||||||
"
|
|
||||||
echo " -c configure options
|
|
||||||
optional; default is '$config_opt'
|
|
||||||
"
|
|
||||||
echo " -m make options
|
|
||||||
optional; default is '$make_opt'
|
|
||||||
"
|
|
||||||
echo " -d log dir
|
|
||||||
optional; default is '$logdir'
|
|
||||||
"
|
|
||||||
echo " -l log filename
|
|
||||||
optional; default is output-PROCID, where PROCID is the bash process id
|
|
||||||
note: you may specify a full path for the log filename here, and exclude the
|
|
||||||
-d option.
|
|
||||||
"
|
|
||||||
echo " -f force a git reset and clean
|
|
||||||
this will cause a 'git reset --hard; git clean -fdx' to be run between checkouts.
|
|
||||||
!! WARNING: This may cause data loss in your git tree.
|
|
||||||
READ the git-clean and git-reset man pages and make
|
|
||||||
sure you understand the implications of
|
|
||||||
'git clean -fdx' and 'git reset --hard' before using !!
|
|
||||||
If you specify this option, make sure the logfile falls outside of the tree.
|
|
||||||
"
|
|
||||||
echo " -h help"
|
|
||||||
}
|
|
||||||
|
|
||||||
while getopts ":r:c:m:l:d:hf" opt
|
|
||||||
do
|
|
||||||
case $opt in
|
|
||||||
r) range=$OPTARG
|
|
||||||
;;
|
|
||||||
c) config_opt=$OPTARG
|
|
||||||
;;
|
|
||||||
m) make_opt=$OPTARG
|
|
||||||
;;
|
|
||||||
d) logdir=$OPTARG
|
|
||||||
;;
|
|
||||||
l) logfile=$OPTARG
|
|
||||||
;;
|
|
||||||
f) force_clean='y'
|
|
||||||
;;
|
|
||||||
h) usage
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
\?) echo "Unknown option: -$OPTARG" >&2
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# append a '/' to logdir if $logdir was specified without one
|
|
||||||
[[ -n "$logdir" ]] && [[ ${logdir:${#logdir}-1} != "/" ]] && logdir="${logdir}/"
|
|
||||||
|
|
||||||
logfile="${logdir}${logfile}"
|
|
||||||
|
|
||||||
head=`git rev-parse --abbrev-ref=strict HEAD`
|
|
||||||
if [ HEAD = "$head" ]
|
|
||||||
then
|
|
||||||
# we're at a detached head, get hash
|
|
||||||
head=`git rev-parse HEAD`
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
total=`git rev-list "$range" |wc -l`
|
|
||||||
|
|
||||||
echo "log output: $logfile"
|
|
||||||
|
|
||||||
rm -f "$logfile"
|
|
||||||
date > "$logfile"
|
|
||||||
echo "git compile check for $range." >> "$logfile"
|
|
||||||
echo "* configure options='$config_opt'" >> "$logfile"
|
|
||||||
echo "* make options='$make_opt'" >> "$logfile"
|
|
||||||
echo "Performing a test compile on $total patches" | tee -a "$logfile"
|
|
||||||
echo "-------------------------------------------------------------" >> "$logfile"
|
|
||||||
echo "" | tee -a "$logfile"
|
|
||||||
|
|
||||||
clean_repo() {
|
|
||||||
if [[ $force_clean == 'y' ]]
|
|
||||||
then
|
|
||||||
git reset --hard >> "$logfile" 2>&1 || true
|
|
||||||
git clean -fdx >> "$logfile" 2>&1 || true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# we want to cleanup and return the git tree back to the previous head
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo ""
|
|
||||||
echo -n "Cleaning up..."
|
|
||||||
clean_repo
|
|
||||||
git checkout $head > /dev/null 2>&1
|
|
||||||
echo "done."
|
|
||||||
}
|
|
||||||
|
|
||||||
cnt=1
|
|
||||||
# don't pipe the git job into read, to avoid subshells
|
|
||||||
while read hash
|
|
||||||
do
|
|
||||||
txt=`git log --pretty=tformat:"%h: %s" $hash^!`
|
|
||||||
echo "${cnt}/${total}: compiling: $txt" | tee -a "$logfile"
|
|
||||||
let cnt=$cnt+1;
|
|
||||||
echo "####################" >> "$logfile"
|
|
||||||
clean_repo
|
|
||||||
make clean > /dev/null 2>&1 || true
|
|
||||||
git checkout $hash >> "$logfile" 2>&1 && \
|
|
||||||
./configure $config_opt >> "$logfile" 2>&1 && \
|
|
||||||
make $make_opt >> "$logfile" 2>&1 ||
|
|
||||||
(
|
|
||||||
S=$?
|
|
||||||
# don't complain for SIGINT, SIGTERM, SIGQUIT
|
|
||||||
if [ $S -ne 130 ] && [ $S -ne 131 ] && [ $S -ne 143 ]
|
|
||||||
then
|
|
||||||
echo "" | tee -a "$logfile"
|
|
||||||
echo "ERROR: commit $hash failed to build!" | tee -a "$logfile"
|
|
||||||
git show --stat $hash | tee -a "$logfile"
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
)
|
|
||||||
done < <(git log $range --pretty=tformat:"%H" --reverse)
|
|
||||||
|
|
||||||
echo "
|
|
||||||
All patches in $range compiled successfully!" | tee -a "$logfile"
|
|
||||||
exit 0
|
|
|
@ -1,77 +0,0 @@
|
||||||
SCRIPTS=$1
|
|
||||||
shift
|
|
||||||
NAME=$1
|
|
||||||
shift
|
|
||||||
VERSION=$1
|
|
||||||
shift
|
|
||||||
RELEASE=$1
|
|
||||||
shift
|
|
||||||
DATE=$1
|
|
||||||
shift
|
|
||||||
COMMIT=$1
|
|
||||||
shift
|
|
||||||
TARBALL=$1
|
|
||||||
shift
|
|
||||||
TARURL=$1
|
|
||||||
shift
|
|
||||||
SPECNAME=$1
|
|
||||||
shift
|
|
||||||
BUILDDIR_NAME=$1
|
|
||||||
shift
|
|
||||||
MARKER=$1
|
|
||||||
shift
|
|
||||||
LOCALVERSION=$1
|
|
||||||
shift
|
|
||||||
RHEV=$1
|
|
||||||
shift
|
|
||||||
ZRELEASE=$1
|
|
||||||
|
|
||||||
SOURCES=rpmbuild/SOURCES
|
|
||||||
SRPMDIR=rpmbuild/SRPM
|
|
||||||
BUILDDIR=${SOURCES}/${BUILDDIR_NAME}
|
|
||||||
SPEC=rpmbuild/SPECS/${SPECNAME}
|
|
||||||
|
|
||||||
# Pre-cleaning
|
|
||||||
rm -rf .tmp asection psection patchlist
|
|
||||||
|
|
||||||
if [ ! -f ${TARBALL} ]; then
|
|
||||||
wget ${TARURL}
|
|
||||||
fi
|
|
||||||
cp ${TARBALL} ${SOURCES}/${TARBALL}
|
|
||||||
|
|
||||||
if [ -n "${ZRELEASE}" ]; then
|
|
||||||
ZRELEASE=.${ZRELEASE}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Handle patches
|
|
||||||
git format-patch --first-parent --no-renames -k --no-binary ${MARKER}.. > patchlist
|
|
||||||
for patchfile in `cat patchlist`; do
|
|
||||||
${SCRIPTS}/frh.py ${patchfile} > .tmp
|
|
||||||
if grep -q '^diff --git ' .tmp; then
|
|
||||||
num=$(echo $patchfile | sed 's/\([0-9]*\).*/\1/')
|
|
||||||
echo "Patch${num}: ${patchfile}" >> psection
|
|
||||||
echo "%patch${num} -p1" >> asection
|
|
||||||
mv .tmp ${SOURCES}/${patchfile}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Handle spec file
|
|
||||||
cp ${SPECNAME}.template ${SPEC}
|
|
||||||
|
|
||||||
sed -i -e "/%%PATCHLIST%%/r psection
|
|
||||||
/%%PATCHLIST%%/d
|
|
||||||
/%%PATCHAPPLY%%/r asection
|
|
||||||
/%%PATCHAPPLY%%/d
|
|
||||||
s/%%VERSION%%/${VERSION}/
|
|
||||||
s/%%RELEASE%%/${RELEASE}/
|
|
||||||
s/%%ZRELEASE%%/${ZRELEASE}/
|
|
||||||
s/%%DATE%%/${DATE}/
|
|
||||||
s/%%COMMIT%%/${COMMIT}/
|
|
||||||
s/%%LOCALVERSION%%/${LOCALVERSION}/
|
|
||||||
s/%%TARBALL%%/${TARBALL}/
|
|
||||||
s/%%RHEV%%/${RHEV}/" $SPEC
|
|
||||||
|
|
||||||
# Final cleaning
|
|
||||||
rm -rf `cat patchlist`
|
|
||||||
rm -rf .tmp asection psection patchlist
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
sha1sum < $1 | cut -d ' ' -f 1
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
if [ -f /etc/os-release ]
|
||||||
|
then
|
||||||
|
. /etc/os-release
|
||||||
|
else
|
||||||
|
echo "ERROR: OS name is not provided."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$NAME" = "Arch Linux" ]
|
||||||
|
then
|
||||||
|
pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \
|
||||||
|
make meson pkgconf python python-setuptools-scm swig
|
||||||
|
elif [ "$NAME" = "Alpine Linux" ]
|
||||||
|
then
|
||||||
|
apk add build-base bison flex git yaml yaml-dev python3-dev \
|
||||||
|
meson py3-setuptools_scm swig
|
||||||
|
elif [ "$NAME" = "Fedora Linux" ]
|
||||||
|
then
|
||||||
|
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
|
||||||
|
make meson python3-devel python3-setuptools swig
|
||||||
|
elif [ "$NAME" = "Ubuntu" ]
|
||||||
|
then
|
||||||
|
apt update
|
||||||
|
apt install -yq build-essential bison flex git libyaml-dev pkg-config \
|
||||||
|
meson python3-dev python3-setuptools python3-setuptools-scm swig
|
||||||
|
else
|
||||||
|
echo "ERROR: OS name is not provided."
|
||||||
|
exit 1
|
||||||
|
fi
|
|
@ -1,4 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
REMOTE_GIT=/pub/scm/utils/dtc/dtc.git
|
REMOTE_GIT=/pub/scm/utils/dtc/dtc.git
|
||||||
REMOTE_PATH=/pub/software/utils/dtc
|
REMOTE_PATH=/pub/software/utils/dtc
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Print additional version information for non-release trees.
|
# Print additional version information for non-release trees.
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
|
|
215
srcpos.c
215
srcpos.c
|
@ -1,23 +1,11 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -33,6 +21,9 @@ struct search_path {
|
||||||
/* This is the list of directories that we search for source files */
|
/* This is the list of directories that we search for source files */
|
||||||
static struct search_path *search_path_head, **search_path_tail;
|
static struct search_path *search_path_head, **search_path_tail;
|
||||||
|
|
||||||
|
/* Detect infinite include recursion. */
|
||||||
|
#define MAX_SRCFILE_DEPTH (200)
|
||||||
|
static int srcfile_depth; /* = 0 */
|
||||||
|
|
||||||
static char *get_dirname(const char *path)
|
static char *get_dirname(const char *path)
|
||||||
{
|
{
|
||||||
|
@ -51,11 +42,71 @@ static char *get_dirname(const char *path)
|
||||||
|
|
||||||
FILE *depfile; /* = NULL */
|
FILE *depfile; /* = NULL */
|
||||||
struct srcfile_state *current_srcfile; /* = NULL */
|
struct srcfile_state *current_srcfile; /* = NULL */
|
||||||
|
static char *initial_path; /* = NULL */
|
||||||
|
static int initial_pathlen; /* = 0 */
|
||||||
|
static bool initial_cpp = true;
|
||||||
|
|
||||||
/* Detect infinite include recursion. */
|
static void set_initial_path(char *fname)
|
||||||
#define MAX_SRCFILE_DEPTH (100)
|
{
|
||||||
static int srcfile_depth; /* = 0 */
|
int i, len = strlen(fname);
|
||||||
|
|
||||||
|
xasprintf(&initial_path, "%s", fname);
|
||||||
|
initial_pathlen = 0;
|
||||||
|
for (i = 0; i != len; i++)
|
||||||
|
if (initial_path[i] == '/')
|
||||||
|
initial_pathlen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *shorten_to_initial_path(char *fname)
|
||||||
|
{
|
||||||
|
char *p1, *p2, *prevslash1 = NULL;
|
||||||
|
int slashes = 0;
|
||||||
|
|
||||||
|
for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
|
||||||
|
if (*p1 != *p2)
|
||||||
|
break;
|
||||||
|
if (*p1 == '/') {
|
||||||
|
prevslash1 = p1;
|
||||||
|
slashes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p1 = prevslash1 + 1;
|
||||||
|
if (prevslash1) {
|
||||||
|
int diff = initial_pathlen - slashes, i, j;
|
||||||
|
int restlen = strlen(fname) - (p1 - fname);
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
res = xmalloc((3 * diff) + restlen + 1);
|
||||||
|
for (i = 0, j = 0; i != diff; i++) {
|
||||||
|
res[j++] = '.';
|
||||||
|
res[j++] = '.';
|
||||||
|
res[j++] = '/';
|
||||||
|
}
|
||||||
|
strcpy(res + j, p1);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given path is an absolute one.
|
||||||
|
*
|
||||||
|
* On Windows, it either needs to begin with a forward slash or with a drive
|
||||||
|
* letter (e.g. "C:").
|
||||||
|
* On all other operating systems, it must begin with a forward slash to be
|
||||||
|
* considered an absolute path.
|
||||||
|
*/
|
||||||
|
static bool is_absolute_path(const char *path)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return (
|
||||||
|
path[0] == '/' ||
|
||||||
|
(((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
return (path[0] == '/');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to open a file in a given directory.
|
* Try to open a file in a given directory.
|
||||||
|
@ -72,7 +123,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
|
||||||
{
|
{
|
||||||
char *fullname;
|
char *fullname;
|
||||||
|
|
||||||
if (!dirname || fname[0] == '/')
|
if (!dirname || is_absolute_path(fname))
|
||||||
fullname = xstrdup(fname);
|
fullname = xstrdup(fname);
|
||||||
else
|
else
|
||||||
fullname = join_path(dirname, fname);
|
fullname = join_path(dirname, fname);
|
||||||
|
@ -129,8 +180,10 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depfile)
|
if (depfile) {
|
||||||
fprintf(depfile, " %s", fullname);
|
fputc(' ', depfile);
|
||||||
|
fprint_path_escaped(depfile, fullname);
|
||||||
|
}
|
||||||
|
|
||||||
if (fullnamep)
|
if (fullnamep)
|
||||||
*fullnamep = fullname;
|
*fullnamep = fullname;
|
||||||
|
@ -157,6 +210,9 @@ void srcfile_push(const char *fname)
|
||||||
srcfile->colno = 1;
|
srcfile->colno = 1;
|
||||||
|
|
||||||
current_srcfile = srcfile;
|
current_srcfile = srcfile;
|
||||||
|
|
||||||
|
if (srcfile_depth == 1)
|
||||||
|
set_initial_path(srcfile->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srcfile_pop(void)
|
bool srcfile_pop(void)
|
||||||
|
@ -197,20 +253,6 @@ void srcfile_add_search_path(const char *dirname)
|
||||||
search_path_tail = &node->next;
|
search_path_tail = &node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The empty source position.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct srcpos srcpos_empty = {
|
|
||||||
.first_line = 0,
|
|
||||||
.first_column = 0,
|
|
||||||
.last_line = 0,
|
|
||||||
.last_column = 0,
|
|
||||||
.file = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TAB_SIZE 8
|
|
||||||
|
|
||||||
void srcpos_update(struct srcpos *pos, const char *text, int len)
|
void srcpos_update(struct srcpos *pos, const char *text, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -224,9 +266,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
|
||||||
if (text[i] == '\n') {
|
if (text[i] == '\n') {
|
||||||
current_srcfile->lineno++;
|
current_srcfile->lineno++;
|
||||||
current_srcfile->colno = 1;
|
current_srcfile->colno = 1;
|
||||||
} else if (text[i] == '\t') {
|
|
||||||
current_srcfile->colno =
|
|
||||||
ALIGN(current_srcfile->colno, TAB_SIZE);
|
|
||||||
} else {
|
} else {
|
||||||
current_srcfile->colno++;
|
current_srcfile->colno++;
|
||||||
}
|
}
|
||||||
|
@ -239,13 +278,46 @@ struct srcpos *
|
||||||
srcpos_copy(struct srcpos *pos)
|
srcpos_copy(struct srcpos *pos)
|
||||||
{
|
{
|
||||||
struct srcpos *pos_new;
|
struct srcpos *pos_new;
|
||||||
|
struct srcfile_state *srcfile_state;
|
||||||
|
|
||||||
|
if (!pos)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
pos_new = xmalloc(sizeof(struct srcpos));
|
pos_new = xmalloc(sizeof(struct srcpos));
|
||||||
|
assert(pos->next == NULL);
|
||||||
memcpy(pos_new, pos, sizeof(struct srcpos));
|
memcpy(pos_new, pos, sizeof(struct srcpos));
|
||||||
|
|
||||||
|
/* allocate without free */
|
||||||
|
srcfile_state = xmalloc(sizeof(struct srcfile_state));
|
||||||
|
memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
|
||||||
|
pos_new->file = srcfile_state;
|
||||||
|
|
||||||
return pos_new;
|
return pos_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
|
||||||
|
{
|
||||||
|
struct srcpos *p;
|
||||||
|
|
||||||
|
if (!pos)
|
||||||
|
return newtail;
|
||||||
|
|
||||||
|
for (p = pos; p->next != NULL; p = p->next);
|
||||||
|
p->next = newtail;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srcpos_free(struct srcpos *pos)
|
||||||
|
{
|
||||||
|
struct srcpos *p_next;
|
||||||
|
|
||||||
|
while (pos) {
|
||||||
|
p_next = pos->next;
|
||||||
|
free(pos);
|
||||||
|
pos = p_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
srcpos_string(struct srcpos *pos)
|
srcpos_string(struct srcpos *pos)
|
||||||
{
|
{
|
||||||
|
@ -271,6 +343,68 @@ srcpos_string(struct srcpos *pos)
|
||||||
return pos_str;
|
return pos_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
|
||||||
|
{
|
||||||
|
char *pos_str, *fresh_fname = NULL, *first, *rest;
|
||||||
|
const char *fname;
|
||||||
|
|
||||||
|
if (!pos) {
|
||||||
|
if (level > 1) {
|
||||||
|
xasprintf(&pos_str, "<no-file>:<no-line>");
|
||||||
|
return pos_str;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pos->file)
|
||||||
|
fname = "<no-file>";
|
||||||
|
else if (!pos->file->name)
|
||||||
|
fname = "<no-filename>";
|
||||||
|
else if (level > 1)
|
||||||
|
fname = pos->file->name;
|
||||||
|
else {
|
||||||
|
fresh_fname = shorten_to_initial_path(pos->file->name);
|
||||||
|
if (fresh_fname)
|
||||||
|
fname = fresh_fname;
|
||||||
|
else
|
||||||
|
fname = pos->file->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level > 1)
|
||||||
|
xasprintf(&first, "%s:%d:%d-%d:%d", fname,
|
||||||
|
pos->first_line, pos->first_column,
|
||||||
|
pos->last_line, pos->last_column);
|
||||||
|
else
|
||||||
|
xasprintf(&first, "%s:%d", fname,
|
||||||
|
first_line ? pos->first_line : pos->last_line);
|
||||||
|
|
||||||
|
if (fresh_fname)
|
||||||
|
free(fresh_fname);
|
||||||
|
|
||||||
|
if (pos->next != NULL) {
|
||||||
|
rest = srcpos_string_comment(pos->next, first_line, level);
|
||||||
|
xasprintf(&pos_str, "%s, %s", first, rest);
|
||||||
|
free(first);
|
||||||
|
free(rest);
|
||||||
|
} else {
|
||||||
|
pos_str = first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *srcpos_string_first(struct srcpos *pos, int level)
|
||||||
|
{
|
||||||
|
return srcpos_string_comment(pos, true, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *srcpos_string_last(struct srcpos *pos, int level)
|
||||||
|
{
|
||||||
|
return srcpos_string_comment(pos, false, level);
|
||||||
|
}
|
||||||
|
|
||||||
void srcpos_verror(struct srcpos *pos, const char *prefix,
|
void srcpos_verror(struct srcpos *pos, const char *prefix,
|
||||||
const char *fmt, va_list va)
|
const char *fmt, va_list va)
|
||||||
{
|
{
|
||||||
|
@ -299,4 +433,9 @@ void srcpos_set_line(char *f, int l)
|
||||||
{
|
{
|
||||||
current_srcfile->name = f;
|
current_srcfile->name = f;
|
||||||
current_srcfile->lineno = l;
|
current_srcfile->lineno = l;
|
||||||
|
|
||||||
|
if (initial_cpp) {
|
||||||
|
initial_cpp = false;
|
||||||
|
set_initial_path(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
48
srcpos.h
48
srcpos.h
|
@ -1,27 +1,14 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
* USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SRCPOS_H_
|
#ifndef SRCPOS_H
|
||||||
#define _SRCPOS_H_
|
#define SRCPOS_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
struct srcfile_state {
|
struct srcfile_state {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
@ -73,6 +60,7 @@ struct srcpos {
|
||||||
int last_line;
|
int last_line;
|
||||||
int last_column;
|
int last_column;
|
||||||
struct srcfile_state *file;
|
struct srcfile_state *file;
|
||||||
|
struct srcpos *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define YYLTYPE struct srcpos
|
#define YYLTYPE struct srcpos
|
||||||
|
@ -92,27 +80,25 @@ struct srcpos {
|
||||||
YYRHSLOC(Rhs, 0).last_column; \
|
YYRHSLOC(Rhs, 0).last_column; \
|
||||||
(Current).file = YYRHSLOC (Rhs, 0).file; \
|
(Current).file = YYRHSLOC (Rhs, 0).file; \
|
||||||
} \
|
} \
|
||||||
|
(Current).next = NULL; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fictional source position used for IR nodes that are
|
|
||||||
* created without otherwise knowing a true source position.
|
|
||||||
* For example,constant definitions from the command line.
|
|
||||||
*/
|
|
||||||
extern struct srcpos srcpos_empty;
|
|
||||||
|
|
||||||
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
|
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
|
||||||
extern struct srcpos *srcpos_copy(struct srcpos *pos);
|
extern struct srcpos *srcpos_copy(struct srcpos *pos);
|
||||||
|
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
|
||||||
|
struct srcpos *old_srcpos);
|
||||||
|
extern void srcpos_free(struct srcpos *pos);
|
||||||
extern char *srcpos_string(struct srcpos *pos);
|
extern char *srcpos_string(struct srcpos *pos);
|
||||||
|
extern char *srcpos_string_first(struct srcpos *pos, int level);
|
||||||
|
extern char *srcpos_string_last(struct srcpos *pos, int level);
|
||||||
|
|
||||||
extern void srcpos_verror(struct srcpos *pos, const char *prefix,
|
|
||||||
const char *fmt, va_list va)
|
extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
|
||||||
__attribute__((format(printf, 3, 0)));
|
const char *fmt, va_list va);
|
||||||
extern void srcpos_error(struct srcpos *pos, const char *prefix,
|
extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...);
|
||||||
__attribute__((format(printf, 3, 4)));
|
|
||||||
|
|
||||||
extern void srcpos_set_line(char *f, int l);
|
extern void srcpos_set_line(char *f, int l);
|
||||||
|
|
||||||
#endif /* _SRCPOS_H_ */
|
#endif /* SRCPOS_H */
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
*.dtb
|
*.dtb
|
||||||
*.dts.test.s
|
*.dts.test.s
|
||||||
*.test.dts
|
*.test.dts
|
||||||
|
*.test.dt.yaml
|
||||||
tmp.*
|
tmp.*
|
||||||
|
/fs/
|
||||||
/add_subnode_with_nops
|
/add_subnode_with_nops
|
||||||
/addr_size_cells
|
/addr_size_cells
|
||||||
|
/addr_size_cells2
|
||||||
/appendprop[12]
|
/appendprop[12]
|
||||||
|
/appendprop_addrrange
|
||||||
/asm_tree_dump
|
/asm_tree_dump
|
||||||
/boot-cpuid
|
/boot-cpuid
|
||||||
/char_literal
|
/char_literal
|
||||||
|
/check_full
|
||||||
|
/check_header
|
||||||
/check_path
|
/check_path
|
||||||
/del_node
|
/del_node
|
||||||
/del_property
|
/del_property
|
||||||
|
@ -23,8 +29,10 @@ tmp.*
|
||||||
/get_path
|
/get_path
|
||||||
/get_phandle
|
/get_phandle
|
||||||
/getprop
|
/getprop
|
||||||
|
/get_prop_offset
|
||||||
/incbin
|
/incbin
|
||||||
/integer-expressions
|
/integer-expressions
|
||||||
|
/fs_tree1
|
||||||
/mangle-layout
|
/mangle-layout
|
||||||
/move_and_save
|
/move_and_save
|
||||||
/node_check_compatible
|
/node_check_compatible
|
||||||
|
@ -46,8 +54,10 @@ tmp.*
|
||||||
/property_iterate
|
/property_iterate
|
||||||
/propname_escapes
|
/propname_escapes
|
||||||
/references
|
/references
|
||||||
|
/relref_merge
|
||||||
/root_node
|
/root_node
|
||||||
/rw_tree1
|
/rw_tree1
|
||||||
|
/rw_oom
|
||||||
/set_name
|
/set_name
|
||||||
/setprop
|
/setprop
|
||||||
/setprop_inplace
|
/setprop_inplace
|
||||||
|
@ -58,6 +68,10 @@ tmp.*
|
||||||
/subnode_offset
|
/subnode_offset
|
||||||
/supernode_atdepth_offset
|
/supernode_atdepth_offset
|
||||||
/sw_tree1
|
/sw_tree1
|
||||||
|
/sw_states
|
||||||
/truncated_property
|
/truncated_property
|
||||||
|
/truncated_string
|
||||||
|
/truncated_memrsv
|
||||||
/utilfdt_test
|
/utilfdt_test
|
||||||
/value-labels
|
/value-labels
|
||||||
|
/get_next_tag_invalid_prop_len
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
LIB_TESTS_L = get_mem_rsv \
|
LIB_TESTS_L = get_mem_rsv \
|
||||||
root_node find_property subnode_offset path_offset \
|
root_node find_property subnode_offset path_offset \
|
||||||
get_name getprop get_phandle \
|
get_name getprop get_prop_offset get_phandle \
|
||||||
get_path supernode_atdepth_offset parent_offset \
|
get_path supernode_atdepth_offset parent_offset \
|
||||||
node_offset_by_prop_value node_offset_by_phandle \
|
node_offset_by_prop_value node_offset_by_phandle \
|
||||||
node_check_compatible node_offset_by_compatible \
|
node_check_compatible node_offset_by_compatible \
|
||||||
get_alias \
|
get_alias get_next_tag_invalid_prop_len \
|
||||||
char_literal \
|
char_literal \
|
||||||
sized_cells \
|
sized_cells \
|
||||||
notfound \
|
notfound \
|
||||||
addr_size_cells \
|
addr_size_cells \
|
||||||
|
addr_size_cells2 \
|
||||||
|
appendprop_addrrange \
|
||||||
stringlist \
|
stringlist \
|
||||||
setprop_inplace nop_property nop_node \
|
setprop_inplace nop_property nop_node \
|
||||||
sw_tree1 \
|
sw_tree1 sw_states \
|
||||||
move_and_save mangle-layout nopulate \
|
move_and_save mangle-layout nopulate \
|
||||||
open_pack rw_tree1 set_name setprop del_property del_node \
|
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
|
||||||
appendprop1 appendprop2 propname_escapes \
|
appendprop1 appendprop2 propname_escapes \
|
||||||
string_escapes references path-references phandle_format \
|
string_escapes references path-references phandle_format \
|
||||||
boot-cpuid incbin \
|
boot-cpuid incbin relref_merge \
|
||||||
extra-terminating-null \
|
extra-terminating-null \
|
||||||
dtbs_equal_ordered \
|
dtbs_equal_ordered \
|
||||||
dtb_reverse dtbs_equal_unordered \
|
dtb_reverse dtbs_equal_unordered \
|
||||||
|
@ -26,18 +28,24 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
property_iterate \
|
property_iterate \
|
||||||
subnode_iterate \
|
subnode_iterate \
|
||||||
overlay overlay_bad_fixup \
|
overlay overlay_bad_fixup \
|
||||||
check_path
|
check_path check_header check_full \
|
||||||
|
fs_tree1
|
||||||
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
LIBTREE_TESTS_L = truncated_property
|
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
|
||||||
|
|
||||||
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
|
ifneq ($(STATIC_BUILD),1)
|
||||||
DL_LIB_TESTS_L = asm_tree_dump value-labels
|
DL_LIB_TESTS_L = asm_tree_dump value-labels
|
||||||
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
endif
|
||||||
|
|
||||||
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
|
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
|
||||||
|
|
||||||
TESTS_TREES_L = test_tree1.dtb
|
TESTS_TREES_L = test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \
|
||||||
|
bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \
|
||||||
|
truncated_string.dtb truncated_memrsv.dtb two_roots.dtb named_root.dtb
|
||||||
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
|
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
|
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
|
||||||
|
@ -45,43 +53,53 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
|
||||||
TESTS_DEPFILES = $(TESTS:%=%.d) \
|
TESTS_DEPFILES = $(TESTS:%=%.d) \
|
||||||
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
|
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
|
||||||
|
|
||||||
TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.*
|
TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
|
||||||
TESTS_CLEANFILES_L += dumptrees
|
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
|
||||||
|
dumptrees
|
||||||
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
|
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
|
||||||
|
TESTS_CLEANDIRS_L = fs
|
||||||
|
TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
.PHONY: tests
|
.PHONY: tests
|
||||||
tests: $(TESTS) $(TESTS_TREES)
|
tests: $(TESTS) $(TESTS_TREES)
|
||||||
|
|
||||||
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
|
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
|
||||||
|
|
||||||
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
|
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
|
||||||
|
# other platforms to patch it out.
|
||||||
|
LIBDL = -ldl
|
||||||
|
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
|
||||||
@$(VECHO) LD [libdl] $@
|
@$(VECHO) LD [libdl] $@
|
||||||
$(LINK.c) -o $@ $^ -ldl
|
$(LINK.c) -o $@ $^ $(LIBDL)
|
||||||
|
|
||||||
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
|
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
|
||||||
util.o $(LIBFDT_archive)
|
util.o $(LIBFDT_dep)
|
||||||
|
|
||||||
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
|
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
|
||||||
|
|
||||||
$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
|
$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
|
||||||
@$(VECHO) DUMPTREES
|
@$(VECHO) DUMPTREES
|
||||||
cd $(TESTS_PREFIX); ./dumptrees >/dev/null
|
cd $(TESTS_PREFIX); ./dumptrees . >/dev/null
|
||||||
|
|
||||||
tests_clean:
|
tests_clean:
|
||||||
@$(VECHO) CLEAN "(tests)"
|
@$(VECHO) CLEAN "(tests)"
|
||||||
rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)
|
|
||||||
rm -f $(TESTS_CLEANFILES)
|
rm -f $(TESTS_CLEANFILES)
|
||||||
|
rm -rf $(TESTS_CLEANDIRS)
|
||||||
|
|
||||||
check: tests ${TESTS_BIN}
|
check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
||||||
cd $(TESTS_PREFIX); ./run_tests.sh
|
cd $(TESTS_PREFIX); ./run_tests.sh
|
||||||
|
|
||||||
checkm: tests ${TESTS_BIN}
|
ifeq ($(NO_VALGRIND),1)
|
||||||
cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$
|
checkm:
|
||||||
|
@echo "make checkm requires valgrind, but NO_VALGRIND=1"
|
||||||
|
else
|
||||||
|
checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
||||||
|
cd $(TESTS_PREFIX); ./run_tests.sh -m
|
||||||
|
endif
|
||||||
|
|
||||||
checkv: tests ${TESTS_BIN}
|
checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
|
||||||
cd $(TESTS_PREFIX); ./run_tests.sh -v
|
cd $(TESTS_PREFIX); ./run_tests.sh -v
|
||||||
|
|
||||||
ifneq ($(DEPTARGETS),)
|
ifneq ($(DEPTARGETS),)
|
||||||
-include $(TESTS_DEPFILES)
|
-include $(TESTS_DEPFILES)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Testcase for fdt_nop_node()
|
* Testcase for fdt_nop_node()
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Testcase for #address-cells and #size-cells handling
|
* Testcase for #address-cells and #size-cells handling
|
||||||
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
|
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -58,7 +45,12 @@ int main(int argc, char *argv[])
|
||||||
fdt = load_blob(argv[1]);
|
fdt = load_blob(argv[1]);
|
||||||
|
|
||||||
check_node(fdt, "/", 2, 2);
|
check_node(fdt, "/", 2, 2);
|
||||||
check_node(fdt, "/identity-bus@0", 2, 2);
|
check_node(fdt, "/identity-bus@0", 2, 1);
|
||||||
check_node(fdt, "/simple-bus@1000000", 2, 1);
|
check_node(fdt, "/simple-bus@1000000", 2, 1);
|
||||||
|
check_node(fdt, "/discrete-bus@2000000", 1, 0);
|
||||||
|
check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
|
||||||
|
check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
|
||||||
|
check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
|
||||||
|
check_node(fdt, "/c3", -FDT_ERR_BADNCELLS, 0);
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Testcase for #address-cells and #size-cells handling
|
||||||
|
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "testdata.h"
|
||||||
|
|
||||||
|
static void check_node(const void *fdt, const char *path, int ac, int sc)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int xac, xsc;
|
||||||
|
|
||||||
|
offset = fdt_path_offset(fdt, path);
|
||||||
|
if (offset < 0)
|
||||||
|
FAIL("Couldn't find path %s", path);
|
||||||
|
|
||||||
|
xac = fdt_address_cells(fdt, offset);
|
||||||
|
xsc = fdt_size_cells(fdt, offset);
|
||||||
|
|
||||||
|
if (xac != ac)
|
||||||
|
FAIL("Address cells for %s is %d instead of %d\n",
|
||||||
|
path, xac, ac);
|
||||||
|
if (xsc != sc)
|
||||||
|
FAIL("Size cells for %s is %d instead of %d\n",
|
||||||
|
path, xsc, sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
void *fdt;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
CONFIG("Usage: %s <dtb file>\n", argv[0]);
|
||||||
|
|
||||||
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob(argv[1]);
|
||||||
|
|
||||||
|
check_node(fdt, "/", 2, 1);
|
||||||
|
PASS();
|
||||||
|
}
|
|
@ -12,4 +12,29 @@
|
||||||
#address-cells = <2>;
|
#address-cells = <2>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
discrete-bus@2000000 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
c0@0 {
|
||||||
|
#address-cells = <1 1>;
|
||||||
|
#size-cells = <1 1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
c1@0 {
|
||||||
|
#address-cells = <0x80000000>;
|
||||||
|
#size-cells = <0x80000000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
c2@0 {
|
||||||
|
#address-cells = <5>;
|
||||||
|
#size-cells = <5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
c3@0 {
|
||||||
|
#address-cells = <0>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
|
empty = "";
|
||||||
|
loop = "loop";
|
||||||
|
nonull = [626164];
|
||||||
|
relative = "s1/subsubnode";
|
||||||
s1 = &sub1;
|
s1 = &sub1;
|
||||||
ss1 = &subsub1;
|
ss1 = &subsub1;
|
||||||
sss1 = &subsubsub1;
|
sss1 = &subsubsub1;
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Testcase for fdt_appendprop()
|
* Testcase for fdt_appendprop()
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -1,21 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Testcase for fdt_appendprop()
|
* Testcase for fdt_appendprop()
|
||||||
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -49,6 +36,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
buf = xmalloc(SPACE);
|
buf = xmalloc(SPACE);
|
||||||
CHECK(fdt_open_into(fdt, buf, SPACE));
|
CHECK(fdt_open_into(fdt, buf, SPACE));
|
||||||
|
free(fdt);
|
||||||
fdt = buf;
|
fdt = buf;
|
||||||
|
|
||||||
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
|
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
/*
|
||||||
|
* libfdt - Flat Device Tree manipulation
|
||||||
|
* Testcase for fdt_appendprop_addrrange()
|
||||||
|
* Copyright (C) 2018 AKASHI Takahiro, Linaro Limited
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "testdata.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
void *fdt, *buf;
|
||||||
|
int offset, xac, xsc, num, i, err;
|
||||||
|
uint64_t addr, size;
|
||||||
|
|
||||||
|
if (argc != 5)
|
||||||
|
CONFIG("Usage: %s <dtb file> <address-cells> <size-cells> <num>\n",
|
||||||
|
argv[0]);
|
||||||
|
|
||||||
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob(argv[1]);
|
||||||
|
xac = strtol(argv[2], NULL, 10);
|
||||||
|
xsc = strtol(argv[3], NULL, 10);
|
||||||
|
num = strtol(argv[4], NULL, 10);
|
||||||
|
|
||||||
|
buf = xmalloc(0x1000);
|
||||||
|
if (!buf)
|
||||||
|
FAIL("Couldn't allocate temporary buffer");
|
||||||
|
err = fdt_open_into(fdt, buf, 0x1000);
|
||||||
|
if (err)
|
||||||
|
FAIL("fdt_open_into(): %s", fdt_strerror(err));
|
||||||
|
free(fdt);
|
||||||
|
fdt = buf;
|
||||||
|
|
||||||
|
/* Set up */
|
||||||
|
err = fdt_setprop_cell(fdt, 0, "#address-cells", xac);
|
||||||
|
if (err)
|
||||||
|
FAIL("fdt_setprop_cell(\"#address-cells\"): %s",
|
||||||
|
fdt_strerror(err));
|
||||||
|
err = fdt_setprop_cell(fdt, 0, "#size-cells", xsc);
|
||||||
|
if (err)
|
||||||
|
FAIL("fdt_setprop_cell(\"#size-cells\"): %s",
|
||||||
|
fdt_strerror(err));
|
||||||
|
|
||||||
|
offset = fdt_path_offset(fdt, "/node@1");
|
||||||
|
if (offset < 0)
|
||||||
|
FAIL("Couldn't find path %s", "/node@1");
|
||||||
|
|
||||||
|
addr = TEST_MEMREGION_ADDR;
|
||||||
|
if (xac > 1)
|
||||||
|
addr += TEST_MEMREGION_ADDR_HI;
|
||||||
|
size = TEST_MEMREGION_SIZE;
|
||||||
|
if (xsc > 1)
|
||||||
|
size += TEST_MEMREGION_SIZE_HI;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do test
|
||||||
|
*/
|
||||||
|
/* 1. repeat append's */
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
err = fdt_appendprop_addrrange(fdt, 0, offset,
|
||||||
|
"prop-memregion", addr, size);
|
||||||
|
if (err)
|
||||||
|
FAIL("Failed to append[%d] \"prop-memregion\": %s",
|
||||||
|
i, fdt_strerror(err));
|
||||||
|
|
||||||
|
check_getprop_addrrange(fdt, 0, offset, "prop-memregion",
|
||||||
|
i + 1);
|
||||||
|
|
||||||
|
addr += size;
|
||||||
|
size += TEST_MEMREGION_SIZE_INC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. default property name */
|
||||||
|
addr = TEST_MEMREGION_ADDR;
|
||||||
|
if (xac > 1)
|
||||||
|
addr += TEST_MEMREGION_ADDR_HI;
|
||||||
|
size = TEST_MEMREGION_SIZE;
|
||||||
|
if (xsc > 1)
|
||||||
|
size += TEST_MEMREGION_SIZE_HI;
|
||||||
|
|
||||||
|
err = fdt_appendprop_addrrange(fdt, 0, offset, "reg", addr, size);
|
||||||
|
if (err)
|
||||||
|
FAIL("Failed to set \"reg\": %s", fdt_strerror(err));
|
||||||
|
check_getprop_addrrange(fdt, 0, offset, "reg", 1);
|
||||||
|
|
||||||
|
PASS();
|
||||||
|
}
|
|
@ -1,21 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* libfdt - Flat Device Tree manipulation
|
* libfdt - Flat Device Tree manipulation
|
||||||
* Tests if an asm tree built into a shared object matches a given dtb
|
* Tests if an asm tree built into a shared object matches a given dtb
|
||||||
* Copyright (C) 2008 David Gibson, IBM Corporation.
|
* Copyright (C) 2008 David Gibson, IBM Corporation.
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2.1 of
|
|
||||||
* the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
node2 {
|
||||||
|
chosen {
|
||||||
|
bootargs = <0xdeadbeef>;
|
||||||
|
stdout-path = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
node {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges;
|
||||||
|
dma-ranges = <0 0 0 0 0>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
gpio: gpio-controller {
|
||||||
|
#gpio-cells = <3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
node {
|
||||||
|
nr-gpios = <1>;
|
||||||
|
foo-gpios = <&gpio>;
|
||||||
|
bar-gpio = <&gpio 1 2 3>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/ {
|
||||||
|
bar: bar {
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
bar_con: endpoint {
|
||||||
|
remote-endpoint = <&foo_con>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
foo {
|
||||||
|
port {
|
||||||
|
foo_con: endpoint {
|
||||||
|
remote-endpoint = <&bar_con>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/ {
|
||||||
|
bar: bar {
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>; // should always be 0
|
||||||
|
port@1 {
|
||||||
|
reg = <1 2>; // should always contain only a single cell
|
||||||
|
bar_con: endpoint {
|
||||||
|
remote-endpoint = <&foo_con>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
port@2 {
|
||||||
|
reg = <2>;
|
||||||
|
bar_con2: endpoint {
|
||||||
|
remote-endpoint = <&foo_con2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
foo {
|
||||||
|
port {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>; // should always be 0
|
||||||
|
foo_con: endpoint@1 {
|
||||||
|
reg = <1 2>; // should always contain only a single cell
|
||||||
|
remote-endpoint = <&bar_con>;
|
||||||
|
};
|
||||||
|
foo_con2: endpoint@2 {
|
||||||
|
reg = <2>;
|
||||||
|
remote-endpoint = <&bar_con2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
foo {
|
||||||
|
remote-endpoint = <0xdeadbeef>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/ { endpoint {}; };
|
|
@ -0,0 +1,14 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
bar: bar {
|
||||||
|
port {
|
||||||
|
bar_con: endpoint {
|
||||||
|
remote-endpoint = <&foo_con>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
foo_con: endpoint {
|
||||||
|
remote-endpoint = <&bar_con>;
|
||||||
|
};
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue