forked from espressif/esp-idf
Compare commits
620 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
463a9d8b7f | ||
|
|
ef34e6f6f7 | ||
|
|
aa51829ec8 | ||
|
|
dcd735759e | ||
|
|
a36bbd4e95 | ||
|
|
3f8a89504f | ||
|
|
1d280a0825 | ||
|
|
3b13eba1b2 | ||
|
|
1f263434a6 | ||
|
|
06cc4e888d | ||
|
|
0a2371972a | ||
|
|
b7a191a996 | ||
|
|
beb73456ee | ||
|
|
e3d65c8e3e | ||
|
|
d11bca44db | ||
|
|
6da2676a3c | ||
|
|
15aa9bc041 | ||
|
|
509ac2cfc1 | ||
|
|
8c23bb4aa9 | ||
|
|
989dac1e64 | ||
|
|
2ea0062fe8 | ||
|
|
5cb04f3e13 | ||
|
|
16e102199a | ||
|
|
2215aeaad8 | ||
|
|
51a1421f65 | ||
|
|
0cefe6df78 | ||
|
|
20e75ef87d | ||
|
|
cb1d440cb8 | ||
|
|
e5d25fb51e | ||
|
|
8306ddf3c1 | ||
|
|
93928a5d11 | ||
|
|
96a5e34d7a | ||
|
|
6bc284f7b7 | ||
|
|
daa2178f30 | ||
|
|
92b10b4ba3 | ||
|
|
69b0919904 | ||
|
|
4cbbe6cca3 | ||
|
|
edcba21b28 | ||
|
|
e8b454e802 | ||
|
|
84029130cf | ||
|
|
6cbda6bd22 | ||
|
|
dae4da07c3 | ||
|
|
ca3b2a8909 | ||
|
|
95f0553f40 | ||
|
|
09935510bd | ||
|
|
fb81b516da | ||
|
|
d93bff2699 | ||
|
|
03addfb0c5 | ||
|
|
0631d185bd | ||
|
|
65cfbbda52 | ||
|
|
6a18a33bad | ||
|
|
6f6677ac42 | ||
|
|
0e623d4dbf | ||
|
|
d41c020649 | ||
|
|
b261647835 | ||
|
|
53e6eb8467 | ||
|
|
ebaa3e1c3e | ||
|
|
66889332ce | ||
|
|
23770edb43 | ||
|
|
6ea738eeb0 | ||
|
|
3e6d04fc86 | ||
|
|
9dc45e788d | ||
|
|
bf712e4f91 | ||
|
|
83813f830d | ||
|
|
b0d6c01b04 | ||
|
|
f955c49423 | ||
|
|
1b15e6cf56 | ||
|
|
1ad1e70077 | ||
|
|
d8665e5343 | ||
|
|
46cb254f21 | ||
|
|
20e6d46d44 | ||
|
|
a89decd3c1 | ||
|
|
1e7933049d | ||
|
|
626c58fc67 | ||
|
|
03d5742e11 | ||
|
|
3c081abb32 | ||
|
|
482d2f06c3 | ||
|
|
4ffa3dbffb | ||
|
|
bf0863a50a | ||
|
|
20d435c561 | ||
|
|
a82215d161 | ||
|
|
dcbcb5fe58 | ||
|
|
23e6b47a28 | ||
|
|
85656ca77d | ||
|
|
6f0f5d79f9 | ||
|
|
314a0443ad | ||
|
|
3ba9eae86c | ||
|
|
a8e01de0e4 | ||
|
|
0104a24a36 | ||
|
|
643757bfad | ||
|
|
30ac846112 | ||
|
|
8e54ee3f16 | ||
|
|
ba11fed9c1 | ||
|
|
bf01dd61f7 | ||
|
|
ee6ba0eb47 | ||
|
|
45a50ed701 | ||
|
|
fd481d9cdd | ||
|
|
ec8e057e4c | ||
|
|
510ec904c9 | ||
|
|
fbdedee4cb | ||
|
|
f8e1ee35e2 | ||
|
|
06aa755265 | ||
|
|
48786c1da0 | ||
|
|
e9be102224 | ||
|
|
3691ebc273 | ||
|
|
31b9329d36 | ||
|
|
d00acce7b2 | ||
|
|
6e05a79536 | ||
|
|
978bf09f83 | ||
|
|
7a5d17e1b7 | ||
|
|
d3e0301aee | ||
|
|
69c0e6243e | ||
|
|
cffe7bf3a1 | ||
|
|
1041bc800c | ||
|
|
dd74a331c7 | ||
|
|
6ee7492512 | ||
|
|
9bf656e12e | ||
|
|
6ae4c29191 | ||
|
|
3fcecdd12e | ||
|
|
f3c8907cef | ||
|
|
7db756fbd9 | ||
|
|
1d72766f1a | ||
|
|
5d03ae7428 | ||
|
|
bfbc10e2d8 | ||
|
|
1fd0e6f482 | ||
|
|
21995978e1 | ||
|
|
e0b6ad0d1a | ||
|
|
2b5a8fe5ea | ||
|
|
bb7e52a4a8 | ||
|
|
c0597aaf69 | ||
|
|
87c30adfed | ||
|
|
3636bf5813 | ||
|
|
ea2959af36 | ||
|
|
585654388f | ||
|
|
939d5a0f6a | ||
|
|
4d3c650b49 | ||
|
|
2318e6828d | ||
|
|
262acbc0a8 | ||
|
|
2b2f0d0f28 | ||
|
|
2887131b39 | ||
|
|
104299353d | ||
|
|
19d394a366 | ||
|
|
e4312f8ab5 | ||
|
|
1930c56bd2 | ||
|
|
5e67f9578d | ||
|
|
46a172178a | ||
|
|
e6006a6bdf | ||
|
|
a5b803540a | ||
|
|
673ccaa1e5 | ||
|
|
08e55b8a66 | ||
|
|
0508ad525a | ||
|
|
97defec6cd | ||
|
|
96e6049dab | ||
|
|
37154d4c08 | ||
|
|
14dd44c05f | ||
|
|
42a462d584 | ||
|
|
c68bd605f8 | ||
|
|
f37837f785 | ||
|
|
69c86bc37e | ||
|
|
14f1a30e38 | ||
|
|
afeed3cc6f | ||
|
|
139913baa2 | ||
|
|
e324013ed6 | ||
|
|
8d189d9fb4 | ||
|
|
e7a6fdca54 | ||
|
|
48dfbe05a4 | ||
|
|
5d00321d07 | ||
|
|
2e8ad19e35 | ||
|
|
c45830d03f | ||
|
|
7725ce4999 | ||
|
|
97488fe806 | ||
|
|
e3f0854771 | ||
|
|
b5d04a21fb | ||
|
|
337b1df430 | ||
|
|
41e64bd79c | ||
|
|
2b7681ec4f | ||
|
|
668c0dfb9b | ||
|
|
0b0f8d6d6c | ||
|
|
a8f956e590 | ||
|
|
3b879ce8c3 | ||
|
|
5102308b2b | ||
|
|
f95a723412 | ||
|
|
88cbc26f4d | ||
|
|
1b53af2e88 | ||
|
|
376107b2ae | ||
|
|
c9294aff6f | ||
|
|
99fb9a3f7c | ||
|
|
e5773cc2fe | ||
|
|
4e6c575fed | ||
|
|
8353ecdf36 | ||
|
|
5bb0b39700 | ||
|
|
9214c887f7 | ||
|
|
ebc2e7bce0 | ||
|
|
065e386c57 | ||
|
|
c595b2fa8c | ||
|
|
eb95bc68c4 | ||
|
|
2b208eecde | ||
|
|
f9f49107ca | ||
|
|
fae116bb2e | ||
|
|
8d90156c07 | ||
|
|
f22d46515b | ||
|
|
27cb3d7f72 | ||
|
|
e0e62232e0 | ||
|
|
a302d210b9 | ||
|
|
a32c72a1b2 | ||
|
|
f1850b54f3 | ||
|
|
c85abf87b5 | ||
|
|
9029ccd21b | ||
|
|
eaeb36375a | ||
|
|
805bc06127 | ||
|
|
4702cd1b51 | ||
|
|
720528ef11 | ||
|
|
d934badaa7 | ||
|
|
35b91ebf2d | ||
|
|
6c7f72cc1b | ||
|
|
7061c8aec2 | ||
|
|
3ba8ae7a62 | ||
|
|
2c27c55679 | ||
|
|
68ad6ad63a | ||
|
|
981b2496cb | ||
|
|
077b727608 | ||
|
|
79f36e85d5 | ||
|
|
d49077c13b | ||
|
|
0c2202ef3e | ||
|
|
e4137cc6ca | ||
|
|
308e4fcce1 | ||
|
|
a6d40e3583 | ||
|
|
95b5745c3c | ||
|
|
bc3134594d | ||
|
|
8300945189 | ||
|
|
c9ca3a05fc | ||
|
|
ecce2bc926 | ||
|
|
b69898257a | ||
|
|
22548d0ea4 | ||
|
|
088ac409d7 | ||
|
|
14ce4cde2e | ||
|
|
83cd515817 | ||
|
|
d48d9a1c88 | ||
|
|
f54cab62a2 | ||
|
|
c64d4236fb | ||
|
|
90568fbf00 | ||
|
|
475a746e46 | ||
|
|
947fc14a3f | ||
|
|
6f6629e568 | ||
|
|
4c4b1da7e7 | ||
|
|
9cc272978c | ||
|
|
5cb6a49c1e | ||
|
|
56d1e4411e | ||
|
|
05510e513b | ||
|
|
5e042803a2 | ||
|
|
74d06101b1 | ||
|
|
2cd3018c0a | ||
|
|
1a8e5a40d6 | ||
|
|
b529c6f282 | ||
|
|
7a05879024 | ||
|
|
1611386431 | ||
|
|
6181686489 | ||
|
|
0562281353 | ||
|
|
8bc1f6e2f5 | ||
|
|
dd99a6dbe8 | ||
|
|
5a686d7ad1 | ||
|
|
0ca0e7d3cc | ||
|
|
f06ef95610 | ||
|
|
0078896347 | ||
|
|
44599d3a84 | ||
|
|
0fa7dcb946 | ||
|
|
d3a8dcb929 | ||
|
|
4e8c1b91c0 | ||
|
|
4ed0d006b4 | ||
|
|
e85804824e | ||
|
|
304f6a577a | ||
|
|
29690afc57 | ||
|
|
98450e80e5 | ||
|
|
1007473a3b | ||
|
|
e875f59ed5 | ||
|
|
4f946ea00e | ||
|
|
666f87109f | ||
|
|
154f315a49 | ||
|
|
b175ec77ad | ||
|
|
f9fa039826 | ||
|
|
b54528696a | ||
|
|
fae64f79bb | ||
|
|
4f297ed3fa | ||
|
|
8eaa440221 | ||
|
|
56d5548747 | ||
|
|
665a341147 | ||
|
|
cab589af9d | ||
|
|
19e355e080 | ||
|
|
1cf2da8d67 | ||
|
|
744625f234 | ||
|
|
5e505898df | ||
|
|
3a1d0e9352 | ||
|
|
8afd0de501 | ||
|
|
1f7a66a22e | ||
|
|
bcc19b7826 | ||
|
|
0a03a55c1e | ||
|
|
61f26c985e | ||
|
|
165e778d7e | ||
|
|
859ddcdb63 | ||
|
|
c599d7aa49 | ||
|
|
da636bd4ac | ||
|
|
834893d8e4 | ||
|
|
059052acaa | ||
|
|
996db972f0 | ||
|
|
4ddc6916c3 | ||
|
|
c06519a759 | ||
|
|
f1e8a49836 | ||
|
|
09cc922b42 | ||
|
|
34c33f7440 | ||
|
|
5464aaac45 | ||
|
|
054e2dbb44 | ||
|
|
59a186b27e | ||
|
|
62a609190d | ||
|
|
9f1d992ef9 | ||
|
|
7cb3d5bc4a | ||
|
|
de27a71a56 | ||
|
|
ed8ddf7e76 | ||
|
|
3860753818 | ||
|
|
2056b891d3 | ||
|
|
c6a6740e3f | ||
|
|
dd1615d57c | ||
|
|
106f066254 | ||
|
|
32b8b60dc5 | ||
|
|
4283b59dde | ||
|
|
be894757ff | ||
|
|
3d0466ccd1 | ||
|
|
92adc524a2 | ||
|
|
0fc30f4379 | ||
|
|
905fdbc1ad | ||
|
|
3a115a1ad2 | ||
|
|
019c72e4fc | ||
|
|
21ecf51a40 | ||
|
|
3c97f7e42e | ||
|
|
de9b0b1c56 | ||
|
|
57a13b09cc | ||
|
|
6a60c4a046 | ||
|
|
f96c02adac | ||
|
|
9351ae7dc9 | ||
|
|
2cde888a6d | ||
|
|
c94434917d | ||
|
|
fb32429387 | ||
|
|
1cc6d2ef62 | ||
|
|
128d650d7d | ||
|
|
090dd78355 | ||
|
|
706df7ab12 | ||
|
|
cfa355c705 | ||
|
|
a87e699104 | ||
|
|
7566bfb548 | ||
|
|
57335cfc26 | ||
|
|
7a6faa093b | ||
|
|
a389312750 | ||
|
|
7d267a340f | ||
|
|
783ef22dd3 | ||
|
|
4f193dfa71 | ||
|
|
c875e5698a | ||
|
|
4cafa3e76e | ||
|
|
1e5ea2827c | ||
|
|
cf5331b9f1 | ||
|
|
28a2e6a775 | ||
|
|
34a327791c | ||
|
|
8bcf5a19d5 | ||
|
|
66a46de2a7 | ||
|
|
bcd496be49 | ||
|
|
79923d0199 | ||
|
|
858b3d2277 | ||
|
|
dedaf624db | ||
|
|
9ca33a260f | ||
|
|
abdf12dc9e | ||
|
|
10d26549fa | ||
|
|
26676c2b8f | ||
|
|
d9cfb05eb6 | ||
|
|
4322e89006 | ||
|
|
96748f3037 | ||
|
|
5a94142481 | ||
|
|
e5ff431b35 | ||
|
|
c225801b3e | ||
|
|
610e3cac31 | ||
|
|
c776991233 | ||
|
|
041fcceddf | ||
|
|
899957f521 | ||
|
|
815d7674ef | ||
|
|
57527ba6f9 | ||
|
|
a21eb04cc6 | ||
|
|
116d0c8145 | ||
|
|
dda49709fe | ||
|
|
ebffa5f9f2 | ||
|
|
fc738680f8 | ||
|
|
1c586ebcfd | ||
|
|
499accb652 | ||
|
|
988147a451 | ||
|
|
9e6c56f9f2 | ||
|
|
1b6eb69f53 | ||
|
|
daa65b6f91 | ||
|
|
7f9626d378 | ||
|
|
6cad60f34b | ||
|
|
b4c7ed999c | ||
|
|
8a5c08df98 | ||
|
|
b1eac64865 | ||
|
|
4e7b559101 | ||
|
|
43616f6f05 | ||
|
|
3b9ab9caa6 | ||
|
|
0dc9ddb77c | ||
|
|
9ab92331c4 | ||
|
|
08416d05ba | ||
|
|
200c82561a | ||
|
|
2e05c6020f | ||
|
|
d139c851f3 | ||
|
|
365e3fd685 | ||
|
|
71fad5e2c0 | ||
|
|
94ba3a20cb | ||
|
|
5a7d3ef319 | ||
|
|
e4a4e6ed81 | ||
|
|
8094e880c6 | ||
|
|
35b9223cf4 | ||
|
|
fe97d14e0f | ||
|
|
2c16557ee7 | ||
|
|
5f8e5db268 | ||
|
|
a9fe3165c4 | ||
|
|
b01036e13e | ||
|
|
10649ae23b | ||
|
|
c4306f7942 | ||
|
|
62be877ada | ||
|
|
546026d018 | ||
|
|
05d3665a14 | ||
|
|
0bba92b2a0 | ||
|
|
399477cd10 | ||
|
|
d3b54ec84a | ||
|
|
e4b44f3488 | ||
|
|
ca80b0445d | ||
|
|
1e01accaa4 | ||
|
|
2ca3735edd | ||
|
|
b9a2639ab4 | ||
|
|
77f186a7b9 | ||
|
|
89e848c820 | ||
|
|
5e0cc123ee | ||
|
|
536c131114 | ||
|
|
ef17d8bba1 | ||
|
|
3194e12479 | ||
|
|
bb52613bea | ||
|
|
4ee065df79 | ||
|
|
63c2834d7b | ||
|
|
dbf2c3d480 | ||
|
|
582d5de497 | ||
|
|
5a351af83f | ||
|
|
a6fc9bf246 | ||
|
|
d52b244ae8 | ||
|
|
00e3cb672b | ||
|
|
67eb732dbe | ||
|
|
c53a5ee427 | ||
|
|
69241907a5 | ||
|
|
d4ee21bd6d | ||
|
|
5b69614e32 | ||
|
|
3e12967535 | ||
|
|
d9f1219a21 | ||
|
|
f3fc4916d2 | ||
|
|
b17ca9cb38 | ||
|
|
801010dac6 | ||
|
|
f84394e550 | ||
|
|
a0256b9e9d | ||
|
|
a37694741c | ||
|
|
fae124a2c1 | ||
|
|
ad100e497a | ||
|
|
da8c09c463 | ||
|
|
6df148aa54 | ||
|
|
3fc9b022b6 | ||
|
|
28ee1c0da2 | ||
|
|
05b306bae1 | ||
|
|
8dbb2083ea | ||
|
|
a8590c7e8e | ||
|
|
8876cda09b | ||
|
|
cec1c5f856 | ||
|
|
a7107d9bbd | ||
|
|
850684438b | ||
|
|
9d00f3b420 | ||
|
|
72264ca9b9 | ||
|
|
da2025a74a | ||
|
|
93bad7a0de | ||
|
|
55f687c763 | ||
|
|
329388fa47 | ||
|
|
0f36dabcaf | ||
|
|
0299e22dd0 | ||
|
|
f072c5af4e | ||
|
|
6982663380 | ||
|
|
1d970ad276 | ||
|
|
a73cc70af9 | ||
|
|
225ee8e5d1 | ||
|
|
fa4cd56d00 | ||
|
|
15f8b0fccc | ||
|
|
97080afba2 | ||
|
|
612822d8c9 | ||
|
|
ff6cb921c3 | ||
|
|
6f7b7c552d | ||
|
|
e00186e683 | ||
|
|
a734b3b1bc | ||
|
|
6de637811f | ||
|
|
6ec0c6743a | ||
|
|
299c86cc84 | ||
|
|
d123f6c04b | ||
|
|
3c17bf1a6f | ||
|
|
8fb20e4529 | ||
|
|
e020d1055a | ||
|
|
05e4b28a74 | ||
|
|
27bc688ed8 | ||
|
|
a214fb2821 | ||
|
|
6b7b9d1550 | ||
|
|
18b873b2e3 | ||
|
|
d1755c1484 | ||
|
|
152ebb104d | ||
|
|
e3b304997f | ||
|
|
1e20ed4849 | ||
|
|
59b663c43d | ||
|
|
e9e28c1265 | ||
|
|
7030d612e2 | ||
|
|
2c852b0d74 | ||
|
|
708bff3b17 | ||
|
|
317f4c5ff5 | ||
|
|
2c025824d7 | ||
|
|
9b95064018 | ||
|
|
ecdffe531e | ||
|
|
31be6be147 | ||
|
|
305a4a1b57 | ||
|
|
e659f1b15a | ||
|
|
2c49592216 | ||
|
|
6afb2743e7 | ||
|
|
f7b458841f | ||
|
|
f1e9b8299f | ||
|
|
9ce1b8986a | ||
|
|
c5bea8dddb | ||
|
|
ba6b502cc9 | ||
|
|
3b0b5f92a7 | ||
|
|
d6bc1b3cbc | ||
|
|
199c4e55f2 | ||
|
|
61339353e9 | ||
|
|
3b2dda5197 | ||
|
|
1b8ed9abf0 | ||
|
|
f9453ef93d | ||
|
|
dcf571c1cd | ||
|
|
538c56426a | ||
|
|
1402e78844 | ||
|
|
01f0c8ef16 | ||
|
|
a774406b91 | ||
|
|
c9bff93080 | ||
|
|
4b8e4ff248 | ||
|
|
9dbf979cf3 | ||
|
|
ad70ab8957 | ||
|
|
cd5dc4d05f | ||
|
|
ebb9384681 | ||
|
|
0d3fde04ff | ||
|
|
0552ec5791 | ||
|
|
524eef9225 | ||
|
|
955f7e2877 | ||
|
|
e28834aa15 | ||
|
|
ac03786412 | ||
|
|
a5dae2ff43 | ||
|
|
1d0142d25d | ||
|
|
65ef597da6 | ||
|
|
310beae373 | ||
|
|
cf0caaec11 | ||
|
|
4af9504a65 | ||
|
|
64bece146c | ||
|
|
6b348b94e3 | ||
|
|
6222040888 | ||
|
|
ea1037742d | ||
|
|
465d46e9dd | ||
|
|
e71e4da388 | ||
|
|
c711e969cc | ||
|
|
3f1ec39a8d | ||
|
|
f62798cb8b | ||
|
|
b6c89984a9 | ||
|
|
520ecb0c4d | ||
|
|
b669495d97 | ||
|
|
8778c551eb | ||
|
|
c34d313a86 | ||
|
|
ebcb3a22b8 | ||
|
|
6781d01e89 | ||
|
|
4c9f30a869 | ||
|
|
61ba1c3026 | ||
|
|
90bbea65c1 | ||
|
|
672e9f4abc | ||
|
|
cb3d458050 | ||
|
|
b72ff61899 | ||
|
|
83b9727c42 | ||
|
|
7bb8b5ba9e | ||
|
|
1f5f6adcb6 | ||
|
|
aa0bb29404 | ||
|
|
2264ea7714 | ||
|
|
a626b26cf9 | ||
|
|
1cc860216e | ||
|
|
16ee476a77 | ||
|
|
674ecc3b56 | ||
|
|
43efee5232 | ||
|
|
5dab23ea98 | ||
|
|
79afd2d580 | ||
|
|
a8e8919bbf | ||
|
|
ba0f4f17ed | ||
|
|
a63b3c4fe6 | ||
|
|
6b8c75d87c | ||
|
|
68d82abe52 | ||
|
|
ec31f235e9 | ||
|
|
7e9d90b180 | ||
|
|
d4fcbe37f3 | ||
|
|
b9a5f764ba | ||
|
|
764b70d7e6 | ||
|
|
a1496b90e5 | ||
|
|
622d6d5504 | ||
|
|
1b903111b6 | ||
|
|
69ef694178 | ||
|
|
81651b47a4 | ||
|
|
30dc86179c | ||
|
|
eff3ac05b3 | ||
|
|
e5349d47a8 | ||
|
|
4253adf42b | ||
|
|
088ed65194 | ||
|
|
0ce94950b7 | ||
|
|
ae8b2684d7 | ||
|
|
9c51f679a7 | ||
|
|
5c07acad46 | ||
|
|
70af759dd2 | ||
|
|
76191a0f55 | ||
|
|
f0c3114f2f |
1
.flake8
1
.flake8
@@ -152,7 +152,6 @@ exclude =
|
||||
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
|
||||
# other third-party libraries
|
||||
tools/kconfig_new/kconfiglib.py,
|
||||
tools/kconfig_new/menuconfig.py,
|
||||
# autogenerated scripts
|
||||
components/protocomm/python/constants_pb2.py,
|
||||
components/protocomm/python/sec0_pb2.py,
|
||||
|
||||
16
.github/ISSUE_TEMPLATE/config.yml
vendored
16
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,16 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: ESP-IDF Programming Guide
|
||||
url: https://docs.espressif.com/projects/esp-idf/en/latest/
|
||||
about: Documentation for configuring and using ESP-IDF
|
||||
- name: Espressif documentation page
|
||||
url: https://www.espressif.com/en/support/download/documents
|
||||
about: Hardware documentation (datasheets, Technical Reference Manual, etc)
|
||||
- name: Forum
|
||||
url: https://esp32.com
|
||||
about: For questions about using ESP-IDF and/or ESP32 series chips. Please submit all questions starting "How do I..." here.
|
||||
- name: Hardware-related services
|
||||
url: https://www.espressif.com/en/products/hardware-services
|
||||
about: Espressif service providing hardware design and certification support
|
||||
|
||||
|
||||
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for ESP-IDF
|
||||
title: ''
|
||||
labels: 'Type: Feature Request'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
Please give as many details as you can. Include suggestions for useful APIs or interfaces if relevant.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
22
.github/main.workflow
vendored
Normal file
22
.github/main.workflow
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
workflow "Sync issues to JIRA" {
|
||||
on = "issues"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync issue and PR comments to JIRA" {
|
||||
on = "issue_comment"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync PRs to JIRA" {
|
||||
on = "pull_request"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
action "Sync to JIRA" {
|
||||
uses = "espressif/github-actions/sync_issues_to_jira@master"
|
||||
secrets = ["GITHUB_TOKEN", "JIRA_URL", "JIRA_USER", "JIRA_PASS"]
|
||||
env = {
|
||||
JIRA_PROJECT = "IDFGH"
|
||||
}
|
||||
}
|
||||
19
.github/workflows/issue_comment.yml
vendored
19
.github/workflows/issue_comment.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Sync issue comments to JIRA
|
||||
|
||||
# This workflow will be triggered when new issue comment is created (including PR comments)
|
||||
on: issue_comment
|
||||
|
||||
jobs:
|
||||
sync_issue_comments_to_jira:
|
||||
name: Sync Issue Comments to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync issue comments to JIRA
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
19
.github/workflows/new_issues.yml
vendored
19
.github/workflows/new_issues.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Sync issues to Jira
|
||||
|
||||
# This workflow will be triggered when a new issue is opened
|
||||
on: issues
|
||||
|
||||
jobs:
|
||||
sync_issues_to_jira:
|
||||
name: Sync issues to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync GitHub issues to Jira project
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
24
.github/workflows/new_prs.yml
vendored
24
.github/workflows/new_prs.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Sync remain PRs to Jira
|
||||
|
||||
# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
|
||||
# Note that, PRs can also get synced when new PR comment is created
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 * * * *"
|
||||
|
||||
jobs:
|
||||
sync_prs_to_jira:
|
||||
name: Sync PRs to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync PRs to Jira project
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
with:
|
||||
cron_job: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
32
.github/workflows/python_lint.yml
vendored
32
.github/workflows/python_lint.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: Python CI
|
||||
|
||||
# This workflow will be triggered when a PR modifies some python relevant files
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "**.py"
|
||||
- "requirements.txt"
|
||||
|
||||
jobs:
|
||||
python_lint:
|
||||
name: python lint
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.5, 3.6, 3.7]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
pip install flake8
|
||||
flake8 . --config=.flake8
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -63,20 +63,8 @@ test_multi_heap_host
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
|
||||
# VIM files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Clion IDE CMake build & config
|
||||
.idea/
|
||||
cmake-build-*/
|
||||
|
||||
# Results for the checking of the Python coding style and static analysis
|
||||
.mypy_cache
|
||||
# Results for the checking of the Python coding style
|
||||
flake8_output.txt
|
||||
|
||||
# ESP-IDF default build directory name
|
||||
# ESP-IDF library
|
||||
build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
@@ -1,10 +1,9 @@
|
||||
stages:
|
||||
- pre_check
|
||||
- build
|
||||
- assign_test
|
||||
- host_test
|
||||
- target_test
|
||||
- post_check
|
||||
- check
|
||||
- deploy
|
||||
- post_check
|
||||
|
||||
@@ -16,8 +15,9 @@ variables:
|
||||
|
||||
# GitLab-CI environment
|
||||
|
||||
# XXX_ATTEMPTS variables (https://docs.gitlab.com/ce/ci/yaml/README.html#job-stages-attempts) are not defined here.
|
||||
# Use values from "CI / CD Settings" - "Variables".
|
||||
# more attempts for more robust
|
||||
GET_SOURCES_ATTEMPTS: "10"
|
||||
ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
|
||||
|
||||
# GIT_STRATEGY is not defined here.
|
||||
# Use an option from "CI / CD Settings" - "General pipelines".
|
||||
@@ -34,24 +34,19 @@ variables:
|
||||
IDF_SKIP_CHECK_SUBMODULES: 1
|
||||
|
||||
UNIT_TEST_BUILD_SYSTEM: cmake
|
||||
EXAMPLE_TEST_BUILD_SYSTEM: cmake
|
||||
# IDF environment
|
||||
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
BATCH_BUILD: "1"
|
||||
V: "0"
|
||||
APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py"
|
||||
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
|
||||
CUSTOM_TOOLCHAIN_PATH: "/opt/xtensa-custom"
|
||||
|
||||
# Docker images
|
||||
# Docker images
|
||||
BOT_DOCKER_IMAGE_TAG: ":latest"
|
||||
# target test config file, used by assign test job
|
||||
# target test config file, used by assign test job
|
||||
CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/tools/ci/config/target-test.yml"
|
||||
# target test repo parameters
|
||||
TEST_ENV_CONFIG_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/ci-test-runner-configs.git"
|
||||
CI_AUTO_TEST_SCRIPT_REPO_URL: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/auto_test_script.git"
|
||||
CI_AUTO_TEST_SCRIPT_REPO_BRANCH: "ci/v3.1"
|
||||
|
||||
# Versioned esp-idf-doc env image to use for all document building jobs
|
||||
ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v7"
|
||||
|
||||
|
||||
|
||||
@@ -59,8 +54,27 @@ variables:
|
||||
.apply_bot_filter: &apply_bot_filter
|
||||
python $APPLY_BOT_FILTER_SCRIPT || exit 0
|
||||
|
||||
.setup_custom_toolchain: &setup_custom_toolchain |
|
||||
if [ "$IDF_XTENSA_TOOLCHAIN_URL" ] ; then
|
||||
echo "Use a custom toolchain: ${IDF_XTENSA_TOOLCHAIN_URL:-Unknown}"
|
||||
rm -rf "$CUSTOM_TOOLCHAIN_PATH" &&
|
||||
mkdir -p -v "$CUSTOM_TOOLCHAIN_PATH" &&
|
||||
pushd "$CUSTOM_TOOLCHAIN_PATH" &&
|
||||
curl -sSL -o xtensa-custom.xxx "$IDF_XTENSA_TOOLCHAIN_URL" &&
|
||||
ls -l xtensa-custom.xxx &&
|
||||
tar xf xtensa-custom.xxx --strip-components 1 &&
|
||||
ls -l . &&
|
||||
popd
|
||||
PATH=$CUSTOM_TOOLCHAIN_PATH/bin:$PATH
|
||||
export PATH
|
||||
fi
|
||||
|
||||
.cleanup_custom_toolchain: &cleanup_custom_toolchain |
|
||||
echo "Cleaning up $CUSTOM_TOOLCHAIN_PATH"
|
||||
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
|
||||
|
||||
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
|
||||
if [[ "$SETUP_TOOLS" == "1" || "$CI_JOB_STAGE" != "target_test" ]]; then
|
||||
if [ "$CI_JOB_STAGE" != "target_test" ]; then
|
||||
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
||||
fi
|
||||
|
||||
@@ -80,10 +94,13 @@ before_script:
|
||||
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
# Set some options and environment for CI
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
|
||||
- *setup_tools_unless_target_test
|
||||
|
||||
- *fetch_submodules
|
||||
|
||||
- *setup_custom_toolchain
|
||||
|
||||
# used for check scripts which we want to run unconditionally
|
||||
.before_script_lesser_nofilter:
|
||||
variables:
|
||||
@@ -92,6 +109,7 @@ before_script:
|
||||
- echo "Not setting up GitLab key, not fetching submodules, not applying bot filter"
|
||||
- source tools/ci/setup_python.sh
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
- *setup_custom_toolchain
|
||||
|
||||
# used for everything else where we want to do no prep, except for bot filter
|
||||
.before_script_lesser:
|
||||
@@ -103,9 +121,13 @@ before_script:
|
||||
# apply bot filter in before script
|
||||
- *apply_bot_filter
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
- *setup_custom_toolchain
|
||||
|
||||
after_script:
|
||||
- *cleanup_custom_toolchain
|
||||
|
||||
.check_job_template:
|
||||
stage: pre_check
|
||||
stage: check
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- host_test
|
||||
@@ -113,37 +135,17 @@ before_script:
|
||||
extends: .before_script_lesser_nofilter
|
||||
|
||||
.check_job_template_with_filter:
|
||||
stage: pre_check
|
||||
stage: check
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- host_test
|
||||
dependencies: []
|
||||
extends: .before_script_lesser_nofilter
|
||||
|
||||
.macos_build_template:
|
||||
stage: build
|
||||
tags:
|
||||
- macos_shell
|
||||
dependencies: []
|
||||
before_script:
|
||||
- *apply_bot_filter
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env
|
||||
# On macOS, these tools need to be installed
|
||||
- $IDF_PATH/tools/idf_tools.py --non-interactive install cmake ninja
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
- *setup_tools_unless_target_test
|
||||
# Install packages required by CI scripts into IDF Python environment
|
||||
- pip install -r $IDF_PATH/tools/ci/python_packages/ttfw_idf/requirements.txt
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
# Part of tools/ci/setup_python.sh; we don't use pyenv on macOS, so can't run the rest of the script.
|
||||
- export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
|
||||
- *fetch_submodules
|
||||
|
||||
include:
|
||||
- '/tools/ci/config/pre_check.yml'
|
||||
- '/tools/ci/config/build.yml'
|
||||
- '/tools/ci/config/assign-test.yml'
|
||||
- '/tools/ci/config/host-test.yml'
|
||||
- '/tools/ci/config/target-test.yml'
|
||||
- '/tools/ci/config/post_check.yml'
|
||||
- '/tools/ci/config/check.yml'
|
||||
- '/tools/ci/config/deploy.yml'
|
||||
|
||||
13
.gitmodules
vendored
13
.gitmodules
vendored
@@ -67,15 +67,10 @@
|
||||
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
|
||||
url = ../../leethomason/tinyxml2.git
|
||||
|
||||
[submodule "components/esp_wifi/lib_esp32"]
|
||||
path = components/esp_wifi/lib_esp32
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/bt/host/nimble/nimble"]
|
||||
path = components/bt/host/nimble/nimble
|
||||
url = ../../espressif/esp-nimble.git
|
||||
|
||||
[submodule "components/cbor/tinycbor"]
|
||||
path = components/cbor/tinycbor
|
||||
url = ../../intel/tinycbor.git
|
||||
|
||||
[submodule "components/esp_wifi/lib"]
|
||||
path = components/esp_wifi/lib
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
|
||||
7
.travis.yml
Normal file
7
.travis.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
language: python
|
||||
sudo: false
|
||||
python:
|
||||
- "3.4"
|
||||
script:
|
||||
- pip install flake8
|
||||
- travis_wait 20 python -m flake8 --config=.flake8 .
|
||||
@@ -1,12 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(esp-idf C CXX ASM)
|
||||
|
||||
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
|
||||
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
|
||||
"again.")
|
||||
endif()
|
||||
|
||||
unset(compile_options)
|
||||
unset(c_compile_options)
|
||||
unset(cxx_compile_options)
|
||||
@@ -16,32 +10,11 @@ unset(link_options)
|
||||
# Add the following build specifications here, since these seem to be dependent
|
||||
# on config values on the root Kconfig.
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
|
||||
else() # BOOTLOADER_BUILD
|
||||
|
||||
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
else()
|
||||
list(APPEND compile_options "-Og")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||
@@ -62,16 +35,19 @@ if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
|
||||
"-Wno-sizeof-pointer-memaccess"
|
||||
"-Wno-clobbered")
|
||||
|
||||
list(APPEND compile_options "-Wno-format-overflow"
|
||||
"-Wno-stringop-truncation"
|
||||
"-Wno-misleading-indentation"
|
||||
"-Wno-cast-function-type"
|
||||
"-Wno-implicit-fallthrough"
|
||||
"-Wno-unused-const-variable"
|
||||
"-Wno-switch-unreachable"
|
||||
"-Wno-format-truncation"
|
||||
"-Wno-memset-elt-size"
|
||||
"-Wno-int-in-bool-context")
|
||||
# doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before
|
||||
if(GCC_NOT_5_2_0)
|
||||
list(APPEND compile_options "-Wno-format-overflow"
|
||||
"-Wno-stringop-truncation"
|
||||
"-Wno-misleading-indentation"
|
||||
"-Wno-cast-function-type"
|
||||
"-Wno-implicit-fallthrough"
|
||||
"-Wno-unused-const-variable"
|
||||
"-Wno-switch-unreachable"
|
||||
"-Wno-format-truncation"
|
||||
"-Wno-memset-elt-size"
|
||||
"-Wno-int-in-bool-context")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
|
||||
|
||||
180
Kconfig
180
Kconfig
@@ -4,13 +4,21 @@
|
||||
#
|
||||
mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
# Hidden option to support checking for this specific target in C code and Kconfig files
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
default "n"
|
||||
|
||||
config IDF_CMAKE
|
||||
bool
|
||||
option env="IDF_CMAKE"
|
||||
|
||||
config IDF_ENV_FPGA
|
||||
# This option is for internal use only
|
||||
bool
|
||||
|
||||
config IDF_TARGET_ENV
|
||||
# A proxy to get environment variable $IDF_TARGET
|
||||
string
|
||||
option env="IDF_TARGET"
|
||||
|
||||
config IDF_TARGET
|
||||
# This option records the IDF target when sdkconfig is generated the first time.
|
||||
@@ -18,39 +26,29 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
# the build system is responsible for detecting the mismatch between
|
||||
# CONFIG_IDF_TARGET and $IDF_TARGET.
|
||||
string
|
||||
default "$IDF_TARGET"
|
||||
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
|
||||
config IDF_TARGET_ESP32S2BETA
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s2beta"
|
||||
select FREERTOS_UNICORE
|
||||
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
|
||||
default IDF_TARGET_ENV
|
||||
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
default 0x0000 if IDF_TARGET_ESP32
|
||||
# note: S2 beta uses Chip ID 0 still, S2 will use 0x0002
|
||||
default 0x0000 if IDF_TARGET_ESP32S2BETA
|
||||
default 0x0000 if IDF_TARGET="esp32"
|
||||
default 0xFFFF
|
||||
|
||||
menu "SDK tool configuration"
|
||||
config SDK_TOOLPREFIX
|
||||
string "Compiler toolchain path/prefix"
|
||||
default "xtensa-esp32-elf-" if IDF_TARGET_ESP32
|
||||
default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2BETA
|
||||
default "xtensa-esp32-elf-"
|
||||
help
|
||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||
a crosstool-ng gcc setup that is in your PATH.
|
||||
|
||||
config SDK_PYTHON
|
||||
string "Python interpreter"
|
||||
string "Python 2 interpreter"
|
||||
depends on !IDF_CMAKE
|
||||
default "python"
|
||||
help
|
||||
The executable name/path that is used to run python.
|
||||
The executable name/path that is used to run python. On some systems Python 2.x
|
||||
may need to be invoked as python2.
|
||||
|
||||
(Note: This option is used with the legacy GNU Make build system only.)
|
||||
|
||||
@@ -68,139 +66,32 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
(Note: this option is used with the legacy GNU Make build system only.)
|
||||
|
||||
config SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
|
||||
bool "Toolchain supports time_t wide 64-bits"
|
||||
default n
|
||||
help
|
||||
Enable this option in case you have a custom toolchain which supports time_t wide 64-bits.
|
||||
This option checks time_t is 64-bits and disables ROM time functions
|
||||
to use the time functions from the toolchain instead.
|
||||
This option allows resolving the Y2K38 problem.
|
||||
See "Setup Linux Toolchain from Scratch" to build
|
||||
a custom toolchain which supports 64-bits time_t.
|
||||
|
||||
Note: ESP-IDF does not currently come with any pre-compiled toolchain
|
||||
that supports 64-bit wide time_t.
|
||||
This will change in a future major release,
|
||||
but currently 64-bit time_t requires a custom built toolchain.
|
||||
|
||||
endmenu # SDK tool configuration
|
||||
|
||||
menu "Build type"
|
||||
|
||||
choice APP_BUILD_TYPE
|
||||
prompt "Application build type"
|
||||
default APP_BUILD_TYPE_APP_2NDBOOT
|
||||
help
|
||||
Select the way the application is built.
|
||||
|
||||
By default, the application is built as a binary file in a format compatible with
|
||||
the ESP32 bootloader. In addition to this application, 2nd stage bootloader is
|
||||
also built. Application and bootloader binaries can be written into flash and
|
||||
loaded/executed from there.
|
||||
|
||||
Another option, useful for only very small and limited applications, is to only link
|
||||
the .elf file of the application, such that it can be loaded directly into RAM over
|
||||
JTAG. Note that since IRAM and DRAM sizes are very limited, it is not possible to
|
||||
build any complex application this way. However for kinds of testing and debugging,
|
||||
this option may provide faster iterations, since the application does not need to be
|
||||
written into flash.
|
||||
Note that at the moment, ESP-IDF does not contain all the startup code required to
|
||||
initialize the CPUs and ROM memory (data/bss). Therefore it is necessary to execute
|
||||
a bit of ROM code prior to executing the application. A gdbinit file may look as follows:
|
||||
|
||||
# Connect to a running instance of OpenOCD
|
||||
target remote :3333
|
||||
# Reset and halt the target
|
||||
mon reset halt
|
||||
# Run to a specific point in ROM code,
|
||||
# where most of initialization is complete.
|
||||
thb *0x40007901
|
||||
c
|
||||
# Load the application into RAM
|
||||
load
|
||||
# Run till app_main
|
||||
tb app_main
|
||||
c
|
||||
|
||||
Execute this gdbinit file as follows:
|
||||
|
||||
xtensa-esp32-elf-gdb build/app-name.elf -x gdbinit
|
||||
|
||||
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
|
||||
CONFIG_APP_BUILD_TYPE_ELF_RAM is required, other options help reduce application
|
||||
memory footprint.
|
||||
|
||||
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||
|
||||
|
||||
config APP_BUILD_TYPE_APP_2NDBOOT
|
||||
bool
|
||||
prompt "Default (binary application + 2nd stage bootloader)"
|
||||
select APP_BUILD_GENERATE_BINARIES
|
||||
select APP_BUILD_BOOTLOADER
|
||||
select APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
config APP_BUILD_TYPE_ELF_RAM
|
||||
bool
|
||||
prompt "ELF file, loadable into RAM (EXPERIMENTAL))"
|
||||
endchoice # APP_BUILD_TYPE
|
||||
|
||||
# Hidden options, set according to the choice above
|
||||
config APP_BUILD_GENERATE_BINARIES
|
||||
bool # Whether to generate .bin files or not
|
||||
|
||||
config APP_BUILD_BOOTLOADER
|
||||
bool # Whether to build the bootloader
|
||||
|
||||
config APP_BUILD_USE_FLASH_SECTIONS
|
||||
bool # Whether to place code/data into memory-mapped flash sections
|
||||
|
||||
endmenu # Build type
|
||||
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE"
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||
|
||||
menu "Compiler options"
|
||||
|
||||
choice COMPILER_OPTIMIZATION
|
||||
prompt "Optimization Level"
|
||||
default COMPILER_OPTIMIZATION_DEFAULT
|
||||
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument) for the app.
|
||||
This option sets compiler optimization level (gcc -O argument).
|
||||
|
||||
- The "Default" setting will add the -0g flag to CFLAGS.
|
||||
- The "Size" setting will add the -0s flag to CFLAGS.
|
||||
- The "Performance" setting will add the -O2 flag to CFLAGS.
|
||||
- The "None" setting will add the -O0 flag to CFLAGS.
|
||||
- for "Release" setting, -Os flag is added to CFLAGS.
|
||||
- for "Debug" setting, -Og flag is added to CFLAGS.
|
||||
|
||||
The "Size" setting cause the compiled code to be smaller and faster, but
|
||||
may lead to difficulties of correlating code addresses to source file
|
||||
lines when debugging.
|
||||
"Release" with -Os produces smaller & faster compiled code but it
|
||||
may be harder to correlated code addresses to source files when debugging.
|
||||
|
||||
The "Performance" setting causes the compiled code to be larger and faster,
|
||||
but will be easier to correlated code addresses to source file lines.
|
||||
To add custom optimization settings, set CFLAGS and/or CPPFLAGS
|
||||
in project makefile, before including $(IDF_PATH)/make/project.mk. Note that
|
||||
custom optimization levels may be unsupported.
|
||||
|
||||
"None" with -O0 produces compiled code without optimization.
|
||||
|
||||
Note that custom optimization levels may be unsupported.
|
||||
|
||||
Compiler optimization for the IDF bootloader is set separately,
|
||||
see the BOOTLOADER_COMPILER_OPTIMIZATION setting.
|
||||
|
||||
config COMPILER_OPTIMIZATION_DEFAULT
|
||||
config COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config COMPILER_OPTIMIZATION_SIZE
|
||||
bool "Optimize for size (-Os)"
|
||||
config COMPILER_OPTIMIZATION_PERF
|
||||
bool "Optimize for performance (-O2)"
|
||||
config COMPILER_OPTIMIZATION_NONE
|
||||
bool "Debug without optimization (-O0)"
|
||||
|
||||
config COMPILER_OPTIMIZATION_LEVEL_RELEASE
|
||||
bool "Release (-Os)"
|
||||
endchoice
|
||||
|
||||
choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
@@ -259,8 +150,9 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
memory for thrown exceptions when there is not enough memory on the heap.
|
||||
|
||||
config COMPILER_CXX_RTTI
|
||||
bool "Enable C++ run-time type info (RTTI)"
|
||||
default n
|
||||
# Invisible option, until the toolchain with RTTI support is released.
|
||||
# Use prompt "Enable C++ run-time type info (RTTI)" when updating.
|
||||
bool
|
||||
help
|
||||
Enabling this option compiles all C++ files with RTTI support enabled.
|
||||
This increases binary size (typically by tens of kB) but allows using
|
||||
@@ -332,12 +224,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
endmenu # Compiler Options
|
||||
|
||||
menu "Component config"
|
||||
source "$COMPONENT_KCONFIGS_SOURCE_FILE"
|
||||
source "$COMPONENT_KCONFIGS"
|
||||
endmenu
|
||||
|
||||
menu "Compatibility options"
|
||||
config LEGACY_INCLUDE_COMMON_HEADERS
|
||||
bool "Include headers across components as before IDF v4.0"
|
||||
bool "Include headers accross components as before IDF v4.0"
|
||||
default n
|
||||
help
|
||||
Soc, esp32, and driver components, the most common
|
||||
|
||||
24
README.md
24
README.md
@@ -1,10 +1,8 @@
|
||||
# Espressif IoT Development Framework
|
||||
|
||||
* [中文版](./README_CN.md)
|
||||
|
||||
[](https://docs.espressif.com/projects/esp-idf/en/latest/?badge=latest)
|
||||
|
||||
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip provided for Windows, Linux and macOS.
|
||||
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip.
|
||||
|
||||
# Developing With ESP-IDF
|
||||
|
||||
@@ -37,15 +35,25 @@ See the Getting Started guide links above for a detailed setup guide. This is a
|
||||
|
||||
## Setup Build Environment
|
||||
|
||||
(See the Getting Started guide listed above for a full list of required steps with more details.)
|
||||
(See Getting Started guide for a full list of required steps with details.)
|
||||
|
||||
* Install host build dependencies mentioned in the Getting Started guide.
|
||||
* Run the install script to set up the build environment. The options include `install.bat` or `install.ps1` for Windows, and `install.sh` for Unix shells.
|
||||
* Run the export script on Windows (`export.bat`) or source it on Unix (`source export.sh`) in every shell environment before using ESP-IDF.
|
||||
* Install host build dependencies mentioned in Getting Started guide.
|
||||
* Add `tools/` directory to the PATH
|
||||
* Run `python -m pip install -r requirements.txt` to install Python dependencies
|
||||
|
||||
## Configuring the Project
|
||||
|
||||
`idf.py menuconfig` opens a text-based configuration menu where you can configure the project.
|
||||
`idf.py menuconfig`
|
||||
|
||||
* Opens a text-based configuration menu for the project.
|
||||
* Use up & down arrow keys to navigate the menu.
|
||||
* Use Enter key to go into a submenu, Escape key to go out or to exit.
|
||||
* Type `?` to see a help screen. Enter key exits the help screen.
|
||||
* Use Space key, or `Y` and `N` keys to enable (Yes) and disable (No) configuration items with checkboxes "`[*]`"
|
||||
* Pressing `?` while highlighting a configuration item displays help about that item.
|
||||
* Type `/` to search the configuration items.
|
||||
|
||||
Once done configuring, press Escape multiple times to exit and say "Yes" to save the new configuration when prompted.
|
||||
|
||||
## Compiling the Project
|
||||
|
||||
|
||||
112
README_CN.md
112
README_CN.md
@@ -1,112 +0,0 @@
|
||||
# Espressif 物联网开发框架
|
||||
|
||||
* [English Version](./README.md)
|
||||
|
||||
[](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/?badge=latest)
|
||||
|
||||
ESP-IDF 是由乐鑫官方推出的针对 [ESP32](https://espressif.com/en/products/hardware/esp32/overview) 系列芯片的开发框架。
|
||||
|
||||
# 使用 ESP-IDF 进行开发
|
||||
|
||||
## 搭建 ESP-IDF 开发环境
|
||||
|
||||
请参阅如下指南搭建 ESP-IDF 的开发环境:
|
||||
|
||||
* [ESP-IDF 稳定版本的入门指南](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
|
||||
* [ESP-IDF 开发版本(master 分支)的入门指南](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
|
||||
|
||||
### 非 GitHub 分叉的 ESP-IDF 项目
|
||||
|
||||
ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodules)),所以它们会指向 GitHub。
|
||||
如果 ESP-IDF 被分叉到的仓库不在 GitHub 上,那么你需要在克隆结束后运行该[脚本](tools/set-submodules-to-github.sh)。它会为所有的子模块设置绝对路径,接着可以通过 `git submodule update --init --recursive` 完成子模块的更新。
|
||||
如果 ESP-IDF 是从 GitHub 上克隆得到,则不需要此步骤。
|
||||
|
||||
## 寻找项目
|
||||
|
||||
除了入门指南中提到的 [esp-idf 模板项目](https://github.com/espressif/esp-idf-template),ESP-IDF 的 [examples](examples) 目录下还带有很多其它示例项目。
|
||||
|
||||
一旦找到了需要的项目,便可以进入该目录,执行配置和构建操作。
|
||||
|
||||
如果要基于示例工程开始你自己的项目,请将示例工程复制到 ESP-IDF 目录之外。
|
||||
|
||||
# 快速参考
|
||||
|
||||
详细的使用方法请参考上面入门指南的链接,这里仅仅列举一些 ESP-IDF 项目开发中常用的命令:
|
||||
|
||||
## 设置构建环境
|
||||
|
||||
(请参考入门指南中列出的详细步骤。)
|
||||
* 在主机中安装入门指南中提到的构建所依赖的工具。
|
||||
* 将 ESP-IDF 中的 `tools/` 目录加入 PATH 环境变量中。
|
||||
* 运行 `python -m pip install -r requirements.txt` 安装 Python 依赖库。
|
||||
|
||||
## 配置项目
|
||||
|
||||
`idf.py menuconfig`
|
||||
|
||||
* 打开项目的文本配置菜单。
|
||||
* 使用上下键浏览菜单。
|
||||
* 使用回车键进入子菜单,退出键返回上一级菜单或者退出配置。
|
||||
* 输入 `?` 查看帮助界面,按下回车键可以退出帮助界面。
|
||||
* 使用空格键或者 `Y` 和 `N` 按键来启用和禁用带复选框“`[*]`”的配置项。
|
||||
* 高亮某个配置项的同时按下 `?` 键可以显示该选项的帮助文档。
|
||||
* 输入 `/` 可以搜索指定的配置项。
|
||||
|
||||
一旦配置完成,请按下退出键多次以退出配置界面,当提示是否保存新的的配置时,选择 “Yes”。
|
||||
|
||||
## 编译项目
|
||||
|
||||
`idf.py build`
|
||||
|
||||
编译应用程序,引导程序,并根据配置生成分区表。
|
||||
|
||||
## 烧写项目
|
||||
|
||||
当构建结束,终端会打印出一条命令行,告知如何使用 esptool.py 工具烧写项目到芯片中。但是你还可以运行下面这条命令来自动烧写:
|
||||
|
||||
`idf.py -p PORT flash`
|
||||
|
||||
将其中的 PORT 替换为系统中实际串口的名字(比如 Windows 下的 `COM3`,Linux 下的 `/dev/ttyUSB0`,或者 MacOS 下的 `/dev/cu.usbserial-X`。如果省略 `-p` 选项,`idf.py flash` 会尝试使用第一个可用的串口进行烧写。
|
||||
|
||||
这会烧写整个项目(包括应用程序,引导程序和分区表)到芯片中,此外还可以使用 `idf.py menuconfig` 来调整串口烧写相关的配置。
|
||||
|
||||
你也不必先运行 `idf.py build`,再运行 `idf.py flash`,`idf.py flash` 会根据需要自动重新构建项目。
|
||||
|
||||
## 观察串口输入
|
||||
|
||||
`idf.py monitor` 会调用 [idf_monitor 工具](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html)来显示 ESP32 的串口输出。`idf_monitor` 还包含一系列的功能来解析程序崩溃后的输出结果并与设备进行交互。更多详细内容,请参阅[文档](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
|
||||
|
||||
输入 `Ctrl-]` 可退出监视器。
|
||||
|
||||
想要一次性执行构建,烧写和监视,可以运行如下命令:
|
||||
|
||||
`idf.py flash monitor`
|
||||
|
||||
## 仅编译并烧写应用程序
|
||||
|
||||
在第一次烧写过后,你可能只想构建并烧写你的应用程序,不包括引导程序和分区表:
|
||||
|
||||
* `idf.py app` - 仅构建应用程序。
|
||||
* `idf.py app-flash` - 仅烧写应用程序。
|
||||
|
||||
`idf.py app-flash` 会自动判断是否有源文件发生了改变而后重新构建应用程序。
|
||||
|
||||
(在正常的开发中,即使引导程序和分区表没有发生变化,每次都重新烧写它们并不会带来什么危害。)
|
||||
|
||||
## 擦除 Flash
|
||||
|
||||
`idf.py flash` 并不会擦除 Flash 上所有的内容,但是有时候我们需要设备恢复到完全擦除的状态,尤其是分区表发生了变化或者 OTA 应用升级。要擦除整块 Flash 请运行 `idf.py erase_flash`。
|
||||
|
||||
这条命令还可以和其余命令整合在一起,`idf.py -p PORT erase_flash flash` 会擦除一切然后重新烧写新的应用程序,引导程序和分区表。
|
||||
|
||||
# 其它参考资源
|
||||
|
||||
* 最新版的文档:https://docs.espressif.com/projects/esp-idf/ ,该文档是由本仓库 [docs 目录](docs) 构建得到。
|
||||
|
||||
* 可以前往 [esp32.com 论坛](https://esp32.com/) 提问,挖掘社区资源。
|
||||
|
||||
* 如果你在使用中发现了错误或者需要新的功能,请先[查看 GitHub Issues](https://github.com/espressif/esp-idf/issues),确保该问题不会被重复提交。
|
||||
|
||||
* 如果你有兴趣为 ESP-IDF 作贡献,请先阅读[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html)。
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ The latest support policy for ESP-IDF can be found at [https://github.com/espres
|
||||
Support Period Policy
|
||||
=====================
|
||||
|
||||
* [中文版](./SUPPORT_POLICY_CN.md)
|
||||
|
||||
Each ESP-IDF major and minor release (V4.0, V4.1, etc) is supported for
|
||||
18 months after the initial stable release date.
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
有关 ESP-IDF 的最新支持政策,详见 [支持期限政策](./SUPPORT_POLICY_CN.md)。
|
||||
支持期限政策
|
||||
=================
|
||||
|
||||
* [English Version](./SUPPORT_POLICY.md)
|
||||
|
||||
ESP-IDF 的每个主要版本和次要版本(如 V4.0、V4.1 等)自其首次稳定版本发布之日起将维护 18 个月。
|
||||
|
||||
维护意味着 ESP-IDF 团队将会对 GitHub 上的发布分支继续进行 bug 修复、安全修补等,并根据需求定期发布新的 bugfix 版本。
|
||||
|
||||
在某一版本支持期限结束,停止更新维护 (EOL) 前,建议用户升级到较新的 ESP-IDF 版本。根据《支持期限政策》,我们将停止对 EOL 版本进行 bug 修复。
|
||||
|
||||
《支持期限政策》不适用于预发布版本(包括 beta、preview、`-rc` 和 `-dev` 版本等)。有时,在发布的版本中存在被标记为 "Preview" 的特定功能,则该功能也不在支持期限内。
|
||||
|
||||
有关 [ ESP-IDF 不同版本](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/versions.html)(主要版本、次要版本、bugfix 版本等)信息,可参阅《ESP-IDF 编程指南》。
|
||||
|
||||
长期支持版本
|
||||
------------
|
||||
|
||||
有些发布版本(从 ESP-IDF V3.3 开始)属于长期支持 (LTS) 版本。LTS 版本将自其首次稳定版本发布之日起维护 30 个月(2.5 年)。
|
||||
|
||||
我们将至少每 18 个月发布一个新的 LTS 版本。这意味着将至少有 12 个月的期限可更新至下一个 LTS 版本。
|
||||
|
||||
示例
|
||||
-----
|
||||
|
||||
ESP-IDF V3.3 于 2019 年 9 月发布,属于 LTS 版本,将维护 30 个月至 2022 年 2 月停止。
|
||||
|
||||
- V3.3 的首个发布版本为 2019 年 9 月发布的 `v3.3`。
|
||||
- ESP-IDF 团队将持续进行 bug 修复、安全修补等更新,并 backport 至分支 `release/v3.3`。
|
||||
- 定期从 release 分支创建稳定的 bugfix 版本,比如,`v3.3.1`、`v3.3.2` 等,并建议用户保持使用最新的 bugfix 版本。
|
||||
- V3.3 的 bugfix 版本发布将持续至 2022 年 2 月,届时所有 V3.3.x 将停止更新维护。
|
||||
|
||||
现有版本
|
||||
--------
|
||||
|
||||
ESP-IDF V3.3 及所有后续更新版本都将遵守该《支持期限政策》。每一版本发布时将同时公布其支持期限。
|
||||
|
||||
对于该政策公布之日前发布的版本,应适用下述支持期限:
|
||||
|
||||
- ESP-IDF V3.1.x 和 V3.2.x 将维护至 2020 年 10 月。
|
||||
- ESP-IDF V3.0.9(计划 2019 年 10 月发布)将是 V3.0 的最后一个 bugfix 版本。ESP-IDF V3.0.x 自 2019 年 10 月起停止更新维护 (EOL)。
|
||||
- ESP-IDF 中 V3.0 之前的版本均已停止更新维护 (EOL)。
|
||||
@@ -23,9 +23,6 @@ endif()
|
||||
|
||||
if(CONFIG_HEAP_TRACING_TOHOST)
|
||||
list(APPEND srcs "heap_trace_tohost.c")
|
||||
set_source_files_properties(heap_trace_tohost.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-frame-address)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
@@ -36,7 +33,4 @@ idf_component_register(SRCS "${srcs}"
|
||||
# disable --coverage for this component, as it is used as transport
|
||||
# for gcov
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
|
||||
|
||||
# Force app_trace to also appear later than gcov in link line
|
||||
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> c)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC gcov ${LIBC} ${LIBM} gcc)
|
||||
|
||||
@@ -1,56 +1,54 @@
|
||||
menu "Application Level Tracing"
|
||||
|
||||
choice APPTRACE_DESTINATION
|
||||
choice ESP32_APPTRACE_DESTINATION
|
||||
prompt "Data Destination"
|
||||
default APPTRACE_DEST_NONE
|
||||
default ESP32_APPTRACE_DEST_NONE
|
||||
help
|
||||
Select destination for application trace: trace memory or none (to disable).
|
||||
|
||||
config APPTRACE_DEST_TRAX
|
||||
config ESP32_APPTRACE_DEST_TRAX
|
||||
bool "Trace memory"
|
||||
select APPTRACE_ENABLE
|
||||
config APPTRACE_DEST_NONE
|
||||
select ESP32_APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_DEST_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
|
||||
config APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_ENABLE
|
||||
bool
|
||||
depends on !ESP32_TRAX && !ESP32S2_TRAX
|
||||
depends on !ESP32_TRAX
|
||||
select ESP32_MEMMAP_TRACEMEM
|
||||
select ESP32S2_MEMMAP_TRACEMEM
|
||||
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module.
|
||||
|
||||
config APPTRACE_LOCK_ENABLE
|
||||
config ESP32_APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !SYSVIEW_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
|
||||
config APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
|
||||
config APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
config ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_DEST_TRAX
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
|
||||
config APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
config ESP32_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
int "Size of the pending data buffer"
|
||||
depends on APPTRACE_DEST_TRAX
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
default 0
|
||||
help
|
||||
Size of the buffer for events in bytes. It is useful for buffering events from
|
||||
@@ -58,10 +56,10 @@ menu "Application Level Tracing"
|
||||
events will be discarded when main HW buffer is full.
|
||||
|
||||
menu "FreeRTOS SystemView Tracing"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
config SYSVIEW_ENABLE
|
||||
bool "SystemView Tracing Enable"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables supporrt for SEGGER SystemView tracing functionality.
|
||||
@@ -210,11 +208,10 @@ menu "Application Level Tracing"
|
||||
|
||||
endmenu
|
||||
|
||||
config APPTRACE_GCOV_ENABLE
|
||||
config ESP32_GCOV_ENABLE
|
||||
bool "GCOV to Host Enable"
|
||||
depends on APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
select ESP_DEBUG_STUBS_ENABLE
|
||||
default n
|
||||
depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables support for GCOV data transfer to host.
|
||||
|
||||
|
||||
@@ -76,11 +76,11 @@
|
||||
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
|
||||
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
|
||||
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// which controls the threshold for flushing data in case of panic.
|
||||
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
|
||||
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
|
||||
// 4. Communication Protocol
|
||||
// =========================
|
||||
@@ -114,7 +114,7 @@
|
||||
// has not completed reading of the previous one yet. So in this case time critical tracing calls (which can not be delayed for too long time due to
|
||||
// the lack of free memory in TRAX block) can be dropped. To avoid such scenarios tracing module implements data buffering. Buffered data will be sent
|
||||
// to the host later when TRAX block switch occurs. The maximum size of the buffered data is controlled by menuconfig option
|
||||
// CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX.
|
||||
// CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX.
|
||||
|
||||
// 4.4 Target Connection/Disconnection
|
||||
// -----------------------------------
|
||||
@@ -158,16 +158,13 @@
|
||||
#include <sys/param.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "soc/sensitive_reg.h"
|
||||
#endif
|
||||
#include "eri.h"
|
||||
#include "trax.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE
|
||||
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
|
||||
#define ESP_APPTRACE_HOST_BUF_SIZE 256
|
||||
|
||||
@@ -205,16 +202,10 @@ const static char *TAG = "esp_apptrace";
|
||||
#define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
|
||||
|
||||
// TODO: move these (and same definitions in trax.c to dport_reg.h)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
|
||||
#define TRACEMEM_MUX_BLK0_ONLY 1
|
||||
#define TRACEMEM_MUX_BLK1_ONLY 2
|
||||
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define TRACEMEM_MUX_BLK0_NUM 19
|
||||
#define TRACEMEM_MUX_BLK1_NUM 20
|
||||
#define TRACEMEM_BLK_NUM2ADDR(_n_) (0x3FFB8000UL + 0x4000UL*((_n_)-4))
|
||||
#endif
|
||||
|
||||
// TRAX is disabled, so we use its registers for our own purposes
|
||||
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
|
||||
@@ -239,17 +230,10 @@ const static char *TAG = "esp_apptrace";
|
||||
#endif
|
||||
#define ESP_APPTRACE_USR_BLOCK_RAW_SZ(_s_) ((_s_) + sizeof(esp_tracedata_hdr_t))
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static volatile uint8_t *s_trax_blocks[] = {
|
||||
(volatile uint8_t *) 0x3FFFC000,
|
||||
(volatile uint8_t *) 0x3FFF8000
|
||||
};
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
static volatile uint8_t *s_trax_blocks[] = {
|
||||
(volatile uint8_t *)TRACEMEM_BLK_NUM2ADDR(TRACEMEM_MUX_BLK0_NUM),
|
||||
(volatile uint8_t *)TRACEMEM_BLK_NUM2ADDR(TRACEMEM_MUX_BLK1_NUM)
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCKS_NUM (sizeof(s_trax_blocks)/sizeof(s_trax_blocks[0]))
|
||||
|
||||
@@ -309,17 +293,17 @@ typedef struct {
|
||||
typedef struct {
|
||||
volatile esp_apptrace_trax_state_t state; // state
|
||||
esp_apptrace_mem_block_t blocks[ESP_APPTRACE_TRAX_BLOCKS_NUM]; // memory blocks
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// ring buffer control struct for pending user blocks
|
||||
esp_apptrace_rb_t rb_pend;
|
||||
// storage for pending user blocks
|
||||
uint8_t pending_data[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
uint8_t pending_data[CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
// ring buffer control struct for pending user data chunks sizes,
|
||||
// every chunk contains whole number of user blocks and fit into TRAX memory block
|
||||
esp_apptrace_rb_t rb_pend_chunk_sz;
|
||||
// storage for above ring buffer data
|
||||
uint16_t pending_chunk_sz[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX/ESP_APPTRACE_TRAX_BLOCK_SIZE + 2];
|
||||
uint16_t pending_chunk_sz[CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX/ESP_APPTRACE_TRAX_BLOCK_SIZE + 2];
|
||||
// current (accumulated) pending user data chunk size
|
||||
uint16_t cur_pending_chunk_sz;
|
||||
#endif
|
||||
@@ -376,7 +360,7 @@ static esp_apptrace_hw_t s_trace_hw[ESP_APPTRACE_HW_MAX] = {
|
||||
}
|
||||
};
|
||||
|
||||
static inline int esp_apptrace_log_lock(void)
|
||||
static inline int esp_apptrace_log_lock()
|
||||
{
|
||||
#if ESP_APPTRACE_PRINT_LOCK
|
||||
esp_apptrace_tmo_t tmo;
|
||||
@@ -388,29 +372,29 @@ static inline int esp_apptrace_log_lock(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_log_unlock(void)
|
||||
static inline void esp_apptrace_log_unlock()
|
||||
{
|
||||
#if ESP_APPTRACE_PRINT_LOCK
|
||||
esp_apptrace_lock_give(&s_log_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_apptrace_lock_initialize(esp_apptrace_lock_t *lock)
|
||||
static inline esp_err_t esp_apptrace_lock_initialize()
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(lock);
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_apptrace_lock_cleanup(void)
|
||||
static inline esp_err_t esp_apptrace_lock_cleanup()
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_err_t ret = esp_apptrace_lock_take(&s_trace_buf.lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
@@ -419,28 +403,17 @@ esp_err_t esp_apptrace_lock(esp_apptrace_tmo_t *tmo)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_unlock(void)
|
||||
esp_err_t esp_apptrace_unlock()
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
ret = esp_apptrace_lock_give(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
|
||||
static inline void esp_apptrace_trax_select_memory_block(int block_num)
|
||||
{
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM-4) : BIT(TRACEMEM_MUX_BLK1_NUM-4));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void esp_apptrace_trax_init(void)
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
static void esp_apptrace_trax_init()
|
||||
{
|
||||
// Stop trace, if any (on the current CPU)
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
|
||||
@@ -453,7 +426,7 @@ static void esp_apptrace_trax_init(void)
|
||||
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", xPortGetCoreID());
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
// keep the size of buffered data for copying to TRAX mem block.
|
||||
// Only whole user blocks should be copied from buffer to TRAX block upon the switch
|
||||
static void esp_apptrace_trax_pend_chunk_sz_update(uint16_t size)
|
||||
@@ -476,7 +449,7 @@ static void esp_apptrace_trax_pend_chunk_sz_update(uint16_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t esp_apptrace_trax_pend_chunk_sz_get(void)
|
||||
static uint16_t esp_apptrace_trax_pend_chunk_sz_get()
|
||||
{
|
||||
uint16_t ch_sz;
|
||||
ESP_APPTRACE_LOGD("Get chunk enter %d w-r-s %d-%d-%d", s_trace_buf.trax.cur_pending_chunk_sz,
|
||||
@@ -494,7 +467,7 @@ static uint16_t esp_apptrace_trax_pend_chunk_sz_get(void)
|
||||
#endif
|
||||
|
||||
// assumed to be protected by caller from multi-core/thread access
|
||||
static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
static esp_err_t esp_apptrace_trax_block_switch()
|
||||
{
|
||||
int prev_block_num = s_trace_buf.trax.state.in_block % 2;
|
||||
int new_block_num = prev_block_num ? (0) : (1);
|
||||
@@ -526,7 +499,7 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
// switch to new block
|
||||
s_trace_buf.trax.state.in_block++;
|
||||
|
||||
esp_apptrace_trax_select_memory_block(new_block_num);
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, new_block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
// handle data from host
|
||||
esp_hostdata_hdr_t *hdr = (esp_hostdata_hdr_t *)s_trace_buf.trax.blocks[new_block_num].start;
|
||||
if (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA && hdr->block_sz > 0) {
|
||||
@@ -544,9 +517,9 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
}
|
||||
hdr->block_sz = 0;
|
||||
}
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// copy pending data to TRAX block if any
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
uint16_t max_chunk_sz = esp_apptrace_trax_pend_chunk_sz_get();
|
||||
#else
|
||||
uint16_t max_chunk_sz = s_trace_buf.trax.blocks[new_block_num].sz;
|
||||
@@ -554,7 +527,7 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
while (s_trace_buf.trax.state.markers[new_block_num] < max_chunk_sz) {
|
||||
uint32_t read_sz = esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend);
|
||||
if (read_sz == 0) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
/* theres is a bug: esp_apptrace_trax_pend_chunk_sz_get returned wrong value,
|
||||
it must be greater or equal to one returned by esp_apptrace_rb_read_size_get */
|
||||
ESP_APPTRACE_LOGE("No pended bytes, must be > 0 and <= %d!", max_chunk_sz);
|
||||
@@ -697,7 +670,7 @@ static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, esp_apptrace_tm
|
||||
return NULL;
|
||||
}
|
||||
// check if we still have pending data
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
if (esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend) > 0) {
|
||||
// if after TRAX block switch still have pending data (not all pending data have been pumped to TRAX block)
|
||||
// alloc new pending buffer
|
||||
@@ -711,7 +684,7 @@ static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, esp_apptrace_tm
|
||||
{
|
||||
// update block pointers
|
||||
if (ESP_APPTRACE_TRAX_INBLOCK_MARKER() + size > ESP_APPTRACE_TRAX_INBLOCK_GET()->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
*pended = 1;
|
||||
ptr = esp_apptrace_rb_produce(&s_trace_buf.trax.rb_pend, size);
|
||||
if (ptr == NULL) {
|
||||
@@ -741,7 +714,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
return NULL;
|
||||
}
|
||||
// check for data in the pending buffer
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
if (esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend) > 0) {
|
||||
// if we have buffered data try to switch TRAX block
|
||||
esp_apptrace_trax_block_switch();
|
||||
@@ -756,7 +729,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
} else {
|
||||
@@ -766,18 +739,18 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (ESP_APPTRACE_TRAX_INBLOCK_MARKER() + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_TRAX_INBLOCK_GET()->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
ESP_APPTRACE_LOGD("TRAX full. Get %d bytes from PEND buffer", size);
|
||||
buf_ptr = esp_apptrace_rb_produce(&s_trace_buf.trax.rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
if (buf_ptr) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
}
|
||||
@@ -788,7 +761,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
} else {
|
||||
@@ -872,7 +845,7 @@ static esp_err_t esp_apptrace_trax_status_reg_get(uint32_t *val)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_dest_init(void)
|
||||
static esp_err_t esp_apptrace_trax_dest_init()
|
||||
{
|
||||
for (int i = 0; i < ESP_APPTRACE_TRAX_BLOCKS_NUM; i++) {
|
||||
s_trace_buf.trax.blocks[i].start = (uint8_t *)s_trax_blocks[i];
|
||||
@@ -880,29 +853,28 @@ static esp_err_t esp_apptrace_trax_dest_init(void)
|
||||
s_trace_buf.trax.state.markers[i] = 0;
|
||||
}
|
||||
s_trace_buf.trax.state.in_block = ESP_APPTRACE_TRAX_INBLOCK_START;
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
esp_apptrace_rb_init(&s_trace_buf.trax.rb_pend, s_trace_buf.trax.pending_data,
|
||||
sizeof(s_trace_buf.trax.pending_data));
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
s_trace_buf.trax.cur_pending_chunk_sz = 0;
|
||||
esp_apptrace_rb_init(&s_trace_buf.trax.rb_pend_chunk_sz, (uint8_t *)s_trace_buf.trax.pending_chunk_sz,
|
||||
sizeof(s_trace_buf.trax.pending_chunk_sz));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
|
||||
#endif
|
||||
#endif
|
||||
esp_apptrace_trax_select_memory_block(0);
|
||||
// Expose block 1 to host, block 0 is current trace input buffer
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, TRACEMEM_MUX_BLK1_ONLY);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_apptrace_init(void)
|
||||
esp_err_t esp_apptrace_init()
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -915,7 +887,7 @@ esp_err_t esp_apptrace_init(void)
|
||||
ESP_APPTRACE_LOGE("Failed to init log lock (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
res = esp_apptrace_trax_dest_init();
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init TRAX dest data (%d)!", res);
|
||||
@@ -925,7 +897,7 @@ esp_err_t esp_apptrace_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
// init TRAX on this CPU
|
||||
esp_apptrace_trax_init();
|
||||
#endif
|
||||
@@ -947,7 +919,7 @@ esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size,
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -984,7 +956,7 @@ uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size,
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1008,7 +980,7 @@ esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, u
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1033,7 +1005,7 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1069,7 +1041,7 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1133,7 +1105,7 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1157,7 +1129,7 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1181,7 +1153,7 @@ esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, u
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1225,7 +1197,7 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1243,7 +1215,7 @@ esp_err_t esp_apptrace_status_reg_set(esp_apptrace_dest_t dest, uint32_t val)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1261,7 +1233,7 @@ esp_err_t esp_apptrace_status_reg_get(esp_apptrace_dest_t dest, uint32_t *val)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
|
||||
@@ -15,12 +15,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
|
||||
@@ -14,23 +14,15 @@
|
||||
|
||||
// This module implements runtime file I/O API for GCOV.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/libc_stubs.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/libc_stubs.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_APPTRACE_GCOV_ENABLE
|
||||
#if CONFIG_ESP32_GCOV_ENABLE
|
||||
|
||||
#define ESP_GCOV_DOWN_BUF_SIZE 4200
|
||||
|
||||
@@ -38,37 +30,37 @@
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_gcov_rtio";
|
||||
|
||||
extern void __gcov_dump(void);
|
||||
extern void __gcov_reset(void);
|
||||
#if GCC_NOT_5_2_0
|
||||
void __gcov_dump(void);
|
||||
void __gcov_reset(void);
|
||||
#else
|
||||
/* The next code for old GCC */
|
||||
|
||||
static struct syscall_stub_table s_gcov_stub_table;
|
||||
|
||||
|
||||
static int gcov_stub_lock_try_acquire_recursive(_lock_t *lock)
|
||||
static void (*s_gcov_exit)(void);
|
||||
/* Root of a program/shared-object state */
|
||||
struct gcov_root
|
||||
{
|
||||
if (*lock && uxSemaphoreGetCount((xSemaphoreHandle)(*lock)) == 0) {
|
||||
// we can do nothing here, gcov dump is initiated with some resource locked
|
||||
// which is also used by gcov functions
|
||||
ESP_EARLY_LOGE(TAG, "Lock 0x%x is busy during GCOV dump! System state can be inconsistent after dump!", lock);
|
||||
}
|
||||
return pdTRUE;
|
||||
}
|
||||
void *list;
|
||||
unsigned dumped : 1; /* counts have been dumped. */
|
||||
unsigned run_counted : 1; /* run has been accounted for. */
|
||||
struct gcov_root *next;
|
||||
struct gcov_root *prev;
|
||||
};
|
||||
|
||||
static void gcov_stub_lock_acquire_recursive(_lock_t *lock)
|
||||
{
|
||||
gcov_stub_lock_try_acquire_recursive(lock);
|
||||
}
|
||||
/* Per-dynamic-object gcov state. */
|
||||
extern struct gcov_root __gcov_root;
|
||||
|
||||
static void gcov_stub_lock_release_recursive(_lock_t *lock)
|
||||
static void esp_gcov_reset_status(void)
|
||||
{
|
||||
__gcov_root.dumped = 0;
|
||||
__gcov_root.run_counted = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int esp_dbg_stub_gcov_dump_do(void)
|
||||
{
|
||||
int ret = ESP_OK;
|
||||
FILE* old_stderr = stderr;
|
||||
FILE* old_stdout = stdout;
|
||||
struct syscall_stub_table* old_table = syscall_table_ptr_pro;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE);
|
||||
void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE);
|
||||
@@ -79,22 +71,18 @@ static int esp_dbg_stub_gcov_dump_do(void)
|
||||
ESP_EARLY_LOGV(TAG, "Config apptrace down buf");
|
||||
esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE);
|
||||
ESP_EARLY_LOGV(TAG, "Dump data...");
|
||||
// incase of dual-core chip APP and PRO CPUs share the same table, so it is safe to save only PRO's table
|
||||
memcpy(&s_gcov_stub_table, old_table, sizeof(s_gcov_stub_table));
|
||||
s_gcov_stub_table._lock_acquire_recursive = &gcov_stub_lock_acquire_recursive;
|
||||
s_gcov_stub_table._lock_release_recursive = &gcov_stub_lock_release_recursive;
|
||||
s_gcov_stub_table._lock_try_acquire_recursive = &gcov_stub_lock_try_acquire_recursive,
|
||||
|
||||
syscall_table_ptr_pro = &s_gcov_stub_table;
|
||||
stderr = (FILE*) &__sf_fake_stderr;
|
||||
stdout = (FILE*) &__sf_fake_stdout;
|
||||
#if GCC_NOT_5_2_0
|
||||
__gcov_dump();
|
||||
// reset dump status to allow incremental data accumulation
|
||||
__gcov_reset();
|
||||
stdout = old_stdout;
|
||||
stderr = old_stderr;
|
||||
syscall_table_ptr_pro = old_table;
|
||||
|
||||
#else
|
||||
ESP_EARLY_LOGV(TAG, "Check for dump handler %p", s_gcov_exit);
|
||||
if (s_gcov_exit) {
|
||||
s_gcov_exit();
|
||||
// reset dump status to allow incremental data accumulation
|
||||
esp_gcov_reset_status();
|
||||
}
|
||||
#endif
|
||||
ESP_EARLY_LOGV(TAG, "Free apptrace down buf");
|
||||
free(down_buf);
|
||||
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
|
||||
@@ -114,17 +102,19 @@ static int esp_dbg_stub_gcov_dump_do(void)
|
||||
*/
|
||||
static int esp_dbg_stub_gcov_entry(void)
|
||||
{
|
||||
#if GCC_NOT_5_2_0
|
||||
return esp_dbg_stub_gcov_dump_do();
|
||||
#else
|
||||
int ret = ESP_OK;
|
||||
// disable IRQs on this CPU, other CPU is halted by OpenOCD
|
||||
unsigned irq_state = portENTER_CRITICAL_NESTED();
|
||||
ret = esp_dbg_stub_gcov_dump_do();
|
||||
portEXIT_CRITICAL_NESTED(irq_state);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void esp_gcov_dump(void)
|
||||
void esp_gcov_dump()
|
||||
{
|
||||
// disable IRQs on this CPU, other CPU is halted by OpenOCD
|
||||
unsigned irq_state = portENTER_CRITICAL_NESTED();
|
||||
@@ -134,13 +124,13 @@ void esp_gcov_dump(void)
|
||||
#endif
|
||||
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
|
||||
// to avoid complains that task watchdog got triggered for other tasks
|
||||
timer_ll_wdt_set_protect(&TIMERG0, false);
|
||||
timer_ll_wdt_feed(&TIMERG0);
|
||||
timer_ll_wdt_set_protect(&TIMERG0, true);
|
||||
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG0.wdt_feed=1;
|
||||
TIMERG0.wdt_wprotect=0;
|
||||
// to avoid reboot on INT_WDT
|
||||
timer_ll_wdt_set_protect(&TIMERG1, false);
|
||||
timer_ll_wdt_feed(&TIMERG1);
|
||||
timer_ll_wdt_set_protect(&TIMERG1, true);
|
||||
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG1.wdt_feed=1;
|
||||
TIMERG1.wdt_wprotect=0;
|
||||
}
|
||||
|
||||
esp_dbg_stub_gcov_dump_do();
|
||||
@@ -150,6 +140,18 @@ void esp_gcov_dump(void)
|
||||
portEXIT_CRITICAL_NESTED(irq_state);
|
||||
}
|
||||
|
||||
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
|
||||
{
|
||||
#if GCC_NOT_5_2_0
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
#else
|
||||
ESP_EARLY_LOGV(TAG, "%s %p", __FUNCTION__, function);
|
||||
s_gcov_exit = function;
|
||||
#endif
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *gcov_rtio_fopen(const char *path, const char *mode)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s '%s' '%s'", __FUNCTION__, path, mode);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
static bool s_tracing;
|
||||
|
||||
esp_err_t heap_trace_init_tohost(void)
|
||||
esp_err_t heap_trace_init_tohost()
|
||||
{
|
||||
if (s_tracing) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <string.h>
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE
|
||||
|
||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Application trace data destinations bits.
|
||||
*/
|
||||
@@ -37,7 +33,7 @@ typedef enum {
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_init(void);
|
||||
esp_err_t esp_apptrace_init();
|
||||
|
||||
/**
|
||||
* @brief Configures down buffer.
|
||||
@@ -266,8 +262,4 @@ int esp_apptrace_fstop(esp_apptrace_dest_t dest);
|
||||
*/
|
||||
void esp_gcov_dump(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
#ifndef ESP_APP_TRACE_UTIL_H_
|
||||
#define ESP_APP_TRACE_UTIL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
@@ -168,8 +164,4 @@ uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb);
|
||||
*/
|
||||
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ESP_APP_TRACE_UTIL_H_
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
#ifndef ESP_SYSVIEW_TRACE_H_
|
||||
#define ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush
|
||||
@@ -81,8 +77,4 @@ void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers
|
||||
*/
|
||||
void esp_sysview_heap_trace_free(void *addr, const void *callers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
# sdkconfig replacement configurations for deprecated options formatted as
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
|
||||
CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION
|
||||
CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE
|
||||
CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_TRAX
|
||||
CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
CONFIG_ESP32_GCOV_ENABLE CONFIG_APPTRACE_GCOV_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
|
||||
@@ -285,12 +285,12 @@ Revision: $Rev: 5626 $
|
||||
* RTT lock configuration fallback
|
||||
*/
|
||||
#ifndef SEGGER_RTT_LOCK
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock(void);
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock();
|
||||
#define SEGGER_RTT_LOCK() SEGGER_SYSVIEW_X_RTT_Lock() // Lock RTT (nestable) (i.e. disable interrupts)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNLOCK
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock(void);
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock();
|
||||
#define SEGGER_RTT_UNLOCK() SEGGER_SYSVIEW_X_RTT_Unlock() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -65,8 +65,6 @@ Revision: $Rev: 5927 $
|
||||
#ifndef SEGGER_SYSVIEW_CONF_H
|
||||
#define SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
@@ -149,7 +147,7 @@ Revision: $Rev: 5927 $
|
||||
* SystemView Id configuration
|
||||
*/
|
||||
//TODO: optimise it
|
||||
#define SEGGER_SYSVIEW_ID_BASE SOC_DROM_LOW // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_BASE 0x3F400000 // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_SHIFT 0 // Number of bits to shift the Id to save bandwidth. (i.e. 2 when Ids are 4 byte aligned)
|
||||
|
||||
/*********************************************************************
|
||||
@@ -168,7 +166,7 @@ Revision: $Rev: 5927 $
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() SEGGER_SYSVIEW_X_GetInterruptId() // Get the currently active interrupt Id from the user-provided function.
|
||||
#endif
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void);
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock();
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state);
|
||||
// to be recursive save IRQ status on the stack of the caller
|
||||
#define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
|
||||
@@ -63,26 +63,11 @@ Revision: $Rev: 3734 $
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
@@ -96,7 +81,7 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
#define SYSVIEW_APP_NAME "FreeRTOS Application"
|
||||
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
#define SYSVIEW_DEVICE_NAME "ESP32"
|
||||
|
||||
// Determine which timer to use as timestamp source
|
||||
#if CONFIG_SYSVIEW_TS_SOURCE_CCOUNT
|
||||
@@ -138,18 +123,14 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
#if TS_USE_CCOUNT
|
||||
// CCOUNT is incremented at CPU frequency
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#endif
|
||||
#endif // TS_USE_CCOUNT
|
||||
|
||||
// System Frequency.
|
||||
#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
|
||||
|
||||
// The lowest RAM address used for IDs (pointers)
|
||||
#define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
|
||||
#define SYSVIEW_RAM_BASE (0x3F400000)
|
||||
|
||||
#if CONFIG_FREERTOS_CORETIMER_0
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
@@ -166,6 +147,78 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0};
|
||||
|
||||
static const char * const s_isr_names[] = {
|
||||
[0] = "WIFI_MAC",
|
||||
[1] = "WIFI_NMI",
|
||||
[2] = "WIFI_BB",
|
||||
[3] = "BT_MAC",
|
||||
[4] = "BT_BB",
|
||||
[5] = "BT_BB_NMI",
|
||||
[6] = "RWBT",
|
||||
[7] = "RWBLE",
|
||||
[8] = "RWBT_NMI",
|
||||
[9] = "RWBLE_NMI",
|
||||
[10] = "SLC0",
|
||||
[11] = "SLC1",
|
||||
[12] = "UHCI0",
|
||||
[13] = "UHCI1",
|
||||
[14] = "TG0_T0_LEVEL",
|
||||
[15] = "TG0_T1_LEVEL",
|
||||
[16] = "TG0_WDT_LEVEL",
|
||||
[17] = "TG0_LACT_LEVEL",
|
||||
[18] = "TG1_T0_LEVEL",
|
||||
[19] = "TG1_T1_LEVEL",
|
||||
[20] = "TG1_WDT_LEVEL",
|
||||
[21] = "TG1_LACT_LEVEL",
|
||||
[22] = "GPIO",
|
||||
[23] = "GPIO_NMI",
|
||||
[24] = "FROM_CPU0",
|
||||
[25] = "FROM_CPU1",
|
||||
[26] = "FROM_CPU2",
|
||||
[27] = "FROM_CPU3",
|
||||
[28] = "SPI0",
|
||||
[29] = "SPI1",
|
||||
[30] = "SPI2",
|
||||
[31] = "SPI3",
|
||||
[32] = "I2S0",
|
||||
[33] = "I2S1",
|
||||
[34] = "UART0",
|
||||
[35] = "UART1",
|
||||
[36] = "UART2",
|
||||
[37] = "SDIO_HOST",
|
||||
[38] = "ETH_MAC",
|
||||
[39] = "PWM0",
|
||||
[40] = "PWM1",
|
||||
[41] = "PWM2",
|
||||
[42] = "PWM3",
|
||||
[43] = "LEDC",
|
||||
[44] = "EFUSE",
|
||||
[45] = "CAN",
|
||||
[46] = "RTC_CORE",
|
||||
[47] = "RMT",
|
||||
[48] = "PCNT",
|
||||
[49] = "I2C_EXT0",
|
||||
[50] = "I2C_EXT1",
|
||||
[51] = "RSA",
|
||||
[52] = "SPI1_DMA",
|
||||
[53] = "SPI2_DMA",
|
||||
[54] = "SPI3_DMA",
|
||||
[55] = "WDT",
|
||||
[56] = "TIMER1",
|
||||
[57] = "TIMER2",
|
||||
[58] = "TG0_T0_EDGE",
|
||||
[59] = "TG0_T1_EDGE",
|
||||
[60] = "TG0_WDT_EDGE",
|
||||
[61] = "TG0_LACT_EDGE",
|
||||
[62] = "TG1_T0_EDGE",
|
||||
[63] = "TG1_T1_EDGE",
|
||||
[64] = "TG1_WDT_EDGE",
|
||||
[65] = "TG1_LACT_EDGE",
|
||||
[66] = "MMU_IA",
|
||||
[67] = "MPU_IA",
|
||||
[68] = "CACHE_IA",
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbSendSystemDesc()
|
||||
@@ -178,9 +231,9 @@ static void _cbSendSystemDesc(void) {
|
||||
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C=Xtensa,O=FreeRTOS");
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]);
|
||||
size_t isr_count = sizeof(s_isr_names)/sizeof(s_isr_names[0]);
|
||||
for (size_t i = 0; i < isr_count; ++i) {
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, esp_isr_names[i]);
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, s_isr_names[i]);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
}
|
||||
}
|
||||
@@ -191,7 +244,7 @@ static void _cbSendSystemDesc(void) {
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static void SEGGER_SYSVIEW_TS_Init(void)
|
||||
static void SEGGER_SYSVIEW_TS_Init()
|
||||
{
|
||||
/* We only need to initialize something if we use Timer Group.
|
||||
* esp_timer and ccount can be used as is.
|
||||
@@ -263,7 +316,7 @@ void SEGGER_SYSVIEW_Conf(void) {
|
||||
SEGGER_SYSVIEW_DisableEvents(disable_evts);
|
||||
}
|
||||
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp()
|
||||
{
|
||||
#if TS_USE_TIMERGROUP
|
||||
uint64_t ts = 0;
|
||||
@@ -276,15 +329,15 @@ U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock(void)
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock()
|
||||
{
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock(void)
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void)
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
|
||||
|
||||
@@ -18,11 +18,7 @@
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#endif
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#if CONFIG_APPTRACE_ENABLE == 1
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE == 1
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
|
||||
@@ -125,7 +125,7 @@ typedef struct {
|
||||
static SemaphoreHandle_t s_print_lock;
|
||||
#endif
|
||||
|
||||
static uint64_t esp_apptrace_test_ts_get(void);
|
||||
static uint64_t esp_apptrace_test_ts_get();
|
||||
|
||||
static void esp_apptrace_test_timer_isr(void *arg)
|
||||
{
|
||||
@@ -145,16 +145,56 @@ static void esp_apptrace_test_timer_isr(void *arg)
|
||||
}
|
||||
|
||||
tim_arg->data.wr_cnt++;
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_apptrace_test_timer_isr_crash(void *arg)
|
||||
{
|
||||
esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg;
|
||||
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->data.wr_cnt < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH) {
|
||||
uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t));
|
||||
*ts = (uint32_t)esp_apptrace_test_ts_get();//xthal_get_ccount();//xTaskGetTickCount();
|
||||
@@ -343,7 +383,7 @@ static void esp_apptrace_test_task_crash(void *p)
|
||||
|
||||
static int s_ts_timer_group, s_ts_timer_idx;
|
||||
|
||||
static uint64_t esp_apptrace_test_ts_get(void)
|
||||
static uint64_t esp_apptrace_test_ts_get()
|
||||
{
|
||||
uint64_t ts = 0;
|
||||
timer_get_counter_value(s_ts_timer_group, s_ts_timer_idx, &ts);
|
||||
@@ -373,7 +413,7 @@ static void esp_apptrace_test_ts_init(int timer_group, int timer_idx)
|
||||
timer_start(timer_group, timer_idx);
|
||||
}
|
||||
|
||||
static void esp_apptrace_test_ts_cleanup(void)
|
||||
static void esp_apptrace_test_ts_cleanup()
|
||||
{
|
||||
timer_config_t config;
|
||||
|
||||
@@ -810,8 +850,28 @@ static void esp_sysview_test_timer_isr(void *arg)
|
||||
|
||||
//ESP_APPTRACE_TEST_LOGI("tim-%d: IRQ %d/%d\n", tim_arg->id, tim_arg->group, tim_arg->timer);
|
||||
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->timer == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->timer == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_sysviewtrace_test_task(void *p)
|
||||
|
||||
@@ -29,11 +29,8 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(python PYTHON)
|
||||
|
||||
idf_component_get_property(partition_table_dir partition_table COMPONENT_DIR)
|
||||
|
||||
add_custom_command(OUTPUT ${blank_otadata_file}
|
||||
COMMAND ${python} ${partition_table_dir}/gen_empty_partition.py
|
||||
COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
|
||||
${otadata_size} ${blank_otadata_file})
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
|
||||
@@ -22,14 +22,4 @@ menu "Application manager"
|
||||
The PROJECT_NAME variable from the build system will not affect the firmware image.
|
||||
This value will not be contained in the esp_app_desc structure.
|
||||
|
||||
config APP_RETRIEVE_LEN_ELF_SHA
|
||||
int "The length of APP ELF SHA is stored in RAM(chars)"
|
||||
default 16
|
||||
range 8 64
|
||||
help
|
||||
At startup, the app will read this many hex characters from the embedded APP ELF SHA-256 hash value
|
||||
and store it in static RAM. This ensures the app ELF SHA-256 value is always available
|
||||
if it needs to be printed by the panic handler code.
|
||||
Changing this value will change the size of a static buffer, in bytes.
|
||||
|
||||
endmenu # "Application manager"
|
||||
|
||||
@@ -72,35 +72,13 @@ static inline char IRAM_ATTR to_hex_digit(unsigned val)
|
||||
return (val < 10) ? ('0' + val) : ('a' + val - 10);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void)
|
||||
{
|
||||
esp_ota_get_app_elf_sha256(NULL, 0);
|
||||
}
|
||||
|
||||
/* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled.
|
||||
* But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and
|
||||
* can lead to a complete lock-up of the CPU.
|
||||
* For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256()
|
||||
* and keep it in the static s_app_elf_sha256 value.
|
||||
*/
|
||||
int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size)
|
||||
{
|
||||
static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2];
|
||||
static bool first_call = true;
|
||||
if (first_call) {
|
||||
first_call = false;
|
||||
const uint8_t* src = esp_app_desc.app_elf_sha256;
|
||||
for (size_t i = 0; i < sizeof(s_app_elf_sha256); ++i) {
|
||||
s_app_elf_sha256[i] = src[i];
|
||||
}
|
||||
}
|
||||
if (dst == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t n = MIN((size - 1) / 2, sizeof(s_app_elf_sha256));
|
||||
size_t n = MIN((size - 1) / 2, sizeof(esp_app_desc.app_elf_sha256));
|
||||
const uint8_t* src = esp_app_desc.app_elf_sha256;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
dst[2*i] = to_hex_digit(s_app_elf_sha256[i] >> 4);
|
||||
dst[2*i + 1] = to_hex_digit(s_app_elf_sha256[i] & 0xf);
|
||||
dst[2*i] = to_hex_digit(src[i] >> 4);
|
||||
dst[2*i + 1] = to_hex_digit(src[i] & 0xf);
|
||||
}
|
||||
dst[2*n] = 0;
|
||||
return 2*n + 1;
|
||||
|
||||
@@ -157,8 +157,7 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
@@ -688,12 +687,12 @@ static esp_err_t esp_ota_current_ota_is_workable(bool valid)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback(void)
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(true);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void)
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(false);
|
||||
}
|
||||
@@ -716,7 +715,7 @@ static int get_last_invalid_otadata(const esp_ota_select_entry_t *two_otadata)
|
||||
return num_invalid_otadata;
|
||||
}
|
||||
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition(void)
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition()
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
if (read_otadata(otadata) == NULL) {
|
||||
|
||||
@@ -221,7 +221,7 @@ esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, es
|
||||
* @return
|
||||
* - ESP_OK: if successful.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback(void);
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback();
|
||||
|
||||
/**
|
||||
* @brief This function is called to roll back to the previously workable app with reboot.
|
||||
@@ -233,14 +233,14 @@ esp_err_t esp_ota_mark_app_valid_cancel_rollback(void);
|
||||
* - ESP_FAIL: if not successful.
|
||||
* - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void);
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
|
||||
/**
|
||||
* @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
|
||||
*
|
||||
* @return partition.
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition(void);
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition();
|
||||
|
||||
/**
|
||||
* @brief Returns state for given partition.
|
||||
|
||||
@@ -249,10 +249,6 @@ def _erase_ota_partition(target, ota_id):
|
||||
|
||||
|
||||
def main():
|
||||
if sys.version_info[0] < 3:
|
||||
print("WARNING: Support for Python 2 is deprecated and will be removed in future versions.", file=sys.stderr)
|
||||
elif sys.version_info[0] == 3 and sys.version_info[1] < 6:
|
||||
print("WARNING: Python 3 versions older than 3.6 are not supported.", file=sys.stderr)
|
||||
global quiet
|
||||
|
||||
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash
|
||||
)
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash)
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]")
|
||||
{
|
||||
const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA;
|
||||
const int sha256_hex_len = 64;
|
||||
char dst[sha256_hex_len + 2];
|
||||
const char fill = 0xcc;
|
||||
int res;
|
||||
|
||||
@@ -58,7 +58,7 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
|
||||
TEST_ASSERT_NOT_NULL(ota_1);
|
||||
TEST_ASSERT_NULL(ota_2); /* this partition shouldn't exist in test partition table */
|
||||
|
||||
TEST_ASSERT_EQUAL_PTR(factory, running); /* this may not be true if/when we get OTA tests that do OTA updates */
|
||||
TEST_ASSERT_EQUAL_PTR(factory, running); /* this may not be true if/when we get OTA tests that do OTA updates */
|
||||
|
||||
/* (The test steps verify subtypes before verifying pointer equality, because the failure messages are more readable
|
||||
this way.)
|
||||
|
||||
@@ -7,13 +7,9 @@
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -122,7 +118,7 @@ static void reboot_as_deep_sleep(void)
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
static void copy_current_app_to_next_part_and_reboot(void)
|
||||
static void copy_current_app_to_next_part_and_reboot()
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
@@ -268,19 +264,19 @@ static void test_flow1(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 5:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
@@ -311,7 +307,7 @@ static void test_flow2(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
@@ -348,13 +344,13 @@ static void test_flow3(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
@@ -406,7 +402,7 @@ static void test_flow4(void)
|
||||
nvs_close(handle);
|
||||
nvs_flash_deinit();
|
||||
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
|
||||
Submodule components/asio/asio updated: 3b66e5b051...55efc179b7
@@ -22,12 +22,8 @@
|
||||
# define ASIO_NO_EXCEPTIONS
|
||||
# endif // CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
|
||||
# ifndef CONFIG_COMPILER_RTTI
|
||||
# define ASIO_NO_TYPEID
|
||||
# endif // CONFIG_COMPILER_RTTI
|
||||
|
||||
//
|
||||
// LWIP compatibility inet and address macros/functions
|
||||
// LWIP compatifility inet and address macros/functions
|
||||
//
|
||||
# define LWIP_COMPAT_SOCKET_INET 1
|
||||
# define LWIP_COMPAT_SOCKET_ADDR 1
|
||||
@@ -38,6 +34,12 @@
|
||||
# define ASIO_DISABLE_SERIAL_PORT
|
||||
# define ASIO_SEPARATE_COMPILATION
|
||||
# define ASIO_STANDALONE
|
||||
# define ASIO_NO_TYPEID
|
||||
# define ASIO_DISABLE_SIGNAL
|
||||
# define ASIO_HAS_PTHREADS
|
||||
# define ASIO_DISABLE_EPOLL
|
||||
# define ASIO_DISABLE_EVENTFD
|
||||
# define ASIO_DISABLE_SIGNAL
|
||||
# define ASIO_DISABLE_SIGACTION
|
||||
|
||||
#endif // _ESP_ASIO_CONFIG_H_
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
idf_component_register(PRIV_REQUIRES partition_table)
|
||||
|
||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
|
||||
if(NOT CONFIG_SECURE_BOOT)
|
||||
if(NOT CONFIG_SECURE_BOOT_ENABLED)
|
||||
set(flash_bootloader FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,29 +1,4 @@
|
||||
menu "Bootloader config"
|
||||
|
||||
choice BOOTLOADER_COMPILER_OPTIMIZATION
|
||||
prompt "Bootloader optimization Level"
|
||||
default BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument)
|
||||
for the bootloader.
|
||||
|
||||
- The default "Size" setting will add the -0s flag to CFLAGS.
|
||||
- The "Debug" setting will add the -Og flag to CFLAGS.
|
||||
- The "Performance" setting will add the -O2 flag to CFLAGS.
|
||||
- The "None" setting will add the -O0 flag to CFLAGS.
|
||||
|
||||
Note that custom optimization levels may be unsupported.
|
||||
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
|
||||
bool "Size (-Os)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_PERF
|
||||
bool "Optimize for performance (-O2)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_NONE
|
||||
bool "Debug without optimization (-O0)"
|
||||
endchoice
|
||||
|
||||
choice BOOTLOADER_LOG_LEVEL
|
||||
bool "Bootloader log verbosity"
|
||||
default BOOTLOADER_LOG_LEVEL_INFO
|
||||
@@ -229,13 +204,10 @@ menu "Bootloader config"
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32 if IDF_TARGET_ESP32
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
range 1 16 if IDF_TARGET_ESP32S2BETA
|
||||
default 16 if IDF_TARGET_ESP32S2BETA
|
||||
range 1 32
|
||||
default 32
|
||||
help
|
||||
The size of the efuse secure version field.
|
||||
Its length is limited to 32 bits for ESP32 and 16 bits for ESP32S2BETA.
|
||||
The size of the efuse secure version field. Its length is limited to 32 bits.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
@@ -247,53 +219,6 @@ menu "Bootloader config"
|
||||
It allow to test anti-rollback implemention without permanent write eFuse bits.
|
||||
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
bool "Skip image validation when exiting deep sleep"
|
||||
depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT
|
||||
default n
|
||||
help
|
||||
This option disables the normal validation of an image coming out of
|
||||
deep sleep (checksums, SHA256, and signature). This is a trade-off
|
||||
between wakeup performance from deep sleep, and image integrity checks.
|
||||
|
||||
Only enable this if you know what you are doing. It should not be used
|
||||
in conjunction with using deep_sleep() entry and changing the active OTA
|
||||
partition as this would skip the validation upon first load of the new
|
||||
OTA partition.
|
||||
|
||||
config BOOTLOADER_RESERVE_RTC_SIZE
|
||||
hex
|
||||
default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
default 0
|
||||
help
|
||||
Reserve RTC FAST memory for Skip image validation. This option in bytes.
|
||||
This option reserves an area in the RTC FAST memory (access only PRO_CPU).
|
||||
Used to save the addresses of the selected application.
|
||||
When a wakeup occurs (from Deep sleep), the bootloader retrieves it and
|
||||
loads the application without validation.
|
||||
|
||||
config BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
bool "Reserve RTC FAST memory for custom purposes"
|
||||
default n
|
||||
help
|
||||
This option allows the customer to place data in the RTC FAST memory,
|
||||
this area remains valid when rebooted, except for power loss.
|
||||
This memory is located at a fixed address and is available
|
||||
for both the bootloader and the application.
|
||||
(The application and bootoloader must be compiled with the same option).
|
||||
The RTC FAST memory has access only through PRO_CPU.
|
||||
|
||||
config BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE
|
||||
hex "Size in bytes for custom purposes"
|
||||
range 0 0x10
|
||||
default 0
|
||||
depends on BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
help
|
||||
This option reserves in RTC FAST memory the area for custom purposes.
|
||||
If you want to create your own bootloader and save more information
|
||||
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
|
||||
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
@@ -304,26 +229,24 @@ menu "Security features"
|
||||
config SECURE_SIGNED_ON_BOOT
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_ON_UPDATE
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_APPS
|
||||
bool
|
||||
default y
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
select MBEDTLS_ECP_C
|
||||
select MBEDTLS_ECDH_C
|
||||
select MBEDTLS_ECDSA_C
|
||||
depends on SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE
|
||||
|
||||
|
||||
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
bool "Require signed app images"
|
||||
depends on !SECURE_BOOT
|
||||
default n
|
||||
depends on !SECURE_BOOT_ENABLED
|
||||
help
|
||||
Require apps to be signed to verify their integrity.
|
||||
|
||||
@@ -332,35 +255,6 @@ menu "Security features"
|
||||
against remote network access, but not physical access. Compared to using hardware Secure Boot this option
|
||||
is much simpler to implement.
|
||||
|
||||
choice SECURE_SIGNED_APPS_SCHEME
|
||||
bool "App Signing Scheme"
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED
|
||||
default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
Select the Secure App signing scheme. Depends on the Chip Revision.
|
||||
There are two options:
|
||||
1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1)
|
||||
Supported in ESP32 and ESP32-ECO3.
|
||||
2. The RSA based secure boot scheme. (Only choice for Secure Boot V2)
|
||||
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
|
||||
|
||||
config SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
bool "ECDSA"
|
||||
depends on IDF_TARGET_ESP32 && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED)
|
||||
help
|
||||
Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key.
|
||||
|
||||
Refer to the documentation before enabling.
|
||||
|
||||
config SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bool "RSA"
|
||||
depends on ESP32_REV_MIN_3 && SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
Appends the RSA-3072 based Signature block to the application.
|
||||
Refer to <Secure Boot Version 2 documentation link> before enabling.
|
||||
endchoice
|
||||
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
bool "Bootloader verifies app signatures"
|
||||
default n
|
||||
@@ -387,48 +281,23 @@ menu "Security features"
|
||||
If hardware secure boot is not enabled, this option still adds significant security against network-based
|
||||
attackers by preventing spoofing of OTA updates.
|
||||
|
||||
config SECURE_BOOT
|
||||
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
|
||||
config SECURE_BOOT_ENABLED
|
||||
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
help
|
||||
Build a bootloader which enables Secure Boot on first boot.
|
||||
Build a bootloader which enables secure boot on first boot.
|
||||
|
||||
Once enabled, Secure Boot will not boot a modified bootloader. The bootloader will only load a partition
|
||||
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition
|
||||
table or boot an app if the data has a verified digital signature. There are implications for reflashing
|
||||
updated apps once secure boot is enabled.
|
||||
|
||||
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
|
||||
|
||||
choice SECURE_BOOT_VERSION
|
||||
bool "Select secure boot version"
|
||||
default SECURE_BOOT_V2_ENABLED if ESP32_REV_MIN_3
|
||||
depends on SECURE_BOOT
|
||||
help
|
||||
Select the Secure Boot Version. Depends on the Chip Revision.
|
||||
Secure Boot V2 is the new RSA based secure boot scheme.
|
||||
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
|
||||
Secure Boot V1 is the AES based secure boot scheme.
|
||||
Supported in ESP32 and ESP32-ECO3.
|
||||
|
||||
config SECURE_BOOT_V1_ENABLED
|
||||
bool "Enable Secure Boot version 1"
|
||||
depends on IDF_TARGET_ESP32
|
||||
help
|
||||
Build a bootloader which enables secure boot version 1 on first boot.
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
config SECURE_BOOT_V2_ENABLED
|
||||
bool "Enable Secure Boot version 2"
|
||||
depends on ESP32_REV_MIN_3
|
||||
help
|
||||
Build a bootloader which enables Secure Boot version 2 on first boot.
|
||||
Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
endchoice
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_MODE
|
||||
bool "Secure bootloader mode"
|
||||
depends on SECURE_BOOT_V1_ENABLED
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
|
||||
config SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
@@ -463,8 +332,7 @@ menu "Security features"
|
||||
If enabled (default), these binary files are signed as part of the build process. The file named in
|
||||
"Secure boot private signing key" will be used to sign the image.
|
||||
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py.
|
||||
Version 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot.
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py
|
||||
(for example, on a remote signing server.)
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
@@ -474,32 +342,28 @@ menu "Security features"
|
||||
help
|
||||
Path to the key file used to sign app images.
|
||||
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format for Secure Boot V1.
|
||||
Key file is an RSA private key in PEM format for Secure Boot V2.
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format.
|
||||
|
||||
Path is evaluated relative to the project directory.
|
||||
|
||||
You can generate a new signing key by running the following command:
|
||||
espsecure.py generate_signing_key secure_boot_signing_key.pem
|
||||
|
||||
See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.
|
||||
See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details.
|
||||
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES && !SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default "signature_verification_key.bin"
|
||||
help
|
||||
Path to a public key file used to verify signed images.
|
||||
Secure Boot V1: This ECDSA public key is compiled into the bootloader and/or
|
||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
|
||||
app, to verify app images.
|
||||
Secure Boot V2: This RSA public key is compiled into the signature block at
|
||||
the end of the bootloader/app.
|
||||
|
||||
Key file is in raw binary format, and can be extracted from a
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||
bool "Hardware Key Encoding"
|
||||
@@ -526,7 +390,7 @@ menu "Security features"
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on SECURE_BOOT
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
default N
|
||||
help
|
||||
You can disable some of the default protections offered by secure boot, in order to enable testing or a
|
||||
@@ -534,7 +398,7 @@ menu "Security features"
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
config SECURE_FLASH_ENC_ENABLED
|
||||
bool "Enable flash encryption on boot (READ DOCS FIRST)"
|
||||
@@ -548,26 +412,6 @@ menu "Security features"
|
||||
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
|
||||
before enabling.
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_KEYSIZE
|
||||
bool "Size of generated AES-XTS key"
|
||||
default SECURE_FLASH_ENCRYPTION_AES128
|
||||
depends on IDF_TARGET_ESP32S2BETA && SECURE_FLASH_ENC_ENABLED
|
||||
help
|
||||
Size of generated AES-XTS key.
|
||||
|
||||
AES-128 uses a 256-bit key (32 bytes) which occupies one Efuse key block.
|
||||
AES-256 uses a 512-bit key (64 bytes) which occupies two Efuse key blocks.
|
||||
|
||||
This setting is ignored if either type of key is already burned to Efuse before the first boot.
|
||||
In this case, the pre-burned key is used and no new key is generated.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES128
|
||||
bool "AES-128 (256-bit key)"
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES256
|
||||
bool "AES-256 (512-bit key)"
|
||||
endchoice
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_MODE
|
||||
bool "Enable usage mode"
|
||||
depends on SECURE_FLASH_ENC_ENABLED
|
||||
@@ -578,7 +422,7 @@ menu "Security features"
|
||||
Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART
|
||||
bootloader
|
||||
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version and
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and
|
||||
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -640,18 +484,6 @@ menu "Security features"
|
||||
image to this length. It is generally not recommended to set this option, unless you have a legacy
|
||||
partitioning scheme which doesn't support 64KB aligned partition lengths.
|
||||
|
||||
config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
||||
bool "Allow additional read protecting of efuses"
|
||||
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
|
||||
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
|
||||
|
||||
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
|
||||
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse holding the public
|
||||
key digest, causing an immediate denial of service and possibly allowing an additional fault
|
||||
injection attack to bypass the signature protection.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -698,23 +530,5 @@ menu "Security features"
|
||||
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config SECURE_DISABLE_ROM_DL_MODE
|
||||
bool "Permanently disable ROM Download Mode"
|
||||
depends on ESP32_REV_MIN_3
|
||||
default n
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
|
||||
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
|
||||
|
||||
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
|
||||
then an error is printed instead.
|
||||
|
||||
It is recommended to enable this option in any production application where Flash
|
||||
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
|
||||
|
||||
It is also possible to permanently disable Download Mode by calling
|
||||
esp_efuse_disable_rom_download_mode() at runtime.
|
||||
|
||||
endmenu # Security features
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ clean: bootloader-clean
|
||||
bootloader-list-components:
|
||||
$(BOOTLOADER_MAKE) list-components
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
ifndef CONFIG_SECURE_BOOT_ENABLED
|
||||
# If secure boot disabled, bootloader flashing is integrated
|
||||
# with 'make flash' and no warnings are printed.
|
||||
|
||||
@@ -115,35 +115,13 @@ $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) | check_pyt
|
||||
@echo "DIGEST $(notdir $@)"
|
||||
$(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
|
||||
|
||||
else ifdef CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
BOOTLOADER_SIGNED_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-signed.bin
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
|
||||
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) --version 2 \
|
||||
-o $(BOOTLOADER_SIGNED_BIN) $(BOOTLOADER_BIN)
|
||||
else
|
||||
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
|
||||
@echo "Bootloader not signed. Sign the bootloader before flashing."
|
||||
@echo "To sign the bootloader, you can use this command:"
|
||||
@echo "espsecure.py sign_data --keyfile SECURE_BOOT_SIGNING_KEY --version 2 $(BOOTLOADER_BIN)"
|
||||
endif
|
||||
@echo $(SEPARATOR)
|
||||
@echo "Use the following command to flash the bootloader:"
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_SIGNED_BIN)"
|
||||
else
|
||||
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
|
||||
endif
|
||||
@echo $(SEPARATOR)
|
||||
|
||||
else # CONFIG_SECURE_BOOT && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE \
|
||||
&& !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH && !CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
bootloader:
|
||||
@echo "Invalid bootloader target: bad sdkconfig?"
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
ifndef CONFIG_SECURE_BOOT_ENABLED
|
||||
# don't build bootloader by default if secure boot is enabled
|
||||
all_binaries: $(BOOTLOADER_BIN)
|
||||
endif
|
||||
@@ -153,8 +131,3 @@ bootloader-clean: $(SDKCONFIG_MAKEFILE)
|
||||
ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
|
||||
rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN)
|
||||
endif
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
rm -f $(BOOTLOADER_SIGNED_BIN)
|
||||
endif
|
||||
endif
|
||||
@@ -1,7 +1,7 @@
|
||||
set(BOOTLOADER_OFFSET 0x1000)
|
||||
|
||||
# Do not generate flash file when building bootloader
|
||||
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -19,8 +19,8 @@ set(bootloader_binary_files
|
||||
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
# There are some additional processing when CONFIG_SECURE_SIGNED_APPS. This happens
|
||||
# when either CONFIG_SECURE_BOOT_V1_ENABLED or CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
|
||||
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
# For both cases, the user either sets binaries to be signed during build or not
|
||||
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
#
|
||||
@@ -29,13 +29,7 @@ idf_build_get_property(project_dir PROJECT_DIR)
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_custom_target(gen_secure_boot_keys)
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
set(secure_apps_signing_scheme "1")
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
set(secure_apps_signing_scheme "2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V1_ENABLED)
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
# Check that the configuration is sane
|
||||
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
|
||||
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
|
||||
@@ -66,18 +60,16 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
# (to pick up a new signing key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_signing_key
|
||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_scheme} \
|
||||
${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
endif()
|
||||
|
||||
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
|
||||
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
|
||||
set(ver_key_arg)
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
else()
|
||||
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
|
||||
@@ -90,39 +82,32 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
fail_at_build_time(gen_secure_boot_verification_key
|
||||
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
|
||||
"\tThis can be extracted from the private signing key."
|
||||
"\tSee docs/security/secure-boot-v1.rst for details.")
|
||||
"\tSee docs/security/secure-boot.rst for details.")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_verification_key)
|
||||
endif()
|
||||
|
||||
set(sign_key_arg)
|
||||
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
|
||||
endif()
|
||||
else()
|
||||
set(sign_key_arg)
|
||||
set(ver_key_arg)
|
||||
endif()
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
idf_build_get_property(python PYTHON)
|
||||
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
|
||||
|
||||
externalproject_add(bootloader
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
|
||||
-DPYTHON_DEPS_CHECKED=1 -DPYTHON=${python}
|
||||
-DPYTHON_DEPS_CHECKED=1
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
${sign_key_arg} ${ver_key_arg}
|
||||
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
|
||||
# the bootloader common component requirements depends on this and
|
||||
# config variables are not available before project() call.
|
||||
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
|
||||
${extra_cmake_args}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
@@ -139,4 +124,4 @@ endif()
|
||||
# So for now we just have the top-level build remove the final build products...
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
${bootloader_binary_files})
|
||||
${bootloader_binary_files})
|
||||
@@ -20,6 +20,3 @@ CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
|
||||
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
|
||||
# Secure Boot Scheme
|
||||
CONFIG_SECURE_BOOT_ENABLED CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
|
||||
@@ -83,39 +83,6 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS "${secure_boot_signing_key}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
|
||||
endif()
|
||||
|
||||
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
|
||||
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generated the signed Bootloader")
|
||||
else()
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Bootloader generated but not signed")
|
||||
endif()
|
||||
|
||||
add_custom_target (gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
@@ -159,18 +126,4 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
|
||||
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
|
||||
VERBATIM)
|
||||
elseif(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
DEPENDS gen_signed_bootloader
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
|
||||
idf_component_register(SRCS "uECC_verify_antifault.c"
|
||||
INCLUDE_DIRS . micro-ecc)
|
||||
# only compile the "micro-ecc/uECC.c" source file
|
||||
idf_component_register(SRCS "micro-ecc/uECC.c"
|
||||
INCLUDE_DIRS micro-ecc)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
|
||||
COMPONENT_SRCDIRS := .
|
||||
# only compile the micro-ecc/uECC.c source file
|
||||
# (SRCDIRS is needed so build system can find the source file)
|
||||
COMPONENT_SRCDIRS := micro-ecc
|
||||
COMPONENT_OBJS := micro-ecc/uECC.o
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := . micro-ecc
|
||||
COMPONENT_ADD_INCLUDEDIRS := micro-ecc
|
||||
|
||||
COMPONENT_SUBMODULES := micro-ecc
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
|
||||
|
||||
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
|
||||
2-clause license.
|
||||
*/
|
||||
|
||||
/* uECC_verify() calls a number of static functions form here and
|
||||
uses other definitions, so we just build that whole source file here and then append
|
||||
our modified version uECC_verify_antifault(). */
|
||||
#include "micro-ecc/uECC.c"
|
||||
|
||||
/* Version of uECC_verify() which also copies message_hash into verified_hash,
|
||||
but only if the signature is valid. Does this in an FI resistant way.
|
||||
*/
|
||||
int uECC_verify_antifault(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve,
|
||||
uint8_t *verified_hash) {
|
||||
uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
|
||||
uECC_word_t z[uECC_MAX_WORDS];
|
||||
uECC_word_t sum[uECC_MAX_WORDS * 2];
|
||||
uECC_word_t rx[uECC_MAX_WORDS];
|
||||
uECC_word_t ry[uECC_MAX_WORDS];
|
||||
uECC_word_t tx[uECC_MAX_WORDS];
|
||||
uECC_word_t ty[uECC_MAX_WORDS];
|
||||
uECC_word_t tz[uECC_MAX_WORDS];
|
||||
const uECC_word_t *points[4];
|
||||
const uECC_word_t *point;
|
||||
bitcount_t num_bits;
|
||||
bitcount_t i;
|
||||
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
uECC_word_t *_public = (uECC_word_t *)public_key;
|
||||
#else
|
||||
uECC_word_t _public[uECC_MAX_WORDS * 2];
|
||||
#endif
|
||||
uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
rx[num_n_words - 1] = 0;
|
||||
r[num_n_words - 1] = 0;
|
||||
s[num_n_words - 1] = 0;
|
||||
|
||||
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
bcopy((uint8_t *) r, signature, curve->num_bytes);
|
||||
bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes);
|
||||
#else
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(
|
||||
_public + num_words, public_key + curve->num_bytes, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
|
||||
#endif
|
||||
|
||||
/* r, s must not be 0. */
|
||||
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* r, s must be < n. */
|
||||
if (uECC_vli_cmp(curve->n, r, num_n_words) != 1 ||
|
||||
uECC_vli_cmp(curve->n, s, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate u1 and u2. */
|
||||
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
||||
u1[num_n_words - 1] = 0;
|
||||
bits2int(u1, message_hash, hash_size, curve);
|
||||
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
||||
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
||||
|
||||
/* Calculate sum = G + Q. */
|
||||
uECC_vli_set(sum, _public, num_words);
|
||||
uECC_vli_set(sum + num_words, _public + num_words, num_words);
|
||||
uECC_vli_set(tx, curve->G, num_words);
|
||||
uECC_vli_set(ty, curve->G + num_words, num_words);
|
||||
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, sum, sum + num_words, curve);
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
|
||||
apply_z(sum, sum + num_words, z, curve);
|
||||
|
||||
/* Use Shamir's trick to calculate u1*G + u2*Q */
|
||||
points[0] = 0;
|
||||
points[1] = curve->G;
|
||||
points[2] = _public;
|
||||
points[3] = sum;
|
||||
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
|
||||
uECC_vli_numBits(u2, num_n_words));
|
||||
|
||||
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
|
||||
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
|
||||
uECC_vli_set(rx, point, num_words);
|
||||
uECC_vli_set(ry, point + num_words, num_words);
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
|
||||
for (i = num_bits - 2; i >= 0; --i) {
|
||||
uECC_word_t index;
|
||||
curve->double_jacobian(rx, ry, z, curve);
|
||||
|
||||
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
|
||||
point = points[index];
|
||||
if (point) {
|
||||
uECC_vli_set(tx, point, num_words);
|
||||
uECC_vli_set(ty, point + num_words, num_words);
|
||||
apply_z(tx, ty, z, curve);
|
||||
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, rx, ry, curve);
|
||||
uECC_vli_modMult_fast(z, z, tz, curve);
|
||||
}
|
||||
}
|
||||
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
|
||||
apply_z(rx, ry, z, curve);
|
||||
|
||||
/* v = x1 (mod n) */
|
||||
if (uECC_vli_cmp(curve->n, rx, num_n_words) != 1) {
|
||||
uECC_vli_sub(rx, rx, curve->n, num_n_words);
|
||||
}
|
||||
|
||||
/* Anti-FI addition. Copy message_hash into verified_hash, but do it in a
|
||||
way that it will only happen if v == r (ie, rx == r)
|
||||
*/
|
||||
const uECC_word_t *mhash_words = (const uECC_word_t *)message_hash;
|
||||
uECC_word_t *vhash_words = (uECC_word_t *)verified_hash;
|
||||
unsigned hash_words = hash_size / sizeof(uECC_word_t);
|
||||
for (int w = 0; w < hash_words; w++) {
|
||||
/* note: using curve->num_words here to encourage compiler to re-read this variable */
|
||||
vhash_words[w] = mhash_words[w] ^ rx[w % curve->num_words] ^ r[w % curve->num_words];
|
||||
}
|
||||
/* Curve may be longer than hash, in which case keep reading the rest of the bytes */
|
||||
for (int w = hash_words; w < curve->num_words; w++) {
|
||||
vhash_words[w % hash_words] |= rx[w] ^ r[w];
|
||||
}
|
||||
|
||||
/* Accept only if v == r. */
|
||||
return (int)(uECC_vli_equal(rx, r, num_words));
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
|
||||
|
||||
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
|
||||
2-clause license.
|
||||
*/
|
||||
#pragma once
|
||||
#include "uECC.h"
|
||||
|
||||
/* Version uECC_verify() that also copies message_hash to verified_hash
|
||||
if the signature is valid, and does it in a way that is harder to attack
|
||||
with fault injection.
|
||||
*/
|
||||
int uECC_verify_antifault(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve,
|
||||
uint8_t *verified_hash);
|
||||
@@ -2,8 +2,7 @@ idf_component_register(SRCS "bootloader_start.c"
|
||||
REQUIRES bootloader bootloader_support)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "ld/${target}/bootloader.ld"
|
||||
"ld/${target}/bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
set(scripts "${target}.bootloader.ld"
|
||||
"${target}.bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
4
components/bootloader/subproject/main/Makefile.projbuild
Normal file
4
components/bootloader/subproject/main/Makefile.projbuild
Normal file
@@ -0,0 +1,4 @@
|
||||
# Submodules normally added in component.mk, but fully qualified
|
||||
# paths can be added at this level (we need binary librtc to be
|
||||
# available to link bootloader).
|
||||
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp_wifi/lib_esp32
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -11,39 +11,39 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
static const char* TAG = "boot";
|
||||
|
||||
static int select_partition_number(bootloader_state_t *bs);
|
||||
static int select_partition_number (bootloader_state_t *bs);
|
||||
static int selected_boot_partition(const bootloader_state_t *bs);
|
||||
|
||||
/*
|
||||
* We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
|
||||
* The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
|
||||
* We do have a stack, so we can do the initialization in C.
|
||||
*/
|
||||
void __attribute__((noreturn)) call_start_cpu0(void)
|
||||
void __attribute__((noreturn)) call_start_cpu0()
|
||||
{
|
||||
// 1. Hardware initialization
|
||||
if (bootloader_init() != ESP_OK) {
|
||||
bootloader_reset();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
// If this boot is a wake up from the deep sleep then go to the short way,
|
||||
// try to load the application which worked before deep sleep.
|
||||
// It skips a lot of checks due to it was done before (while first boot).
|
||||
bootloader_utility_load_boot_image_from_deep_sleep();
|
||||
// If it is not successful try to load an application as usual.
|
||||
#endif
|
||||
|
||||
// 2. Select the number of boot partition
|
||||
bootloader_state_t bs = {0};
|
||||
bootloader_state_t bs = { 0 };
|
||||
int boot_index = select_partition_number(&bs);
|
||||
if (boot_index == INVALID_INDEX) {
|
||||
bootloader_reset();
|
||||
@@ -54,7 +54,7 @@ void __attribute__((noreturn)) call_start_cpu0(void)
|
||||
}
|
||||
|
||||
// Select the number of boot partition
|
||||
static int select_partition_number(bootloader_state_t *bs)
|
||||
static int select_partition_number (bootloader_state_t *bs)
|
||||
{
|
||||
// 1. Load partition table
|
||||
if (!bootloader_utility_load_partition_table(bs)) {
|
||||
@@ -76,7 +76,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
if (boot_index == INVALID_INDEX) {
|
||||
return boot_index; // Unrecoverable failure (not due to corrupt ota data or bad partition contents)
|
||||
}
|
||||
if (bootloader_common_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
||||
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
||||
// Factory firmware.
|
||||
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
||||
@@ -93,7 +93,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
return bootloader_utility_get_selected_boot_partition(bs);
|
||||
}
|
||||
#endif
|
||||
// TEST firmware.
|
||||
// TEST firmware.
|
||||
#ifdef CONFIG_BOOTLOADER_APP_TEST
|
||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
||||
ESP_LOGI(TAG, "Detect a boot condition of the test firmware");
|
||||
@@ -115,7 +115,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
}
|
||||
|
||||
// Return global reent struct if any newlib functions are linked to bootloader
|
||||
struct _reent *__getreent(void)
|
||||
{
|
||||
struct _reent* __getreent() {
|
||||
return _GLOBAL_REENT;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,20 +6,14 @@
|
||||
#
|
||||
|
||||
LINKER_SCRIPTS := \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.ld \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.rom.ld \
|
||||
$(IDF_TARGET).bootloader.ld \
|
||||
$(IDF_TARGET).bootloader.rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.newlib-funcs.ld \
|
||||
$(IDF_PATH)/components/$(IDF_TARGET)/ld/$(IDF_TARGET).peripherals.ld
|
||||
|
||||
# SPI driver patch for ROM is only needed in ESP32
|
||||
ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
endif
|
||||
ifdef CONFIG_ESP32_REV_MIN_3
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.eco3.ld
|
||||
endif
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
@@ -44,7 +44,6 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
@@ -76,7 +75,6 @@ SECTIONS
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
@@ -153,7 +151,6 @@ SECTIONS
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
Linker file used to link the bootloader.
|
||||
*/
|
||||
|
||||
|
||||
/* Simplified memory map for the bootloader
|
||||
|
||||
The main purpose is to make sure the bootloader can load into main memory
|
||||
without overwriting itself.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* I/O */
|
||||
dport0_seg (RW) : org = 0x3FF00000, len = 0x10
|
||||
iram_loader_seg (RWX) : org = 0x40062000, len = 0x4000 /* 16KB, IRAM */
|
||||
iram_seg (RWX) : org = 0x40066000, len = 0x4000 /* 16KB, IRAM */
|
||||
/* 8k at the end of DRAM, before ROM data & stack */
|
||||
dram_seg (RW) : org = 0x3FFFA000, len = 0x2000
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.iram_loader.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_loader_text_start = ABSOLUTE(.);
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_efuse_esp32s2.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_wdt.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_loader_text_end = ABSOLUTE(.);
|
||||
} > iram_loader_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
} > iram_seg
|
||||
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.dram0.rodata :
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
. = (. + 3) & ~ 3;
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
__init_array_end = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
/* Literals are also RO data. */
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram .iram.*) /* catch stray IRAM_ATTR */
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* ESP32S2 ROM address table
|
||||
* Generated for ROM with MD5sum: f054d40c5f6b9207d3827460a6f5748c
|
||||
*/
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x4000d954 );
|
||||
|
||||
/* ToDo: Following address may need modification */
|
||||
PROVIDE ( MD5Final = 0x400056e8 );
|
||||
PROVIDE ( MD5Init = 0x40005648 );
|
||||
PROVIDE ( MD5Update = 0x40005668 );
|
||||
/* bootloader will use following functions from xtensa hal library */
|
||||
xthal_get_ccount = 0x40015cbc;
|
||||
xthal_get_ccompare = 0x40015ce8;
|
||||
xthal_set_ccompare = 0x40015cc4;
|
||||
@@ -1,62 +1,42 @@
|
||||
set(srcs
|
||||
set(srcs
|
||||
"src/bootloader_clock.c"
|
||||
"src/bootloader_common.c"
|
||||
"src/bootloader_flash.c"
|
||||
"src/bootloader_flash_config.c"
|
||||
"src/bootloader_random.c"
|
||||
"src/bootloader_utility.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c"
|
||||
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
||||
"src/bootloader_efuse_${IDF_TARGET}.c"
|
||||
)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
# Not supported on ESP32S2Beta yet
|
||||
list(APPEND srcs "src/flash_encrypt.c")
|
||||
endif()
|
||||
"src/flash_qio_mode.c")
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
set(include_dirs "include" "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires micro-ecc spi_flash efuse)
|
||||
list(APPEND srcs
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
list(APPEND srcs
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c"
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c")
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
if(BOOTLOADER_BUILD)
|
||||
list(APPEND srcs
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT AND BOOTLOADER_BUILD)
|
||||
list(APPEND srcs
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
endif()
|
||||
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}")
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME))
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
|
||||
# in the library.
|
||||
|
||||
@@ -19,26 +19,11 @@ ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_OBJEXCLUDE := src/bootloader_init.o
|
||||
endif
|
||||
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2beta.o \
|
||||
src/bootloader_efuse_esp32s2beta.o
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot_signatures.o \
|
||||
src/idf/secure_boot_signatures.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot.o
|
||||
endif
|
||||
|
||||
#
|
||||
# Secure boot signing key support
|
||||
#
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS
|
||||
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
# this path is created relative to the component build directory
|
||||
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)
|
||||
|
||||
@@ -53,7 +38,7 @@ ORIG_SECURE_BOOT_VERIFICATION_KEY := $(call resolvepath,$(call dequote,$(CONFIG_
|
||||
$(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
@echo "Secure boot verification public key '$@' missing."
|
||||
@echo "This can be extracted from the private signing key, see"
|
||||
@echo "docs/security/secure-boot-v1.rst for details."
|
||||
@echo "docs/security/secure-boot.rst for details."
|
||||
exit 1
|
||||
|
||||
# copy it into the build dir, so the secure boot verification key has
|
||||
@@ -61,11 +46,10 @@ $(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(summary) CP $< $@
|
||||
cp $< $@
|
||||
endif #CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
endif
|
||||
|
||||
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
endif #CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
endif #CONFIG_SECURE_SIGNED_APPS
|
||||
endif
|
||||
|
||||
@@ -24,11 +24,6 @@ extern "C" {
|
||||
*/
|
||||
void bootloader_clock_configure(void);
|
||||
|
||||
/** @brief Return the rated maximum frequency of this chip
|
||||
*/
|
||||
int bootloader_clock_get_rated_freq_mhz(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_app_format.h"
|
||||
// RESET_REASON is declared in rom/rtc.h
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -94,13 +88,6 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
|
||||
*/
|
||||
bool bootloader_common_label_search(const char *list, char *label);
|
||||
|
||||
/**
|
||||
* @brief Configure default SPI pin modes and drive strengths
|
||||
*
|
||||
* @param drv GPIO drive level (determined by clock frequency)
|
||||
*/
|
||||
void bootloader_configure_spi_pins(int drv);
|
||||
|
||||
/**
|
||||
* @brief Calculates a sha-256 for a given partition or returns a appended digest.
|
||||
*
|
||||
@@ -167,14 +154,6 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
*/
|
||||
uint8_t bootloader_common_get_chip_revision(void);
|
||||
|
||||
/**
|
||||
* @brief Query reset reason
|
||||
*
|
||||
* @param cpu_no CPU number
|
||||
* @return reset reason enumeration
|
||||
*/
|
||||
RESET_REASON bootloader_common_get_reset_reason(int cpu_no);
|
||||
|
||||
/**
|
||||
* @brief Check if the image (bootloader and application) has valid chip ID and revision
|
||||
*
|
||||
@@ -189,69 +168,7 @@ esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hd
|
||||
/**
|
||||
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
|
||||
*/
|
||||
void bootloader_common_vddsdio_configure(void);
|
||||
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
/**
|
||||
* @brief Returns partition from rtc_retain_mem
|
||||
*
|
||||
* Uses to get the partition of application which was worked before to go to the deep sleep.
|
||||
* This partition was stored in rtc_retain_mem.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return partition: If rtc_retain_mem is valid.
|
||||
* - NULL: If it is not valid.
|
||||
*/
|
||||
esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void);
|
||||
|
||||
/**
|
||||
* @brief Update the partition and reboot_counter in rtc_retain_mem.
|
||||
*
|
||||
* This function saves the partition of application for fast booting from the deep sleep.
|
||||
* An algorithm uses this partition to avoid reading the otadata and does not validate an image.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @param[in] partition App partition description. Can be NULL, in this case rtc_retain_mem.partition is not updated.
|
||||
* @param[in] reboot_counter If true then update reboot_counter.
|
||||
*
|
||||
*/
|
||||
void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter);
|
||||
|
||||
/**
|
||||
* @brief Reset entire rtc_retain_mem.
|
||||
*
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*/
|
||||
void bootloader_common_reset_rtc_retain_mem(void);
|
||||
|
||||
/**
|
||||
* @brief Returns reboot_counter from rtc_retain_mem
|
||||
*
|
||||
* The reboot_counter counts the number of reboots. Reset only when power is off.
|
||||
* The very first launch of the application will be from 1.
|
||||
* Overflow is not possible, it will stop at the value UINT16_MAX.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return reboot_counter: 1..65535
|
||||
* - 0: If rtc_retain_mem is not valid.
|
||||
*/
|
||||
uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void);
|
||||
|
||||
/**
|
||||
* @brief Returns rtc_retain_mem
|
||||
*
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return rtc_retain_mem
|
||||
*/
|
||||
rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void);
|
||||
|
||||
#endif
|
||||
void bootloader_common_vddsdio_configure();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" {
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void bootloader_flash_update_id(void);
|
||||
void bootloader_flash_update_id();
|
||||
|
||||
/**
|
||||
* @brief Set the flash CS setup and hold time.
|
||||
@@ -35,7 +35,7 @@ void bootloader_flash_update_id(void);
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void bootloader_flash_cs_timing_config(void);
|
||||
void bootloader_flash_cs_timing_config();
|
||||
|
||||
/**
|
||||
* @brief Configure SPI flash clock.
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -47,17 +46,11 @@ typedef enum {
|
||||
*
|
||||
* @return true if flash encryption is enabled.
|
||||
*/
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
#endif
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) {
|
||||
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
/* __builtin_parity is in flash, so we calculate parity inline */
|
||||
bool enabled = false;
|
||||
while (flash_crypt_cnt) {
|
||||
while(flash_crypt_cnt) {
|
||||
if (flash_crypt_cnt & 1) {
|
||||
enabled = !enabled;
|
||||
}
|
||||
@@ -128,12 +121,8 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
|
||||
* is enabled but secure boot is not used. This should protect against
|
||||
* serial re-flashing of an unauthorised code in absence of secure boot.
|
||||
*
|
||||
* @note On ESP32 V3 only, write protecting FLASH_CRYPT_CNT will also prevent
|
||||
* disabling UART Download Mode. If both are wanted, call
|
||||
* esp_efuse_disable_rom_download_mode() before calling this function.
|
||||
*
|
||||
*/
|
||||
void esp_flash_write_protect_crypt_cnt(void);
|
||||
void esp_flash_write_protect_crypt_cnt();
|
||||
|
||||
/** @brief Return the flash encryption mode
|
||||
*
|
||||
@@ -142,7 +131,7 @@ void esp_flash_write_protect_crypt_cnt(void);
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void);
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode();
|
||||
|
||||
|
||||
/** @brief Check the flash encryption mode during startup
|
||||
|
||||
@@ -42,43 +42,15 @@ typedef struct {
|
||||
uint8_t image_digest[32]; /* appended SHA-256 digest */
|
||||
} esp_image_metadata_t;
|
||||
|
||||
/* Mode selection for esp_image_load() */
|
||||
typedef enum {
|
||||
ESP_IMAGE_VERIFY, /* Verify image contents, not load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_VERIFY_SILENT, /* Verify image contents, not load to memory, load metadata. Don't print errors. */
|
||||
ESP_IMAGE_VERIFY, /* Verify image contents, load metadata. Print errors. */
|
||||
ESP_IMAGE_VERIFY_SILENT, /* Verify image contents, load metadata. Don't print errors. */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
ESP_IMAGE_LOAD, /* Verify image contents, load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_LOAD_NO_VALIDATE, /* Not verify image contents, load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_LOAD, /* Verify image contents, load to memory. Print errors. */
|
||||
#endif
|
||||
} esp_image_load_mode_t;
|
||||
|
||||
typedef struct {
|
||||
esp_partition_pos_t partition; /*!< Partition of application which worked before goes to the deep sleep. */
|
||||
uint16_t reboot_counter; /*!< Reboot counter. Reset only when power is off. */
|
||||
uint16_t reserve; /*!< Reserve */
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
uint8_t custom[CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE]; /*!< Reserve for custom propose */
|
||||
#endif
|
||||
uint32_t crc; /*!< Check sum crc32 */
|
||||
} rtc_retain_mem_t;
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
_Static_assert(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
|
||||
_Static_assert(CONFIG_BOOTLOADER_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
|
||||
#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
|
||||
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
|
||||
_Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved RTC area must exceed size of rtc_retain_mem_t");
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Verify an app image.
|
||||
*
|
||||
@@ -132,24 +104,6 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t
|
||||
*/
|
||||
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Load an app image without verification (available only in space of bootloader).
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param part Partition to load the app from.
|
||||
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function.
|
||||
* 'start_addr' member should be set (to the start address of the image.)
|
||||
* Other fields will all be initialised by this function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if verify or load was successful
|
||||
* - ESP_ERR_IMAGE_FLASH_FAIL if a SPI flash error occurs
|
||||
* - ESP_ERR_IMAGE_INVALID if the image appears invalid.
|
||||
* - ESP_ERR_INVALID_ARG if the partition or data pointers are invalid.
|
||||
*/
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Verify the bootloader image.
|
||||
*
|
||||
|
||||
@@ -16,18 +16,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#else
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
||||
#error "internal sdkconfig error, secure boot should always enable all signature options"
|
||||
#endif
|
||||
@@ -44,31 +36,20 @@ extern "C" {
|
||||
|
||||
/** @brief Is secure boot currently enabled in hardware?
|
||||
*
|
||||
* This means that the ROM bootloader code will only boot
|
||||
* a verified secure bootloader from now on.
|
||||
* Secure boot is enabled if the ABS_DONE_0 efuse is blown. This means
|
||||
* that the ROM bootloader code will only boot a verified secure
|
||||
* bootloader digest from now on.
|
||||
*
|
||||
* @return true if secure boot is enabled.
|
||||
*/
|
||||
static inline bool esp_secure_boot_enabled(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
#elif CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
return ets_use_secure_boot_v2();
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return ets_efuse_secure_boot_enabled();
|
||||
#endif
|
||||
return false; /* Secure Boot not enabled in menuconfig */
|
||||
static inline bool esp_secure_boot_enabled(void) {
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* This function is only used in the context of the Secure Boot V1 scheme.
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will:
|
||||
* 1) generate the secure boot key and burn it on EFUSE
|
||||
* (without enabling R/W protection)
|
||||
@@ -85,17 +66,18 @@ static inline bool esp_secure_boot_enabled(void)
|
||||
*/
|
||||
esp_err_t esp_secure_boot_generate_digest(void);
|
||||
|
||||
/** @brief Enable secure boot V1 if it is not already enabled.
|
||||
/** @brief Enable secure boot if it is not already enabled.
|
||||
*
|
||||
* @important If this function succeeds, secure boot V1 is permanently
|
||||
* @important If this function succeeds, secure boot is permanently
|
||||
* enabled on the chip via efuse.
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important In case of Secure Boot V1, this will enable r/w protection
|
||||
* of secure boot key on EFUSE, therefore it is to be ensured that
|
||||
* esp_secure_boot_generate_digest() is called before this .If secure boot is not
|
||||
* yet enabled for bootloader, this will
|
||||
* @important This will enable r/w protection of secure boot key on EFUSE,
|
||||
* therefore it is to be ensured that esp_secure_boot_generate_digest()
|
||||
* is called before this
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will
|
||||
* 1) enable R/W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
*
|
||||
@@ -111,97 +93,35 @@ esp_err_t esp_secure_boot_generate_digest(void);
|
||||
*/
|
||||
esp_err_t esp_secure_boot_permanently_enable(void);
|
||||
|
||||
/** @brief Enables secure boot V2 if it is not already enabled.
|
||||
/** @brief Verify the secure boot signature (determinstic ECDSA w/ SHA256) appended to some binary data in flash.
|
||||
*
|
||||
* @important If this function succeeds, secure boot V2 is permanently
|
||||
* enabled on the chip via efuse.
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important In case of Secure Boot V2, this will enable write protection
|
||||
* of secure boot key on EFUSE in BLK2. .If secure boot is not
|
||||
* yet enabled for bootloader, this will
|
||||
* 1) enable W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_1 efuse.
|
||||
*
|
||||
* This function does not verify secure boot of the bootloader (the
|
||||
* ROM bootloader does this.)
|
||||
*
|
||||
* @param image_data Image metadata of the application to be loaded.
|
||||
*
|
||||
* Will fail if efuses have been part-burned in a way that indicates
|
||||
* secure boot should not or could not be correctly enabled.
|
||||
*
|
||||
* @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
|
||||
* secure boot to be enabled cleanly. ESP_OK if secure boot
|
||||
* is enabled on this chip from now on.
|
||||
*/
|
||||
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data);
|
||||
|
||||
/** @brief Verify the secure boot signature appended to some binary data in flash.
|
||||
*
|
||||
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
|
||||
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
|
||||
*
|
||||
* Public key is compiled into the calling program in the ECDSA Scheme.
|
||||
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
|
||||
* Public key is compiled into the calling program. See docs/security/secure-boot.rst for details.
|
||||
*
|
||||
* @param src_addr Starting offset of the data in flash.
|
||||
* @param length Length of data in bytes. Signature is appended -after- length bytes.
|
||||
*
|
||||
* If flash encryption is enabled, the image will be transparently decrypted while being verified.
|
||||
*
|
||||
* @note This function doesn't have any fault injection resistance so should not be called
|
||||
* during a secure boot itself (but can be called when verifying an update, etc.)
|
||||
*
|
||||
* @return ESP_OK if signature is valid, ESP_ERR_INVALID_STATE if
|
||||
* signature fails, ESP_FAIL for other failures (ie can't read flash).
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length);
|
||||
|
||||
/** @brief Verify the secure boot signature block (deterministic ECDSA w/ SHA256) based on the SHA256 hash of some data.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @brief Secure boot verification block, on-flash data format. */
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
uint8_t signature[64];
|
||||
} esp_secure_boot_sig_block_t;
|
||||
|
||||
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
|
||||
*
|
||||
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
|
||||
* verification must be enabled in project configuration to use this function.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to ECDSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
|
||||
|
||||
|
||||
/** @brief Verify the RSA secure boot signature block for Secure Boot V2.
|
||||
*
|
||||
* Performs RSA-PSS Verification of the SHA-256 image based on the public key
|
||||
* in the signature block, compared against the public key digest stored in efuse.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to RSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
|
||||
|
||||
/** @brief Legacy ECDSA verification function
|
||||
*
|
||||
* @note Deprecated, call either esp_secure_boot_verify_ecdsa_signature_block() or esp_secure_boot_verify_rsa_signature_block() instead.
|
||||
*
|
||||
* @param sig_block Pointer to ECDSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
|
||||
__attribute__((deprecated("use esp_secure_boot_verify_ecdsa_signature_block instead")));
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest);
|
||||
|
||||
#define FLASH_OFFS_SECURE_BOOT_IV_DIGEST 0
|
||||
|
||||
|
||||
@@ -18,11 +18,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
#define FLASH_BLOCK_SIZE 0x10000
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
/* Provide a Flash API for bootloader_support code,
|
||||
that can be used from bootloader or app code.
|
||||
@@ -36,7 +35,7 @@
|
||||
*
|
||||
* @return Number of free pages
|
||||
*/
|
||||
uint32_t bootloader_mmap_get_free_pages(void);
|
||||
uint32_t bootloader_mmap_get_free_pages();
|
||||
|
||||
/**
|
||||
* @brief Map a region of flash to data memory
|
||||
|
||||
@@ -14,37 +14,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief labels from bootloader linker script: bootloader.ld
|
||||
*
|
||||
*/
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _data_start;
|
||||
extern int _data_end;
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief bootloader image header
|
||||
*
|
||||
*/
|
||||
extern esp_image_header_t bootloader_image_hdr;
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief Common initialization steps that are applied to all targets.
|
||||
*
|
||||
*/
|
||||
esp_err_t bootloader_read_bootloader_header(void);
|
||||
esp_err_t bootloader_check_bootloader_validity(void);
|
||||
void bootloader_clear_bss_section(void);
|
||||
void bootloader_config_wdt(void);
|
||||
void bootloader_enable_random(void);
|
||||
void bootloader_print_banner(void);
|
||||
/**@}*/
|
||||
|
||||
/* @brief Prepares hardware for work.
|
||||
*
|
||||
@@ -56,4 +25,4 @@ void bootloader_print_banner(void);
|
||||
* @return ESP_OK - If the setting is successful.
|
||||
* ESP_FAIL - If the setting is not successful.
|
||||
*/
|
||||
esp_err_t bootloader_init(void);
|
||||
esp_err_t bootloader_init();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
typedef void *bootloader_sha256_handle_t;
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void);
|
||||
bootloader_sha256_handle_t bootloader_sha256_start();
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "bootloader_config.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_config.h"
|
||||
|
||||
/**
|
||||
* @brief Load partition table.
|
||||
@@ -55,16 +54,6 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
*/
|
||||
__attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
/**
|
||||
* @brief Load that application which was worked before we go to the deep sleep.
|
||||
*
|
||||
* Checks the reboot reason if it is the deep sleep and has a valid partition in the RTC memory
|
||||
* then try to load the application which was worked before we go to the deep sleep.
|
||||
*
|
||||
*/
|
||||
void bootloader_utility_load_boot_image_from_deep_sleep(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Software reset the ESP32
|
||||
@@ -97,28 +86,3 @@ __attribute__((noreturn)) void bootloader_reset(void);
|
||||
* ESP_ERR_INVALID_ARG: Error in the passed arguments
|
||||
*/
|
||||
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Debug log contents of a buffer as hexadecimal
|
||||
*
|
||||
* @note Only works if component log level is DEBUG or higher.
|
||||
*
|
||||
* @param buffer Buffer to log
|
||||
* @param length Length of buffer in bytes. Maximum length 128 bytes.
|
||||
* @param label Label to print at beginning of log line.
|
||||
*/
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label);
|
||||
|
||||
/** @brief Generates the digest of the data between offset & offset+length.
|
||||
*
|
||||
* This function should be used when the size of the data is larger than 3.2MB.
|
||||
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-256
|
||||
* of the data in chunks of 3.2MB, considering the MMU capacity.
|
||||
*
|
||||
* @param[in] flash_offset Offset of the data in flash.
|
||||
* @param[in] len Length of data in bytes.
|
||||
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
|
||||
*
|
||||
* @return ESP_OK if secure boot digest is generated successfully.
|
||||
*/
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
|
||||
|
||||
@@ -30,7 +30,7 @@ void bootloader_enable_qio_mode(void);
|
||||
* mfg_id = (ID >> 16) & 0xFF;
|
||||
flash_id = ID & 0xffff;
|
||||
*/
|
||||
uint32_t bootloader_read_flash_id(void);
|
||||
uint32_t bootloader_read_flash_id();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -11,21 +11,14 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#else
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
void bootloader_clock_configure(void)
|
||||
void bootloader_clock_configure()
|
||||
{
|
||||
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
||||
// Wait for it to be printed.
|
||||
@@ -34,30 +27,23 @@ void bootloader_clock_configure(void)
|
||||
// and will be done with the bootloader much earlier than UART FIFO is empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
|
||||
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
|
||||
* document). For rev. 0, switch to 240 instead if it has been enabled
|
||||
* previously.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
||||
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
|
||||
DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) {
|
||||
cpu_freq_mhz = 240;
|
||||
}
|
||||
#endif
|
||||
|
||||
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
|
||||
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
clk_cfg.xtal_freq = RTC_XTAL_FREQ_40M;
|
||||
clk_cfg.cpu_freq = RTC_CPU_FREQ_80M;
|
||||
#endif
|
||||
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
|
||||
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
|
||||
rtc_clk_init(clk_cfg);
|
||||
|
||||
@@ -17,23 +17,16 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#endif
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "sys/param.h"
|
||||
@@ -188,7 +181,22 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t
|
||||
size = data.image_len;
|
||||
}
|
||||
// If image is type by data then hash is calculated for entire image.
|
||||
return bootloader_sha256_flash_contents(address, size, out_sha_256);
|
||||
const void *partition_bin = bootloader_mmap(address, size);
|
||||
if (partition_bin == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", address, size);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
bootloader_munmap(partition_bin);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, partition_bin, size);
|
||||
bootloader_sha256_finish(sha_handle, out_sha_256);
|
||||
|
||||
bootloader_munmap(partition_bin);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max)
|
||||
@@ -234,15 +242,13 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const uint32_t app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
|
||||
const uint32_t mmap_size = app_desc_offset + sizeof(esp_app_desc_t);
|
||||
const uint8_t *image = bootloader_mmap(partition->offset, mmap_size);
|
||||
const uint8_t *image = bootloader_mmap(partition->offset, partition->size);
|
||||
if (image == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, mmap_size);
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, partition->size);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
memcpy(app_desc, image + app_desc_offset, sizeof(esp_app_desc_t));
|
||||
memcpy(app_desc, image + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), sizeof(esp_app_desc_t));
|
||||
bootloader_munmap(image);
|
||||
|
||||
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||
@@ -252,7 +258,7 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_common_vddsdio_configure(void)
|
||||
void bootloader_common_vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
@@ -267,6 +273,35 @@ void bootloader_common_vddsdio_configure(void)
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type)
|
||||
{
|
||||
@@ -281,76 +316,7 @@ esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hd
|
||||
ESP_LOGE(TAG, "can't run on lower chip revision, expected %d, found %d", revision, img_hdr->min_chip_rev);
|
||||
err = ESP_FAIL;
|
||||
} else if (revision != img_hdr->min_chip_rev) {
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
ESP_LOGI(TAG, "chip revision: %d, min. %s chip revision: %d", revision, type == ESP_IMAGE_BOOTLOADER ? "bootloader" : "application", img_hdr->min_chip_rev);
|
||||
#endif
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
RESET_REASON bootloader_common_get_reset_reason(int cpu_no)
|
||||
{
|
||||
return rtc_get_reset_reason(cpu_no);
|
||||
}
|
||||
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
|
||||
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
|
||||
|
||||
static bool check_rtc_retain_mem(void)
|
||||
{
|
||||
return crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc)) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
|
||||
}
|
||||
|
||||
static void update_rtc_retain_mem_crc(void)
|
||||
{
|
||||
rtc_retain_mem->crc = crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc));
|
||||
}
|
||||
|
||||
void bootloader_common_reset_rtc_retain_mem(void)
|
||||
{
|
||||
memset(rtc_retain_mem, 0, sizeof(rtc_retain_mem_t));
|
||||
}
|
||||
|
||||
uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void)
|
||||
{
|
||||
if (check_rtc_retain_mem()) {
|
||||
return rtc_retain_mem->reboot_counter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void)
|
||||
{
|
||||
if (check_rtc_retain_mem()) {
|
||||
return &rtc_retain_mem->partition;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter)
|
||||
{
|
||||
if (reboot_counter) {
|
||||
if (!check_rtc_retain_mem()) {
|
||||
bootloader_common_reset_rtc_retain_mem();
|
||||
}
|
||||
if (++rtc_retain_mem->reboot_counter == 0) {
|
||||
// do not allow to overflow. Stop it.
|
||||
--rtc_retain_mem->reboot_counter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (partition != NULL) {
|
||||
rtc_retain_mem->partition.offset = partition->offset;
|
||||
rtc_retain_mem->partition.size = partition->size;
|
||||
}
|
||||
|
||||
update_rtc_retain_mem_crc();
|
||||
}
|
||||
|
||||
rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
|
||||
{
|
||||
return rtc_retain_mem;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
return 160;
|
||||
}
|
||||
return 240;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
/* No known limitation: all chips are 240MHz rated */
|
||||
return 240;
|
||||
}
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
/* No other revisions for ESP32-S2beta */
|
||||
return 0;
|
||||
}
|
||||
@@ -15,10 +15,8 @@
|
||||
|
||||
#include <bootloader_flash.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
@@ -27,7 +25,7 @@ static const char *TAG = "bootloader_mmap";
|
||||
|
||||
static spi_flash_mmap_handle_t map;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages(void)
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
}
|
||||
@@ -39,7 +37,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
return NULL; /* existing mapping in use... */
|
||||
}
|
||||
const void *result = NULL;
|
||||
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
|
||||
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
||||
size += (src_addr - src_page);
|
||||
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
|
||||
if (err != ESP_OK) {
|
||||
@@ -51,7 +49,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapping && map) {
|
||||
if(mapping && map) {
|
||||
spi_flash_munmap(map);
|
||||
}
|
||||
map = 0;
|
||||
@@ -69,11 +67,7 @@ esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_
|
||||
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
|
||||
{
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_flash_write_encrypted(dest_addr, src, size);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return SPI_Encrypt_Write(dest_addr, src, size);
|
||||
#endif
|
||||
} else {
|
||||
return spi_flash_write(dest_addr, src, size);
|
||||
}
|
||||
@@ -92,41 +86,24 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#else
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include <soc/dport_reg.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/spi_flash.h>
|
||||
#include <esp32/rom/cache.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/spi_flash.h>
|
||||
#include <esp32s2beta/rom/cache.h>
|
||||
#endif
|
||||
|
||||
static const char *TAG = "bootloader_flash";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Use first 50 blocks in MMU for bootloader_mmap,
|
||||
50th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x320000)
|
||||
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/* Use first 63 blocks in MMU for bootloader_mmap,
|
||||
63th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x3f0000)
|
||||
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
|
||||
#endif
|
||||
#define MMU_BLOCK0_VADDR 0x3f400000
|
||||
#define MMU_BLOCK50_VADDR 0x3f720000
|
||||
#define MMU_FREE_PAGES ((MMU_BLOCK50_VADDR - MMU_BLOCK0_VADDR) / FLASH_BLOCK_SIZE)
|
||||
|
||||
#define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool mapped;
|
||||
|
||||
// Current bootloader mapping (ab)used for bootloader_read()
|
||||
static uint32_t current_read_mapping = UINT32_MAX;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages(void)
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
/**
|
||||
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
|
||||
@@ -141,41 +118,25 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
ESP_LOGE(TAG, "tried to bootloader_mmap twice");
|
||||
return NULL; /* can't map twice */
|
||||
}
|
||||
if (size > MMU_SIZE) {
|
||||
if (size > 0x320000) {
|
||||
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
|
||||
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
|
||||
uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
mapped = true;
|
||||
|
||||
@@ -185,17 +146,10 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapped) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Full MMU reset */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
mmu_init(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//TODO, save the autoload value.
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
#endif
|
||||
mapped = false;
|
||||
current_read_mapping = UINT32_MAX;
|
||||
}
|
||||
@@ -203,7 +157,7 @@ void bootloader_munmap(const void *mapping)
|
||||
|
||||
static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
|
||||
{
|
||||
switch (r) {
|
||||
switch(r) {
|
||||
case ESP_ROM_SPIFLASH_RESULT_OK:
|
||||
return ESP_OK;
|
||||
case ESP_ROM_SPIFLASH_RESULT_ERR:
|
||||
@@ -217,18 +171,10 @@ static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
|
||||
|
||||
static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
#endif
|
||||
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
return spi_to_esp_err(r);
|
||||
}
|
||||
@@ -237,42 +183,28 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
{
|
||||
uint32_t *dest_words = (uint32_t *)dest;
|
||||
|
||||
/* Use the 51st MMU mapping to read from flash in 64KB blocks.
|
||||
(MMU will transparently decrypt if encryption is enabled.)
|
||||
*/
|
||||
for (int word = 0; word < size / 4; word++) {
|
||||
uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
|
||||
uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
|
||||
uint32_t *map_ptr;
|
||||
if (map_at != current_read_mapping) {
|
||||
/* Move the 64KB mmu mapping window to fit map_at */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, FLASH_READ_VADDR, map_at, 64, 1, 0);
|
||||
#endif
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1);
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return ESP_FAIL;
|
||||
}
|
||||
current_read_mapping = map_at;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
}
|
||||
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
||||
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
|
||||
dest_words[word] = *map_ptr;
|
||||
}
|
||||
return ESP_OK;
|
||||
@@ -323,12 +255,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
}
|
||||
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// TODO: use the same ROM AP here
|
||||
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
|
||||
#endif
|
||||
} else {
|
||||
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
void bootloader_flash_update_id(void)
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config(void)
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
|
||||
@@ -62,7 +62,6 @@ void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 1);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
@@ -1,118 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||
|
||||
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
uint32_t spi_clk_div = 0;
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
spi_clk_div = 1;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
spi_clk_div = 2;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
spi_clk_div = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
spi_clk_div = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
int spi_cache_dummy = 0;
|
||||
int drv = 2;
|
||||
switch (pfhdr->spi_mode) {
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
default:
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
drv = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bootloader_configure_spi_pins(drv);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -13,55 +13,145 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "hal/timer_ll.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "flash_qio_mode.h"
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _data_start;
|
||||
extern int _data_end;
|
||||
|
||||
static const char* TAG = "boot";
|
||||
|
||||
static esp_err_t bootloader_main();
|
||||
static void print_flash_info(const esp_image_header_t* pfhdr);
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr);
|
||||
static void bootloader_init_flash_configure(const esp_image_header_t* pfhdr);
|
||||
static void uart_console_configure(void);
|
||||
static void wdt_reset_check(void);
|
||||
|
||||
|
||||
static const char *TAG = "boot";
|
||||
|
||||
esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
|
||||
|
||||
void bootloader_clear_bss_section(void)
|
||||
esp_err_t bootloader_init()
|
||||
{
|
||||
cpu_configure_region_protection();
|
||||
cpu_init_memctl();
|
||||
|
||||
/* Sanity check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
int *sp = get_sp();
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Clear bss
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
}
|
||||
|
||||
esp_err_t bootloader_read_bootloader_header(void)
|
||||
{
|
||||
/* load bootloader image header */
|
||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to load bootloader image header!");
|
||||
/* completely reset MMU for both CPUs
|
||||
(in case serial bootloader was running) */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Read_Disable(1);
|
||||
Cache_Flush(0);
|
||||
Cache_Flush(1);
|
||||
mmu_init(0);
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
/* (above steps probably unnecessary for most serial bootloader
|
||||
usage, all that's absolutely needed is that we unmask DROM0
|
||||
cache on the following two lines - normal ROM boot exits with
|
||||
DROM0 cache unmasked, but serial bootloader exits with it
|
||||
masked. However can't hurt to be thorough and reset
|
||||
everything.)
|
||||
|
||||
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug.
|
||||
*/
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
|
||||
if(bootloader_main() != ESP_OK){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bootloader_check_bootloader_validity(void)
|
||||
static esp_err_t bootloader_main()
|
||||
{
|
||||
/* read chip revision from efuse */
|
||||
bootloader_common_vddsdio_configure();
|
||||
/* Read and keep flash ID, for further use. */
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
esp_image_header_t fhdr;
|
||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to load bootloader header!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Check chip ID and minimum chip revision that supported by this image */
|
||||
uint8_t revision = bootloader_common_get_chip_revision();
|
||||
ESP_LOGI(TAG, "chip revision: %d", revision);
|
||||
/* compare with the one set in bootloader image header */
|
||||
if (bootloader_common_check_chip_validity(&bootloader_image_hdr, ESP_IMAGE_BOOTLOADER) != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Chip Revision: %d", revision);
|
||||
if (bootloader_common_check_chip_validity(&fhdr, ESP_IMAGE_BOOTLOADER) != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_config_wdt(void)
|
||||
{
|
||||
bootloader_init_flash_configure(&fhdr);
|
||||
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
bootloader_clock_configure();
|
||||
uart_console_configure();
|
||||
wdt_reset_check();
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
|
||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||
ets_set_appcpu_boot_addr(0);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||
rtc_wdt_protect_off();
|
||||
@@ -72,28 +162,293 @@ void bootloader_config_wdt(void)
|
||||
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||
rtc_wdt_enable();
|
||||
rtc_wdt_protect_on();
|
||||
#else /* disable watch dog */
|
||||
#else
|
||||
/* disable watch dog here */
|
||||
rtc_wdt_disable();
|
||||
#endif
|
||||
timer_ll_wdt_set_protect(&TIMERG0, false);
|
||||
timer_ll_wdt_flashboot_en(&TIMERG0, false);
|
||||
}
|
||||
REG_SET_FIELD(TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY, TIMG_WDT_WKEY_VALUE);
|
||||
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
void bootloader_enable_random(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
||||
bootloader_random_enable();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&fhdr);
|
||||
|
||||
update_flash_config(&fhdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_print_banner(void)
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
ESP_LOGI(TAG, "compile time " __TIME__);
|
||||
uint32_t size;
|
||||
switch(pfhdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
Cache_Read_Disable( 0 );
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Flush(0);
|
||||
Cache_Read_Enable( 0 );
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t* phdr)
|
||||
{
|
||||
#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
|
||||
|
||||
ESP_LOGD(TAG, "magic %02x", phdr->magic );
|
||||
ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
|
||||
ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
|
||||
ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
|
||||
ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
|
||||
|
||||
const char* str;
|
||||
switch ( phdr->spi_speed ) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str );
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str );
|
||||
|
||||
switch ( phdr->spi_size ) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootloader reads SPI configuration from bin header, so that
|
||||
* the burning configuration can be different with compiling configuration.
|
||||
*/
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
bootloader_flash_gpio_config(pfhdr);
|
||||
bootloader_flash_dummy_config(pfhdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static void uart_console_configure(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
|
||||
const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
|
||||
const uint32_t uart_reset[3] = { DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST };
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
||||
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
|
||||
} else {
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
}
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void wdt_reset_check(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
wdt_reset_info_dump(1);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void __assert_func(const char *file, int line, const char *func, const char *expr)
|
||||
{
|
||||
ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
|
||||
while (1) {
|
||||
}
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__ ("break 0,0");
|
||||
}
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
#include "esp_system.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
@@ -35,9 +34,7 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
uint32_t random;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t start, now;
|
||||
#endif
|
||||
|
||||
assert(buffer != NULL);
|
||||
|
||||
@@ -50,18 +47,14 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
as-is, we repeatedly read the RNG register and XOR all
|
||||
values.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
random = REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, start);
|
||||
do {
|
||||
random ^= REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, now);
|
||||
} while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// ToDo: Get random from register
|
||||
random = 12345678;
|
||||
#endif
|
||||
} while(now - start < 80*32*2); /* extra factor of 2 is precautionary */
|
||||
}
|
||||
|
||||
buffer_bytes[i] = random >> ((i % 4) * 8);
|
||||
}
|
||||
}
|
||||
@@ -72,11 +65,7 @@ void bootloader_random_enable(void)
|
||||
/* Ensure the hardware RNG is enabled following a soft reset. This should always be the case already (this clock is
|
||||
never disabled while the CPU is running), this is a "belts and braces" type check.
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN);
|
||||
#else
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
/* Enable SAR ADC in test mode to feed ADC readings of the 1.1V
|
||||
reference via I2S into the RNG entropy input.
|
||||
@@ -86,23 +75,11 @@ void bootloader_random_enable(void)
|
||||
*/
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 2, RTC_CNTL_DTEST_RTC_S);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
#else
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP);
|
||||
#endif
|
||||
|
||||
// Test pattern configuration byte 0xAD:
|
||||
//--[7:4] channel_sel: 10-->en_test
|
||||
//--[3:2] bit_width : 3-->12bit
|
||||
@@ -111,31 +88,22 @@ void bootloader_random_enable(void)
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB4_REG, 0xADADADAD);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S);
|
||||
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL);
|
||||
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S);
|
||||
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG,SYSCON_SARADC_DATA_TO_I2S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
@@ -157,43 +125,22 @@ void bootloader_random_disable(void)
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
|
||||
/* Disable i2s clock */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
#else
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
/* Restore SYSCON mode registers */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Restore SAR ADC mode */
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
|
||||
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
#else
|
||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||
#endif
|
||||
|
||||
/* Disable pull supply voltage to SAR ADC */
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@@ -29,19 +28,6 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#else
|
||||
#error "Unsupported IDF_TARGET"
|
||||
#endif
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@@ -65,22 +51,22 @@
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
static const char* TAG = "boot";
|
||||
|
||||
/* Reduce literal size for some generic string literals */
|
||||
#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
|
||||
|
||||
static bool ota_has_initial_contents;
|
||||
|
||||
static void load_image(const esp_image_metadata_t *image_data);
|
||||
static void load_image(const esp_image_metadata_t* image_data);
|
||||
static void unpack_load_app(const esp_image_metadata_t *data);
|
||||
static void set_cache_and_start_app(uint32_t drom_addr,
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
|
||||
// Read ota_info partition and fill array from two otadata structures.
|
||||
static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_select_entry_t *two_otadata)
|
||||
@@ -110,7 +96,7 @@ static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_selec
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
|
||||
{
|
||||
const esp_partition_info_t *partitions;
|
||||
const char *partition_usage;
|
||||
@@ -133,16 +119,16 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
ESP_LOGI(TAG, "Partition Table:");
|
||||
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
|
||||
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
for(int i = 0; i < num_partitions; i++) {
|
||||
const esp_partition_info_t *partition = &partitions[i];
|
||||
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
|
||||
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
|
||||
partition_usage = "unknown";
|
||||
|
||||
/* valid partition table */
|
||||
switch (partition->type) {
|
||||
switch(partition->type) {
|
||||
case PART_TYPE_APP: /* app partition */
|
||||
switch (partition->subtype) {
|
||||
switch(partition->subtype) {
|
||||
case PART_SUBTYPE_FACTORY: /* factory binary */
|
||||
bs->factory = partition->pos;
|
||||
partition_usage = "factory app";
|
||||
@@ -157,14 +143,15 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
|
||||
++bs->app_count;
|
||||
partition_usage = "OTA app";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
partition_usage = "Unknown app";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break; /* PART_TYPE_APP */
|
||||
case PART_TYPE_DATA: /* data partition */
|
||||
switch (partition->subtype) {
|
||||
switch(partition->subtype) {
|
||||
case PART_SUBTYPE_DATA_OTA: /* ota data */
|
||||
bs->ota_info = partition->pos;
|
||||
partition_usage = "OTA data";
|
||||
@@ -201,7 +188,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
|
||||
bootloader_munmap(partitions);
|
||||
|
||||
ESP_LOGI(TAG, "End of partition table");
|
||||
ESP_LOGI(TAG,"End of partition table");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -227,7 +214,7 @@ static esp_partition_pos_t index_to_partition(const bootloader_state_t *bs, int
|
||||
static void log_invalid_app_partition(int index)
|
||||
{
|
||||
const char *not_bootable = " is not bootable"; /* save a few string literal bytes */
|
||||
switch (index) {
|
||||
switch(index) {
|
||||
case FACTORY_INDEX:
|
||||
ESP_LOGE(TAG, "Factory app partition%s", not_bootable);
|
||||
break;
|
||||
@@ -330,8 +317,8 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=%d)", bs->app_count);
|
||||
if (bs->factory.offset != 0) {
|
||||
ESP_LOGI(TAG, "Defaulting to factory image");
|
||||
@@ -341,7 +328,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
boot_index = 0;
|
||||
// Try to boot from ota_0.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
// Factory is not found and both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
ota_has_initial_contents = true;
|
||||
@@ -354,7 +341,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
ESP_LOGI(TAG, "Secure version (from eFuse) = %d", esp_efuse_read_secure_version());
|
||||
// When CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK is enabled factory partition should not be in partition table, only two ota_app are there.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
ESP_LOGI(TAG, "otadata[0..1] in initial state");
|
||||
// both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
@@ -429,31 +416,8 @@ static void set_actual_ota_seq(const bootloader_state_t *bs, int index)
|
||||
update_anti_rollback(&bs->ota[index]);
|
||||
#endif
|
||||
}
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
esp_partition_pos_t partition = index_to_partition(bs, index);
|
||||
bootloader_common_update_rtc_retain_mem(&partition, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
void bootloader_utility_load_boot_image_from_deep_sleep(void)
|
||||
{
|
||||
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
|
||||
esp_partition_pos_t* partition = bootloader_common_get_rtc_retain_mem_partition();
|
||||
if (partition != NULL) {
|
||||
esp_image_metadata_t image_data;
|
||||
if (bootloader_load_image_no_verify(partition, &image_data) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Fast booting app from partition at offset 0x%x", partition->offset);
|
||||
bootloader_common_update_rtc_retain_mem(NULL, true);
|
||||
load_image(&image_data);
|
||||
}
|
||||
}
|
||||
ESP_LOGE(TAG, "Fast booting is not successful");
|
||||
ESP_LOGI(TAG, "Try to load an app as usual with all validations");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x"
|
||||
|
||||
void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index)
|
||||
@@ -462,7 +426,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
esp_partition_pos_t part;
|
||||
esp_image_metadata_t image_data;
|
||||
|
||||
if (start_index == TEST_APP_INDEX) {
|
||||
if(start_index == TEST_APP_INDEX) {
|
||||
if (try_load_partition(&bs->test, &image_data)) {
|
||||
load_image(&image_data);
|
||||
} else {
|
||||
@@ -472,7 +436,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
/* work backwards from start_index, down to the factory app */
|
||||
for (index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
for(index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
part = index_to_partition(bs, index);
|
||||
if (part.size == 0) {
|
||||
continue;
|
||||
@@ -486,7 +450,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
/* failing that work forwards from start_index, try valid OTA slots */
|
||||
for (index = start_index + 1; index < bs->app_count; index++) {
|
||||
for(index = start_index + 1; index < bs->app_count; index++) {
|
||||
part = index_to_partition(bs, index);
|
||||
if (part.size == 0) {
|
||||
continue;
|
||||
@@ -510,7 +474,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
// Copy loaded segments to RAM, set up caches for mapped segments, and start application.
|
||||
static void load_image(const esp_image_metadata_t *image_data)
|
||||
static void load_image(const esp_image_metadata_t* image_data)
|
||||
{
|
||||
/**
|
||||
* Rough steps for a first boot, when encryption and secure boot are both disabled:
|
||||
@@ -555,19 +519,11 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
* then Step 6 enables secure boot.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
|
||||
esp_err_t err;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
err = esp_secure_boot_v2_permanently_enable(image_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot v2 failed (%d)", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* Steps 1 & 2 (see above for full description):
|
||||
* 1) Generate secure boot EFUSE key
|
||||
* 2) Compute digest of plaintext bootloader
|
||||
@@ -594,7 +550,7 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* Step 6 (see above for full description):
|
||||
* 6) Burn EFUSE to enable secure boot
|
||||
*/
|
||||
@@ -615,21 +571,18 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
so issue a system reset to ensure flash encryption
|
||||
cache resets properly */
|
||||
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
|
||||
uart_tx_wait_idle(0);
|
||||
bootloader_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Disabling RNG early entropy source...");
|
||||
#if !CONFIG_IDF_ENV_FPGA
|
||||
bootloader_random_disable();
|
||||
#endif
|
||||
|
||||
// copy loaded segments to RAM, set up caches for mapped segments, and start application
|
||||
unpack_load_app(image_data);
|
||||
}
|
||||
|
||||
static void unpack_load_app(const esp_image_metadata_t *data)
|
||||
static void unpack_load_app(const esp_image_metadata_t* data)
|
||||
{
|
||||
uint32_t drom_addr = 0;
|
||||
uint32_t drom_load_addr = 0;
|
||||
@@ -665,12 +618,12 @@ static void unpack_load_app(const esp_image_metadata_t *data)
|
||||
|
||||
ESP_LOGD(TAG, "calling set_cache_and_start_app");
|
||||
set_cache_and_start_app(drom_addr,
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
}
|
||||
|
||||
static void set_cache_and_start_app(
|
||||
@@ -684,13 +637,8 @@ static void set_cache_and_start_app(
|
||||
{
|
||||
int rc;
|
||||
ESP_LOGD(TAG, "configure drom and irom and start");
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
Cache_Read_Disable( 0 );
|
||||
Cache_Flush( 0 );
|
||||
|
||||
/* Clear the MMU entries that are already set up,
|
||||
so the new app only has the mappings it creates.
|
||||
@@ -702,66 +650,33 @@ static void set_cache_and_start_app(
|
||||
uint32_t drom_load_addr_aligned = drom_load_addr & MMU_FLASH_MASK;
|
||||
uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr);
|
||||
ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
|
||||
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000,
|
||||
64, drom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#endif
|
||||
|
||||
uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK;
|
||||
uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr);
|
||||
ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
|
||||
rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t iram1_used = 0, irom0_used = 0;
|
||||
if (irom_load_addr + irom_size > IRAM1_ADDRESS_LOW) {
|
||||
iram1_used = 1;
|
||||
}
|
||||
if (irom_load_addr + irom_size > IROM0_ADDRESS_LOW) {
|
||||
irom0_used = 1;
|
||||
}
|
||||
if (iram1_used || irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM1_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IRAM1);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IRAM1);
|
||||
if (irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IROM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IROM0);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IROM0);
|
||||
}
|
||||
}
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
|
||||
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
|
||||
DPORT_PRO_CACHE_MASK_DRAM1 );
|
||||
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
|
||||
DPORT_PRO_CACHE_MASK_DRAM1 );
|
||||
|
||||
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
|
||||
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_ICACHE_CTRL1_REG, (DPORT_PRO_ICACHE_MASK_IRAM0) | (DPORT_PRO_ICACHE_MASK_IRAM1 & 0) | (DPORT_PRO_ICACHE_MASK_IROM0 & 0) | DPORT_PRO_ICACHE_MASK_DROM0 );
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
|
||||
Cache_Read_Enable( 0 );
|
||||
|
||||
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
||||
|
||||
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
|
||||
@@ -773,6 +688,7 @@ static void set_cache_and_start_app(
|
||||
(*entry)();
|
||||
}
|
||||
|
||||
|
||||
void bootloader_reset(void)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@@ -803,58 +719,3 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
assert(length <= 128); // Avoid unbounded VLA size
|
||||
const uint8_t *bytes = (const uint8_t *)buffer;
|
||||
char hexbuf[length * 2 + 1];
|
||||
hexbuf[length * 2] = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int shift = 0; shift < 2; shift++) {
|
||||
uint8_t nibble = (bytes[i] >> (shift ? 0 : 4)) & 0x0F;
|
||||
if (nibble < 10) {
|
||||
hexbuf[i * 2 + shift] = '0' + nibble;
|
||||
} else {
|
||||
hexbuf[i * 2 + shift] = 'a' + nibble - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "%s: %s", label, hexbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
{
|
||||
if (digest == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Handling firmware images larger than MMU capacity */
|
||||
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */
|
||||
uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */
|
||||
|
||||
const void * image = bootloader_mmap(flash_offset, partial_image_len);
|
||||
if (image == NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, image, partial_image_len);
|
||||
bootloader_munmap(image);
|
||||
|
||||
flash_offset += partial_image_len;
|
||||
len -= partial_image_len;
|
||||
}
|
||||
bootloader_sha256_finish(sha_handle, digest);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -1,480 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
|
||||
static const char *TAG = "boot.esp32";
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
void bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
uint32_t pkg_ver = chip_ver & 0x7;
|
||||
|
||||
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
|
||||
// For ESP32D2WD the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
||||
// For ESP32PICOD2 the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
|
||||
// For ESP32PICOD4 the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else {
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
/* completely reset MMU in case serial bootloader was running */
|
||||
Cache_Read_Disable(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Read_Disable(1);
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
mmu_init(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
/* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug. */
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
#endif
|
||||
|
||||
/* normal ROM boot exits with DROM0 cache unmasked,
|
||||
but serial bootloader exits with it masked. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_check_rated_cpu_clock(void)
|
||||
{
|
||||
int rated_freq = bootloader_clock_get_rated_freq_mhz();
|
||||
if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
|
||||
rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
Cache_Read_Disable(0);
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Flush(0);
|
||||
Cache_Read_Enable(0);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_gpio_config(&bootloader_image_hdr);
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void bootloader_init_uart_console(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX};
|
||||
const uint32_t rx_idx_list[3] = {U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX};
|
||||
const uint32_t uart_reset[3] = {DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST};
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
||||
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
#else
|
||||
ESP_LOGE(TAG, "WDT reset info: &s CPU not support!\n", cpu_name);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
wdt_reset_info_dump(1);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__("break 0,0");
|
||||
}
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
// workaround for tensilica erratum572
|
||||
cpu_init_memctl();
|
||||
// protect memory region
|
||||
cpu_configure_region_protection();
|
||||
// check that static RAM is after the stack
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
int *sp = get_sp();
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
}
|
||||
#endif
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// bootst up vddsdio
|
||||
bootloader_common_vddsdio_configure();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// check rated CPU clock
|
||||
if ((ret = bootloader_check_rated_cpu_clock()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize uart console, from now on, we can use esp_log
|
||||
bootloader_init_uart_console();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -16,10 +16,9 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_periph.h"
|
||||
#include "esp32/rom/ets_sys.h" // TO REMOVE
|
||||
|
||||
static uint32_t words_hashed;
|
||||
|
||||
@@ -28,7 +27,7 @@ static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t));
|
||||
// Words in final SHA256 digest
|
||||
static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void)
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
|
||||
@@ -38,7 +38,7 @@ static const char *TAG = "flash_encrypt";
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_bootloader();
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
@@ -73,10 +73,6 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata5 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE && coding_scheme != EFUSE_CODING_SCHEME_VAL_34) {
|
||||
ESP_LOGE(TAG, "Unknown/unsupported CODING_SCHEME value 0x%x", coding_scheme);
|
||||
@@ -101,10 +97,11 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
&& REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
esp_efuse_write_random_key(EFUSE_BLK1_WDATA0_REG);
|
||||
// defer efuse programming step to the end
|
||||
esp_efuse_burn_new_values();
|
||||
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
new_wdata0 |= EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1;
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1);
|
||||
esp_efuse_burn_new_values();
|
||||
} else {
|
||||
|
||||
if(!(efuse_key_read_protected && efuse_key_write_protected)) {
|
||||
@@ -125,36 +122,34 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
operation does nothing. Please note this is not recommended!
|
||||
*/
|
||||
ESP_LOGI(TAG, "Setting CRYPT_CONFIG efuse to 0xF");
|
||||
new_wdata5 |= EFUSE_FLASH_CRYPT_CONFIG_M;
|
||||
REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M);
|
||||
esp_efuse_burn_new_values();
|
||||
|
||||
uint32_t new_wdata6 = 0;
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader decryption...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
ESP_LOGI(TAG, "Disable UART bootloader MMU cache...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_CACHE;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
|
||||
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
|
||||
@@ -162,16 +157,10 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
|
||||
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
|
||||
// otherwise the Flash Encryption key cannot be read protected
|
||||
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA5_REG, new_wdata5);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
if (new_wdata6 != 0) {
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -185,7 +174,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
|
||||
/* If the last flash_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis || flash_crypt_cnt == 0xFF) {
|
||||
if (flash_crypt_wr_dis) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -221,19 +210,16 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
uint32_t new_flash_crypt_cnt;
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
// Go straight to max, permanently enabled
|
||||
ESP_LOGI(TAG, "Setting FLASH_CRYPT_CNT for permanent encryption");
|
||||
new_flash_crypt_cnt = EFUSE_FLASH_CRYPT_CNT;
|
||||
#else
|
||||
/* Set least significant 0-bit in flash_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~flash_crypt_cnt) & EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
/* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == EFUSE_RD_FLASH_CRYPT_CNT (0x7F) */
|
||||
new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
#endif
|
||||
uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt);
|
||||
uint32_t wdata0_reg = ((new_flash_crypt_cnt & EFUSE_FLASH_CRYPT_CNT) << EFUSE_FLASH_CRYPT_CNT_S);
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
ESP_LOGI(TAG, "Write protecting FLASH_CRYPT_CNT eFuse");
|
||||
wdata0_reg |= EFUSE_WR_DIS_FLASH_CRYPT_CNT;
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, wdata0_reg);
|
||||
esp_efuse_burn_new_values();
|
||||
@@ -243,29 +229,20 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
static esp_err_t encrypt_bootloader()
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
|
||||
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
|
||||
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* If secure boot is enabled and bootloader was plaintext, also
|
||||
* need to encrypt secure boot IV+digest.
|
||||
*/
|
||||
@@ -378,4 +355,4 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,10 @@
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@@ -40,8 +38,8 @@
|
||||
* from the bootloader code.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
static const char *TAG = "secure_boot_v1";
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
/**
|
||||
* @function : secure_boot_generate
|
||||
* @description: generate boot digest (aka "abstract") & iv
|
||||
@@ -96,6 +94,12 @@ static bool secure_boot_generate(uint32_t image_len){
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Burn values written to the efuse write registers */
|
||||
static inline void burn_efuses()
|
||||
{
|
||||
esp_efuse_burn_new_values();
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_generate_digest(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -135,7 +139,7 @@ esp_err_t esp_secure_boot_generate_digest(void)
|
||||
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new secure boot key...");
|
||||
esp_efuse_write_random_key(EFUSE_BLK2_WDATA0_REG);
|
||||
esp_efuse_burn_new_values();
|
||||
burn_efuses();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
|
||||
}
|
||||
@@ -158,9 +162,6 @@ esp_err_t esp_secure_boot_generate_digest(void)
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
@@ -172,7 +173,8 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
if (efuse_key_read_protected == false
|
||||
&& efuse_key_write_protected == false) {
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
new_wdata0 = EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2;
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||
burn_efuses();
|
||||
efuse_key_read_protected = true;
|
||||
efuse_key_write_protected = true;
|
||||
}
|
||||
@@ -189,7 +191,7 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
ESP_LOGI(TAG, "blowing secure boot efuse...");
|
||||
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||
|
||||
new_wdata6 |= EFUSE_RD_ABS_DONE_0;
|
||||
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
@@ -205,9 +207,8 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
burn_efuses();
|
||||
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
|
||||
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after);
|
||||
if (after & EFUSE_RD_ABS_DONE_0) {
|
||||
@@ -218,228 +219,3 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_signature_t *sig_block, uint8_t *digest)
|
||||
{
|
||||
uint32_t crc = crc32_le(0, (uint8_t *)sig_block, CRC_SIGN_BLOCK_LEN);
|
||||
if (sig_block->block[0].magic_byte == SIG_BLOCK_MAGIC_BYTE && sig_block->block[0].block_crc == crc && !memcmp(digest, sig_block->block[0].image_digest, DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "valid signature block found");
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t flash_size, uint8_t *public_key_digest)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "reading signature block");
|
||||
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
if (sig_block == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Validating Signature block */
|
||||
ret = validate_signature_block(sig_block, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "signature block (address 0x%x) validation failed %d", sig_block_addr, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Verifying Signature block */
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0};
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
|
||||
bootloader_sha256_finish(sig_block_sha, public_key_digest);
|
||||
|
||||
secure_boot_v2_status_t error;
|
||||
error = ets_secure_boot_verify_signature(sig_block, image_digest, public_key_digest, verified_digest);
|
||||
if (error != SBV2_SUCCESS) {
|
||||
ESP_LOGE(TAG, "secure boot v2 verification failed %d", error);
|
||||
ret = ESP_FAIL;
|
||||
goto done;
|
||||
} else {
|
||||
ret = ESP_OK;
|
||||
}
|
||||
|
||||
done:
|
||||
bootloader_munmap(sig_block);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
ESP_LOGI(TAG, "enabling secure boot v2...");
|
||||
esp_err_t ret;
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "secure boot v2 is already enabled. Continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE) {
|
||||
ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Verify the bootloader */
|
||||
esp_image_metadata_t bootloader_data = { 0 };
|
||||
ret = esp_image_verify_bootloader_data(&bootloader_data);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t boot_pub_key_digest[DIGEST_LEN];
|
||||
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
|
||||
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
|
||||
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
|
||||
uint32_t efuse_blk2_r0, efuse_blk2_r1, efuse_blk2_r2, efuse_blk2_r3, efuse_blk2_r4, efuse_blk2_r5, efuse_blk2_r6, efuse_blk2_r7;
|
||||
efuse_blk2_r0 = REG_READ(EFUSE_BLK2_RDATA0_REG);
|
||||
efuse_blk2_r1 = REG_READ(EFUSE_BLK2_RDATA1_REG);
|
||||
efuse_blk2_r2 = REG_READ(EFUSE_BLK2_RDATA2_REG);
|
||||
efuse_blk2_r3 = REG_READ(EFUSE_BLK2_RDATA3_REG);
|
||||
efuse_blk2_r4 = REG_READ(EFUSE_BLK2_RDATA4_REG);
|
||||
efuse_blk2_r5 = REG_READ(EFUSE_BLK2_RDATA5_REG);
|
||||
efuse_blk2_r6 = REG_READ(EFUSE_BLK2_RDATA6_REG);
|
||||
efuse_blk2_r7 = REG_READ(EFUSE_BLK2_RDATA7_REG);
|
||||
|
||||
if (efuse_key_read_protected == true) {
|
||||
ESP_LOGE(TAG, "Secure Boot v2 digest(BLK2) read protected, aborting....");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (efuse_key_write_protected == false
|
||||
&& efuse_blk2_r0 == 0 && efuse_blk2_r1 == 0
|
||||
&& efuse_blk2_r2 == 0 && efuse_blk2_r3 == 0
|
||||
&& efuse_blk2_r4 == 0 && efuse_blk2_r5 == 0
|
||||
&& efuse_blk2_r6 == 0 && efuse_blk2_r7 == 0) {
|
||||
/* Verifies the signature block appended to the image matches with the signature block of the app to be loaded */
|
||||
ret = secure_boot_v2_digest_generate(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, boot_pub_key_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Public key digest generation failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Burning public key hash to efuse.");
|
||||
uint32_t *boot_public_key_digest_ptr = (uint32_t *) boot_pub_key_digest;
|
||||
for (int i = 0; i < 8 ; i++) {
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4 * i, boot_public_key_digest_ptr[i]);
|
||||
ESP_LOGD(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, boot_public_key_digest_ptr[i]);
|
||||
}
|
||||
// delay burning until second half of this function
|
||||
|
||||
} else {
|
||||
uint32_t efuse_blk2_digest[8];
|
||||
efuse_blk2_digest[0] = efuse_blk2_r0;
|
||||
efuse_blk2_digest[1] = efuse_blk2_r1;
|
||||
efuse_blk2_digest[2] = efuse_blk2_r2;
|
||||
efuse_blk2_digest[3] = efuse_blk2_r3;
|
||||
efuse_blk2_digest[4] = efuse_blk2_r4;
|
||||
efuse_blk2_digest[5] = efuse_blk2_r5;
|
||||
efuse_blk2_digest[6] = efuse_blk2_r6;
|
||||
efuse_blk2_digest[7] = efuse_blk2_r7;
|
||||
memcpy(boot_pub_key_digest, efuse_blk2_digest, DIGEST_LEN);
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2");
|
||||
}
|
||||
|
||||
// This case is needed either if a pre-burned digest is present but not write-protected,
|
||||
// or if we are burning the digest now
|
||||
if (efuse_key_write_protected == false) {
|
||||
ESP_LOGI(TAG, "Write protecting public key digest...");
|
||||
new_wdata0 |= EFUSE_WR_DIS_BLK2; // delay burning until second half of this function
|
||||
}
|
||||
|
||||
uint8_t app_pub_key_digest[DIGEST_LEN];
|
||||
ret = secure_boot_v2_digest_generate(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, app_pub_key_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Application signature block is invalid.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Confirming if the public key in the bootloader's signature block matches with the one in the application's signature block */
|
||||
if (memcmp(boot_pub_key_digest, app_pub_key_digest, DIGEST_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Application not signed with a valid private key.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (efuse_key_read_protected) {
|
||||
ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is read protected. Refusing to blow secure boot efuse.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "blowing secure boot efuse...");
|
||||
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||
|
||||
new_wdata6 |= EFUSE_RD_ABS_DONE_1;
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
|
||||
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
||||
bool rd_dis_now = true;
|
||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
/* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
|
||||
when Flash Encryption is being enabled */
|
||||
rd_dis_now = esp_flash_encryption_enabled();
|
||||
#endif
|
||||
if (rd_dis_now) {
|
||||
ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
|
||||
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
|
||||
}
|
||||
#else
|
||||
ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
|
||||
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA0 0x%08x EFUSE_BLK0_RDATA6 0x%08x",
|
||||
REG_READ(EFUSE_BLK0_RDATA0_REG), after);
|
||||
if (after & EFUSE_RD_ABS_DONE_1) {
|
||||
ESP_LOGI(TAG, "secure boot v2 is now enabled.");
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, " secure boot v2 not enabled, EFUSE_RD_ABS_DONE_1 is probably write protected!");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
@@ -15,40 +15,61 @@
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_fault.h"
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "uECC_verify_antifault.h"
|
||||
#include "uECC.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
|
||||
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
|
||||
|
||||
#define SIGNATURE_VERIFICATION_KEYLEN 64
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* Mmap source address mask */
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* ignored in this function */
|
||||
const uint8_t *data;
|
||||
const esp_secure_boot_sig_block_t *sigblock;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
|
||||
uint32_t free_page_count = bootloader_mmap_get_free_pages();
|
||||
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
|
||||
|
||||
int32_t data_len_remain = length;
|
||||
uint32_t data_addr = src_addr;
|
||||
while (data_len_remain > 0) {
|
||||
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
|
||||
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
|
||||
uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
|
||||
data = (const uint8_t *) bootloader_mmap(data_addr, data_len);
|
||||
if(!data) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len);
|
||||
bootloader_sha256_finish(handle, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
bootloader_sha256_data(handle, data, data_len);
|
||||
bootloader_munmap(data);
|
||||
|
||||
data_addr += data_len;
|
||||
data_len_remain -= data_len;
|
||||
}
|
||||
|
||||
/* Done! Get the digest */
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
|
||||
// Map the signature block
|
||||
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
if(!sigblock) {
|
||||
@@ -56,7 +77,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// Verify the signature
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
|
||||
// Unmap
|
||||
bootloader_munmap(sigblock);
|
||||
|
||||
@@ -64,12 +85,6 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
|
||||
{
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 };
|
||||
return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
ptrdiff_t keylen;
|
||||
|
||||
@@ -87,98 +102,11 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
bool is_valid;
|
||||
is_valid = uECC_verify_antifault(signature_verification_key_start,
|
||||
is_valid = uECC_verify(signature_verification_key_start,
|
||||
image_digest,
|
||||
DIGEST_LEN,
|
||||
sig_block->signature,
|
||||
uECC_secp256r1(),
|
||||
verified_digest);
|
||||
uECC_secp256r1());
|
||||
ESP_LOGD(TAG, "Verification result %d", is_valid);
|
||||
|
||||
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0}; // ignored in this function
|
||||
const uint8_t *data;
|
||||
|
||||
/* Padding to round off the input to the nearest 4k boundary */
|
||||
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
|
||||
|
||||
data = bootloader_mmap(src_addr, padded_length + sizeof(ets_secure_boot_signature_t));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, padded_length);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Calculate digest of main image */
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
|
||||
bootloader_munmap(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
const ets_secure_boot_signature_t *sig_block = (const ets_secure_boot_signature_t *)(data + padded_length);
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
|
||||
bootloader_munmap(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
secure_boot_v2_status_t r;
|
||||
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
|
||||
|
||||
memcpy(efuse_trusted_digest, (uint8_t *)EFUSE_BLK2_RDATA0_REG, DIGEST_LEN); /* EFUSE_BLK2_RDATA0_REG - Stores the Secure Boot Public Key Digest */
|
||||
|
||||
if (!ets_use_secure_boot_v2()) {
|
||||
ESP_LOGI(TAG, "Secure Boot eFuse bit(ABS_DONE_1) not yet programmed.");
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
|
||||
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
|
||||
/* Most likely explanation for this is that BLK2 is empty, and we're going to burn it
|
||||
after we verify that the signature is valid. However, if BLK2 is not empty then we need to
|
||||
fail here.
|
||||
*/
|
||||
bool all_zeroes = true;
|
||||
for (int i = 0; i < DIGEST_LEN; i++) {
|
||||
all_zeroes = all_zeroes && (efuse_trusted_digest[i] == 0);
|
||||
}
|
||||
if (!all_zeroes) {
|
||||
ESP_LOGE(TAG, "Different public key digest burned to eFuse BLK2");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_FAULT_ASSERT(!ets_use_secure_boot_v2());
|
||||
#endif
|
||||
|
||||
memcpy(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
r = ets_secure_boot_verify_signature(sig_block, image_digest, efuse_trusted_digest, verified_digest);
|
||||
if (r != SBV2_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
|
||||
return (r == SBV2_SUCCESS) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,399 +0,0 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
static const char *TAG = "boot.esp32s2";
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
void bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
//ToDo: save the autoload value
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
|
||||
/* normal ROM boot exits with DROM0 cache unmasked,
|
||||
but serial bootloader exits with it masked. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_DROM0);
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Resume_ICache(autoload);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_MEM_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_gpio_config(&bootloader_image_hdr);
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void bootloader_init_uart_console(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX};
|
||||
const uint32_t rx_idx_list[3] = {U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX};
|
||||
const uint32_t uart_reset[3] = {DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST};
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_PDEBUGENABLE, 1);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_RCD_RECORDING, 1);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
stat = 0xdeadbeef;
|
||||
pid = 0;
|
||||
inst = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGINST);
|
||||
dstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGSTATUS);
|
||||
data = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGDATA);
|
||||
pc = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGPC);
|
||||
lsstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0STAT);
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0ADDR);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0DATA);
|
||||
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#if !CONFIG_ESP32S2_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__("break 0,0");
|
||||
}
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
// protect memory region
|
||||
cpu_configure_region_protection();
|
||||
/* check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
}
|
||||
#endif
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize uart console, from now on, we can use esp_log
|
||||
bootloader_init_uart_console();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32s2beta/rom/sha.h"
|
||||
|
||||
static SHA_CTX ctx;
|
||||
|
||||
// Words per SHA256 block
|
||||
// static const size_t BLOCK_WORDS = (64/sizeof(uint32_t));
|
||||
// Words in final SHA256 digest
|
||||
// static const size_t DIGEST_WORDS = (32/sizeof(uint32_t));
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
ets_sha_init(&ctx, SHA2_256);
|
||||
return &ctx; // Meaningless non-NULL value
|
||||
}
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
assert(data_len % 4 == 0);
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
if (digest == NULL) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
return;
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
|
||||
static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
{
|
||||
// TODO: not clear why this is read from DATA1 and written to PGM_DATA2
|
||||
uint32_t cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", cnt);
|
||||
|
||||
bool flash_crypt_wr_dis = false; // TODO: check if CRYPT_CNT is write disabled
|
||||
|
||||
_Static_assert(EFUSE_SPI_BOOT_CRYPT_CNT == 0x7, "assuming CRYPT_CNT is only 3 bits wide");
|
||||
|
||||
if (cnt == 1 || cnt == 3 || cnt == 7) {
|
||||
/* Flash is already encrypted */
|
||||
int left;
|
||||
if (cnt == 7 /* || disabled */) {
|
||||
left = 0;
|
||||
} else if (cnt == 3) {
|
||||
left = 1;
|
||||
} else {
|
||||
left = 2;
|
||||
}
|
||||
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(cnt, flash_crypt_wr_dis);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
/* Before first flash encryption pass, need to initialise key & crypto config */
|
||||
|
||||
/* Find out if a key is already set */
|
||||
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, NULL);
|
||||
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, NULL);
|
||||
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, NULL);
|
||||
|
||||
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2);
|
||||
|
||||
if (!has_key && (has_aes256_1 || has_aes256_2)) {
|
||||
ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (has_key) {
|
||||
ESP_LOGI(TAG, "Using pre-existing key in efuse");
|
||||
|
||||
ESP_LOGE(TAG, "TODO: Check key is read & write protected"); // TODO
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
|
||||
const unsigned BLOCKS_NEEDED = 2;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2;
|
||||
#else
|
||||
const unsigned BLOCKS_NEEDED = 1;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
#endif
|
||||
|
||||
if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) {
|
||||
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) {
|
||||
uint32_t buf[8];
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
|
||||
ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d",
|
||||
block - ETS_EFUSE_BLOCK_KEY0, purpose);
|
||||
bootloader_debug_buffer(buf, sizeof(buf), "Key content");
|
||||
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
|
||||
bzero(buf, sizeof(buf));
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Key generation complete");
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "TODO: burn remaining security protection bits"); // TODO
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Encrypt all flash data that should be encrypted */
|
||||
static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
|
||||
/* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (spi_boot_crypt_cnt == 0) {
|
||||
/* Very first flash of encrypted data: generate keys, etc. */
|
||||
err = initialise_flash_encryption();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_bootloader();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Now iterate the just-loaded partition table, looking for entries to encrypt
|
||||
*/
|
||||
|
||||
/* Go through each partition and encrypt if necessary */
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
err = encrypt_partition(i, &partition_table[i]);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
/* Set least significant 0-bit in spi_boot_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
|
||||
/* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
|
||||
uint32_t new_spi_boot_crypt_cnt = spi_boot_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt);
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_FIELD(EFUSE_PGM_DATA2_REG, EFUSE_SPI_BOOT_CRYPT_CNT, new_spi_boot_crypt_cnt);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
ESP_LOGI(TAG, "Flash encryption completed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
|
||||
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
|
||||
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
// TODO: anything different for secure boot?
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Valid partition table loded */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
|
||||
{
|
||||
esp_err_t err;
|
||||
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
|
||||
|
||||
if (partition->type == PART_TYPE_APP) {
|
||||
/* check if the partition holds a valid unencrypted app */
|
||||
esp_image_metadata_t data_ignored;
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&partition->pos,
|
||||
&data_ignored);
|
||||
should_encrypt = (err == ESP_OK);
|
||||
} else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
should_encrypt = true;
|
||||
}
|
||||
|
||||
if (!should_encrypt) {
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* should_encrypt */
|
||||
ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
|
||||
|
||||
err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
|
||||
ESP_LOGI(TAG, "Done encrypting");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
|
||||
|
||||
if (src_addr % FLASH_SECTOR_SIZE != 0) {
|
||||
ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x",src_addr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||
uint32_t sec_start = i + src_addr;
|
||||
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint8_t hash[32];
|
||||
|
||||
if (ets_efuse_secure_boot_enabled())
|
||||
{
|
||||
ESP_LOGI(TAG, "secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying bootloader signature...\n");
|
||||
int r = ets_secure_boot_verify_bootloader(hash, false);
|
||||
if (r != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify bootloader signature");
|
||||
return r;
|
||||
}
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
assert(ets_efuse_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys = { 0 };
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
if ((src_addr + length) % 4096 != 0) {
|
||||
ESP_LOGE(TAG, "addr 0x%x length 0x%x doesn't end on a sector boundary", src_addr, length);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(handle, data, length);
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
#else
|
||||
/* Use thread-safe esp-idf SHA function */
|
||||
esp_sha(SHA2_256, data, length, digest);
|
||||
#endif
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
|
||||
if (r == ETS_OK) {
|
||||
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys, verified_digest);
|
||||
}
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
}
|
||||
|
||||
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
@@ -13,26 +13,18 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <bootloader_utility.h>
|
||||
#include <esp_secure_boot.h>
|
||||
#include <esp_fault.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <esp32/rom/secure_boot.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/rtc.h>
|
||||
#include <esp32s2beta/rom/secure_boot.h>
|
||||
#endif
|
||||
|
||||
/* Checking signatures as part of verifying images is necessary:
|
||||
- Always if secure boot is enabled
|
||||
@@ -40,11 +32,11 @@
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_BOOT
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE 1
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE
|
||||
#endif
|
||||
#else /* !BOOTLOADER_BUILD */
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE 1
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -58,12 +50,18 @@ static const char *TAG = "esp_image";
|
||||
/* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */
|
||||
#define STACK_LOAD_HEADROOM 32768
|
||||
|
||||
/* Mmap source address mask */
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* 64 bits of random data to obfuscate loaded RAM with, until verification is complete
|
||||
(Means loaded code isn't executable until after the secure boot check.)
|
||||
*/
|
||||
static uint32_t ram_obfs_value[2];
|
||||
|
||||
/* Range of IRAM used by the loader, defined in ld script */
|
||||
extern int _loader_text_start;
|
||||
extern int _loader_text_end;
|
||||
#endif
|
||||
|
||||
/* Return true if load_addr is an address the bootloader should load into */
|
||||
@@ -94,29 +92,21 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
|
||||
static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data);
|
||||
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
|
||||
static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bool do_load = (mode == ESP_IMAGE_LOAD) || (mode == ESP_IMAGE_LOAD_NO_VALIDATE);
|
||||
bool do_verify = (mode == ESP_IMAGE_LOAD) || (mode == ESP_IMAGE_VERIFY) || (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
bool do_load = (mode == ESP_IMAGE_LOAD);
|
||||
#else
|
||||
bool do_load = false; // Can't load the image in app mode
|
||||
bool do_verify = true; // In app mode is avalible only verify mode
|
||||
bool do_load = false; // Can't load the image in app mode
|
||||
#endif
|
||||
bool silent = (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
bool silent = (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
esp_err_t err = ESP_OK;
|
||||
// checksum the image a word at a time. This shaves 30-40ms per MB of image size
|
||||
uint32_t checksum_word = ESP_ROM_CHECKSUM_INITIAL;
|
||||
uint32_t *checksum = NULL;
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
#if SECURE_BOOT_CHECK_SIGNATURE
|
||||
/* used for anti-FI checks */
|
||||
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
|
||||
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
|
||||
#endif
|
||||
|
||||
if (data == NULL || part == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -136,46 +126,41 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (do_verify) {
|
||||
checksum = &checksum_word;
|
||||
|
||||
// Calculate SHA-256 of image if secure boot is on, or if image has a hash appended
|
||||
// Calculate SHA-256 of image if secure boot is on, or if image has a hash appended
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
if (1) {
|
||||
if (1) {
|
||||
#else
|
||||
if (data->image.hash_appended) {
|
||||
if (data->image.hash_appended) {
|
||||
#endif
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, &data->image, sizeof(esp_image_header_t));
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, &data->image, sizeof(esp_image_header_t));
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "image header: 0x%02x 0x%02x 0x%02x 0x%02x %08x",
|
||||
data->image.magic,
|
||||
data->image.segment_count,
|
||||
data->image.spi_mode,
|
||||
data->image.spi_size,
|
||||
data->image.entry_addr);
|
||||
ESP_LOGD(TAG, "image header: 0x%02x 0x%02x 0x%02x 0x%02x %08x",
|
||||
data->image.magic,
|
||||
data->image.segment_count,
|
||||
data->image.spi_mode,
|
||||
data->image.spi_size,
|
||||
data->image.entry_addr);
|
||||
|
||||
err = verify_image_header(data->start_addr, &data->image, silent);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
err = verify_image_header(data->start_addr, &data->image, silent);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (data->image.segment_count > ESP_IMAGE_MAX_SEGMENTS) {
|
||||
FAIL_LOAD("image at 0x%x segment count %d exceeds max %d",
|
||||
data->start_addr, data->image.segment_count, ESP_IMAGE_MAX_SEGMENTS);
|
||||
}
|
||||
} // if (do_verify)
|
||||
if (data->image.segment_count > ESP_IMAGE_MAX_SEGMENTS) {
|
||||
FAIL_LOAD("image at 0x%x segment count %d exceeds max %d",
|
||||
data->start_addr, data->image.segment_count, ESP_IMAGE_MAX_SEGMENTS);
|
||||
}
|
||||
|
||||
uint32_t next_addr = data->start_addr + sizeof(esp_image_header_t);
|
||||
for (int i = 0; i < data->image.segment_count; i++) {
|
||||
for(int i = 0; i < data->image.segment_count; i++) {
|
||||
esp_image_segment_header_t *header = &data->segments[i];
|
||||
ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr);
|
||||
|
||||
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, checksum);
|
||||
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, &checksum_word);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
@@ -184,112 +169,69 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
next_addr += header->data_len;
|
||||
}
|
||||
|
||||
if (do_verify) {
|
||||
// Segments all loaded, verify length
|
||||
uint32_t end_addr = next_addr;
|
||||
if (end_addr < data->start_addr) {
|
||||
FAIL_LOAD("image offset has wrapped");
|
||||
// Segments all loaded, verify length
|
||||
uint32_t end_addr = next_addr;
|
||||
if (end_addr < data->start_addr) {
|
||||
FAIL_LOAD("image offset has wrapped");
|
||||
}
|
||||
|
||||
data->image_len = end_addr - data->start_addr;
|
||||
ESP_LOGV(TAG, "image start 0x%08x end of last section 0x%08x", data->start_addr, end_addr);
|
||||
if (!esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_checksum(sha_handle, checksum_word, data);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (data->image_len > part->size) {
|
||||
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
|
||||
}
|
||||
|
||||
data->image_len = end_addr - data->start_addr;
|
||||
ESP_LOGV(TAG, "image start 0x%08x end of last section 0x%08x", data->start_addr, end_addr);
|
||||
if (NULL != checksum && !esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_checksum(sha_handle, checksum_word, data);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders.
|
||||
For Secure Boot V2, we do verify signature on bootloader which includes the SHA calculation.
|
||||
|
||||
(For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
|
||||
esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
|
||||
*/
|
||||
bool verify_sha;
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
verify_sha = true;
|
||||
#else // ESP32, or ESP32S2 without secure boot enabled
|
||||
verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET);
|
||||
#endif
|
||||
|
||||
if (verify_sha) {
|
||||
if (data->image_len > part->size) {
|
||||
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
|
||||
}
|
||||
bool is_bootloader = (data->start_addr == ESP_BOOTLOADER_OFFSET);
|
||||
/* For secure boot, we don't verify signature on bootloaders.
|
||||
|
||||
For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because esptool.py may have
|
||||
rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.
|
||||
*/
|
||||
if (!is_bootloader) {
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
// secure boot images have a signature appended
|
||||
#if defined(BOOTLOADER_BUILD) && !defined(CONFIG_SECURE_BOOT)
|
||||
// If secure boot is not enabled in hardware, then
|
||||
// skip the signature check in bootloader when the debugger is attached.
|
||||
// This is done to allow for breakpoints in Flash.
|
||||
if (!esp_cpu_in_ocd_debug_mode()) {
|
||||
#else // CONFIG_SECURE_BOOT
|
||||
if (true) {
|
||||
#endif // end checking for JTAG
|
||||
err = verify_secure_boot_signature(sha_handle, data, image_digest, verified_digest);
|
||||
sha_handle = NULL; // verify_secure_boot_signature finishes sha_handle
|
||||
}
|
||||
#else // SECURE_BOOT_CHECK_SIGNATURE
|
||||
// No secure boot, but SHA-256 can be appended for basic corruption detection
|
||||
if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_simple_hash(sha_handle, data);
|
||||
sha_handle = NULL; // calling verify_simple_hash finishes sha_handle
|
||||
}
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // verify_sha
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (sha_handle != NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
sha_handle = NULL;
|
||||
} //verify_sha
|
||||
|
||||
// Separately, if there's a hash appended to the image then copy it out to the data->image_digest field
|
||||
if (data->image.hash_appended) {
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (hash == NULL) {
|
||||
err = ESP_FAIL;
|
||||
goto err;
|
||||
}
|
||||
memcpy(data->image_digest, hash, HASH_LEN);
|
||||
bootloader_munmap(hash);
|
||||
// secure boot images have a signature appended
|
||||
err = verify_secure_boot_signature(sha_handle, data);
|
||||
#else
|
||||
// No secure boot, but SHA-256 can be appended for basic corruption detection
|
||||
if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_simple_hash(sha_handle, data);
|
||||
}
|
||||
} // do_verify
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // is_bootloader
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (sha_handle != NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->image.hash_appended) {
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (hash == NULL) {
|
||||
err = ESP_FAIL;
|
||||
goto err;
|
||||
}
|
||||
memcpy(data->image_digest, hash, HASH_LEN);
|
||||
bootloader_munmap(hash);
|
||||
}
|
||||
|
||||
sha_handle = NULL;
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
/* If signature was checked in bootloader build, verified_digest should equal image_digest
|
||||
|
||||
This is to detect any fault injection that caused signature verification to not complete normally.
|
||||
|
||||
Any attack which bypasses this check should be of limited use as the RAM contents are still obfuscated, therefore we do the check
|
||||
immediately before we deobfuscate.
|
||||
|
||||
Note: the conditions for making this check are the same as for setting verify_sha above, but on ESP32 SB V1 we move the test for
|
||||
"only verify signature in bootloader" into the macro so it's tested multiple times.
|
||||
*/
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
|
||||
ESP_FAULT_ASSERT(data->start_addr == ESP_BOOTLOADER_OFFSET || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#endif
|
||||
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
|
||||
// Deobfuscate RAM
|
||||
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) {
|
||||
if (do_load) { // Need to deobfuscate RAM
|
||||
for (int i = 0; i < data->image.segment_count; i++) {
|
||||
uint32_t load_addr = data->segments[i].load_addr;
|
||||
if (should_load(load_addr)) {
|
||||
uint32_t *loaded = (uint32_t *)load_addr;
|
||||
for (int j = 0; j < data->segments[i].data_len / sizeof(uint32_t); j++) {
|
||||
for (int j = 0; j < data->segments[i].data_len/sizeof(uint32_t); j++) {
|
||||
loaded[j] ^= (j & 1) ? ram_obfs_value[0] : ram_obfs_value[1];
|
||||
}
|
||||
}
|
||||
@@ -300,9 +242,9 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
// Success!
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
err:
|
||||
if (err == ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (sha_handle != NULL) {
|
||||
// Need to finish the hash process to free the handle
|
||||
@@ -311,7 +253,7 @@ err:
|
||||
// Prevent invalid/incomplete data leaking out
|
||||
bzero(data, sizeof(esp_image_metadata_t));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
@@ -322,15 +264,6 @@ esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metad
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
return image_load(ESP_IMAGE_LOAD_NO_VALIDATE, part, data);
|
||||
#else
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
return image_load(mode, part, data);
|
||||
@@ -346,6 +279,9 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
|
||||
}
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (bootloader_common_check_chip_validity(image, ESP_IMAGE_APPLICATION) != ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (!silent) {
|
||||
if (image->spi_mode > ESP_IMAGE_SPI_MODE_SLOW_READ) {
|
||||
ESP_LOGW(TAG, "image at 0x%x has invalid SPI mode %d", src_addr, image->spi_mode);
|
||||
@@ -357,140 +293,9 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
|
||||
ESP_LOGW(TAG, "image at 0x%x has invalid SPI size %d", src_addr, image->spi_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ESP_OK) {
|
||||
// Checking the chip revision header *will* print a bunch of other info
|
||||
// regardless of silent setting as this may be important, but don't bother checking it
|
||||
// if it looks like the app partition is erased or otherwise garbage
|
||||
if (bootloader_common_check_chip_validity(image, ESP_IMAGE_APPLICATION) != ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* Check the region load_addr - load_end doesn't overlap any memory used by the bootloader, registers, or other invalid memory
|
||||
*/
|
||||
static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_t load_end, bool print_error, bool no_recurse)
|
||||
{
|
||||
/* Addresses of static data and the "loader" section of bootloader IRAM, all defined in ld script */
|
||||
const char *reason = NULL;
|
||||
extern int _dram_start, _dram_end, _loader_text_start, _loader_text_end;
|
||||
void *load_addr_p = (void *)load_addr;
|
||||
void *load_end_p = (void *)load_end;
|
||||
|
||||
if (load_end == load_addr) {
|
||||
return true; // zero-length segments are fine
|
||||
}
|
||||
assert(load_end > load_addr); // data_len<16MB is checked in verify_segment_header() which is called before this, so this should always be true
|
||||
|
||||
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_end_p)) { /* Writing to DRAM */
|
||||
/* Check if we're clobbering the stack */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
|
||||
load_addr, load_end)) {
|
||||
reason = "overlaps bootloader stack";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* Check if we're clobbering static data
|
||||
|
||||
(_dram_start.._dram_end includes bss, data, rodata sections in DRAM)
|
||||
*/
|
||||
if (bootloader_util_regions_overlap((intptr_t)&_dram_start, (intptr_t)&_dram_end, load_addr, load_end)) {
|
||||
reason = "overlaps bootloader data";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* LAST DRAM CHECK (recursive): for D/IRAM, check the equivalent IRAM addresses if needed
|
||||
|
||||
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
|
||||
section. In which case we recurse to check the part which falls in D/IRAM.
|
||||
|
||||
Note: We start with SOC_DIRAM_DRAM_LOW/HIGH and convert that address to IRAM to account for any reversing of word order
|
||||
(chip-specific).
|
||||
*/
|
||||
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_DRAM_LOW, SOC_DIRAM_DRAM_HIGH, load_addr, load_end)) {
|
||||
intptr_t iram_load_addr, iram_load_end;
|
||||
|
||||
if (esp_ptr_in_diram_dram(load_addr_p)) {
|
||||
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram(load_addr_p);
|
||||
} else {
|
||||
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_LOW);
|
||||
}
|
||||
|
||||
if (esp_ptr_in_diram_dram(load_end_p)) {
|
||||
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram(load_end_p);
|
||||
} else {
|
||||
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_HIGH);
|
||||
}
|
||||
|
||||
if (iram_load_end < iram_load_addr) {
|
||||
return verify_load_addresses(segment_index, iram_load_end, iram_load_addr, print_error, true);
|
||||
} else {
|
||||
return verify_load_addresses(segment_index, iram_load_addr, iram_load_end, print_error, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esp_ptr_in_iram(load_addr_p) && esp_ptr_in_iram(load_end_p)) { /* Writing to IRAM */
|
||||
/* Check for overlap of 'loader' section of IRAM */
|
||||
if (bootloader_util_regions_overlap((intptr_t)&_loader_text_start, (intptr_t)&_loader_text_end,
|
||||
load_addr, load_end)) {
|
||||
reason = "overlaps loader IRAM";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* LAST IRAM CHECK (recursive): for D/IRAM, check the equivalent DRAM address if needed
|
||||
|
||||
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
|
||||
section. In which case we recurse to check the part which falls in D/IRAM.
|
||||
Note: We start with SOC_DIRAM_IRAM_LOW/HIGH and convert that address to DRAM to account for any reversing of word order
|
||||
(chip-specific).
|
||||
*/
|
||||
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_IRAM_LOW, SOC_DIRAM_IRAM_HIGH, load_addr, load_end)) {
|
||||
intptr_t dram_load_addr, dram_load_end;
|
||||
|
||||
if (esp_ptr_in_diram_iram(load_addr_p)) {
|
||||
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram(load_addr_p);
|
||||
} else {
|
||||
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_LOW);
|
||||
}
|
||||
|
||||
if (esp_ptr_in_diram_iram(load_end_p)) {
|
||||
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram(load_end_p);
|
||||
} else {
|
||||
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_HIGH);
|
||||
}
|
||||
|
||||
if (dram_load_end < dram_load_addr) {
|
||||
return verify_load_addresses(segment_index, dram_load_end, dram_load_addr, print_error, true);
|
||||
} else {
|
||||
return verify_load_addresses(segment_index, dram_load_addr, dram_load_end, print_error, true);
|
||||
}
|
||||
}
|
||||
/* Sections entirely in RTC memory won't overlap with a vanilla bootloader but are valid load addresses, thus skipping them from the check */
|
||||
} else if (esp_ptr_in_rtc_iram_fast(load_addr_p) && esp_ptr_in_rtc_iram_fast(load_end_p)){
|
||||
return true;
|
||||
} else if (esp_ptr_in_rtc_dram_fast(load_addr_p) && esp_ptr_in_rtc_dram_fast(load_end_p)){
|
||||
return true;
|
||||
} else if (esp_ptr_in_rtc_slow(load_addr_p) && esp_ptr_in_rtc_slow(load_end_p)) {
|
||||
return true;
|
||||
} else { /* Not a DRAM or an IRAM or RTC Fast IRAM, RTC Fast DRAM or RTC Slow address */
|
||||
reason = "bad load address range";
|
||||
goto invalid;
|
||||
}
|
||||
return true;
|
||||
|
||||
invalid:
|
||||
if (print_error) {
|
||||
ESP_LOGE(TAG, "Segment %d 0x%08x-0x%08x invalid: %s", segment_index, load_addr, load_end, reason);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -527,15 +332,40 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
ESP_LOGI(TAG, "segment %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s",
|
||||
index, data_addr, load_addr,
|
||||
data_len, data_len,
|
||||
(do_load) ? "load" : (is_mapping) ? "map" : "");
|
||||
(do_load)?"load":(is_mapping)?"map":"");
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* Before loading segment, check it doesn't clobber bootloader RAM. */
|
||||
if (do_load && data_len > 0) {
|
||||
if (!verify_load_addresses(index, load_addr, load_addr + data_len, true, false)) {
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
if (do_load) {
|
||||
const intptr_t load_end = load_addr + data_len;
|
||||
if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
|
||||
/* Writing to DRAM */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (load_end > sp - STACK_LOAD_HEADROOM) {
|
||||
/* Bootloader .data/.rodata/.bss is above the stack, so this
|
||||
* also checks that we aren't overwriting these segments.
|
||||
*
|
||||
* TODO: This assumes specific arrangement of sections we have
|
||||
* in the ESP32. Rewrite this in a generic way to support other
|
||||
* layouts.
|
||||
*/
|
||||
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
|
||||
index, load_end, sp, sp - STACK_LOAD_HEADROOM);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
} else {
|
||||
/* Writing to IRAM */
|
||||
const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
|
||||
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
|
||||
|
||||
if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
|
||||
load_addr, load_end)) {
|
||||
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
|
||||
index, load_addr, load_end, loader_iram_start, loader_iram_end);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
@@ -545,10 +375,6 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
|
||||
int32_t data_len_remain = data_len;
|
||||
while (data_len_remain > 0) {
|
||||
#if SECURE_BOOT_CHECK_SIGNATURE && defined(BOOTLOADER_BUILD)
|
||||
/* Double check the address verification done above */
|
||||
ESP_FAULT_ASSERT(!do_load || verify_load_addresses(0, load_addr, load_addr + data_len_remain, false, false));
|
||||
#endif
|
||||
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
|
||||
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
|
||||
data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
|
||||
@@ -572,26 +398,13 @@ err:
|
||||
|
||||
static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
|
||||
{
|
||||
// If we are not loading, and the checksum is empty, skip processing this
|
||||
// segment for data
|
||||
if (!do_load && checksum == NULL) {
|
||||
ESP_LOGD(TAG, "skipping checksum for segment");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len);
|
||||
if (!data) {
|
||||
if(!data) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed",
|
||||
data_addr, data_len);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (checksum == NULL && sha_handle == NULL) {
|
||||
memcpy((void *)load_addr, data, data_len);
|
||||
bootloader_munmap(data);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Set up the obfuscation value to use for loading
|
||||
while (ram_obfs_value[0] == 0 || ram_obfs_value[1] == 0) {
|
||||
@@ -603,11 +416,9 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
const uint32_t *src = data;
|
||||
|
||||
for (int i = 0; i < data_len; i += 4) {
|
||||
int w_i = i / 4; // Word index
|
||||
int w_i = i/4; // Word index
|
||||
uint32_t w = src[w_i];
|
||||
if (checksum != NULL) {
|
||||
*checksum ^= w;
|
||||
}
|
||||
*checksum ^= w;
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
if (do_load) {
|
||||
dest[w_i] = w ^ ((w_i & 1) ? ram_obfs_value[0] : ram_obfs_value[1]);
|
||||
@@ -632,7 +443,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent)
|
||||
{
|
||||
if ((segment->data_len & 3) != 0
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "invalid segment length 0x%x", segment->data_len);
|
||||
}
|
||||
@@ -648,7 +459,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
ESP_LOGV(TAG, "segment %d map_segment %d segment_data_offs 0x%x load_addr 0x%x",
|
||||
index, map_segment, segment_data_offs, load_addr);
|
||||
if (map_segment
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "Segment %d load address 0x%08x, doesn't match data 0x%08x",
|
||||
index, load_addr, segment_data_offs);
|
||||
@@ -662,7 +473,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
static bool should_map(uint32_t load_addr)
|
||||
{
|
||||
return (load_addr >= SOC_IROM_LOW && load_addr < SOC_IROM_HIGH)
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
}
|
||||
|
||||
static bool should_load(uint32_t load_addr)
|
||||
@@ -685,15 +496,15 @@ static bool should_load(uint32_t load_addr)
|
||||
|
||||
if (!load_rtc_memory) {
|
||||
if (load_addr >= SOC_RTC_IRAM_LOW && load_addr < SOC_RTC_IRAM_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
if (load_addr >= SOC_RTC_DRAM_LOW && load_addr < SOC_RTC_DRAM_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
if (load_addr >= SOC_RTC_DATA_LOW && load_addr < SOC_RTC_DATA_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC slow memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC slow memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -721,8 +532,8 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
|
||||
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
|
||||
};
|
||||
return esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&bootloader_part,
|
||||
data);
|
||||
&bootloader_part,
|
||||
data);
|
||||
}
|
||||
|
||||
|
||||
@@ -733,13 +544,13 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
length = (length + 15) & ~15; // Pad to next full 16 byte block
|
||||
|
||||
// Verify checksum
|
||||
WORD_ALIGNED_ATTR uint8_t buf[16];
|
||||
uint8_t buf[16];
|
||||
esp_err_t err = bootloader_flash_read(data->start_addr + unpadded_length, buf, length - unpadded_length, true);
|
||||
uint8_t calc = buf[length - unpadded_length - 1];
|
||||
uint8_t checksum = (checksum_word >> 24)
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
if (err != ESP_OK || checksum != calc) {
|
||||
ESP_LOGE(TAG, "Checksum failed. Calculated 0x%x read 0x%x", checksum, calc);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
@@ -757,51 +568,30 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *caption);
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
uint8_t image_hash[HASH_LEN] = { 0 };
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
const void *simple_hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
bootloader_munmap(padding);
|
||||
end = padded_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
|
||||
debug_log_hash(image_hash, "Calculated secure boot hash");
|
||||
|
||||
// Use hash to verify signature block
|
||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||
const void *sig_block;
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t));
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
#endif
|
||||
|
||||
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sig_block, image_hash);
|
||||
bootloader_munmap(sig_block);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure boot signature verification failed");
|
||||
@@ -822,12 +612,6 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// Adjust image length result to include the appended signature
|
||||
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
|
||||
#endif
|
||||
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -837,13 +621,13 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated hash");
|
||||
debug_log_hash(image_hash, "Calculated hash");
|
||||
|
||||
// Simple hash for verification only
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (memcmp(hash, image_hash, HASH_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Image hash failed - image is corrupt");
|
||||
bootloader_debug_buffer(hash, HASH_LEN, "Expected hash");
|
||||
debug_log_hash(hash, "Expected hash");
|
||||
bootloader_munmap(hash);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
@@ -851,3 +635,14 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_munmap(hash);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Log a hash as a hex string
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
char hash_print[HASH_LEN * 2 + 1];
|
||||
hash_print[HASH_LEN * 2] = 0;
|
||||
bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
|
||||
ESP_LOGD(TAG, "%s: %s", label, hash_print);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -31,25 +31,16 @@ void esp_flash_encryption_init_checks()
|
||||
// FLASH_CRYPT_CNT *must* be write protected. This will have happened automatically
|
||||
// if bootloader is IDF V4.0 or newer but may not have happened for previous ESP-IDF bootloaders.
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
#ifdef CONFIG_SECURE_BOOT
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
|
||||
bool flash_crypt_cnt_wr_dis = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
|
||||
uint8_t flash_crypt_cnt_wr_dis = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
|
||||
if (!flash_crypt_cnt_wr_dis) {
|
||||
uint8_t flash_crypt_cnt = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt,
|
||||
ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count);
|
||||
if (flash_crypt_cnt == (1<<(ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count))-1) {
|
||||
// If encryption counter is already max, no need to write protect it
|
||||
// (this distinction is important on ESP32 ECO3 where write-protecting FLASH_CRYPT_CNT also write-protects UART_DL_DIS)
|
||||
flash_crypt_cnt_wr_dis = true;
|
||||
}
|
||||
if (!flash_crypt_cnt_wr_dis) {
|
||||
ESP_EARLY_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
|
||||
esp_flash_write_protect_crypt_cnt();
|
||||
}
|
||||
ESP_EARLY_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
|
||||
esp_flash_write_protect_crypt_cnt();
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT
|
||||
#endif // CONFIG_SECURE_BOOT_ENABLED
|
||||
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
|
||||
// Second check is to print a warning or error if the current running flash encryption mode
|
||||
@@ -57,44 +48,39 @@ void esp_flash_encryption_init_checks()
|
||||
mode = esp_get_flash_encryption_mode();
|
||||
if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
ESP_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
|
||||
ESP_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
|
||||
ESP_EARLY_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
|
||||
ESP_EARLY_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
|
||||
#else
|
||||
ESP_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
|
||||
ESP_EARLY_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
|
||||
#endif
|
||||
} else if (mode == ESP_FLASH_ENC_MODE_RELEASE) {
|
||||
ESP_LOGI(TAG, "Flash encryption mode is RELEASE");
|
||||
ESP_EARLY_LOGI(TAG, "Flash encryption mode is RELEASE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void esp_flash_write_protect_crypt_cnt(void)
|
||||
void esp_flash_write_protect_crypt_cnt()
|
||||
{
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
|
||||
uint8_t flash_crypt_cnt_wr_dis = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
|
||||
if (!flash_crypt_cnt_wr_dis) {
|
||||
esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode()
|
||||
{
|
||||
bool efuse_flash_crypt_cnt_wr_protected;
|
||||
uint8_t efuse_flash_crypt_cnt_wr_protected = 0;
|
||||
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
|
||||
esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
|
||||
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
/* Check if FLASH CRYPT CNT is write protected */
|
||||
efuse_flash_crypt_cnt_wr_protected = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
|
||||
if (!efuse_flash_crypt_cnt_wr_protected) {
|
||||
uint8_t flash_crypt_cnt = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt, ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count);
|
||||
if (flash_crypt_cnt == (1 << (ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count)) - 1) {
|
||||
efuse_flash_crypt_cnt_wr_protected = true; // CRYPT_CNT at max is same as write protected
|
||||
}
|
||||
}
|
||||
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &efuse_flash_crypt_cnt_wr_protected, 1);
|
||||
if (efuse_flash_crypt_cnt_wr_protected) {
|
||||
dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
|
||||
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
|
||||
dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
|
||||
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_CACHE, &dis_dl_cache, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_ENCRYPT, &dis_dl_enc, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_DECRYPT, &dis_dl_dec, 1);
|
||||
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
|
||||
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
|
||||
mode = ESP_FLASH_ENC_MODE_RELEASE;
|
||||
|
||||
@@ -16,26 +16,14 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* SPI flash controller */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SPIFLASH SPI1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
Suitable for use with the execute_flash_command static function.
|
||||
@@ -51,11 +39,10 @@
|
||||
|
||||
static const char *TAG = "qio_mode";
|
||||
|
||||
typedef unsigned (*read_status_fn_t)(void);
|
||||
typedef unsigned (*read_status_fn_t)();
|
||||
typedef void (*write_status_fn_t)(unsigned);
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
typedef struct __attribute__((packed)) {
|
||||
const char *manufacturer;
|
||||
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
|
||||
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
|
||||
@@ -66,11 +53,11 @@ typedef struct __attribute__((packed))
|
||||
} qio_info_t;
|
||||
|
||||
/* Read 8 bit status using RDSR command */
|
||||
static unsigned read_status_8b_rdsr(void);
|
||||
static unsigned read_status_8b_rdsr();
|
||||
/* Read 8 bit status (second byte) using RDSR2 command */
|
||||
static unsigned read_status_8b_rdsr2(void);
|
||||
static unsigned read_status_8b_rdsr2();
|
||||
/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void);
|
||||
static unsigned read_status_16b_rdsr_rdsr2();
|
||||
|
||||
/* Write 8 bit status using WRSR */
|
||||
static void write_status_8b_wrsr(unsigned new_status);
|
||||
@@ -80,7 +67,7 @@ static void write_status_8b_wrsr2(unsigned new_status);
|
||||
static void write_status_16b_wrsr(unsigned new_status);
|
||||
|
||||
/* Read 8 bit status of XM25QU64A */
|
||||
static unsigned read_status_8b_xmc25qu64a(void);
|
||||
static unsigned read_status_8b_xmc25qu64a();
|
||||
/* Write 8 bit status of XM25QU64A */
|
||||
static void write_status_8b_xmc25qu64a(unsigned new_status);
|
||||
|
||||
@@ -103,7 +90,7 @@ static void write_status_8b_xmc25qu64a(unsigned new_status);
|
||||
Searching of this table stops when the first match is found.
|
||||
*/
|
||||
const static qio_info_t chip_data[] = {
|
||||
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
|
||||
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
|
||||
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
|
||||
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
|
||||
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
|
||||
@@ -122,8 +109,8 @@ const static qio_info_t chip_data[] = {
|
||||
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
|
||||
/* Generic function to use the "user command" SPI controller functionality
|
||||
to send commands to the SPI flash and read the respopnse.
|
||||
@@ -134,53 +121,13 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
uint32_t bootloader_read_flash_id(void)
|
||||
uint32_t bootloader_read_flash_id()
|
||||
{
|
||||
uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24);
|
||||
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
|
||||
return id;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define FLASH_WRAP_CMD 0x77
|
||||
typedef enum {
|
||||
FLASH_WRAP_MODE_8B = 0,
|
||||
FLASH_WRAP_MODE_16B = 2,
|
||||
FLASH_WRAP_MODE_32B = 4,
|
||||
FLASH_WRAP_MODE_64B = 6,
|
||||
FLASH_WRAP_MODE_DISABLE = 1
|
||||
} spi_flash_wrap_mode_t;
|
||||
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bootloader_enable_qio_mode(void)
|
||||
{
|
||||
uint32_t raw_flash_id;
|
||||
@@ -198,7 +145,7 @@ void bootloader_enable_qio_mode(void)
|
||||
flash_id = raw_flash_id & 0xFFFF;
|
||||
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
|
||||
|
||||
for (i = 0; i < NUM_CHIPS - 1; i++) {
|
||||
for (i = 0; i < NUM_CHIPS-1; i++) {
|
||||
const qio_info_t *chip = &chip_data[i];
|
||||
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
|
||||
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
|
||||
@@ -209,22 +156,19 @@ void bootloader_enable_qio_mode(void)
|
||||
if (i == NUM_CHIPS - 1) {
|
||||
ESP_LOGI(TAG, "Enabling default flash chip QIO");
|
||||
}
|
||||
|
||||
enable_qio_mode(chip_data[i].read_status_fn,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
{
|
||||
uint32_t status;
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
|
||||
// which is compiled into the bootloader instead.
|
||||
@@ -234,28 +178,27 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
//assignment from that chip's WP pin.
|
||||
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
if (CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO &&
|
||||
(pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
|
||||
(pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
|
||||
ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
|
||||
status = read_status_fn();
|
||||
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
|
||||
|
||||
if ((status & (1 << status_qio_bit)) == 0) {
|
||||
if ((status & (1<<status_qio_bit)) == 0) {
|
||||
execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
write_status_fn(status | (1 << status_qio_bit));
|
||||
write_status_fn(status | (1<<status_qio_bit));
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
|
||||
status = read_status_fn();
|
||||
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
|
||||
if ((status & (1 << status_qio_bit)) == 0) {
|
||||
if ((status & (1<<status_qio_bit)) == 0) {
|
||||
ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -275,29 +218,22 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
esp_rom_spiflash_config_readmode(mode);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (ets_efuse_get_wp_pad() <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_spiflash_select_qio_pins(ets_efuse_get_wp_pad(), spiconfig);
|
||||
} else {
|
||||
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_rdsr(void)
|
||||
static unsigned read_status_8b_rdsr()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_rdsr2(void)
|
||||
static unsigned read_status_8b_rdsr2()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void)
|
||||
static unsigned read_status_16b_rdsr_rdsr2()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
}
|
||||
@@ -317,7 +253,7 @@ static void write_status_16b_wrsr(unsigned new_status)
|
||||
execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_xmc25qu64a(void)
|
||||
static unsigned read_status_8b_xmc25qu64a()
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
@@ -338,11 +274,7 @@ static void write_status_8b_xmc25qu64a(unsigned new_status)
|
||||
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 0;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
@@ -350,17 +282,9 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
|
||||
if (g_rom_spiflash_dummy_len_plus[1]) {
|
||||
@@ -375,8 +299,8 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
}
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user