Compare commits
1138 Commits
edk2-stabl
...
edk2-stabl
Author | SHA1 | Date | |
---|---|---|---|
|
06dc822d04 | ||
|
e8453aa373 | ||
|
0b143fa43e | ||
|
a7632e913c | ||
|
503248ccdf | ||
|
7513559926 | ||
|
46db105b7b | ||
|
0c5c45a133 | ||
|
5ffcbc4690 | ||
|
cbccf99592 | ||
|
020bb4b46d | ||
|
63d92674d2 | ||
|
547067dd86 | ||
|
c1a42bb0e2 | ||
|
6847329af2 | ||
|
53ea57fea4 | ||
|
6c02386403 | ||
|
17f65e4063 | ||
|
a13947b2fa | ||
|
78ab44cb96 | ||
|
aad9cba85f | ||
|
48a83481d2 | ||
|
ad40eb4e6c | ||
|
019f513a19 | ||
|
5ba203b54e | ||
|
4535fc312b | ||
|
d4e0b9607c | ||
|
5a6d764e1d | ||
|
82c65f14d4 | ||
|
a048af3c90 | ||
|
53b40c9c6d | ||
|
60835c96cd | ||
|
1371e15fff | ||
|
d181539b83 | ||
|
f034c05cc4 | ||
|
9b851fd6b2 | ||
|
7e6f150b69 | ||
|
7b453107f8 | ||
|
739adc8ba4 | ||
|
9b1ba18677 | ||
|
f2a8fae3f6 | ||
|
1bd632db77 | ||
|
354ef14cf5 | ||
|
0716b2390f | ||
|
f04e7547cd | ||
|
d05ff36c20 | ||
|
56aa9d19d8 | ||
|
647aa7110f | ||
|
5a677bbc45 | ||
|
1fde2b9d5b | ||
|
32ed3624fa | ||
|
fbc9cb4c8b | ||
|
57e7b66ab9 | ||
|
7f0b28415c | ||
|
20da7ca42a | ||
|
3b49d0a598 | ||
|
30937f2f98 | ||
|
7b7508ad78 | ||
|
e88a5b9833 | ||
|
0d7601e546 | ||
|
437eb3f7a8 | ||
|
e2db781f0c | ||
|
13e5492bfd | ||
|
8a2732186a | ||
|
0731236fc1 | ||
|
43c3df7846 | ||
|
88a363009a | ||
|
13ed9e5fc0 | ||
|
449a6e4934 | ||
|
0bbed0664f | ||
|
6995a1b79b | ||
|
cf845a749a | ||
|
0afa1d08f1 | ||
|
fefcf90c33 | ||
|
9f7e0d0ade | ||
|
3ef8bfc2b3 | ||
|
f4571f24d1 | ||
|
e4bb269a85 | ||
|
3caf1e2e22 | ||
|
5894fb1fa2 | ||
|
68d18bef41 | ||
|
4de7047976 | ||
|
c45f678a1e | ||
|
9711c9230b | ||
|
6587e08d3a | ||
|
0020157a98 | ||
|
fb040cced3 | ||
|
61bacc0fa1 | ||
|
5277540e37 | ||
|
3a4a6ead32 | ||
|
19c50eb61c | ||
|
8714978781 | ||
|
f8422f1e0b | ||
|
9b3ca509ab | ||
|
b098f5e9e9 | ||
|
1c0eb91503 | ||
|
a80e887819 | ||
|
c9db7bf10a | ||
|
39936d3393 | ||
|
7f7f511c5a | ||
|
24758e993a | ||
|
a5110b8955 | ||
|
43bec9ea3d | ||
|
5d8648345c | ||
|
5dc2699d10 | ||
|
313d2ec991 | ||
|
c76028a6ff | ||
|
5b035defa8 | ||
|
bade7f423b | ||
|
f2bd39fb60 | ||
|
095db69d4c | ||
|
c85ac5245c | ||
|
3196253710 | ||
|
01ea2ad59c | ||
|
3a68156778 | ||
|
e8db4f9c53 | ||
|
bb4e939253 | ||
|
feea651448 | ||
|
422e93e1de | ||
|
9f2d50f145 | ||
|
d9800046ea | ||
|
340f8f4565 | ||
|
26f5961f3e | ||
|
7f293b25d6 | ||
|
ca04956e1b | ||
|
667aa7ccbf | ||
|
0414377c02 | ||
|
e2c1104c50 | ||
|
f96dd8185d | ||
|
5764abda7c | ||
|
9275bb82ca | ||
|
bcab901b7c | ||
|
98f2808115 | ||
|
292e540854 | ||
|
056b0f1b20 | ||
|
3633d5309f | ||
|
e0eacd7daa | ||
|
94b7df5c4a | ||
|
f0f7140150 | ||
|
65904cdbb3 | ||
|
e17f459af2 | ||
|
be01087e07 | ||
|
e6042aec1b | ||
|
a3741780fe | ||
|
4698f544d2 | ||
|
14132666fa | ||
|
b88d95bb5b | ||
|
2d0c42fdf2 | ||
|
e3f8605a23 | ||
|
9565ab67c2 | ||
|
1a9369ef10 | ||
|
b4b9496b3c | ||
|
c9fa9762e8 | ||
|
de6859ec0c | ||
|
e4e27351e8 | ||
|
8665226464 | ||
|
c2db6a86a2 | ||
|
ef0460b852 | ||
|
bfe36cb4ef | ||
|
dcf51c05e8 | ||
|
aa1b377e71 | ||
|
2eea9c6fdf | ||
|
ee52b81c94 | ||
|
8834e10b30 | ||
|
e188ecc8b4 | ||
|
aa211bb6ef | ||
|
6bbd4de3bf | ||
|
34ceda3e93 | ||
|
92b9639503 | ||
|
6a0b48873b | ||
|
c3d92cff58 | ||
|
548c9669df | ||
|
bbb8a81858 | ||
|
e557442e3f | ||
|
9001b750df | ||
|
656419f922 | ||
|
137c2c6eff | ||
|
7f79b736b0 | ||
|
22f89fea1e | ||
|
9b484b33ba | ||
|
9a10c305a1 | ||
|
def0c5e181 | ||
|
aaaa7fd4d1 | ||
|
ce5855a8fa | ||
|
c6486c3fa9 | ||
|
1b647d65be | ||
|
b7ce4f93d5 | ||
|
7ed9c63d9e | ||
|
fdb056373c | ||
|
53936785b7 | ||
|
bdb54bfd83 | ||
|
eca948f6f3 | ||
|
e848b58d7c | ||
|
744ad444e5 | ||
|
3887820e5f | ||
|
1b0d659e6d | ||
|
ffde22468e | ||
|
92c19c68cb | ||
|
d7c9de51d2 | ||
|
012809cdca | ||
|
4b68cef04c | ||
|
479613bd06 | ||
|
60b12e69fb | ||
|
9bedaec05b | ||
|
1facb8fdef | ||
|
a44f558a84 | ||
|
6074f57e5b | ||
|
c25f146d8d | ||
|
8c30327deb | ||
|
91e4bcb313 | ||
|
50528537b2 | ||
|
ff2655d1a4 | ||
|
e43d0884ed | ||
|
7ff0459739 | ||
|
d0da48f112 | ||
|
b87f31f034 | ||
|
98625337e4 | ||
|
1f6fe5cb03 | ||
|
3e07c65641 | ||
|
91e2b4b6ec | ||
|
b630feee02 | ||
|
3d2f7953b2 | ||
|
9132a31b9c | ||
|
02539e9008 | ||
|
b3ee616e67 | ||
|
210b29fa99 | ||
|
a8ae714d4a | ||
|
17bd834eb5 | ||
|
dbd546a32d | ||
|
cb38ace647 | ||
|
3d9d66ad76 | ||
|
3d83274967 | ||
|
31830b0702 | ||
|
97e60818b6 | ||
|
f1d6c1eba1 | ||
|
8d6193902f | ||
|
12d99b8f23 | ||
|
23d982e205 | ||
|
79f802a50e | ||
|
386ca8abf7 | ||
|
5e6b870a53 | ||
|
e94d04a01b | ||
|
6ff53d2a13 | ||
|
d35773d5c0 | ||
|
21a23e6966 | ||
|
1da651cdb7 | ||
|
d9269d6913 | ||
|
e77966b341 | ||
|
c2e38a520e | ||
|
3bd5c994c8 | ||
|
82d0007750 | ||
|
5d29e2d020 | ||
|
9a6c4ac68e | ||
|
133891b712 | ||
|
75e92c1354 | ||
|
26824851b0 | ||
|
425df6923e | ||
|
77e42ca4df | ||
|
813c2b1525 | ||
|
f08715947a | ||
|
35f9d7c41b | ||
|
a0a49eb87c | ||
|
540fd45f75 | ||
|
d3c9e40abc | ||
|
0a81a98e90 | ||
|
9af8a299ce | ||
|
5b86bbf891 | ||
|
c7195b9ec3 | ||
|
e906346dcb | ||
|
a35de0aff3 | ||
|
256c4470f8 | ||
|
9c6f3545ae | ||
|
3c92912885 | ||
|
abc16e2531 | ||
|
d9a4084544 | ||
|
f45e3a4afa | ||
|
bceaf6952a | ||
|
48aa2edf5d | ||
|
f7f1b33282 | ||
|
bdafda8c45 | ||
|
df667535ed | ||
|
7da5f343bc | ||
|
3ed1c78466 | ||
|
627d1d6693 | ||
|
f43a14e3cf | ||
|
f56d52c7f5 | ||
|
c267eb889f | ||
|
0622a7b1b2 | ||
|
0a4aa20e8d | ||
|
88228db38e | ||
|
6511277827 | ||
|
01356d2963 | ||
|
c8edb70945 | ||
|
00217f1919 | ||
|
db77d8f7ee | ||
|
d45cf5ffdf | ||
|
422fe85cc3 | ||
|
e46e3040fc | ||
|
e18ac66d84 | ||
|
cae974bea2 | ||
|
0f01cec52f | ||
|
acfd555795 | ||
|
0060e0a694 | ||
|
654dc3ed85 | ||
|
a4a2258a1f | ||
|
20286e168b | ||
|
3900a63e3a | ||
|
03013d999c | ||
|
1a99203052 | ||
|
89f569ae8e | ||
|
00b8bf7eda | ||
|
322969adf1 | ||
|
239b50a863 | ||
|
3a9f932d80 | ||
|
7fe5022f28 | ||
|
763e0f0a72 | ||
|
6e9f7e5e3d | ||
|
45bc28172f | ||
|
8f22a331b9 | ||
|
2d233af64b | ||
|
58ae92a993 | ||
|
82808b4226 | ||
|
493f2c6931 | ||
|
cdc686223a | ||
|
102da0255b | ||
|
bd7c73ba77 | ||
|
a2433243fb | ||
|
8927e27777 | ||
|
b90beadfae | ||
|
4260c47867 | ||
|
9af1064995 | ||
|
b16fd231f6 | ||
|
fd708fe0e1 | ||
|
567bc4b4ae | ||
|
a4cfb842fc | ||
|
394e8e4bf5 | ||
|
3ee4f6cb36 | ||
|
e1d24410da | ||
|
14c7ed8b51 | ||
|
365fdb0f93 | ||
|
8c91934019 | ||
|
b7b3a5f99b | ||
|
5ebec96f28 | ||
|
4e3600b038 | ||
|
3b18b80aff | ||
|
9b52b06f96 | ||
|
dafce295e6 | ||
|
82e0b2f043 | ||
|
8cb890364b | ||
|
6aa48ab791 | ||
|
915f0831d8 | ||
|
cde194be8d | ||
|
6ff7c838d0 | ||
|
cfd73e0065 | ||
|
28dd887d68 | ||
|
037d86dd7a | ||
|
344f615df9 | ||
|
4ef72fe022 | ||
|
40e2e3ca33 | ||
|
321b078889 | ||
|
0ae52d4fd1 | ||
|
8035edbe12 | ||
|
bb78cfbec0 | ||
|
68d720fd92 | ||
|
7191dd3c59 | ||
|
b1d3895fb9 | ||
|
ca407c7246 | ||
|
4403bbd7c0 | ||
|
568eee7cf3 | ||
|
1c877c7160 | ||
|
09fe015af9 | ||
|
1a2ad3ba9e | ||
|
8f39da712f | ||
|
b1357a40fc | ||
|
74f90d38c4 | ||
|
fc72a6ceaa | ||
|
08c77cce0e | ||
|
3f89db8690 | ||
|
bc5012b8fb | ||
|
5a4b24b89a | ||
|
67c25bcc3a | ||
|
ea38791043 | ||
|
ff95c0fcba | ||
|
5af8fccd26 | ||
|
d3733188a2 | ||
|
7b6327ff03 | ||
|
8db87f9835 | ||
|
356b96b3a2 | ||
|
2c06e76bba | ||
|
9099dcbd61 | ||
|
15ac284815 | ||
|
4ac2457673 | ||
|
93ddc0d133 | ||
|
f8683a4ba0 | ||
|
84ce1f1bdc | ||
|
b99917ce3e | ||
|
c812d3209c | ||
|
b6174e2d09 | ||
|
89db28b9c9 | ||
|
80e28dcec8 | ||
|
394d589652 | ||
|
b8af2c9eda | ||
|
f4c15d3807 | ||
|
c22a32e1ab | ||
|
9b2a082e5b | ||
|
0a6fc3d067 | ||
|
aaa90aacaf | ||
|
0f30087b9a | ||
|
ba86bb2c4d | ||
|
6c4966423b | ||
|
ff306cfd6c | ||
|
a93bf06b1d | ||
|
154e243a99 | ||
|
2552fd58f5 | ||
|
f8edb7e998 | ||
|
5c7526f501 | ||
|
8adad18a94 | ||
|
ebe377f9eb | ||
|
7e9cef643d | ||
|
bcf181a33b | ||
|
8b680e4af1 | ||
|
f2cdb268ef | ||
|
ceacd9e992 | ||
|
242ab73d7f | ||
|
88899a372c | ||
|
be4e0cfbad | ||
|
fa37a846d0 | ||
|
789ea79e94 | ||
|
3e3acb3a27 | ||
|
9ad2b981bd | ||
|
c857042471 | ||
|
9378310dd8 | ||
|
b304d2807b | ||
|
ec94e97a6e | ||
|
c8543b8d83 | ||
|
f4f9c4cb63 | ||
|
f355b98606 | ||
|
3a3713e62c | ||
|
8293e6766a | ||
|
86c4f437d8 | ||
|
00acc6cbf9 | ||
|
fd8c6bed8a | ||
|
4e74764245 | ||
|
8c43227c64 | ||
|
3fd8800954 | ||
|
54a3d5ec48 | ||
|
089e9c19a8 | ||
|
38e72aa877 | ||
|
7601b251fd | ||
|
d3abb40d77 | ||
|
1510d6a391 | ||
|
e6956d0052 | ||
|
722da9078e | ||
|
ea56fa3d47 | ||
|
faef5a367c | ||
|
f793bfcae9 | ||
|
8af507c1f1 | ||
|
befd18fca6 | ||
|
469eb46169 | ||
|
55d6e39f72 | ||
|
8dd962a657 | ||
|
c635a56384 | ||
|
505812ae1d | ||
|
81cada9892 | ||
|
ecdbdba636 | ||
|
da8c0b8f4d | ||
|
f9941d31dd | ||
|
093cceaf79 | ||
|
a53e5b4174 | ||
|
f47074425d | ||
|
be7fcaa1c9 | ||
|
ad8f2d6b07 | ||
|
feec20b28d | ||
|
f159102a13 | ||
|
245bdd2cb9 | ||
|
de15e7c265 | ||
|
2a8fc911b9 | ||
|
704ff0ff2a | ||
|
f2bd980059 | ||
|
43bad5b5ba | ||
|
9ad9dc9d4f | ||
|
e54310451f | ||
|
91dee771fc | ||
|
70d5086c32 | ||
|
2a7a1223d0 | ||
|
13406bdeb5 | ||
|
f07fb43b2d | ||
|
052aa07da4 | ||
|
b2034179e8 | ||
|
f60d5ca97f | ||
|
178938b2b9 | ||
|
ad1db975c0 | ||
|
cdc3fa5418 | ||
|
270fece684 | ||
|
b8b890ca0a | ||
|
2377733248 | ||
|
b3c1bc1cfa | ||
|
98800cce65 | ||
|
611c7f1101 | ||
|
64ab457d1f | ||
|
3a402f9611 | ||
|
a91443885d | ||
|
52f012129a | ||
|
61ac4fc70d | ||
|
d5d60a4331 | ||
|
099dfbb29d | ||
|
0358c0bfc1 | ||
|
6cdf647b5f | ||
|
951a03536c | ||
|
0c7f189e60 | ||
|
4fcfd089aa | ||
|
0f1946b662 | ||
|
c5c5c980db | ||
|
63d425002a | ||
|
d5339c04d7 | ||
|
3a3a3af4a2 | ||
|
93f6df5f3b | ||
|
d70cdcf0b5 | ||
|
b6d542e927 | ||
|
92958abf7a | ||
|
002f38a44a | ||
|
b36fbd3645 | ||
|
c6a60cf4b9 | ||
|
1e823422fb | ||
|
bfd42b2075 | ||
|
1854eee1b4 | ||
|
c14f034a1a | ||
|
1755932f89 | ||
|
b447a20bdf | ||
|
40b9ca6beb | ||
|
6e3c834ae4 | ||
|
cda6f9455c | ||
|
3571e1360e | ||
|
9c463f6f59 | ||
|
d189a3f9b6 | ||
|
dc528558c9 | ||
|
309809455a | ||
|
e33d3e7f56 | ||
|
3b5a58c5f0 | ||
|
0f127f3187 | ||
|
05db94018b | ||
|
1a258c7703 | ||
|
7a7bedce25 | ||
|
be7295b364 | ||
|
ddfb0ab1bb | ||
|
1c76101134 | ||
|
df4f154da9 | ||
|
ca08f3d453 | ||
|
c884b23ac4 | ||
|
a7947b6366 | ||
|
06033f5aba | ||
|
58802e02c4 | ||
|
8c654bb3ec | ||
|
bd6aa93296 | ||
|
776ec4ea3c | ||
|
60f6a2774e | ||
|
6fedaa1c04 | ||
|
1cae0d4215 | ||
|
d84f090fd7 | ||
|
3fdc47c65b | ||
|
21276ce093 | ||
|
998d4c98b7 | ||
|
48b6c60cc6 | ||
|
a5d8a39963 | ||
|
e4004e8e50 | ||
|
9432cabfb9 | ||
|
d4bc5378e0 | ||
|
7cfc48fe4f | ||
|
d6f99b2ac4 | ||
|
3ab0dadd66 | ||
|
8acb61dfb3 | ||
|
9bb1f080c4 | ||
|
91a33d4113 | ||
|
edf88807f7 | ||
|
e1fbff3ded | ||
|
aab6a9c9ae | ||
|
c5824c27be | ||
|
d2c46681fa | ||
|
af4ee6953c | ||
|
48f0e94921 | ||
|
ee026ea78b | ||
|
ef5dcba975 | ||
|
0bb7f64702 | ||
|
9b2b0942f1 | ||
|
0467236267 | ||
|
e428889115 | ||
|
4efcc11c94 | ||
|
e576dfadd6 | ||
|
9025a014f9 | ||
|
0a44fd3165 | ||
|
8436d4de71 | ||
|
9817d442cd | ||
|
683df865a7 | ||
|
f73c9adfc6 | ||
|
991c5d89ba | ||
|
db0f8c2f84 | ||
|
49188b2aa4 | ||
|
f45e254f2e | ||
|
4deef2d865 | ||
|
e210fc130e | ||
|
98936dc4f4 | ||
|
335644f90f | ||
|
3f55418d53 | ||
|
4fb393aaa8 | ||
|
65c73df44c | ||
|
dd7523b5b1 | ||
|
9e7a063b07 | ||
|
4d9ca66204 | ||
|
8c944c9383 | ||
|
f34c7645bd | ||
|
7d8a04e9d2 | ||
|
c4c15b8702 | ||
|
6510e19794 | ||
|
b654edec03 | ||
|
5269c26e07 | ||
|
447e5d3902 | ||
|
6672b3cff2 | ||
|
45098e8a9a | ||
|
c08eaaaf37 | ||
|
9c2d8281af | ||
|
7efce2e59c | ||
|
e497432c2c | ||
|
a9f9d5cf56 | ||
|
419b30d642 | ||
|
ed08c57113 | ||
|
478c07d483 | ||
|
6c1fb56802 | ||
|
9c20342eed | ||
|
3000c2963d | ||
|
d4e2909bfc | ||
|
d671d1fa48 | ||
|
5650f307b3 | ||
|
4d23a7ec84 | ||
|
4817953949 | ||
|
8b2ac43bd8 | ||
|
effddeea39 | ||
|
7c10e8abb6 | ||
|
d39271f114 | ||
|
90e52483bf | ||
|
aa9aff2d4e | ||
|
878478116a | ||
|
96bb6704e0 | ||
|
869f234140 | ||
|
3e025c7742 | ||
|
f291a581ac | ||
|
43a0e08d02 | ||
|
6e9bd495b3 | ||
|
d21c2cd082 | ||
|
5042ee43d9 | ||
|
4ac82ea1e1 | ||
|
381f8ef6a1 | ||
|
5bc09cf05a | ||
|
090e267b5b | ||
|
695d90b9b1 | ||
|
a1c35ff312 | ||
|
32bcdfa512 | ||
|
5f7c91f0d7 | ||
|
f7079d1bc1 | ||
|
5fc899535e | ||
|
d390920ed4 | ||
|
f52b30e73d | ||
|
92a1ac4080 | ||
|
e24529a5c3 | ||
|
045e4b84c1 | ||
|
2f524a745e | ||
|
0dee1d1358 | ||
|
0c8ea9fe1a | ||
|
1b6b4a83e1 | ||
|
01ce872739 | ||
|
a2c3bf1f2f | ||
|
799d88c1ba | ||
|
912718d8c7 | ||
|
d42fdd6f83 | ||
|
89465fe9e0 | ||
|
b0ed7ebdeb | ||
|
cd99d07d53 | ||
|
d6961bb47a | ||
|
7d325f93e1 | ||
|
64a228f5f8 | ||
|
5a8bc527b3 | ||
|
484b1534ed | ||
|
5e75c4d1fe | ||
|
6b7855209a | ||
|
c72ca46668 | ||
|
4249278aa6 | ||
|
d93fe5b579 | ||
|
748fea6279 | ||
|
191fa79bce | ||
|
a3e25cc8a1 | ||
|
40d572f70d | ||
|
8068188431 | ||
|
1f3b1eb308 | ||
|
a17add32c2 | ||
|
a2ab46adbc | ||
|
806d1be6a7 | ||
|
b58ec859c7 | ||
|
f9ec8e51d2 | ||
|
3391e20ffa | ||
|
02d7797d1a | ||
|
825c3e2c1b | ||
|
eaaaece4ad | ||
|
faca87fa03 | ||
|
492679a55d | ||
|
d6607d8b30 | ||
|
ced77332ca | ||
|
f98608ab3f | ||
|
859b55443a | ||
|
de7c6081cb | ||
|
7c47d89003 | ||
|
1dc875a7d5 | ||
|
0758a8e979 | ||
|
efc52d67e1 | ||
|
364e0b4cda | ||
|
e569fbd205 | ||
|
ddd2be6b00 | ||
|
28de1a5550 | ||
|
57f9b7f89e | ||
|
6ae2d31ca2 | ||
|
7288ff4095 | ||
|
9b08c655ff | ||
|
3b9cd71454 | ||
|
9bfaa3da1e | ||
|
63fd7f3898 | ||
|
7d48d20a3d | ||
|
6d38761085 | ||
|
9767a597d7 | ||
|
643623147a | ||
|
6c9a3d4233 | ||
|
ed1c70cf1a | ||
|
6c6fef0247 | ||
|
3be909099c | ||
|
e63d54db95 | ||
|
a5c2ce7cd1 | ||
|
11ceb258f3 | ||
|
1158fc8e2c | ||
|
8f3ed1bc4d | ||
|
55942db1d3 | ||
|
bc498ac4ca | ||
|
51a6fb4118 | ||
|
63c89da242 | ||
|
17cb8ddba3 | ||
|
763840c9ab | ||
|
f668e78871 | ||
|
590f5f09b7 | ||
|
17efae27ac | ||
|
49df3fcee1 | ||
|
43df61878d | ||
|
c69f6406b9 | ||
|
90e11edd16 | ||
|
a1ddad9593 | ||
|
61d3b2d427 | ||
|
fc0a025ec3 | ||
|
6be54f15a0 | ||
|
8923699291 | ||
|
07952a962a | ||
|
ecb30848fd | ||
|
d55cfdc51f | ||
|
d8dd54f071 | ||
|
ec41733cfd | ||
|
1e404c405a | ||
|
2632178bc6 | ||
|
15bee1937f | ||
|
0980779a9d | ||
|
e521b3c54e | ||
|
82f6f44fc4 | ||
|
d9cd82e8bc | ||
|
c241c96f85 | ||
|
ddd34a8183 | ||
|
f5cb376703 | ||
|
39c503f155 | ||
|
82662a3b5f | ||
|
fdb3f06b82 | ||
|
6b3d196a7c | ||
|
4c0f6e349d | ||
|
2be4828af1 | ||
|
edfe16a6d9 | ||
|
1d3215fd24 | ||
|
b85048261a | ||
|
70228e101e | ||
|
c70bdf9d4a | ||
|
0997352ddb | ||
|
c230c002ac | ||
|
b1c1147059 | ||
|
cb30c8f251 | ||
|
5cd8be6079 | ||
|
a83dbf008c | ||
|
adc6898366 | ||
|
929d1a24d1 | ||
|
9e56970090 | ||
|
c13742b180 | ||
|
fbb9607223 | ||
|
578bcdc260 | ||
|
6d8f4bafad | ||
|
0b9026a823 | ||
|
c73fce3d12 | ||
|
3cf658ee7e | ||
|
e36d5ac7d1 | ||
|
f1d78c489a | ||
|
764e8ba138 | ||
|
c32be82e99 | ||
|
f9713abe95 | ||
|
1e947f9bf5 | ||
|
466b877f43 | ||
|
5b45b44e6f | ||
|
c788c2b1ad | ||
|
534fcb84de | ||
|
0f1ddb21ff | ||
|
707e6be745 | ||
|
3e63a91b17 | ||
|
7a38ad07d0 | ||
|
a67efa3b22 | ||
|
58bccfa57c | ||
|
422bf2725b | ||
|
02b7b861b1 | ||
|
ec97412b7c | ||
|
82af1cbf0d | ||
|
c44e0a896c | ||
|
818283de3f | ||
|
e465aae055 | ||
|
27fb01a0b0 | ||
|
b3407223c5 | ||
|
f76d50166b | ||
|
69c135462d | ||
|
67ead55b35 | ||
|
348a34d984 | ||
|
d148a178c1 | ||
|
ccb4c38a50 | ||
|
214bc6e206 | ||
|
ea26838a52 | ||
|
84a534b406 | ||
|
c4a53853c1 | ||
|
ce7b77a71b | ||
|
eb9db72ca8 | ||
|
a4826c8664 | ||
|
54d33a5314 | ||
|
f69248d093 | ||
|
5bd326c5f3 | ||
|
7f9e354a01 | ||
|
ddb7050c68 | ||
|
66360134f8 | ||
|
418aded964 | ||
|
ef62da4ff7 | ||
|
f60f4cfeb4 | ||
|
2a0755a947 | ||
|
a57268fe9e | ||
|
6b81166fff | ||
|
1825c24fd8 | ||
|
a302263ebb | ||
|
c38f0816e7 | ||
|
582b6cdd08 | ||
|
f16bd39441 | ||
|
6a5033ca3e | ||
|
ba562ca040 | ||
|
dd40a1f85c | ||
|
f9fd0c2108 | ||
|
ce4cca7c06 | ||
|
fc70522ffe | ||
|
aad15888d6 | ||
|
493dde944d | ||
|
38c92f7030 | ||
|
9854561c08 | ||
|
a2e7559576 | ||
|
f6fc95c943 | ||
|
48cf40b8c9 | ||
|
f221466ea7 | ||
|
e79bf8d707 | ||
|
5add2c5577 | ||
|
ff82167537 | ||
|
f7c4d22465 | ||
|
dad13c8067 | ||
|
81c6f1762e | ||
|
4cefb5e903 | ||
|
bb3594e842 | ||
|
f6c8bbbe92 | ||
|
68ddad3f60 | ||
|
5feb1fbd44 | ||
|
6deb4baa1f | ||
|
efb5659334 | ||
|
7de8045a09 | ||
|
6c585b52e5 | ||
|
ba3b642d5b | ||
|
c36b7b5114 | ||
|
cd72b6cfd1 | ||
|
d80c3d6e19 | ||
|
81a46615f5 | ||
|
0d622d9c3d | ||
|
f97117bae7 | ||
|
c194ccca26 | ||
|
8f628f7820 | ||
|
8d774c745c | ||
|
788421d5a7 | ||
|
43516263a8 | ||
|
fae43d06dd | ||
|
a8ecf980c0 | ||
|
c1d8b697cf | ||
|
b219e2cd4c | ||
|
0dbaba4239 | ||
|
13a623cf9c | ||
|
d22867471f | ||
|
957ca63190 | ||
|
5099057fb8 | ||
|
4be497df49 | ||
|
93b8ed68dd | ||
|
b854b07540 | ||
|
cc530cd10c | ||
|
1d031e750b | ||
|
29f7ad8b7c | ||
|
8c39253dff | ||
|
02d7b79771 | ||
|
7636747f44 | ||
|
7feed95031 | ||
|
db62b65c63 | ||
|
3d6b7fd303 | ||
|
26cfe2c659 | ||
|
de949fdbcf | ||
|
e60536756e | ||
|
513edcec28 | ||
|
7aa8af4576 | ||
|
4b026f0d5a | ||
|
b34ed98694 | ||
|
c10f7f77b0 | ||
|
7dcf32c1ee | ||
|
e5b911d411 | ||
|
184ee9b1de | ||
|
e50c2bb383 | ||
|
3e61b953b7 | ||
|
f74abe4a2c | ||
|
0eb522987f | ||
|
0f7fb5c5e5 | ||
|
b238ce28f8 | ||
|
0a5d2b505c | ||
|
61364ab927 | ||
|
bd33a385ee | ||
|
cd70de1cc0 | ||
|
cc1d13c922 | ||
|
3b0e04305b | ||
|
668621362f | ||
|
322ac05f8b | ||
|
1333d8c8d3 | ||
|
01712e6508 | ||
|
c6a6193d12 | ||
|
3b4ad37ebe | ||
|
d14feb6cb7 | ||
|
45b0be3840 | ||
|
77b738b36f | ||
|
b5808fe960 | ||
|
7285f275ff | ||
|
1549651da6 | ||
|
c37cce7a84 | ||
|
38ed2ff3dd | ||
|
a4960cf1b6 | ||
|
8778ee616a | ||
|
21821933ae | ||
|
7990438f14 | ||
|
f469c70281 | ||
|
a9e3458ba7 | ||
|
75839f977d | ||
|
50f911d25d | ||
|
9108fc17b0 | ||
|
300aae1180 | ||
|
84b223c18c | ||
|
adec2bd598 | ||
|
73974f809c | ||
|
e0ed7a9b15 | ||
|
04ff9d663b | ||
|
bca6fcd78f | ||
|
d74d56fcfa | ||
|
422da35375 | ||
|
b47fe2655d | ||
|
3feea54eae | ||
|
2c061de063 | ||
|
eafd990f26 | ||
|
8b0932c19f | ||
|
6aa31db5eb | ||
|
6d57592740 | ||
|
fb02f5b2cd | ||
|
c602e97446 | ||
|
12a4ef58a8 | ||
|
f891b052c5 | ||
|
47650a5cab | ||
|
61a9fa589a | ||
|
eccb856f01 | ||
|
1e0f973b65 | ||
|
83357313dd | ||
|
b75d1de536 | ||
|
4ef78a39f0 | ||
|
c8b8157e12 | ||
|
9a1f14ad72 | ||
|
a23fdff6fb | ||
|
5cd3d4bc43 | ||
|
18fcb37598 | ||
|
2ed845b3c3 | ||
|
d9c919744b | ||
|
48997fe4d3 | ||
|
430743a1e8 | ||
|
c67617f3c6 | ||
|
a22f4c34df | ||
|
4e2ac8062c | ||
|
c40c6351fa | ||
|
a523556244 | ||
|
302eb57b18 | ||
|
63653ff8c8 | ||
|
710ff7490a | ||
|
f6f66e0c30 | ||
|
94057f7402 | ||
|
a6a835bdb1 | ||
|
e3756ba90a | ||
|
4cca792399 | ||
|
a56af23f06 | ||
|
b112ec225f | ||
|
4465cd124f | ||
|
072b9c2839 | ||
|
27f44ea1fb | ||
|
9d1c9d0379 | ||
|
2d9950a2bf | ||
|
eaea26b781 | ||
|
6eacb857c1 | ||
|
7d3d87e4d7 | ||
|
dd01704111 | ||
|
c7c964b109 | ||
|
c0328cf380 | ||
|
8120390aab | ||
|
8f38b08b50 | ||
|
8ffa47fb3a | ||
|
1f0d809629 | ||
|
859046e000 | ||
|
df851da3ce | ||
|
e18792566c | ||
|
f55477fe2d | ||
|
cf3ad972a2 | ||
|
2649a735b2 | ||
|
972d887264 | ||
|
c9d7262843 | ||
|
396e791059 | ||
|
08a475df10 | ||
|
70911f1f4a | ||
|
4bb34b6df1 | ||
|
cc617b6e14 | ||
|
0ef6fbbd11 | ||
|
d96c7befc0 | ||
|
c751368c37 | ||
|
76b51586f4 | ||
|
0e660ee7a1 | ||
|
088573c973 | ||
|
ad12178c3d | ||
|
80f7c1b464 | ||
|
a292d6c8ef | ||
|
21429c1566 | ||
|
266efa6b29 | ||
|
43f2c9f8eb | ||
|
8ef8175a33 | ||
|
76fc038746 | ||
|
9b2e99e50a | ||
|
a85cdb9f2b | ||
|
44c9a93948 | ||
|
f235838f58 | ||
|
5556529b94 | ||
|
1bbbd6a79d | ||
|
59bbab3a9a | ||
|
082208a849 | ||
|
e2a8eaec0f | ||
|
52b6a7c889 | ||
|
0d141df465 | ||
|
31d60b9ba4 | ||
|
d42046e1da | ||
|
caa6584f36 | ||
|
83e78feb80 | ||
|
0ce7f25fe3 | ||
|
ba5410320b | ||
|
4a1aeca3bd | ||
|
6cfb6da951 | ||
|
d0d38ce20e | ||
|
f9c2c71ed6 | ||
|
0286fe8176 | ||
|
40801ac995 | ||
|
166830d8f7 | ||
|
f273905161 | ||
|
4fa25853cd | ||
|
df73a69faf | ||
|
f68cb23c14 | ||
|
49accdedf9 | ||
|
b948a49615 | ||
|
33a3293651 | ||
|
fd30b00707 | ||
|
88bd066166 | ||
|
e1ed55738e | ||
|
253909974a | ||
|
d786a17232 | ||
|
999463c865 | ||
|
a5abd9cc2c | ||
|
123b720eeb | ||
|
a457823f27 | ||
|
caa917491a | ||
|
ec8c74e8bc | ||
|
796b380ca7 | ||
|
665afccc52 | ||
|
95bb203861 | ||
|
c7a0aca0ed | ||
|
01b6090b75 | ||
|
c5d6a57da0 | ||
|
69ebe82806 | ||
|
78fb6b0e02 | ||
|
bfb141cf19 | ||
|
2fe25a74d6 | ||
|
d3add11e87 | ||
|
d39d1260c6 | ||
|
97eedf5dfb | ||
|
7e55cf6b48 | ||
|
a80032dc44 | ||
|
fc8b8deac2 | ||
|
3bfbc91507 | ||
|
91f6c533f8 | ||
|
0c3e8e9947 | ||
|
cb277815d5 | ||
|
e6edbe315f | ||
|
13c5e34a1b | ||
|
804666c86e | ||
|
49054b6bb6 | ||
|
62a75650e4 | ||
|
9caaa79dd7 | ||
|
490a62beb7 | ||
|
e8b9296c67 | ||
|
0f9395d7c5 | ||
|
94d4efb54e | ||
|
2926498f01 | ||
|
965dbf97ab | ||
|
d5cf0fba20 | ||
|
c9416efeef | ||
|
6cc63aee53 | ||
|
c8ff8e05af | ||
|
9c33f16f8c | ||
|
0a58c9a391 | ||
|
0844a16a07 | ||
|
46f6752834 | ||
|
4f47eaf945 | ||
|
4d613feee5 | ||
|
b49a6c8f80 | ||
|
fe6142f04c |
50
.azurepipelines/ReadMe.md
Normal file
50
.azurepipelines/ReadMe.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Azure DevOps Pipelines
|
||||
|
||||
These yml files are used to provide CI builds using the Azure DevOps Pipeline Service.
|
||||
Most of the CI leverages edk2-pytools to support cross platform building and execution.
|
||||
|
||||
## Core CI
|
||||
|
||||
Focused on building and testing all packages in Edk2 without an actual target platform.
|
||||
|
||||
See `.pytools/ReadMe.py` for more details
|
||||
|
||||
## Platform CI
|
||||
|
||||
Focused on building a single target platform and confirming functionality on that platform.
|
||||
|
||||
## Conventions
|
||||
|
||||
* Files extension should be *.yml. *.yaml is also supported but in Edk2 we use those for our package configuration.
|
||||
* Platform CI files should be in the `<PlatformPkg>/.azurepipelines` folder.
|
||||
* Core CI files are in the root folder.
|
||||
* Shared templates are in the `templates` folder.
|
||||
* Top level CI files should be named `<host os>-<tool_chain_tag>.yml`
|
||||
|
||||
## Links
|
||||
|
||||
* Basic Azure Landing Site - https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops
|
||||
* Pipeline jobs - https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml
|
||||
* Pipeline yml scheme - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema
|
||||
* Pipeline expression - https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops
|
||||
* PyTools - https://github.com/tianocore/edk2-pytool-extensions and https://github.com/tianocore/edk2-pytool-library
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
### Templates and parameters
|
||||
|
||||
They are great but evil. If they are used as part of determining the steps of a build they must resolve before the build starts. They can not use variables set in a yml or determined as part of a matrix. If they are used in a step then they can be bound late.
|
||||
|
||||
### File matching patterns
|
||||
|
||||
On Linux this can hang if there are too many files in the search list.
|
||||
|
||||
### Templates and file splitting
|
||||
|
||||
Suggestion is to do one big yaml file that does what you want for one of your targets. Then do the second one and find the deltas. From that you can start to figure out the right split of files, steps, jobs.
|
||||
|
||||
### Conditional steps
|
||||
|
||||
If you want the step to show up in the log but not run, use a step conditional. This is great when a platform doesn't currently support a feature but you want the builders to know that the features exists and maybe someday it will.
|
||||
|
||||
If you want the step to not show up use a template step conditional wrapper. Beware this will be evaluated early (at build start). This can hide things not needed on a given OS for example.
|
@@ -2,6 +2,7 @@
|
||||
# Azure Pipeline build file for a build using ubuntu and GCC5
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
trigger:
|
||||
@@ -14,5 +15,5 @@ jobs:
|
||||
parameters:
|
||||
tool_chain_tag: 'GCC5'
|
||||
vm_image: 'ubuntu-latest'
|
||||
arch_list: "IA32,X64,ARM,AARCH64"
|
||||
arch_list: "IA32,X64,ARM,AARCH64,RISCV64"
|
||||
|
||||
|
59
.azurepipelines/templates/ReadMe.md
Normal file
59
.azurepipelines/templates/ReadMe.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# CI Templates
|
||||
|
||||
This folder contains azure pipeline yml templates for "Core" and "Platform" Continuous Integration and PR validation.
|
||||
|
||||
## Common CI templates
|
||||
|
||||
### basetools-build-steps.yml
|
||||
|
||||
This template compiles the Edk2 basetools from source. The steps in this template are
|
||||
conditional and will only run if variable `pkg_count` is greater than 0.
|
||||
|
||||
It also has two conditional steps only used when the toolchain contains GCC. These two steps
|
||||
use `apt` to update the system packages and add those necessary for Edk2 builds.
|
||||
|
||||
## Core CI templates
|
||||
|
||||
### pr-gate-build-job.yml
|
||||
|
||||
This templates contains the jobs and most importantly the matrix of which packages and
|
||||
targets to run for Core CI.
|
||||
|
||||
### pr-gate-steps.yml
|
||||
|
||||
This template is the main Core CI template. It controls all the steps run and is responsible for most functionality of the Core CI process. This template sets
|
||||
the `pkg_count` variable using the `stuart_pr_eval` tool when the
|
||||
build type is "pull request"
|
||||
|
||||
### spell-check-prereq-steps.yml
|
||||
|
||||
This template installs the node based tools used by the spell checker plugin. The steps
|
||||
in this template are conditional and will only run if variable `pkg_count` is greater than 0.
|
||||
|
||||
## Platform CI templates
|
||||
|
||||
### platform-build-run-steps.yml
|
||||
|
||||
This template makes heavy use of pytools to build and run a platform in the Edk2 repo
|
||||
|
||||
Also uses basetools-build-steps.yml to compile basetools
|
||||
|
||||
#### Special Notes
|
||||
|
||||
* For a build type of pull request it will conditionally build if the patches change files that impact the platform.
|
||||
* uses `stuart_pr_eval` to determine impact
|
||||
* For manual builds or CI builds it will always build the platform
|
||||
* It compiles basetools from source
|
||||
* Will use `stuart_build --FlashOnly` to attempt to run the built image if the `Run` parameter is set.
|
||||
* See the parameters block for expected configuration options
|
||||
* Parameter `extra_install_step` allows the caller to insert extra steps. This is useful if additional dependencies, tools, or other things need to be installed. Here is an example of installing qemu on Windows.
|
||||
|
||||
``` yaml
|
||||
steps:
|
||||
- template: ../../.azurepipelines/templates/build-run-steps.yml
|
||||
parameters:
|
||||
extra_install_step:
|
||||
- powershell: choco install qemu; Write-Host "##vso[task.prependpath]c:\Program Files\qemu"
|
||||
displayName: Install QEMU and Set QEMU on path # friendly name displayed in the UI
|
||||
condition: and(gt(variables.pkg_count, 0), succeeded())
|
||||
```
|
134
.azurepipelines/templates/platform-build-run-steps.yml
Normal file
134
.azurepipelines/templates/platform-build-run-steps.yml
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
## @file
|
||||
# File steps.yml
|
||||
#
|
||||
# template file containing the steps to build
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
parameters:
|
||||
- name: tool_chain_tag
|
||||
type: string
|
||||
default: ''
|
||||
- name: build_pkg
|
||||
type: string
|
||||
default: ''
|
||||
- name: build_target
|
||||
type: string
|
||||
default: ''
|
||||
- name: build_arch
|
||||
type: string
|
||||
default: ''
|
||||
- name: build_file
|
||||
type: string
|
||||
default: ''
|
||||
- name: build_flags
|
||||
type: string
|
||||
default: ''
|
||||
- name: run_flags
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
- name: extra_install_step
|
||||
type: stepList
|
||||
default: []
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: "3.8.x"
|
||||
architecture: "x64"
|
||||
|
||||
- script: pip install -r pip-requirements.txt --upgrade
|
||||
displayName: 'Install/Upgrade pip modules'
|
||||
|
||||
# Set default
|
||||
- bash: echo "##vso[task.setvariable variable=pkg_count]${{ 1 }}"
|
||||
|
||||
# trim the package list if this is a PR
|
||||
- task: CmdLine@1
|
||||
displayName: Check if ${{ parameters.build_pkg }} need testing
|
||||
inputs:
|
||||
filename: stuart_pr_eval
|
||||
arguments: -c ${{ parameters.build_file }} -t ${{ parameters.build_target}} -a ${{ parameters.build_arch}} --pr-target origin/$(System.PullRequest.targetBranch) --output-count-format-string "##vso[task.setvariable variable=pkg_count;isOutpout=true]{pkgcount}"
|
||||
condition: eq(variables['Build.Reason'], 'PullRequest')
|
||||
|
||||
# Setup repo
|
||||
- task: CmdLine@1
|
||||
displayName: Setup
|
||||
inputs:
|
||||
filename: stuart_setup
|
||||
arguments: -c ${{ parameters.build_file }} TOOL_CHAIN_TAG=${{ parameters.tool_chain_tag}} -t ${{ parameters.build_target}} -a ${{ parameters.build_arch}} ${{ parameters.build_flags}}
|
||||
condition: and(gt(variables.pkg_count, 0), succeeded())
|
||||
|
||||
# Stuart Update
|
||||
- task: CmdLine@1
|
||||
displayName: Update
|
||||
inputs:
|
||||
filename: stuart_update
|
||||
arguments: -c ${{ parameters.build_file }} TOOL_CHAIN_TAG=${{ parameters.tool_chain_tag}} -t ${{ parameters.build_target}} -a ${{ parameters.build_arch}} ${{ parameters.build_flags}}
|
||||
condition: and(gt(variables.pkg_count, 0), succeeded())
|
||||
|
||||
# build basetools
|
||||
# do this after setup and update so that code base dependencies
|
||||
# are all resolved.
|
||||
- template: basetools-build-steps.yml
|
||||
parameters:
|
||||
tool_chain_tag: ${{ parameters.tool_chain_tag }}
|
||||
|
||||
# Potential Extra steps
|
||||
- ${{ parameters.extra_install_step }}
|
||||
|
||||
# Build
|
||||
- task: CmdLine@1
|
||||
displayName: Build
|
||||
inputs:
|
||||
filename: stuart_build
|
||||
arguments: -c ${{ parameters.build_file }} TOOL_CHAIN_TAG=${{ parameters.tool_chain_tag}} TARGET=${{ parameters.build_target}} -a ${{ parameters.build_arch}} ${{ parameters.build_flags}}
|
||||
condition: and(gt(variables.pkg_count, 0), succeeded())
|
||||
|
||||
# Run
|
||||
- task: CmdLine@1
|
||||
displayName: Run to shell
|
||||
inputs:
|
||||
filename: stuart_build
|
||||
arguments: -c ${{ parameters.build_file }} TOOL_CHAIN_TAG=${{ parameters.tool_chain_tag}} TARGET=${{ parameters.build_target}} -a ${{ parameters.build_arch}} ${{ parameters.build_flags}} ${{ parameters.run_flags }} --FlashOnly
|
||||
condition: and(and(gt(variables.pkg_count, 0), succeeded()), eq(variables['Run'], true))
|
||||
timeoutInMinutes: 1
|
||||
|
||||
# Copy the build logs to the artifact staging directory
|
||||
- task: CopyFiles@2
|
||||
displayName: "Copy build logs"
|
||||
inputs:
|
||||
targetFolder: "$(Build.ArtifactStagingDirectory)"
|
||||
SourceFolder: "Build"
|
||||
contents: |
|
||||
BUILDLOG_*.txt
|
||||
BUILDLOG_*.md
|
||||
CI_*.txt
|
||||
CI_*.md
|
||||
CISETUP.txt
|
||||
SETUPLOG.txt
|
||||
UPDATE_LOG.txt
|
||||
PREVALLOG.txt
|
||||
TestSuites.xml
|
||||
**/BUILD_TOOLS_REPORT.html
|
||||
**/OVERRIDELOG.TXT
|
||||
BASETOOLS_BUILD*.*
|
||||
flattenFolders: true
|
||||
condition: succeededOrFailed()
|
||||
|
||||
# Publish build artifacts to Azure Artifacts/TFS or a file share
|
||||
- task: PublishBuildArtifacts@1
|
||||
continueOnError: true
|
||||
displayName: "Publish build logs"
|
||||
inputs:
|
||||
pathtoPublish: "$(Build.ArtifactStagingDirectory)"
|
||||
artifactName: "Build Logs $(System.JobName)"
|
||||
condition: succeededOrFailed()
|
@@ -4,6 +4,7 @@
|
||||
# template file used to build supported packages.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
@@ -22,10 +23,10 @@ jobs:
|
||||
matrix:
|
||||
TARGET_MDE_CPU:
|
||||
Build.Pkgs: 'MdePkg,UefiCpuPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
|
||||
TARGET_MDEMODULE_DEBUG:
|
||||
Build.Pkgs: 'MdeModulePkg'
|
||||
Build.Targets: 'DEBUG'
|
||||
Build.Targets: 'DEBUG,NOOPT'
|
||||
TARGET_MDEMODULE_RELEASE:
|
||||
Build.Pkgs: 'MdeModulePkg'
|
||||
Build.Targets: 'RELEASE,NO-TARGET'
|
||||
@@ -35,15 +36,20 @@ jobs:
|
||||
TARGET_OTHER:
|
||||
Build.Pkgs: 'PcAtChipsetPkg,ShellPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
|
||||
TARGET_FMP:
|
||||
Build.Pkgs: 'FmpDevicePkg,FatPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
|
||||
TARGET_FMP_FAT_TEST:
|
||||
Build.Pkgs: 'FmpDevicePkg,FatPkg,UnitTestFrameworkPkg,DynamicTablesPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
|
||||
TARGET_CRYPTO:
|
||||
Build.Pkgs: 'CryptoPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
|
||||
TARGET_SECURITY:
|
||||
Build.Pkgs: 'SecurityPkg'
|
||||
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
|
||||
TARGET_PLATFORMS:
|
||||
# For Platforms only check code. Leave it to Platform CI
|
||||
# to build them.
|
||||
Build.Pkgs: 'ArmVirtPkg,EmulatorPkg,OvmfPkg'
|
||||
Build.Targets: 'NO-TARGET'
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
@@ -20,7 +20,7 @@ steps:
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.7.x'
|
||||
versionSpec: '3.8.x'
|
||||
architecture: 'x64'
|
||||
|
||||
- script: pip install -r pip-requirements.txt --upgrade
|
||||
@@ -39,11 +39,6 @@ steps:
|
||||
arguments: -c .pytool/CISettings.py -p ${{ parameters.build_pkgs }} --pr-target origin/$(System.PullRequest.targetBranch) --output-csv-format-string "##vso[task.setvariable variable=pkgs_to_build;isOutpout=true]{pkgcsv}" --output-count-format-string "##vso[task.setvariable variable=pkg_count;isOutpout=true]{pkgcount}"
|
||||
condition: eq(variables['Build.Reason'], 'PullRequest')
|
||||
|
||||
# build basetools
|
||||
- template: basetools-build-steps.yml
|
||||
parameters:
|
||||
tool_chain_tag: ${{ parameters.tool_chain_tag }}
|
||||
|
||||
# install spell check prereqs
|
||||
- template: spell-check-prereq-steps.yml
|
||||
|
||||
@@ -62,6 +57,13 @@ steps:
|
||||
arguments: -c .pytool/CISettings.py -p $(pkgs_to_build) -t ${{ parameters.build_targets}} -a ${{ parameters.build_archs}} TOOL_CHAIN_TAG=${{ parameters.tool_chain_tag}}
|
||||
condition: and(gt(variables.pkg_count, 0), succeeded())
|
||||
|
||||
# build basetools
|
||||
# do this after setup and update so that code base dependencies
|
||||
# are all resolved.
|
||||
- template: basetools-build-steps.yml
|
||||
parameters:
|
||||
tool_chain_tag: ${{ parameters.tool_chain_tag }}
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: Build and Test ${{ parameters.build_pkgs }} ${{ parameters.build_archs}}
|
||||
inputs:
|
||||
|
13
.gitmodules
vendored
13
.gitmodules
vendored
@@ -4,3 +4,16 @@
|
||||
[submodule "SoftFloat"]
|
||||
path = ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
|
||||
url = https://github.com/ucb-bar/berkeley-softfloat-3.git
|
||||
[submodule "UnitTestFrameworkPkg/Library/CmockaLib/cmocka"]
|
||||
path = UnitTestFrameworkPkg/Library/CmockaLib/cmocka
|
||||
url = https://git.cryptomilk.org/projects/cmocka.git
|
||||
[submodule "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma"]
|
||||
path = MdeModulePkg/Universal/RegularExpressionDxe/oniguruma
|
||||
url = https://github.com/kkos/oniguruma
|
||||
[submodule "MdeModulePkg/Library/BrotliCustomDecompressLib/brotli"]
|
||||
path = MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
|
||||
url = https://github.com/google/brotli
|
||||
[submodule "BaseTools/Source/C/BrotliCompress/brotli"]
|
||||
path = BaseTools/Source/C/BrotliCompress/brotli
|
||||
url = https://github.com/google/brotli
|
||||
ignore = untracked
|
||||
|
73
.mailmap
Normal file
73
.mailmap
Normal file
@@ -0,0 +1,73 @@
|
||||
#
|
||||
# This list is used by git-shortlog to update a few name translations
|
||||
# in the git archive to adjust for job changes or incorrect/inconsistent
|
||||
# name usage.
|
||||
#
|
||||
# Please keep this file sorted alphabetically, and email in lowercase.
|
||||
# The format used is:
|
||||
#
|
||||
# Firstname Lastname <email@domain.tld>
|
||||
#
|
||||
|
||||
Aaron Li <aaron.li@intel.com> <songpeng.li@intel.com>
|
||||
Antoine Cœur <coeur@gmx.fr>
|
||||
Antoine Cœur <coeur@gmx.fr> <Coeur@gmx.fr>
|
||||
Ard Biesheuvel <ard.biesheuvel@linaro.org> <abiesheuvel@Edk2>
|
||||
Ashley DeSimone <ashley.e.desimone@intel.com> <ashdesimone@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Baraneedharan Anbazhagan <anbazhagan@hp.com>
|
||||
Chasel Chiu <chasel.chiu@intel.com>
|
||||
Christopher J Zurcher <christopher.j.zurcher@intel.com>
|
||||
Eric Dong <eric.dong@intel.com>
|
||||
Eric Dong <eric.dong@intel.com> Eric Dong <eirc.dong@intel.com>
|
||||
Eric Dong <eric.dong@intel.com> <ydong10@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Eric Dong <eric.dong@intel.com> <ydong10@Edk2>
|
||||
Erik Bjorge <erik.c.bjorge@intel.com> <geekboy15a@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Eugene Cohen <eugene@nuviainc.com>
|
||||
Eugene Cohen <eugene@nuviainc.com> <eugene@hp.com>
|
||||
Hao A Wu <hao.a.wu@intel.com>
|
||||
Hao A Wu <hao.a.wu@intel.com> <hwu1225@Edk2>
|
||||
Hot Tian <hot.tian@intel.com>
|
||||
Hot Tian <hot.tian@intel.com> <hhtian@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Jiewen Yao <jiewen.yao@intel.com>
|
||||
Jiewen Yao <jiewen.yao@intel.com> <Jiewen.yao@intel.com>
|
||||
Jiewen Yao <jiewen.yao@intel.com> <Jiewen.Yao@intel.com>
|
||||
Jiewen Yao <jiewen.yao@intel.com> <jyao1>
|
||||
Jiewen Yao <jiewen.yao@intel.com> <jyao1@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Jiewen Yao <jiewen.yao@intel.com> <jyao1@Edk2>
|
||||
Jim Dailey <Jim.Dailey@Dell.com>
|
||||
Jim Dailey <Jim.Dailey@Dell.com> <Jim_Dailey@Dell.com>
|
||||
Laszlo Ersek <lersek@redhat.com> <lersek@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Laszlo Ersek <lersek@redhat.com> <lersek@Edk2>
|
||||
Liming Gao <liming.gao@intel.com> <Gao, Liming liming.gao@intel.com>
|
||||
Liming Gao <liming.gao@intel.com> <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Liming Gao <liming.gao@intel.com> <lgao4@Edk2>
|
||||
Liming Gao <liming.gao@intel.com> <liming.gao@intel.com>
|
||||
Maciej Rabeda <maciej.rabeda@intel.com>
|
||||
Marc-André Lureau <marcandre.lureau@redhat.com> <marcandre.lureau@redhat.com>
|
||||
Marvin Häuser <Marvin.Haeuser@outlook.com>
|
||||
Marvin Häuser <Marvin.Haeuser@outlook.com> edk2-devel <edk2-devel-bounces@lists.01.org>
|
||||
Marvin Häuser <mhaeuser@outlook.de>
|
||||
Maurice Ma <maurice.ma@intel.com>
|
||||
Michael Kubacki <michael.a.kubacki@intel.com>
|
||||
Michael Kubacki <michael.a.kubacki@intel.com> </o=Intel/ou=External (FYDIBOHF25SPDLT)/cn=Recipients/cn=3c8b0226e75f4ab08d20c151cb7a8a72>
|
||||
Ming Tan <ming.tan@intel.com>
|
||||
Nikolai Saoukh <nms@otdel-1.org>
|
||||
Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
Ray Ni <ray.ni@intel.com>
|
||||
Ray Ni <ray.ni@intel.com> <C:/Program Files (x86)/Git/O=Intel/OU=Pacifica02/cn=Recipients/cn=rni2>
|
||||
Ray Ni <ray.ni@intel.com> <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Ray Ni <ray.ni@intel.com> <niruiyu@Edk2>
|
||||
Ray Ni <ray.ni@intel.com> <ruiyu.ni@intel.com>
|
||||
Ray Ni <ray.ni@intel.com> <Ruiyu.ni@Intel.com>
|
||||
Ray Ni <ray.ni@intel.com> <ruyu.ni@intel.com>
|
||||
Samer El-Haj-Mahmoud <samer@elhajmahmoud.com> <elhaj@hpe.com>
|
||||
Samer El-Haj-Mahmoud <samer@elhajmahmoud.com> <Samer El-Haj-Mahmoud elhaj@hp.com>
|
||||
Shenglei Zhang <shenglei.zhang@intel.com>
|
||||
Star Zeng <star.zeng@intel.com>
|
||||
Star Zeng <star.zeng@intel.com> <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
|
||||
Star Zeng <star.zeng@intel.com> <lzeng14@Edk2>
|
||||
Vitaly Cheptsov <vit9696@protonmail.com> Vitaly Cheptsov via Groups.Io <vit9696=protonmail.com@groups.io>
|
||||
Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com> Vladimir Olovyannikov via edk2-devel <edk2-devel@lists.01.org>
|
||||
Yonghong Zhu <yonghong.zhu@intel.com>
|
||||
Yonghong Zhu <yonghong.zhu@intel.com> <yzhu52@Edk2>
|
||||
Yu-Chen Lin <yuchenlin@synology.com>
|
@@ -1,6 +1,8 @@
|
||||
# @file
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
||||
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
import os
|
||||
@@ -39,7 +41,10 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
''' return iterable of edk2 packages supported by this build.
|
||||
These should be edk2 workspace relative paths '''
|
||||
|
||||
return ("MdePkg",
|
||||
return ("ArmVirtPkg",
|
||||
"DynamicTablesPkg",
|
||||
"EmulatorPkg",
|
||||
"MdePkg",
|
||||
"MdeModulePkg",
|
||||
"NetworkPkg",
|
||||
"PcAtChipsetPkg",
|
||||
@@ -48,15 +53,19 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
"FmpDevicePkg",
|
||||
"ShellPkg",
|
||||
"FatPkg",
|
||||
"CryptoPkg"
|
||||
"CryptoPkg",
|
||||
"UnitTestFrameworkPkg",
|
||||
"OvmfPkg"
|
||||
)
|
||||
|
||||
def GetArchitecturesSupported(self):
|
||||
''' return iterable of edk2 architectures supported by this build '''
|
||||
return ("IA32",
|
||||
return (
|
||||
"IA32",
|
||||
"X64",
|
||||
"ARM",
|
||||
"AARCH64")
|
||||
"AARCH64",
|
||||
"RISCV64")
|
||||
|
||||
def GetTargetsSupported(self):
|
||||
''' return iterable of edk2 target tags supported by this build '''
|
||||
@@ -117,7 +126,7 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
|
||||
def GetActiveScopes(self):
|
||||
''' return tuple containing scopes that should be active for this process '''
|
||||
scopes = ("cibuild","edk2-build")
|
||||
scopes = ("cibuild", "edk2-build", "host-based-test")
|
||||
|
||||
self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
|
||||
|
||||
@@ -126,6 +135,8 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
scopes += ("gcc_aarch64_linux",)
|
||||
if "ARM" in self.ActualArchitectures:
|
||||
scopes += ("gcc_arm_linux",)
|
||||
if "RISCV64" in self.ActualArchitectures:
|
||||
scopes += ("gcc_riscv64_unknown",)
|
||||
|
||||
return scopes
|
||||
|
||||
@@ -133,18 +144,27 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
''' return iterable containing RequiredSubmodule objects.
|
||||
If no RequiredSubmodules return an empty iterable
|
||||
'''
|
||||
rs=[]
|
||||
rs = []
|
||||
rs.append(RequiredSubmodule(
|
||||
"ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"CryptoPkg/Library/OpensslLib/openssl", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"UnitTestFrameworkPkg/Library/CmockaLib/cmocka", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"MdeModulePkg/Universal/RegularExpressionDxe/oniguruma", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"MdeModulePkg/Library/BrotliCustomDecompressLib/brotli", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"BaseTools/Source/C/BrotliCompress/brotli", False))
|
||||
return rs
|
||||
|
||||
def GetName(self):
|
||||
return "Edk2"
|
||||
|
||||
def GetDependencies(self):
|
||||
return []
|
||||
return [
|
||||
]
|
||||
|
||||
def GetPackagesPath(self):
|
||||
return ()
|
||||
@@ -155,10 +175,11 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
|
||||
def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list:
|
||||
''' Filter potential packages to test based on changed files. '''
|
||||
build_these_packages=[]
|
||||
possible_packages=potentialPackagesList.copy()
|
||||
build_these_packages = []
|
||||
possible_packages = potentialPackagesList.copy()
|
||||
for f in changedFilesList:
|
||||
nodes=f.split("/") # split each part of path for comparison later
|
||||
# split each part of path for comparison later
|
||||
nodes = f.split("/")
|
||||
|
||||
# python file change in .pytool folder causes building all
|
||||
if f.endswith(".py") and ".pytool" in nodes:
|
||||
|
@@ -100,7 +100,7 @@ class CharEncodingCheck(ICiBuildPlugin):
|
||||
overall_status += 1
|
||||
|
||||
tc.LogStdOut("Tested Encoding on {0} files".format(files_tested))
|
||||
if overall_status is not 0:
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("CharEncoding {0} Failed. Errors {1}".format(packagename, overall_status), "CHAR_ENCODING_CHECK_FAILED")
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# @file HostUnitTestCompiler_plugin.py
|
||||
# @file CompilerPlugin.py
|
||||
##
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
@@ -42,7 +42,7 @@ class CompilerPlugin(ICiBuildPlugin):
|
||||
return ["DEBUG", "RELEASE"]
|
||||
|
||||
##
|
||||
# External function of plugin. This function is used to perform the task of the MuBuild Plugin
|
||||
# External function of plugin. This function is used to perform the task of the ICiBuildPlugin Plugin
|
||||
#
|
||||
# - package is the edk2 path to package. This means workspace/packagepath relative.
|
||||
# - edk2path object configured with workspace and packages path
|
||||
|
@@ -113,7 +113,7 @@ class DependencyCheck(ICiBuildPlugin):
|
||||
overall_status += 1
|
||||
|
||||
# If XML object exists, add results
|
||||
if overall_status is not 0:
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("Failed with {0} errors".format(overall_status), "DEPENDENCYCHECK_FAILED")
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
|
@@ -54,21 +54,25 @@ class DscCompleteCheck(ICiBuildPlugin):
|
||||
# Parse the config for required DscPath element
|
||||
if "DscPath" not in pkgconfig:
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("DscPath not found in config file. Nothing to check.")
|
||||
tc.LogStdError(
|
||||
"DscPath not found in config file. Nothing to check.")
|
||||
return -1
|
||||
|
||||
abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSytemFromEdk2RelativePath(packagename)
|
||||
abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSytemFromEdk2RelativePath(
|
||||
packagename)
|
||||
abs_dsc_path = os.path.join(abs_pkg_path, pkgconfig["DscPath"].strip())
|
||||
wsr_dsc_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(abs_dsc_path)
|
||||
wsr_dsc_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(
|
||||
abs_dsc_path)
|
||||
|
||||
if abs_dsc_path is None or wsr_dsc_path is "" or not os.path.isfile(abs_dsc_path):
|
||||
if abs_dsc_path is None or wsr_dsc_path == "" or not os.path.isfile(abs_dsc_path):
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("Package Dsc not found")
|
||||
return 0
|
||||
|
||||
# Get INF Files
|
||||
INFFiles = self.WalkDirectoryForExtension([".inf"], abs_pkg_path)
|
||||
INFFiles = [Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(x) for x in INFFiles] # make edk2relative path so can compare with DSC
|
||||
INFFiles = [Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(
|
||||
x) for x in INFFiles] # make edk2relative path so can compare with DSC
|
||||
|
||||
# remove ignores
|
||||
|
||||
@@ -79,8 +83,10 @@ class DscCompleteCheck(ICiBuildPlugin):
|
||||
tc.LogStdOut("Ignoring INF {0}".format(a))
|
||||
INFFiles.remove(a)
|
||||
except:
|
||||
tc.LogStdError("DscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
logging.info("DscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
tc.LogStdError(
|
||||
"DscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
logging.info(
|
||||
"DscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
|
||||
# DSC Parser
|
||||
dp = DscParser()
|
||||
@@ -99,11 +105,19 @@ class DscCompleteCheck(ICiBuildPlugin):
|
||||
infp.SetPackagePaths(Edk2pathObj.PackagePathList)
|
||||
infp.ParseFile(INF)
|
||||
if("MODULE_TYPE" not in infp.Dict):
|
||||
tc.LogStdOut("Ignoring INF. Missing key for MODULE_TYPE {0}".format(INF))
|
||||
tc.LogStdOut(
|
||||
"Ignoring INF. Missing key for MODULE_TYPE {0}".format(INF))
|
||||
continue
|
||||
|
||||
if(infp.Dict["MODULE_TYPE"] == "HOST_APPLICATION"):
|
||||
tc.LogStdOut("Ignoring INF. Module type is HOST_APPLICATION {0}".format(INF))
|
||||
tc.LogStdOut(
|
||||
"Ignoring INF. Module type is HOST_APPLICATION {0}".format(INF))
|
||||
continue
|
||||
|
||||
if len(infp.SupportedPhases) == 1 and \
|
||||
"HOST_APPLICATION" in infp.SupportedPhases:
|
||||
tc.LogStdOut(
|
||||
"Ignoring Library INF due to only supporting type HOST_APPLICATION {0}".format(INF))
|
||||
continue
|
||||
|
||||
logging.critical(INF + " not in " + wsr_dsc_path)
|
||||
@@ -111,8 +125,9 @@ class DscCompleteCheck(ICiBuildPlugin):
|
||||
overall_status = overall_status + 1
|
||||
|
||||
# If XML object exists, add result
|
||||
if overall_status is not 0:
|
||||
tc.SetFailed("DscCompleteCheck {0} Failed. Errors {1}".format(wsr_dsc_path, overall_status), "CHECK_FAILED")
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("DscCompleteCheck {0} Failed. Errors {1}".format(
|
||||
wsr_dsc_path, overall_status), "CHECK_FAILED")
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
return overall_status
|
||||
|
@@ -7,6 +7,11 @@ that it would not be built if the package were built). This is critical because
|
||||
much of the CI infrastructure assumes that all modules will be listed in the DSC
|
||||
and compiled.
|
||||
|
||||
This test will ignore INFs in the following cases:
|
||||
|
||||
1. When MODULE_TYPE = HOST_APPLICATION
|
||||
2. When a Library instance **only** supports the HOST_APPLICATION environment
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin has a few configuration options to support the UEFI codebase.
|
||||
@@ -14,7 +19,7 @@ The plugin has a few configuration options to support the UEFI codebase.
|
||||
``` yaml
|
||||
"DscCompleteCheck": {
|
||||
"DscPath": "", # Path to dsc from root of package
|
||||
"IgnoreInf": [] # Ignore INF if found in filesystem by not dsc
|
||||
"IgnoreInf": [] # Ignore INF if found in filesystem but not dsc
|
||||
}
|
||||
```
|
||||
|
||||
|
309
.pytool/Plugin/EccCheck/EccCheck.py
Normal file
309
.pytool/Plugin/EccCheck/EccCheck.py
Normal file
@@ -0,0 +1,309 @@
|
||||
# @file EccCheck.py
|
||||
#
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
import csv
|
||||
import xml.dom.minidom
|
||||
from typing import List, Dict, Tuple
|
||||
import logging
|
||||
from io import StringIO
|
||||
from edk2toolext.environment import shell_environment
|
||||
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
|
||||
from edk2toolext.environment.var_dict import VarDict
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
|
||||
|
||||
class EccCheck(ICiBuildPlugin):
|
||||
"""
|
||||
A CiBuildPlugin that finds the Ecc issues of newly added code in pull request.
|
||||
|
||||
Configuration options:
|
||||
"EccCheck": {
|
||||
"ExceptionList": [],
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
"""
|
||||
|
||||
ReModifyFile = re.compile(r'[B-Q,S-Z]+[\d]*\t(.*)')
|
||||
FindModifyFile = re.compile(r'\+\+\+ b\/(.*)')
|
||||
LineScopePattern = (r'@@ -\d*\,*\d* \+\d*\,*\d* @@.*')
|
||||
LineNumRange = re.compile(r'@@ -\d*\,*\d* \+(\d*)\,*(\d*) @@.*')
|
||||
|
||||
def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
|
||||
""" Provide the testcase name and classname for use in reporting
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
a tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
"""
|
||||
return ("Check for efi coding style for " + packagename, packagename + ".EccCheck")
|
||||
|
||||
##
|
||||
# External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin
|
||||
#
|
||||
# - package is the edk2 path to package. This means workspace/packagepath relative.
|
||||
# - edk2path object configured with workspace and packages path
|
||||
# - PkgConfig Object (dict) for the pkg
|
||||
# - EnvConfig Object
|
||||
# - Plugin Manager Instance
|
||||
# - Plugin Helper Obj Instance
|
||||
# - Junit Logger
|
||||
# - output_stream the StringIO output stream from this plugin via logging
|
||||
def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
|
||||
edk2_path = Edk2pathObj.WorkspacePath
|
||||
python_path = os.path.join(edk2_path, "BaseTools", "Source", "Python")
|
||||
env = shell_environment.GetEnvironment()
|
||||
env.set_shell_var('PYTHONPATH', python_path)
|
||||
env.set_shell_var('WORKSPACE', edk2_path)
|
||||
self.ECC_PASS = True
|
||||
self.ApplyConfig(pkgconfig, edk2_path, packagename)
|
||||
modify_dir_list = self.GetModifyDir(packagename)
|
||||
patch = self.GetDiff(packagename)
|
||||
ecc_diff_range = self.GetDiffRange(patch, packagename, edk2_path)
|
||||
self.GenerateEccReport(modify_dir_list, ecc_diff_range, edk2_path)
|
||||
ecc_log = os.path.join(edk2_path, "Ecc.log")
|
||||
self.RevertCode()
|
||||
if self.ECC_PASS:
|
||||
tc.SetSuccess()
|
||||
self.RemoveFile(ecc_log)
|
||||
return 0
|
||||
else:
|
||||
with open(ecc_log, encoding='utf8') as output:
|
||||
ecc_output = output.readlines()
|
||||
for line in ecc_output:
|
||||
logging.error(line.strip())
|
||||
self.RemoveFile(ecc_log)
|
||||
tc.SetFailed("EccCheck failed for {0}".format(packagename), "Ecc detected issues")
|
||||
return 1
|
||||
|
||||
def RevertCode(self) -> None:
|
||||
submoudle_params = "submodule update --init"
|
||||
RunCmd("git", submoudle_params)
|
||||
reset_params = "reset HEAD --hard"
|
||||
RunCmd("git", reset_params)
|
||||
|
||||
def GetDiff(self, pkg: str) -> List[str]:
|
||||
return_buffer = StringIO()
|
||||
params = "diff --unified=0 origin/master HEAD"
|
||||
RunCmd("git", params, outstream=return_buffer)
|
||||
p = return_buffer.getvalue().strip()
|
||||
patch = p.split("\n")
|
||||
return_buffer.close()
|
||||
|
||||
return patch
|
||||
|
||||
def RemoveFile(self, file: str) -> None:
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
return
|
||||
|
||||
def GetModifyDir(self, pkg: str) -> List[str]:
|
||||
return_buffer = StringIO()
|
||||
params = "diff --name-status" + ' HEAD' + ' origin/master'
|
||||
RunCmd("git", params, outstream=return_buffer)
|
||||
p1 = return_buffer.getvalue().strip()
|
||||
dir_list = p1.split("\n")
|
||||
return_buffer.close()
|
||||
modify_dir_list = []
|
||||
for modify_dir in dir_list:
|
||||
file_path = self.ReModifyFile.findall(modify_dir)
|
||||
if file_path:
|
||||
file_dir = os.path.dirname(file_path[0])
|
||||
else:
|
||||
continue
|
||||
if pkg in file_dir and file_dir != pkg:
|
||||
modify_dir_list.append('%s' % file_dir)
|
||||
else:
|
||||
continue
|
||||
|
||||
modify_dir_list = list(set(modify_dir_list))
|
||||
return modify_dir_list
|
||||
|
||||
def GetDiffRange(self, patch_diff: List[str], pkg: str, workingdir: str) -> Dict[str, List[Tuple[int, int]]]:
|
||||
IsDelete = True
|
||||
StartCheck = False
|
||||
range_directory: Dict[str, List[Tuple[int, int]]] = {}
|
||||
for line in patch_diff:
|
||||
modify_file = self.FindModifyFile.findall(line)
|
||||
if modify_file and pkg in modify_file[0] and not StartCheck and os.path.isfile(modify_file[0]):
|
||||
modify_file_comment_dic = self.GetCommentRange(modify_file[0], workingdir)
|
||||
IsDelete = False
|
||||
StartCheck = True
|
||||
modify_file_dic = modify_file[0]
|
||||
modify_file_dic = modify_file_dic.replace("/", os.sep)
|
||||
range_directory[modify_file_dic] = []
|
||||
elif line.startswith('--- '):
|
||||
StartCheck = False
|
||||
elif re.match(self.LineScopePattern, line, re.I) and not IsDelete and StartCheck:
|
||||
start_line = self.LineNumRange.search(line).group(1)
|
||||
line_range = self.LineNumRange.search(line).group(2)
|
||||
if not line_range:
|
||||
line_range = '1'
|
||||
range_directory[modify_file_dic].append((int(start_line), int(start_line) + int(line_range) - 1))
|
||||
for i in modify_file_comment_dic:
|
||||
if int(i[0]) <= int(start_line) <= int(i[1]):
|
||||
range_directory[modify_file_dic].append(i)
|
||||
return range_directory
|
||||
|
||||
def GetCommentRange(self, modify_file: str, workingdir: str) -> List[Tuple[int, int]]:
|
||||
modify_file_path = os.path.join(workingdir, modify_file)
|
||||
with open(modify_file_path) as f:
|
||||
line_no = 1
|
||||
comment_range: List[Tuple[int, int]] = []
|
||||
Start = False
|
||||
for line in f:
|
||||
if line.startswith('/**'):
|
||||
start_no = line_no
|
||||
Start = True
|
||||
if line.startswith('**/') and Start:
|
||||
end_no = line_no
|
||||
Start = False
|
||||
comment_range.append((int(start_no), int(end_no)))
|
||||
line_no += 1
|
||||
|
||||
if comment_range and comment_range[0][0] == 1:
|
||||
del comment_range[0]
|
||||
return comment_range
|
||||
|
||||
def GenerateEccReport(self, modify_dir_list: List[str], ecc_diff_range: Dict[str, List[Tuple[int, int]]],
|
||||
edk2_path: str) -> None:
|
||||
ecc_need = False
|
||||
ecc_run = True
|
||||
config = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "config.ini")
|
||||
exception = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "exception.xml")
|
||||
report = os.path.join(edk2_path, "Ecc.csv")
|
||||
for modify_dir in modify_dir_list:
|
||||
target = os.path.join(edk2_path, modify_dir)
|
||||
logging.info('Run ECC tool for the commit in %s' % modify_dir)
|
||||
ecc_need = True
|
||||
ecc_params = "-c {0} -e {1} -t {2} -r {3}".format(config, exception, target, report)
|
||||
return_code = RunCmd("Ecc", ecc_params, workingdir=edk2_path)
|
||||
if return_code != 0:
|
||||
ecc_run = False
|
||||
break
|
||||
if not ecc_run:
|
||||
logging.error('Fail to run ECC tool')
|
||||
self.ParseEccReport(ecc_diff_range, edk2_path)
|
||||
|
||||
if not ecc_need:
|
||||
logging.info("Doesn't need run ECC check")
|
||||
|
||||
revert_params = "checkout -- {}".format(exception)
|
||||
RunCmd("git", revert_params)
|
||||
return
|
||||
|
||||
def ParseEccReport(self, ecc_diff_range: Dict[str, List[Tuple[int, int]]], edk2_path: str) -> None:
|
||||
ecc_log = os.path.join(edk2_path, "Ecc.log")
|
||||
ecc_csv = "Ecc.csv"
|
||||
file = os.listdir(edk2_path)
|
||||
row_lines = []
|
||||
ignore_error_code = self.GetIgnoreErrorCode()
|
||||
if ecc_csv in file:
|
||||
with open(ecc_csv) as csv_file:
|
||||
reader = csv.reader(csv_file)
|
||||
for row in reader:
|
||||
for modify_file in ecc_diff_range:
|
||||
if modify_file in row[3]:
|
||||
for i in ecc_diff_range[modify_file]:
|
||||
line_no = int(row[4])
|
||||
if i[0] <= line_no <= i[1] and row[1] not in ignore_error_code:
|
||||
row[0] = '\nEFI coding style error'
|
||||
row[1] = 'Error code: ' + row[1]
|
||||
row[3] = 'file: ' + row[3]
|
||||
row[4] = 'Line number: ' + row[4]
|
||||
row_line = '\n *'.join(row)
|
||||
row_lines.append(row_line)
|
||||
break
|
||||
break
|
||||
if row_lines:
|
||||
self.ECC_PASS = False
|
||||
|
||||
with open(ecc_log, 'a') as log:
|
||||
all_line = '\n'.join(row_lines)
|
||||
all_line = all_line + '\n'
|
||||
log.writelines(all_line)
|
||||
return
|
||||
|
||||
def ApplyConfig(self, pkgconfig: Dict[str, List[str]], edk2_path: str, pkg: str) -> None:
|
||||
if "IgnoreFiles" in pkgconfig:
|
||||
for a in pkgconfig["IgnoreFiles"]:
|
||||
a = os.path.join(edk2_path, pkg, a)
|
||||
a = a.replace(os.sep, "/")
|
||||
|
||||
logging.info("Ignoring Files {0}".format(a))
|
||||
if os.path.exists(a):
|
||||
if os.path.isfile(a):
|
||||
self.RemoveFile(a)
|
||||
elif os.path.isdir(a):
|
||||
shutil.rmtree(a)
|
||||
else:
|
||||
logging.error("EccCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore files".format(a))
|
||||
|
||||
if "ExceptionList" in pkgconfig:
|
||||
exception_list = pkgconfig["ExceptionList"]
|
||||
exception_xml = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "exception.xml")
|
||||
try:
|
||||
logging.info("Appending exceptions")
|
||||
self.AppendException(exception_list, exception_xml)
|
||||
except Exception as e:
|
||||
logging.error("Fail to apply exceptions")
|
||||
raise e
|
||||
return
|
||||
|
||||
def AppendException(self, exception_list: List[str], exception_xml: str) -> None:
|
||||
error_code_list = exception_list[::2]
|
||||
keyword_list = exception_list[1::2]
|
||||
dom_tree = xml.dom.minidom.parse(exception_xml)
|
||||
root_node = dom_tree.documentElement
|
||||
for error_code, keyword in zip(error_code_list, keyword_list):
|
||||
customer_node = dom_tree.createElement("Exception")
|
||||
keyword_node = dom_tree.createElement("KeyWord")
|
||||
keyword_node_text_value = dom_tree.createTextNode(keyword)
|
||||
keyword_node.appendChild(keyword_node_text_value)
|
||||
customer_node.appendChild(keyword_node)
|
||||
error_code_node = dom_tree.createElement("ErrorID")
|
||||
error_code_text_value = dom_tree.createTextNode(error_code)
|
||||
error_code_node.appendChild(error_code_text_value)
|
||||
customer_node.appendChild(error_code_node)
|
||||
root_node.appendChild(customer_node)
|
||||
with open(exception_xml, 'w') as f:
|
||||
dom_tree.writexml(f, indent='', addindent='', newl='\n', encoding='UTF-8')
|
||||
return
|
||||
|
||||
def GetIgnoreErrorCode(self) -> set:
|
||||
"""
|
||||
Below are kinds of error code that are accurate in ecc scanning of edk2 level.
|
||||
But EccCheck plugin is partial scanning so they are always false positive issues.
|
||||
The mapping relationship of error code and error message is listed BaseTools/Sourc/Python/Ecc/EccToolError.py
|
||||
"""
|
||||
ignore_error_code = {
|
||||
"10000",
|
||||
"10001",
|
||||
"10002",
|
||||
"10003",
|
||||
"10004",
|
||||
"10005",
|
||||
"10006",
|
||||
"10007",
|
||||
"10008",
|
||||
"10009",
|
||||
"10010",
|
||||
"10011",
|
||||
"10012",
|
||||
"10013",
|
||||
"10015",
|
||||
"10016",
|
||||
"10017",
|
||||
"10022",
|
||||
}
|
||||
return ignore_error_code
|
11
.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml
Normal file
11
.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
## @file
|
||||
# CiBuildPlugin used to check Ecc issues
|
||||
#
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
"scope": "cibuild",
|
||||
"name": "EccCheck Test",
|
||||
"module": "EccCheck"
|
||||
}
|
15
.pytool/Plugin/EccCheck/Readme.md
Normal file
15
.pytool/Plugin/EccCheck/Readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# EFI Coding style Check Plugin
|
||||
|
||||
This CiBuildPlugin finds the Ecc issues of newly added code in pull request.
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin can be configured to ignore certain files and issues.
|
||||
|
||||
"EccCheck": {
|
||||
"ExceptionList": [],
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
"""
|
||||
|
||||
OPTIONAL List of file to ignore.
|
@@ -221,7 +221,7 @@ class GuidCheck(ICiBuildPlugin):
|
||||
|
||||
# add result to test case
|
||||
overall_status = len(Errors)
|
||||
if overall_status is not 0:
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("GuidCheck {0} Failed. Errors {1}".format(
|
||||
packagename, overall_status), "CHECK_FAILED")
|
||||
else:
|
||||
|
@@ -0,0 +1,149 @@
|
||||
# @file HostUnitTestCompilerPlugin.py
|
||||
##
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from edk2toollib.uefi.edk2.parsers.dsc_parser import DscParser
|
||||
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
|
||||
from edk2toolext.environment.uefi_build import UefiBuilder
|
||||
from edk2toolext import edk2_logging
|
||||
from edk2toolext.environment.var_dict import VarDict
|
||||
from edk2toollib.utility_functions import GetHostInfo
|
||||
|
||||
|
||||
class HostUnitTestCompilerPlugin(ICiBuildPlugin):
|
||||
"""
|
||||
A CiBuildPlugin that compiles the dsc for host based unit test apps.
|
||||
An IUefiBuildPlugin may be attached to this plugin that will run the
|
||||
unit tests and collect the results after successful compilation.
|
||||
|
||||
Configuration options:
|
||||
"HostUnitTestCompilerPlugin": {
|
||||
"DscPath": "<path to dsc from root of pkg>"
|
||||
}
|
||||
"""
|
||||
|
||||
def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
|
||||
""" Provide the testcase name and classname for use in reporting
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
a tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
"""
|
||||
num,types = self.__GetHostUnitTestArch(environment)
|
||||
types = types.replace(" ", "_")
|
||||
|
||||
return ("Compile and Run Host-Based UnitTests for " + packagename + " on arch " + types,
|
||||
packagename + ".HostUnitTestCompiler." + types)
|
||||
|
||||
def RunsOnTargetList(self):
|
||||
return ["NOOPT"]
|
||||
|
||||
#
|
||||
# Find the intersection of application types that can run on this host
|
||||
# and the TARGET_ARCH being build in this request.
|
||||
#
|
||||
# return tuple with (number of UEFI arch types, space separated string)
|
||||
def __GetHostUnitTestArch(self, environment):
|
||||
requested = environment.GetValue("TARGET_ARCH").split(' ')
|
||||
host = []
|
||||
if GetHostInfo().arch == 'x86':
|
||||
#assume 64bit can handle 64 and 32
|
||||
#assume 32bit can only handle 32
|
||||
## change once IA32 issues resolved host.append("IA32")
|
||||
if GetHostInfo().bit == '64':
|
||||
host.append("X64")
|
||||
elif GetHostInfo().arch == 'ARM':
|
||||
if GetHostInfo().bit == '64':
|
||||
host.append("AARCH64")
|
||||
elif GetHostInfo().bit == '32':
|
||||
host.append("ARM")
|
||||
|
||||
willrun = set(requested) & set(host)
|
||||
return (len(willrun), " ".join(willrun))
|
||||
|
||||
|
||||
##
|
||||
# External function of plugin. This function is used to perform the task of the ICiBuildPlugin Plugin
|
||||
#
|
||||
# - package is the edk2 path to package. This means workspace/packagepath relative.
|
||||
# - edk2path object configured with workspace and packages path
|
||||
# - PkgConfig Object (dict) for the pkg
|
||||
# - EnvConfig Object
|
||||
# - Plugin Manager Instance
|
||||
# - Plugin Helper Obj Instance
|
||||
# - Junit Logger
|
||||
# - output_stream the StringIO output stream from this plugin via logging
|
||||
def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
|
||||
self._env = environment
|
||||
environment.SetValue("CI_BUILD_TYPE", "host_unit_test", "Set in HostUnitTestCompilerPlugin")
|
||||
|
||||
# Parse the config for required DscPath element
|
||||
if "DscPath" not in pkgconfig:
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("DscPath not found in config file. Nothing to compile for HostBasedUnitTests.")
|
||||
return -1
|
||||
|
||||
AP = Edk2pathObj.GetAbsolutePathOnThisSytemFromEdk2RelativePath(packagename)
|
||||
|
||||
APDSC = os.path.join(AP, pkgconfig["DscPath"].strip())
|
||||
AP_Path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(APDSC)
|
||||
if AP is None or AP_Path is None or not os.path.isfile(APDSC):
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("Package HostBasedUnitTest Dsc not found.")
|
||||
return -1
|
||||
|
||||
logging.info("Building {0}".format(AP_Path))
|
||||
self._env.SetValue("ACTIVE_PLATFORM", AP_Path, "Set in Compiler Plugin")
|
||||
num, RUNNABLE_ARCHITECTURES = self.__GetHostUnitTestArch(environment)
|
||||
if(num == 0):
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("No host architecture compatibility")
|
||||
return -1
|
||||
|
||||
if not environment.SetValue("TARGET_ARCH",
|
||||
RUNNABLE_ARCHITECTURES,
|
||||
"Update Target Arch based on Host Support"):
|
||||
#use AllowOverride function since this is a controlled attempt to change
|
||||
environment.AllowOverride("TARGET_ARCH")
|
||||
if not environment.SetValue("TARGET_ARCH",
|
||||
RUNNABLE_ARCHITECTURES,
|
||||
"Update Target Arch based on Host Support"):
|
||||
raise RuntimeError("Can't Change TARGET_ARCH as required")
|
||||
|
||||
# Parse DSC to check for SUPPORTED_ARCHITECTURES
|
||||
dp = DscParser()
|
||||
dp.SetBaseAbsPath(Edk2pathObj.WorkspacePath)
|
||||
dp.SetPackagePaths(Edk2pathObj.PackagePathList)
|
||||
dp.ParseFile(AP_Path)
|
||||
if "SUPPORTED_ARCHITECTURES" in dp.LocalVars:
|
||||
SUPPORTED_ARCHITECTURES = dp.LocalVars["SUPPORTED_ARCHITECTURES"].split('|')
|
||||
TARGET_ARCHITECTURES = environment.GetValue("TARGET_ARCH").split(' ')
|
||||
|
||||
# Skip if there is no intersection between SUPPORTED_ARCHITECTURES and TARGET_ARCHITECTURES
|
||||
if len(set(SUPPORTED_ARCHITECTURES) & set(TARGET_ARCHITECTURES)) == 0:
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("No supported architecutres to build for host unit tests")
|
||||
return -1
|
||||
|
||||
uefiBuilder = UefiBuilder()
|
||||
# do all the steps
|
||||
# WorkSpace, PackagesPath, PInHelper, PInManager
|
||||
ret = uefiBuilder.Go(Edk2pathObj.WorkspacePath, os.pathsep.join(Edk2pathObj.PackagePathList), PLMHelper, PLM)
|
||||
if ret != 0: # failure:
|
||||
tc.SetFailed("Compile failed for {0}".format(packagename), "Compile_FAILED")
|
||||
tc.LogStdError("{0} Compile failed with error code {1} ".format(AP_Path, ret))
|
||||
return 1
|
||||
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
return 0
|
@@ -0,0 +1,12 @@
|
||||
##
|
||||
# CiBuildPlugin used to build anything that identifies
|
||||
# as a unit test.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
"scope": "host-based-test",
|
||||
"name": "Host Unit Test Compiler Plugin",
|
||||
"module": "HostUnitTestCompilerPlugin"
|
||||
}
|
24
.pytool/Plugin/HostUnitTestCompilerPlugin/Readme.md
Normal file
24
.pytool/Plugin/HostUnitTestCompilerPlugin/Readme.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Host UnitTest Compiler Plugin
|
||||
|
||||
A CiBuildPlugin that compiles the dsc for host based unit test apps.
|
||||
An IUefiBuildPlugin may be attached to this plugin that will run the unit tests and collect the results after successful compilation.
|
||||
|
||||
## Configuration
|
||||
|
||||
The package relative path of the DSC file to build.
|
||||
|
||||
``` yaml
|
||||
"HostUnitTestCompilerPlugin": {
|
||||
"DscPath": "<path to dsc from root of pkg>"
|
||||
}
|
||||
```
|
||||
|
||||
### DscPath
|
||||
|
||||
Package relative path to the DSC file to build.
|
||||
|
||||
## Copyright
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
@@ -0,0 +1,140 @@
|
||||
# @file HostUnitTestDscCompleteCheck.py
|
||||
#
|
||||
# This is a copy of DscCompleteCheck with different filtering logic.
|
||||
# It should be discussed if this should be one plugin
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
import logging
|
||||
import os
|
||||
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
|
||||
from edk2toollib.uefi.edk2.parsers.dsc_parser import DscParser
|
||||
from edk2toollib.uefi.edk2.parsers.inf_parser import InfParser
|
||||
from edk2toolext.environment.var_dict import VarDict
|
||||
|
||||
|
||||
class HostUnitTestDscCompleteCheck(ICiBuildPlugin):
|
||||
"""
|
||||
A CiBuildPlugin that scans the package Host Unit Test dsc file and confirms all Host application modules (inf files) are
|
||||
listed in the components sections.
|
||||
|
||||
Configuration options:
|
||||
"HostUnitTestDscCompleteCheck": {
|
||||
"DscPath": "", # Path to Host based unit test DSC file
|
||||
"IgnoreInf": [] # Ignore INF if found in filesystem but not dsc
|
||||
}
|
||||
"""
|
||||
|
||||
def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
|
||||
""" Provide the testcase name and classname for use in reporting
|
||||
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
a tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
"""
|
||||
return ("Check the " + packagename + " Host Unit Test DSC for a being complete", packagename + ".HostUnitTestDscCompleteCheck")
|
||||
|
||||
##
|
||||
# External function of plugin. This function is used to perform the task of the MuBuild Plugin
|
||||
#
|
||||
# - package is the edk2 path to package. This means workspace/packagepath relative.
|
||||
# - edk2path object configured with workspace and packages path
|
||||
# - PkgConfig Object (dict) for the pkg
|
||||
# - VarDict containing the shell environment Build Vars
|
||||
# - Plugin Manager Instance
|
||||
# - Plugin Helper Obj Instance
|
||||
# - Junit Logger
|
||||
# - output_stream the StringIO output stream from this plugin via logging
|
||||
def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
|
||||
overall_status = 0
|
||||
|
||||
# Parse the config for required DscPath element
|
||||
if "DscPath" not in pkgconfig:
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError(
|
||||
"DscPath not found in config file. Nothing to check.")
|
||||
return -1
|
||||
|
||||
abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSytemFromEdk2RelativePath(
|
||||
packagename)
|
||||
abs_dsc_path = os.path.join(abs_pkg_path, pkgconfig["DscPath"].strip())
|
||||
wsr_dsc_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(
|
||||
abs_dsc_path)
|
||||
|
||||
if abs_dsc_path is None or wsr_dsc_path == "" or not os.path.isfile(abs_dsc_path):
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("Package Host Unit Test Dsc not found")
|
||||
return 0
|
||||
|
||||
# Get INF Files
|
||||
INFFiles = self.WalkDirectoryForExtension([".inf"], abs_pkg_path)
|
||||
INFFiles = [Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(
|
||||
x) for x in INFFiles] # make edk2relative path so can compare with DSC
|
||||
|
||||
# remove ignores
|
||||
|
||||
if "IgnoreInf" in pkgconfig:
|
||||
for a in pkgconfig["IgnoreInf"]:
|
||||
a = a.replace(os.sep, "/")
|
||||
try:
|
||||
tc.LogStdOut("Ignoring INF {0}".format(a))
|
||||
INFFiles.remove(a)
|
||||
except:
|
||||
tc.LogStdError(
|
||||
"HostUnitTestDscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
logging.info(
|
||||
"HostUnitTestDscCompleteCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore file".format(a))
|
||||
|
||||
# DSC Parser
|
||||
dp = DscParser()
|
||||
dp.SetBaseAbsPath(Edk2pathObj.WorkspacePath)
|
||||
dp.SetPackagePaths(Edk2pathObj.PackagePathList)
|
||||
dp.SetInputVars(environment.GetAllBuildKeyValues())
|
||||
dp.ParseFile(wsr_dsc_path)
|
||||
|
||||
# Check if INF in component section
|
||||
for INF in INFFiles:
|
||||
if not any(INF.strip() in x for x in dp.ThreeMods) and \
|
||||
not any(INF.strip() in x for x in dp.SixMods) and \
|
||||
not any(INF.strip() in x for x in dp.OtherMods):
|
||||
|
||||
infp = InfParser().SetBaseAbsPath(Edk2pathObj.WorkspacePath)
|
||||
infp.SetPackagePaths(Edk2pathObj.PackagePathList)
|
||||
infp.ParseFile(INF)
|
||||
if("MODULE_TYPE" not in infp.Dict):
|
||||
tc.LogStdOut(
|
||||
"Ignoring INF. Missing key for MODULE_TYPE {0}".format(INF))
|
||||
continue
|
||||
|
||||
if(infp.Dict["MODULE_TYPE"] == "HOST_APPLICATION"):
|
||||
# should compile test a library that is declared type HOST_APPLICATION
|
||||
pass
|
||||
|
||||
elif len(infp.SupportedPhases) > 0 and \
|
||||
"HOST_APPLICATION" in infp.SupportedPhases:
|
||||
# should compile test a library that supports HOST_APPLICATION but
|
||||
# require it to be an explicit opt-in
|
||||
pass
|
||||
|
||||
else:
|
||||
tc.LogStdOut(
|
||||
"Ignoring INF. MODULE_TYPE or suppored phases not HOST_APPLICATION {0}".format(INF))
|
||||
continue
|
||||
|
||||
logging.critical(INF + " not in " + wsr_dsc_path)
|
||||
tc.LogStdError("{0} not in {1}".format(INF, wsr_dsc_path))
|
||||
overall_status = overall_status + 1
|
||||
|
||||
# If XML object exists, add result
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("HostUnitTestDscCompleteCheck {0} Failed. Errors {1}".format(
|
||||
wsr_dsc_path, overall_status), "CHECK_FAILED")
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
return overall_status
|
@@ -0,0 +1,12 @@
|
||||
##
|
||||
# CiBuildPlugin used to confirm all INFs are listed in
|
||||
# the components section of package dsc
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
"scope": "host-based-test",
|
||||
"name": "Host Unit Test Dsc Complete Check Test",
|
||||
"module": "HostUnitTestDscCompleteCheck"
|
||||
}
|
32
.pytool/Plugin/HostUnitTestDscCompleteCheck/Readme.md
Normal file
32
.pytool/Plugin/HostUnitTestDscCompleteCheck/Readme.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Host Unit Test Dsc Complete Check Plugin
|
||||
|
||||
This CiBuildPlugin scans all INF files from a package for those related to host
|
||||
based unit tests confirms they are listed in the unit test DSC file for the package.
|
||||
The test considers it an error if any INF meeting the requirements does not appear
|
||||
in the `Components` section of the unit test DSC. This is critical because
|
||||
much of the CI infrastructure assumes that modules will be listed in the DSC
|
||||
and compiled.
|
||||
|
||||
This test will only require INFs in the following cases:
|
||||
|
||||
1. When MODULE_TYPE = HOST_APPLICATION
|
||||
2. When a Library instance supports the HOST_APPLICATION environment
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin has a few configuration options to support the UEFI codebase.
|
||||
|
||||
``` yaml
|
||||
"HostUnitTestDscCompleteCheck": {
|
||||
"DscPath": "", # Path to Host based unit test DSC file
|
||||
"IgnoreInf": [] # Ignore INF if found in filesystem but not dsc
|
||||
}
|
||||
```
|
||||
|
||||
### DscPath
|
||||
|
||||
Path to DSC to consider platform dsc
|
||||
|
||||
### IgnoreInf
|
||||
|
||||
Ignore error if Inf file is not listed in DSC file
|
@@ -67,7 +67,7 @@ class LibraryClassCheck(ICiBuildPlugin):
|
||||
abs_dec_path = self.__GetPkgDec(abs_pkg_path)
|
||||
wsr_dec_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(abs_dec_path)
|
||||
|
||||
if abs_dec_path is None or wsr_dec_path is "" or not os.path.isfile(abs_dec_path):
|
||||
if abs_dec_path is None or wsr_dec_path == "" or not os.path.isfile(abs_dec_path):
|
||||
tc.SetSkipped()
|
||||
tc.LogStdError("No DEC file {0} in package {1}".format(abs_dec_path, abs_pkg_path))
|
||||
return -1
|
||||
@@ -146,7 +146,7 @@ class LibraryClassCheck(ICiBuildPlugin):
|
||||
|
||||
|
||||
# If XML object exists, add result
|
||||
if overall_status is not 0:
|
||||
if overall_status != 0:
|
||||
tc.SetFailed("LibraryClassCheck {0} Failed. Errors {1}".format(wsr_dec_path, overall_status), "CHECK_FAILED")
|
||||
else:
|
||||
tc.SetSuccess()
|
||||
|
115
.pytool/Plugin/LicenseCheck/LicenseCheck.py
Normal file
115
.pytool/Plugin/LicenseCheck/LicenseCheck.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# @file LicenseCheck.py
|
||||
#
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import os
|
||||
import logging
|
||||
import re
|
||||
from io import StringIO
|
||||
from typing import List, Tuple
|
||||
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
|
||||
from edk2toolext.environment.var_dict import VarDict
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
|
||||
|
||||
class LicenseCheck(ICiBuildPlugin):
|
||||
|
||||
"""
|
||||
A CiBuildPlugin to check the license for new added files.
|
||||
|
||||
Configuration options:
|
||||
"LicenseCheck": {
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
"""
|
||||
|
||||
license_format_preflix = 'SPDX-License-Identifier'
|
||||
|
||||
bsd2_patent = 'BSD-2-Clause-Patent'
|
||||
|
||||
Readdedfileformat = re.compile(r'\+\+\+ b\/(.*)')
|
||||
|
||||
file_extension_list = [".c", ".h", ".inf", ".dsc", ".dec", ".py", ".bat", ".sh", ".uni", ".yaml",
|
||||
".fdf", ".inc", "yml", ".asm", ".asm16", ".asl", ".vfr", ".s", ".S", ".aslc",
|
||||
".nasm", ".nasmb", ".idf", ".Vfr", ".H"]
|
||||
|
||||
def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
|
||||
""" Provide the testcase name and classname for use in reporting
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
a tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
"""
|
||||
return ("Check for license for " + packagename, packagename + ".LicenseCheck")
|
||||
|
||||
##
|
||||
# External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin
|
||||
#
|
||||
# - package is the edk2 path to package. This means workspace/packagepath relative.
|
||||
# - edk2path object configured with workspace and packages path
|
||||
# - PkgConfig Object (dict) for the pkg
|
||||
# - EnvConfig Object
|
||||
# - Plugin Manager Instance
|
||||
# - Plugin Helper Obj Instance
|
||||
# - Junit Logger
|
||||
# - output_stream the StringIO output stream from this plugin via logging
|
||||
def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
|
||||
return_buffer = StringIO()
|
||||
params = "diff --unified=0 origin/master HEAD"
|
||||
RunCmd("git", params, outstream=return_buffer)
|
||||
p = return_buffer.getvalue().strip()
|
||||
patch = p.split("\n")
|
||||
return_buffer.close()
|
||||
|
||||
ignore_files = []
|
||||
if "IgnoreFiles" in pkgconfig:
|
||||
ignore_files = pkgconfig["IgnoreFiles"]
|
||||
|
||||
self.ok = True
|
||||
self.startcheck = False
|
||||
self.license = True
|
||||
self.all_file_pass = True
|
||||
count = len(patch)
|
||||
line_index = 0
|
||||
for line in patch:
|
||||
if line.startswith('--- /dev/null'):
|
||||
nextline = patch[line_index + 1]
|
||||
added_file = self.Readdedfileformat.search(nextline).group(1)
|
||||
added_file_extension = os.path.splitext(added_file)[1]
|
||||
if added_file_extension in self.file_extension_list and packagename in added_file:
|
||||
if (self.IsIgnoreFile(added_file, ignore_files)):
|
||||
line_index = line_index + 1
|
||||
continue
|
||||
self.startcheck = True
|
||||
self.license = False
|
||||
if self.startcheck and self.license_format_preflix in line:
|
||||
if self.bsd2_patent in line:
|
||||
self.license = True
|
||||
if line_index + 1 == count or patch[line_index + 1].startswith('diff --') and self.startcheck:
|
||||
if not self.license:
|
||||
self.all_file_pass = False
|
||||
error_message = "Invalid license in: " + added_file + " Hint: Only BSD-2-Clause-Patent is accepted."
|
||||
logging.error(error_message)
|
||||
self.startcheck = False
|
||||
self.license = True
|
||||
line_index = line_index + 1
|
||||
|
||||
if self.all_file_pass:
|
||||
tc.SetSuccess()
|
||||
return 0
|
||||
else:
|
||||
tc.SetFailed("License Check {0} Failed. ".format(packagename), "LICENSE_CHECK_FAILED")
|
||||
return 1
|
||||
|
||||
def IsIgnoreFile(self, file: str, ignore_files: List[str]) -> bool:
|
||||
for f in ignore_files:
|
||||
if f in file:
|
||||
return True
|
||||
return False
|
11
.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml
Normal file
11
.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
## @file
|
||||
# CiBuildPlugin used to check license issues for new added files
|
||||
#
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
"scope": "cibuild",
|
||||
"name": "License Check Test",
|
||||
"module": "LicenseCheck"
|
||||
}
|
17
.pytool/Plugin/LicenseCheck/Readme.md
Normal file
17
.pytool/Plugin/LicenseCheck/Readme.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# License Check Plugin
|
||||
|
||||
This CiBuildPlugin scans all new added files in a package to make sure code
|
||||
is contributed under BSD-2-Clause-Patent.
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin can be configured to ignore certain files.
|
||||
|
||||
``` yaml
|
||||
"LicenseCheck": {
|
||||
"IgnoreFiles": []
|
||||
}
|
||||
```
|
||||
### IgnoreFiles
|
||||
|
||||
OPTIONAL List of file to ignore.
|
@@ -22,6 +22,8 @@
|
||||
],
|
||||
"minWordLength": 5,
|
||||
"allowCompoundWords": false,
|
||||
"maxNumberOfProblems": 200,
|
||||
"maxDuplicateProblems": 200,
|
||||
"ignoreWords": [
|
||||
"muchange"
|
||||
],
|
||||
@@ -161,5 +163,20 @@
|
||||
"bootability",
|
||||
"Sdhci",
|
||||
"inmodule",
|
||||
"RISCV",
|
||||
"edksetup",
|
||||
"iscsi",
|
||||
"nvdata",
|
||||
"pytools",
|
||||
"NTDDI",
|
||||
"Wnonportable",
|
||||
"CLANGPDB",
|
||||
"nologo",
|
||||
"lldmap",
|
||||
"ASMLINK",
|
||||
"NODEFAULTLIB",
|
||||
"vcruntimed",
|
||||
"ucrtd",
|
||||
"msvcrtd",
|
||||
]
|
||||
}
|
||||
|
@@ -2,31 +2,32 @@
|
||||
|
||||
## Basic Status
|
||||
|
||||
| Package | Windows VS2019 (IA32/X64)| Ubuntu GCC (IA32/X64/ARM/AARCH64) | Known Issues |
|
||||
| :---- | :----- | :---- | :--- |
|
||||
| ArmPkg |
|
||||
| ArmPlatformPkg |
|
||||
| ArmVirtPkg |
|
||||
| CryptoPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| DynamicTablesPkg |
|
||||
| EmbeddedPkg |
|
||||
| EmulatorPkg |
|
||||
| FatPkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| FmpDevicePkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| IntelFsp2Pkg |
|
||||
| IntelFsp2WrapperPkg |
|
||||
| MdeModulePkg | :heavy_check_mark: | :heavy_check_mark: | DxeIpl dependency on ArmPkg, Depends on StandaloneMmPkg, Spell checking in audit mode
|
||||
| MdePkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| NetworkPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| OvmfPkg |
|
||||
| PcAtChipsetPkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| SecurityPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| ShellPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 3 modules are not being built by DSC
|
||||
| SignedCapsulePkg |
|
||||
| SourceLevelDebugPkg |
|
||||
| StandaloneMmPkg |
|
||||
| UefiCpuPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 2 binary modules not being built by DSC
|
||||
| UefiPayloadPkg |
|
||||
| Package | Windows VS2019 (IA32/X64)| Ubuntu GCC (IA32/X64/ARM/AARCH64) | Known Issues |
|
||||
| :---- | :----- | :---- | :--- |
|
||||
| ArmPkg |
|
||||
| ArmPlatformPkg |
|
||||
| ArmVirtPkg | SEE PACKAGE README | SEE PACKAGE README |
|
||||
| CryptoPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| DynamicTablesPkg | | :heavy_check_mark: |
|
||||
| EmbeddedPkg |
|
||||
| EmulatorPkg | SEE PACKAGE README | SEE PACKAGE README | Spell checking in audit mode
|
||||
| FatPkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| FmpDevicePkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| IntelFsp2Pkg |
|
||||
| IntelFsp2WrapperPkg |
|
||||
| MdeModulePkg | :heavy_check_mark: | :heavy_check_mark: | DxeIpl dependency on ArmPkg, Depends on StandaloneMmPkg, Spell checking in audit mode
|
||||
| MdePkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| NetworkPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| OvmfPkg | SEE PACKAGE README | SEE PACKAGE README | Spell checking in audit mode
|
||||
| PcAtChipsetPkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| SecurityPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
|
||||
| ShellPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 3 modules are not being built by DSC
|
||||
| SignedCapsulePkg |
|
||||
| SourceLevelDebugPkg |
|
||||
| StandaloneMmPkg |
|
||||
| UefiCpuPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 2 binary modules not being built by DSC
|
||||
| UefiPayloadPkg |
|
||||
| UnitTestFrameworkPkg | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|
||||
For more detailed status look at the test results of the latest CI run on the
|
||||
repo readme.
|
||||
@@ -77,7 +78,7 @@ per package configuration which comes from this file.
|
||||
## Running CI locally
|
||||
|
||||
The EDKII Tools environment (and by extension the ci) is designed to support
|
||||
easily and consistantly running locally and in a cloud ci environment. To do
|
||||
easily and consistently running locally and in a cloud ci environment. To do
|
||||
that a few steps should be followed. Details of EDKII Tools can be found in the
|
||||
[docs folder here](https://github.com/tianocore/edk2-pytool-extensions/tree/master/docs)
|
||||
|
||||
@@ -88,7 +89,7 @@ that a few steps should be followed. Details of EDKII Tools can be found in the
|
||||
* VS 2017 or VS 2019
|
||||
* Windows SDK (for rc)
|
||||
* Windows WDK (for capsules)
|
||||
* Ubuntu 16.04
|
||||
* Ubuntu 18.04 or Fedora
|
||||
* GCC5
|
||||
* Easy to add more but this is the current state
|
||||
2. Python 3.7.x or newer on path
|
||||
@@ -137,11 +138,31 @@ location makes more sense for the community.
|
||||
|
||||
### Module Inclusion Test - DscCompleteCheck
|
||||
|
||||
This test scans all available modules (via INF files) and compares them to the
|
||||
package-level DSC file for the package each module is contained within. The test
|
||||
considers it an error if any module does not appear in the `Components` section
|
||||
of at least one package-level DSC (indicating that it would not be built if the
|
||||
package were built).
|
||||
This scans all INF files from a package and confirms they are
|
||||
listed in the package level DSC file. The test considers it an error if any INF
|
||||
does not appear in the `Components` section of the package-level DSC (indicating
|
||||
that it would not be built if the package were built). This is critical because
|
||||
much of the CI infrastructure assumes that all modules will be listed in the DSC
|
||||
and compiled.
|
||||
|
||||
This test will ignore INFs in the following cases:
|
||||
|
||||
1. When `MODULE_TYPE` = `HOST_APPLICATION`
|
||||
2. When a Library instance **only** supports the `HOST_APPLICATION` environment
|
||||
|
||||
### Host Module Inclusion Test - HostUnitTestDscCompleteCheck
|
||||
|
||||
This test scans all INF files from a package for those related to host
|
||||
based unit tests and confirms they are listed in the unit test DSC file for the package.
|
||||
The test considers it an error if any INF meeting the requirements does not appear
|
||||
in the `Components` section of the unit test DSC. This is critical because
|
||||
much of the CI infrastructure assumes that modules will be listed in the DSC
|
||||
and compiled.
|
||||
|
||||
This test will only require INFs in the following cases:
|
||||
|
||||
1. When `MODULE_TYPE` = `HOST_APPLICATION`
|
||||
2. When a Library instance explicitly supports the `HOST_APPLICATION` environment
|
||||
|
||||
### Code Compilation Test - CompilerPlugin
|
||||
|
||||
@@ -150,6 +171,46 @@ all package-level DSCs were built, the Code Compilation Test simply runs through
|
||||
and builds every package-level DSC on every toolchain and for every architecture
|
||||
that is supported. Any module that fails to build is considered an error.
|
||||
|
||||
### Host Unit Test Compilation and Run Test - HostUnitTestCompilerPlugin
|
||||
|
||||
A test that compiles the dsc for host based unit test apps.
|
||||
On Windows this will also enable a build plugin to execute that will run the unit tests and verify the results.
|
||||
|
||||
These tools will be invoked on any CI
|
||||
pass that includes the NOOPT target. In order for these tools to do their job,
|
||||
the package and tests must be configured in a particular way...
|
||||
|
||||
#### Including Host-Based Tests in the Package YAML
|
||||
|
||||
For example, looking at the `MdeModulePkg.ci.yaml` config file, there are two
|
||||
config options that control HostBased test behavior:
|
||||
|
||||
```json
|
||||
## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
|
||||
"HostUnitTestCompilerPlugin": {
|
||||
"DscPath": "Test/MdeModulePkgHostTest.dsc"
|
||||
},
|
||||
```
|
||||
|
||||
This option tell the test builder to run. The test builder needs to know which
|
||||
modules in this package are host-based tests, so that DSC path is provided.
|
||||
|
||||
#### Configuring the HostBased DSC
|
||||
|
||||
The HostBased DSC for `MdeModulePkg` is located at
|
||||
`MdeModulePkg/Test/MdeModulePkgHostTest.dsc`.
|
||||
|
||||
To add automated host-based unit test building to a new package, create a
|
||||
similar DSC. The new DSC should make sure to have the `NOOPT` BUILD_TARGET
|
||||
and should include the line:
|
||||
|
||||
```
|
||||
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
|
||||
```
|
||||
|
||||
All of the modules that are included in the `Components` section of this
|
||||
DSC should be of type HOST_APPLICATION.
|
||||
|
||||
### GUID Uniqueness Test - GuidCheck
|
||||
|
||||
This test works on the collection of all packages rather than an individual
|
||||
@@ -207,6 +268,8 @@ few standard scopes.
|
||||
| global-nix | edk2_invocable++ | Running on Linux based OS |
|
||||
| edk2-build | | This indicates that an invocable is building EDK2 based UEFI code |
|
||||
| cibuild | set in .pytool/CISettings.py | Suggested target for edk2 continuous integration builds. Tools used for CiBuilds can use this scope. Example: asl compiler |
|
||||
| host-based-test | set in .pytool/CISettings.py | Turns on the host based tests and plugin |
|
||||
| host-test-win | set in .pytool/CISettings.py | Enables the host based test runner for Windows |
|
||||
|
||||
## Future investments
|
||||
|
||||
@@ -216,8 +279,6 @@ few standard scopes.
|
||||
* Visual Studio AARCH64 and ARM support
|
||||
* BaseTools C tools CI/PR and binary release process
|
||||
* BaseTools Python tools CI/PR process
|
||||
* Host based unit testing
|
||||
* Extensible private/closed source platform reporting
|
||||
* Platform builds, validation
|
||||
* UEFI SCTs
|
||||
* Other automation
|
||||
|
@@ -78,10 +78,6 @@
|
||||
# Define if the GICv3 controller should use the GICv2 legacy
|
||||
gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
|
||||
|
||||
# Whether to implement warm reboot for capsule update using a jump back to the
|
||||
# PEI entry point with caches and interrupts disabled.
|
||||
gArmTokenSpaceGuid.PcdArmReenterPeiForCapsuleWarmReboot|FALSE|BOOLEAN|0x0000001F
|
||||
|
||||
[PcdsFeatureFlag.ARM]
|
||||
# Whether to map normal memory as non-shareable. FALSE is the safe choice, but
|
||||
# TRUE may be appropriate to fix performance problems if you don't care about
|
||||
|
@@ -4,6 +4,7 @@
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.<BR>
|
||||
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
# Copyright (c) Microsoft Corporation.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
@@ -28,6 +29,9 @@
|
||||
RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
|
||||
*_*_*_CC_FLAGS = -DDISABLE_NEW_DEPRECATED_INTERFACES
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
|
||||
|
||||
[LibraryClasses.common]
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
@@ -133,12 +137,16 @@
|
||||
ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
|
||||
ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
|
||||
ArmPkg/Library/ArmLib/ArmBaseLib.inf
|
||||
ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
|
||||
ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
|
||||
ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
|
||||
ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||||
|
||||
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
|
||||
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
|
||||
|
||||
[Components.AARCH64]
|
||||
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
||||
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
||||
ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
|
||||
|
@@ -13,7 +13,68 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include "CpuDxe.h"
|
||||
|
||||
#define TT_ATTR_INDX_INVALID ((UINT32)~0)
|
||||
#define INVALID_ENTRY ((UINT32)~0)
|
||||
|
||||
#define MIN_T0SZ 16
|
||||
#define BITS_PER_LEVEL 9
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
GetRootTranslationTableInfo (
|
||||
IN UINTN T0SZ,
|
||||
OUT UINTN *RootTableLevel,
|
||||
OUT UINTN *RootTableEntryCount
|
||||
)
|
||||
{
|
||||
*RootTableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL;
|
||||
*RootTableEntryCount = TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
PageAttributeToGcdAttribute (
|
||||
IN UINT64 PageAttributes
|
||||
)
|
||||
{
|
||||
UINT64 GcdAttributes;
|
||||
|
||||
switch (PageAttributes & TT_ATTR_INDX_MASK) {
|
||||
case TT_ATTR_INDX_DEVICE_MEMORY:
|
||||
GcdAttributes = EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_NON_CACHEABLE:
|
||||
GcdAttributes = EFI_MEMORY_WC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_THROUGH:
|
||||
GcdAttributes = EFI_MEMORY_WT;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_BACK:
|
||||
GcdAttributes = EFI_MEMORY_WB;
|
||||
break;
|
||||
default:
|
||||
DEBUG ((DEBUG_ERROR,
|
||||
"PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n",
|
||||
PageAttributes));
|
||||
ASSERT (0);
|
||||
// The Global Coherency Domain (GCD) value is defined as a bit set.
|
||||
// Returning 0 means no attribute has been set.
|
||||
GcdAttributes = 0;
|
||||
}
|
||||
|
||||
// Determine protection attributes
|
||||
if (((PageAttributes & TT_AP_MASK) == TT_AP_NO_RO) ||
|
||||
((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO)) {
|
||||
// Read only cases map to write-protect
|
||||
GcdAttributes |= EFI_MEMORY_RO;
|
||||
}
|
||||
|
||||
// Process eXecute Never attribute
|
||||
if ((PageAttributes & (TT_PXN_MASK | TT_UXN_MASK)) != 0) {
|
||||
GcdAttributes |= EFI_MEMORY_XP;
|
||||
}
|
||||
|
||||
return GcdAttributes;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
@@ -37,7 +98,7 @@ GetFirstPageAttribute (
|
||||
{
|
||||
return FirstEntry & TT_ATTR_INDX_MASK;
|
||||
} else {
|
||||
return TT_ATTR_INDX_INVALID;
|
||||
return INVALID_ENTRY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +139,8 @@ GetNextEntryAttribute (
|
||||
// If Entry is a Table Descriptor type entry then go through the sub-level table
|
||||
if ((EntryType == TT_TYPE_BLOCK_ENTRY) ||
|
||||
((TableLevel == 3) && (EntryType == TT_TYPE_BLOCK_ENTRY_LEVEL3))) {
|
||||
if ((*PrevEntryAttribute == TT_ATTR_INDX_INVALID) || (EntryAttribute != *PrevEntryAttribute)) {
|
||||
if (*PrevEntryAttribute != TT_ATTR_INDX_INVALID) {
|
||||
if ((*PrevEntryAttribute == INVALID_ENTRY) || (EntryAttribute != *PrevEntryAttribute)) {
|
||||
if (*PrevEntryAttribute != INVALID_ENTRY) {
|
||||
// Update GCD with the last region
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors,
|
||||
*StartGcdRegion,
|
||||
@@ -103,7 +164,7 @@ GetNextEntryAttribute (
|
||||
(BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel))),
|
||||
PrevEntryAttribute, StartGcdRegion);
|
||||
} else {
|
||||
if (*PrevEntryAttribute != TT_ATTR_INDX_INVALID) {
|
||||
if (*PrevEntryAttribute != INVALID_ENTRY) {
|
||||
// Update GCD with the last region
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors,
|
||||
*StartGcdRegion,
|
||||
@@ -112,7 +173,7 @@ GetNextEntryAttribute (
|
||||
|
||||
// Start of the new region
|
||||
*StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL(TableLevel));
|
||||
*PrevEntryAttribute = TT_ATTR_INDX_INVALID;
|
||||
*PrevEntryAttribute = INVALID_ENTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +238,7 @@ SyncCacheConfig (
|
||||
&PageAttribute, &BaseAddressGcdRegion);
|
||||
|
||||
// Update GCD with the last region if valid
|
||||
if (PageAttribute != TT_ATTR_INDX_INVALID) {
|
||||
if (PageAttribute != INVALID_ENTRY) {
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors,
|
||||
BaseAddressGcdRegion,
|
||||
EndAddressGcdRegion - BaseAddressGcdRegion,
|
||||
|
@@ -134,13 +134,6 @@ GetMemoryRegion (
|
||||
OUT UINTN *RegionAttributes
|
||||
);
|
||||
|
||||
VOID
|
||||
GetRootTranslationTableInfo (
|
||||
IN UINTN T0SZ,
|
||||
OUT UINTN *TableLevel,
|
||||
OUT UINTN *TableEntryCount
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
SetGcdMemorySpaceAttributes (
|
||||
IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2016-2018, ARM Limited. All rights reserved.
|
||||
Copyright (c) 2016-2019, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include <Protocol/MmCommunication.h>
|
||||
#include <Protocol/MmCommunication2.h>
|
||||
|
||||
#include <IndustryStandard/ArmStdSmc.h>
|
||||
|
||||
@@ -39,39 +39,34 @@ STATIC EFI_HANDLE mMmCommunicateHandle;
|
||||
/**
|
||||
Communicates with a registered handler.
|
||||
|
||||
This function provides an interface to send and receive messages to the
|
||||
Standalone MM environment on behalf of UEFI services. This function is part
|
||||
of the MM Communication Protocol that may be called in physical mode prior to
|
||||
SetVirtualAddressMap() and in virtual mode after SetVirtualAddressMap().
|
||||
This function provides a service to send and receive messages from a registered UEFI service.
|
||||
|
||||
@param[in] This The EFI_MM_COMMUNICATION_PROTOCOL
|
||||
instance.
|
||||
@param[in, out] CommBuffer A pointer to the buffer to convey
|
||||
into MMRAM.
|
||||
@param[in, out] CommSize The size of the data buffer being
|
||||
passed in. This is optional.
|
||||
@param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance.
|
||||
@param[in] CommBufferPhysical Physical address of the MM communication buffer
|
||||
@param[in] CommBufferVirtual Virtual address of the MM communication buffer
|
||||
@param[in] CommSize The size of the data buffer being passed in. On exit, the size of data
|
||||
being returned. Zero if the handler does not wish to reply with any data.
|
||||
This parameter is optional and may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The message was successfully posted.
|
||||
@retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
|
||||
@retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
|
||||
If this error is returned, the MessageLength field
|
||||
in the CommBuffer header or the integer pointed by
|
||||
CommSize, are updated to reflect the maximum payload
|
||||
size the implementation can accommodate.
|
||||
@retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
|
||||
if not omitted, are in address range that cannot be
|
||||
accessed by the MM environment.
|
||||
|
||||
@retval EFI_SUCCESS The message was successfully posted.
|
||||
@retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
|
||||
@retval EFI_BAD_BUFFER_SIZE The buffer size is incorrect for the MM
|
||||
implementation. If this error is
|
||||
returned, the MessageLength field in
|
||||
the CommBuffer header or the integer
|
||||
pointed by CommSize are updated to reflect
|
||||
the maximum payload size the
|
||||
implementation can accommodate.
|
||||
@retval EFI_ACCESS_DENIED The CommunicateBuffer parameter
|
||||
or CommSize parameter, if not omitted,
|
||||
are in address range that cannot be
|
||||
accessed by the MM environment
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MmCommunicationCommunicate (
|
||||
IN CONST EFI_MM_COMMUNICATION_PROTOCOL *This,
|
||||
IN OUT VOID *CommBuffer,
|
||||
IN OUT UINTN *CommSize OPTIONAL
|
||||
MmCommunication2Communicate (
|
||||
IN CONST EFI_MM_COMMUNICATION2_PROTOCOL *This,
|
||||
IN OUT VOID *CommBufferPhysical,
|
||||
IN OUT VOID *CommBufferVirtual,
|
||||
IN OUT UINTN *CommSize OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
|
||||
@@ -87,11 +82,11 @@ MmCommunicationCommunicate (
|
||||
//
|
||||
// Check parameters
|
||||
//
|
||||
if (CommBuffer == NULL) {
|
||||
if (CommBufferVirtual == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CommunicateHeader = CommBuffer;
|
||||
CommunicateHeader = CommBufferVirtual;
|
||||
// CommBuffer is a mandatory parameter. Hence, Rely on
|
||||
// MessageLength + Header to ascertain the
|
||||
// total size of the communication payload rather than
|
||||
@@ -136,7 +131,7 @@ MmCommunicationCommunicate (
|
||||
CommunicateSmcArgs.Arg1 = 0;
|
||||
|
||||
// Copy Communication Payload
|
||||
CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBuffer, BufferSize);
|
||||
CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBufferVirtual, BufferSize);
|
||||
|
||||
// comm_buffer_address (64-bit physical address)
|
||||
CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
|
||||
@@ -149,7 +144,7 @@ MmCommunicationCommunicate (
|
||||
|
||||
switch (CommunicateSmcArgs.Arg0) {
|
||||
case ARM_SMC_MM_RET_SUCCESS:
|
||||
ZeroMem (CommBuffer, BufferSize);
|
||||
ZeroMem (CommBufferVirtual, BufferSize);
|
||||
// On successful return, the size of data being returned is inferred from
|
||||
// MessageLength + Header.
|
||||
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mNsCommBuffMemRegion.VirtualBase;
|
||||
@@ -158,7 +153,7 @@ MmCommunicationCommunicate (
|
||||
sizeof (CommunicateHeader->MessageLength);
|
||||
|
||||
CopyMem (
|
||||
CommBuffer,
|
||||
CommBufferVirtual,
|
||||
(VOID *)mNsCommBuffMemRegion.VirtualBase,
|
||||
BufferSize
|
||||
);
|
||||
@@ -191,8 +186,8 @@ MmCommunicationCommunicate (
|
||||
//
|
||||
// MM Communication Protocol instance
|
||||
//
|
||||
EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = {
|
||||
MmCommunicationCommunicate
|
||||
STATIC EFI_MM_COMMUNICATION2_PROTOCOL mMmCommunication2 = {
|
||||
MmCommunication2Communicate
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -259,6 +254,43 @@ GetMmCompatibility ()
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_GUID* CONST mGuidedEventGuid[] = {
|
||||
&gEfiEndOfDxeEventGroupGuid,
|
||||
&gEfiEventExitBootServicesGuid,
|
||||
&gEfiEventReadyToBootGuid,
|
||||
};
|
||||
|
||||
STATIC EFI_EVENT mGuidedEvent[ARRAY_SIZE (mGuidedEventGuid)];
|
||||
|
||||
/**
|
||||
Event notification that is fired when GUIDed Event Group is signaled.
|
||||
|
||||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
MmGuidedEventNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_MM_COMMUNICATE_HEADER Header;
|
||||
UINTN Size;
|
||||
|
||||
//
|
||||
// Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure
|
||||
//
|
||||
CopyGuid (&Header.HeaderGuid, Context);
|
||||
Header.MessageLength = 1;
|
||||
Header.Data[0] = 0;
|
||||
|
||||
Size = sizeof (Header);
|
||||
MmCommunication2Communicate (&mMmCommunication2, &Header, &Header, &Size);
|
||||
}
|
||||
|
||||
/**
|
||||
The Entry Point for MM Communication
|
||||
|
||||
@@ -275,12 +307,13 @@ GetMmCompatibility ()
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MmCommunicationInitialize (
|
||||
MmCommunication2Initialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
|
||||
// Check if we can make the MM call
|
||||
Status = GetMmCompatibility ();
|
||||
@@ -325,9 +358,9 @@ MmCommunicationInitialize (
|
||||
// Install the communication protocol
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mMmCommunicateHandle,
|
||||
&gEfiMmCommunicationProtocolGuid,
|
||||
&gEfiMmCommunication2ProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&mMmCommunication
|
||||
&mMmCommunication2
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "MmCommunicationInitialize: "
|
||||
@@ -345,14 +378,27 @@ MmCommunicationInitialize (
|
||||
NULL,
|
||||
&mSetVirtualAddressMapEvent
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
for (Index = 0; Index < ARRAY_SIZE (mGuidedEventGuid); Index++) {
|
||||
Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
|
||||
MmGuidedEventNotify, mGuidedEventGuid[Index],
|
||||
mGuidedEventGuid[Index], &mGuidedEvent[Index]);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
if (EFI_ERROR (Status)) {
|
||||
while (Index-- > 0) {
|
||||
gBS->CloseEvent (mGuidedEvent[Index]);
|
||||
}
|
||||
goto UninstallProtocol;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
|
||||
UninstallProtocol:
|
||||
gBS->UninstallProtocolInterface (
|
||||
mMmCommunicateHandle,
|
||||
&gEfiMmCommunicationProtocolGuid,
|
||||
&mMmCommunication
|
||||
&gEfiMmCommunication2ProtocolGuid,
|
||||
&mMmCommunication2
|
||||
);
|
||||
|
||||
CleanAddedMemorySpace:
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# DXE MM Communicate driver
|
||||
#
|
||||
# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
|
||||
# Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
@@ -14,7 +14,7 @@
|
||||
FILE_GUID = 09EE81D3-F15E-43F4-85B4-CB9873DA5D6B
|
||||
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = MmCommunicationInitialize
|
||||
ENTRY_POINT = MmCommunication2Initialize
|
||||
|
||||
#
|
||||
# The following is for reference only and not required by
|
||||
@@ -40,7 +40,12 @@
|
||||
UefiDriverEntryPoint
|
||||
|
||||
[Protocols]
|
||||
gEfiMmCommunicationProtocolGuid ## PRODUCES
|
||||
gEfiMmCommunication2ProtocolGuid ## PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiEndOfDxeEventGroupGuid
|
||||
gEfiEventExitBootServicesGuid
|
||||
gEfiEventReadyToBootGuid
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdMmBufferBase
|
||||
|
@@ -219,11 +219,6 @@ ArmReadCurrentEL (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINT64
|
||||
PageAttributeToGcdAttribute (
|
||||
IN UINT64 PageAttributes
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArmWriteCptr (
|
||||
IN UINT64 Cptr
|
||||
|
@@ -211,24 +211,6 @@ ArmCleanInvalidateDataCacheEntryByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableDataCache (
|
||||
|
@@ -19,7 +19,8 @@ EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] =
|
||||
PHYSICAL_ADDRESS gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;
|
||||
UINTN gDebuggerNoHandlerValue = 0; // todo: define for AArch64
|
||||
|
||||
#define EL0_STACK_PAGES 2
|
||||
#define EL0_STACK_SIZE EFI_PAGES_TO_SIZE(2)
|
||||
STATIC UINTN mNewStackBase[EL0_STACK_SIZE / sizeof (UINTN)];
|
||||
|
||||
VOID
|
||||
RegisterEl0Stack (
|
||||
@@ -31,14 +32,11 @@ RETURN_STATUS ArchVectorConfig(
|
||||
)
|
||||
{
|
||||
UINTN HcrReg;
|
||||
UINT8 *Stack;
|
||||
|
||||
Stack = AllocatePages (EL0_STACK_PAGES);
|
||||
if (Stack == NULL) {
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
RegisterEl0Stack ((UINT8 *)Stack + EFI_PAGES_TO_SIZE (EL0_STACK_PAGES));
|
||||
// Round down sp by 16 bytes alignment
|
||||
RegisterEl0Stack (
|
||||
(VOID *)(((UINTN)mNewStackBase + EL0_STACK_SIZE) & ~0xFUL)
|
||||
);
|
||||
|
||||
if (ArmReadCurrentEL() == AARCH64_EL2) {
|
||||
HcrReg = ArmReadHcr();
|
||||
|
@@ -7,11 +7,13 @@
|
||||
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Chipset/AArch64.h>
|
||||
#include <Base.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
#include <Chipset/AArch64.h>
|
||||
|
||||
#include "AArch64Lib.h"
|
||||
#include "ArmLibPrivate.h"
|
||||
|
||||
@@ -40,6 +42,8 @@ ArmInvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
AArch64DataCacheOperation (ArmInvalidateDataCacheEntryBySetWay);
|
||||
}
|
||||
@@ -50,6 +54,8 @@ ArmCleanInvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
AArch64DataCacheOperation (ArmCleanInvalidateDataCacheEntryBySetWay);
|
||||
}
|
||||
@@ -60,6 +66,8 @@ ArmCleanDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
AArch64DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
|
||||
}
|
||||
|
@@ -17,5 +17,23 @@ AArch64AllDataCachesOperation (
|
||||
IN AARCH64_CACHE_OPERATION DataCacheOperation
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
#endif // __AARCH64_LIB_H__
|
||||
|
||||
|
@@ -13,6 +13,8 @@
|
||||
.set DAIF_RD_FIQ_BIT, (1 << 6)
|
||||
.set DAIF_RD_IRQ_BIT, (1 << 7)
|
||||
|
||||
.set SCTLR_ELx_M_BIT_POS, (0)
|
||||
|
||||
ASM_FUNC(ArmReadMidr)
|
||||
mrs x0, midr_el1 // Read from Main ID Register (MIDR)
|
||||
ret
|
||||
@@ -120,13 +122,18 @@ ASM_FUNC(ArmSetMAIR)
|
||||
ASM_FUNC(ArmUpdateTranslationTableEntry)
|
||||
dsb nshst
|
||||
lsr x1, x1, #12
|
||||
EL1_OR_EL2_OR_EL3(x0)
|
||||
EL1_OR_EL2_OR_EL3(x2)
|
||||
1: tlbi vaae1, x1 // TLB Invalidate VA , EL1
|
||||
mrs x2, sctlr_el1
|
||||
b 4f
|
||||
2: tlbi vae2, x1 // TLB Invalidate VA , EL2
|
||||
mrs x2, sctlr_el2
|
||||
b 4f
|
||||
3: tlbi vae3, x1 // TLB Invalidate VA , EL3
|
||||
4: dsb nsh
|
||||
mrs x2, sctlr_el3
|
||||
4: tbnz x2, SCTLR_ELx_M_BIT_POS, 5f
|
||||
dc ivac, x0 // invalidate in Dcache if MMU is still off
|
||||
5: dsb nsh
|
||||
isb
|
||||
ret
|
||||
|
||||
|
@@ -6,11 +6,14 @@
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include <Uefi.h>
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
#include "ArmV7Lib.h"
|
||||
#include "ArmLibPrivate.h"
|
||||
|
||||
@@ -39,6 +42,8 @@ ArmInvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
ArmV7DataCacheOperation (ArmInvalidateDataCacheEntryBySetWay);
|
||||
}
|
||||
@@ -49,6 +54,8 @@ ArmCleanInvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
ArmV7DataCacheOperation (ArmCleanInvalidateDataCacheEntryBySetWay);
|
||||
}
|
||||
@@ -59,6 +66,8 @@ ArmCleanDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (!ArmMmuEnabled ());
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
ArmV7DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
|
||||
}
|
||||
|
@@ -30,5 +30,23 @@ ArmV7AllDataCachesOperation (
|
||||
IN ARM_V7_CACHE_OPERATION DataCacheOperation
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanInvalidateDataCacheEntryBySetWay (
|
||||
IN UINTN SetWayFormat
|
||||
);
|
||||
|
||||
#endif // __ARM_V7_LIB_H__
|
||||
|
||||
|
@@ -44,12 +44,12 @@
|
||||
AArch64/AArch64Support.S
|
||||
AArch64/AArch64ArchTimerSupport.S
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid
|
||||
|
||||
[FeaturePcd.ARM]
|
||||
gArmTokenSpaceGuid.PcdNormalMemoryNonshareableOverride
|
||||
|
@@ -10,8 +10,6 @@
|
||||
#include <Base.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#include "ArmLibPrivate.h"
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* File managing the MMU for ARMv8 architecture
|
||||
*
|
||||
* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2011-2020, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2016, Linaro Limited. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
*
|
||||
@@ -19,9 +19,6 @@
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
// We use this index definition to define an invalid block entry
|
||||
#define TT_ATTR_INDX_INVALID ((UINT32)~0)
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
ArmMemoryAttributeToPageAttribute (
|
||||
@@ -47,7 +44,7 @@ ArmMemoryAttributeToPageAttribute (
|
||||
return TT_ATTR_INDX_MEMORY_NON_CACHEABLE;
|
||||
|
||||
default:
|
||||
ASSERT(0);
|
||||
ASSERT (0);
|
||||
case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:
|
||||
case ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE:
|
||||
if (ArmReadCurrentEL () == AARCH64_EL2)
|
||||
@@ -57,78 +54,40 @@ ArmMemoryAttributeToPageAttribute (
|
||||
}
|
||||
}
|
||||
|
||||
UINT64
|
||||
PageAttributeToGcdAttribute (
|
||||
IN UINT64 PageAttributes
|
||||
)
|
||||
{
|
||||
UINT64 GcdAttributes;
|
||||
|
||||
switch (PageAttributes & TT_ATTR_INDX_MASK) {
|
||||
case TT_ATTR_INDX_DEVICE_MEMORY:
|
||||
GcdAttributes = EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_NON_CACHEABLE:
|
||||
GcdAttributes = EFI_MEMORY_WC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_THROUGH:
|
||||
GcdAttributes = EFI_MEMORY_WT;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_BACK:
|
||||
GcdAttributes = EFI_MEMORY_WB;
|
||||
break;
|
||||
default:
|
||||
DEBUG ((EFI_D_ERROR, "PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n", PageAttributes));
|
||||
ASSERT (0);
|
||||
// The Global Coherency Domain (GCD) value is defined as a bit set.
|
||||
// Returning 0 means no attribute has been set.
|
||||
GcdAttributes = 0;
|
||||
}
|
||||
|
||||
// Determine protection attributes
|
||||
if (((PageAttributes & TT_AP_MASK) == TT_AP_NO_RO) || ((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO)) {
|
||||
// Read only cases map to write-protect
|
||||
GcdAttributes |= EFI_MEMORY_RO;
|
||||
}
|
||||
|
||||
// Process eXecute Never attribute
|
||||
if ((PageAttributes & (TT_PXN_MASK | TT_UXN_MASK)) != 0 ) {
|
||||
GcdAttributes |= EFI_MEMORY_XP;
|
||||
}
|
||||
|
||||
return GcdAttributes;
|
||||
}
|
||||
|
||||
#define MIN_T0SZ 16
|
||||
#define BITS_PER_LEVEL 9
|
||||
#define MAX_VA_BITS 48
|
||||
|
||||
VOID
|
||||
GetRootTranslationTableInfo (
|
||||
IN UINTN T0SZ,
|
||||
OUT UINTN *TableLevel,
|
||||
OUT UINTN *TableEntryCount
|
||||
STATIC
|
||||
UINTN
|
||||
GetRootTableEntryCount (
|
||||
IN UINTN T0SZ
|
||||
)
|
||||
{
|
||||
// Get the level of the root table
|
||||
if (TableLevel) {
|
||||
*TableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL;
|
||||
}
|
||||
return TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL;
|
||||
}
|
||||
|
||||
if (TableEntryCount) {
|
||||
*TableEntryCount = 1UL << (BITS_PER_LEVEL - (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL);
|
||||
}
|
||||
STATIC
|
||||
UINTN
|
||||
GetRootTableLevel (
|
||||
IN UINTN T0SZ
|
||||
)
|
||||
{
|
||||
return (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReplaceLiveEntry (
|
||||
ReplaceTableEntry (
|
||||
IN UINT64 *Entry,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 RegionStart
|
||||
IN UINT64 RegionStart,
|
||||
IN BOOLEAN IsLiveBlockMapping
|
||||
)
|
||||
{
|
||||
if (!ArmMmuEnabled ()) {
|
||||
if (!ArmMmuEnabled () || !IsLiveBlockMapping) {
|
||||
*Entry = Value;
|
||||
ArmUpdateTranslationTableEntry (Entry, (VOID *)(UINTN)RegionStart);
|
||||
} else {
|
||||
ArmReplaceLiveTranslationEntry (Entry, Value, RegionStart);
|
||||
}
|
||||
@@ -136,258 +95,214 @@ ReplaceLiveEntry (
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
LookupAddresstoRootTable (
|
||||
IN UINT64 MaxAddress,
|
||||
OUT UINTN *T0SZ,
|
||||
OUT UINTN *TableEntryCount
|
||||
FreePageTablesRecursive (
|
||||
IN UINT64 *TranslationTable,
|
||||
IN UINTN Level
|
||||
)
|
||||
{
|
||||
UINTN TopBit;
|
||||
UINTN Index;
|
||||
|
||||
// Check the parameters are not NULL
|
||||
ASSERT ((T0SZ != NULL) && (TableEntryCount != NULL));
|
||||
ASSERT (Level <= 3);
|
||||
|
||||
// Look for the highest bit set in MaxAddress
|
||||
for (TopBit = 63; TopBit != 0; TopBit--) {
|
||||
if ((1ULL << TopBit) & MaxAddress) {
|
||||
// MaxAddress top bit is found
|
||||
TopBit = TopBit + 1;
|
||||
break;
|
||||
if (Level < 3) {
|
||||
for (Index = 0; Index < TT_ENTRY_COUNT; Index++) {
|
||||
if ((TranslationTable[Index] & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY) {
|
||||
FreePageTablesRecursive ((VOID *)(UINTN)(TranslationTable[Index] &
|
||||
TT_ADDRESS_MASK_BLOCK_ENTRY),
|
||||
Level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT (TopBit != 0);
|
||||
|
||||
// Calculate T0SZ from the top bit of the MaxAddress
|
||||
*T0SZ = 64 - TopBit;
|
||||
|
||||
// Get the Table info from T0SZ
|
||||
GetRootTranslationTableInfo (*T0SZ, NULL, TableEntryCount);
|
||||
FreePages (TranslationTable, 1);
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64*
|
||||
GetBlockEntryListFromAddress (
|
||||
IN UINT64 *RootTable,
|
||||
IN UINT64 RegionStart,
|
||||
OUT UINTN *TableLevel,
|
||||
IN OUT UINT64 *BlockEntrySize,
|
||||
OUT UINT64 **LastBlockEntry
|
||||
BOOLEAN
|
||||
IsBlockEntry (
|
||||
IN UINT64 Entry,
|
||||
IN UINTN Level
|
||||
)
|
||||
{
|
||||
UINTN RootTableLevel;
|
||||
UINTN RootTableEntryCount;
|
||||
UINT64 *TranslationTable;
|
||||
UINT64 *BlockEntry;
|
||||
UINT64 *SubTableBlockEntry;
|
||||
UINT64 BlockEntryAddress;
|
||||
UINTN BaseAddressAlignment;
|
||||
UINTN PageLevel;
|
||||
UINTN Index;
|
||||
UINTN IndexLevel;
|
||||
UINTN T0SZ;
|
||||
UINT64 Attributes;
|
||||
UINT64 TableAttributes;
|
||||
|
||||
// Initialize variable
|
||||
BlockEntry = NULL;
|
||||
|
||||
// Ensure the parameters are valid
|
||||
if (!(TableLevel && BlockEntrySize && LastBlockEntry)) {
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
if (Level == 3) {
|
||||
return (Entry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY_LEVEL3;
|
||||
}
|
||||
return (Entry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY;
|
||||
}
|
||||
|
||||
// Ensure the Region is aligned on 4KB boundary
|
||||
if ((RegionStart & (SIZE_4KB - 1)) != 0) {
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsTableEntry (
|
||||
IN UINT64 Entry,
|
||||
IN UINTN Level
|
||||
)
|
||||
{
|
||||
if (Level == 3) {
|
||||
//
|
||||
// TT_TYPE_TABLE_ENTRY aliases TT_TYPE_BLOCK_ENTRY_LEVEL3
|
||||
// so we need to take the level into account as well.
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return (Entry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY;
|
||||
}
|
||||
|
||||
// Ensure the required size is aligned on 4KB boundary and not 0
|
||||
if ((*BlockEntrySize & (SIZE_4KB - 1)) != 0 || *BlockEntrySize == 0) {
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdateRegionMappingRecursive (
|
||||
IN UINT64 RegionStart,
|
||||
IN UINT64 RegionEnd,
|
||||
IN UINT64 AttributeSetMask,
|
||||
IN UINT64 AttributeClearMask,
|
||||
IN UINT64 *PageTable,
|
||||
IN UINTN Level
|
||||
)
|
||||
{
|
||||
UINTN BlockShift;
|
||||
UINT64 BlockMask;
|
||||
UINT64 BlockEnd;
|
||||
UINT64 *Entry;
|
||||
UINT64 EntryValue;
|
||||
VOID *TranslationTable;
|
||||
EFI_STATUS Status;
|
||||
|
||||
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
||||
// Get the Table info from T0SZ
|
||||
GetRootTranslationTableInfo (T0SZ, &RootTableLevel, &RootTableEntryCount);
|
||||
ASSERT (((RegionStart | RegionEnd) & EFI_PAGE_MASK) == 0);
|
||||
|
||||
// If the start address is 0x0 then we use the size of the region to identify the alignment
|
||||
if (RegionStart == 0) {
|
||||
// Identify the highest possible alignment for the Region Size
|
||||
BaseAddressAlignment = LowBitSet64 (*BlockEntrySize);
|
||||
} else {
|
||||
// Identify the highest possible alignment for the Base Address
|
||||
BaseAddressAlignment = LowBitSet64 (RegionStart);
|
||||
}
|
||||
BlockShift = (Level + 1) * BITS_PER_LEVEL + MIN_T0SZ;
|
||||
BlockMask = MAX_UINT64 >> BlockShift;
|
||||
|
||||
// Identify the Page Level the RegionStart must belong to. Note that PageLevel
|
||||
// should be at least 1 since block translations are not supported at level 0
|
||||
PageLevel = MAX (3 - ((BaseAddressAlignment - 12) / 9), 1);
|
||||
DEBUG ((DEBUG_VERBOSE, "%a(%d): %llx - %llx set %lx clr %lx\n", __FUNCTION__,
|
||||
Level, RegionStart, RegionEnd, AttributeSetMask, AttributeClearMask));
|
||||
|
||||
// If the required size is smaller than the current block size then we need to go to the page below.
|
||||
// The PageLevel was calculated on the Base Address alignment but did not take in account the alignment
|
||||
// of the allocation size
|
||||
while (*BlockEntrySize < TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel)) {
|
||||
// It does not fit so we need to go a page level above
|
||||
PageLevel++;
|
||||
}
|
||||
for (; RegionStart < RegionEnd; RegionStart = BlockEnd) {
|
||||
BlockEnd = MIN (RegionEnd, (RegionStart | BlockMask) + 1);
|
||||
Entry = &PageTable[(RegionStart >> (64 - BlockShift)) & (TT_ENTRY_COUNT - 1)];
|
||||
|
||||
//
|
||||
// Get the Table Descriptor for the corresponding PageLevel. We need to decompose RegionStart to get appropriate entries
|
||||
//
|
||||
//
|
||||
// If RegionStart or BlockEnd is not aligned to the block size at this
|
||||
// level, we will have to create a table mapping in order to map less
|
||||
// than a block, and recurse to create the block or page entries at
|
||||
// the next level. No block mappings are allowed at all at level 0,
|
||||
// so in that case, we have to recurse unconditionally.
|
||||
// If we are changing a table entry and the AttributeClearMask is non-zero,
|
||||
// we cannot replace it with a block entry without potentially losing
|
||||
// attribute information, so keep the table entry in that case.
|
||||
//
|
||||
if (Level == 0 || ((RegionStart | BlockEnd) & BlockMask) != 0 ||
|
||||
(IsTableEntry (*Entry, Level) && AttributeClearMask != 0)) {
|
||||
ASSERT (Level < 3);
|
||||
|
||||
TranslationTable = RootTable;
|
||||
for (IndexLevel = RootTableLevel; IndexLevel <= PageLevel; IndexLevel++) {
|
||||
BlockEntry = (UINT64*)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, IndexLevel, RegionStart);
|
||||
|
||||
if ((IndexLevel != 3) && ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY)) {
|
||||
// Go to the next table
|
||||
TranslationTable = (UINT64*)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
|
||||
|
||||
// If we are at the last level then update the last level to next level
|
||||
if (IndexLevel == PageLevel) {
|
||||
// Enter the next level
|
||||
PageLevel++;
|
||||
}
|
||||
} else if ((*BlockEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) {
|
||||
// If we are not at the last level then we need to split this BlockEntry
|
||||
if (IndexLevel != PageLevel) {
|
||||
// Retrieve the attributes from the block entry
|
||||
Attributes = *BlockEntry & TT_ATTRIBUTES_MASK;
|
||||
|
||||
// Convert the block entry attributes into Table descriptor attributes
|
||||
TableAttributes = TT_TABLE_AP_NO_PERMISSION;
|
||||
if (Attributes & TT_NS) {
|
||||
TableAttributes = TT_TABLE_NS;
|
||||
}
|
||||
|
||||
// Get the address corresponding at this entry
|
||||
BlockEntryAddress = RegionStart;
|
||||
BlockEntryAddress = BlockEntryAddress >> TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel);
|
||||
// Shift back to right to set zero before the effective address
|
||||
BlockEntryAddress = BlockEntryAddress << TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel);
|
||||
|
||||
// Set the correct entry type for the next page level
|
||||
if ((IndexLevel + 1) == 3) {
|
||||
Attributes |= TT_TYPE_BLOCK_ENTRY_LEVEL3;
|
||||
} else {
|
||||
Attributes |= TT_TYPE_BLOCK_ENTRY;
|
||||
}
|
||||
|
||||
// Create a new translation table
|
||||
if (!IsTableEntry (*Entry, Level)) {
|
||||
//
|
||||
// No table entry exists yet, so we need to allocate a page table
|
||||
// for the next level.
|
||||
//
|
||||
TranslationTable = AllocatePages (1);
|
||||
if (TranslationTable == NULL) {
|
||||
return NULL;
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// Populate the newly created lower level table
|
||||
SubTableBlockEntry = TranslationTable;
|
||||
for (Index = 0; Index < TT_ENTRY_COUNT; Index++) {
|
||||
*SubTableBlockEntry = Attributes | (BlockEntryAddress + (Index << TT_ADDRESS_OFFSET_AT_LEVEL(IndexLevel + 1)));
|
||||
SubTableBlockEntry++;
|
||||
if (!ArmMmuEnabled ()) {
|
||||
//
|
||||
// Make sure we are not inadvertently hitting in the caches
|
||||
// when populating the page tables.
|
||||
//
|
||||
InvalidateDataCacheRange (TranslationTable, EFI_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// Fill the BlockEntry with the new TranslationTable
|
||||
ReplaceLiveEntry (BlockEntry,
|
||||
(UINTN)TranslationTable | TableAttributes | TT_TYPE_TABLE_ENTRY,
|
||||
RegionStart);
|
||||
ZeroMem (TranslationTable, EFI_PAGE_SIZE);
|
||||
|
||||
if (IsBlockEntry (*Entry, Level)) {
|
||||
//
|
||||
// We are splitting an existing block entry, so we have to populate
|
||||
// the new table with the attributes of the block entry it replaces.
|
||||
//
|
||||
Status = UpdateRegionMappingRecursive (RegionStart & ~BlockMask,
|
||||
(RegionStart | BlockMask) + 1, *Entry & TT_ATTRIBUTES_MASK,
|
||||
0, TranslationTable, Level + 1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// The range we passed to UpdateRegionMappingRecursive () is block
|
||||
// aligned, so it is guaranteed that no further pages were allocated
|
||||
// by it, and so we only have to free the page we allocated here.
|
||||
//
|
||||
FreePages (TranslationTable, 1);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TranslationTable = (VOID *)(UINTN)(*Entry & TT_ADDRESS_MASK_BLOCK_ENTRY);
|
||||
}
|
||||
|
||||
//
|
||||
// Recurse to the next level
|
||||
//
|
||||
Status = UpdateRegionMappingRecursive (RegionStart, BlockEnd,
|
||||
AttributeSetMask, AttributeClearMask, TranslationTable,
|
||||
Level + 1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (!IsTableEntry (*Entry, Level)) {
|
||||
//
|
||||
// We are creating a new table entry, so on failure, we can free all
|
||||
// allocations we made recursively, given that the whole subhierarchy
|
||||
// has not been wired into the live page tables yet. (This is not
|
||||
// possible for existing table entries, since we cannot revert the
|
||||
// modifications we made to the subhierarchy it represents.)
|
||||
//
|
||||
FreePageTablesRecursive (TranslationTable, Level + 1);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!IsTableEntry (*Entry, Level)) {
|
||||
EntryValue = (UINTN)TranslationTable | TT_TYPE_TABLE_ENTRY;
|
||||
ReplaceTableEntry (Entry, EntryValue, RegionStart,
|
||||
IsBlockEntry (*Entry, Level));
|
||||
}
|
||||
} else {
|
||||
if (IndexLevel != PageLevel) {
|
||||
EntryValue = (*Entry & AttributeClearMask) | AttributeSetMask;
|
||||
EntryValue |= RegionStart;
|
||||
EntryValue |= (Level == 3) ? TT_TYPE_BLOCK_ENTRY_LEVEL3
|
||||
: TT_TYPE_BLOCK_ENTRY;
|
||||
|
||||
if (IsTableEntry (*Entry, Level)) {
|
||||
//
|
||||
// Case when we have an Invalid Entry and we are at a page level above of the one targetted.
|
||||
// We are replacing a table entry with a block entry. This is only
|
||||
// possible if we are keeping none of the original attributes.
|
||||
// We can free the table entry's page table, and all the ones below
|
||||
// it, since we are dropping the only possible reference to it.
|
||||
//
|
||||
|
||||
// Create a new translation table
|
||||
TranslationTable = AllocatePages (1);
|
||||
if (TranslationTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem (TranslationTable, TT_ENTRY_COUNT * sizeof(UINT64));
|
||||
|
||||
// Fill the new BlockEntry with the TranslationTable
|
||||
*BlockEntry = ((UINTN)TranslationTable & TT_ADDRESS_MASK_DESCRIPTION_TABLE) | TT_TYPE_TABLE_ENTRY;
|
||||
ASSERT (AttributeClearMask == 0);
|
||||
TranslationTable = (VOID *)(UINTN)(*Entry & TT_ADDRESS_MASK_BLOCK_ENTRY);
|
||||
ReplaceTableEntry (Entry, EntryValue, RegionStart, TRUE);
|
||||
FreePageTablesRecursive (TranslationTable, Level + 1);
|
||||
} else {
|
||||
ReplaceTableEntry (Entry, EntryValue, RegionStart, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose the found PageLevel to the caller
|
||||
*TableLevel = PageLevel;
|
||||
|
||||
// Now, we have the Table Level we can get the Block Size associated to this table
|
||||
*BlockEntrySize = TT_BLOCK_ENTRY_SIZE_AT_LEVEL (PageLevel);
|
||||
|
||||
// The last block of the root table depends on the number of entry in this table,
|
||||
// otherwise it is always the (TT_ENTRY_COUNT - 1)th entry in the table.
|
||||
*LastBlockEntry = TT_LAST_BLOCK_ADDRESS(TranslationTable,
|
||||
(PageLevel == RootTableLevel) ? RootTableEntryCount : TT_ENTRY_COUNT);
|
||||
|
||||
return BlockEntry;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdateRegionMapping (
|
||||
IN UINT64 *RootTable,
|
||||
IN UINT64 RegionStart,
|
||||
IN UINT64 RegionLength,
|
||||
IN UINT64 Attributes,
|
||||
IN UINT64 BlockEntryMask
|
||||
IN UINT64 AttributeSetMask,
|
||||
IN UINT64 AttributeClearMask
|
||||
)
|
||||
{
|
||||
UINT32 Type;
|
||||
UINT64 *BlockEntry;
|
||||
UINT64 *LastBlockEntry;
|
||||
UINT64 BlockEntrySize;
|
||||
UINTN TableLevel;
|
||||
UINTN T0SZ;
|
||||
|
||||
// Ensure the Length is aligned on 4KB boundary
|
||||
if ((RegionLength == 0) || ((RegionLength & (SIZE_4KB - 1)) != 0)) {
|
||||
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
||||
if (((RegionStart | RegionLength) & EFI_PAGE_MASK)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
do {
|
||||
// Get the first Block Entry that matches the Virtual Address and also the information on the Table Descriptor
|
||||
// such as the size of the Block Entry and the address of the last BlockEntry of the Table Descriptor
|
||||
BlockEntrySize = RegionLength;
|
||||
BlockEntry = GetBlockEntryListFromAddress (RootTable, RegionStart, &TableLevel, &BlockEntrySize, &LastBlockEntry);
|
||||
if (BlockEntry == NULL) {
|
||||
// GetBlockEntryListFromAddress() return NULL when it fails to allocate new pages from the Translation Tables
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
||||
|
||||
if (TableLevel != 3) {
|
||||
Type = TT_TYPE_BLOCK_ENTRY;
|
||||
} else {
|
||||
Type = TT_TYPE_BLOCK_ENTRY_LEVEL3;
|
||||
}
|
||||
|
||||
do {
|
||||
// Fill the Block Entry with attribute and output block address
|
||||
*BlockEntry &= BlockEntryMask;
|
||||
*BlockEntry |= (RegionStart & TT_ADDRESS_MASK_BLOCK_ENTRY) | Attributes | Type;
|
||||
|
||||
ArmUpdateTranslationTableEntry (BlockEntry, (VOID *)RegionStart);
|
||||
|
||||
// Go to the next BlockEntry
|
||||
RegionStart += BlockEntrySize;
|
||||
RegionLength -= BlockEntrySize;
|
||||
BlockEntry++;
|
||||
|
||||
// Break the inner loop when next block is a table
|
||||
// Rerun GetBlockEntryListFromAddress to avoid page table memory leak
|
||||
if (TableLevel != 3 && BlockEntry <= LastBlockEntry &&
|
||||
(*BlockEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY) {
|
||||
break;
|
||||
}
|
||||
} while ((RegionLength >= BlockEntrySize) && (BlockEntry <= LastBlockEntry));
|
||||
} while (RegionLength != 0);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return UpdateRegionMappingRecursive (RegionStart, RegionStart + RegionLength,
|
||||
AttributeSetMask, AttributeClearMask, ArmGetTTBR0BaseAddress (),
|
||||
GetRootTableLevel (T0SZ));
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -398,7 +313,6 @@ FillTranslationTable (
|
||||
)
|
||||
{
|
||||
return UpdateRegionMapping (
|
||||
RootTable,
|
||||
MemoryRegion->VirtualBase,
|
||||
MemoryRegion->Length,
|
||||
ArmMemoryAttributeToPageAttribute (MemoryRegion->Attributes) | TT_AF,
|
||||
@@ -455,8 +369,6 @@ ArmSetMemoryAttributes (
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 *TranslationTable;
|
||||
UINT64 PageAttributes;
|
||||
UINT64 PageAttributeMask;
|
||||
|
||||
@@ -473,19 +385,8 @@ ArmSetMemoryAttributes (
|
||||
TT_PXN_MASK | TT_XN_MASK);
|
||||
}
|
||||
|
||||
TranslationTable = ArmGetTTBR0BaseAddress ();
|
||||
|
||||
Status = UpdateRegionMapping (
|
||||
TranslationTable,
|
||||
BaseAddress,
|
||||
Length,
|
||||
PageAttributes,
|
||||
PageAttributeMask);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return UpdateRegionMapping (BaseAddress, Length, PageAttributes,
|
||||
PageAttributeMask);
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -497,17 +398,7 @@ SetMemoryRegionAttribute (
|
||||
IN UINT64 BlockEntryMask
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 *RootTable;
|
||||
|
||||
RootTable = ArmGetTTBR0BaseAddress ();
|
||||
|
||||
Status = UpdateRegionMapping (RootTable, BaseAddress, Length, Attributes, BlockEntryMask);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return UpdateRegionMapping (BaseAddress, Length, Attributes, BlockEntryMask);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
@@ -584,14 +475,14 @@ ArmConfigureMmu (
|
||||
)
|
||||
{
|
||||
VOID* TranslationTable;
|
||||
UINT32 TranslationTableAttribute;
|
||||
UINTN MaxAddressBits;
|
||||
UINT64 MaxAddress;
|
||||
UINTN T0SZ;
|
||||
UINTN RootTableEntryCount;
|
||||
UINT64 TCR;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if(MemoryTable == NULL) {
|
||||
if (MemoryTable == NULL) {
|
||||
ASSERT (MemoryTable != NULL);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
@@ -603,11 +494,11 @@ ArmConfigureMmu (
|
||||
// into account the architectural limitations that result from UEFI's
|
||||
// use of 4 KB pages.
|
||||
//
|
||||
MaxAddress = MIN (LShiftU64 (1ULL, ArmGetPhysicalAddressBits ()) - 1,
|
||||
MAX_ALLOC_ADDRESS);
|
||||
MaxAddressBits = MIN (ArmGetPhysicalAddressBits (), MAX_VA_BITS);
|
||||
MaxAddress = LShiftU64 (1ULL, MaxAddressBits) - 1;
|
||||
|
||||
// Lookup the Table Level to get the information
|
||||
LookupAddresstoRootTable (MaxAddress, &T0SZ, &RootTableEntryCount);
|
||||
T0SZ = 64 - MaxAddressBits;
|
||||
RootTableEntryCount = GetRootTableEntryCount (T0SZ);
|
||||
|
||||
//
|
||||
// Set TCR that allows us to retrieve T0SZ in the subsequent functions
|
||||
@@ -632,7 +523,9 @@ ArmConfigureMmu (
|
||||
} else if (MaxAddress < SIZE_256TB) {
|
||||
TCR |= TCR_PS_256TB;
|
||||
} else {
|
||||
DEBUG ((EFI_D_ERROR, "ArmConfigureMmu: The MaxAddress 0x%lX is not supported by this MMU configuration.\n", MaxAddress));
|
||||
DEBUG ((DEBUG_ERROR,
|
||||
"ArmConfigureMmu: The MaxAddress 0x%lX is not supported by this MMU configuration.\n",
|
||||
MaxAddress));
|
||||
ASSERT (0); // Bigger than 48-bit memory space are not supported
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
@@ -654,7 +547,9 @@ ArmConfigureMmu (
|
||||
} else if (MaxAddress < SIZE_256TB) {
|
||||
TCR |= TCR_IPS_256TB;
|
||||
} else {
|
||||
DEBUG ((EFI_D_ERROR, "ArmConfigureMmu: The MaxAddress 0x%lX is not supported by this MMU configuration.\n", MaxAddress));
|
||||
DEBUG ((DEBUG_ERROR,
|
||||
"ArmConfigureMmu: The MaxAddress 0x%lX is not supported by this MMU configuration.\n",
|
||||
MaxAddress));
|
||||
ASSERT (0); // Bigger than 48-bit memory space are not supported
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
@@ -684,9 +579,12 @@ ArmConfigureMmu (
|
||||
if (TranslationTable == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
// We set TTBR0 just after allocating the table to retrieve its location from the subsequent
|
||||
// functions without needing to pass this value across the functions. The MMU is only enabled
|
||||
// after the translation tables are populated.
|
||||
//
|
||||
// We set TTBR0 just after allocating the table to retrieve its location from
|
||||
// the subsequent functions without needing to pass this value across the
|
||||
// functions. The MMU is only enabled after the translation tables are
|
||||
// populated.
|
||||
//
|
||||
ArmSetTTBR0 (TranslationTable);
|
||||
|
||||
if (TranslationTableBase != NULL) {
|
||||
@@ -694,46 +592,37 @@ ArmConfigureMmu (
|
||||
}
|
||||
|
||||
if (TranslationTableSize != NULL) {
|
||||
*TranslationTableSize = RootTableEntryCount * sizeof(UINT64);
|
||||
*TranslationTableSize = RootTableEntryCount * sizeof (UINT64);
|
||||
}
|
||||
|
||||
ZeroMem (TranslationTable, RootTableEntryCount * sizeof(UINT64));
|
||||
//
|
||||
// Make sure we are not inadvertently hitting in the caches
|
||||
// when populating the page tables.
|
||||
//
|
||||
InvalidateDataCacheRange (TranslationTable,
|
||||
RootTableEntryCount * sizeof (UINT64));
|
||||
ZeroMem (TranslationTable, RootTableEntryCount * sizeof (UINT64));
|
||||
|
||||
// Disable MMU and caches. ArmDisableMmu() also invalidates the TLBs
|
||||
ArmDisableMmu ();
|
||||
ArmDisableDataCache ();
|
||||
ArmDisableInstructionCache ();
|
||||
|
||||
// Make sure nothing sneaked into the cache
|
||||
ArmCleanInvalidateDataCache ();
|
||||
ArmInvalidateInstructionCache ();
|
||||
|
||||
TranslationTableAttribute = TT_ATTR_INDX_INVALID;
|
||||
while (MemoryTable->Length != 0) {
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
// Find the memory attribute for the Translation Table
|
||||
if ((UINTN)TranslationTable >= MemoryTable->PhysicalBase &&
|
||||
(UINTN)TranslationTable + EFI_PAGE_SIZE <= MemoryTable->PhysicalBase +
|
||||
MemoryTable->Length) {
|
||||
TranslationTableAttribute = MemoryTable->Attributes;
|
||||
}
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
Status = FillTranslationTable (TranslationTable, MemoryTable);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto FREE_TRANSLATION_TABLE;
|
||||
goto FreeTranslationTable;
|
||||
}
|
||||
MemoryTable++;
|
||||
}
|
||||
|
||||
ASSERT (TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK ||
|
||||
TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK);
|
||||
|
||||
ArmSetMAIR (MAIR_ATTR(TT_ATTR_INDX_DEVICE_MEMORY, MAIR_ATTR_DEVICE_MEMORY) | // mapped to EFI_MEMORY_UC
|
||||
MAIR_ATTR(TT_ATTR_INDX_MEMORY_NON_CACHEABLE, MAIR_ATTR_NORMAL_MEMORY_NON_CACHEABLE) | // mapped to EFI_MEMORY_WC
|
||||
MAIR_ATTR(TT_ATTR_INDX_MEMORY_WRITE_THROUGH, MAIR_ATTR_NORMAL_MEMORY_WRITE_THROUGH) | // mapped to EFI_MEMORY_WT
|
||||
MAIR_ATTR(TT_ATTR_INDX_MEMORY_WRITE_BACK, MAIR_ATTR_NORMAL_MEMORY_WRITE_BACK)); // mapped to EFI_MEMORY_WB
|
||||
//
|
||||
// EFI_MEMORY_UC ==> MAIR_ATTR_DEVICE_MEMORY
|
||||
// EFI_MEMORY_WC ==> MAIR_ATTR_NORMAL_MEMORY_NON_CACHEABLE
|
||||
// EFI_MEMORY_WT ==> MAIR_ATTR_NORMAL_MEMORY_WRITE_THROUGH
|
||||
// EFI_MEMORY_WB ==> MAIR_ATTR_NORMAL_MEMORY_WRITE_BACK
|
||||
//
|
||||
ArmSetMAIR (
|
||||
MAIR_ATTR (TT_ATTR_INDX_DEVICE_MEMORY, MAIR_ATTR_DEVICE_MEMORY) |
|
||||
MAIR_ATTR (TT_ATTR_INDX_MEMORY_NON_CACHEABLE, MAIR_ATTR_NORMAL_MEMORY_NON_CACHEABLE) |
|
||||
MAIR_ATTR (TT_ATTR_INDX_MEMORY_WRITE_THROUGH, MAIR_ATTR_NORMAL_MEMORY_WRITE_THROUGH) |
|
||||
MAIR_ATTR (TT_ATTR_INDX_MEMORY_WRITE_BACK, MAIR_ATTR_NORMAL_MEMORY_WRITE_BACK)
|
||||
);
|
||||
|
||||
ArmDisableAlignmentCheck ();
|
||||
ArmEnableStackAlignmentCheck ();
|
||||
@@ -743,7 +632,7 @@ ArmConfigureMmu (
|
||||
ArmEnableMmu ();
|
||||
return EFI_SUCCESS;
|
||||
|
||||
FREE_TRANSLATION_TABLE:
|
||||
FreeTranslationTable:
|
||||
FreePages (TranslationTable, 1);
|
||||
return Status;
|
||||
}
|
||||
@@ -760,7 +649,7 @@ ArmMmuBaseLibConstructor (
|
||||
// The ArmReplaceLiveTranslationEntry () helper function may be invoked
|
||||
// with the MMU off so we have to ensure that it gets cleaned to the PoC
|
||||
//
|
||||
WriteBackDataCacheRange (ArmReplaceLiveTranslationEntry,
|
||||
WriteBackDataCacheRange ((VOID *)(UINTN)ArmReplaceLiveTranslationEntry,
|
||||
ArmReplaceLiveTranslationEntrySize);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
|
32
ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibConvert.c
Normal file
32
ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibConvert.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/** @file
|
||||
* File managing the MMU for ARMv7 architecture
|
||||
*
|
||||
* Copyright (c) 2011-2016, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
UINT32
|
||||
ConvertSectionAttributesToPageAttributes (
|
||||
IN UINT32 SectionAttributes,
|
||||
IN BOOLEAN IsLargePage
|
||||
)
|
||||
{
|
||||
UINT32 PageAttributes;
|
||||
|
||||
PageAttributes = 0;
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (SectionAttributes, IsLargePage);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (SectionAttributes);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN (SectionAttributes, IsLargePage);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG (SectionAttributes);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S (SectionAttributes);
|
||||
|
||||
return PageAttributes;
|
||||
}
|
@@ -31,15 +31,6 @@
|
||||
#define ID_MMFR0_SHR_IMP_HW_COHERENT 1
|
||||
#define ID_MMFR0_SHR_IGNORED 0xf
|
||||
|
||||
#define __EFI_MEMORY_RWX 0 // no restrictions
|
||||
|
||||
#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \
|
||||
EFI_MEMORY_WC | \
|
||||
EFI_MEMORY_WT | \
|
||||
EFI_MEMORY_WB | \
|
||||
EFI_MEMORY_UCE | \
|
||||
EFI_MEMORY_WP)
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadIdMmfr0 (
|
||||
@@ -52,24 +43,6 @@ ArmHasMpExtensions (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINT32
|
||||
ConvertSectionAttributesToPageAttributes (
|
||||
IN UINT32 SectionAttributes,
|
||||
IN BOOLEAN IsLargePage
|
||||
)
|
||||
{
|
||||
UINT32 PageAttributes;
|
||||
|
||||
PageAttributes = 0;
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (SectionAttributes, IsLargePage);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (SectionAttributes);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN (SectionAttributes, IsLargePage);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG (SectionAttributes);
|
||||
PageAttributes |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S (SectionAttributes);
|
||||
|
||||
return PageAttributes;
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
PreferNonshareableMemory (
|
||||
@@ -165,14 +138,22 @@ PopulateLevel2PageTable (
|
||||
// Case where a virtual memory map descriptor overlapped a section entry
|
||||
|
||||
// Allocate a Level2 Page Table for this Section
|
||||
TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));
|
||||
TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;
|
||||
TranslationTable = (UINTN)AllocateAlignedPages (
|
||||
EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_PAGE_SIZE),
|
||||
TRANSLATION_TABLE_PAGE_ALIGNMENT);
|
||||
|
||||
// Translate the Section Descriptor into Page Descriptor
|
||||
SectionDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (*SectionEntry, FALSE);
|
||||
|
||||
BaseSectionAddress = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(*SectionEntry);
|
||||
|
||||
//
|
||||
// Make sure we are not inadvertently hitting in the caches
|
||||
// when populating the page tables
|
||||
//
|
||||
InvalidateDataCacheRange ((VOID *)TranslationTable,
|
||||
TRANSLATION_TABLE_PAGE_SIZE);
|
||||
|
||||
// Populate the new Level2 Page Table for the section
|
||||
PageEntry = (UINT32*)TranslationTable;
|
||||
for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {
|
||||
@@ -189,9 +170,15 @@ PopulateLevel2PageTable (
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
TranslationTable = (UINTN)AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_PAGE_SIZE + TRANSLATION_TABLE_PAGE_ALIGNMENT));
|
||||
TranslationTable = ((UINTN)TranslationTable + TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK;
|
||||
|
||||
TranslationTable = (UINTN)AllocateAlignedPages (
|
||||
EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_PAGE_SIZE),
|
||||
TRANSLATION_TABLE_PAGE_ALIGNMENT);
|
||||
//
|
||||
// Make sure we are not inadvertently hitting in the caches
|
||||
// when populating the page tables
|
||||
//
|
||||
InvalidateDataCacheRange ((VOID *)TranslationTable,
|
||||
TRANSLATION_TABLE_PAGE_SIZE);
|
||||
ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE);
|
||||
|
||||
*SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |
|
||||
@@ -210,6 +197,13 @@ PopulateLevel2PageTable (
|
||||
PhysicalBase += TT_DESCRIPTOR_PAGE_SIZE;
|
||||
}
|
||||
|
||||
//
|
||||
// Invalidate again to ensure that any line fetches that may have occurred
|
||||
// [speculatively] since the previous invalidate are evicted again.
|
||||
//
|
||||
ArmDataMemoryBarrier ();
|
||||
InvalidateDataCacheRange ((UINT32 *)TranslationTable + FirstPageOffset,
|
||||
RemainLength / TT_DESCRIPTOR_PAGE_SIZE * sizeof (*PageEntry));
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -284,7 +278,16 @@ FillTranslationTable (
|
||||
RemainLength >= TT_DESCRIPTOR_SECTION_SIZE) {
|
||||
// Case: Physical address aligned on the Section Size (1MB) && the length
|
||||
// is greater than the Section Size
|
||||
*SectionEntry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;
|
||||
*SectionEntry = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;
|
||||
|
||||
//
|
||||
// Issue a DMB to ensure that the page table entry update made it to
|
||||
// memory before we issue the invalidate, otherwise, a subsequent
|
||||
// speculative fetch could observe the old value.
|
||||
//
|
||||
ArmDataMemoryBarrier ();
|
||||
ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);
|
||||
|
||||
PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;
|
||||
RemainLength -= TT_DESCRIPTOR_SECTION_SIZE;
|
||||
} else {
|
||||
@@ -294,9 +297,17 @@ FillTranslationTable (
|
||||
// Case: Physical address aligned on the Section Size (1MB) && the length
|
||||
// does not fill a section
|
||||
// Case: Physical address NOT aligned on the Section Size (1MB)
|
||||
PopulateLevel2PageTable (SectionEntry++, PhysicalBase, PageMapLength,
|
||||
PopulateLevel2PageTable (SectionEntry, PhysicalBase, PageMapLength,
|
||||
MemoryRegion->Attributes);
|
||||
|
||||
//
|
||||
// Issue a DMB to ensure that the page table entry update made it to
|
||||
// memory before we issue the invalidate, otherwise, a subsequent
|
||||
// speculative fetch could observe the old value.
|
||||
//
|
||||
ArmDataMemoryBarrier ();
|
||||
ArmInvalidateDataCacheEntryByMVA ((UINTN)SectionEntry++);
|
||||
|
||||
// If it is the last entry
|
||||
if (RemainLength < TT_DESCRIPTOR_SECTION_SIZE) {
|
||||
break;
|
||||
@@ -316,16 +327,15 @@ ArmConfigureMmu (
|
||||
OUT UINTN *TranslationTableSize OPTIONAL
|
||||
)
|
||||
{
|
||||
VOID* TranslationTable;
|
||||
ARM_MEMORY_REGION_ATTRIBUTES TranslationTableAttribute;
|
||||
VOID *TranslationTable;
|
||||
UINT32 TTBRAttributes;
|
||||
|
||||
// Allocate pages for translation table.
|
||||
TranslationTable = AllocatePages (EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE + TRANSLATION_TABLE_SECTION_ALIGNMENT));
|
||||
TranslationTable = AllocateAlignedPages (
|
||||
EFI_SIZE_TO_PAGES (TRANSLATION_TABLE_SECTION_SIZE),
|
||||
TRANSLATION_TABLE_SECTION_ALIGNMENT);
|
||||
if (TranslationTable == NULL) {
|
||||
return RETURN_OUT_OF_RESOURCES;
|
||||
}
|
||||
TranslationTable = (VOID*)(((UINTN)TranslationTable + TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK);
|
||||
|
||||
if (TranslationTableBase != NULL) {
|
||||
*TranslationTableBase = TranslationTable;
|
||||
@@ -335,30 +345,20 @@ ArmConfigureMmu (
|
||||
*TranslationTableSize = TRANSLATION_TABLE_SECTION_SIZE;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure we are not inadvertently hitting in the caches
|
||||
// when populating the page tables
|
||||
//
|
||||
InvalidateDataCacheRange (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);
|
||||
ZeroMem (TranslationTable, TRANSLATION_TABLE_SECTION_SIZE);
|
||||
|
||||
// By default, mark the translation table as belonging to a uncached region
|
||||
TranslationTableAttribute = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;
|
||||
while (MemoryTable->Length != 0) {
|
||||
// Find the memory attribute for the Translation Table
|
||||
if (((UINTN)TranslationTable >= MemoryTable->PhysicalBase) && ((UINTN)TranslationTable <= MemoryTable->PhysicalBase - 1 + MemoryTable->Length)) {
|
||||
TranslationTableAttribute = MemoryTable->Attributes;
|
||||
}
|
||||
|
||||
FillTranslationTable (TranslationTable, MemoryTable);
|
||||
MemoryTable++;
|
||||
}
|
||||
|
||||
// Translate the Memory Attributes into Translation Table Register Attributes
|
||||
if ((TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK) ||
|
||||
(TranslationTableAttribute == ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK)) {
|
||||
TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC : TTBR_WRITE_BACK_ALLOC;
|
||||
} else {
|
||||
// Page tables must reside in memory mapped as write-back cacheable
|
||||
ASSERT (0);
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
TTBRAttributes = ArmHasMpExtensions () ? TTBR_MP_WRITE_BACK_ALLOC
|
||||
: TTBR_WRITE_BACK_ALLOC;
|
||||
if (TTBRAttributes & TTBR_SHAREABLE) {
|
||||
if (PreferNonshareableMemory ()) {
|
||||
TTBRAttributes ^= TTBR_SHAREABLE;
|
||||
@@ -376,19 +376,7 @@ ArmConfigureMmu (
|
||||
}
|
||||
}
|
||||
|
||||
ArmCleanInvalidateDataCache ();
|
||||
ArmInvalidateInstructionCache ();
|
||||
|
||||
ArmDisableDataCache ();
|
||||
ArmDisableInstructionCache();
|
||||
// TLBs are also invalidated when calling ArmDisableMmu()
|
||||
ArmDisableMmu ();
|
||||
|
||||
// Make sure nothing sneaked into the cache
|
||||
ArmCleanInvalidateDataCache ();
|
||||
ArmInvalidateInstructionCache ();
|
||||
|
||||
ArmSetTTBR0 ((VOID *)(UINTN)(((UINTN)TranslationTable & ~TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK) | (TTBRAttributes & 0x7F)));
|
||||
ArmSetTTBR0 ((VOID *)((UINTN)TranslationTable | TTBRAttributes));
|
||||
|
||||
//
|
||||
// The TTBCR register value is undefined at reset in the Non-Secure world.
|
||||
@@ -423,419 +411,3 @@ ArmConfigureMmu (
|
||||
ArmEnableMmu();
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ConvertSectionToPages (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress
|
||||
)
|
||||
{
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 SectionDescriptor;
|
||||
UINT32 PageTableDescriptor;
|
||||
UINT32 PageDescriptor;
|
||||
UINT32 Index;
|
||||
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
volatile ARM_PAGE_TABLE_ENTRY *PageTable;
|
||||
|
||||
DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// Calculate index into first level translation table for start of modification
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// Get section attributes and convert to page attributes
|
||||
SectionDescriptor = FirstLevelTable[FirstLevelIdx];
|
||||
PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (SectionDescriptor, FALSE);
|
||||
|
||||
// Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)
|
||||
PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)AllocatePages (1);
|
||||
if (PageTable == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// Write the page table entries out
|
||||
for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {
|
||||
PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor;
|
||||
}
|
||||
|
||||
// Formulate page table entry, Domain=0, NS=0
|
||||
PageTableDescriptor = (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
|
||||
|
||||
// Write the page table entry out, replacing section entry
|
||||
FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdatePageEntries (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes,
|
||||
OUT BOOLEAN *FlushTlbs OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 EntryValue;
|
||||
UINT32 EntryMask;
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 Offset;
|
||||
UINT32 NumPageEntries;
|
||||
UINT32 Descriptor;
|
||||
UINT32 p;
|
||||
UINT32 PageTableIndex;
|
||||
UINT32 PageTableEntry;
|
||||
UINT32 CurrentPageTableEntry;
|
||||
VOID *Mva;
|
||||
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
volatile ARM_PAGE_TABLE_ENTRY *PageTable;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
|
||||
// EntryValue: values at bit positions specified by EntryMask
|
||||
EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK;
|
||||
if (Attributes & EFI_MEMORY_XP) {
|
||||
EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN;
|
||||
} else {
|
||||
EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
|
||||
}
|
||||
|
||||
// Although the PI spec is unclear on this, the GCD guarantees that only
|
||||
// one Attribute bit is set at a time, so the order of the conditionals below
|
||||
// is irrelevant. If no memory attribute is specified, we preserve whatever
|
||||
// memory type is set in the page tables, and update the permission attributes
|
||||
// only.
|
||||
if (Attributes & EFI_MEMORY_UC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// map to strongly ordered
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// map to normal non-cachable
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
|
||||
} else if (Attributes & EFI_MEMORY_WT) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// write through with no-allocate
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WB) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// write back (with allocate)
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
|
||||
} else if (Attributes & CACHE_ATTRIBUTE_MASK) {
|
||||
// catch unsupported memory type attributes
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_RO) {
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO;
|
||||
} else {
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW;
|
||||
}
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// Calculate number of 4KB page table entries to change
|
||||
NumPageEntries = Length / TT_DESCRIPTOR_PAGE_SIZE;
|
||||
|
||||
// Iterate for the number of 4KB pages to change
|
||||
Offset = 0;
|
||||
for(p = 0; p < NumPageEntries; p++) {
|
||||
// Calculate index into first level translation table for page table value
|
||||
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// Read the descriptor from the first level page table
|
||||
Descriptor = FirstLevelTable[FirstLevelIdx];
|
||||
|
||||
// Does this descriptor need to be converted from section entry to 4K pages?
|
||||
if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {
|
||||
Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
if (EFI_ERROR(Status)) {
|
||||
// Exit for loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-read descriptor
|
||||
Descriptor = FirstLevelTable[FirstLevelIdx];
|
||||
if (FlushTlbs != NULL) {
|
||||
*FlushTlbs = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain page table base address
|
||||
PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);
|
||||
|
||||
// Calculate index into the page table
|
||||
PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
|
||||
ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
|
||||
|
||||
// Get the entry
|
||||
CurrentPageTableEntry = PageTable[PageTableIndex];
|
||||
|
||||
// Mask off appropriate fields
|
||||
PageTableEntry = CurrentPageTableEntry & ~EntryMask;
|
||||
|
||||
// Mask in new attributes and/or permissions
|
||||
PageTableEntry |= EntryValue;
|
||||
|
||||
if (CurrentPageTableEntry != PageTableEntry) {
|
||||
Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
|
||||
|
||||
// Only need to update if we are changing the entry
|
||||
PageTable[PageTableIndex] = PageTableEntry;
|
||||
ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Offset += TT_DESCRIPTOR_PAGE_SIZE;
|
||||
|
||||
} // End first level translation table loop
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdateSectionEntries (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT32 EntryMask;
|
||||
UINT32 EntryValue;
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 NumSections;
|
||||
UINT32 i;
|
||||
UINT32 CurrentDescriptor;
|
||||
UINT32 Descriptor;
|
||||
VOID *Mva;
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
|
||||
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
|
||||
// EntryValue: values at bit positions specified by EntryMask
|
||||
|
||||
// Make sure we handle a section range that is unmapped
|
||||
EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN_MASK |
|
||||
TT_DESCRIPTOR_SECTION_AP_MASK;
|
||||
EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;
|
||||
|
||||
// Although the PI spec is unclear on this, the GCD guarantees that only
|
||||
// one Attribute bit is set at a time, so the order of the conditionals below
|
||||
// is irrelevant. If no memory attribute is specified, we preserve whatever
|
||||
// memory type is set in the page tables, and update the permission attributes
|
||||
// only.
|
||||
if (Attributes & EFI_MEMORY_UC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// map to strongly ordered
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// map to normal non-cachable
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
|
||||
} else if (Attributes & EFI_MEMORY_WT) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// write through with no-allocate
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WB) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// write back (with allocate)
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
|
||||
} else if (Attributes & CACHE_ATTRIBUTE_MASK) {
|
||||
// catch unsupported memory type attributes
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_RO) {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
|
||||
} else {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_XP) {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK;
|
||||
}
|
||||
|
||||
// obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// calculate index into first level translation table for start of modification
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// calculate number of 1MB first level entries this applies to
|
||||
NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;
|
||||
|
||||
// iterate through each descriptor
|
||||
for(i=0; i<NumSections; i++) {
|
||||
CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];
|
||||
|
||||
// has this descriptor already been converted to pages?
|
||||
if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {
|
||||
// forward this 1MB range to page table function instead
|
||||
Status = UpdatePageEntries (
|
||||
(FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,
|
||||
TT_DESCRIPTOR_SECTION_SIZE,
|
||||
Attributes,
|
||||
NULL);
|
||||
} else {
|
||||
// still a section entry
|
||||
|
||||
if (CurrentDescriptor != 0) {
|
||||
// mask off appropriate fields
|
||||
Descriptor = CurrentDescriptor & ~EntryMask;
|
||||
} else {
|
||||
Descriptor = ((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
}
|
||||
|
||||
// mask in new attributes and/or permissions
|
||||
Descriptor |= EntryValue;
|
||||
|
||||
if (CurrentDescriptor != Descriptor) {
|
||||
Mva = (VOID *)(UINTN)(((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
|
||||
// Only need to update if we are changing the descriptor
|
||||
FirstLevelTable[FirstLevelIdx + i] = Descriptor;
|
||||
ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryAttributes (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 ChunkLength;
|
||||
BOOLEAN FlushTlbs;
|
||||
|
||||
if (BaseAddress > (UINT64)MAX_ADDRESS) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Length = MIN (Length, (UINT64)MAX_ADDRESS - BaseAddress + 1);
|
||||
if (Length == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
FlushTlbs = FALSE;
|
||||
while (Length > 0) {
|
||||
if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&
|
||||
Length >= TT_DESCRIPTOR_SECTION_SIZE) {
|
||||
|
||||
ChunkLength = Length - Length % TT_DESCRIPTOR_SECTION_SIZE;
|
||||
|
||||
DEBUG ((DEBUG_PAGE,
|
||||
"SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n",
|
||||
BaseAddress, ChunkLength, Attributes));
|
||||
|
||||
Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes);
|
||||
|
||||
FlushTlbs = TRUE;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Process page by page until the next section boundary, but only if
|
||||
// we have more than a section's worth of area to deal with after that.
|
||||
//
|
||||
ChunkLength = TT_DESCRIPTOR_SECTION_SIZE -
|
||||
(BaseAddress % TT_DESCRIPTOR_SECTION_SIZE);
|
||||
if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) {
|
||||
ChunkLength = Length;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_PAGE,
|
||||
"SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n",
|
||||
BaseAddress, ChunkLength, Attributes));
|
||||
|
||||
Status = UpdatePageEntries (BaseAddress, ChunkLength, Attributes,
|
||||
&FlushTlbs);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
BaseAddress += ChunkLength;
|
||||
Length -= ChunkLength;
|
||||
}
|
||||
|
||||
if (FlushTlbs) {
|
||||
ArmInvalidateTlb ();
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
ArmMmuBaseLibConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
435
ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c
Normal file
435
ArmPkg/Library/ArmMmuLib/Arm/ArmMmuLibUpdate.c
Normal file
@@ -0,0 +1,435 @@
|
||||
/** @file
|
||||
* File managing the MMU for ARMv7 architecture
|
||||
*
|
||||
* Copyright (c) 2011-2016, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/CacheMaintenanceLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
#define __EFI_MEMORY_RWX 0 // no restrictions
|
||||
|
||||
#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \
|
||||
EFI_MEMORY_WC | \
|
||||
EFI_MEMORY_WT | \
|
||||
EFI_MEMORY_WB | \
|
||||
EFI_MEMORY_UCE | \
|
||||
EFI_MEMORY_WP)
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ConvertSectionToPages (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress
|
||||
)
|
||||
{
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 SectionDescriptor;
|
||||
UINT32 PageTableDescriptor;
|
||||
UINT32 PageDescriptor;
|
||||
UINT32 Index;
|
||||
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
volatile ARM_PAGE_TABLE_ENTRY *PageTable;
|
||||
|
||||
DEBUG ((DEBUG_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// Calculate index into first level translation table for start of modification
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// Get section attributes and convert to page attributes
|
||||
SectionDescriptor = FirstLevelTable[FirstLevelIdx];
|
||||
PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (SectionDescriptor, FALSE);
|
||||
|
||||
// Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)
|
||||
PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)AllocatePages (1);
|
||||
if (PageTable == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// Write the page table entries out
|
||||
for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {
|
||||
PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor;
|
||||
}
|
||||
|
||||
// Formulate page table entry, Domain=0, NS=0
|
||||
PageTableDescriptor = (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
|
||||
|
||||
// Write the page table entry out, replacing section entry
|
||||
FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdatePageEntries (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes,
|
||||
OUT BOOLEAN *FlushTlbs OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 EntryValue;
|
||||
UINT32 EntryMask;
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 Offset;
|
||||
UINT32 NumPageEntries;
|
||||
UINT32 Descriptor;
|
||||
UINT32 p;
|
||||
UINT32 PageTableIndex;
|
||||
UINT32 PageTableEntry;
|
||||
UINT32 CurrentPageTableEntry;
|
||||
VOID *Mva;
|
||||
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
volatile ARM_PAGE_TABLE_ENTRY *PageTable;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
|
||||
// EntryValue: values at bit positions specified by EntryMask
|
||||
EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK;
|
||||
if (Attributes & EFI_MEMORY_XP) {
|
||||
EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN;
|
||||
} else {
|
||||
EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
|
||||
}
|
||||
|
||||
// Although the PI spec is unclear on this, the GCD guarantees that only
|
||||
// one Attribute bit is set at a time, so the order of the conditionals below
|
||||
// is irrelevant. If no memory attribute is specified, we preserve whatever
|
||||
// memory type is set in the page tables, and update the permission attributes
|
||||
// only.
|
||||
if (Attributes & EFI_MEMORY_UC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// map to strongly ordered
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// map to normal non-cachable
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
|
||||
} else if (Attributes & EFI_MEMORY_WT) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// write through with no-allocate
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WB) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
|
||||
// write back (with allocate)
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
|
||||
} else if (Attributes & CACHE_ATTRIBUTE_MASK) {
|
||||
// catch unsupported memory type attributes
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_RO) {
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO;
|
||||
} else {
|
||||
EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW;
|
||||
}
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// Calculate number of 4KB page table entries to change
|
||||
NumPageEntries = Length / TT_DESCRIPTOR_PAGE_SIZE;
|
||||
|
||||
// Iterate for the number of 4KB pages to change
|
||||
Offset = 0;
|
||||
for(p = 0; p < NumPageEntries; p++) {
|
||||
// Calculate index into first level translation table for page table value
|
||||
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// Read the descriptor from the first level page table
|
||||
Descriptor = FirstLevelTable[FirstLevelIdx];
|
||||
|
||||
// Does this descriptor need to be converted from section entry to 4K pages?
|
||||
if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {
|
||||
Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
if (EFI_ERROR(Status)) {
|
||||
// Exit for loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-read descriptor
|
||||
Descriptor = FirstLevelTable[FirstLevelIdx];
|
||||
if (FlushTlbs != NULL) {
|
||||
*FlushTlbs = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain page table base address
|
||||
PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);
|
||||
|
||||
// Calculate index into the page table
|
||||
PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
|
||||
ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
|
||||
|
||||
// Get the entry
|
||||
CurrentPageTableEntry = PageTable[PageTableIndex];
|
||||
|
||||
// Mask off appropriate fields
|
||||
PageTableEntry = CurrentPageTableEntry & ~EntryMask;
|
||||
|
||||
// Mask in new attributes and/or permissions
|
||||
PageTableEntry |= EntryValue;
|
||||
|
||||
if (CurrentPageTableEntry != PageTableEntry) {
|
||||
Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
|
||||
|
||||
// Only need to update if we are changing the entry
|
||||
PageTable[PageTableIndex] = PageTableEntry;
|
||||
ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Offset += TT_DESCRIPTOR_PAGE_SIZE;
|
||||
|
||||
} // End first level translation table loop
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
UpdateSectionEntries (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT32 EntryMask;
|
||||
UINT32 EntryValue;
|
||||
UINT32 FirstLevelIdx;
|
||||
UINT32 NumSections;
|
||||
UINT32 i;
|
||||
UINT32 CurrentDescriptor;
|
||||
UINT32 Descriptor;
|
||||
VOID *Mva;
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
|
||||
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
|
||||
// EntryValue: values at bit positions specified by EntryMask
|
||||
|
||||
// Make sure we handle a section range that is unmapped
|
||||
EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN_MASK |
|
||||
TT_DESCRIPTOR_SECTION_AP_MASK;
|
||||
EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;
|
||||
|
||||
// Although the PI spec is unclear on this, the GCD guarantees that only
|
||||
// one Attribute bit is set at a time, so the order of the conditionals below
|
||||
// is irrelevant. If no memory attribute is specified, we preserve whatever
|
||||
// memory type is set in the page tables, and update the permission attributes
|
||||
// only.
|
||||
if (Attributes & EFI_MEMORY_UC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// map to strongly ordered
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WC) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// map to normal non-cachable
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
|
||||
} else if (Attributes & EFI_MEMORY_WT) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// write through with no-allocate
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
|
||||
} else if (Attributes & EFI_MEMORY_WB) {
|
||||
// modify cacheability attributes
|
||||
EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
|
||||
// write back (with allocate)
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
|
||||
} else if (Attributes & CACHE_ATTRIBUTE_MASK) {
|
||||
// catch unsupported memory type attributes
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_RO) {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
|
||||
} else {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
|
||||
}
|
||||
|
||||
if (Attributes & EFI_MEMORY_XP) {
|
||||
EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK;
|
||||
}
|
||||
|
||||
// obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// calculate index into first level translation table for start of modification
|
||||
FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// calculate number of 1MB first level entries this applies to
|
||||
NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;
|
||||
|
||||
// iterate through each descriptor
|
||||
for(i=0; i<NumSections; i++) {
|
||||
CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];
|
||||
|
||||
// has this descriptor already been converted to pages?
|
||||
if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {
|
||||
// forward this 1MB range to page table function instead
|
||||
Status = UpdatePageEntries (
|
||||
(FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,
|
||||
TT_DESCRIPTOR_SECTION_SIZE,
|
||||
Attributes,
|
||||
NULL);
|
||||
} else {
|
||||
// still a section entry
|
||||
|
||||
if (CurrentDescriptor != 0) {
|
||||
// mask off appropriate fields
|
||||
Descriptor = CurrentDescriptor & ~EntryMask;
|
||||
} else {
|
||||
Descriptor = ((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
}
|
||||
|
||||
// mask in new attributes and/or permissions
|
||||
Descriptor |= EntryValue;
|
||||
|
||||
if (CurrentDescriptor != Descriptor) {
|
||||
Mva = (VOID *)(UINTN)(((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
|
||||
// Only need to update if we are changing the descriptor
|
||||
FirstLevelTable[FirstLevelIdx + i] = Descriptor;
|
||||
ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryAttributes (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 ChunkLength;
|
||||
BOOLEAN FlushTlbs;
|
||||
|
||||
if (BaseAddress > (UINT64)MAX_ADDRESS) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Length = MIN (Length, (UINT64)MAX_ADDRESS - BaseAddress + 1);
|
||||
if (Length == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
FlushTlbs = FALSE;
|
||||
while (Length > 0) {
|
||||
if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&
|
||||
Length >= TT_DESCRIPTOR_SECTION_SIZE) {
|
||||
|
||||
ChunkLength = Length - Length % TT_DESCRIPTOR_SECTION_SIZE;
|
||||
|
||||
DEBUG ((DEBUG_PAGE,
|
||||
"SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n",
|
||||
BaseAddress, ChunkLength, Attributes));
|
||||
|
||||
Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes);
|
||||
|
||||
FlushTlbs = TRUE;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Process page by page until the next section boundary, but only if
|
||||
// we have more than a section's worth of area to deal with after that.
|
||||
//
|
||||
ChunkLength = TT_DESCRIPTOR_SECTION_SIZE -
|
||||
(BaseAddress % TT_DESCRIPTOR_SECTION_SIZE);
|
||||
if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) {
|
||||
ChunkLength = Length;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_PAGE,
|
||||
"SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n",
|
||||
BaseAddress, ChunkLength, Attributes));
|
||||
|
||||
Status = UpdatePageEntries (BaseAddress, ChunkLength, Attributes,
|
||||
&FlushTlbs);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
BaseAddress += ChunkLength;
|
||||
Length -= ChunkLength;
|
||||
}
|
||||
|
||||
if (FlushTlbs) {
|
||||
ArmInvalidateTlb ();
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
)
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);
|
||||
}
|
@@ -14,6 +14,8 @@
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = ArmMmuLib
|
||||
|
||||
[Defines.AARCH64]
|
||||
CONSTRUCTOR = ArmMmuBaseLibConstructor
|
||||
|
||||
[Sources.AARCH64]
|
||||
@@ -21,7 +23,9 @@
|
||||
AArch64/ArmMmuLibReplaceEntry.S
|
||||
|
||||
[Sources.ARM]
|
||||
Arm/ArmMmuLibConvert.c
|
||||
Arm/ArmMmuLibCore.c
|
||||
Arm/ArmMmuLibUpdate.c
|
||||
Arm/ArmMmuLibV7Support.S |GCC
|
||||
Arm/ArmMmuLibV7Support.asm |RVCT
|
||||
|
||||
|
@@ -1,16 +1,16 @@
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Limited. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/ArmSmcLib.h>
|
||||
|
||||
VOID
|
||||
ArmCallSmc (
|
||||
IN OUT ARM_SMC_ARGS *Args
|
||||
)
|
||||
{
|
||||
}
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Limited. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/ArmSmcLib.h>
|
||||
|
||||
VOID
|
||||
ArmCallSmc (
|
||||
IN OUT ARM_SMC_ARGS *Args
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@@ -1,24 +0,0 @@
|
||||
/** @file
|
||||
ResetSystemLib implementation using PSCI calls
|
||||
|
||||
Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <AsmMacroIoLibV8.h>
|
||||
|
||||
ASM_FUNC(DisableMmuAndReenterPei)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
bl ArmDisableMmu
|
||||
|
||||
// no memory accesses after MMU and caches have been disabled
|
||||
|
||||
MOV64 (x0, FixedPcdGet64 (PcdFvBaseAddress))
|
||||
blr x0
|
||||
|
||||
// never returns
|
||||
nop
|
@@ -1,29 +0,0 @@
|
||||
;/** @file
|
||||
; ResetSystemLib implementation using PSCI calls
|
||||
;
|
||||
; Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
;
|
||||
;**/
|
||||
|
||||
AREA Reset, CODE, READONLY
|
||||
|
||||
EXPORT DisableMmuAndReenterPei
|
||||
IMPORT ArmDisableMmu
|
||||
|
||||
DisableMmuAndReenterPei
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
|
||||
bl ArmDisableMmu
|
||||
|
||||
; no memory accesses after MMU and caches have been disabled
|
||||
|
||||
movl x0, FixedPcdGet64 (PcdFvBaseAddress)
|
||||
blr x0
|
||||
|
||||
; never returns
|
||||
nop
|
||||
|
||||
END
|
@@ -1,23 +0,0 @@
|
||||
/** @file
|
||||
ResetSystemLib implementation using PSCI calls
|
||||
|
||||
Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <AsmMacroIoLib.h>
|
||||
|
||||
ASM_FUNC(DisableMmuAndReenterPei)
|
||||
push {lr}
|
||||
|
||||
bl ArmDisableMmu
|
||||
|
||||
// no memory accesses after MMU and caches have been disabled
|
||||
|
||||
MOV32 (r0, FixedPcdGet64 (PcdFvBaseAddress))
|
||||
blx r0
|
||||
|
||||
// never returns
|
||||
nop
|
@@ -1,28 +0,0 @@
|
||||
;/** @file
|
||||
; ResetSystemLib implementation using PSCI calls
|
||||
;
|
||||
; Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
;
|
||||
;**/
|
||||
|
||||
INCLUDE AsmMacroExport.inc
|
||||
PRESERVE8
|
||||
|
||||
IMPORT ArmDisableMmu
|
||||
|
||||
RVCT_ASM_EXPORT DisableMmuAndReenterPei
|
||||
push {lr}
|
||||
|
||||
bl ArmDisableMmu
|
||||
|
||||
; no memory accesses after MMU and caches have been disabled
|
||||
|
||||
mov32 r0, FixedPcdGet64 (PcdFvBaseAddress)
|
||||
blx r0
|
||||
|
||||
; never returns
|
||||
nop
|
||||
|
||||
END
|
@@ -10,13 +10,10 @@
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/ArmMmuLib.h>
|
||||
#include <Library/ArmSmcLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/ResetSystemLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
|
||||
#include <IndustryStandard/ArmStdSmc.h>
|
||||
|
||||
@@ -76,79 +73,6 @@ ResetShutdown (
|
||||
ArmCallSmc (&ArmSmcArgs);
|
||||
}
|
||||
|
||||
VOID DisableMmuAndReenterPei (VOID);
|
||||
|
||||
/**
|
||||
This function causes the system to enter S3 and then wake up immediately.
|
||||
|
||||
If this function returns, it means that the system does not support S3 feature.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
EnterS3WithImmediateWake (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Alloc;
|
||||
EFI_MEMORY_DESCRIPTOR *MemMap;
|
||||
UINTN MemMapSize;
|
||||
UINTN MapKey, DescriptorSize;
|
||||
UINT32 DescriptorVersion;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (FeaturePcdGet (PcdArmReenterPeiForCapsuleWarmReboot) &&
|
||||
!EfiAtRuntime ()) {
|
||||
//
|
||||
// At boot time, we are the only core running, so we can implement the
|
||||
// immediate wake (which is used by capsule update) by disabling the MMU
|
||||
// and interrupts, and jumping to the PEI entry point.
|
||||
//
|
||||
|
||||
//
|
||||
// Obtain the size of the memory map
|
||||
//
|
||||
MemMapSize = 0;
|
||||
MemMap = NULL;
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,
|
||||
&DescriptorVersion);
|
||||
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||
|
||||
//
|
||||
// Add some slack to the allocation to cater for changes in the memory
|
||||
// map if ExitBootServices () fails the first time around.
|
||||
//
|
||||
MemMapSize += SIZE_4KB;
|
||||
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData,
|
||||
EFI_SIZE_TO_PAGES (MemMapSize), &Alloc);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
MemMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN)Alloc;
|
||||
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,
|
||||
&DescriptorVersion);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gBS->ExitBootServices (gImageHandle, MapKey);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// ExitBootServices () may fail the first time around if an event fired
|
||||
// right after the call to GetMemoryMap() which allocated or freed memory.
|
||||
// Since that first call to ExitBootServices () will disarm the timer,
|
||||
// this is guaranteed not to happen again, so one additional attempt
|
||||
// should suffice.
|
||||
//
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize,
|
||||
&DescriptorVersion);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gBS->ExitBootServices (gImageHandle, MapKey);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
DisableMmuAndReenterPei ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes a systemwide reset. The exact type of the reset is
|
||||
defined by the EFI_GUID that follows the Null-terminated Unicode string passed
|
||||
|
@@ -15,14 +15,6 @@
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = ResetSystemLib
|
||||
|
||||
[Sources.AARCH64]
|
||||
AArch64/Reset.S | GCC
|
||||
AArch64/Reset.asm | MSFT
|
||||
|
||||
[Sources.ARM]
|
||||
Arm/Reset.S | GCC
|
||||
Arm/Reset.asm | RVCT
|
||||
|
||||
[Sources]
|
||||
ArmSmcPsciResetSystemLib.c
|
||||
|
||||
@@ -32,15 +24,6 @@
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmMmuLib
|
||||
ArmSmcLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
UefiBootServicesTableLib
|
||||
UefiRuntimeLib
|
||||
|
||||
[FeaturePcd]
|
||||
gArmTokenSpaceGuid.PcdArmReenterPeiForCapsuleWarmReboot
|
||||
|
||||
[FixedPcd]
|
||||
gArmTokenSpaceGuid.PcdFvBaseAddress
|
||||
|
@@ -1,283 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - 2019, Linaro Limited
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include <softfloat.h>
|
||||
|
||||
/*
|
||||
* On ARM32 EABI defines both a soft-float ABI and a hard-float ABI,
|
||||
* hard-float is basically a super set of soft-float. Hard-float requires
|
||||
* all the support routines provided for soft-float, but the compiler may
|
||||
* choose to optimize to not use some of them.
|
||||
*
|
||||
* The AEABI functions uses soft-float calling convention even if the
|
||||
* functions are compiled for hard-float. So where float and double would
|
||||
* have been expected we use aeabi_float_t and aeabi_double_t respectively
|
||||
* instead.
|
||||
*/
|
||||
typedef uint32_t aeabi_float_t;
|
||||
typedef uint64_t aeabi_double_t;
|
||||
|
||||
/*
|
||||
* Helpers to convert between float32 and aeabi_float_t, and float64 and
|
||||
* aeabi_double_t used by the AEABI functions below.
|
||||
*/
|
||||
static aeabi_float_t f32_to_f(float32_t val)
|
||||
{
|
||||
return val.v;
|
||||
}
|
||||
|
||||
static float32_t f32_from_f(aeabi_float_t val)
|
||||
{
|
||||
float32_t res;
|
||||
|
||||
res.v = val;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static aeabi_double_t f64_to_d(float64_t val)
|
||||
{
|
||||
return val.v;
|
||||
}
|
||||
|
||||
static float64_t f64_from_d(aeabi_double_t val)
|
||||
{
|
||||
float64_t res;
|
||||
|
||||
res.v = val;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* From ARM Run-time ABI for ARM Architecture
|
||||
* ARM IHI 0043D, current through ABI release 2.09
|
||||
*
|
||||
* 4.1.2 The floating-point helper functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Table 2, Standard aeabi_double_t precision floating-point arithmetic helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
|
||||
aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 3, double precision floating-point comparison helper functions
|
||||
*/
|
||||
|
||||
int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_eq(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_lt(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_le(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_le(f64_from_d(b), f64_from_d(a));
|
||||
}
|
||||
|
||||
int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_lt(f64_from_d(b), f64_from_d(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 4, Standard single precision floating-point arithmetic helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 5, Standard single precision floating-point comparison helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_eq(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_lt(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_le(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_le(f32_from_f(b), f32_from_f(a));
|
||||
}
|
||||
|
||||
int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_lt(f32_from_f(b), f32_from_f(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 6, Standard floating-point to integer conversions
|
||||
*/
|
||||
|
||||
int __aeabi_d2iz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_i32_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
unsigned __aeabi_d2uiz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_ui32_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
long long __aeabi_d2lz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_i64_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
unsigned long long __aeabi_d2ulz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_ui64_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
int __aeabi_f2iz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_i32_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
unsigned __aeabi_f2uiz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_ui32_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
long long __aeabi_f2lz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_i64_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
unsigned long long __aeabi_f2ulz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_ui64_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 7, Standard conversions between floating types
|
||||
*/
|
||||
|
||||
aeabi_float_t __aeabi_d2f(aeabi_double_t a)
|
||||
{
|
||||
return f32_to_f(f64_to_f32(f64_from_d(a)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_f2d(aeabi_float_t a)
|
||||
{
|
||||
return f64_to_d(f32_to_f64(f32_from_f(a)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 8, Standard integer to floating-point conversions
|
||||
*/
|
||||
|
||||
aeabi_double_t __aeabi_i2d(int a)
|
||||
{
|
||||
return f64_to_d(i32_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ui2d(unsigned a)
|
||||
{
|
||||
return f64_to_d(ui32_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_l2d(long long a)
|
||||
{
|
||||
return f64_to_d(i64_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ul2d(unsigned long long a)
|
||||
{
|
||||
return f64_to_d(ui64_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_i2f(int a)
|
||||
{
|
||||
return f32_to_f(i32_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_ui2f(unsigned a)
|
||||
{
|
||||
return f32_to_f(ui32_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_l2f(long long a)
|
||||
{
|
||||
return f32_to_f(i64_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_ul2f(unsigned long long a)
|
||||
{
|
||||
return f32_to_f(ui64_to_f32(a));
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2015 - 2019, Linaro Limited
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include <softfloat.h>
|
||||
|
||||
/*
|
||||
* On ARM32 EABI defines both a soft-float ABI and a hard-float ABI,
|
||||
* hard-float is basically a super set of soft-float. Hard-float requires
|
||||
* all the support routines provided for soft-float, but the compiler may
|
||||
* choose to optimize to not use some of them.
|
||||
*
|
||||
* The AEABI functions uses soft-float calling convention even if the
|
||||
* functions are compiled for hard-float. So where float and double would
|
||||
* have been expected we use aeabi_float_t and aeabi_double_t respectively
|
||||
* instead.
|
||||
*/
|
||||
typedef uint32_t aeabi_float_t;
|
||||
typedef uint64_t aeabi_double_t;
|
||||
|
||||
/*
|
||||
* Helpers to convert between float32 and aeabi_float_t, and float64 and
|
||||
* aeabi_double_t used by the AEABI functions below.
|
||||
*/
|
||||
static aeabi_float_t f32_to_f(float32_t val)
|
||||
{
|
||||
return val.v;
|
||||
}
|
||||
|
||||
static float32_t f32_from_f(aeabi_float_t val)
|
||||
{
|
||||
float32_t res;
|
||||
|
||||
res.v = val;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static aeabi_double_t f64_to_d(float64_t val)
|
||||
{
|
||||
return val.v;
|
||||
}
|
||||
|
||||
static float64_t f64_from_d(aeabi_double_t val)
|
||||
{
|
||||
float64_t res;
|
||||
|
||||
res.v = val;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* From ARM Run-time ABI for ARM Architecture
|
||||
* ARM IHI 0043D, current through ABI release 2.09
|
||||
*
|
||||
* 4.1.2 The floating-point helper functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Table 2, Standard aeabi_double_t precision floating-point arithmetic helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
|
||||
aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 3, double precision floating-point comparison helper functions
|
||||
*/
|
||||
|
||||
int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_eq(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_lt(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_le(f64_from_d(a), f64_from_d(b));
|
||||
}
|
||||
|
||||
int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_le(f64_from_d(b), f64_from_d(a));
|
||||
}
|
||||
|
||||
int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b)
|
||||
{
|
||||
return f64_lt(f64_from_d(b), f64_from_d(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 4, Standard single precision floating-point arithmetic helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a)));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 5, Standard single precision floating-point comparison helper
|
||||
* functions
|
||||
*/
|
||||
|
||||
int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_eq(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_lt(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_le(f32_from_f(a), f32_from_f(b));
|
||||
}
|
||||
|
||||
int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_le(f32_from_f(b), f32_from_f(a));
|
||||
}
|
||||
|
||||
int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b)
|
||||
{
|
||||
return f32_lt(f32_from_f(b), f32_from_f(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 6, Standard floating-point to integer conversions
|
||||
*/
|
||||
|
||||
int __aeabi_d2iz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_i32_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
unsigned __aeabi_d2uiz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_ui32_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
long long __aeabi_d2lz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_i64_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
unsigned long long __aeabi_d2ulz(aeabi_double_t a)
|
||||
{
|
||||
return f64_to_ui64_r_minMag(f64_from_d(a), false);
|
||||
}
|
||||
|
||||
int __aeabi_f2iz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_i32_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
unsigned __aeabi_f2uiz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_ui32_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
long long __aeabi_f2lz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_i64_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
unsigned long long __aeabi_f2ulz(aeabi_float_t a)
|
||||
{
|
||||
return f32_to_ui64_r_minMag(f32_from_f(a), false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 7, Standard conversions between floating types
|
||||
*/
|
||||
|
||||
aeabi_float_t __aeabi_d2f(aeabi_double_t a)
|
||||
{
|
||||
return f32_to_f(f64_to_f32(f64_from_d(a)));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_f2d(aeabi_float_t a)
|
||||
{
|
||||
return f64_to_d(f32_to_f64(f32_from_f(a)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Table 8, Standard integer to floating-point conversions
|
||||
*/
|
||||
|
||||
aeabi_double_t __aeabi_i2d(int a)
|
||||
{
|
||||
return f64_to_d(i32_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ui2d(unsigned a)
|
||||
{
|
||||
return f64_to_d(ui32_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_l2d(long long a)
|
||||
{
|
||||
return f64_to_d(i64_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_double_t __aeabi_ul2d(unsigned long long a)
|
||||
{
|
||||
return f64_to_d(ui64_to_f64(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_i2f(int a)
|
||||
{
|
||||
return f32_to_f(i32_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_ui2f(unsigned a)
|
||||
{
|
||||
return f32_to_f(ui32_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_l2f(long long a)
|
||||
{
|
||||
return f32_to_f(i64_to_f32(a));
|
||||
}
|
||||
|
||||
aeabi_float_t __aeabi_ul2f(unsigned long long a)
|
||||
{
|
||||
return f32_to_f(ui64_to_f32(a));
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2012 - 2017, ARM Limited. All rights reserved.
|
||||
// Copyright (c) 2012 - 2020, ARM Limited. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
@@ -25,6 +25,9 @@ ASM_PFX(ArmCallSvc):
|
||||
ldp x0, x1, [x0, #0]
|
||||
|
||||
svc #0
|
||||
// Prevent speculative execution beyond svc instruction
|
||||
dsb nsh
|
||||
isb
|
||||
|
||||
// Pop the ARM_SVC_ARGS structure address from the stack into x9
|
||||
ldr x9, [sp, #16]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
|
||||
// Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
@@ -18,6 +18,9 @@ ASM_PFX(ArmCallSvc):
|
||||
ldm r0, {r0-r7}
|
||||
|
||||
svc #0
|
||||
// Prevent speculative execution beyond svc instruction
|
||||
dsb nsh
|
||||
isb
|
||||
|
||||
// Load the ARM_SVC_ARGS structure address from the stack into r8
|
||||
ldr r8, [sp]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
|
||||
// Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
@@ -16,6 +16,9 @@
|
||||
ldm r0, {r0-r7}
|
||||
|
||||
svc #0
|
||||
// Prevent speculative execution beyond svc instruction
|
||||
dsb nsh
|
||||
isb
|
||||
|
||||
// Load the ARM_SVC_ARGS structure address from the stack into r8
|
||||
ldr r8, [sp]
|
||||
|
142
ArmPkg/Library/CompilerIntrinsicsLib/AArch64/Atomics.S
Normal file
142
ArmPkg/Library/CompilerIntrinsicsLib/AArch64/Atomics.S
Normal file
@@ -0,0 +1,142 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2020, Arm, Limited. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Provide the GCC intrinsics that are required when using GCC 9 or
|
||||
* later with the -moutline-atomics options (which became the default
|
||||
* in GCC 10)
|
||||
*/
|
||||
.arch armv8-a
|
||||
|
||||
.macro reg_alias, pfx, sz
|
||||
r0_\sz .req \pfx\()0
|
||||
r1_\sz .req \pfx\()1
|
||||
tmp0_\sz .req \pfx\()16
|
||||
tmp1_\sz .req \pfx\()17
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define register aliases of the right type for each size
|
||||
* (xN for 8 bytes, wN for everything smaller)
|
||||
*/
|
||||
reg_alias w, 1
|
||||
reg_alias w, 2
|
||||
reg_alias w, 4
|
||||
reg_alias x, 8
|
||||
|
||||
.macro fn_start, name:req
|
||||
.section .text.\name
|
||||
.globl \name
|
||||
.type \name, %function
|
||||
\name\():
|
||||
.endm
|
||||
|
||||
.macro fn_end, name:req
|
||||
.size \name, . - \name
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Emit an atomic helper for \model with operands of size \sz, using
|
||||
* the operation specified by \insn (which is the LSE name), and which
|
||||
* can be implemented using the generic load-locked/store-conditional
|
||||
* (LL/SC) sequence below, using the arithmetic operation given by
|
||||
* \opc.
|
||||
*/
|
||||
.macro emit_ld_sz, sz:req, insn:req, opc:req, model:req, s, a, l
|
||||
fn_start __aarch64_\insn\()\sz\()\model
|
||||
mov tmp0_\sz, r0_\sz
|
||||
0: ld\a\()xr\s r0_\sz, [x1]
|
||||
.ifnc \insn, swp
|
||||
\opc tmp1_\sz, r0_\sz, tmp0_\sz
|
||||
st\l\()xr\s w15, tmp1_\sz, [x1]
|
||||
.else
|
||||
st\l\()xr\s w15, tmp0_\sz, [x1]
|
||||
.endif
|
||||
cbnz w15, 0b
|
||||
ret
|
||||
fn_end __aarch64_\insn\()\sz\()\model
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Emit atomic helpers for \model for operand sizes in the
|
||||
* set {1, 2, 4, 8}, for the instruction pattern given by
|
||||
* \insn. (This is the LSE name, but this implementation uses
|
||||
* the generic LL/SC sequence using \opc as the arithmetic
|
||||
* operation on the target.)
|
||||
*/
|
||||
.macro emit_ld, insn:req, opc:req, model:req, a, l
|
||||
emit_ld_sz 1, \insn, \opc, \model, b, \a, \l
|
||||
emit_ld_sz 2, \insn, \opc, \model, h, \a, \l
|
||||
emit_ld_sz 4, \insn, \opc, \model, , \a, \l
|
||||
emit_ld_sz 8, \insn, \opc, \model, , \a, \l
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Emit the compare and swap helper for \model and size \sz
|
||||
* using LL/SC instructions.
|
||||
*/
|
||||
.macro emit_cas_sz, sz:req, model:req, uxt:req, s, a, l
|
||||
fn_start __aarch64_cas\sz\()\model
|
||||
\uxt tmp0_\sz, r0_\sz
|
||||
0: ld\a\()xr\s r0_\sz, [x2]
|
||||
cmp r0_\sz, tmp0_\sz
|
||||
bne 1f
|
||||
st\l\()xr\s w15, r1_\sz, [x2]
|
||||
cbnz w15, 0b
|
||||
1: ret
|
||||
fn_end __aarch64_cas\sz\()\model
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Emit compare-and-swap helpers for \model for operand sizes in the
|
||||
* set {1, 2, 4, 8, 16}.
|
||||
*/
|
||||
.macro emit_cas, model:req, a, l
|
||||
emit_cas_sz 1, \model, uxtb, b, \a, \l
|
||||
emit_cas_sz 2, \model, uxth, h, \a, \l
|
||||
emit_cas_sz 4, \model, mov , , \a, \l
|
||||
emit_cas_sz 8, \model, mov , , \a, \l
|
||||
|
||||
/*
|
||||
* We cannot use the parameterized sequence for 16 byte CAS, so we
|
||||
* need to define it explicitly.
|
||||
*/
|
||||
fn_start __aarch64_cas16\model
|
||||
mov x16, x0
|
||||
mov x17, x1
|
||||
0: ld\a\()xp x0, x1, [x4]
|
||||
cmp x0, x16
|
||||
ccmp x1, x17, #0, eq
|
||||
bne 1f
|
||||
st\l\()xp w15, x16, x17, [x4]
|
||||
cbnz w15, 0b
|
||||
1: ret
|
||||
fn_end __aarch64_cas16\model
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Emit the set of GCC outline atomic helper functions for
|
||||
* the memory ordering model given by \model:
|
||||
* - relax unordered loads and stores
|
||||
* - acq load-acquire, unordered store
|
||||
* - rel unordered load, store-release
|
||||
* - acq_rel load-acquire, store-release
|
||||
*/
|
||||
.macro emit_model, model:req, a, l
|
||||
emit_ld ldadd, add, \model, \a, \l
|
||||
emit_ld ldclr, bic, \model, \a, \l
|
||||
emit_ld ldeor, eor, \model, \a, \l
|
||||
emit_ld ldset, orr, \model, \a, \l
|
||||
emit_ld swp, mov, \model, \a, \l
|
||||
emit_cas \model, \a, \l
|
||||
.endm
|
||||
|
||||
emit_model _relax
|
||||
emit_model _acq, a
|
||||
emit_model _rel,, l
|
||||
emit_model _acq_rel, a, l
|
@@ -79,6 +79,9 @@
|
||||
Arm/ldivmod.asm | MSFT
|
||||
Arm/llsr.asm | MSFT
|
||||
|
||||
[Sources.AARCH64]
|
||||
AArch64/Atomics.S | GCC
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
@@ -1,55 +1,55 @@
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
static __attribute__((__used__))
|
||||
void *__memset(void *s, int c, size_t n)
|
||||
{
|
||||
unsigned char *d = s;
|
||||
|
||||
while (n--)
|
||||
*d++ = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// Other modules (such as CryptoPkg/IntrinsicLib) may provide another
|
||||
// implementation of memset(), which may conflict with this one if this
|
||||
// object was pulled into the link due to the definitions below. So make
|
||||
// our memset() 'weak' to let the other implementation take precedence.
|
||||
//
|
||||
__attribute__((__weak__, __alias__("__memset")))
|
||||
void *memset(void *dest, int c, size_t n);
|
||||
|
||||
#ifdef __arm__
|
||||
|
||||
void __aeabi_memset(void *dest, size_t n, int c)
|
||||
{
|
||||
__memset(dest, c, n);
|
||||
}
|
||||
|
||||
__attribute__((__alias__("__aeabi_memset")))
|
||||
void __aeabi_memset4(void *dest, size_t n, int c);
|
||||
|
||||
__attribute__((__alias__("__aeabi_memset")))
|
||||
void __aeabi_memset8(void *dest, size_t n, int c);
|
||||
|
||||
void __aeabi_memclr(void *dest, size_t n)
|
||||
{
|
||||
__memset(dest, 0, n);
|
||||
}
|
||||
|
||||
__attribute__((__alias__("__aeabi_memclr")))
|
||||
void __aeabi_memclr4(void *dest, size_t n);
|
||||
|
||||
__attribute__((__alias__("__aeabi_memclr")))
|
||||
void __aeabi_memclr8(void *dest, size_t n);
|
||||
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
static __attribute__((__used__))
|
||||
void *__memset(void *s, int c, size_t n)
|
||||
{
|
||||
unsigned char *d = s;
|
||||
|
||||
while (n--)
|
||||
*d++ = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//
|
||||
// Other modules (such as CryptoPkg/IntrinsicLib) may provide another
|
||||
// implementation of memset(), which may conflict with this one if this
|
||||
// object was pulled into the link due to the definitions below. So make
|
||||
// our memset() 'weak' to let the other implementation take precedence.
|
||||
//
|
||||
__attribute__((__weak__, __alias__("__memset")))
|
||||
void *memset(void *dest, int c, size_t n);
|
||||
|
||||
#ifdef __arm__
|
||||
|
||||
void __aeabi_memset(void *dest, size_t n, int c)
|
||||
{
|
||||
__memset(dest, c, n);
|
||||
}
|
||||
|
||||
__attribute__((__alias__("__aeabi_memset")))
|
||||
void __aeabi_memset4(void *dest, size_t n, int c);
|
||||
|
||||
__attribute__((__alias__("__aeabi_memset")))
|
||||
void __aeabi_memset8(void *dest, size_t n, int c);
|
||||
|
||||
void __aeabi_memclr(void *dest, size_t n)
|
||||
{
|
||||
__memset(dest, 0, n);
|
||||
}
|
||||
|
||||
__attribute__((__alias__("__aeabi_memclr")))
|
||||
void __aeabi_memclr4(void *dest, size_t n);
|
||||
|
||||
__attribute__((__alias__("__aeabi_memclr")))
|
||||
void __aeabi_memclr8(void *dest, size_t n);
|
||||
|
||||
#endif
|
||||
|
@@ -1,21 +1,21 @@
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
|
||||
//
|
||||
// GCC in LTO mode interoperates poorly with non-standard libraries that
|
||||
// provide implementations of compiler intrinsics such as memcpy/memset
|
||||
// or the stack protector entry points.
|
||||
//
|
||||
// By referencing these functions from a non-LTO object that can be passed
|
||||
// to the linker via the -plugin-opt=-pass-through=-lxxx options, the
|
||||
// intrinsics are included in the link in a way that allows them to be
|
||||
// pruned again if no other references to them exist.
|
||||
//
|
||||
|
||||
.long memcpy - .
|
||||
.long memset - .
|
||||
.long __stack_chk_fail - .
|
||||
.long __stack_chk_guard - .
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
|
||||
//
|
||||
// GCC in LTO mode interoperates poorly with non-standard libraries that
|
||||
// provide implementations of compiler intrinsics such as memcpy/memset
|
||||
// or the stack protector entry points.
|
||||
//
|
||||
// By referencing these functions from a non-LTO object that can be passed
|
||||
// to the linker via the -plugin-opt=-pass-through=-lxxx options, the
|
||||
// intrinsics are included in the link in a way that allows them to be
|
||||
// pruned again if no other references to them exist.
|
||||
//
|
||||
|
||||
.long memcpy - .
|
||||
.long memset - .
|
||||
.long __stack_chk_fail - .
|
||||
.long __stack_chk_guard - .
|
||||
|
@@ -1,55 +1,55 @@
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
|
||||
//
|
||||
// GCC in LTO mode interoperates poorly with non-standard libraries that
|
||||
// provide implementations of compiler intrinsics such as memcpy/memset
|
||||
// or the stack protector entry points.
|
||||
//
|
||||
// By referencing these functions from a non-LTO object that can be passed
|
||||
// to the linker via the -plugin-opt=-pass-through=-lxxx options, the
|
||||
// intrinsics are included in the link in a way that allows them to be
|
||||
// pruned again if no other references to them exist.
|
||||
//
|
||||
|
||||
.long memcpy - .
|
||||
.long memset - .
|
||||
.long __stack_chk_fail - .
|
||||
.long __stack_chk_guard - .
|
||||
.long __ashrdi3 - .
|
||||
.long __ashldi3 - .
|
||||
.long __aeabi_idiv - .
|
||||
.long __aeabi_idivmod - .
|
||||
.long __aeabi_uidiv - .
|
||||
.long __aeabi_uidivmod - .
|
||||
.long __divdi3 - .
|
||||
.long __divsi3 - .
|
||||
.long __lshrdi3 - .
|
||||
.long __aeabi_memcpy - .
|
||||
.long __aeabi_memset - .
|
||||
.long memmove - .
|
||||
.long __modsi3 - .
|
||||
.long __moddi3 - .
|
||||
.long __muldi3 - .
|
||||
.long __aeabi_lmul - .
|
||||
.long __ARM_ll_mullu - .
|
||||
.long __udivsi3 - .
|
||||
.long __umodsi3 - .
|
||||
.long __udivdi3 - .
|
||||
.long __umoddi3 - .
|
||||
.long __udivmoddi4 - .
|
||||
.long __clzsi2 - .
|
||||
.long __ctzsi2 - .
|
||||
.long __ucmpdi2 - .
|
||||
.long __switch8 - .
|
||||
.long __switchu8 - .
|
||||
.long __switch16 - .
|
||||
.long __switch32 - .
|
||||
.long __aeabi_ulcmp - .
|
||||
.long __aeabi_uldivmod - .
|
||||
.long __aeabi_ldivmod - .
|
||||
.long __aeabi_llsr - .
|
||||
.long __aeabi_llsl - .
|
||||
//
|
||||
// Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
|
||||
//
|
||||
// GCC in LTO mode interoperates poorly with non-standard libraries that
|
||||
// provide implementations of compiler intrinsics such as memcpy/memset
|
||||
// or the stack protector entry points.
|
||||
//
|
||||
// By referencing these functions from a non-LTO object that can be passed
|
||||
// to the linker via the -plugin-opt=-pass-through=-lxxx options, the
|
||||
// intrinsics are included in the link in a way that allows them to be
|
||||
// pruned again if no other references to them exist.
|
||||
//
|
||||
|
||||
.long memcpy - .
|
||||
.long memset - .
|
||||
.long __stack_chk_fail - .
|
||||
.long __stack_chk_guard - .
|
||||
.long __ashrdi3 - .
|
||||
.long __ashldi3 - .
|
||||
.long __aeabi_idiv - .
|
||||
.long __aeabi_idivmod - .
|
||||
.long __aeabi_uidiv - .
|
||||
.long __aeabi_uidivmod - .
|
||||
.long __divdi3 - .
|
||||
.long __divsi3 - .
|
||||
.long __lshrdi3 - .
|
||||
.long __aeabi_memcpy - .
|
||||
.long __aeabi_memset - .
|
||||
.long memmove - .
|
||||
.long __modsi3 - .
|
||||
.long __moddi3 - .
|
||||
.long __muldi3 - .
|
||||
.long __aeabi_lmul - .
|
||||
.long __ARM_ll_mullu - .
|
||||
.long __udivsi3 - .
|
||||
.long __umodsi3 - .
|
||||
.long __udivdi3 - .
|
||||
.long __umoddi3 - .
|
||||
.long __udivmoddi4 - .
|
||||
.long __clzsi2 - .
|
||||
.long __ctzsi2 - .
|
||||
.long __ucmpdi2 - .
|
||||
.long __switch8 - .
|
||||
.long __switchu8 - .
|
||||
.long __switch16 - .
|
||||
.long __switch32 - .
|
||||
.long __aeabi_ulcmp - .
|
||||
.long __aeabi_uldivmod - .
|
||||
.long __aeabi_ldivmod - .
|
||||
.long __aeabi_llsr - .
|
||||
.long __aeabi_llsl - .
|
||||
|
@@ -2,7 +2,7 @@
|
||||
Implementation for PlatformBootManagerLib library class interfaces.
|
||||
|
||||
Copyright (C) 2015-2016, Red Hat, Inc.
|
||||
Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2014 - 2019, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
#include <Protocol/EsrtManagement.h>
|
||||
#include <Protocol/GraphicsOutput.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/NonDiscoverableDevice.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/PciRootBridgeIo.h>
|
||||
#include <Protocol/PlatformBootManager.h>
|
||||
#include <Guid/EventGroup.h>
|
||||
#include <Guid/NonDiscoverableDevice.h>
|
||||
#include <Guid/TtyTerm.h>
|
||||
#include <Guid/SerialPortLibVendor.h>
|
||||
|
||||
@@ -254,6 +256,37 @@ IsPciDisplay (
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
|
||||
USB host controller.
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsUsbHost (
|
||||
IN EFI_HANDLE Handle,
|
||||
IN CONST CHAR16 *ReportText
|
||||
)
|
||||
{
|
||||
NON_DISCOVERABLE_DEVICE *Device;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->HandleProtocol (Handle,
|
||||
&gEdkiiNonDiscoverableDeviceProtocolGuid,
|
||||
(VOID **)&Device);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (CompareGuid (Device->Type, &gEdkiiNonDiscoverableUhciDeviceGuid) ||
|
||||
CompareGuid (Device->Type, &gEdkiiNonDiscoverableEhciDeviceGuid) ||
|
||||
CompareGuid (Device->Type, &gEdkiiNonDiscoverableXhciDeviceGuid)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
|
||||
the matching driver to produce all first-level child handles.
|
||||
@@ -324,7 +357,8 @@ VOID
|
||||
PlatformRegisterFvBootOption (
|
||||
CONST EFI_GUID *FileGuid,
|
||||
CHAR16 *Description,
|
||||
UINT32 Attributes
|
||||
UINT32 Attributes,
|
||||
EFI_INPUT_KEY *Key
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
@@ -376,6 +410,9 @@ PlatformRegisterFvBootOption (
|
||||
if (OptionIndex == -1) {
|
||||
Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Status = EfiBootManagerAddKeyOptionVariable (NULL,
|
||||
(UINT16)NewOption.OptionNumber, 0, Key, NULL);
|
||||
ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
|
||||
}
|
||||
EfiBootManagerFreeLoadOption (&NewOption);
|
||||
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
|
||||
@@ -549,6 +586,11 @@ PlatformBootManagerBeforeConsole (
|
||||
//
|
||||
EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
|
||||
|
||||
//
|
||||
// Dispatch deferred images after EndOfDxe event.
|
||||
//
|
||||
EfiBootManagerDispatchDeferredImages ();
|
||||
|
||||
//
|
||||
// Locate the PCI root bridges and make the PCI bus driver connect each,
|
||||
// non-recursively. This will produce a number of child handles with PciIo on
|
||||
@@ -569,6 +611,15 @@ PlatformBootManagerBeforeConsole (
|
||||
//
|
||||
FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
|
||||
|
||||
//
|
||||
// The core BDS code connects short-form USB device paths by explicitly
|
||||
// looking for handles with PCI I/O installed, and checking the PCI class
|
||||
// code whether it matches the one for a USB host controller. This means
|
||||
// non-discoverable USB host controllers need to have the non-discoverable
|
||||
// PCI driver attached first.
|
||||
//
|
||||
FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid, IsUsbHost, Connect);
|
||||
|
||||
//
|
||||
// Add the hardcoded short-form USB keyboard device path to ConIn.
|
||||
//
|
||||
@@ -578,7 +629,13 @@ PlatformBootManagerBeforeConsole (
|
||||
//
|
||||
// Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
|
||||
//
|
||||
ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4);
|
||||
STATIC_ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4,
|
||||
"PcdDefaultTerminalType must be TTYTERM");
|
||||
STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultParity) != 0,
|
||||
"PcdUartDefaultParity must be set to an actual value, not 'default'");
|
||||
STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultStopBits) != 0,
|
||||
"PcdUartDefaultStopBits must be set to an actual value, not 'default'");
|
||||
|
||||
CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);
|
||||
|
||||
EfiBootManagerUpdateConsoleVariable (ConIn,
|
||||
@@ -668,6 +725,7 @@ PlatformBootManagerAfterConsole (
|
||||
UINTN FirmwareVerLength;
|
||||
UINTN PosX;
|
||||
UINTN PosY;
|
||||
EFI_INPUT_KEY Key;
|
||||
|
||||
FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
|
||||
|
||||
@@ -695,11 +753,6 @@ PlatformBootManagerAfterConsole (
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Connect the rest of the devices.
|
||||
//
|
||||
EfiBootManagerConnectAll ();
|
||||
|
||||
//
|
||||
// On ARM, there is currently no reason to use the phased capsule
|
||||
// update approach where some capsules are dispatched before EndOfDxe
|
||||
@@ -709,17 +762,12 @@ PlatformBootManagerAfterConsole (
|
||||
//
|
||||
HandleCapsules ();
|
||||
|
||||
//
|
||||
// Enumerate all possible boot options.
|
||||
//
|
||||
EfiBootManagerRefreshAllBootOption ();
|
||||
|
||||
//
|
||||
// Register UEFI Shell
|
||||
//
|
||||
PlatformRegisterFvBootOption (
|
||||
&gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE
|
||||
);
|
||||
Key.ScanCode = SCAN_NULL;
|
||||
Key.UnicodeChar = L's';
|
||||
PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", 0, &Key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -770,5 +818,49 @@ PlatformBootManagerUnableToBoot (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return;
|
||||
EFI_STATUS Status;
|
||||
EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
|
||||
EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
|
||||
UINTN OldBootOptionCount;
|
||||
UINTN NewBootOptionCount;
|
||||
|
||||
//
|
||||
// Record the total number of boot configured boot options
|
||||
//
|
||||
BootOptions = EfiBootManagerGetLoadOptions (&OldBootOptionCount,
|
||||
LoadOptionTypeBoot);
|
||||
EfiBootManagerFreeLoadOptions (BootOptions, OldBootOptionCount);
|
||||
|
||||
//
|
||||
// Connect all devices, and regenerate all boot options
|
||||
//
|
||||
EfiBootManagerConnectAll ();
|
||||
EfiBootManagerRefreshAllBootOption ();
|
||||
|
||||
//
|
||||
// Record the updated number of boot configured boot options
|
||||
//
|
||||
BootOptions = EfiBootManagerGetLoadOptions (&NewBootOptionCount,
|
||||
LoadOptionTypeBoot);
|
||||
EfiBootManagerFreeLoadOptions (BootOptions, NewBootOptionCount);
|
||||
|
||||
//
|
||||
// If the number of configured boot options has changed, reboot
|
||||
// the system so the new boot options will be taken into account
|
||||
// while executing the ordinary BDS bootflow sequence.
|
||||
//
|
||||
if (NewBootOptionCount != OldBootOptionCount) {
|
||||
DEBUG ((DEBUG_WARN, "%a: rebooting after refreshing all boot options\n",
|
||||
__FUNCTION__));
|
||||
gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
}
|
||||
|
||||
Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
EfiBootManagerBoot (&BootManagerMenu);
|
||||
}
|
||||
}
|
||||
|
@@ -66,6 +66,9 @@
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
|
||||
|
||||
[Guids]
|
||||
gEdkiiNonDiscoverableEhciDeviceGuid
|
||||
gEdkiiNonDiscoverableUhciDeviceGuid
|
||||
gEdkiiNonDiscoverableXhciDeviceGuid
|
||||
gEfiFileInfoGuid
|
||||
gEfiFileSystemInfoGuid
|
||||
gEfiFileSystemVolumeLabelInfoIdGuid
|
||||
@@ -74,6 +77,7 @@
|
||||
gUefiShellFileGuid
|
||||
|
||||
[Protocols]
|
||||
gEdkiiNonDiscoverableDeviceProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
|
@@ -94,10 +94,6 @@
|
||||
gArmPlatformTokenSpaceGuid.PcdArmMaliDpBase|0x0|UINT64|0x00000050
|
||||
gArmPlatformTokenSpaceGuid.PcdArmMaliDpMemoryRegionLength|0x0|UINT32|0x00000051
|
||||
|
||||
## PL180 MCI
|
||||
gArmPlatformTokenSpaceGuid.PcdPL180SysMciRegAddress|0x00000000|UINT32|0x00000028
|
||||
gArmPlatformTokenSpaceGuid.PcdPL180MciBaseAddress|0x00000000|UINT32|0x00000029
|
||||
|
||||
# Graphics Output Pixel format
|
||||
# 0 : PixelRedGreenBlueReserved8BitPerColor
|
||||
# 1 : PixelBlueGreenRedReserved8BitPerColor
|
||||
|
@@ -4,6 +4,7 @@
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.<BR>
|
||||
# Copyright (c) 2016 - 2017, Linaro Ltd. All rights reserved.<BR>
|
||||
# Copyright (c) Microsoft Corporation.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
@@ -90,11 +91,11 @@
|
||||
ArmPlatformPkg/Drivers/LcdGraphicsOutputDxe/LcdGraphicsOutputDxe.inf
|
||||
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
|
||||
ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf
|
||||
ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
|
||||
ArmPlatformPkg/Drivers/SP805WatchdogDxe/SP805WatchdogDxe.inf
|
||||
|
||||
ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
|
||||
ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf
|
||||
ArmPlatformPkg/Library/HdLcd/HdLcd.inf
|
||||
ArmPlatformPkg/Library/LcdHwNullLib/LcdHwNullLib.inf
|
||||
ArmPlatformPkg/Library/LcdPlatformNullLib/LcdPlatformNullLib.inf
|
||||
ArmPlatformPkg/Library/NorFlashPlatformNullLib/NorFlashPlatformNullLib.inf
|
||||
@@ -102,6 +103,7 @@
|
||||
ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
|
||||
ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
|
||||
ArmPlatformPkg/Library/PL031RealTimeClockLib/PL031RealTimeClockLib.inf
|
||||
ArmPlatformPkg/Library/PL111Lcd/PL111Lcd.inf
|
||||
ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
|
||||
|
||||
ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf
|
||||
|
@@ -38,6 +38,7 @@
|
||||
UefiLib
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
|
||||
|
@@ -1,563 +0,0 @@
|
||||
/** @file
|
||||
This file implement the MMC Host Protocol for the ARM PrimeCell PL180.
|
||||
|
||||
Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "PL180Mci.h"
|
||||
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
|
||||
EFI_MMC_HOST_PROTOCOL *gpMmcHost;
|
||||
|
||||
// Untested ...
|
||||
//#define USE_STREAM
|
||||
|
||||
#define MMCI0_BLOCKLEN 512
|
||||
#define MMCI0_POW2_BLOCKLEN 9
|
||||
#define MMCI0_TIMEOUT 1000
|
||||
|
||||
#define SYS_MCI_CARDIN BIT0
|
||||
#define SYS_MCI_WPROT BIT1
|
||||
|
||||
BOOLEAN
|
||||
MciIsPowerOn (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return ((MmioRead32 (MCI_POWER_CONTROL_REG) & MCI_POWER_ON) == MCI_POWER_ON);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
MCI_TRACE ("MciInitialize()");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MciIsCardPresent (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_CARDIN);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
MciIsReadOnly (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
|
||||
}
|
||||
|
||||
// Convert block size to 2^n
|
||||
STATIC
|
||||
UINT32
|
||||
GetPow2BlockLen (
|
||||
IN UINT32 BlockLen
|
||||
)
|
||||
{
|
||||
UINTN Loop;
|
||||
UINTN Pow2BlockLen;
|
||||
|
||||
Loop = 0x8000;
|
||||
Pow2BlockLen = 15;
|
||||
do {
|
||||
Loop = (Loop >> 1) & 0xFFFF;
|
||||
Pow2BlockLen--;
|
||||
} while (Pow2BlockLen && (!(Loop & BlockLen)));
|
||||
|
||||
return Pow2BlockLen;
|
||||
}
|
||||
|
||||
VOID
|
||||
MciPrepareDataPath (
|
||||
IN UINTN TransferDirection
|
||||
)
|
||||
{
|
||||
// Set Data Length & Data Timer
|
||||
MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
|
||||
MmioWrite32 (MCI_DATA_LENGTH_REG, MMCI0_BLOCKLEN);
|
||||
|
||||
#ifndef USE_STREAM
|
||||
//Note: we are using a hardcoded BlockLen (==512). If we decide to use a variable size, we could
|
||||
// compute the pow2 of BlockLen with the above function GetPow2BlockLen ()
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
|
||||
#else
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
|
||||
#endif
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciSendCommand (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN MMC_CMD MmcCmd,
|
||||
IN UINT32 Argument
|
||||
)
|
||||
{
|
||||
UINT32 Status;
|
||||
UINT32 Cmd;
|
||||
UINTN RetVal;
|
||||
UINTN CmdCtrlReg;
|
||||
UINT32 DoneMask;
|
||||
|
||||
RetVal = EFI_SUCCESS;
|
||||
|
||||
if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
|
||||
MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);
|
||||
} else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
|
||||
MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);
|
||||
} else if (MmcCmd == MMC_CMD6) {
|
||||
MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
|
||||
MmioWrite32 (MCI_DATA_LENGTH_REG, 64);
|
||||
#ifndef USE_STREAM
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (64));
|
||||
#else
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
|
||||
#endif
|
||||
} else if (MmcCmd == MMC_ACMD51) {
|
||||
MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);
|
||||
/* SCR register is 8 bytes long. */
|
||||
MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
|
||||
#ifndef USE_STREAM
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | GetPow2BlockLen (8));
|
||||
#else
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_CARD_TO_CONT | MCI_DATACTL_STREAM_TRANS);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Create Command for PL180
|
||||
Cmd = (MMC_GET_INDX (MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLE;
|
||||
if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
|
||||
Cmd |= MCI_CPSM_WAIT_RESPONSE;
|
||||
}
|
||||
|
||||
if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
|
||||
Cmd |= MCI_CPSM_LONG_RESPONSE;
|
||||
}
|
||||
|
||||
// Clear Status register static flags
|
||||
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
|
||||
|
||||
// Write to command argument register
|
||||
MmioWrite32 (MCI_ARGUMENT_REG, Argument);
|
||||
|
||||
// Write to command register
|
||||
MmioWrite32 (MCI_COMMAND_REG, Cmd);
|
||||
|
||||
DoneMask = (Cmd & MCI_CPSM_WAIT_RESPONSE)
|
||||
? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)
|
||||
: (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_ERROR);
|
||||
do {
|
||||
Status = MmioRead32 (MCI_STATUS_REG);
|
||||
} while (! (Status & DoneMask));
|
||||
|
||||
if ((Status & MCI_STATUS_CMD_ERROR)) {
|
||||
// Clear Status register error flags
|
||||
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);
|
||||
|
||||
if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {
|
||||
DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_NO_RESPONSE;
|
||||
} else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {
|
||||
//DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_TIMEOUT;
|
||||
} else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
|
||||
// The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.
|
||||
RetVal = EFI_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable Command Path
|
||||
CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);
|
||||
MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciReceiveResponse (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN MMC_RESPONSE_TYPE Type,
|
||||
IN UINT32* Buffer
|
||||
)
|
||||
{
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ( (Type == MMC_RESPONSE_TYPE_R1)
|
||||
|| (Type == MMC_RESPONSE_TYPE_R1b)
|
||||
|| (Type == MMC_RESPONSE_TYPE_R3)
|
||||
|| (Type == MMC_RESPONSE_TYPE_R6)
|
||||
|| (Type == MMC_RESPONSE_TYPE_R7))
|
||||
{
|
||||
Buffer[0] = MmioRead32 (MCI_RESPONSE3_REG);
|
||||
} else if (Type == MMC_RESPONSE_TYPE_R2) {
|
||||
Buffer[0] = MmioRead32 (MCI_RESPONSE0_REG);
|
||||
Buffer[1] = MmioRead32 (MCI_RESPONSE1_REG);
|
||||
Buffer[2] = MmioRead32 (MCI_RESPONSE2_REG);
|
||||
Buffer[3] = MmioRead32 (MCI_RESPONSE3_REG);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciReadBlockData (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Length,
|
||||
IN UINT32* Buffer
|
||||
)
|
||||
{
|
||||
UINTN Loop;
|
||||
UINTN Finish;
|
||||
UINTN Status;
|
||||
EFI_STATUS RetVal;
|
||||
UINTN DataCtrlReg;
|
||||
EFI_TPL Tpl;
|
||||
|
||||
RetVal = EFI_SUCCESS;
|
||||
|
||||
// Read data from the RX FIFO
|
||||
Loop = 0;
|
||||
if (Length < MMCI0_BLOCKLEN) {
|
||||
Finish = Length / 4;
|
||||
} else {
|
||||
Finish = MMCI0_BLOCKLEN / 4;
|
||||
}
|
||||
|
||||
// Raise the TPL at the highest level to disable Interrupts.
|
||||
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
do {
|
||||
// Read the Status flags
|
||||
Status = MmioRead32 (MCI_STATUS_REG);
|
||||
|
||||
// Do eight reads if possible else a single read
|
||||
if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
} else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {
|
||||
Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
|
||||
Loop++;
|
||||
} else {
|
||||
//Check for error conditions and timeouts
|
||||
if (Status & MCI_STATUS_CMD_DATATIMEOUT) {
|
||||
DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_TIMEOUT;
|
||||
break;
|
||||
} else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {
|
||||
DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_CRC_ERROR;
|
||||
break;
|
||||
} else if (Status & MCI_STATUS_CMD_START_BIT_ERROR) {
|
||||
DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_NO_RESPONSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//clear RX over run flag
|
||||
if(Status & MCI_STATUS_CMD_RXOVERRUN) {
|
||||
MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);
|
||||
}
|
||||
} while ((Loop < Finish));
|
||||
|
||||
// Restore Tpl
|
||||
gBS->RestoreTPL (Tpl);
|
||||
|
||||
// Clear Status flags
|
||||
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
|
||||
|
||||
//Disable Data path
|
||||
DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciWriteBlockData (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Length,
|
||||
IN UINT32* Buffer
|
||||
)
|
||||
{
|
||||
UINTN Loop;
|
||||
UINTN Finish;
|
||||
UINTN Timer;
|
||||
UINTN Status;
|
||||
EFI_STATUS RetVal;
|
||||
UINTN DataCtrlReg;
|
||||
EFI_TPL Tpl;
|
||||
|
||||
RetVal = EFI_SUCCESS;
|
||||
|
||||
// Write the data to the TX FIFO
|
||||
Loop = 0;
|
||||
Finish = MMCI0_BLOCKLEN / 4;
|
||||
Timer = MMCI0_TIMEOUT * 100;
|
||||
|
||||
// Raise the TPL at the highest level to disable Interrupts.
|
||||
Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
do {
|
||||
// Read the Status flags
|
||||
Status = MmioRead32 (MCI_STATUS_REG);
|
||||
|
||||
// Do eight writes if possible else a single write
|
||||
if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
} else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {
|
||||
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
|
||||
Loop++;
|
||||
} else {
|
||||
// Check for error conditions and timeouts
|
||||
if (Status & MCI_STATUS_CMD_DATATIMEOUT) {
|
||||
DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_TIMEOUT;
|
||||
goto Exit;
|
||||
} else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {
|
||||
DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));
|
||||
RetVal = EFI_CRC_ERROR;
|
||||
goto Exit;
|
||||
} else if (Status & MCI_STATUS_CMD_TX_UNDERRUN) {
|
||||
DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TX buffer Underrun! Response:0x%X Status:0x%x, Number of bytes written 0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status, Loop));
|
||||
RetVal = EFI_BUFFER_TOO_SMALL;
|
||||
ASSERT(0);
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
} while (Loop < Finish);
|
||||
|
||||
// Restore Tpl
|
||||
gBS->RestoreTPL (Tpl);
|
||||
|
||||
// Wait for FIFO to drain
|
||||
Timer = MMCI0_TIMEOUT * 60;
|
||||
Status = MmioRead32 (MCI_STATUS_REG);
|
||||
#ifndef USE_STREAM
|
||||
// Single block
|
||||
while (((Status & MCI_STATUS_TXDONE) != MCI_STATUS_TXDONE) && Timer) {
|
||||
#else
|
||||
// Stream
|
||||
while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
|
||||
#endif
|
||||
NanoSecondDelay(10);
|
||||
Status = MmioRead32 (MCI_STATUS_REG);
|
||||
Timer--;
|
||||
}
|
||||
|
||||
// Clear Status flags
|
||||
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
|
||||
|
||||
if (Timer == 0) {
|
||||
DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));
|
||||
RetVal = EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
Exit:
|
||||
// Disable Data path
|
||||
DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);
|
||||
MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
MciNotifyState (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN MMC_STATE State
|
||||
)
|
||||
{
|
||||
UINT32 Data32;
|
||||
|
||||
switch (State) {
|
||||
case MmcInvalidState:
|
||||
ASSERT (0);
|
||||
break;
|
||||
case MmcHwInitializationState:
|
||||
// If device already turn on then restart it
|
||||
Data32 = MmioRead32 (MCI_POWER_CONTROL_REG);
|
||||
if ((Data32 & 0x2) == MCI_POWER_UP) {
|
||||
MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
|
||||
|
||||
// Turn off
|
||||
MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0);
|
||||
MmioWrite32 (MCI_POWER_CONTROL_REG, 0);
|
||||
MicroSecondDelay (100);
|
||||
}
|
||||
|
||||
MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
|
||||
// Setup clock
|
||||
// - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
|
||||
MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
|
||||
|
||||
// Set the voltage
|
||||
MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));
|
||||
MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
|
||||
MicroSecondDelay (10);
|
||||
MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
|
||||
MicroSecondDelay (100);
|
||||
|
||||
// Set Data Length & Data Timer
|
||||
MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFF);
|
||||
MmioWrite32 (MCI_DATA_LENGTH_REG, 8);
|
||||
|
||||
ASSERT ((MmioRead32 (MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
|
||||
break;
|
||||
case MmcIdleState:
|
||||
MCI_TRACE ("MciNotifyState(MmcIdleState)");
|
||||
break;
|
||||
case MmcReadyState:
|
||||
MCI_TRACE ("MciNotifyState(MmcReadyState)");
|
||||
break;
|
||||
case MmcIdentificationState:
|
||||
MCI_TRACE ("MciNotifyState (MmcIdentificationState)");
|
||||
break;
|
||||
case MmcStandByState:{
|
||||
volatile UINT32 PwrCtrlReg;
|
||||
MCI_TRACE ("MciNotifyState (MmcStandByState)");
|
||||
|
||||
// Enable MCICMD push-pull drive
|
||||
PwrCtrlReg = MmioRead32 (MCI_POWER_CONTROL_REG);
|
||||
//Disable Open Drain output
|
||||
PwrCtrlReg &= ~ (MCI_POWER_OPENDRAIN);
|
||||
MmioWrite32 (MCI_POWER_CONTROL_REG, PwrCtrlReg);
|
||||
|
||||
// Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
|
||||
//
|
||||
// Note: Increasing clock speed causes TX FIFO under-run errors.
|
||||
// So careful when optimising this driver for higher performance.
|
||||
//
|
||||
MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
|
||||
// Set MMCI0 clock to 24MHz (by bypassing the divider)
|
||||
//MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
|
||||
break;
|
||||
}
|
||||
case MmcTransferState:
|
||||
//MCI_TRACE ("MciNotifyState(MmcTransferState)");
|
||||
break;
|
||||
case MmcSendingDataState:
|
||||
MCI_TRACE ("MciNotifyState(MmcSendingDataState)");
|
||||
break;
|
||||
case MmcReceiveDataState:
|
||||
MCI_TRACE ("MciNotifyState(MmcReceiveDataState)");
|
||||
break;
|
||||
case MmcProgrammingState:
|
||||
MCI_TRACE ("MciNotifyState(MmcProgrammingState)");
|
||||
break;
|
||||
case MmcDisconnectState:
|
||||
MCI_TRACE ("MciNotifyState(MmcDisconnectState)");
|
||||
break;
|
||||
default:
|
||||
ASSERT (0);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;
|
||||
|
||||
EFI_STATUS
|
||||
MciBuildDevicePath (
|
||||
IN EFI_MMC_HOST_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
||||
)
|
||||
{
|
||||
EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
|
||||
|
||||
NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
|
||||
CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mPL180MciDevicePathGuid);
|
||||
|
||||
*DevicePath = NewDevicePathNode;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_MMC_HOST_PROTOCOL gMciHost = {
|
||||
MMC_HOST_PROTOCOL_REVISION,
|
||||
MciIsCardPresent,
|
||||
MciIsReadOnly,
|
||||
MciBuildDevicePath,
|
||||
MciNotifyState,
|
||||
MciSendCommand,
|
||||
MciReceiveResponse,
|
||||
MciReadBlockData,
|
||||
MciWriteBlockData
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
PL180MciDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL180\n",
|
||||
MCI_PERIPH_ID_REG0));
|
||||
|
||||
// Check if this is a PL180
|
||||
if (MmioRead8 (MCI_PERIPH_ID_REG0) != MCI_PERIPH_ID0 ||
|
||||
MmioRead8 (MCI_PERIPH_ID_REG1) != MCI_PERIPH_ID1 ||
|
||||
MmioRead8 (MCI_PERIPH_ID_REG2) != MCI_PERIPH_ID2 ||
|
||||
MmioRead8 (MCI_PCELL_ID_REG0) != MCI_PCELL_ID0 ||
|
||||
MmioRead8 (MCI_PCELL_ID_REG1) != MCI_PCELL_ID1 ||
|
||||
MmioRead8 (MCI_PCELL_ID_REG2) != MCI_PCELL_ID2 ||
|
||||
MmioRead8 (MCI_PCELL_ID_REG3) != MCI_PCELL_ID3) {
|
||||
|
||||
DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL180"
|
||||
" failed\n", MCI_PERIPH_ID_REG0));
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Handle = NULL;
|
||||
|
||||
MCI_TRACE ("PL180MciDxeInitialize()");
|
||||
|
||||
//Publish Component Name, BlockIO protocol interfaces
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Handle,
|
||||
&gEfiMmcHostProtocolGuid, &gMciHost,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@@ -1,162 +0,0 @@
|
||||
/** @file
|
||||
Header for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
|
||||
|
||||
Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PL180_MCI_H
|
||||
#define __PL180_MCI_H
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/MmcHost.h>
|
||||
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#define PL180_MCI_DXE_VERSION 0x10
|
||||
|
||||
#define MCI_SYSCTL FixedPcdGet32 (PcdPL180MciBaseAddress)
|
||||
|
||||
#define MCI_POWER_CONTROL_REG (MCI_SYSCTL + 0x000)
|
||||
#define MCI_CLOCK_CONTROL_REG (MCI_SYSCTL + 0x004)
|
||||
#define MCI_ARGUMENT_REG (MCI_SYSCTL + 0x008)
|
||||
#define MCI_COMMAND_REG (MCI_SYSCTL + 0x00C)
|
||||
#define MCI_RESPCMD_REG (MCI_SYSCTL + 0x010)
|
||||
#define MCI_RESPONSE3_REG (MCI_SYSCTL + 0x014)
|
||||
#define MCI_RESPONSE2_REG (MCI_SYSCTL + 0x018)
|
||||
#define MCI_RESPONSE1_REG (MCI_SYSCTL + 0x01C)
|
||||
#define MCI_RESPONSE0_REG (MCI_SYSCTL + 0x020)
|
||||
#define MCI_DATA_TIMER_REG (MCI_SYSCTL + 0x024)
|
||||
#define MCI_DATA_LENGTH_REG (MCI_SYSCTL + 0x028)
|
||||
#define MCI_DATA_CTL_REG (MCI_SYSCTL + 0x02C)
|
||||
#define MCI_DATA_COUNTER (MCI_SYSCTL + 0x030)
|
||||
#define MCI_STATUS_REG (MCI_SYSCTL + 0x034)
|
||||
#define MCI_CLEAR_STATUS_REG (MCI_SYSCTL + 0x038)
|
||||
#define MCI_INT0_MASK_REG (MCI_SYSCTL + 0x03C)
|
||||
#define MCI_INT1_MASK_REG (MCI_SYSCTL + 0x040)
|
||||
#define MCI_SELECT_REG (MCI_SYSCTL + 0x044)
|
||||
#define MCI_FIFOCOUNT_REG (MCI_SYSCTL + 0x048)
|
||||
#define MCI_FIFO_REG (MCI_SYSCTL + 0x080)
|
||||
#define MCI_PERIPH_ID_REG0 (MCI_SYSCTL + 0xFE0)
|
||||
#define MCI_PERIPH_ID_REG1 (MCI_SYSCTL + 0xFE4)
|
||||
#define MCI_PERIPH_ID_REG2 (MCI_SYSCTL + 0xFE8)
|
||||
#define MCI_PERIPH_ID_REG3 (MCI_SYSCTL + 0xFEC)
|
||||
#define MCI_PCELL_ID_REG0 (MCI_SYSCTL + 0xFF0)
|
||||
#define MCI_PCELL_ID_REG1 (MCI_SYSCTL + 0xFF4)
|
||||
#define MCI_PCELL_ID_REG2 (MCI_SYSCTL + 0xFF8)
|
||||
#define MCI_PCELL_ID_REG3 (MCI_SYSCTL + 0xFFC)
|
||||
|
||||
#define MCI_PERIPH_ID0 0x80
|
||||
#define MCI_PERIPH_ID1 0x11
|
||||
#define MCI_PERIPH_ID2 0x04
|
||||
#define MCI_PERIPH_ID3 0x00
|
||||
#define MCI_PCELL_ID0 0x0D
|
||||
#define MCI_PCELL_ID1 0xF0
|
||||
#define MCI_PCELL_ID2 0x05
|
||||
#define MCI_PCELL_ID3 0xB1
|
||||
|
||||
#define MCI_POWER_OFF 0
|
||||
#define MCI_POWER_UP BIT1
|
||||
#define MCI_POWER_ON (BIT1 | BIT0)
|
||||
#define MCI_POWER_OPENDRAIN BIT6
|
||||
#define MCI_POWER_ROD BIT7
|
||||
|
||||
#define MCI_CLOCK_ENABLE BIT8
|
||||
#define MCI_CLOCK_POWERSAVE BIT9
|
||||
#define MCI_CLOCK_BYPASS BIT10
|
||||
#define MCI_CLOCK_WIDEBUS BIT11
|
||||
|
||||
#define MCI_STATUS_CMD_CMDCRCFAIL BIT0
|
||||
#define MCI_STATUS_CMD_DATACRCFAIL BIT1
|
||||
#define MCI_STATUS_CMD_CMDTIMEOUT BIT2
|
||||
#define MCI_STATUS_CMD_DATATIMEOUT BIT3
|
||||
#define MCI_STATUS_CMD_TX_UNDERRUN BIT4
|
||||
#define MCI_STATUS_CMD_RXOVERRUN BIT5
|
||||
#define MCI_STATUS_CMD_RESPEND BIT6
|
||||
#define MCI_STATUS_CMD_SENT BIT7
|
||||
#define MCI_STATUS_CMD_DATAEND BIT8
|
||||
#define MCI_STATUS_CMD_START_BIT_ERROR BIT9
|
||||
#define MCI_STATUS_CMD_DATABLOCKEND BIT10
|
||||
#define MCI_STATUS_CMD_ACTIVE BIT11
|
||||
#define MCI_STATUS_CMD_TXACTIVE BIT12
|
||||
#define MCI_STATUS_CMD_RXACTIVE BIT13
|
||||
#define MCI_STATUS_CMD_TXFIFOHALFEMPTY BIT14
|
||||
#define MCI_STATUS_CMD_RXFIFOHALFFULL BIT15
|
||||
#define MCI_STATUS_CMD_TXFIFOFULL BIT16
|
||||
#define MCI_STATUS_CMD_RXFIFOFULL BIT17
|
||||
#define MCI_STATUS_CMD_TXFIFOEMPTY BIT18
|
||||
#define MCI_STATUS_CMD_RXFIFOEMPTY BIT19
|
||||
#define MCI_STATUS_CMD_TXDATAAVAILBL BIT20
|
||||
#define MCI_STATUS_CMD_RXDATAAVAILBL BIT21
|
||||
|
||||
#define MCI_STATUS_TXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
|
||||
#define MCI_STATUS_RXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
|
||||
#define MCI_STATUS_READ_ERROR ( MCI_STATUS_CMD_DATACRCFAIL \
|
||||
| MCI_STATUS_CMD_DATATIMEOUT \
|
||||
| MCI_STATUS_CMD_RXOVERRUN \
|
||||
| MCI_STATUS_CMD_START_BIT_ERROR )
|
||||
#define MCI_STATUS_WRITE_ERROR ( MCI_STATUS_CMD_DATACRCFAIL \
|
||||
| MCI_STATUS_CMD_DATATIMEOUT \
|
||||
| MCI_STATUS_CMD_TX_UNDERRUN )
|
||||
#define MCI_STATUS_CMD_ERROR ( MCI_STATUS_CMD_CMDCRCFAIL \
|
||||
| MCI_STATUS_CMD_CMDTIMEOUT \
|
||||
| MCI_STATUS_CMD_START_BIT_ERROR )
|
||||
|
||||
#define MCI_CLR_CMD_STATUS ( MCI_STATUS_CMD_RESPEND \
|
||||
| MCI_STATUS_CMD_SENT \
|
||||
| MCI_STATUS_CMD_ERROR )
|
||||
|
||||
#define MCI_CLR_READ_STATUS ( MCI_STATUS_RXDONE \
|
||||
| MCI_STATUS_READ_ERROR )
|
||||
|
||||
#define MCI_CLR_WRITE_STATUS ( MCI_STATUS_TXDONE \
|
||||
| MCI_STATUS_WRITE_ERROR )
|
||||
|
||||
#define MCI_CLR_ALL_STATUS (BIT11 - 1)
|
||||
|
||||
#define MCI_DATACTL_DISABLE_MASK 0xFE
|
||||
#define MCI_DATACTL_ENABLE BIT0
|
||||
#define MCI_DATACTL_CONT_TO_CARD 0
|
||||
#define MCI_DATACTL_CARD_TO_CONT BIT1
|
||||
#define MCI_DATACTL_BLOCK_TRANS 0
|
||||
#define MCI_DATACTL_STREAM_TRANS BIT2
|
||||
#define MCI_DATACTL_DMA_DISABLED 0
|
||||
#define MCI_DATACTL_DMA_ENABLE BIT3
|
||||
|
||||
#define INDX_MASK 0x3F
|
||||
|
||||
#define MCI_CPSM_WAIT_RESPONSE BIT6
|
||||
#define MCI_CPSM_LONG_RESPONSE BIT7
|
||||
#define MCI_CPSM_LONG_INTERRUPT BIT8
|
||||
#define MCI_CPSM_LONG_PENDING BIT9
|
||||
#define MCI_CPSM_ENABLE BIT10
|
||||
|
||||
#define MCI_TRACE(txt) DEBUG ((EFI_D_BLKIO, "ARM_MCI: " txt "\n"))
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MciGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MciGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
#endif
|
@@ -1,46 +0,0 @@
|
||||
#/** @file
|
||||
# INF file for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
|
||||
#
|
||||
# Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PL180MciDxe
|
||||
FILE_GUID = 09831032-6fa3-4484-af4f-0a000a8d3a82
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = PL180MciDxeInitialize
|
||||
|
||||
[Sources.common]
|
||||
PL180Mci.c
|
||||
|
||||
[Packages]
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiLib
|
||||
UefiDriverEntryPoint
|
||||
BaseMemoryLib
|
||||
ArmLib
|
||||
IoLib
|
||||
TimerLib
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiMmcHostProtocolGuid
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdPL180SysMciRegAddress
|
||||
gArmPlatformTokenSpaceGuid.PcdPL180MciBaseAddress
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
@@ -78,10 +78,14 @@ PL011UartInitializePort (
|
||||
UINT32 Integer;
|
||||
UINT32 Fractional;
|
||||
UINT32 HardwareFifoDepth;
|
||||
UINT32 UartPid2;
|
||||
|
||||
HardwareFifoDepth = FixedPcdGet16 (PcdUartDefaultReceiveFifoDepth);
|
||||
if (HardwareFifoDepth == 0) {
|
||||
UartPid2 = MmioRead32 (UartBase + UARTPID2);
|
||||
HardwareFifoDepth = (PL011_UARTPID2_VER (UartPid2) > PL011_VER_R1P4) ? 32 : 16;
|
||||
}
|
||||
|
||||
HardwareFifoDepth = (PL011_UARTPID2_VER (MmioRead32 (UartBase + UARTPID2)) \
|
||||
> PL011_VER_R1P4) \
|
||||
? 32 : 16 ;
|
||||
// The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can accept
|
||||
// 1 char buffer as the minimum FIFO size. Because everything can be rounded
|
||||
// down, there is no maximum FIFO size.
|
||||
|
@@ -30,6 +30,7 @@
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[FixedPcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultReceiveFifoDepth
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PL011UartInteger
|
||||
|
@@ -8,6 +8,7 @@
|
||||
**/
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/CacheMaintenanceLib.h>
|
||||
#include <Library/DebugAgentLib.h>
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
@@ -59,13 +60,14 @@ CEntryPoint (
|
||||
{
|
||||
// Data Cache enabled on Primary core when MMU is enabled.
|
||||
ArmDisableDataCache ();
|
||||
// Invalidate Data cache
|
||||
ArmInvalidateDataCache ();
|
||||
// Invalidate instruction cache
|
||||
ArmInvalidateInstructionCache ();
|
||||
// Enable Instruction Caches on all cores.
|
||||
ArmEnableInstructionCache ();
|
||||
|
||||
InvalidateDataCacheRange ((VOID *)(UINTN)PcdGet64 (PcdCPUCoresStackBase),
|
||||
PcdGet32 (PcdCPUCorePrimaryStackSize));
|
||||
|
||||
//
|
||||
// Note: Doesn't have to Enable CPU interface in non-secure world,
|
||||
// as Non-secure interface is already enabled in Secure world.
|
||||
@@ -77,6 +79,11 @@ CEntryPoint (
|
||||
ASSERT (((UINTN)PeiVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
|
||||
ArmWriteVBar ((UINTN)PeiVectorTable);
|
||||
|
||||
// Enable Floating Point
|
||||
if (FixedPcdGet32 (PcdVFPEnabled)) {
|
||||
ArmEnableVFP ();
|
||||
}
|
||||
|
||||
//Note: The MMU will be enabled by MemoryPeim. Only the primary core will have the MMU on.
|
||||
|
||||
// If not primary Jump to Secondary Main
|
||||
|
@@ -44,6 +44,7 @@
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
ArmPlatformLib
|
||||
CacheMaintenanceLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
DebugAgentLib
|
||||
@@ -62,6 +63,7 @@
|
||||
[FixedPcd]
|
||||
gArmTokenSpaceGuid.PcdFvBaseAddress
|
||||
gArmTokenSpaceGuid.PcdFvSize
|
||||
gArmTokenSpaceGuid.PcdVFPEnabled
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase
|
||||
gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
|
||||
|
@@ -44,6 +44,7 @@
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
ArmPlatformLib
|
||||
CacheMaintenanceLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
DebugAgentLib
|
||||
@@ -60,6 +61,7 @@
|
||||
[FixedPcd]
|
||||
gArmTokenSpaceGuid.PcdFvBaseAddress
|
||||
gArmTokenSpaceGuid.PcdFvSize
|
||||
gArmTokenSpaceGuid.PcdVFPEnabled
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase
|
||||
gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
CacheMaintenanceLib
|
||||
DebugLib
|
||||
DebugAgentLib
|
||||
ArmLib
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
CacheMaintenanceLib
|
||||
DebugLib
|
||||
DebugAgentLib
|
||||
ArmLib
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Library/CacheMaintenanceLib.h>
|
||||
#include <Library/DebugAgentLib.h>
|
||||
#include <Library/PrePiLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
@@ -22,7 +23,7 @@
|
||||
#include "PrePi.h"
|
||||
|
||||
#define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) || \
|
||||
((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase)))
|
||||
((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= FixedPcdGet64 (PcdSystemMemoryBase)))
|
||||
|
||||
UINT64 mSystemMemoryEnd = FixedPcdGet64(PcdSystemMemoryBase) +
|
||||
FixedPcdGet64(PcdSystemMemorySize) - 1;
|
||||
@@ -178,8 +179,6 @@ CEntryPoint (
|
||||
|
||||
// Data Cache enabled on Primary core when MMU is enabled.
|
||||
ArmDisableDataCache ();
|
||||
// Invalidate Data cache
|
||||
ArmInvalidateDataCache ();
|
||||
// Invalidate instruction cache
|
||||
ArmInvalidateInstructionCache ();
|
||||
// Enable Instruction Caches on all cores.
|
||||
@@ -200,6 +199,10 @@ CEntryPoint (
|
||||
|
||||
// If not primary Jump to Secondary Main
|
||||
if (ArmPlatformIsPrimaryCore (MpId)) {
|
||||
|
||||
InvalidateDataCacheRange ((VOID *)UefiMemoryBase,
|
||||
FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
|
||||
|
||||
// Goto primary Main.
|
||||
PrimaryMain (UefiMemoryBase, StacksBase, StartTimeStamp);
|
||||
} else {
|
||||
@@ -209,4 +212,3 @@ CEntryPoint (
|
||||
// DXE Core should always load and never return
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
|
@@ -81,7 +81,7 @@ class EfiSectionTE:
|
||||
filename = self.base_te + debug_rva + 0xc
|
||||
else:
|
||||
filename = self.base_te + debug_rva + 0x10
|
||||
filename = struct.unpack("200s", self.ec.getMemoryService().read(filename, 200, 32))[0]
|
||||
filename = struct.unpack("400s", self.ec.getMemoryService().read(filename, 400, 32))[0]
|
||||
return filename[0:string.find(filename,'\0')]
|
||||
|
||||
def get_debug_elfbase(self):
|
||||
@@ -119,7 +119,7 @@ class EfiSectionPE32:
|
||||
filename = self.base_pe32 + debug_rva + 0xc
|
||||
else:
|
||||
filename = self.base_pe32 + debug_rva + 0x10
|
||||
filename = struct.unpack("200s", self.ec.getMemoryService().read(str(filename), 200, 32))[0]
|
||||
filename = struct.unpack("400s", self.ec.getMemoryService().read(str(filename), 400, 32))[0]
|
||||
return filename[0:string.find(filename,'\0')]
|
||||
|
||||
def get_debug_elfbase(self):
|
||||
@@ -154,7 +154,7 @@ class EfiSectionPE64:
|
||||
filename = self.base_pe64 + debug_rva + 0xc
|
||||
else:
|
||||
filename = self.base_pe64 + debug_rva + 0x10
|
||||
filename = struct.unpack("200s", self.ec.getMemoryService().read(str(filename), 200, 32))[0]
|
||||
filename = struct.unpack("400s", self.ec.getMemoryService().read(str(filename), 400, 32))[0]
|
||||
return filename[0:string.find(filename,'\0')]
|
||||
|
||||
def get_debug_elfbase(self):
|
||||
|
@@ -1,328 +1,328 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2014, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
||||
import getopt
|
||||
import operator
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
from sys import argv
|
||||
from cStringIO import StringIO
|
||||
|
||||
modules = {}
|
||||
functions = {}
|
||||
functions_addr = {}
|
||||
|
||||
def usage():
|
||||
print "-t,--trace: Location of the Trace file"
|
||||
print "-s,--symbols: Location of the symbols and modules"
|
||||
|
||||
def get_address_from_string(address):
|
||||
return int(address.strip("S:").strip("N:").strip("EL2:").strip("EL1:"), 16)
|
||||
|
||||
def get_module_from_addr(modules, addr):
|
||||
for key,value in modules.items():
|
||||
if (value['start'] <= addr) and (addr <= value['end']):
|
||||
return key
|
||||
return None
|
||||
|
||||
def add_cycles_to_function(functions, func_name, addr, cycles):
|
||||
if func_name != "<Unknown>":
|
||||
# Check if we are still in the previous function
|
||||
if add_cycles_to_function.prev_func_name == func_name:
|
||||
add_cycles_to_function.prev_entry['cycles'] += cycles
|
||||
return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
|
||||
|
||||
if func_name in functions.keys():
|
||||
for module_name, module_value in functions[func_name].iteritems():
|
||||
if (module_value['start'] <= addr) and (addr < module_value['end']):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_name, module_name)
|
||||
elif (module_value['end'] == 0):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_name, module_name)
|
||||
|
||||
# Workaround to fix the 'info func' limitation that does not expose the 'static' function
|
||||
module_name = get_module_from_addr(modules, addr)
|
||||
functions[func_name] = {}
|
||||
functions[func_name][module_name] = {}
|
||||
functions[func_name][module_name]['start'] = 0
|
||||
functions[func_name][module_name]['end'] = 0
|
||||
functions[func_name][module_name]['cycles'] = cycles
|
||||
functions[func_name][module_name]['count'] = 0
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = functions[func_name][module_name]
|
||||
return (func_name, module_name)
|
||||
else:
|
||||
# Check if we are still in the previous function
|
||||
if (add_cycles_to_function.prev_entry is not None) and (add_cycles_to_function.prev_entry['start'] <= addr) and (addr < add_cycles_to_function.prev_entry['end']):
|
||||
add_cycles_to_function.prev_entry['cycles'] += cycles
|
||||
return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
|
||||
|
||||
# Generate the key for the given address
|
||||
key = addr & ~0x0FFF
|
||||
|
||||
if key not in functions_addr.keys():
|
||||
if 'Unknown' not in functions.keys():
|
||||
functions['Unknown'] = {}
|
||||
if 'Unknown' not in functions['Unknown'].keys():
|
||||
functions['Unknown']['Unknown'] = {}
|
||||
functions['Unknown']['Unknown']['cycles'] = 0
|
||||
functions['Unknown']['Unknown']['count'] = 0
|
||||
functions['Unknown']['Unknown']['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
return None
|
||||
|
||||
for func_key, module in functions_addr[key].iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
if (module_value['start'] <= addr) and (addr < module_value['end']):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
# In case o <Unknown> we prefer to fallback on the direct search
|
||||
add_cycles_to_function.prev_func_name = func_key
|
||||
add_cycles_to_function.prev_module_name = module_key
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_key, module_key)
|
||||
|
||||
print "Warning: Function %s @ 0x%x not found" % (func_name, addr)
|
||||
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
return None
|
||||
|
||||
# Static variables for the previous function
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
add_cycles_to_function.prev_entry = None
|
||||
|
||||
def trace_read():
|
||||
global trace_process
|
||||
line = trace.readline()
|
||||
trace_process += len(line)
|
||||
return line
|
||||
|
||||
#
|
||||
# Parse arguments
|
||||
#
|
||||
trace_name = None
|
||||
symbols_file = None
|
||||
|
||||
opts,args = getopt.getopt(sys.argv[1:], "ht:vs:v", ["help","trace=","symbols="])
|
||||
if (opts is None) or (not opts):
|
||||
usage()
|
||||
sys.exit()
|
||||
|
||||
for o,a in opts:
|
||||
if o in ("-h","--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif o in ("-t","--trace"):
|
||||
trace_name = a
|
||||
elif o in ("-s","--symbols"):
|
||||
symbols_file = a
|
||||
else:
|
||||
assert False, "Unhandled option (%s)" % o
|
||||
|
||||
#
|
||||
# We try first to see if we run the script from DS-5
|
||||
#
|
||||
try:
|
||||
from arm_ds.debugger_v1 import Debugger
|
||||
from arm_ds.debugger_v1 import DebugException
|
||||
|
||||
# Debugger object for accessing the debugger
|
||||
debugger = Debugger()
|
||||
|
||||
# Initialisation commands
|
||||
ec = debugger.getExecutionContext(0)
|
||||
ec.getExecutionService().stop()
|
||||
ec.getExecutionService().waitForStop()
|
||||
# in case the execution context reference is out of date
|
||||
ec = debugger.getExecutionContext(0)
|
||||
|
||||
#
|
||||
# Get the module name and their memory range
|
||||
#
|
||||
info_file = ec.executeDSCommand("info file")
|
||||
info_file_str = StringIO(info_file)
|
||||
|
||||
line = info_file_str.readline().strip('\n')
|
||||
while line != '':
|
||||
if ("Symbols from" in line):
|
||||
# Get the module name from the line 'Symbols from "/home/...."'
|
||||
module_name = line.split("\"")[1].split("/")[-1]
|
||||
modules[module_name] = {}
|
||||
|
||||
# Look for the text section
|
||||
line = info_file_str.readline().strip('\n')
|
||||
while (line != '') and ("Symbols from" not in line):
|
||||
if ("ER_RO" in line):
|
||||
modules[module_name]['start'] = get_address_from_string(line.split()[0])
|
||||
modules[module_name]['end'] = get_address_from_string(line.split()[2])
|
||||
line = info_file_str.readline().strip('\n')
|
||||
break;
|
||||
if (".text" in line):
|
||||
modules[module_name]['start'] = get_address_from_string(line.split()[0])
|
||||
modules[module_name]['end'] = get_address_from_string(line.split()[2])
|
||||
line = info_file_str.readline().strip('\n')
|
||||
break;
|
||||
line = info_file_str.readline().strip('\n')
|
||||
line = info_file_str.readline().strip('\n')
|
||||
|
||||
#
|
||||
# Get the function name and their memory range
|
||||
#
|
||||
info_func = ec.executeDSCommand("info func")
|
||||
info_func_str = StringIO(info_func)
|
||||
|
||||
# Skip the first line 'Low-level symbols ...'
|
||||
line = info_func_str.readline().strip('\n')
|
||||
func_prev = None
|
||||
while line != '':
|
||||
# We ignore all the functions after 'Functions in'
|
||||
if ("Functions in " in line):
|
||||
line = info_func_str.readline().strip('\n')
|
||||
while line != '':
|
||||
line = info_func_str.readline().strip('\n')
|
||||
line = info_func_str.readline().strip('\n')
|
||||
continue
|
||||
|
||||
if ("Low-level symbols" in line):
|
||||
# We need to fixup the last function of the module
|
||||
if func_prev is not None:
|
||||
func_prev['end'] = modules[module_name]['end']
|
||||
func_prev = None
|
||||
|
||||
line = info_func_str.readline().strip('\n')
|
||||
continue
|
||||
|
||||
func_name = line.split()[1]
|
||||
func_start = get_address_from_string(line.split()[0])
|
||||
module_name = get_module_from_addr(modules, func_start)
|
||||
|
||||
if func_name not in functions.keys():
|
||||
functions[func_name] = {}
|
||||
functions[func_name][module_name] = {}
|
||||
functions[func_name][module_name]['start'] = func_start
|
||||
functions[func_name][module_name]['cycles'] = 0
|
||||
functions[func_name][module_name]['count'] = 0
|
||||
|
||||
# Set the end address of the previous function
|
||||
if func_prev is not None:
|
||||
func_prev['end'] = func_start
|
||||
func_prev = functions[func_name][module_name]
|
||||
|
||||
line = info_func_str.readline().strip('\n')
|
||||
|
||||
# Fixup the last function
|
||||
func_prev['end'] = modules[module_name]['end']
|
||||
|
||||
if symbols_file is not None:
|
||||
pickle.dump((modules, functions), open(symbols_file, "w"))
|
||||
except:
|
||||
if symbols_file is None:
|
||||
print "Error: Symbols file is required when run out of ARM DS-5"
|
||||
sys.exit()
|
||||
|
||||
(modules, functions) = pickle.load(open(symbols_file, "r"))
|
||||
|
||||
#
|
||||
# Build optimized table for the <Unknown> functions
|
||||
#
|
||||
functions_addr = {}
|
||||
for func_key, module in functions.iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
key = module_value['start'] & ~0x0FFF
|
||||
if key not in functions_addr.keys():
|
||||
functions_addr[key] = {}
|
||||
if func_key not in functions_addr[key].keys():
|
||||
functions_addr[key][func_key] = {}
|
||||
functions_addr[key][func_key][module_key] = module_value
|
||||
|
||||
#
|
||||
# Process the trace file
|
||||
#
|
||||
if trace_name is None:
|
||||
sys.exit()
|
||||
|
||||
trace = open(trace_name, "r")
|
||||
trace_size = os.path.getsize(trace_name)
|
||||
trace_process = 0
|
||||
|
||||
# Get the column names from the first line
|
||||
columns = trace_read().split()
|
||||
column_addr = columns.index('Address')
|
||||
column_cycles = columns.index('Cycles')
|
||||
column_function = columns.index('Function')
|
||||
|
||||
line = trace_read()
|
||||
i = 0
|
||||
prev_callee = None
|
||||
while line:
|
||||
try:
|
||||
func_name = line.split('\t')[column_function].strip()
|
||||
address = get_address_from_string(line.split('\t')[column_addr])
|
||||
cycles = int(line.split('\t')[column_cycles])
|
||||
callee = add_cycles_to_function(functions, func_name, address, cycles)
|
||||
if (prev_callee != None) and (prev_callee != callee):
|
||||
functions[prev_callee[0]][prev_callee[1]]['count'] += 1
|
||||
prev_callee = callee
|
||||
except ValueError:
|
||||
pass
|
||||
line = trace_read()
|
||||
if ((i % 1000000) == 0) and (i != 0):
|
||||
percent = (trace_process * 100.00) / trace_size
|
||||
print "Processing file ... (%.2f %%)" % (percent)
|
||||
i = i + 1
|
||||
|
||||
# Fixup the last callee
|
||||
functions[prev_callee[0]][prev_callee[1]]['count'] += 1
|
||||
|
||||
#
|
||||
# Process results
|
||||
#
|
||||
functions_cycles = {}
|
||||
all_functions_cycles = {}
|
||||
total_cycles = 0
|
||||
|
||||
for func_key, module in functions.iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
key = "%s/%s" % (module_key, func_key)
|
||||
functions_cycles[key] = (module_value['cycles'], module_value['count'])
|
||||
total_cycles += module_value['cycles']
|
||||
|
||||
if func_key not in all_functions_cycles.keys():
|
||||
all_functions_cycles[func_key] = (module_value['cycles'], module_value['count'])
|
||||
else:
|
||||
all_functions_cycles[func_key] = tuple(map(sum, zip(all_functions_cycles[func_key], (module_value['cycles'], module_value['count']))))
|
||||
|
||||
sorted_functions_cycles = sorted(functions_cycles.iteritems(), key=operator.itemgetter(1), reverse = True)
|
||||
sorted_all_functions_cycles = sorted(all_functions_cycles.items(), key=operator.itemgetter(1), reverse = True)
|
||||
|
||||
print
|
||||
print "----"
|
||||
for (key,value) in sorted_functions_cycles[:20]:
|
||||
if value[0] != 0:
|
||||
print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
|
||||
else:
|
||||
break;
|
||||
print "----"
|
||||
for (key,value) in sorted_all_functions_cycles[:20]:
|
||||
if value[0] != 0:
|
||||
print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
|
||||
else:
|
||||
break;
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2014, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
||||
import getopt
|
||||
import operator
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
from sys import argv
|
||||
from cStringIO import StringIO
|
||||
|
||||
modules = {}
|
||||
functions = {}
|
||||
functions_addr = {}
|
||||
|
||||
def usage():
|
||||
print "-t,--trace: Location of the Trace file"
|
||||
print "-s,--symbols: Location of the symbols and modules"
|
||||
|
||||
def get_address_from_string(address):
|
||||
return int(address.strip("S:").strip("N:").strip("EL2:").strip("EL1:"), 16)
|
||||
|
||||
def get_module_from_addr(modules, addr):
|
||||
for key,value in modules.items():
|
||||
if (value['start'] <= addr) and (addr <= value['end']):
|
||||
return key
|
||||
return None
|
||||
|
||||
def add_cycles_to_function(functions, func_name, addr, cycles):
|
||||
if func_name != "<Unknown>":
|
||||
# Check if we are still in the previous function
|
||||
if add_cycles_to_function.prev_func_name == func_name:
|
||||
add_cycles_to_function.prev_entry['cycles'] += cycles
|
||||
return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
|
||||
|
||||
if func_name in functions.keys():
|
||||
for module_name, module_value in functions[func_name].iteritems():
|
||||
if (module_value['start'] <= addr) and (addr < module_value['end']):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_name, module_name)
|
||||
elif (module_value['end'] == 0):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_name, module_name)
|
||||
|
||||
# Workaround to fix the 'info func' limitation that does not expose the 'static' function
|
||||
module_name = get_module_from_addr(modules, addr)
|
||||
functions[func_name] = {}
|
||||
functions[func_name][module_name] = {}
|
||||
functions[func_name][module_name]['start'] = 0
|
||||
functions[func_name][module_name]['end'] = 0
|
||||
functions[func_name][module_name]['cycles'] = cycles
|
||||
functions[func_name][module_name]['count'] = 0
|
||||
|
||||
add_cycles_to_function.prev_func_name = func_name
|
||||
add_cycles_to_function.prev_module_name = module_name
|
||||
add_cycles_to_function.prev_entry = functions[func_name][module_name]
|
||||
return (func_name, module_name)
|
||||
else:
|
||||
# Check if we are still in the previous function
|
||||
if (add_cycles_to_function.prev_entry is not None) and (add_cycles_to_function.prev_entry['start'] <= addr) and (addr < add_cycles_to_function.prev_entry['end']):
|
||||
add_cycles_to_function.prev_entry['cycles'] += cycles
|
||||
return (add_cycles_to_function.prev_func_name, add_cycles_to_function.prev_module_name)
|
||||
|
||||
# Generate the key for the given address
|
||||
key = addr & ~0x0FFF
|
||||
|
||||
if key not in functions_addr.keys():
|
||||
if 'Unknown' not in functions.keys():
|
||||
functions['Unknown'] = {}
|
||||
if 'Unknown' not in functions['Unknown'].keys():
|
||||
functions['Unknown']['Unknown'] = {}
|
||||
functions['Unknown']['Unknown']['cycles'] = 0
|
||||
functions['Unknown']['Unknown']['count'] = 0
|
||||
functions['Unknown']['Unknown']['cycles'] += cycles
|
||||
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
return None
|
||||
|
||||
for func_key, module in functions_addr[key].iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
if (module_value['start'] <= addr) and (addr < module_value['end']):
|
||||
module_value['cycles'] += cycles
|
||||
|
||||
# In case o <Unknown> we prefer to fallback on the direct search
|
||||
add_cycles_to_function.prev_func_name = func_key
|
||||
add_cycles_to_function.prev_module_name = module_key
|
||||
add_cycles_to_function.prev_entry = module_value
|
||||
return (func_key, module_key)
|
||||
|
||||
print "Warning: Function %s @ 0x%x not found" % (func_name, addr)
|
||||
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
return None
|
||||
|
||||
# Static variables for the previous function
|
||||
add_cycles_to_function.prev_func_name = None
|
||||
add_cycles_to_function.prev_entry = None
|
||||
|
||||
def trace_read():
|
||||
global trace_process
|
||||
line = trace.readline()
|
||||
trace_process += len(line)
|
||||
return line
|
||||
|
||||
#
|
||||
# Parse arguments
|
||||
#
|
||||
trace_name = None
|
||||
symbols_file = None
|
||||
|
||||
opts,args = getopt.getopt(sys.argv[1:], "ht:vs:v", ["help","trace=","symbols="])
|
||||
if (opts is None) or (not opts):
|
||||
usage()
|
||||
sys.exit()
|
||||
|
||||
for o,a in opts:
|
||||
if o in ("-h","--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif o in ("-t","--trace"):
|
||||
trace_name = a
|
||||
elif o in ("-s","--symbols"):
|
||||
symbols_file = a
|
||||
else:
|
||||
assert False, "Unhandled option (%s)" % o
|
||||
|
||||
#
|
||||
# We try first to see if we run the script from DS-5
|
||||
#
|
||||
try:
|
||||
from arm_ds.debugger_v1 import Debugger
|
||||
from arm_ds.debugger_v1 import DebugException
|
||||
|
||||
# Debugger object for accessing the debugger
|
||||
debugger = Debugger()
|
||||
|
||||
# Initialisation commands
|
||||
ec = debugger.getExecutionContext(0)
|
||||
ec.getExecutionService().stop()
|
||||
ec.getExecutionService().waitForStop()
|
||||
# in case the execution context reference is out of date
|
||||
ec = debugger.getExecutionContext(0)
|
||||
|
||||
#
|
||||
# Get the module name and their memory range
|
||||
#
|
||||
info_file = ec.executeDSCommand("info file")
|
||||
info_file_str = StringIO(info_file)
|
||||
|
||||
line = info_file_str.readline().strip('\n')
|
||||
while line != '':
|
||||
if ("Symbols from" in line):
|
||||
# Get the module name from the line 'Symbols from "/home/...."'
|
||||
module_name = line.split("\"")[1].split("/")[-1]
|
||||
modules[module_name] = {}
|
||||
|
||||
# Look for the text section
|
||||
line = info_file_str.readline().strip('\n')
|
||||
while (line != '') and ("Symbols from" not in line):
|
||||
if ("ER_RO" in line):
|
||||
modules[module_name]['start'] = get_address_from_string(line.split()[0])
|
||||
modules[module_name]['end'] = get_address_from_string(line.split()[2])
|
||||
line = info_file_str.readline().strip('\n')
|
||||
break;
|
||||
if (".text" in line):
|
||||
modules[module_name]['start'] = get_address_from_string(line.split()[0])
|
||||
modules[module_name]['end'] = get_address_from_string(line.split()[2])
|
||||
line = info_file_str.readline().strip('\n')
|
||||
break;
|
||||
line = info_file_str.readline().strip('\n')
|
||||
line = info_file_str.readline().strip('\n')
|
||||
|
||||
#
|
||||
# Get the function name and their memory range
|
||||
#
|
||||
info_func = ec.executeDSCommand("info func")
|
||||
info_func_str = StringIO(info_func)
|
||||
|
||||
# Skip the first line 'Low-level symbols ...'
|
||||
line = info_func_str.readline().strip('\n')
|
||||
func_prev = None
|
||||
while line != '':
|
||||
# We ignore all the functions after 'Functions in'
|
||||
if ("Functions in " in line):
|
||||
line = info_func_str.readline().strip('\n')
|
||||
while line != '':
|
||||
line = info_func_str.readline().strip('\n')
|
||||
line = info_func_str.readline().strip('\n')
|
||||
continue
|
||||
|
||||
if ("Low-level symbols" in line):
|
||||
# We need to fixup the last function of the module
|
||||
if func_prev is not None:
|
||||
func_prev['end'] = modules[module_name]['end']
|
||||
func_prev = None
|
||||
|
||||
line = info_func_str.readline().strip('\n')
|
||||
continue
|
||||
|
||||
func_name = line.split()[1]
|
||||
func_start = get_address_from_string(line.split()[0])
|
||||
module_name = get_module_from_addr(modules, func_start)
|
||||
|
||||
if func_name not in functions.keys():
|
||||
functions[func_name] = {}
|
||||
functions[func_name][module_name] = {}
|
||||
functions[func_name][module_name]['start'] = func_start
|
||||
functions[func_name][module_name]['cycles'] = 0
|
||||
functions[func_name][module_name]['count'] = 0
|
||||
|
||||
# Set the end address of the previous function
|
||||
if func_prev is not None:
|
||||
func_prev['end'] = func_start
|
||||
func_prev = functions[func_name][module_name]
|
||||
|
||||
line = info_func_str.readline().strip('\n')
|
||||
|
||||
# Fixup the last function
|
||||
func_prev['end'] = modules[module_name]['end']
|
||||
|
||||
if symbols_file is not None:
|
||||
pickle.dump((modules, functions), open(symbols_file, "w"))
|
||||
except:
|
||||
if symbols_file is None:
|
||||
print "Error: Symbols file is required when run out of ARM DS-5"
|
||||
sys.exit()
|
||||
|
||||
(modules, functions) = pickle.load(open(symbols_file, "r"))
|
||||
|
||||
#
|
||||
# Build optimized table for the <Unknown> functions
|
||||
#
|
||||
functions_addr = {}
|
||||
for func_key, module in functions.iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
key = module_value['start'] & ~0x0FFF
|
||||
if key not in functions_addr.keys():
|
||||
functions_addr[key] = {}
|
||||
if func_key not in functions_addr[key].keys():
|
||||
functions_addr[key][func_key] = {}
|
||||
functions_addr[key][func_key][module_key] = module_value
|
||||
|
||||
#
|
||||
# Process the trace file
|
||||
#
|
||||
if trace_name is None:
|
||||
sys.exit()
|
||||
|
||||
trace = open(trace_name, "r")
|
||||
trace_size = os.path.getsize(trace_name)
|
||||
trace_process = 0
|
||||
|
||||
# Get the column names from the first line
|
||||
columns = trace_read().split()
|
||||
column_addr = columns.index('Address')
|
||||
column_cycles = columns.index('Cycles')
|
||||
column_function = columns.index('Function')
|
||||
|
||||
line = trace_read()
|
||||
i = 0
|
||||
prev_callee = None
|
||||
while line:
|
||||
try:
|
||||
func_name = line.split('\t')[column_function].strip()
|
||||
address = get_address_from_string(line.split('\t')[column_addr])
|
||||
cycles = int(line.split('\t')[column_cycles])
|
||||
callee = add_cycles_to_function(functions, func_name, address, cycles)
|
||||
if (prev_callee != None) and (prev_callee != callee):
|
||||
functions[prev_callee[0]][prev_callee[1]]['count'] += 1
|
||||
prev_callee = callee
|
||||
except ValueError:
|
||||
pass
|
||||
line = trace_read()
|
||||
if ((i % 1000000) == 0) and (i != 0):
|
||||
percent = (trace_process * 100.00) / trace_size
|
||||
print "Processing file ... (%.2f %%)" % (percent)
|
||||
i = i + 1
|
||||
|
||||
# Fixup the last callee
|
||||
functions[prev_callee[0]][prev_callee[1]]['count'] += 1
|
||||
|
||||
#
|
||||
# Process results
|
||||
#
|
||||
functions_cycles = {}
|
||||
all_functions_cycles = {}
|
||||
total_cycles = 0
|
||||
|
||||
for func_key, module in functions.iteritems():
|
||||
for module_key, module_value in module.iteritems():
|
||||
key = "%s/%s" % (module_key, func_key)
|
||||
functions_cycles[key] = (module_value['cycles'], module_value['count'])
|
||||
total_cycles += module_value['cycles']
|
||||
|
||||
if func_key not in all_functions_cycles.keys():
|
||||
all_functions_cycles[func_key] = (module_value['cycles'], module_value['count'])
|
||||
else:
|
||||
all_functions_cycles[func_key] = tuple(map(sum, zip(all_functions_cycles[func_key], (module_value['cycles'], module_value['count']))))
|
||||
|
||||
sorted_functions_cycles = sorted(functions_cycles.iteritems(), key=operator.itemgetter(1), reverse = True)
|
||||
sorted_all_functions_cycles = sorted(all_functions_cycles.items(), key=operator.itemgetter(1), reverse = True)
|
||||
|
||||
print
|
||||
print "----"
|
||||
for (key,value) in sorted_functions_cycles[:20]:
|
||||
if value[0] != 0:
|
||||
print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
|
||||
else:
|
||||
break;
|
||||
print "----"
|
||||
for (key,value) in sorted_all_functions_cycles[:20]:
|
||||
if value[0] != 0:
|
||||
print "%s (cycles: %d - %d%%, count: %d)" % (key, value[0], (value[0] * 100) / total_cycles, value[1])
|
||||
else:
|
||||
break;
|
||||
|
@@ -165,13 +165,11 @@
|
||||
# Secure Boot dependencies
|
||||
#
|
||||
!if $(SECURE_BOOT_ENABLE) == TRUE
|
||||
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
|
||||
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
|
||||
|
||||
# re-use the UserPhysicalPresent() dummy implementation from the ovmf tree
|
||||
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
|
||||
!else
|
||||
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
|
||||
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
|
||||
!endif
|
||||
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
|
||||
@@ -379,6 +377,10 @@
|
||||
<PcdsFixedAtBuild>
|
||||
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
|
||||
}
|
||||
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
|
||||
<PcdsFixedAtBuild>
|
||||
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
|
||||
}
|
||||
ShellPkg/Application/Shell/Shell.inf {
|
||||
<LibraryClasses>
|
||||
ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
|
||||
|
119
ArmVirtPkg/ArmVirtPkg.ci.yaml
Normal file
119
ArmVirtPkg/ArmVirtPkg.ci.yaml
Normal file
@@ -0,0 +1,119 @@
|
||||
## @file
|
||||
# Core CI configuration for ArmVirtPkg
|
||||
#
|
||||
# ArmVirtPkg is part of Platform Ci for builds so this is only
|
||||
# used for code analysis.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
## options defined .pytool/Plugin/LicenseCheck
|
||||
"LicenseCheck": {
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
"EccCheck": {
|
||||
## Exception sample looks like below:
|
||||
## "ExceptionList": [
|
||||
## "<ErrorID>", "<KeyWord>"
|
||||
## ]
|
||||
"ExceptionList": [
|
||||
],
|
||||
## Both file path and directory path are accepted.
|
||||
"IgnoreFiles": [
|
||||
]
|
||||
},
|
||||
## options defined .pytool/Plugin/CompilerPlugin
|
||||
"CompilerPlugin": {
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
|
||||
"HostUnitTestCompilerPlugin": {
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/CharEncodingCheck
|
||||
"CharEncodingCheck": {
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/DependencyCheck
|
||||
"DependencyCheck": {
|
||||
"AcceptableDependencies": [
|
||||
"MdePkg/MdePkg.dec",
|
||||
"MdeModulePkg/MdeModulePkg.dec",
|
||||
"ArmVirtPkg/ArmVirtPkg.dec",
|
||||
"NetworkPkg/NetworkPkg.dec",
|
||||
"ArmPkg/ArmPkg.dec",
|
||||
"OvmfPkg/OvmfPkg.dec",
|
||||
"EmbeddedPkg/EmbeddedPkg.dec",
|
||||
"ArmPlatformPkg/ArmPlatformPkg.dec",
|
||||
"SecurityPkg/SecurityPkg.dec",
|
||||
"ShellPkg/ShellPkg.dec" #Is this ok?
|
||||
],
|
||||
# For host based unit tests
|
||||
"AcceptableDependencies-HOST_APPLICATION":[
|
||||
"UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
|
||||
],
|
||||
# For UEFI shell based apps
|
||||
"AcceptableDependencies-UEFI_APPLICATION":[
|
||||
|
||||
],
|
||||
"IgnoreInf": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/DscCompleteCheck
|
||||
"DscCompleteCheck": {
|
||||
"IgnoreInf": [""],
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
|
||||
"HostUnitTestDscCompleteCheck": {
|
||||
"IgnoreInf": [""],
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/GuidCheck
|
||||
"GuidCheck": {
|
||||
"IgnoreGuidName": [],
|
||||
"IgnoreGuidValue": [],
|
||||
"IgnoreFoldersAndFiles": [],
|
||||
"IgnoreDuplicates": [],
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/LibraryClassCheck
|
||||
"LibraryClassCheck": {
|
||||
"IgnoreHeaderFile": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/SpellCheck
|
||||
"SpellCheck": {
|
||||
"AuditOnly": False, # Fails right now with over 270 errors
|
||||
"IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files
|
||||
"ExtendWords": [
|
||||
"setjump",
|
||||
"plong",
|
||||
"lparam",
|
||||
"lpdword",
|
||||
"lpthread",
|
||||
"lresult",
|
||||
"bootable",
|
||||
"bsymbolic",
|
||||
"endiannness",
|
||||
"fvmain",
|
||||
"multiboot",
|
||||
"qemu's",
|
||||
"ramdisk",
|
||||
"ramfb",
|
||||
"unbootable",
|
||||
"virt's",
|
||||
"werror",
|
||||
"xenio"
|
||||
], # words to extend to the dictionary for this package
|
||||
"IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
|
||||
"AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
|
||||
}
|
||||
}
|
@@ -36,6 +36,12 @@
|
||||
[Protocols]
|
||||
gFdtClientProtocolGuid = { 0xE11FACA0, 0x4710, 0x4C8E, { 0xA7, 0xA2, 0x01, 0xBA, 0xA2, 0x59, 0x1B, 0x4C } }
|
||||
|
||||
[PcdsFeatureFlag]
|
||||
#
|
||||
# Feature Flag PCD that defines whether TPM2 support is enabled
|
||||
#
|
||||
gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled|FALSE|BOOLEAN|0x00000004
|
||||
|
||||
[PcdsFixedAtBuild, PcdsPatchableInModule]
|
||||
#
|
||||
# This is the physical address where the device tree is expected to be stored
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#
|
||||
DEFINE TTY_TERMINAL = FALSE
|
||||
DEFINE SECURE_BOOT_ENABLE = FALSE
|
||||
DEFINE TPM2_ENABLE = FALSE
|
||||
DEFINE TPM2_CONFIG_ENABLE = FALSE
|
||||
|
||||
#
|
||||
# Network definition
|
||||
@@ -56,6 +58,8 @@
|
||||
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
|
||||
QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
|
||||
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
|
||||
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
|
||||
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
|
||||
|
||||
ArmPlatformLib|ArmPlatformPkg/Library/ArmPlatformLibNull/ArmPlatformLibNull.inf
|
||||
|
||||
@@ -74,12 +78,30 @@
|
||||
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
|
||||
PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
|
||||
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
|
||||
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
|
||||
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
|
||||
!else
|
||||
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.PEIM]
|
||||
ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoPeiLib.inf
|
||||
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
|
||||
ResetSystemLib|MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf
|
||||
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.DXE_DRIVER]
|
||||
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
|
||||
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.UEFI_DRIVER]
|
||||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
|
||||
@@ -100,6 +122,8 @@
|
||||
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE
|
||||
|
||||
gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled|$(TPM2_ENABLE)
|
||||
|
||||
[PcdsFixedAtBuild.common]
|
||||
!if $(ARCH) == AARCH64
|
||||
gArmTokenSpaceGuid.PcdVFPEnabled|1
|
||||
@@ -186,10 +210,6 @@
|
||||
# point only, for entry point versions >= 3.0.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosEntryPointProvideMethod|0x2
|
||||
|
||||
# ACPI predates the AARCH64 architecture by 5 versions, so
|
||||
# we only target OSes that support ACPI v5.0 or later
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20
|
||||
|
||||
[PcdsDynamicDefault.common]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
|
||||
|
||||
@@ -237,9 +257,29 @@
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
|
||||
|
||||
#
|
||||
# IPv4 and IPv6 PXE Boot support.
|
||||
#
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01
|
||||
|
||||
#
|
||||
# TPM2 support
|
||||
#
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0
|
||||
!endif
|
||||
|
||||
[PcdsDynamicHii]
|
||||
gArmVirtTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gArmVirtVariableGuid|0x0|FALSE|NV,BS
|
||||
|
||||
!if $(TPM2_CONFIG_ENABLE) == TRUE
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|3|NV,BS
|
||||
!endif
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Components Section - list of all EDK II Modules needed by this Platform
|
||||
@@ -261,6 +301,23 @@
|
||||
|
||||
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
|
||||
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf {
|
||||
<LibraryClasses>
|
||||
ResetSystemLib|ArmVirtPkg/Library/ArmVirtPsciResetSystemPeiLib/ArmVirtPsciResetSystemPeiLib.inf
|
||||
}
|
||||
OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
|
||||
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
|
||||
<LibraryClasses>
|
||||
HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
|
||||
}
|
||||
!endif
|
||||
|
||||
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
|
||||
<LibraryClasses>
|
||||
NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
|
||||
@@ -295,6 +352,9 @@
|
||||
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
|
||||
<LibraryClasses>
|
||||
NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
|
||||
!endif
|
||||
}
|
||||
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
|
||||
OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
|
||||
@@ -371,11 +431,18 @@
|
||||
NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
|
||||
NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
|
||||
}
|
||||
OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
|
||||
|
||||
#
|
||||
# Networking stack
|
||||
#
|
||||
!include NetworkPkg/NetworkComponents.dsc.inc
|
||||
|
||||
NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf {
|
||||
<LibraryClasses>
|
||||
NULL|OvmfPkg/Library/PxeBcPcdProducerLib/PxeBcPcdProducerLib.inf
|
||||
}
|
||||
|
||||
!if $(NETWORK_TLS_ENABLE) == TRUE
|
||||
NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
|
||||
<LibraryClasses>
|
||||
@@ -389,6 +456,11 @@
|
||||
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
|
||||
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
|
||||
|
||||
#
|
||||
# NVME Driver
|
||||
#
|
||||
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
|
||||
|
||||
#
|
||||
# SMBIOS Support
|
||||
#
|
||||
@@ -430,6 +502,26 @@
|
||||
MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
|
||||
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
|
||||
|
||||
#
|
||||
# TPM2 support
|
||||
#
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf {
|
||||
<LibraryClasses>
|
||||
HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
|
||||
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
|
||||
NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
|
||||
NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
|
||||
}
|
||||
!if $(TPM2_CONFIG_ENABLE) == TRUE
|
||||
SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
|
||||
!endif
|
||||
!endif
|
||||
|
||||
#
|
||||
# ACPI Support
|
||||
#
|
||||
|
@@ -113,6 +113,12 @@ READ_LOCK_STATUS = TRUE
|
||||
INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
|
||||
INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
|
||||
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
INF MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf
|
||||
INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
|
||||
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
|
||||
!endif
|
||||
|
||||
FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
|
||||
SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
|
||||
SECTION FV_IMAGE = FVMAIN
|
||||
|
@@ -103,6 +103,7 @@ READ_LOCK_STATUS = TRUE
|
||||
#
|
||||
INF ShellPkg/Application/Shell/Shell.inf
|
||||
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
|
||||
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
|
||||
|
||||
#
|
||||
# Bds
|
||||
@@ -113,6 +114,7 @@ READ_LOCK_STATUS = TRUE
|
||||
INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
|
||||
INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
|
||||
INF MdeModulePkg/Application/UiApp/UiApp.inf
|
||||
INF OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
|
||||
|
||||
#
|
||||
# Networking stack
|
||||
@@ -126,6 +128,11 @@ READ_LOCK_STATUS = TRUE
|
||||
INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
|
||||
INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
|
||||
|
||||
#
|
||||
# NVME Driver
|
||||
#
|
||||
INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
|
||||
|
||||
#
|
||||
# SMBIOS Support
|
||||
#
|
||||
@@ -173,6 +180,16 @@ READ_LOCK_STATUS = TRUE
|
||||
INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
|
||||
INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
|
||||
|
||||
#
|
||||
# TPM2 support
|
||||
#
|
||||
!if $(TPM2_ENABLE) == TRUE
|
||||
INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
|
||||
!if $(TPM2_CONFIG_ENABLE) == TRUE
|
||||
INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
|
||||
!endif
|
||||
!endif
|
||||
|
||||
#
|
||||
# TianoCore logo (splash screen)
|
||||
#
|
||||
|
@@ -56,6 +56,8 @@
|
||||
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
|
||||
QemuFwCfgLib|ArmVirtPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
|
||||
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
|
||||
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
|
||||
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
|
||||
|
||||
ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.inf
|
||||
|
||||
@@ -73,6 +75,7 @@
|
||||
PciPcdProducerLib|ArmVirtPkg/Library/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
|
||||
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
|
||||
PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridgeLib.inf
|
||||
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
|
||||
|
||||
[LibraryClasses.common.DXE_DRIVER]
|
||||
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
|
||||
@@ -80,14 +83,12 @@
|
||||
[LibraryClasses.common.UEFI_DRIVER]
|
||||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
|
||||
[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE]
|
||||
[BuildOptions]
|
||||
#
|
||||
# CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists
|
||||
# on emitting GOT based symbol references when running in shared mode, unless
|
||||
# we override visibility to 'hidden' in all modules that make up the PrePi
|
||||
# build.
|
||||
# We need to avoid jump tables in SEC modules, so that the PE/COFF
|
||||
# self-relocation code itself is guaranteed to be position independent.
|
||||
#
|
||||
GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h
|
||||
GCC:*_*_*_CC_FLAGS = -fno-jump-tables
|
||||
|
||||
################################################################################
|
||||
#
|
||||
@@ -172,6 +173,12 @@
|
||||
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|3
|
||||
|
||||
[PcdsPatchableInModule.common]
|
||||
# we need to provide a resolution for this PCD that supports PcdSet64()
|
||||
# being called from ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c,
|
||||
# even though that call will be compiled out on this platform as it does
|
||||
# not (and cannot) support the TPM2 driver stack
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0
|
||||
|
||||
#
|
||||
# This will be overridden in the code
|
||||
#
|
||||
@@ -231,6 +238,12 @@
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
|
||||
|
||||
#
|
||||
# IPv4 and IPv6 PXE Boot support.
|
||||
#
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
|
||||
gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Components Section - list of all EDK II Modules needed by this Platform
|
||||
@@ -355,11 +368,18 @@
|
||||
NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
|
||||
NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
|
||||
}
|
||||
OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
|
||||
|
||||
#
|
||||
# Networking stack
|
||||
#
|
||||
!include NetworkPkg/NetworkComponents.dsc.inc
|
||||
|
||||
NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf {
|
||||
<LibraryClasses>
|
||||
NULL|OvmfPkg/Library/PxeBcPcdProducerLib/PxeBcPcdProducerLib.inf
|
||||
}
|
||||
|
||||
!if $(NETWORK_TLS_ENABLE) == TRUE
|
||||
NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
|
||||
<LibraryClasses>
|
||||
@@ -373,6 +393,11 @@
|
||||
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
|
||||
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
|
||||
|
||||
#
|
||||
# NVME Driver
|
||||
#
|
||||
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
|
||||
|
||||
#
|
||||
# SMBIOS Support
|
||||
#
|
||||
|
@@ -136,7 +136,7 @@ READ_STATUS = TRUE
|
||||
READ_LOCK_CAP = TRUE
|
||||
READ_LOCK_STATUS = TRUE
|
||||
|
||||
INF ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
|
||||
INF RuleOverride = SELF_RELOC ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
|
||||
|
||||
FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
|
||||
SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
|
||||
|
@@ -39,6 +39,11 @@
|
||||
TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
|
||||
}
|
||||
|
||||
[Rule.Common.SEC.SELF_RELOC]
|
||||
FILE SEC = $(NAMED_GUID) {
|
||||
TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
|
||||
}
|
||||
|
||||
[Rule.Common.PEI_CORE]
|
||||
FILE PEI_CORE = $(NAMED_GUID) FIXED {
|
||||
TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
|
||||
|
@@ -47,18 +47,17 @@
|
||||
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
|
||||
PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||||
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
|
||||
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
|
||||
|
||||
[LibraryClasses.common.UEFI_DRIVER]
|
||||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
|
||||
[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE]
|
||||
[BuildOptions]
|
||||
#
|
||||
# CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists
|
||||
# on emitting GOT based symbol references when running in shared mode, unless
|
||||
# we override visibility to 'hidden' in all modules that make up the PrePi
|
||||
# build.
|
||||
# We need to avoid jump tables in SEC modules, so that the PE/COFF
|
||||
# self-relocation code itself is guaranteed to be position independent.
|
||||
#
|
||||
GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h
|
||||
GCC:*_*_*_CC_FLAGS = -fno-jump-tables
|
||||
|
||||
################################################################################
|
||||
#
|
||||
@@ -95,6 +94,12 @@
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
|
||||
|
||||
[PcdsPatchableInModule.common]
|
||||
# we need to provide a resolution for this PCD that supports PcdSet64()
|
||||
# being called from ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c,
|
||||
# even though that call will be compiled out on this platform as it does
|
||||
# not (and cannot) support the TPM2 driver stack
|
||||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0
|
||||
|
||||
#
|
||||
# This will be overridden in the code
|
||||
#
|
||||
|
@@ -182,6 +182,7 @@ READ_LOCK_STATUS = TRUE
|
||||
#
|
||||
INF ShellPkg/Application/Shell/Shell.inf
|
||||
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
|
||||
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
|
||||
|
||||
#
|
||||
# Bds
|
||||
@@ -232,7 +233,7 @@ READ_STATUS = TRUE
|
||||
READ_LOCK_CAP = TRUE
|
||||
READ_LOCK_STATUS = TRUE
|
||||
|
||||
INF ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
|
||||
INF RuleOverride = SELF_RELOC ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
|
||||
|
||||
FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
|
||||
SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
|
||||
|
@@ -1,22 +0,0 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2018, Linaro Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PLATFORM_HIDDEN_H
|
||||
#define __PLATFORM_HIDDEN_H
|
||||
|
||||
//
|
||||
// Setting the GCC -fvisibility=hidden command line option is not quite the same
|
||||
// as setting the pragma below: the former only affects definitions, whereas the
|
||||
// pragma affects extern declarations as well. So if we want to ensure that no
|
||||
// GOT indirected symbol references are emitted, we need to use the pragma, or
|
||||
// GOT based cross object references could be emitted, e.g., in libraries, and
|
||||
// these cannot be relaxed to ordinary symbol references at link time.
|
||||
//
|
||||
#pragma GCC visibility push (hidden)
|
||||
|
||||
#endif
|
@@ -110,7 +110,12 @@ ArmVirtGicArchLibConstructor (
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ASSERT (RegSize == 32);
|
||||
//
|
||||
// When the GICv2 is emulated with virtualization=on, it adds a virtual
|
||||
// set of control registers. This means the register property can be
|
||||
// either 32 or 64 bytes in size.
|
||||
//
|
||||
ASSERT ((RegSize == 32) || (RegSize == 64));
|
||||
|
||||
DistBase = SwapBytes64 (Reg[0]);
|
||||
CpuBase = SwapBytes64 (Reg[2]);
|
||||
|
@@ -145,20 +145,6 @@ ResetShutdown (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes the system to enter S3 and then wake up immediately.
|
||||
|
||||
If this function returns, it means that the system does not support S3 feature.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
EnterS3WithImmediateWake (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes a systemwide reset. The exact type of the reset is
|
||||
defined by the EFI_GUID that follows the Null-terminated Unicode string passed
|
||||
|
@@ -0,0 +1,232 @@
|
||||
/** @file
|
||||
Reset System lib using PSCI hypervisor or secure monitor calls
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2014-2020, Linaro Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
#include <Library/ArmHvcLib.h>
|
||||
#include <Library/ArmSmcLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/ResetSystemLib.h>
|
||||
|
||||
#include <IndustryStandard/ArmStdSmc.h>
|
||||
|
||||
typedef enum {
|
||||
PsciMethodUnknown,
|
||||
PsciMethodSmc,
|
||||
PsciMethodHvc,
|
||||
} PSCI_METHOD;
|
||||
|
||||
STATIC
|
||||
PSCI_METHOD
|
||||
DiscoverPsciMethod (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID *DeviceTreeBase;
|
||||
INT32 Node, Prev;
|
||||
INT32 Len;
|
||||
CONST CHAR8 *Compatible;
|
||||
CONST CHAR8 *CompatibleItem;
|
||||
CONST VOID *Prop;
|
||||
|
||||
DeviceTreeBase = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
||||
ASSERT (fdt_check_header (DeviceTreeBase) == 0);
|
||||
|
||||
//
|
||||
// Enumerate all FDT nodes looking for the PSCI node and capture the method
|
||||
//
|
||||
for (Prev = 0;; Prev = Node) {
|
||||
Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
|
||||
if (Node < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
|
||||
if (Compatible == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Iterate over the NULL-separated items in the compatible string
|
||||
//
|
||||
for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
|
||||
CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {
|
||||
|
||||
if (AsciiStrCmp (CompatibleItem, "arm,psci-0.2") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Prop = fdt_getprop (DeviceTreeBase, Node, "method", NULL);
|
||||
if (!Prop) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Missing PSCI method property\n",
|
||||
__FUNCTION__));
|
||||
return PsciMethodUnknown;
|
||||
}
|
||||
|
||||
if (AsciiStrnCmp (Prop, "hvc", 3) == 0) {
|
||||
return PsciMethodHvc;
|
||||
} else if (AsciiStrnCmp (Prop, "smc", 3) == 0) {
|
||||
return PsciMethodSmc;
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Unknown PSCI method \"%a\"\n", __FUNCTION__,
|
||||
Prop));
|
||||
return PsciMethodUnknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PsciMethodUnknown;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
PerformPsciAction (
|
||||
IN UINTN Arg0
|
||||
)
|
||||
{
|
||||
ARM_SMC_ARGS ArmSmcArgs;
|
||||
ARM_HVC_ARGS ArmHvcArgs;
|
||||
|
||||
ArmSmcArgs.Arg0 = Arg0;
|
||||
ArmHvcArgs.Arg0 = Arg0;
|
||||
|
||||
switch (DiscoverPsciMethod ()) {
|
||||
case PsciMethodHvc:
|
||||
ArmCallHvc (&ArmHvcArgs);
|
||||
break;
|
||||
|
||||
case PsciMethodSmc:
|
||||
ArmCallSmc (&ArmSmcArgs);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG ((DEBUG_ERROR, "%a: no PSCI method defined\n", __FUNCTION__));
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes a system-wide reset (cold reset), in which
|
||||
all circuitry within the system returns to its initial state. This type of reset
|
||||
is asynchronous to system operation and operates without regard to
|
||||
cycle boundaries.
|
||||
|
||||
If this function returns, it means that the system does not support cold reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetCold (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Send a PSCI 0.2 SYSTEM_RESET command
|
||||
PerformPsciAction (ARM_SMC_ID_PSCI_SYSTEM_RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes a system-wide initialization (warm reset), in which all processors
|
||||
are set to their initial state. Pending cycles are not corrupted.
|
||||
|
||||
If this function returns, it means that the system does not support warm reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetWarm (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Map a warm reset into a cold reset
|
||||
ResetCold ();
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes the system to enter a power state equivalent
|
||||
to the ACPI G2/S5 or G3 states.
|
||||
|
||||
If this function returns, it means that the system does not support shutdown reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetShutdown (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Send a PSCI 0.2 SYSTEM_OFF command
|
||||
PerformPsciAction (ARM_SMC_ID_PSCI_SYSTEM_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
This function causes a systemwide reset. The exact type of the reset is
|
||||
defined by the EFI_GUID that follows the Null-terminated Unicode string passed
|
||||
into ResetData. If the platform does not recognize the EFI_GUID in ResetData
|
||||
the platform must pick a supported reset type to perform.The platform may
|
||||
optionally log the parameters from any non-normal reset that occurs.
|
||||
|
||||
@param[in] DataSize The size, in bytes, of ResetData.
|
||||
@param[in] ResetData The data buffer starts with a Null-terminated string,
|
||||
followed by the EFI_GUID.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetPlatformSpecific (
|
||||
IN UINTN DataSize,
|
||||
IN VOID *ResetData
|
||||
)
|
||||
{
|
||||
// Map the platform specific reset as reboot
|
||||
ResetCold ();
|
||||
}
|
||||
|
||||
/**
|
||||
The ResetSystem function resets the entire platform.
|
||||
|
||||
@param[in] ResetType The type of reset to perform.
|
||||
@param[in] ResetStatus The status code for the reset.
|
||||
@param[in] DataSize The size, in bytes, of ResetData.
|
||||
@param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown
|
||||
the data buffer starts with a Null-terminated string, optionally
|
||||
followed by additional binary data. The string is a description
|
||||
that the caller may use to further indicate the reason for the
|
||||
system reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetSystem (
|
||||
IN EFI_RESET_TYPE ResetType,
|
||||
IN EFI_STATUS ResetStatus,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *ResetData OPTIONAL
|
||||
)
|
||||
{
|
||||
switch (ResetType) {
|
||||
case EfiResetWarm:
|
||||
ResetWarm ();
|
||||
break;
|
||||
|
||||
case EfiResetCold:
|
||||
ResetCold ();
|
||||
break;
|
||||
|
||||
case EfiResetShutdown:
|
||||
ResetShutdown ();
|
||||
return;
|
||||
|
||||
case EfiResetPlatformSpecific:
|
||||
ResetPlatformSpecific (DataSize, ResetData);
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user