mirror of
https://github.com/qca/qca-swiss-army-knife.git
synced 2025-12-10 07:44:42 +01:00
Compare commits
157 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e3ee2446a | ||
|
|
61d85e04cf | ||
|
|
03252af2fe | ||
|
|
c1e4ca6032 | ||
|
|
852bd62202 | ||
|
|
c66ae81c34 | ||
|
|
a87e8e4971 | ||
|
|
e81a60303e | ||
|
|
0ff2f11365 | ||
|
|
7c191e5530 | ||
|
|
34ba9a417a | ||
|
|
0c0ecdde8d | ||
|
|
e53ea71655 | ||
|
|
3349c9cfbd | ||
|
|
8adc4981da | ||
|
|
4883953301 | ||
|
|
7a1463a442 | ||
|
|
4af5153126 | ||
|
|
a5ef12e166 | ||
|
|
06cbf01a58 | ||
|
|
583eed7e66 | ||
|
|
e9a0327f3f | ||
|
|
741a9f6d27 | ||
|
|
d23aaaec6e | ||
|
|
8ec3e5dbb8 | ||
|
|
88724401e4 | ||
|
|
0982c0f22e | ||
|
|
ef11ea4c7a | ||
|
|
0a556ac040 | ||
|
|
02efab2e3e | ||
|
|
f216408592 | ||
|
|
60d4be5e42 | ||
|
|
6209ad4248 | ||
|
|
0df6dcf34f | ||
|
|
b011424559 | ||
|
|
32f41c2db0 | ||
|
|
779e51b9de | ||
|
|
8aafad4337 | ||
|
|
d0f69db447 | ||
|
|
cc349436fe | ||
|
|
e5372e1524 | ||
|
|
d5ebee489e | ||
|
|
2bd53768fa | ||
|
|
9a16a4abec | ||
|
|
c880314adb | ||
|
|
27d9574ce6 | ||
|
|
a163e2363f | ||
|
|
b0e7d9c976 | ||
|
|
69808f48c1 | ||
|
|
1a320ce216 | ||
|
|
1b7c9fb32c | ||
|
|
df3a159d34 | ||
|
|
c3dde80180 | ||
|
|
b0e905ff7b | ||
|
|
1b102ba512 | ||
|
|
581c684881 | ||
|
|
16978c25c8 | ||
|
|
29b0a2607f | ||
|
|
014bb0c6ac | ||
|
|
d2fb7b932a | ||
|
|
4661dc4994 | ||
|
|
e471454ac6 | ||
|
|
25a662da8a | ||
|
|
105e81816d | ||
|
|
52d3a2f0fc | ||
|
|
9983705ee8 | ||
|
|
64a3e2aabf | ||
|
|
ae8de256db | ||
|
|
8e32e24877 | ||
|
|
3c1f22bdc4 | ||
|
|
fe60d963b2 | ||
|
|
df3e162316 | ||
|
|
f85b165960 | ||
|
|
b8f89c13d0 | ||
|
|
ec8783694c | ||
|
|
5be8c832f5 | ||
|
|
4b2b0e0c16 | ||
|
|
8633532930 | ||
|
|
26ca6eff75 | ||
|
|
3d23932fd8 | ||
|
|
4ffa07ff68 | ||
|
|
5ede3cc07e | ||
|
|
45f9903552 | ||
|
|
cc7558fe2c | ||
|
|
6fef42b8a8 | ||
|
|
c2bd6f580d | ||
|
|
60bec5a5b9 | ||
|
|
8c813ad8b8 | ||
|
|
6cb86fb99b | ||
|
|
31bc69fe0c | ||
|
|
15852ea927 | ||
|
|
0c01a2abc3 | ||
|
|
4d397963b1 | ||
|
|
30ea075ea1 | ||
|
|
bec3a2f191 | ||
|
|
f9cbcad82a | ||
|
|
7c5ac7ec65 | ||
|
|
497200c3fd | ||
|
|
063dff9967 | ||
|
|
141f3b0e02 | ||
|
|
605442e9a8 | ||
|
|
99c601ea1f | ||
|
|
6c34812fc7 | ||
|
|
26f9460b33 | ||
|
|
f371c26cea | ||
|
|
db953a5381 | ||
|
|
e1df87fd10 | ||
|
|
3ead7a23e8 | ||
|
|
e92ab4b9b9 | ||
|
|
a208017c60 | ||
|
|
30da9160b8 | ||
|
|
8a80300141 | ||
|
|
d9c3d5857a | ||
|
|
e23fbd3c96 | ||
|
|
d278f25bc9 | ||
|
|
496c42817e | ||
|
|
25d27878f4 | ||
|
|
ceb26e3416 | ||
|
|
b9a32cfd44 | ||
|
|
f33d779002 | ||
|
|
4d0fe54348 | ||
|
|
e07a588ad4 | ||
|
|
cc5a3bd6f6 | ||
|
|
d2a219ab16 | ||
|
|
cf8d9a8c83 | ||
|
|
a34666a4fc | ||
|
|
e5f25e1af0 | ||
|
|
dfd83b4336 | ||
|
|
4b4ce97aa9 | ||
|
|
40f0f7474b | ||
|
|
17622eeb5d | ||
|
|
25e5adbb2d | ||
|
|
91c07af56b | ||
|
|
7e2081c04b | ||
|
|
4a20ff7a97 | ||
|
|
d610cee8b7 | ||
|
|
c991fcb638 | ||
|
|
cfb531695a | ||
|
|
b2b06517bb | ||
|
|
41b194534b | ||
|
|
587f0ca617 | ||
|
|
7903ede3c6 | ||
|
|
04d7947835 | ||
|
|
6e45f8edcd | ||
|
|
6502f41f55 | ||
|
|
957c4b05fb | ||
|
|
604f47bec1 | ||
|
|
511deeff3a | ||
|
|
6d32fea2d2 | ||
|
|
8acc7b7bc9 | ||
|
|
496ac7d700 | ||
|
|
43438ab80b | ||
|
|
65b32571db | ||
|
|
0c8d850849 | ||
|
|
fb0da09651 | ||
|
|
da261b1555 | ||
|
|
c6ac8ad9aa |
22 changed files with 13788 additions and 155 deletions
|
|
@ -9,21 +9,19 @@ ATHEROS_DEPS += \
|
|||
ar5416.ini \
|
||||
ar5416_howl.ini \
|
||||
ar5416_sowl.ini \
|
||||
ar9280.ini \
|
||||
ar9280_merlin2.ini \
|
||||
ar9285.ini \
|
||||
ar9285_v1_2.ini \
|
||||
ar9287.ini \
|
||||
ar9287_1_1.ini \
|
||||
ar9271.ini \
|
||||
ar9300_osprey22.ini \
|
||||
ar9330_11.ini \
|
||||
ar9330_12.ini \
|
||||
ar9340.ini \
|
||||
ar9485.ini \
|
||||
ar955x.ini \
|
||||
ar9580.ini \
|
||||
ar9300_jupiter20.ini \
|
||||
ar9300_jupiter21.ini \
|
||||
ar9300_aphrodite10.ini
|
||||
endif
|
||||
|
||||
|
|
@ -39,6 +37,7 @@ ATH9K_HEADERS = \
|
|||
ar955x-1p0:ar955x_1p0_initvals.h \
|
||||
ar9580-1p0:ar9580_1p0_initvals.h \
|
||||
ar9462-2p0:ar9462_2p0_initvals.h \
|
||||
ar9462-2p1:ar9462_2p1_initvals.h \
|
||||
ar9565-1p0:ar9565_1p0_initvals.h
|
||||
|
||||
ifndef ATHEROS
|
||||
|
|
|
|||
|
|
@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
|
|||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18253ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{0x00018c08, 0x0003580c},
|
||||
{0x00018c08, 0x0003780c},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
|
||||
{0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
|
||||
{0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
|
||||
{0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81},
|
||||
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
|
||||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
|
||||
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
|
||||
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
|
||||
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2},
|
||||
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
|
||||
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
|
||||
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
|
||||
{0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282},
|
||||
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
|
||||
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
|
||||
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
|
||||
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
|
||||
|
|
@ -78,13 +78,13 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
|
||||
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
|
||||
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
|
||||
{0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
|
||||
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
|
||||
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
|
||||
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
|
||||
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000},
|
||||
{0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000},
|
||||
{0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa},
|
||||
{0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00},
|
||||
{0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00},
|
||||
{0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
|
||||
{0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
|
||||
{0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
|
||||
|
|
@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
|
|||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18213ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{0x00018c08, 0x0003580c},
|
||||
{0x00018c08, 0x0003780c},
|
||||
};
|
||||
|
||||
static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18212ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{0x00018c08, 0x0003580c},
|
||||
{0x00018c08, 0x0003780c},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
|
||||
|
|
@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
|
|||
{0x00009fc0, 0x803e4788},
|
||||
{0x00009fc4, 0x0001efb5},
|
||||
{0x00009fcc, 0x40000014},
|
||||
{0x00009fd0, 0x01193b93},
|
||||
{0x00009fd0, 0x0a193b93},
|
||||
{0x0000a20c, 0x00000000},
|
||||
{0x0000a220, 0x00000000},
|
||||
{0x0000a224, 0x00000000},
|
||||
|
|
@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
|
|||
{0x0000a7cc, 0x00000000},
|
||||
{0x0000a7d0, 0x00000000},
|
||||
{0x0000a7d4, 0x00000004},
|
||||
{0x0000a7dc, 0x00000001},
|
||||
{0x0000a7dc, 0x00000000},
|
||||
{0x0000a7f0, 0x80000000},
|
||||
{0x0000a8d0, 0x004b6a8e},
|
||||
{0x0000a8d4, 0x00000820},
|
||||
|
|
@ -879,6 +879,69 @@ static const u32 ar9462_2p0_radio_postamble[][5] = {
|
|||
{0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
|
||||
};
|
||||
|
||||
static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de},
|
||||
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400},
|
||||
{0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402},
|
||||
{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603},
|
||||
{0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02},
|
||||
{0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04},
|
||||
{0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20},
|
||||
{0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20},
|
||||
{0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22},
|
||||
{0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24},
|
||||
{0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640},
|
||||
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660},
|
||||
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861},
|
||||
{0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81},
|
||||
{0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83},
|
||||
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84},
|
||||
{0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3},
|
||||
{0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5},
|
||||
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9},
|
||||
{0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec},
|
||||
{0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0},
|
||||
{0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4},
|
||||
{0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
|
||||
{0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
|
||||
{0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
|
||||
{0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
};
|
||||
|
||||
static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
|
|
@ -886,7 +949,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de},
|
||||
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
|
|
@ -906,20 +969,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
|
||||
{0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84},
|
||||
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0},
|
||||
{0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4},
|
||||
{0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
|
||||
{0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
|
||||
{0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
|
||||
{0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
|
@ -1053,7 +1116,6 @@ static const u32 ar9462_2p0_mac_core[][2] = {
|
|||
{0x00008044, 0x00000000},
|
||||
{0x00008048, 0x00000000},
|
||||
{0x0000804c, 0xffffffff},
|
||||
{0x00008050, 0xffffffff},
|
||||
{0x00008054, 0x00000000},
|
||||
{0x00008058, 0x00000000},
|
||||
{0x0000805c, 0x000fc78f},
|
||||
|
|
@ -1117,9 +1179,9 @@ static const u32 ar9462_2p0_mac_core[][2] = {
|
|||
{0x000081f8, 0x00000000},
|
||||
{0x000081fc, 0x00000000},
|
||||
{0x00008240, 0x00100000},
|
||||
{0x00008244, 0x0010f424},
|
||||
{0x00008244, 0x0010f400},
|
||||
{0x00008248, 0x00000800},
|
||||
{0x0000824c, 0x0001e848},
|
||||
{0x0000824c, 0x0001e800},
|
||||
{0x00008250, 0x00000000},
|
||||
{0x00008254, 0x00000000},
|
||||
{0x00008258, 0x00000000},
|
||||
|
|
@ -1450,4 +1512,284 @@ static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = {
|
|||
{0x0000b1fc, 0x00000196},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000a000, 0x00010000},
|
||||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
{0x0000a00c, 0x00810080},
|
||||
{0x0000a010, 0x00830082},
|
||||
{0x0000a014, 0x01810180},
|
||||
{0x0000a018, 0x01830182},
|
||||
{0x0000a01c, 0x01850184},
|
||||
{0x0000a020, 0x01890188},
|
||||
{0x0000a024, 0x018b018a},
|
||||
{0x0000a028, 0x018d018c},
|
||||
{0x0000a02c, 0x03820190},
|
||||
{0x0000a030, 0x03840383},
|
||||
{0x0000a034, 0x03880385},
|
||||
{0x0000a038, 0x038a0389},
|
||||
{0x0000a03c, 0x038c038b},
|
||||
{0x0000a040, 0x0390038d},
|
||||
{0x0000a044, 0x03920391},
|
||||
{0x0000a048, 0x03940393},
|
||||
{0x0000a04c, 0x03960395},
|
||||
{0x0000a050, 0x00000000},
|
||||
{0x0000a054, 0x00000000},
|
||||
{0x0000a058, 0x00000000},
|
||||
{0x0000a05c, 0x00000000},
|
||||
{0x0000a060, 0x00000000},
|
||||
{0x0000a064, 0x00000000},
|
||||
{0x0000a068, 0x00000000},
|
||||
{0x0000a06c, 0x00000000},
|
||||
{0x0000a070, 0x00000000},
|
||||
{0x0000a074, 0x00000000},
|
||||
{0x0000a078, 0x00000000},
|
||||
{0x0000a07c, 0x00000000},
|
||||
{0x0000a080, 0x29292929},
|
||||
{0x0000a084, 0x29292929},
|
||||
{0x0000a088, 0x29292929},
|
||||
{0x0000a08c, 0x29292929},
|
||||
{0x0000a090, 0x22292929},
|
||||
{0x0000a094, 0x1d1d2222},
|
||||
{0x0000a098, 0x0c111117},
|
||||
{0x0000a09c, 0x00030303},
|
||||
{0x0000a0a0, 0x00000000},
|
||||
{0x0000a0a4, 0x00000000},
|
||||
{0x0000a0a8, 0x00000000},
|
||||
{0x0000a0ac, 0x00000000},
|
||||
{0x0000a0b0, 0x00000000},
|
||||
{0x0000a0b4, 0x00000000},
|
||||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x01000101},
|
||||
{0x0000a0c8, 0x011e011f},
|
||||
{0x0000a0cc, 0x011c011d},
|
||||
{0x0000a0d0, 0x02030204},
|
||||
{0x0000a0d4, 0x02010202},
|
||||
{0x0000a0d8, 0x021f0200},
|
||||
{0x0000a0dc, 0x0302021e},
|
||||
{0x0000a0e0, 0x03000301},
|
||||
{0x0000a0e4, 0x031e031f},
|
||||
{0x0000a0e8, 0x0402031d},
|
||||
{0x0000a0ec, 0x04000401},
|
||||
{0x0000a0f0, 0x041e041f},
|
||||
{0x0000a0f4, 0x0502041d},
|
||||
{0x0000a0f8, 0x05000501},
|
||||
{0x0000a0fc, 0x051e051f},
|
||||
{0x0000a100, 0x06010602},
|
||||
{0x0000a104, 0x061f0600},
|
||||
{0x0000a108, 0x061d061e},
|
||||
{0x0000a10c, 0x07020703},
|
||||
{0x0000a110, 0x07000701},
|
||||
{0x0000a114, 0x00000000},
|
||||
{0x0000a118, 0x00000000},
|
||||
{0x0000a11c, 0x00000000},
|
||||
{0x0000a120, 0x00000000},
|
||||
{0x0000a124, 0x00000000},
|
||||
{0x0000a128, 0x00000000},
|
||||
{0x0000a12c, 0x00000000},
|
||||
{0x0000a130, 0x00000000},
|
||||
{0x0000a134, 0x00000000},
|
||||
{0x0000a138, 0x00000000},
|
||||
{0x0000a13c, 0x00000000},
|
||||
{0x0000a140, 0x001f0000},
|
||||
{0x0000a144, 0x01000101},
|
||||
{0x0000a148, 0x011e011f},
|
||||
{0x0000a14c, 0x011c011d},
|
||||
{0x0000a150, 0x02030204},
|
||||
{0x0000a154, 0x02010202},
|
||||
{0x0000a158, 0x021f0200},
|
||||
{0x0000a15c, 0x0302021e},
|
||||
{0x0000a160, 0x03000301},
|
||||
{0x0000a164, 0x031e031f},
|
||||
{0x0000a168, 0x0402031d},
|
||||
{0x0000a16c, 0x04000401},
|
||||
{0x0000a170, 0x041e041f},
|
||||
{0x0000a174, 0x0502041d},
|
||||
{0x0000a178, 0x05000501},
|
||||
{0x0000a17c, 0x051e051f},
|
||||
{0x0000a180, 0x06010602},
|
||||
{0x0000a184, 0x061f0600},
|
||||
{0x0000a188, 0x061d061e},
|
||||
{0x0000a18c, 0x07020703},
|
||||
{0x0000a190, 0x07000701},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
{0x0000a1a0, 0x00000000},
|
||||
{0x0000a1a4, 0x00000000},
|
||||
{0x0000a1a8, 0x00000000},
|
||||
{0x0000a1ac, 0x00000000},
|
||||
{0x0000a1b0, 0x00000000},
|
||||
{0x0000a1b4, 0x00000000},
|
||||
{0x0000a1b8, 0x00000000},
|
||||
{0x0000a1bc, 0x00000000},
|
||||
{0x0000a1c0, 0x00000000},
|
||||
{0x0000a1c4, 0x00000000},
|
||||
{0x0000a1c8, 0x00000000},
|
||||
{0x0000a1cc, 0x00000000},
|
||||
{0x0000a1d0, 0x00000000},
|
||||
{0x0000a1d4, 0x00000000},
|
||||
{0x0000a1d8, 0x00000000},
|
||||
{0x0000a1dc, 0x00000000},
|
||||
{0x0000a1e0, 0x00000000},
|
||||
{0x0000a1e4, 0x00000000},
|
||||
{0x0000a1e8, 0x00000000},
|
||||
{0x0000a1ec, 0x00000000},
|
||||
{0x0000a1f0, 0x00000396},
|
||||
{0x0000a1f4, 0x00000396},
|
||||
{0x0000a1f8, 0x00000396},
|
||||
{0x0000a1fc, 0x00000196},
|
||||
{0x0000b000, 0x00010000},
|
||||
{0x0000b004, 0x00030002},
|
||||
{0x0000b008, 0x00050004},
|
||||
{0x0000b00c, 0x00810080},
|
||||
{0x0000b010, 0x00830082},
|
||||
{0x0000b014, 0x01810180},
|
||||
{0x0000b018, 0x01830182},
|
||||
{0x0000b01c, 0x01850184},
|
||||
{0x0000b020, 0x02810280},
|
||||
{0x0000b024, 0x02830282},
|
||||
{0x0000b028, 0x02850284},
|
||||
{0x0000b02c, 0x02890288},
|
||||
{0x0000b030, 0x028b028a},
|
||||
{0x0000b034, 0x0388028c},
|
||||
{0x0000b038, 0x038a0389},
|
||||
{0x0000b03c, 0x038c038b},
|
||||
{0x0000b040, 0x0390038d},
|
||||
{0x0000b044, 0x03920391},
|
||||
{0x0000b048, 0x03940393},
|
||||
{0x0000b04c, 0x03960395},
|
||||
{0x0000b050, 0x00000000},
|
||||
{0x0000b054, 0x00000000},
|
||||
{0x0000b058, 0x00000000},
|
||||
{0x0000b05c, 0x00000000},
|
||||
{0x0000b060, 0x00000000},
|
||||
{0x0000b064, 0x00000000},
|
||||
{0x0000b068, 0x00000000},
|
||||
{0x0000b06c, 0x00000000},
|
||||
{0x0000b070, 0x00000000},
|
||||
{0x0000b074, 0x00000000},
|
||||
{0x0000b078, 0x00000000},
|
||||
{0x0000b07c, 0x00000000},
|
||||
{0x0000b080, 0x2a2d2f32},
|
||||
{0x0000b084, 0x21232328},
|
||||
{0x0000b088, 0x19191c1e},
|
||||
{0x0000b08c, 0x12141417},
|
||||
{0x0000b090, 0x07070e0e},
|
||||
{0x0000b094, 0x03030305},
|
||||
{0x0000b098, 0x00000003},
|
||||
{0x0000b09c, 0x00000000},
|
||||
{0x0000b0a0, 0x00000000},
|
||||
{0x0000b0a4, 0x00000000},
|
||||
{0x0000b0a8, 0x00000000},
|
||||
{0x0000b0ac, 0x00000000},
|
||||
{0x0000b0b0, 0x00000000},
|
||||
{0x0000b0b4, 0x00000000},
|
||||
{0x0000b0b8, 0x00000000},
|
||||
{0x0000b0bc, 0x00000000},
|
||||
{0x0000b0c0, 0x003f0020},
|
||||
{0x0000b0c4, 0x00400041},
|
||||
{0x0000b0c8, 0x0140005f},
|
||||
{0x0000b0cc, 0x0160015f},
|
||||
{0x0000b0d0, 0x017e017f},
|
||||
{0x0000b0d4, 0x02410242},
|
||||
{0x0000b0d8, 0x025f0240},
|
||||
{0x0000b0dc, 0x027f0260},
|
||||
{0x0000b0e0, 0x0341027e},
|
||||
{0x0000b0e4, 0x035f0340},
|
||||
{0x0000b0e8, 0x037f0360},
|
||||
{0x0000b0ec, 0x04400441},
|
||||
{0x0000b0f0, 0x0460045f},
|
||||
{0x0000b0f4, 0x0541047f},
|
||||
{0x0000b0f8, 0x055f0540},
|
||||
{0x0000b0fc, 0x057f0560},
|
||||
{0x0000b100, 0x06400641},
|
||||
{0x0000b104, 0x0660065f},
|
||||
{0x0000b108, 0x067e067f},
|
||||
{0x0000b10c, 0x07410742},
|
||||
{0x0000b110, 0x075f0740},
|
||||
{0x0000b114, 0x077f0760},
|
||||
{0x0000b118, 0x07800781},
|
||||
{0x0000b11c, 0x07a0079f},
|
||||
{0x0000b120, 0x07c107bf},
|
||||
{0x0000b124, 0x000007c0},
|
||||
{0x0000b128, 0x00000000},
|
||||
{0x0000b12c, 0x00000000},
|
||||
{0x0000b130, 0x00000000},
|
||||
{0x0000b134, 0x00000000},
|
||||
{0x0000b138, 0x00000000},
|
||||
{0x0000b13c, 0x00000000},
|
||||
{0x0000b140, 0x003f0020},
|
||||
{0x0000b144, 0x00400041},
|
||||
{0x0000b148, 0x0140005f},
|
||||
{0x0000b14c, 0x0160015f},
|
||||
{0x0000b150, 0x017e017f},
|
||||
{0x0000b154, 0x02410242},
|
||||
{0x0000b158, 0x025f0240},
|
||||
{0x0000b15c, 0x027f0260},
|
||||
{0x0000b160, 0x0341027e},
|
||||
{0x0000b164, 0x035f0340},
|
||||
{0x0000b168, 0x037f0360},
|
||||
{0x0000b16c, 0x04400441},
|
||||
{0x0000b170, 0x0460045f},
|
||||
{0x0000b174, 0x0541047f},
|
||||
{0x0000b178, 0x055f0540},
|
||||
{0x0000b17c, 0x057f0560},
|
||||
{0x0000b180, 0x06400641},
|
||||
{0x0000b184, 0x0660065f},
|
||||
{0x0000b188, 0x067e067f},
|
||||
{0x0000b18c, 0x07410742},
|
||||
{0x0000b190, 0x075f0740},
|
||||
{0x0000b194, 0x077f0760},
|
||||
{0x0000b198, 0x07800781},
|
||||
{0x0000b19c, 0x07a0079f},
|
||||
{0x0000b1a0, 0x07c107bf},
|
||||
{0x0000b1a4, 0x000007c0},
|
||||
{0x0000b1a8, 0x00000000},
|
||||
{0x0000b1ac, 0x00000000},
|
||||
{0x0000b1b0, 0x00000000},
|
||||
{0x0000b1b4, 0x00000000},
|
||||
{0x0000b1b8, 0x00000000},
|
||||
{0x0000b1bc, 0x00000000},
|
||||
{0x0000b1c0, 0x00000000},
|
||||
{0x0000b1c4, 0x00000000},
|
||||
{0x0000b1c8, 0x00000000},
|
||||
{0x0000b1cc, 0x00000000},
|
||||
{0x0000b1d0, 0x00000000},
|
||||
{0x0000b1d4, 0x00000000},
|
||||
{0x0000b1d8, 0x00000000},
|
||||
{0x0000b1dc, 0x00000000},
|
||||
{0x0000b1e0, 0x00000000},
|
||||
{0x0000b1e4, 0x00000000},
|
||||
{0x0000b1e8, 0x00000000},
|
||||
{0x0000b1ec, 0x00000000},
|
||||
{0x0000b1f0, 0x00000396},
|
||||
{0x0000b1f4, 0x00000396},
|
||||
{0x0000b1f8, 0x00000396},
|
||||
{0x0000b1fc, 0x00000196},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_baseband_core_mix_rxgain[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00009fd0, 0x0a2d6b93},
|
||||
};
|
||||
|
||||
static const u32 ar9462_2p0_baseband_postamble_mix_rxgain[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae},
|
||||
{0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da},
|
||||
{0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8},
|
||||
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e},
|
||||
};
|
||||
|
||||
#endif /* INITVALS_9462_2P0_H */
|
||||
|
|
|
|||
1774
tools/initvals/ar9462_2p1_initvals.h
Normal file
1774
tools/initvals/ar9462_2p1_initvals.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
|
|||
{0x00009d10, 0x01834061},
|
||||
{0x00009d14, 0x00c00400},
|
||||
{0x00009d18, 0x00000000},
|
||||
{0x00009e08, 0x0078230c},
|
||||
{0x00009e24, 0x990bb515},
|
||||
{0x00009e28, 0x126f0000},
|
||||
{0x00009e08, 0x0038230c},
|
||||
{0x00009e24, 0x9907b515},
|
||||
{0x00009e28, 0x126f0600},
|
||||
{0x00009e30, 0x06336f77},
|
||||
{0x00009e34, 0x6af6532f},
|
||||
{0x00009e38, 0x0cc80c00},
|
||||
|
|
@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
|
|||
|
||||
static const u32 ar9565_1p0_baseband_postamble[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d},
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009},
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
|
||||
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
|
||||
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81},
|
||||
|
|
@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
|
|||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
|
||||
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
|
||||
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
|
||||
{0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
|
||||
{0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
|
|
@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = {
|
|||
|
||||
static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004050, 0x00300300},
|
||||
{0x0000406c, 0x00100000},
|
||||
{0x0000a000, 0x00010000},
|
||||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
|
|
@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
|||
{0x0000a0b4, 0x00000000},
|
||||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x01000101},
|
||||
{0x0000a0c8, 0x011e011f},
|
||||
{0x0000a0cc, 0x011c011d},
|
||||
{0x0000a0d0, 0x02030204},
|
||||
{0x0000a0d4, 0x02010202},
|
||||
{0x0000a0d8, 0x021f0200},
|
||||
{0x0000a0dc, 0x0302021e},
|
||||
{0x0000a0e0, 0x03000301},
|
||||
{0x0000a0e4, 0x031e031f},
|
||||
{0x0000a0e8, 0x0402031d},
|
||||
{0x0000a0ec, 0x04000401},
|
||||
{0x0000a0f0, 0x041e041f},
|
||||
{0x0000a0f4, 0x0502041d},
|
||||
{0x0000a0f8, 0x05000501},
|
||||
{0x0000a0fc, 0x051e051f},
|
||||
{0x0000a100, 0x06010602},
|
||||
{0x0000a104, 0x061f0600},
|
||||
{0x0000a108, 0x061d061e},
|
||||
{0x0000a10c, 0x07020703},
|
||||
{0x0000a110, 0x07000701},
|
||||
{0x0000a0c0, 0x00bf00a0},
|
||||
{0x0000a0c4, 0x11a011a1},
|
||||
{0x0000a0c8, 0x11be11bf},
|
||||
{0x0000a0cc, 0x11bc11bd},
|
||||
{0x0000a0d0, 0x22632264},
|
||||
{0x0000a0d4, 0x22612262},
|
||||
{0x0000a0d8, 0x227f2260},
|
||||
{0x0000a0dc, 0x4322227e},
|
||||
{0x0000a0e0, 0x43204321},
|
||||
{0x0000a0e4, 0x433e433f},
|
||||
{0x0000a0e8, 0x4462433d},
|
||||
{0x0000a0ec, 0x44604461},
|
||||
{0x0000a0f0, 0x447e447f},
|
||||
{0x0000a0f4, 0x5582447d},
|
||||
{0x0000a0f8, 0x55805581},
|
||||
{0x0000a0fc, 0x559e559f},
|
||||
{0x0000a100, 0x66816682},
|
||||
{0x0000a104, 0x669f6680},
|
||||
{0x0000a108, 0x669d669e},
|
||||
{0x0000a10c, 0x77627763},
|
||||
{0x0000a110, 0x77607761},
|
||||
{0x0000a114, 0x00000000},
|
||||
{0x0000a118, 0x00000000},
|
||||
{0x0000a11c, 0x00000000},
|
||||
|
|
@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
|
|||
{0x0000a134, 0x00000000},
|
||||
{0x0000a138, 0x00000000},
|
||||
{0x0000a13c, 0x00000000},
|
||||
{0x0000a140, 0x001f0000},
|
||||
{0x0000a144, 0x01000101},
|
||||
{0x0000a148, 0x011e011f},
|
||||
{0x0000a14c, 0x011c011d},
|
||||
{0x0000a150, 0x02030204},
|
||||
{0x0000a154, 0x02010202},
|
||||
{0x0000a158, 0x021f0200},
|
||||
{0x0000a15c, 0x0302021e},
|
||||
{0x0000a160, 0x03000301},
|
||||
{0x0000a164, 0x031e031f},
|
||||
{0x0000a168, 0x0402031d},
|
||||
{0x0000a16c, 0x04000401},
|
||||
{0x0000a170, 0x041e041f},
|
||||
{0x0000a174, 0x0502041d},
|
||||
{0x0000a178, 0x05000501},
|
||||
{0x0000a17c, 0x051e051f},
|
||||
{0x0000a180, 0x06010602},
|
||||
{0x0000a184, 0x061f0600},
|
||||
{0x0000a188, 0x061d061e},
|
||||
{0x0000a18c, 0x07020703},
|
||||
{0x0000a190, 0x07000701},
|
||||
{0x0000a140, 0x00bf00a0},
|
||||
{0x0000a144, 0x11a011a1},
|
||||
{0x0000a148, 0x11be11bf},
|
||||
{0x0000a14c, 0x11bc11bd},
|
||||
{0x0000a150, 0x22632264},
|
||||
{0x0000a154, 0x22612262},
|
||||
{0x0000a158, 0x227f2260},
|
||||
{0x0000a15c, 0x4322227e},
|
||||
{0x0000a160, 0x43204321},
|
||||
{0x0000a164, 0x433e433f},
|
||||
{0x0000a168, 0x4462433d},
|
||||
{0x0000a16c, 0x44604461},
|
||||
{0x0000a170, 0x447e447f},
|
||||
{0x0000a174, 0x5582447d},
|
||||
{0x0000a178, 0x55805581},
|
||||
{0x0000a17c, 0x559e559f},
|
||||
{0x0000a180, 0x66816682},
|
||||
{0x0000a184, 0x669f6680},
|
||||
{0x0000a188, 0x669d669e},
|
||||
{0x0000a18c, 0x77e677e7},
|
||||
{0x0000a190, 0x77e477e5},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
|
@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
|
|||
|
||||
static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18213ede},
|
||||
{0x00018c00, 0x18212ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{0x00018c08, 0x0003780c},
|
||||
};
|
||||
|
|
@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = {
|
|||
{0x0000a180, 0x66816682},
|
||||
{0x0000a184, 0x669f6680},
|
||||
{0x0000a188, 0x669d669e},
|
||||
{0x0000a18c, 0x77627763},
|
||||
{0x0000a190, 0x77607761},
|
||||
{0x0000a18c, 0x77e677e7},
|
||||
{0x0000a190, 0x77e477e5},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
|
@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
|
|||
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
|
||||
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
|
||||
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
|
||||
|
|
@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
|
|||
{0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5},
|
||||
{0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9},
|
||||
{0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb},
|
||||
{0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0},
|
||||
{0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1},
|
||||
{0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2},
|
||||
{0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3},
|
||||
{0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4},
|
||||
{0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
|
||||
{0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
|
@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
|
|||
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
|
||||
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
|
||||
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
|
||||
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
|
||||
|
|
@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
|
|||
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
|
||||
{0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0},
|
||||
{0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1},
|
||||
{0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2},
|
||||
{0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3},
|
||||
{0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4},
|
||||
{0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
|
||||
{0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
|
|
|
|||
|
|
@ -138,24 +138,50 @@ ca6088034f339ea8f106f7f034d34baafec0c0ca ar9340Modes_high_ob_db_tx_gain_t
|
|||
481b3066bd6b4dfa425027157f7c6252b535ebe4 ar9340Common_wo_xlna_rx_gain_table_1p0
|
||||
1b9f617ab8c10ec0760e81fe61d469692f2acc29 ar9340_1p0_soc_preamble
|
||||
d9efd1c575ac43d60c310d717c59617a5323c111 ar9462_modes_fast_clock_2p0
|
||||
8bf1688079add33889085f3d35a5fab61c33487f ar9462_pciephy_clkreq_enable_L1_2p0
|
||||
8dacf543535b605143b40aef74f7d46af064cb43 ar9462_2p0_baseband_postamble
|
||||
222ed8213d3ffb0d12cf4c7019bdfd874e45c7d7 ar9462_pciephy_clkreq_enable_L1_2p0
|
||||
d7a2102c22264c288fa3d9de27e5ae84b8f3812e ar9462_2p0_baseband_postamble
|
||||
d0f7aff1a1ab7e6f6bbda0da067714459341ce5f ar9462_common_rx_gain_table_2p0
|
||||
bc232a96b4c1530bebe654420652a9f080a09db8 ar9462_pciephy_clkreq_disable_L1_2p0
|
||||
f4c2241d40995e09f8736ed2ef5eaa5d6f051aa5 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
|
||||
2fbe90336971cd66f0264c0cc57605c2de069d5f ar9462_pciephy_clkreq_disable_L1_2p0
|
||||
a3173672141a2ac797e660228d41a609f9ab2c4c ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
|
||||
057d1ee3d10321f1cc4d6c19cf1927e2ae56af28 ar9462_2p0_radio_postamble_sys2ant
|
||||
481b3066bd6b4dfa425027157f7c6252b535ebe4 ar9462_common_wo_xlna_rx_gain_table_2p0
|
||||
dfaefa89122b4b769bfcf93b4bd9569f2b0ee961 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
|
||||
a36b90fcdeeb4071fd090537f008f8091d885581 ar9462_modes_low_ob_db_tx_gain_table_2p0
|
||||
7c0a54aaf0f77f5bf048126e43feea746732d43f ar9462_2p0_soc_postamble
|
||||
e87864956a7209224880cff035b4441b0ab3fbcc ar9462_2p0_baseband_core
|
||||
53d41e2eb8eadab02e1b615f4f596a55cf2a8905 ar9462_2p0_baseband_core
|
||||
b50d2fe654b069110bdbe06e5065f2aa9b117e3e ar9462_2p0_radio_postamble
|
||||
5a98e71e601539bf31af7b9d18b210ab70f99dae ar9462_modes_high_ob_db_tx_gain_table_2p0
|
||||
f7a7bdff0af20658239e4b491f470a8c9517c0ae ar9462_modes_mix_ob_db_tx_gain_table_2p0
|
||||
068b0f30229b9cbf385a49303d29b8fb979f25b3 ar9462_modes_high_ob_db_tx_gain_table_2p0
|
||||
fd98d0361e085b102131c2dc07c601e0a7ccdd13 ar9462_2p0_radio_core
|
||||
3e60b14761abfa24d758727954d1d5cc398abf7f ar9462_2p0_soc_preamble
|
||||
fc8623151293cc7739d0fb8e2873256749c74930 ar9462_2p0_mac_core
|
||||
2e6ddfe3c7e291ca6bebb5791d8a73c492db0399 ar9462_2p0_mac_core
|
||||
c8dc777b012068116cd5282aade8eb460f397d20 ar9462_2p0_mac_postamble
|
||||
72675fd0f308e6f31502e283119e12469d262f40 ar9462_common_mixed_rx_gain_table_2p0
|
||||
185f0537e40b74dcc4db33c7e111c1bfe79f3104 ar9462_2p0_baseband_postamble_5g_xlna
|
||||
72675fd0f308e6f31502e283119e12469d262f40 ar9462_2p0_5g_xlna_only_rxgain
|
||||
8f24703571c460bced3d0fea95b5cfeac34a724d ar9462_2p0_baseband_core_mix_rxgain
|
||||
cb83a8c304aae0b6fc937e61d145253a8f470d24 ar9462_2p0_baseband_postamble_mix_rxgain
|
||||
e6f8d81842a61171ac17eff584e93b4e95b5dbbf ar9462_2p1_mac_core
|
||||
c8dc777b012068116cd5282aade8eb460f397d20 ar9462_2p1_mac_postamble
|
||||
53d41e2eb8eadab02e1b615f4f596a55cf2a8905 ar9462_2p1_baseband_core
|
||||
d7a2102c22264c288fa3d9de27e5ae84b8f3812e ar9462_2p1_baseband_postamble
|
||||
fd98d0361e085b102131c2dc07c601e0a7ccdd13 ar9462_2p1_radio_core
|
||||
b50d2fe654b069110bdbe06e5065f2aa9b117e3e ar9462_2p1_radio_postamble
|
||||
3e60b14761abfa24d758727954d1d5cc398abf7f ar9462_2p1_soc_preamble
|
||||
7c0a54aaf0f77f5bf048126e43feea746732d43f ar9462_2p1_soc_postamble
|
||||
057d1ee3d10321f1cc4d6c19cf1927e2ae56af28 ar9462_2p1_radio_postamble_sys2ant
|
||||
d0f7aff1a1ab7e6f6bbda0da067714459341ce5f ar9462_2p1_common_rx_gain
|
||||
72675fd0f308e6f31502e283119e12469d262f40 ar9462_2p1_common_mixed_rx_gain
|
||||
8f24703571c460bced3d0fea95b5cfeac34a724d ar9462_2p1_baseband_core_mix_rxgain
|
||||
cb83a8c304aae0b6fc937e61d145253a8f470d24 ar9462_2p1_baseband_postamble_mix_rxgain
|
||||
185f0537e40b74dcc4db33c7e111c1bfe79f3104 ar9462_2p1_baseband_postamble_5g_xlna
|
||||
481b3066bd6b4dfa425027157f7c6252b535ebe4 ar9462_2p1_common_wo_xlna_rx_gain
|
||||
72675fd0f308e6f31502e283119e12469d262f40 ar9462_2p1_common_5g_xlna_only_rx_gain
|
||||
a36b90fcdeeb4071fd090537f008f8091d885581 ar9462_2p1_modes_low_ob_db_tx_gain
|
||||
068b0f30229b9cbf385a49303d29b8fb979f25b3 ar9462_2p1_modes_high_ob_db_tx_gain
|
||||
f7a7bdff0af20658239e4b491f470a8c9517c0ae ar9462_2p1_modes_mix_ob_db_tx_gain
|
||||
d9efd1c575ac43d60c310d717c59617a5323c111 ar9462_2p1_modes_fast_clock
|
||||
dfaefa89122b4b769bfcf93b4bd9569f2b0ee961 ar9462_2p1_baseband_core_txfir_coeff_japan_2484
|
||||
c8dc777b012068116cd5282aade8eb460f397d20 ar9485_1_1_mac_postamble
|
||||
5d20e4848b97566ad55e0e95458463d622ee5480 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1
|
||||
d9a90632a00a7b417154173b947dfffdeab23e51 ar9485Common_wo_xlna_rx_gain_1_1
|
||||
|
|
@ -194,20 +220,20 @@ b836a622916e66da6a23c9cd34a7d933571ff6db ar955x_1p0_modes_no_xpa_tx_gain_
|
|||
d9efd1c575ac43d60c310d717c59617a5323c111 ar955x_1p0_modes_fast_clock
|
||||
839b2486a70775db100fca6421860d4922fbf945 ar9565_1p0_mac_core
|
||||
c8dc777b012068116cd5282aade8eb460f397d20 ar9565_1p0_mac_postamble
|
||||
be2a958615907b5f7766336b124d79cb3dbb3c1f ar9565_1p0_baseband_core
|
||||
7ae44b5234dc536c5fe3bd484ecbf4bd4f8f8ee1 ar9565_1p0_baseband_postamble
|
||||
26297fd915614c1f9ad22fb611335a2ac715a2d9 ar9565_1p0_baseband_core
|
||||
e719a3c597fa3511cfb436aeb4cfdda3b5949685 ar9565_1p0_baseband_postamble
|
||||
98708e6c8cde013777cd5c5c9ded6dfe038b652f ar9565_1p0_radio_core
|
||||
bc722e44e8c7039983b485fc099275c6629974cf ar9565_1p0_radio_postamble
|
||||
524fae156c2942a28c62603dac8f9ee99ff0e25a ar9565_1p0_soc_preamble
|
||||
b045882e6e5b3f54d9eed19022abe6a44bc04e73 ar9565_1p0_soc_postamble
|
||||
bc0a956de3b035894bf68722ca4c8a4365fe0f4b ar9565_1p0_Common_rx_gain_table
|
||||
6af86113836112173aab7266f22acee984d956a9 ar9565_1p0_Common_rx_gain_table
|
||||
4bf703cdebf0bfb9ad867cb53b79d6c3957b6f91 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table
|
||||
2fbe90336971cd66f0264c0cc57605c2de069d5f ar9565_1p0_pciephy_clkreq_disable_L1
|
||||
a3173672141a2ac797e660228d41a609f9ab2c4c ar9565_1p0_pciephy_clkreq_disable_L1
|
||||
6db24dff7f419466d4734d59063314b9e52d4640 ar9565_1p0_modes_fast_clock
|
||||
d297fe8586260e902a2b629323e4802fe207f2b7 ar9565_1p0_common_wo_xlna_rx_gain_table
|
||||
9cbace0a26242ed035a0c2fbae7cec34267c7258 ar9565_1p0_common_wo_xlna_rx_gain_table
|
||||
4bf703cdebf0bfb9ad867cb53b79d6c3957b6f91 ar9565_1p0_modes_low_ob_db_tx_gain_table
|
||||
7e7f55da5f2572348ddf79e41e9ab9647d94caff ar9565_1p0_modes_high_ob_db_tx_gain_table
|
||||
a67925a1d3f3263537a4a0d6096f3f8994190f14 ar9565_1p0_modes_high_power_tx_gain_table
|
||||
e1be4dc91b540109b236b6b4002a9108ad3a01de ar9565_1p0_modes_high_ob_db_tx_gain_table
|
||||
19ed468cdcc0c0be512a64d55f40c609e6d75720 ar9565_1p0_modes_high_power_tx_gain_table
|
||||
87e0ecae5df96673e22bc448b17d813510964de8 ar9580_1p0_modes_fast_clock
|
||||
6b0fb5b3698c99f42a885c8e982ae436363f1865 ar9580_1p0_radio_postamble
|
||||
5b81bf27a30c826cfde3e8f6746473e949cb41ef ar9580_1p0_baseband_core
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ struct initval_family {
|
|||
#include <ar955x_1p0_initvals.h>
|
||||
#include <ar9580_1p0_initvals.h>
|
||||
#include <ar9462_2p0_initvals.h>
|
||||
#include <ar9462_2p1_initvals.h>
|
||||
#include <ar9565_1p0_initvals.h>
|
||||
|
||||
#else
|
||||
|
|
@ -112,9 +113,6 @@ struct initval_family {
|
|||
|
||||
#include "ar5416_sowl.ini"
|
||||
|
||||
|
||||
#include "ar9280.ini"
|
||||
|
||||
#define ar9280Modes_merlin2 ar9280Modes_9280_2
|
||||
#define ar9280Common_merlin2 ar9280Common_9280_2
|
||||
#define ar9280Modes_fast_clock_merlin2 ar9280Modes_fast_clock_9280_2
|
||||
|
|
@ -148,10 +146,6 @@ struct initval_family {
|
|||
|
||||
#include "ar9285_v1_2.ini"
|
||||
|
||||
#define ar9287PciePhy_AWOW_kiwi1_0 ar9287PciePhy_AWOW_9287_1_0
|
||||
|
||||
#include "ar9287.ini"
|
||||
|
||||
#define ar9287Modes_kiwi1_1 ar9287Modes_9287_1_1
|
||||
#define ar9287Common_kiwi1_1 ar9287Common_9287_1_1
|
||||
#define ar9287Common_normal_cck_fir_coeff_kiwi1_1 ar9287Common_normal_cck_fir_coeff_9287_1_1
|
||||
|
|
@ -318,15 +312,44 @@ struct initval_family {
|
|||
#define ar9300_jupiter_2p0_soc_postamble ar9462_2p0_soc_postamble
|
||||
#define ar9300_jupiter_2p0_baseband_core ar9462_2p0_baseband_core
|
||||
#define ar9300_jupiter_2p0_radio_postamble ar9462_2p0_radio_postamble
|
||||
#define ar9300Modes_mix_ob_db_tx_gain_table_jupiter_2p0 ar9462_modes_mix_ob_db_tx_gain_table_2p0
|
||||
#define ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p0 ar9462_modes_high_ob_db_tx_gain_table_2p0
|
||||
#define ar9300_jupiter_2p0_radio_core ar9462_2p0_radio_core
|
||||
#define ar9300_jupiter_2p0_soc_preamble ar9462_2p0_soc_preamble
|
||||
#define ar9300_jupiter_2p0_mac_core ar9462_2p0_mac_core
|
||||
#define ar9300_jupiter_2p0_mac_postamble ar9462_2p0_mac_postamble
|
||||
#define ar9300Common_mixed_rx_gain_table_jupiter_2p0 ar9462_common_mixed_rx_gain_table_2p0
|
||||
#define ar9300_jupiter_2p0_baseband_postamble_5g_xlna ar9462_2p0_baseband_postamble_5g_xlna
|
||||
#define ar9300Common_5g_xlna_only_rx_gain_table_jupiter_2p0 ar9462_2p0_5g_xlna_only_rxgain
|
||||
#define ar9300_jupiter_2p0_baseband_core_mix_rxgain ar9462_2p0_baseband_core_mix_rxgain
|
||||
#define ar9300_jupiter_2p0_baseband_postamble_mix_rxgain ar9462_2p0_baseband_postamble_mix_rxgain
|
||||
|
||||
#include "ar9300_jupiter20.ini"
|
||||
|
||||
#define ar9300_jupiter_2p1_mac_core ar9462_2p1_mac_core
|
||||
#define ar9300_jupiter_2p1_mac_postamble ar9462_2p1_mac_postamble
|
||||
#define ar9300_jupiter_2p1_baseband_core ar9462_2p1_baseband_core
|
||||
#define ar9300_jupiter_2p1_baseband_postamble ar9462_2p1_baseband_postamble
|
||||
#define ar9300_jupiter_2p1_radio_core ar9462_2p1_radio_core
|
||||
#define ar9300_jupiter_2p1_radio_postamble ar9462_2p1_radio_postamble
|
||||
#define ar9300_jupiter_2p1_soc_preamble ar9462_2p1_soc_preamble
|
||||
#define ar9300_jupiter_2p1_soc_postamble ar9462_2p1_soc_postamble
|
||||
#define ar9300_jupiter_2p1_radio_postamble_sys2ant ar9462_2p1_radio_postamble_sys2ant
|
||||
#define ar9300Common_rx_gain_table_jupiter_2p1 ar9462_2p1_common_rx_gain
|
||||
#define ar9300Common_mixed_rx_gain_table_jupiter_2p1 ar9462_2p1_common_mixed_rx_gain
|
||||
#define ar9300_jupiter_2p1_baseband_core_mix_rxgain ar9462_2p1_baseband_core_mix_rxgain
|
||||
#define ar9300_jupiter_2p1_baseband_postamble_mix_rxgain ar9462_2p1_baseband_postamble_mix_rxgain
|
||||
#define ar9300_jupiter_2p1_baseband_postamble_5g_xlna ar9462_2p1_baseband_postamble_5g_xlna
|
||||
#define ar9300Common_wo_xlna_rx_gain_table_jupiter_2p1 ar9462_2p1_common_wo_xlna_rx_gain
|
||||
#define ar9300Common_5g_xlna_only_rx_gain_table_jupiter_2p1 ar9462_2p1_common_5g_xlna_only_rx_gain
|
||||
#define ar9300Modes_low_ob_db_tx_gain_table_jupiter_2p1 ar9462_2p1_modes_low_ob_db_tx_gain
|
||||
#define ar9300Modes_high_ob_db_tx_gain_table_jupiter_2p1 ar9462_2p1_modes_high_ob_db_tx_gain
|
||||
#define ar9300Modes_mix_ob_db_tx_gain_table_jupiter_2p1 ar9462_2p1_modes_mix_ob_db_tx_gain
|
||||
#define ar9300Modes_fast_clock_jupiter_2p1 ar9462_2p1_modes_fast_clock
|
||||
#define ar9300_jupiter_2p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p1_baseband_core_txfir_coeff_japan_2484
|
||||
|
||||
#include "ar9300_jupiter21.ini"
|
||||
|
||||
#define ar9340_wasp_1p0_radio_postamble ar9340_1p0_radio_postamble
|
||||
#define ar9340Modes_lowest_ob_db_tx_gain_table_wasp_1p0 ar9340Modes_lowest_ob_db_tx_gain_table_1p0
|
||||
#define ar9340Modes_fast_clock_wasp_1p0 ar9340Modes_fast_clock_1p0
|
||||
|
|
@ -903,12 +926,42 @@ static void ar9462_2p0_hw_print_initvals(bool check)
|
|||
INI_PRINT(ar9462_2p0_soc_postamble);
|
||||
INI_PRINT(ar9462_2p0_baseband_core);
|
||||
INI_PRINT(ar9462_2p0_radio_postamble);
|
||||
INI_PRINT(ar9462_modes_mix_ob_db_tx_gain_table_2p0);
|
||||
INI_PRINT(ar9462_modes_high_ob_db_tx_gain_table_2p0);
|
||||
INI_PRINT(ar9462_2p0_radio_core);
|
||||
INI_PRINT(ar9462_2p0_soc_preamble);
|
||||
INI_PRINT(ar9462_2p0_mac_core);
|
||||
INI_PRINT(ar9462_2p0_mac_postamble);
|
||||
INI_PRINT(ar9462_common_mixed_rx_gain_table_2p0);
|
||||
INI_PRINT(ar9462_2p0_baseband_postamble_5g_xlna);
|
||||
INI_PRINT(ar9462_2p0_5g_xlna_only_rxgain);
|
||||
INI_PRINT(ar9462_2p0_baseband_core_mix_rxgain);
|
||||
INI_PRINT(ar9462_2p0_baseband_postamble_mix_rxgain);
|
||||
}
|
||||
|
||||
static void ar9462_2p1_hw_print_initvals(bool check)
|
||||
{
|
||||
INI_PRINT(ar9462_2p1_mac_core);
|
||||
INI_PRINT(ar9462_2p1_mac_postamble);
|
||||
INI_PRINT(ar9462_2p1_baseband_core);
|
||||
INI_PRINT(ar9462_2p1_baseband_postamble);
|
||||
INI_PRINT(ar9462_2p1_radio_core);
|
||||
INI_PRINT(ar9462_2p1_radio_postamble);
|
||||
INI_PRINT(ar9462_2p1_soc_preamble);
|
||||
INI_PRINT(ar9462_2p1_soc_postamble);
|
||||
INI_PRINT(ar9462_2p1_radio_postamble_sys2ant);
|
||||
INI_PRINT(ar9462_2p1_common_rx_gain);
|
||||
INI_PRINT(ar9462_2p1_common_mixed_rx_gain);
|
||||
INI_PRINT(ar9462_2p1_baseband_core_mix_rxgain);
|
||||
INI_PRINT(ar9462_2p1_baseband_postamble_mix_rxgain);
|
||||
INI_PRINT(ar9462_2p1_baseband_postamble_5g_xlna);
|
||||
INI_PRINT(ar9462_2p1_common_wo_xlna_rx_gain);
|
||||
INI_PRINT(ar9462_2p1_common_5g_xlna_only_rx_gain);
|
||||
INI_PRINT(ar9462_2p1_modes_low_ob_db_tx_gain);
|
||||
INI_PRINT(ar9462_2p1_modes_high_ob_db_tx_gain);
|
||||
INI_PRINT(ar9462_2p1_modes_mix_ob_db_tx_gain);
|
||||
INI_PRINT(ar9462_2p1_modes_fast_clock);
|
||||
INI_PRINT(ar9462_2p1_baseband_core_txfir_coeff_japan_2484);
|
||||
}
|
||||
|
||||
static void ar9565_1p0_hw_print_initvals(bool check)
|
||||
|
|
@ -947,6 +1000,7 @@ struct initval_family families[] = {
|
|||
FAM("ar9330-1p2", "9330_1P2", NULL , ar9330_1p2_hw_print_initvals),
|
||||
FAM("ar9340" , "9340" , NULL , ar9340_hw_print_initvals),
|
||||
FAM("ar9462-2p0", "9462_2P0", "AR9462 2.0", ar9462_2p0_hw_print_initvals),
|
||||
FAM("ar9462-2p1", "9462_2P1", "AR9462 2.1", ar9462_2p1_hw_print_initvals),
|
||||
FAM("ar9485" , "9485" , "AR9485 1.1", ar9485_hw_print_initvals),
|
||||
FAM("ar955x-1p0", "955X_1P0", "AR955X 1.0", ar955x_1p0_hw_print_initvals),
|
||||
FAM("ar9565-1p0", "9565_1P0", "AR9565 1.0", ar9565_1p0_hw_print_initvals),
|
||||
|
|
|
|||
734
tools/scripts/ath10k/ath10k-bdencoder
Executable file
734
tools/scripts/ath10k/ath10k-bdencoder
Executable file
|
|
@ -0,0 +1,734 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2015 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
import struct
|
||||
import ctypes
|
||||
import os.path
|
||||
import argparse
|
||||
import json
|
||||
import binascii
|
||||
import hashlib
|
||||
import tempfile
|
||||
import subprocess
|
||||
import logging
|
||||
import sys
|
||||
import shutil
|
||||
import mailbox
|
||||
|
||||
MAX_BUF_LEN = 2000000
|
||||
|
||||
# the signature length also includes null byte and padding
|
||||
ATH10K_BOARD_SIGNATURE = b"QCA-ATH10K-BOARD"
|
||||
ATH10K_BOARD_SIGNATURE_LEN = 20
|
||||
|
||||
PADDING_MAGIC = 0x6d
|
||||
DEFAULT_BD_API = 2
|
||||
DEFAULT_BOARD_FILE = 'board-%d.bin' % DEFAULT_BD_API
|
||||
DEFAULT_JSON_FILE = 'board-%d.json' % DEFAULT_BD_API
|
||||
TYPE_LENGTH_SIZE = 8
|
||||
BIN_SUFFIX = '.bin'
|
||||
|
||||
ATH10K_FIRMWARE_URL = 'https://git.codelinaro.org/clo/ath-firmware/ath10k-firmware/-/commit'
|
||||
|
||||
ATH10K_BD_IE_BOARD = 0
|
||||
ATH10K_BD_IE_BOARD_EXT = 1
|
||||
|
||||
ATH10K_BD_IE_BOARD_NAME = 0
|
||||
ATH10K_BD_IE_BOARD_DATA = 1
|
||||
|
||||
ATH10K_BD_IE_BOARD_EXT_NAME = 0
|
||||
ATH10K_BD_IE_BOARD_EXT_DATA = 1
|
||||
|
||||
|
||||
def padding_needed(len):
|
||||
if len % 4 != 0:
|
||||
return 4 - len % 4
|
||||
return 0
|
||||
|
||||
|
||||
def add_ie(buf, offset, id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<2i%ds%ds' % (len(value), padding_len)
|
||||
if not isinstance(value, bytes):
|
||||
value = value.encode()
|
||||
struct.pack_into(fmt, buf, offset, id, len(value), value, padding.raw)
|
||||
offset = offset + TYPE_LENGTH_SIZE + len(value) + padding_len
|
||||
|
||||
return offset
|
||||
|
||||
|
||||
def xclip(msg):
|
||||
p = subprocess.Popen(['xclip', '-selection', 'clipboard'],
|
||||
stdin=subprocess.PIPE)
|
||||
p.communicate(msg.encode())
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def pretty_array_str(array):
|
||||
return '\',\''.join(array)
|
||||
|
||||
|
||||
class BoardName():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardName()
|
||||
fmt = '<%ds' % length
|
||||
(name, ) = struct.unpack_from(fmt, buf, offset)
|
||||
self.name = name.decode()
|
||||
|
||||
logging.debug('BoardName.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, ebdf, buf, offset):
|
||||
ie_id = ATH10K_BD_IE_BOARD_NAME
|
||||
if ebdf:
|
||||
ie_id = ATH10K_BD_IE_BOARD_EXT_NAME
|
||||
|
||||
return add_ie(buf, offset, ie_id, self.name.encode('utf-8'))
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'BoardName(%s)' % self.name
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
||||
|
||||
class BoardData():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardData()
|
||||
fmt = '<%ds' % length
|
||||
(self.data, ) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
logging.debug('BoardData.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, ebdf, buf, offset):
|
||||
ie_id = ATH10K_BD_IE_BOARD_DATA
|
||||
if ebdf:
|
||||
ie_id = ATH10K_BD_IE_BOARD_EXT_DATA
|
||||
|
||||
return add_ie(buf, offset, ie_id, self.data)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.data is not None:
|
||||
s = '%d B' % (len(self.data))
|
||||
else:
|
||||
s = 'n/a'
|
||||
|
||||
return 'BoardData(%s)' % (s)
|
||||
|
||||
def __init__(self, data=None):
|
||||
self.data = data
|
||||
|
||||
|
||||
class Board():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
logging.debug('Board.parse_ie(): offset %d length %d' % (offset, length))
|
||||
|
||||
self = Board()
|
||||
|
||||
# looping board IEs
|
||||
while length > 0:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
|
||||
logging.debug('Board.parse_ie(): found ie_id %d ie_len %d offset %d length %d' %
|
||||
(ie_id, ie_len, offset, length))
|
||||
|
||||
if TYPE_LENGTH_SIZE + ie_len > length:
|
||||
raise Exception('Error: ie_len too big (%d > %d)' % (ie_len,
|
||||
length))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
length -= TYPE_LENGTH_SIZE
|
||||
|
||||
# FIXME: create separate ExtenderBoard() class so that we
|
||||
# don't need these "or" hacks here. Maybe add a common
|
||||
# abstract class to avoid code duplication?
|
||||
if ie_id == ATH10K_BD_IE_BOARD_NAME or ie_id == ATH10K_BD_IE_BOARD_EXT_NAME:
|
||||
self.names.append(BoardName.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH10K_BD_IE_BOARD_DATA or ie_id == ATH10K_BD_IE_BOARD_EXT_DATA:
|
||||
self.data = BoardData.parse_ie(buf, offset, ie_len)
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
length -= ie_len + padding_needed(ie_len)
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
# store position ie header of this element
|
||||
ie_offset = offset
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
ie_id = ATH10K_BD_IE_BOARD
|
||||
|
||||
if self.ebdf:
|
||||
ie_id = ATH10K_BD_IE_BOARD_EXT
|
||||
|
||||
for name in self.names:
|
||||
offset = name.add_to_buf(self.ebdf, buf, offset)
|
||||
|
||||
offset = self.data.add_to_buf(self.ebdf, buf, offset)
|
||||
|
||||
# write ie header as now we know the full length
|
||||
ie_len = offset - ie_offset - TYPE_LENGTH_SIZE
|
||||
struct.pack_into('<2i', buf, ie_offset, ie_id, ie_len)
|
||||
|
||||
return offset
|
||||
|
||||
def get_names_as_str(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(boardname.name)
|
||||
|
||||
return names
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(str(boardname))
|
||||
|
||||
return 'Board(%s, %s)' % (','.join(names), self.data)
|
||||
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.names = []
|
||||
self.ebdf = False
|
||||
|
||||
|
||||
class BoardContainer:
|
||||
|
||||
def find_board(self, name):
|
||||
for board in self.boards:
|
||||
for boardname in board.names:
|
||||
if name == boardname.name:
|
||||
return board
|
||||
|
||||
def add_board(self, data, names):
|
||||
boardnames = []
|
||||
ebdf = False
|
||||
|
||||
for name in names:
|
||||
b = self.find_board(name)
|
||||
if b:
|
||||
self.boards.remove(b)
|
||||
|
||||
if "bmi-eboard-id" in name:
|
||||
ebdf = True
|
||||
boardnames.append(BoardName(name))
|
||||
|
||||
board = Board()
|
||||
board.ebdf = ebdf
|
||||
board.data = BoardData(data)
|
||||
board.names = boardnames
|
||||
|
||||
self.boards.append(board)
|
||||
|
||||
@staticmethod
|
||||
def open_json(filename):
|
||||
self = BoardContainer()
|
||||
|
||||
if not os.path.exists(filename):
|
||||
print('mapping file %s not found' % (filename))
|
||||
return
|
||||
|
||||
f = open(filename, 'r')
|
||||
mapping = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
for b in mapping:
|
||||
board_filename = b['data']
|
||||
f = open(board_filename, 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
self.add_board(data, b['names'])
|
||||
|
||||
return self
|
||||
|
||||
def validate(self):
|
||||
allnames = []
|
||||
|
||||
for board in self.boards:
|
||||
for name in board.names:
|
||||
if name in allnames:
|
||||
# TODO: Find a better way to report problems,
|
||||
# maybe return a list of strings? Or use an
|
||||
# exception?
|
||||
print('Warning: duplicate board name: %s' % (name.name))
|
||||
return
|
||||
|
||||
allnames.append(name)
|
||||
|
||||
def _add_signature(self, buf, offset):
|
||||
signature = ATH10K_BOARD_SIGNATURE + b'\0'
|
||||
length = len(signature)
|
||||
pad_len = padding_needed(length)
|
||||
length = length + pad_len
|
||||
|
||||
padding = ctypes.create_string_buffer(pad_len)
|
||||
|
||||
for i in range(pad_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<%ds%ds' % (len(signature), pad_len)
|
||||
struct.pack_into(fmt, buf, offset, signature, padding.raw)
|
||||
offset += length
|
||||
|
||||
# make sure ATH10K_BOARD_SIGNATURE_LEN is correct
|
||||
assert ATH10K_BOARD_SIGNATURE_LEN == length
|
||||
|
||||
return offset
|
||||
|
||||
@staticmethod
|
||||
def open(name):
|
||||
self = BoardContainer()
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
buf_len = len(buf)
|
||||
|
||||
logging.debug('BoardContainer.open(): name %s' % (name))
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (len(ATH10K_BOARD_SIGNATURE))
|
||||
(signature, null) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
if signature != ATH10K_BOARD_SIGNATURE or null != 0:
|
||||
print("invalid signature found in %s" % name)
|
||||
return 1
|
||||
|
||||
offset += ATH10K_BOARD_SIGNATURE_LEN
|
||||
|
||||
# looping main IEs
|
||||
while offset < buf_len:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
logging.debug('BoardContainer.open(): found offset %d ie_id %d ie_len %d' %
|
||||
(offset, ie_id, ie_len))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
if offset + ie_len > buf_len:
|
||||
print('Error: Buffer too short (%d + %d > %d)' % (offset,
|
||||
ie_len,
|
||||
buf_len))
|
||||
return 1
|
||||
|
||||
# FIXME: create separate ExtenderBoard() class and
|
||||
# self.extender_boards list
|
||||
if ie_id == ATH10K_BD_IE_BOARD or ie_id == ATH10K_BD_IE_BOARD_EXT:
|
||||
self.boards.append(Board.parse_ie(buf, offset, ie_len))
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
|
||||
self.validate()
|
||||
|
||||
return self
|
||||
|
||||
def write(self, name):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
fd = open(name, 'wb')
|
||||
fd.write(buf.raw[0:buf_len])
|
||||
fd.close()
|
||||
|
||||
self.validate()
|
||||
|
||||
print("board binary file '%s' is created" % name)
|
||||
|
||||
def get_bin(self):
|
||||
buf = ctypes.create_string_buffer(MAX_BUF_LEN)
|
||||
offset = 0
|
||||
|
||||
offset = self._add_signature(buf, offset)
|
||||
|
||||
for board in self.boards:
|
||||
offset = board.add_to_buf(buf, offset)
|
||||
|
||||
# returns buffer and it's length
|
||||
return buf, offset
|
||||
|
||||
def get_summary(self, sort=False):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
s = ''
|
||||
|
||||
s += 'FileSize: %d\n' % (buf_len)
|
||||
s += 'FileCRC32: %08x\n' % (_crc32(buf[0:buf_len]))
|
||||
s += 'FileMD5: %s\n' % (hashlib.md5(buf[0:buf_len]).hexdigest())
|
||||
|
||||
boards = self.boards
|
||||
|
||||
if sort:
|
||||
boards = sorted(boards, key=lambda board: board.get_names_as_str())
|
||||
|
||||
index = 0
|
||||
for board in boards:
|
||||
if not sort:
|
||||
index_s = '[%d]' % (index)
|
||||
else:
|
||||
index_s = ''
|
||||
|
||||
s += 'BoardNames%s: \'%s\'\n' % (index_s, pretty_array_str(board.get_names_as_str()))
|
||||
s += 'BoardLength%s: %d\n' % (index_s, len(board.data.data))
|
||||
s += 'BoardCRC32%s: %08x\n' % (index_s, _crc32(board.data.data))
|
||||
s += 'BoardMD5%s: %s\n' % (index_s, hashlib.md5(board.data.data).hexdigest())
|
||||
index += 1
|
||||
|
||||
return s
|
||||
|
||||
def __init__(self):
|
||||
self.boards = []
|
||||
|
||||
|
||||
def cmd_extract(args):
|
||||
cont = BoardContainer().open(args.extract)
|
||||
|
||||
mapping = []
|
||||
|
||||
for board in cont.boards:
|
||||
filename = board.names[0].name + '.bin'
|
||||
|
||||
b = {}
|
||||
b['names'] = board.get_names_as_str()
|
||||
b['data'] = filename
|
||||
mapping.append(b)
|
||||
|
||||
f = open(filename, 'wb')
|
||||
f.write(board.data.data)
|
||||
f.close()
|
||||
|
||||
print("%s created size: %d" % (filename, len(board.data.data)))
|
||||
|
||||
filename = DEFAULT_JSON_FILE
|
||||
f = open(filename, 'w')
|
||||
f.write(json.dumps(mapping, indent=4))
|
||||
f.close()
|
||||
|
||||
print("%s created" % (filename))
|
||||
|
||||
|
||||
def cmd_info(args):
|
||||
filename = args.info
|
||||
|
||||
cont = BoardContainer().open(filename)
|
||||
|
||||
print(cont.get_summary())
|
||||
|
||||
|
||||
def cmd_diff(args):
|
||||
if args.diff:
|
||||
filename1 = args.diff[0]
|
||||
filename2 = args.diff[1]
|
||||
else:
|
||||
filename1 = args.diffstat[0]
|
||||
filename2 = args.diffstat[1]
|
||||
|
||||
print(diff_boardfiles(filename1, filename2, args.diff))
|
||||
|
||||
|
||||
def diff_boardfiles(filename1, filename2, diff):
|
||||
result = ''
|
||||
|
||||
container1 = BoardContainer().open(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp()
|
||||
os.write(temp1_fd, container1.get_summary(sort=True).encode())
|
||||
|
||||
container2 = BoardContainer().open(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp()
|
||||
os.write(temp2_fd, container2.get_summary(sort=True).encode())
|
||||
|
||||
# this function is used both with --diff and --diffstat
|
||||
if diff:
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
print('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
print('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
result += '%s\n' % (output.decode())
|
||||
|
||||
# create simple statistics about changes in board images
|
||||
|
||||
new_boards = {}
|
||||
deleted_boards = {}
|
||||
changed_boards = {}
|
||||
|
||||
for board in container2.boards:
|
||||
# convert the list to a string
|
||||
s = pretty_array_str(board.get_names_as_str())
|
||||
new_boards[s] = board
|
||||
|
||||
for board in container1.boards:
|
||||
# convert the list to a string
|
||||
names = pretty_array_str(board.get_names_as_str())
|
||||
|
||||
if names not in new_boards:
|
||||
# board image has been deleted
|
||||
deleted_boards[names] = board
|
||||
continue
|
||||
|
||||
board2 = new_boards[names]
|
||||
del new_boards[names]
|
||||
|
||||
if board.data.data == board2.data.data:
|
||||
# board image hasn't changed
|
||||
continue
|
||||
|
||||
# board image has changed
|
||||
changed_boards[names] = board2
|
||||
|
||||
result += 'New:\n%s\n\n' % ('\n'.join(new_boards.keys()))
|
||||
result += 'Changed:\n%s\n\n' % ('\n'.join(changed_boards.keys()))
|
||||
result += 'Deleted:\n%s\n' % ('\n'.join(deleted_boards.keys()))
|
||||
|
||||
result += '%d board image(s) added, %d changed, %d deleted, %d in total' % (len(new_boards),
|
||||
len(changed_boards),
|
||||
len(deleted_boards),
|
||||
len(container2.boards))
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def cmd_create(args):
|
||||
mapping_file = args.create
|
||||
|
||||
if args.output:
|
||||
output = args.output
|
||||
else:
|
||||
output = DEFAULT_BOARD_FILE
|
||||
|
||||
cont = BoardContainer.open_json(mapping_file)
|
||||
cont.write(output)
|
||||
|
||||
|
||||
def cmd_add_board(args):
|
||||
if len(args.add_board) < 3:
|
||||
print('error: --add-board requires 3 or more arguments, only %d given' % (len(args.add_board)))
|
||||
sys.exit(1)
|
||||
|
||||
board_filename = args.add_board[0]
|
||||
new_filename = args.add_board[1]
|
||||
new_names = args.add_board[2:]
|
||||
|
||||
f = open(new_filename, 'rb')
|
||||
new_data = f.read()
|
||||
f.close()
|
||||
|
||||
# copy the original file for diff
|
||||
(temp_fd, temp_pathname) = tempfile.mkstemp()
|
||||
shutil.copyfile(board_filename, temp_pathname)
|
||||
|
||||
container = BoardContainer.open(board_filename)
|
||||
container.add_board(new_data, new_names)
|
||||
container.write(board_filename)
|
||||
|
||||
print(diff_boardfiles(temp_pathname, board_filename, False))
|
||||
|
||||
os.remove(temp_pathname)
|
||||
|
||||
|
||||
def git_get_head_id():
|
||||
return subprocess.check_output(['git', 'log', '--format=format:%H', '-1'], text=True)
|
||||
|
||||
|
||||
def cmd_add_mbox(args):
|
||||
board_filename = args.add_mbox[0]
|
||||
mbox_filename = args.add_mbox[1]
|
||||
|
||||
mbox = mailbox.mbox(mbox_filename)
|
||||
|
||||
for msg in mbox:
|
||||
board_files = {}
|
||||
|
||||
for part in msg.walk():
|
||||
filename = part.get_filename()
|
||||
|
||||
if not filename:
|
||||
# not an attachment
|
||||
continue
|
||||
|
||||
if not filename.endswith(BIN_SUFFIX):
|
||||
continue
|
||||
|
||||
name = filename[:-len(BIN_SUFFIX)]
|
||||
board_files[name] = part.get_payload(decode=True)
|
||||
|
||||
print('Found mail "%s" with %d board files' % (msg['Subject'],
|
||||
len(board_files)))
|
||||
|
||||
# copy the original file for diff
|
||||
(temp_fd, temp_pathname) = tempfile.mkstemp()
|
||||
shutil.copyfile(board_filename, temp_pathname)
|
||||
|
||||
container = BoardContainer.open(board_filename)
|
||||
for name, data in board_files.items():
|
||||
names = [name]
|
||||
container.add_board(data, names)
|
||||
|
||||
container.write(board_filename)
|
||||
|
||||
applied_msg = ''
|
||||
|
||||
if args.commit:
|
||||
cmd = ['git', 'commit', '--quiet', '-m', msg['Subject'], board_filename]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
applied_msg += 'Thanks, added to %s:\n\n' % (board_filename)
|
||||
|
||||
applied_msg += diff_boardfiles(temp_pathname, board_filename, False)
|
||||
applied_msg += '\n\n'
|
||||
|
||||
if args.commit:
|
||||
applied_msg += '%s/%s\n\n' % (ATH10K_FIRMWARE_URL, git_get_head_id())
|
||||
|
||||
os.remove(temp_pathname)
|
||||
|
||||
print('----------------------------------------------')
|
||||
print(applied_msg)
|
||||
print('----------------------------------------------')
|
||||
|
||||
xclip(applied_msg)
|
||||
|
||||
|
||||
def main():
|
||||
description = '''ath10k board-N.bin files manegement tool
|
||||
|
||||
ath10k-bdencoder is for creating (--create), listing (--info) and
|
||||
comparing (--diff, --diffstat) ath10k board-N.bin files. The
|
||||
board-N.bin is a container format which can have unlimited number of
|
||||
actual board images ("board files"), each image containing one or
|
||||
names which ath10k uses to find the correct image.
|
||||
|
||||
For creating board files you need a mapping file in JSON which
|
||||
contains the names and filenames for the actual binary:
|
||||
|
||||
[
|
||||
{"names": ["AAA1", "AAAA2"], "data": "A.bin"},
|
||||
{"names": ["B"], "data": "B.bin"},
|
||||
{"names": ["C"], "data": "C.bin"},
|
||||
]
|
||||
|
||||
In this example the board-N.bin will contain three board files which
|
||||
are read from files named A.bin (using names AAA1 and AAAA2 in the
|
||||
board-N.bin file), B.bin (using name B) and C.bin (using name C). You
|
||||
can use --extract switch to see examples from real board-N.bin files.
|
||||
'''
|
||||
|
||||
parser = argparse.ArgumentParser(description=description,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
cmd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
cmd_group.add_argument("-c", "--create", metavar='JSON_FILE',
|
||||
help='create board-N.bin from a mapping file in JSON format')
|
||||
cmd_group.add_argument("-e", "--extract", metavar='BOARD_FILE',
|
||||
help='extract board-N.bin file to a JSON mapping file and individual board files, compatible with the format used with --create command')
|
||||
cmd_group.add_argument("-i", "--info", metavar='BOARD_FILE',
|
||||
help='show all details about a board-N.bin file')
|
||||
cmd_group.add_argument('-d', '--diff', metavar='BOARD_FILE', nargs=2,
|
||||
help='show differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-D', '--diffstat', metavar='BOARD_FILE', nargs=2,
|
||||
help='show a summary of differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-a', '--add-board', metavar='NAME', nargs='+',
|
||||
help='add a board file to an existing board-N.bin, first argument is the filename of board-N.bin to add to, second is the filename board file (board.bin) to add and then followed by one or more arguments are names used in board-N.bin')
|
||||
|
||||
cmd_group.add_argument('-A', '--add-mbox', metavar='FILENAME', nargs=2,
|
||||
help='FIXME')
|
||||
|
||||
parser.add_argument('-C', '--commit', action='store_true',
|
||||
help='commit changes to a git repository')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='enable verbose (debug) messages')
|
||||
parser.add_argument("-o", "--output", metavar="BOARD_FILE",
|
||||
help='name of the output file, otherwise the default is: %s' %
|
||||
(DEFAULT_BOARD_FILE))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if args.create:
|
||||
return cmd_create(args)
|
||||
elif args.extract:
|
||||
return cmd_extract(args)
|
||||
elif args.info:
|
||||
return cmd_info(args)
|
||||
elif args.diff:
|
||||
return cmd_diff(args)
|
||||
elif args.diffstat:
|
||||
return cmd_diff(args)
|
||||
elif args.add_board:
|
||||
return cmd_add_board(args)
|
||||
elif args.add_mbox:
|
||||
return cmd_add_mbox(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
501
tools/scripts/ath10k/ath10k-check
Executable file
501
tools/scripts/ath10k/ath10k-check
Executable file
|
|
@ -0,0 +1,501 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# Run 'ath10k-check --help' to see the instructions
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
import tempfile
|
||||
import queue
|
||||
import threading
|
||||
import string
|
||||
import hashlib
|
||||
import distutils.spawn
|
||||
|
||||
CHECKPATCH_COMMIT = '99b70ece33d87500ef7bee8e32cb99772c45ce14'
|
||||
|
||||
GIT_URL = 'https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl?id=%s'
|
||||
|
||||
DRIVER_DIR = 'drivers/net/wireless/ath/ath10k/'
|
||||
|
||||
FILTER_REGEXP = r'/ath'
|
||||
|
||||
IGNORE_FILES = ['trace.h']
|
||||
|
||||
CHECKPATCH_IGNORE = ['MSLEEP',
|
||||
'USLEEP_RANGE',
|
||||
'PRINTK_WITHOUT_KERN_LEVEL',
|
||||
|
||||
# ath10k does not follow networking comment style
|
||||
'NETWORKING_BLOCK_COMMENT_STYLE',
|
||||
|
||||
'LINUX_VERSION_CODE',
|
||||
'COMPLEX_MACRO',
|
||||
'PREFER_DEV_LEVEL',
|
||||
'PREFER_PR_LEVEL',
|
||||
'COMPARISON_TO_NULL',
|
||||
'BIT_MACRO',
|
||||
'CONSTANT_COMPARISON',
|
||||
'MACRO_WITH_FLOW_CONTROL',
|
||||
|
||||
# Spams hundreds of lines useless 'struct should
|
||||
# normally be const' warnings, maybe a bug in
|
||||
# checkpatch?
|
||||
'CONST_STRUCT',
|
||||
|
||||
# TODO: look like valid warnings, investigate
|
||||
'MACRO_ARG_REUSE',
|
||||
'OPEN_ENDED_LINE',
|
||||
'FUNCTION_ARGUMENTS',
|
||||
'CONFIG_DESCRIPTION',
|
||||
'ASSIGNMENT_CONTINUATIONS',
|
||||
'UNNECESSARY_PARENTHESES',
|
||||
|
||||
# Not sure if these really useful warnings,
|
||||
# disable for now.
|
||||
'MACRO_ARG_PRECEDENCE',
|
||||
|
||||
'BOOL_MEMBER',
|
||||
]
|
||||
|
||||
CHECKPATCH_OPTS = ['--strict', '-q', '--terse', '--no-summary',
|
||||
'--max-line-length=90', '--show-types']
|
||||
|
||||
checkpatch_filter = [
|
||||
('ath10k_read_simulate_fw_crash', 'LONG_LINE'),
|
||||
('wmi_ops', 'LONG_LINE'),
|
||||
('wmi_tlv_policy', 'SPACING'),
|
||||
('ath10k_core_register_work', 'RETURN_VOID'),
|
||||
('ATH10K_HW_RATE_CCK_.*', 'LONG_LINE'),
|
||||
('ATH10K_DFS_STAT_INC', 'MACRO_ARG_UNUSED'),
|
||||
|
||||
# checkpatch doesn't like uninitialized_var()
|
||||
('ath10k_init_hw_params', 'FUNCTION_ARGUMENTS'),
|
||||
]
|
||||
|
||||
# global variables
|
||||
|
||||
logger = logging.getLogger('ath10k-check')
|
||||
|
||||
threads = 1
|
||||
|
||||
|
||||
class CPWarning():
|
||||
|
||||
def __str__(self):
|
||||
return 'CPWarning(%s, %s, %s, %s, %s)' % (self.path, self.lineno,
|
||||
self.tag, self.type,
|
||||
self.msg)
|
||||
|
||||
def __init__(self):
|
||||
self.path = ''
|
||||
self.lineno = ''
|
||||
self.type = ''
|
||||
self.msg = ''
|
||||
self.tag = ''
|
||||
|
||||
|
||||
def run_gcc(args):
|
||||
# to disable utf-8 from gcc, easier to paste that way
|
||||
os.environ['LC_CTYPE'] = 'C'
|
||||
|
||||
cmd = 'rm -f %s/*.o' % (DRIVER_DIR)
|
||||
logger.debug('%s' % cmd)
|
||||
subprocess.call(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
cmd = ['make', '-k', '-j', str(threads)]
|
||||
|
||||
if not args.no_extra:
|
||||
cmd.append('W=1')
|
||||
|
||||
cmd.append(DRIVER_DIR)
|
||||
|
||||
env = os.environ.copy()
|
||||
|
||||
# disable ccache in case it's in use, it's useless as we are
|
||||
# compiling only few files and it also breaks GCC's
|
||||
# -Wimplicit-fallthrough check
|
||||
env['CCACHE_DISABLE'] = '1'
|
||||
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=env, universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def run_sparse(args):
|
||||
cmd = ['make', '-k', '-j',
|
||||
str(threads), DRIVER_DIR, 'C=2', 'CF="-D__CHECK_ENDIAN__"']
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def find_tagname(tag_map, filename, lineno):
|
||||
if filename.find('Kconfig') != -1:
|
||||
return None
|
||||
|
||||
if filename not in tag_map:
|
||||
return None
|
||||
|
||||
# we need the tags sorted per linenumber
|
||||
sorted_tags = sorted(tag_map[filename], key=lambda tup: tup[0])
|
||||
|
||||
lineno = int(lineno)
|
||||
|
||||
prev = None
|
||||
|
||||
# find the tag which is in lineno
|
||||
for (l, tag) in sorted_tags:
|
||||
if l > lineno:
|
||||
return prev
|
||||
|
||||
prev = tag
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def parse_checkpatch_warning(line):
|
||||
m = re.match(r'(.*?):(\d+): .*?:(.*?): (.*)', line, re.M | re.I)
|
||||
result = CPWarning()
|
||||
result.path = m.group(1)
|
||||
result.lineno = m.group(2)
|
||||
result.type = m.group(3)
|
||||
result.msg = m.group(4)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def is_filtered(cpwarning):
|
||||
if cpwarning.tag is None:
|
||||
return False
|
||||
|
||||
for (tag, type) in checkpatch_filter:
|
||||
matchobj = re.match(tag, cpwarning.tag)
|
||||
if matchobj is None:
|
||||
continue
|
||||
|
||||
if cpwarning.type == type:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_checkpatch_cmdline():
|
||||
return ['checkpatch.pl'] + CHECKPATCH_OPTS + \
|
||||
['--ignore', ",".join(CHECKPATCH_IGNORE)]
|
||||
|
||||
|
||||
def run_checkpatch_cmd(args, q, tag_map):
|
||||
checkpatch_cmd = get_checkpatch_cmdline() + ['-f']
|
||||
|
||||
while True:
|
||||
try:
|
||||
f = q.get_nowait()
|
||||
except queue.Empty:
|
||||
# no more files to check
|
||||
break
|
||||
|
||||
cmd = checkpatch_cmd + [f]
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdoutdata, stderrdata) = p.communicate()
|
||||
|
||||
if stdoutdata is None:
|
||||
continue
|
||||
|
||||
lines = stdoutdata.splitlines()
|
||||
for line in lines:
|
||||
w = parse_checkpatch_warning(line)
|
||||
w.tag = find_tagname(tag_map, f, w.lineno)
|
||||
|
||||
if not args.no_filter and is_filtered(w):
|
||||
logger.debug('FILTERED: %s' % w)
|
||||
continue
|
||||
|
||||
logger.debug(w)
|
||||
print('%s:%s: %s' % (w.path, w.lineno, w.msg))
|
||||
|
||||
q.task_done()
|
||||
|
||||
|
||||
def run_checkpatch(args):
|
||||
# get all files which need to be checked
|
||||
cmd = 'git ls-tree HEAD %s | cut -f 2' % (DRIVER_DIR)
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
driver_files = output.splitlines()
|
||||
|
||||
# drop files we need to ignore
|
||||
for name in IGNORE_FILES:
|
||||
full_name = '%s%s' % (DRIVER_DIR, name)
|
||||
if full_name in driver_files:
|
||||
driver_files.remove(full_name)
|
||||
|
||||
logger.debug('driver_files: %s' % (driver_files))
|
||||
|
||||
# create global index file
|
||||
(fd, tmpfilename) = tempfile.mkstemp()
|
||||
f = os.fdopen(fd, 'w')
|
||||
f.write('\n'.join(driver_files))
|
||||
f.close()
|
||||
|
||||
# FIXME: do we need to call os.close(fd) still?
|
||||
|
||||
cmd = 'gtags -f %s' % (tmpfilename)
|
||||
logger.debug('%s' % (cmd))
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
os.remove(tmpfilename)
|
||||
|
||||
# tag_map[FILENAME] = [(start line, tagname)]
|
||||
tag_map = {}
|
||||
|
||||
# create tag mapping
|
||||
for f in driver_files:
|
||||
# global gives an error from Kconfig and Makefile
|
||||
if f.endswith('Kconfig') or f.endswith('Makefile'):
|
||||
continue
|
||||
|
||||
cmd = 'global -f %s' % (f)
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
lines = output.splitlines()
|
||||
for l in lines:
|
||||
columns = l.split()
|
||||
tagname = columns[0]
|
||||
line = int(columns[1])
|
||||
|
||||
if f not in tag_map:
|
||||
tag_map[f] = []
|
||||
|
||||
tag_map[f].append((line, tagname))
|
||||
|
||||
q = queue.Queue()
|
||||
|
||||
for f in driver_files:
|
||||
q.put(f)
|
||||
|
||||
# run checkpatch for all files
|
||||
for i in range(threads):
|
||||
t = threading.Thread(
|
||||
target=run_checkpatch_cmd, args=(args, q, tag_map))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
q.join()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def show_version(args):
|
||||
gcc_version = 'not found'
|
||||
sparse_version = 'not found'
|
||||
checkpatch_version = 'not found'
|
||||
checkpatch_md5sum = 'N/A'
|
||||
gtags_version = 'not found'
|
||||
|
||||
run = subprocess.check_output
|
||||
|
||||
f = open(sys.argv[0], 'rb')
|
||||
ath10kcheck_md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
try:
|
||||
gcc_version = run(['gcc', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
sparse_version = run(['sparse', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
checkpatch_version = run(['checkpatch.pl', '--version'],
|
||||
universal_newlines=True).splitlines()[1]
|
||||
path = distutils.spawn.find_executable(
|
||||
'checkpatch.pl', os.environ['PATH'])
|
||||
f = open(path, 'rb')
|
||||
checkpatch_md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
gtags_version = run(['gtags', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
print('ath10k-check (md5sum %s)' % (ath10kcheck_md5sum))
|
||||
print
|
||||
print('gcc:\t\t%s' % (gcc_version))
|
||||
print('sparse:\t\t%s' % (sparse_version))
|
||||
print('checkpatch.pl:\t%s (md5sum %s)' % (checkpatch_version, checkpatch_md5sum))
|
||||
print('gtags:\t\t%s' % (gtags_version))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
global threads
|
||||
|
||||
checkpatch_url = GIT_URL % (CHECKPATCH_COMMIT)
|
||||
|
||||
description = '''ath10k source code checker
|
||||
|
||||
Runs various tests (gcc, sparse and checkpatch) with filtering
|
||||
unnecessary warnings away, the goal is to have empty output from the
|
||||
script.
|
||||
|
||||
Run this from the main kernel source directory which is preconfigured
|
||||
with ath10k enabled. gcc recompilation is forced every time,
|
||||
irrespective if there are any changes in source or not. So this can be
|
||||
run multiple times and every time the same warnings will appear.
|
||||
|
||||
Requirements (all available in $PATH):
|
||||
|
||||
* gcc
|
||||
* sparse
|
||||
* checkpatch.pl
|
||||
* gtags (from package global)
|
||||
|
||||
'''
|
||||
|
||||
s = '''Installation:
|
||||
|
||||
As checkpatch is evolving this script always matches a certain version
|
||||
of checkpatch. Download the checkpatch version from the URL below and
|
||||
install it somewhere in your $$PATH:
|
||||
|
||||
$CHECKPATCH_URL
|
||||
|
||||
Alternatively if you want manually run checkpatch with the same
|
||||
settings as ath10k-check uses here's the command line:
|
||||
|
||||
$CHECKPATCH_CMDLINE
|
||||
'''
|
||||
|
||||
checkpatch_cmdline = '%s foo.patch' % ' '.join(get_checkpatch_cmdline())
|
||||
epilog = string.Template(s).substitute(CHECKPATCH_URL=checkpatch_url,
|
||||
CHECKPATCH_CMDLINE=checkpatch_cmdline)
|
||||
|
||||
parser = argparse.ArgumentParser(description=description, epilog=epilog,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
parser.add_argument('-d', '--debug', action='store_true',
|
||||
help='enable debug messages')
|
||||
|
||||
parser.add_argument('--fast', action='store_true',
|
||||
help='run only tests which finish in few seconds')
|
||||
|
||||
parser.add_argument('--no-extra', action='store_true',
|
||||
help='Do not run extra checks like W=1')
|
||||
|
||||
parser.add_argument('--no-filter', action='store_true',
|
||||
help='Don\'t filter output with regexp: %r' % (FILTER_REGEXP))
|
||||
|
||||
parser.add_argument('--version', action='store_true',
|
||||
help='Show version information about dependencies')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
timefmt = ''
|
||||
|
||||
if args.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
timefmt = '%(asctime)s '
|
||||
|
||||
logfmt = '%s%%(levelname)s: %%(message)s' % (timefmt)
|
||||
|
||||
logging.basicConfig(format=logfmt)
|
||||
|
||||
if args.version:
|
||||
show_version(args)
|
||||
|
||||
if args.fast:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = False
|
||||
else:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = True
|
||||
|
||||
try:
|
||||
cores = subprocess.check_output(['nproc'], universal_newlines=True)
|
||||
except (OSError, subprocess.CalledProcessError):
|
||||
cores = '4'
|
||||
logger.warning('Failed to run nproc, assuming %s cores' % (cores))
|
||||
|
||||
threads = int(cores) + 2
|
||||
|
||||
logger.debug('threads %d' % (threads))
|
||||
|
||||
if gcc:
|
||||
ret = run_gcc(args)
|
||||
if ret != 0:
|
||||
logger.debug('gcc failed: %d', ret)
|
||||
sys.exit(1)
|
||||
|
||||
if sparse:
|
||||
ret = run_sparse(args)
|
||||
if ret != 0:
|
||||
logger.debug('sparse failed: %d', ret)
|
||||
sys.exit(2)
|
||||
|
||||
if checkpatch:
|
||||
ret = run_checkpatch(args)
|
||||
if ret != 0:
|
||||
logger.debug('checkpatch failed: %d', ret)
|
||||
sys.exit(3)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
806
tools/scripts/ath10k/ath10k-fw-repo
Executable file
806
tools/scripts/ath10k/ath10k-fw-repo
Executable file
|
|
@ -0,0 +1,806 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2016 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import os
|
||||
import logging
|
||||
import re
|
||||
import argparse
|
||||
import shutil
|
||||
import sys
|
||||
import filecmp
|
||||
import functools
|
||||
import subprocess
|
||||
import email
|
||||
|
||||
# global variables
|
||||
logger = None
|
||||
blacklist = False
|
||||
|
||||
BRANCH_DEFAULT_PRIORITY = 1000
|
||||
BRANCH_PRIORITY_FILE = '.priority'
|
||||
BRANCH_IGNORE_FILE = '.ignore'
|
||||
WHENCE_FILE = 'WHENCE'
|
||||
|
||||
FIRMWARE_BLACKLIST = [
|
||||
'999.999.0.636',
|
||||
'10.2-00082-4-2'
|
||||
]
|
||||
|
||||
|
||||
@functools.total_ordering
|
||||
class Hardware():
|
||||
def get_path(self):
|
||||
return os.path.join(self.hw, self.hw_ver)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.name < other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'Hardware(\'%s\'): %s %s' % (self.name, self.board_files,
|
||||
sorted(self.firmware_branches))
|
||||
|
||||
def __init__(self, hw, hw_ver):
|
||||
# QCA6174
|
||||
self.hw = hw
|
||||
|
||||
# hw3.0
|
||||
self.hw_ver = hw_ver
|
||||
|
||||
self.name = '%s %s' % (hw, hw_ver)
|
||||
|
||||
self.firmware_branches = []
|
||||
self.board_files = []
|
||||
|
||||
|
||||
@functools.total_ordering
|
||||
class FirmwareBranch():
|
||||
def __eq__(self, other):
|
||||
return self.priority == other.priority and self.name == other.name
|
||||
|
||||
def __lt__(self, other):
|
||||
# '.' is always of the lower priority
|
||||
if self.name == '.':
|
||||
return True
|
||||
|
||||
if other.name == '.':
|
||||
return False
|
||||
|
||||
if self.priority != other.priority:
|
||||
if self.priority < other.priority:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return self.name < other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'FirmwareBranch(\'%s\'): %s' % (self.name, sorted(self.firmwares))
|
||||
|
||||
def __init__(self, name, path=None):
|
||||
self.name = name
|
||||
self.firmwares = []
|
||||
self.priority = BRANCH_DEFAULT_PRIORITY
|
||||
|
||||
if path:
|
||||
priority_path = os.path.join(path, BRANCH_PRIORITY_FILE)
|
||||
if os.path.isfile(priority_path):
|
||||
try:
|
||||
f = open(priority_path, 'r')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
self.priority = int(buf)
|
||||
except Exception as e:
|
||||
print('Failed to read %s: %s' % (priority_path, e))
|
||||
|
||||
|
||||
class BoardFile():
|
||||
|
||||
@staticmethod
|
||||
def create_from_path(path):
|
||||
filename = os.path.basename(path)
|
||||
|
||||
match = re.search(r'^board-(\d+).bin', filename)
|
||||
if match is None:
|
||||
match = re.search(r'^board.bin', filename)
|
||||
if match is None:
|
||||
return None
|
||||
|
||||
if len(match.groups()) > 1:
|
||||
bd_api = match.group(1)
|
||||
else:
|
||||
bd_api = None
|
||||
|
||||
return BoardFile(path, bd_api)
|
||||
|
||||
def get_installation_name(self):
|
||||
return os.path.basename(self.path)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return '%s' % (self.get_installation_name())
|
||||
|
||||
def __init__(self, path, bd_api):
|
||||
self.path = path
|
||||
self.bd_api = bd_api
|
||||
|
||||
|
||||
class Firmware():
|
||||
|
||||
@staticmethod
|
||||
def create_from_path(path):
|
||||
filename = os.path.basename(path)
|
||||
|
||||
match = re.search(r'^firmware-(\d+).bin_(.+)', filename)
|
||||
if match is None:
|
||||
return None
|
||||
|
||||
fw_api = match.group(1)
|
||||
fw_ver = match.group(2)
|
||||
|
||||
return Firmware(fw_ver, path, fw_api)
|
||||
|
||||
def get_installation_name(self):
|
||||
return 'firmware-%s.bin' % (self.fw_api)
|
||||
|
||||
def get_notice_filename(self):
|
||||
return 'notice_ath10k_firmware-%s.txt' % (self.fw_api)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.fw_ver == other.fw_ver
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
# FIXME: firmware-5.bin_10.4-3.2-00080 and
|
||||
# firmware-5.bin_10.4-3.2.1-00028 are sorted incorrectly
|
||||
def __lt__(self, other):
|
||||
s = self.fw_ver
|
||||
o = other.fw_ver
|
||||
|
||||
# FIXME: An ugly hack that to make the comparison easier to
|
||||
# implement. Just to get some sort of simple sorting working
|
||||
# replace '-' with '.' in version string. But now for example
|
||||
# '10.2.4.70.2 > 10.2.4.70-2' is not compared correctly.
|
||||
|
||||
s = s.replace('-', '.')
|
||||
o = o.replace('-', '.')
|
||||
|
||||
s = s.split('.')
|
||||
o = o.split('.')
|
||||
|
||||
s2 = s
|
||||
o2 = o
|
||||
|
||||
s = []
|
||||
o = []
|
||||
|
||||
for t in s2:
|
||||
try:
|
||||
k = int(t)
|
||||
except:
|
||||
k = t
|
||||
|
||||
s.append(k)
|
||||
|
||||
for t in o2:
|
||||
try:
|
||||
k = int(t)
|
||||
except:
|
||||
k = t
|
||||
|
||||
o.append(k)
|
||||
|
||||
l = min(len(s), len(o))
|
||||
|
||||
for i in range(l):
|
||||
|
||||
if s[i] < o[i]:
|
||||
return True
|
||||
elif s[i] > o[i]:
|
||||
return False
|
||||
|
||||
if len(s) > len(o):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __le__(self, other):
|
||||
return self.__lt__(other) or self.__eq__(other)
|
||||
|
||||
def __gt__(self, other):
|
||||
return not self.__le__(other)
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.__gt__(other) or self.__eq__(other)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return '%s' % (self.fw_ver)
|
||||
|
||||
# path can be None with unittests
|
||||
def __init__(self, fw_ver, path=None, fw_api=None):
|
||||
self.path = path
|
||||
self.fw_api = fw_api
|
||||
self.fw_ver = fw_ver
|
||||
self.notice_path = None
|
||||
|
||||
if path:
|
||||
s = 'notice.txt_%s' % (self.fw_ver)
|
||||
n = os.path.join(os.path.dirname(path), s)
|
||||
if os.path.isfile(n):
|
||||
self.notice_path = n
|
||||
|
||||
|
||||
def scan_dir(path):
|
||||
fw_list = []
|
||||
bd_list = []
|
||||
|
||||
files = os.listdir(path)
|
||||
files.sort()
|
||||
|
||||
for f in files:
|
||||
f_path = os.path.join(path, f)
|
||||
|
||||
if not os.path.isfile(f_path):
|
||||
continue
|
||||
|
||||
firmware = Firmware.create_from_path(f_path)
|
||||
if firmware:
|
||||
if blacklist and firmware.fw_ver in FIRMWARE_BLACKLIST:
|
||||
logger.debug('\'%s\' blacklisted' % (firmware.fw_ver))
|
||||
continue
|
||||
|
||||
fw_list.append(firmware)
|
||||
continue
|
||||
|
||||
boardfile = BoardFile.create_from_path(f_path)
|
||||
if boardfile:
|
||||
bd_list.append(boardfile)
|
||||
continue
|
||||
|
||||
# skip notice files
|
||||
if f.startswith('notice.txt'):
|
||||
continue
|
||||
|
||||
if f == BRANCH_PRIORITY_FILE:
|
||||
continue
|
||||
|
||||
logger.warning('Unknown file: %s' % (f_path))
|
||||
|
||||
return fw_list, bd_list
|
||||
|
||||
|
||||
# QCA988X/hw2.0
|
||||
def scan_hw_ver(hw):
|
||||
path = hw.get_path()
|
||||
files = os.listdir(path)
|
||||
files.sort()
|
||||
|
||||
for fw_branch in files:
|
||||
fw_branch_path = os.path.join(path, fw_branch)
|
||||
|
||||
if not os.path.isdir(fw_branch_path):
|
||||
continue
|
||||
|
||||
if os.path.exists(os.path.join(fw_branch_path, BRANCH_IGNORE_FILE)):
|
||||
logger.debug('Ignoring firmware branch: %s' % (fw_branch))
|
||||
continue
|
||||
|
||||
logger.debug('Found firmware branch: %s' % (fw_branch))
|
||||
fb = FirmwareBranch(fw_branch, fw_branch_path)
|
||||
hw.firmware_branches.append(fb)
|
||||
|
||||
(fw, bd) = scan_dir(fw_branch_path)
|
||||
fb.firmwares += fw
|
||||
|
||||
# board file should be only in "." (main) branch, not in other branches
|
||||
|
||||
# this is the main branch named "."
|
||||
fb = FirmwareBranch('.')
|
||||
|
||||
(fw, bd) = scan_dir(path)
|
||||
fb.firmwares += fw
|
||||
hw.board_files += bd
|
||||
|
||||
hw.firmware_branches.append(fb)
|
||||
|
||||
|
||||
# QCA98XX
|
||||
def scan_hw(path):
|
||||
hws = []
|
||||
|
||||
files = os.listdir(path)
|
||||
files.sort()
|
||||
|
||||
for hw_ver in files:
|
||||
hw_ver_path = os.path.join(path, hw_ver)
|
||||
|
||||
if not os.path.isdir(hw_ver_path):
|
||||
continue
|
||||
|
||||
logger.debug('Found hw version: %s' % (hw_ver))
|
||||
|
||||
hw = Hardware(path, hw_ver)
|
||||
scan_hw_ver(hw)
|
||||
hws.append(hw)
|
||||
|
||||
return hws
|
||||
|
||||
|
||||
def scan_repository(directory):
|
||||
hws = {}
|
||||
|
||||
files = os.listdir(directory)
|
||||
files.sort()
|
||||
|
||||
for hw_name in files:
|
||||
if not os.path.isdir(hw_name):
|
||||
continue
|
||||
|
||||
# skip hidden directories
|
||||
if hw_name.startswith('.'):
|
||||
continue
|
||||
|
||||
logger.debug('Found hw: %s' % (hw_name))
|
||||
|
||||
hw_list = scan_hw(hw_name)
|
||||
|
||||
for hw in hw_list:
|
||||
hws[hw.name] = hw
|
||||
|
||||
return hws
|
||||
|
||||
|
||||
def install_file(args, src, installdir, dest):
|
||||
if args.dry_run:
|
||||
return
|
||||
|
||||
destpath = os.path.join(installdir, dest)
|
||||
|
||||
destdir = os.path.dirname(destpath)
|
||||
if not os.path.isdir(destdir):
|
||||
os.makedirs(destdir)
|
||||
|
||||
shutil.copyfile(src, destpath)
|
||||
|
||||
return destpath
|
||||
|
||||
|
||||
def get_firmware_version(path):
|
||||
cmd = ['ath10k-fwencoder', '--info', path]
|
||||
info = subprocess.check_output(cmd, universal_newlines=True)
|
||||
msg = email.message_from_string(info)
|
||||
return msg['FirmwareVersion']
|
||||
|
||||
|
||||
def get_board_crc32(path):
|
||||
cmd = ['ath10k-fwencoder', '--crc32', path]
|
||||
return subprocess.check_output(cmd, universal_newlines=True).strip()
|
||||
|
||||
|
||||
# print indent
|
||||
def pi(level, msg):
|
||||
print('%s%s' % (level * '\t', msg))
|
||||
|
||||
|
||||
def whence_update(linux_firmware, firmware_path, version):
|
||||
f = open(os.path.join(linux_firmware, WHENCE_FILE), 'r')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
pattern = r'(File: %s\nVersion: ).*\n' % (firmware_path)
|
||||
|
||||
# \g<1> is same as \1 but needed to separate from the version string
|
||||
replace = r'\g<1>%s\n' % (version)
|
||||
|
||||
(buf, sub_count) = re.subn(pattern, replace, buf, flags=re.MULTILINE)
|
||||
|
||||
if sub_count != 1:
|
||||
print('Failed to update %s to WHENCE: %d' % (firmware_path, sub_count))
|
||||
return
|
||||
|
||||
f = open(os.path.join(linux_firmware, WHENCE_FILE), 'w')
|
||||
f.write(buf)
|
||||
f.close()
|
||||
|
||||
|
||||
def whence_add(linux_firmware, firmware_path, version, license_path=None):
|
||||
f = open(os.path.join(linux_firmware, WHENCE_FILE), 'r')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
pattern = r'(Driver: ath10k.*?\n\n.*?)\n\n'
|
||||
|
||||
# \g<1> is same as \1 but needed to separate from the version string
|
||||
replace = r'\g<1>\nFile: %s\n' % (firmware_path)
|
||||
replace += r'Version: %s\n' % (version)
|
||||
|
||||
if license_path is not None:
|
||||
replace += r'File: %s\n' % (license_path)
|
||||
|
||||
replace += r'\n'
|
||||
|
||||
(buf, sub_count) = re.subn(pattern, replace, buf, flags=re.MULTILINE | re.DOTALL)
|
||||
|
||||
if sub_count != 1:
|
||||
print('Failed to add %s to WHENCE: %d' % (firmware_path, sub_count))
|
||||
return
|
||||
|
||||
f = open(os.path.join(linux_firmware, WHENCE_FILE), 'w')
|
||||
f.write(buf)
|
||||
f.close()
|
||||
|
||||
|
||||
def git_commit(args, msg, repodir, files):
|
||||
if not args.commit:
|
||||
# nothing to do
|
||||
return
|
||||
|
||||
cmd = ['git', '-C', repodir, 'commit', '--quiet', '--signoff', '-m', msg] + files
|
||||
|
||||
logger.debug('Running: %r' % (cmd))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def git_add(args, repodir, files):
|
||||
if not args.commit:
|
||||
# nothing to do
|
||||
return
|
||||
|
||||
cmd = ['git', '-C', repodir, 'add'] + files
|
||||
|
||||
logger.debug('Running: %r' % (cmd))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def cmd_check(args):
|
||||
scan_repository('.')
|
||||
|
||||
|
||||
def cmd_list(args):
|
||||
level = 0
|
||||
|
||||
hws = scan_repository('.')
|
||||
for hw in sorted(hws.values()):
|
||||
pi(level, '%s:' % (hw.name))
|
||||
level += 1
|
||||
|
||||
# print board files
|
||||
if len(hw.board_files) > 0:
|
||||
pi(level, 'board')
|
||||
level += 1
|
||||
|
||||
for board_file in sorted(hw.board_files):
|
||||
pi(level, board_file)
|
||||
|
||||
level -= 1
|
||||
|
||||
# print firmware branches
|
||||
for branch in sorted(hw.firmware_branches):
|
||||
if len(branch.firmwares) == 0:
|
||||
# don't print empty branches
|
||||
continue
|
||||
|
||||
pi(level, '%s' % (branch.name))
|
||||
level += 1
|
||||
|
||||
for fw in sorted(branch.firmwares):
|
||||
pi(level, fw.fw_ver)
|
||||
|
||||
level -= 1
|
||||
|
||||
level -= 1
|
||||
|
||||
|
||||
def cmd_list_lib_dir(args):
|
||||
fw_dir = args.list_lib_dir[0]
|
||||
ath10k_dir = os.path.join(fw_dir, 'ath10k')
|
||||
|
||||
if not os.path.exists(ath10k_dir):
|
||||
print('directory %s does not exist, aborting' % (ath10k_dir))
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.isdir(ath10k_dir):
|
||||
print('%s is not a directory, aborting' % (ath10k_dir))
|
||||
sys.exit(1)
|
||||
|
||||
# sort the results based on dirpath
|
||||
for (dirpath, dirnames, filenames) in sorted(os.walk(ath10k_dir)):
|
||||
found = []
|
||||
for filename in sorted(filenames):
|
||||
path = os.path.join(dirpath, filename)
|
||||
|
||||
match = re.match(r'firmware.*\.bin', filename)
|
||||
if match is not None:
|
||||
# this is a firmware file
|
||||
s = '%s\t%s' % (filename, get_firmware_version(path))
|
||||
found.append(s)
|
||||
|
||||
match = re.match(r'board.*\.bin', filename)
|
||||
if match is not None:
|
||||
# this is a board file
|
||||
s = '%s\t%s' % (filename, get_board_crc32(path))
|
||||
found.append(s)
|
||||
|
||||
if len(found) > 0:
|
||||
# Just show QCA1234/hw1.0 directories. I would have liked
|
||||
# to use os.path functions here but just could not find
|
||||
# anything sensible there.
|
||||
pi(0, '%s:' % ('/'.join(dirpath.split('/')[-2:])))
|
||||
for line in found:
|
||||
pi(1, line)
|
||||
|
||||
|
||||
def cmd_get_latest_in_branch(args):
|
||||
# As this command is mostly for scripts to parse, don't show
|
||||
# warnings etc to clutter the output, unless we are debugging of
|
||||
# course.
|
||||
if not args.debug:
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
hws = scan_repository('.')
|
||||
|
||||
args_hw = args.get_latest_in_branch[0]
|
||||
args_hwver = args.get_latest_in_branch[1]
|
||||
args_fwbranch = args.get_latest_in_branch[2]
|
||||
|
||||
# TODO: hw is always in uppercase and hwver lower case, check that
|
||||
hw_name = '%s %s' % (args_hw, args_hwver)
|
||||
|
||||
if hw_name not in hws:
|
||||
print('Did not find hardware: %s' % (hw_name))
|
||||
sys.exit(1)
|
||||
|
||||
hw = hws[hw_name]
|
||||
|
||||
fw_branch = None
|
||||
|
||||
for b in hw.firmware_branches:
|
||||
if b.name == args_fwbranch:
|
||||
fw_branch = b
|
||||
break
|
||||
|
||||
if fw_branch is None:
|
||||
print('Did not find firmware branch: %s' % (args_fwbranch))
|
||||
sys.exit(1)
|
||||
|
||||
if len(fw_branch.firmwares) == 0:
|
||||
# no firmware images in this branch, just use return value 0 with no output
|
||||
sys.exit(0)
|
||||
|
||||
print(sorted(fw_branch.firmwares)[-1].path)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def cmd_get_latest_in_hw(args):
|
||||
# As this command is mostly for scripts to parse, don't show
|
||||
# warnings etc to clutter the output, unless we are debugging of
|
||||
# course.
|
||||
if not args.debug:
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
hws = scan_repository('.')
|
||||
|
||||
args_hw = args.get_latest[0]
|
||||
args_hwver = args.get_latest[1]
|
||||
|
||||
# TODO: hw is always in uppercase and hwver lower case, check that
|
||||
hw_name = '%s %s' % (args_hw, args_hwver)
|
||||
|
||||
if hw_name not in hws:
|
||||
print('Did not find hardware: %s' % (hw_name))
|
||||
sys.exit(1)
|
||||
|
||||
hw = hws[hw_name]
|
||||
|
||||
fw_branch = sorted(hw.firmware_branches)[-1]
|
||||
|
||||
if len(fw_branch.firmwares) == 0:
|
||||
# no firmware images in this branch, just use return value 0 with no output
|
||||
sys.exit(0)
|
||||
|
||||
print(sorted(fw_branch.firmwares)[-1].path)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def cmd_install(args):
|
||||
global blacklist
|
||||
|
||||
blacklist = True
|
||||
|
||||
hws = scan_repository('.')
|
||||
|
||||
linux_firmware = args.install[0]
|
||||
installdir = os.path.join(linux_firmware, 'ath10k')
|
||||
|
||||
if not os.path.isdir(installdir):
|
||||
logger.error('%s is not a directory' % (installdir))
|
||||
sys.exit(1)
|
||||
|
||||
logger.debug('Installing to directory %s' % (installdir))
|
||||
|
||||
# install firmware files
|
||||
for hw in sorted(hws.values()):
|
||||
# every Hardware() should have at least one firmware branch, the
|
||||
# main '.' branch so no need to check the length
|
||||
fw_list = sorted(sorted(hw.firmware_branches)[-1].firmwares)
|
||||
|
||||
if len(fw_list) == 0:
|
||||
# no firmware images found
|
||||
continue
|
||||
|
||||
destdir = hw.get_path()
|
||||
|
||||
# install latest firmware
|
||||
#
|
||||
# FIXME: should we install the latest for every FW API
|
||||
# version (2, 4, 5 etc.), not just the latest?
|
||||
fw = fw_list[-1]
|
||||
|
||||
dest = os.path.join(destdir, fw.get_installation_name())
|
||||
d = os.path.join(installdir, dest)
|
||||
if not os.path.exists(d) or not filecmp.cmp(fw.path, d):
|
||||
installed = []
|
||||
|
||||
if os.path.exists(d):
|
||||
action = 'update'
|
||||
else:
|
||||
action = 'add'
|
||||
|
||||
logger.info('Installing %s (%s)' % (dest, fw.fw_ver))
|
||||
destpath = install_file(args, fw.path, installdir, dest)
|
||||
installed.append(destpath)
|
||||
firmware_path = os.path.join('ath10k', dest)
|
||||
|
||||
if fw.notice_path:
|
||||
dest = os.path.join(destdir, fw.get_notice_filename())
|
||||
logger.info('Installing %s (%s)' % (dest, fw.fw_ver))
|
||||
destpath = install_file(args, fw.notice_path, installdir, dest)
|
||||
installed.append(destpath)
|
||||
notice_path = os.path.join('ath10k', dest)
|
||||
else:
|
||||
notice_path = None
|
||||
|
||||
if action == 'update':
|
||||
# updating an existing firmware file
|
||||
whence_update(linux_firmware, firmware_path, fw.fw_ver)
|
||||
else:
|
||||
# adding a new firmware file
|
||||
whence_add(linux_firmware, firmware_path, fw.fw_ver, notice_path)
|
||||
git_add(args, linux_firmware, installed)
|
||||
|
||||
installed.append(WHENCE_FILE)
|
||||
|
||||
# "ath10k: QCA9888 hw2.0: update firmware-5.bin to 10.4-3.5.1-00035"
|
||||
log = 'ath10k: %s: %s %s to %s' % (hw.name,
|
||||
action,
|
||||
fw.get_installation_name(),
|
||||
fw.fw_ver)
|
||||
|
||||
git_commit(args, log, linux_firmware, installed)
|
||||
else:
|
||||
logger.debug(
|
||||
'No update needed for %s (%s)' % (dest, fw.fw_ver))
|
||||
|
||||
# install board files
|
||||
for hw in sorted(hws.values()):
|
||||
bd_list = hw.board_files
|
||||
|
||||
for bd in bd_list:
|
||||
installed = []
|
||||
dest = os.path.join(installdir, bd.path)
|
||||
if not os.path.exists(dest) or not filecmp.cmp(bd.path, dest):
|
||||
if os.path.exists(dest):
|
||||
action = 'update'
|
||||
else:
|
||||
action = 'add'
|
||||
|
||||
logger.info('Installing %s' % (bd.path))
|
||||
destpath = install_file(args, bd.path, installdir, bd.path)
|
||||
installed.append(destpath)
|
||||
|
||||
# TODO: update WHENCE file when adding a new board
|
||||
# file to linux-firmware
|
||||
|
||||
log = 'ath10k: %s: %s %s' % (hw.name,
|
||||
action,
|
||||
bd.get_installation_name())
|
||||
git_commit(args, log, linux_firmware, installed)
|
||||
else:
|
||||
logger.debug('No update needed for %s' % (dest))
|
||||
|
||||
|
||||
def main():
|
||||
global logger
|
||||
|
||||
logger = logging.getLogger('ath10k-fw-repo')
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Install firmware images from the ath10k-firmware git repository. Run it from the top directory of the working tree.')
|
||||
|
||||
parser.add_argument('--debug', action='store_true',
|
||||
help='Enable debug messages.')
|
||||
parser.add_argument('--dry-run', action='store_true',
|
||||
help='Do not run any actual commands.')
|
||||
|
||||
parser.add_argument('--check', action='store_true',
|
||||
help='Check the ath10k-firmware repository content for validity.')
|
||||
parser.add_argument('--list', action='store_true',
|
||||
help='List all files found from the ath10k-firmware repository.')
|
||||
|
||||
parser.add_argument('--list-lib-dir', action='store',
|
||||
nargs=1, metavar='LIB_FIRMWARE_DIRECTORY',
|
||||
help='List all files found from the specified directory, which can either be a linux-firmware repository or /lib/firmware directory.')
|
||||
|
||||
parser.add_argument('--install', action='store', nargs=1, metavar='DESTINATION',
|
||||
help='Install all ath10k firmware images to DESTINATION folder, for example /lib/firmware.')
|
||||
|
||||
parser.add_argument('--commit', action='store_true',
|
||||
help='When installing files also git commit them, for example when updating linux-firmware.git.')
|
||||
|
||||
parser.add_argument('--get-latest-in-branch', action='store', nargs=3,
|
||||
metavar=('HW', 'HWVER', 'BRANCH'),
|
||||
help='Show latest firmware version from a firmware branch. Just outputs the version for easy parsing in scripts.')
|
||||
|
||||
parser.add_argument('--get-latest', action='store', nargs=2,
|
||||
metavar=('HW', 'HWVER'),
|
||||
help='Show latest firmware version for hardware version. Just outputs the version for easy parsing in scripts.')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(format='%(message)s')
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# commands
|
||||
if args.check:
|
||||
cmd_check(args)
|
||||
elif args.list:
|
||||
cmd_list(args)
|
||||
elif args.list_lib_dir:
|
||||
cmd_list_lib_dir(args)
|
||||
elif args.install:
|
||||
cmd_install(args)
|
||||
elif args.get_latest_in_branch:
|
||||
cmd_get_latest_in_branch(args)
|
||||
elif args.get_latest:
|
||||
cmd_get_latest_in_hw(args)
|
||||
else:
|
||||
logger.error('No command defined')
|
||||
parser.print_usage()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
934
tools/scripts/ath10k/ath10k-fwencoder
Executable file
934
tools/scripts/ath10k/ath10k-fwencoder
Executable file
|
|
@ -0,0 +1,934 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import ctypes
|
||||
import struct
|
||||
import optparse
|
||||
import time
|
||||
import math
|
||||
import logging
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
import binascii
|
||||
import tempfile
|
||||
import subprocess
|
||||
import hashlib
|
||||
|
||||
DEFAULT_FW_API_VERSION = 4
|
||||
|
||||
ATH10K_SIGNATURE = b"QCA-ATH10K"
|
||||
MAX_LEN = 2000000
|
||||
|
||||
ATH10K_FW_IE_FW_VERSION = 0
|
||||
ATH10K_FW_IE_TIMESTAMP = 1
|
||||
ATH10K_FW_IE_FEATURES = 2
|
||||
ATH10K_FW_IE_FW_IMAGE = 3
|
||||
ATH10K_FW_IE_OTP_IMAGE = 4
|
||||
ATH10K_FW_IE_WMI_OP_VERSION = 5
|
||||
ATH10K_FW_IE_HTT_OP_VERSION = 6
|
||||
ATH10K_FW_IE_FW_CODE_SWAP_IMAGE = 7
|
||||
|
||||
# enum ath10k_fw_features from ath10k/core.h
|
||||
ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0
|
||||
ATH10K_FW_FEATURE_WMI_10X = 1
|
||||
ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2
|
||||
ATH10K_FW_FEATURE_NO_P2P = 3
|
||||
ATH10K_FW_FEATURE_WMI_10_2 = 4
|
||||
ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT = 5
|
||||
ATH10K_FW_FEATURE_WOWLAN_SUPPORT = 6
|
||||
ATH10K_FW_FEATURE_IGNORE_OTP_RESULT = 7
|
||||
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING = 8
|
||||
ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9
|
||||
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10
|
||||
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11
|
||||
ATH10K_FW_FEATURE_MFP_SUPPORT = 12
|
||||
ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13
|
||||
ATH10K_FW_FEATURE_BTCOEX_PARAM = 14
|
||||
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15
|
||||
ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16
|
||||
ATH10K_FW_FEATURE_NO_PS = 17
|
||||
ATH10K_FW_FEATURE_MGMT_TX_BY_REF = 18
|
||||
ATH10K_FW_FEATURE_NON_BMI = 19
|
||||
ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL = 20
|
||||
ATH10K_FW_FEATURE_PEER_FIXED_RATE = 21
|
||||
ATH10K_FW_FEATURE_MAX = 22
|
||||
|
||||
feature_map = {
|
||||
'ext-wmi-mgmt-rx': ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX,
|
||||
'wmi-10x': ATH10K_FW_FEATURE_WMI_10X,
|
||||
'wmi-mgmt-tx': ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
'no-p2p': ATH10K_FW_FEATURE_NO_P2P,
|
||||
'wmi-10-2': ATH10K_FW_FEATURE_WMI_10_2,
|
||||
'multi-vif-ps': ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
|
||||
'wowlan': ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
|
||||
'ignore-otp-result': ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
|
||||
'no-nwifi-decap-4addr-padding':
|
||||
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
|
||||
'skip-clock-init': ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,
|
||||
'raw-mode': ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
|
||||
'adaptive-cca': ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
|
||||
'mfp-support': ATH10K_FW_FEATURE_MFP_SUPPORT,
|
||||
'peer-flow-ctrl': ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
'btcoex-param': ATH10K_FW_FEATURE_BTCOEX_PARAM,
|
||||
'skip-null-func-war': ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR,
|
||||
'allows-mesh-bcast': ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST,
|
||||
'no-ps': ATH10K_FW_FEATURE_NO_PS,
|
||||
'mgmt-tx-by-ref': ATH10K_FW_FEATURE_MGMT_TX_BY_REF,
|
||||
'non-bmi': ATH10K_FW_FEATURE_NON_BMI,
|
||||
'single-chan-info-per-channel': ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL,
|
||||
'peer-fixed-rate': ATH10K_FW_FEATURE_PEER_FIXED_RATE,
|
||||
}
|
||||
|
||||
# from enum ath10k_fw_wmi_op_version in ath10k/hw.h
|
||||
ATH10K_FW_WMI_OP_VERSION_UNSET = 0
|
||||
ATH10K_FW_WMI_OP_VERSION_MAIN = 1
|
||||
ATH10K_FW_WMI_OP_VERSION_10_1 = 2
|
||||
ATH10K_FW_WMI_OP_VERSION_10_2 = 3
|
||||
ATH10K_FW_WMI_OP_VERSION_TLV = 4
|
||||
ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5
|
||||
ATH10K_FW_WMI_OP_VERSION_10_4 = 6
|
||||
|
||||
wmi_op_version_map = {
|
||||
'unset': ATH10K_FW_WMI_OP_VERSION_UNSET,
|
||||
'main': ATH10K_FW_WMI_OP_VERSION_MAIN,
|
||||
'10.1': ATH10K_FW_WMI_OP_VERSION_10_1,
|
||||
'10.2': ATH10K_FW_WMI_OP_VERSION_10_2,
|
||||
'tlv': ATH10K_FW_WMI_OP_VERSION_TLV,
|
||||
'10.2.4': ATH10K_FW_WMI_OP_VERSION_10_2_4,
|
||||
'10.4': ATH10K_FW_WMI_OP_VERSION_10_4,
|
||||
}
|
||||
|
||||
|
||||
# from enum ath10k_fw_wmi_op_version in ath10k/hw.h
|
||||
ATH10K_FW_HTT_OP_VERSION_UNSET = 0
|
||||
ATH10K_FW_HTT_OP_VERSION_MAIN = 1
|
||||
ATH10K_FW_HTT_OP_VERSION_10_1 = 2
|
||||
ATH10K_FW_HTT_OP_VERSION_TLV = 3
|
||||
ATH10K_FW_HTT_OP_VERSION_10_4 = 4
|
||||
|
||||
htt_op_version_map = {
|
||||
'unset': ATH10K_FW_HTT_OP_VERSION_UNSET,
|
||||
'main': ATH10K_FW_HTT_OP_VERSION_MAIN,
|
||||
'10.1': ATH10K_FW_HTT_OP_VERSION_10_1,
|
||||
'tlv': ATH10K_FW_HTT_OP_VERSION_TLV,
|
||||
'10.4': ATH10K_FW_HTT_OP_VERSION_10_4,
|
||||
}
|
||||
|
||||
ETHTOOL_FWVERS_LEN = 32
|
||||
|
||||
# global variables
|
||||
logger = None
|
||||
|
||||
|
||||
class FWEncoderError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_output_name(fw_api=None):
|
||||
if fw_api is not None:
|
||||
api = fw_api
|
||||
else:
|
||||
api = DEFAULT_FW_API_VERSION
|
||||
|
||||
return 'firmware-%s.bin' % api
|
||||
|
||||
|
||||
class FirmwareContainer:
|
||||
|
||||
def add_element(self, type_id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
logger.debug('adding id %d len(value) %d'
|
||||
'padding_len %d' % (type_id,
|
||||
len(value),
|
||||
padding_len))
|
||||
fmt = '<ii%ds%ds' % (len(value), padding_len)
|
||||
struct.pack_into(fmt, self.buf, self.buf_len, type_id, len(value),
|
||||
value, padding.raw)
|
||||
self.buf_len = self.buf_len + 4 + 4 + len(value) + padding_len
|
||||
|
||||
def add_u32(self, type_id, value):
|
||||
if not type(value) is int:
|
||||
raise FWEncoderError('u32 IE %d is not int: %s' %
|
||||
(type_id, str(value)))
|
||||
|
||||
buf = ctypes.create_string_buffer(4)
|
||||
struct.pack_into("<i", buf, 0, value)
|
||||
self.add_element(type_id, buf.raw)
|
||||
|
||||
def read_u32(self, type_id):
|
||||
(val,) = struct.unpack_from("<i", self.elements[type_id])
|
||||
return val
|
||||
|
||||
def add_bitmap(self, ie, enabled, maximum):
|
||||
|
||||
if (max(enabled) >= maximum):
|
||||
logger.error("bitmap %d out of maximum (%d >= %d)" %
|
||||
(ie, max(enabled), maximum))
|
||||
return
|
||||
|
||||
bytes = [0] * maximum
|
||||
|
||||
for i in range(maximum):
|
||||
if i not in enabled:
|
||||
continue
|
||||
|
||||
max_set = i
|
||||
index = int(i / 8)
|
||||
bit = i % 8
|
||||
bytes[index] = bytes[index] | (1 << bit)
|
||||
|
||||
# remove trailing null bits away, that changing only
|
||||
# maximum doesn't affect created binary size
|
||||
length = int(math.ceil((max_set + 1) / float(8)))
|
||||
bytes = bytes[:length]
|
||||
|
||||
buf = ctypes.create_string_buffer(length)
|
||||
|
||||
for index in range(length):
|
||||
struct.pack_into('<B', buf, index, bytes[index])
|
||||
|
||||
self.add_element(ie, buf.raw)
|
||||
|
||||
def read_bitmap(self, ie):
|
||||
buf = self.elements[ie]
|
||||
length = len(buf)
|
||||
|
||||
bits = []
|
||||
|
||||
for index in range(length):
|
||||
val = struct.unpack_from('<B', buf, index)[0]
|
||||
|
||||
for bit in range(8):
|
||||
if val & 0x1:
|
||||
bits.append(index * 8 + bit)
|
||||
|
||||
val = val >> 1
|
||||
|
||||
return bits
|
||||
|
||||
def set_signature(self, signature):
|
||||
self.signature = signature
|
||||
self.signature_len = len(signature)
|
||||
|
||||
# include the null byte
|
||||
length = len(signature) + 1
|
||||
|
||||
padding_len = padding_needed(length)
|
||||
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
fmt = '<%dsb%ds' % (len(signature), padding_len)
|
||||
struct.pack_into(fmt, self.buf, 0, signature, 0, padding.raw)
|
||||
self.buf_len = length
|
||||
|
||||
def write(self, name):
|
||||
f = open(name, 'wb')
|
||||
f.write(self.buf.raw[:self.buf_len])
|
||||
f.close()
|
||||
|
||||
return self.buf_len
|
||||
|
||||
def open(self, name):
|
||||
f = open(name, 'rb')
|
||||
self.buf = f.read()
|
||||
self.buf_len = len(self.buf)
|
||||
f.close()
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (self.signature_len)
|
||||
(signature, null) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + self.signature_len + 1
|
||||
|
||||
if signature != self.signature or null != 0:
|
||||
logger.error("Invalid signature!")
|
||||
return False
|
||||
|
||||
offset = self.signature_len + 1
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements = {}
|
||||
|
||||
while offset + 4 + 4 < self.buf_len:
|
||||
(type_id, length) = struct.unpack_from("<ii", self.buf, offset)
|
||||
offset = offset + 4 + 4
|
||||
|
||||
if offset + length > self.buf_len:
|
||||
logger.error("Buffer too short")
|
||||
return
|
||||
|
||||
fmt = '<%ds' % length
|
||||
(payload,) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + length
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements[type_id] = payload
|
||||
|
||||
return True
|
||||
|
||||
def __init__(self, signature):
|
||||
self.buf = ctypes.create_string_buffer(MAX_LEN)
|
||||
self.buf_len = 0
|
||||
|
||||
self.set_signature(signature)
|
||||
|
||||
|
||||
class Ath10kFirmwareContainer(object):
|
||||
def _load_file(self, name):
|
||||
if os.path.getsize(name) > MAX_LEN:
|
||||
raise FWEncoderError('file %s is too large, maximum size is %d' %
|
||||
(name, MAX_LEN))
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
return buf
|
||||
|
||||
def set_fw_code_swap_image(self, fw_code_swap_image_name):
|
||||
self.fw_code_swap_image = self._load_file(fw_code_swap_image_name)
|
||||
|
||||
def get_fw_code_swap_image(self):
|
||||
return self.fw_code_swap_image
|
||||
|
||||
def set_htt_op_version(self, htt_op_version):
|
||||
s = htt_op_version
|
||||
|
||||
# convert the string to integer
|
||||
if s in htt_op_version_map:
|
||||
version = htt_op_version_map[s]
|
||||
elif is_int(s):
|
||||
version = s
|
||||
else:
|
||||
print('Error: Invalid HTT OP version: %s' % s)
|
||||
return 1
|
||||
|
||||
self.htt_op_version = version
|
||||
|
||||
def get_htt_op_version(self):
|
||||
version = self.htt_op_version
|
||||
|
||||
# find value from the dict
|
||||
try:
|
||||
name = [key for key, value in htt_op_version_map.items()
|
||||
if value == version][0]
|
||||
except IndexError:
|
||||
name = str(version)
|
||||
|
||||
return name
|
||||
|
||||
def set_wmi_op_version(self, wmi_op_version):
|
||||
s = wmi_op_version
|
||||
|
||||
# convert the string to integer
|
||||
if s in wmi_op_version_map:
|
||||
version = wmi_op_version_map[s]
|
||||
elif is_int(s):
|
||||
version = s
|
||||
else:
|
||||
print('Error: Invalid WMI OP version: %s' % s)
|
||||
return 1
|
||||
|
||||
self.wmi_op_version = version
|
||||
|
||||
def get_wmi_op_version(self):
|
||||
version = self.wmi_op_version
|
||||
|
||||
# find value from the dict
|
||||
try:
|
||||
name = [key for key, value in wmi_op_version_map.items()
|
||||
if value == version][0]
|
||||
except IndexError:
|
||||
name = str(version)
|
||||
|
||||
return name
|
||||
|
||||
def set_features(self, features):
|
||||
self.features = features.split(',')
|
||||
|
||||
enabled = []
|
||||
for capa in self.features:
|
||||
if capa not in feature_map:
|
||||
print("Error: '%s' not found from the feature map" % capa)
|
||||
return 1
|
||||
|
||||
enabled.append(feature_map[capa])
|
||||
|
||||
self.features_bitmap = enabled
|
||||
|
||||
def get_features(self):
|
||||
s = ""
|
||||
|
||||
if self.features_bitmap is None:
|
||||
return None
|
||||
|
||||
for capa in self.features_bitmap:
|
||||
# find value from the dict
|
||||
try:
|
||||
name = [key for key, value in feature_map.items()
|
||||
if value == capa][0]
|
||||
except IndexError:
|
||||
name = str(capa)
|
||||
|
||||
s = s + name + ","
|
||||
|
||||
# strip last comma
|
||||
if len(s) > 0:
|
||||
s = s[:-1]
|
||||
|
||||
return s
|
||||
|
||||
def set_fw_image(self, fw_image_name):
|
||||
self.fw_image = self._load_file(fw_image_name)
|
||||
|
||||
def get_fw_image(self):
|
||||
return self.fw_image
|
||||
|
||||
def set_otp_image(self, otp_image_name):
|
||||
self.otp_image = self._load_file(otp_image_name)
|
||||
|
||||
def get_otp_image(self):
|
||||
return self.otp_image
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self.timestamp = int(timestamp)
|
||||
|
||||
def get_timestamp(self):
|
||||
return self.timestamp
|
||||
|
||||
def get_timestamp_as_iso8601(self):
|
||||
if self.timestamp is None:
|
||||
return None
|
||||
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.gmtime(self.timestamp))
|
||||
|
||||
# fw_version must be a string
|
||||
def set_fw_version(self, fw_version):
|
||||
self.fw_version = fw_version
|
||||
# reserve one byte for null
|
||||
if len(self.fw_version) > ETHTOOL_FWVERS_LEN - 1:
|
||||
print('Firmware version string too long: %d' % (len(self.fw_version)))
|
||||
return 1
|
||||
|
||||
# returns a string
|
||||
def get_fw_version(self):
|
||||
return self.fw_version
|
||||
|
||||
def get_summary(self):
|
||||
s = ''
|
||||
|
||||
s = s + 'FileSize: %s\n' % (len(self.file))
|
||||
s = s + 'FileCRC32: %08x\n' % (_crc32(self.file))
|
||||
s = s + 'FileMD5: %s\n' % (hashlib.md5(self.file).hexdigest())
|
||||
|
||||
if self.get_fw_version():
|
||||
s = s + 'FirmwareVersion: %s\n' % (self.get_fw_version())
|
||||
|
||||
if self.get_timestamp():
|
||||
s = s + 'Timestamp: %s\n' % (self.get_timestamp_as_iso8601())
|
||||
|
||||
if self.get_features():
|
||||
s = s + 'Features: %s\n' % (self.get_features())
|
||||
|
||||
if self.get_fw_image():
|
||||
s = s + 'FirmwareImageSize: %s\n' % (len(self.get_fw_image()))
|
||||
s = s + 'FirmwareImageCRC32: %08x\n' % (_crc32(self.get_fw_image()))
|
||||
|
||||
if self.get_otp_image():
|
||||
s = s + 'OTPImageSize: %s\n' % (len(self.get_otp_image()))
|
||||
s = s + 'OTPImageCRC32: %08x\n' % (_crc32(self.get_otp_image()))
|
||||
|
||||
if self.get_wmi_op_version():
|
||||
s = s + 'WMIOpVersion: %s\n' % (self.get_wmi_op_version())
|
||||
|
||||
if self.get_htt_op_version():
|
||||
s = s + 'HTTOpVersion: %s\n' % (self.get_htt_op_version())
|
||||
|
||||
if self.get_fw_code_swap_image():
|
||||
s = s + 'FirmwareCodeSwapImageSize: %s\n' % (len(self.get_fw_code_swap_image()))
|
||||
s = s + 'FirmwareCodeSwapImageCRC32: %08x\n' % (_crc32(self.get_fw_code_swap_image()))
|
||||
|
||||
return s.strip()
|
||||
|
||||
def load(self, filename):
|
||||
c = FirmwareContainer(ATH10K_SIGNATURE)
|
||||
c.open(filename)
|
||||
|
||||
self.file = c.buf
|
||||
|
||||
for e in c.elements:
|
||||
if e == ATH10K_FW_IE_FW_VERSION:
|
||||
self.fw_version = c.elements[e].decode()
|
||||
elif e == ATH10K_FW_IE_TIMESTAMP:
|
||||
self.timestamp = c.read_u32(e)
|
||||
elif e == ATH10K_FW_IE_OTP_IMAGE:
|
||||
self.otp_image = c.elements[e]
|
||||
elif e == ATH10K_FW_IE_FW_IMAGE:
|
||||
self.fw_image = c.elements[e]
|
||||
elif e == ATH10K_FW_IE_FEATURES:
|
||||
self.features_bitmap = c.read_bitmap(ATH10K_FW_IE_FEATURES)
|
||||
elif e == ATH10K_FW_IE_WMI_OP_VERSION:
|
||||
self.wmi_op_version = c.read_u32(ATH10K_FW_IE_WMI_OP_VERSION)
|
||||
elif e == ATH10K_FW_IE_HTT_OP_VERSION:
|
||||
self.htt_op_version = c.read_u32(ATH10K_FW_IE_HTT_OP_VERSION)
|
||||
elif e == ATH10K_FW_IE_FW_CODE_SWAP_IMAGE:
|
||||
self.fw_code_swap_image = c.elements[e]
|
||||
else:
|
||||
print("Unknown IE: ", e)
|
||||
|
||||
def save(self, filename):
|
||||
self.container = FirmwareContainer(ATH10K_SIGNATURE)
|
||||
|
||||
if self.fw_version:
|
||||
self.container.add_element(ATH10K_FW_IE_FW_VERSION,
|
||||
self.fw_version.encode())
|
||||
if self.timestamp:
|
||||
self.container.add_u32(ATH10K_FW_IE_TIMESTAMP, self.timestamp)
|
||||
|
||||
# FIXME: otp should be after fw_image but that breaks the
|
||||
# current tests
|
||||
if self.otp_image:
|
||||
self.container.add_element(ATH10K_FW_IE_OTP_IMAGE, self.otp_image)
|
||||
|
||||
if self.fw_image:
|
||||
self.container.add_element(ATH10K_FW_IE_FW_IMAGE, self.fw_image)
|
||||
|
||||
# FIXME: features should be before fw_image but that breaks
|
||||
# the current tests
|
||||
if self.features_bitmap:
|
||||
self.container.add_bitmap(ATH10K_FW_IE_FEATURES,
|
||||
self.features_bitmap,
|
||||
ATH10K_FW_FEATURE_MAX)
|
||||
|
||||
if self.wmi_op_version:
|
||||
self.container.add_u32(ATH10K_FW_IE_WMI_OP_VERSION, self.wmi_op_version)
|
||||
|
||||
if self.htt_op_version:
|
||||
self.container.add_u32(ATH10K_FW_IE_HTT_OP_VERSION,
|
||||
self.htt_op_version)
|
||||
|
||||
if self.fw_code_swap_image:
|
||||
self.container.add_element(ATH10K_FW_IE_FW_CODE_SWAP_IMAGE,
|
||||
self.fw_code_swap_image)
|
||||
|
||||
return self.container.write(filename)
|
||||
|
||||
def __init__(self):
|
||||
self.fw_version = None
|
||||
self.timestamp = None
|
||||
self.features = None
|
||||
self.features_bitmap = None
|
||||
self.fw_image = None
|
||||
self.otp_image = None
|
||||
self.wmi_op_version = None
|
||||
self.htt_op_version = None
|
||||
self.fw_code_swap_image = None
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def padding_needed(length):
|
||||
if length % 4 != 0:
|
||||
return 4 - length % 4
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def is_int(val):
|
||||
try:
|
||||
int(val)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def write_file(filename, buf):
|
||||
f = open(filename, 'wb')
|
||||
f.write(buf)
|
||||
f.close
|
||||
|
||||
|
||||
def info(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath10kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print(c.get_summary())
|
||||
|
||||
|
||||
def dump(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath10kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print("ath10k-fwencoder --create \\")
|
||||
|
||||
if c.get_fw_version():
|
||||
print("--firmware-version=%s \\" % c.get_fw_version())
|
||||
|
||||
if c.get_timestamp() and options.show_timestamp:
|
||||
print("--timestamp=%u \\" % c.get_timestamp())
|
||||
|
||||
if c.get_features():
|
||||
print("--features=%s \\" % c.get_features())
|
||||
|
||||
if c.get_fw_image():
|
||||
name = "athwlan.bin"
|
||||
print("--firmware=%s \\" % name)
|
||||
|
||||
if c.get_otp_image():
|
||||
name = "otp.bin"
|
||||
print("--otp=%s \\" % name)
|
||||
|
||||
if c.get_wmi_op_version():
|
||||
print('--set-wmi-op-version=%s \\' % c.get_wmi_op_version())
|
||||
|
||||
if c.get_htt_op_version():
|
||||
print('--set-htt-op-version=%s \\' % (c.get_htt_op_version()))
|
||||
|
||||
if c.get_fw_code_swap_image():
|
||||
name = "athwlan.codeswap.bin"
|
||||
print("--firmware-codeswap=%s \\" % name)
|
||||
|
||||
print('')
|
||||
|
||||
|
||||
def extract(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath10kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if c.get_fw_image():
|
||||
name = "athwlan.bin"
|
||||
write_file(name, c.get_fw_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_fw_image())))
|
||||
|
||||
if c.get_otp_image():
|
||||
name = "otp.bin"
|
||||
write_file(name, c.get_otp_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_otp_image())))
|
||||
|
||||
if c.get_fw_code_swap_image():
|
||||
name = "athwlan.codeswap.bin"
|
||||
write_file(name, c.get_fw_code_swap_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_fw_code_swap_image())))
|
||||
|
||||
print('')
|
||||
|
||||
|
||||
def modify(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath10kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if options.firmware_version:
|
||||
c.set_fw_version(options.firmware_version)
|
||||
|
||||
if options.timestamp:
|
||||
stamp = str(int(options.timestamp))
|
||||
else:
|
||||
# if no timestamp provided use the current time so that the
|
||||
# timestamp shows the time of last modication
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.otp:
|
||||
c.set_otp_image(options.otp)
|
||||
|
||||
if options.fw:
|
||||
c.set_fw_image(options.fw)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
if options.wmi_op_version:
|
||||
c.set_wmi_op_version(options.wmi_op_version)
|
||||
|
||||
if options.htt_op_version:
|
||||
c.set_htt_op_version(options.htt_op_version)
|
||||
|
||||
if options.fw_codeswap:
|
||||
c.set_fw_code_swap_image(options.fw_codeswap)
|
||||
|
||||
file_len = c.save(filename)
|
||||
|
||||
print('%s modified: %d B' % (filename, file_len))
|
||||
|
||||
|
||||
def create(options):
|
||||
output = get_output_name(options.fw_api)
|
||||
|
||||
if options.output:
|
||||
output = options.output
|
||||
|
||||
c = Ath10kFirmwareContainer()
|
||||
|
||||
if options.firmware_version:
|
||||
c.set_fw_version(options.firmware_version)
|
||||
|
||||
# always add a timestamp
|
||||
if options.timestamp:
|
||||
stamp = int(options.timestamp)
|
||||
else:
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.otp:
|
||||
c.set_otp_image(options.otp)
|
||||
|
||||
if options.fw:
|
||||
c.set_fw_image(options.fw)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
if options.wmi_op_version:
|
||||
c.set_wmi_op_version(options.wmi_op_version)
|
||||
|
||||
if options.htt_op_version:
|
||||
c.set_htt_op_version(options.htt_op_version)
|
||||
|
||||
if options.fw_codeswap:
|
||||
c.set_fw_code_swap_image(options.fw_codeswap)
|
||||
|
||||
file_len = c.save(output)
|
||||
|
||||
print('%s created: %d B' % (output, file_len))
|
||||
|
||||
|
||||
def cmd_crc32(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
f = open(filename, 'rb')
|
||||
buf = f.read()
|
||||
print('%08x' % (_crc32(buf)))
|
||||
f.close()
|
||||
|
||||
|
||||
def cmd_diff(options, args):
|
||||
if len(args) != 2:
|
||||
print('Usage: ath10k-fwencoder --diff FILE FILE')
|
||||
return 1
|
||||
|
||||
filename1 = args[0]
|
||||
filename2 = args[1]
|
||||
|
||||
c1 = Ath10kFirmwareContainer()
|
||||
c1.load(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp1_pathname, 'w')
|
||||
f.write(c1.get_summary())
|
||||
f.close()
|
||||
|
||||
c2 = Ath10kFirmwareContainer()
|
||||
c2.load(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp2_pathname, 'w')
|
||||
f.write(c2.get_summary())
|
||||
f.close()
|
||||
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
logger.error('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
logger.error('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
print(output)
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
|
||||
def main():
|
||||
global logger
|
||||
|
||||
logger = logging.getLogger('ath10k-fwencoder')
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s')
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
# actions
|
||||
parser.add_option("-c", "--create", action="store_true", dest="create",
|
||||
help='Create container file '
|
||||
'for ath10k (%s)' % get_output_name())
|
||||
parser.add_option("-D", "--dump-cmdline", action="store_true", dest="dump",
|
||||
help='Show the cmdline used to create '
|
||||
'this container file')
|
||||
parser.add_option('--dump', action='store_true', dest='dump',
|
||||
help='Same as --dump-cmdline '
|
||||
'(for backwards compatibility)')
|
||||
parser.add_option("-e", "--extract", action="store_true", dest="extract",
|
||||
help='Extract binary files from the container file '
|
||||
'and dump cmdline as well')
|
||||
parser.add_option("--info", action="store_true", dest="info",
|
||||
help='Show information about the container file')
|
||||
parser.add_option("--modify", action="store_true", dest="modify",
|
||||
help='Modify the container file')
|
||||
parser.add_option('--crc32', action='store_true', dest='crc32',
|
||||
help='Count crc32 checksum for a file')
|
||||
parser.add_option('--diff', action='store_true', dest='diff',
|
||||
help='Show differences between two firmware files')
|
||||
|
||||
# parameters
|
||||
parser.add_option("-o", "--output", action="store", type="string",
|
||||
dest="output", help='Name of output file')
|
||||
|
||||
# FW IEs, only use long style of option names!
|
||||
parser.add_option("--otp", action="store", type="string",
|
||||
dest="otp",
|
||||
help='Name of otp.bin file')
|
||||
parser.add_option("--firmware", action="store", type="string",
|
||||
dest="fw",
|
||||
help='Name of athwlan.bin file')
|
||||
parser.add_option("--firmware-version", action="store",
|
||||
type="string", dest="firmware_version",
|
||||
help='Firmware version string to be used')
|
||||
parser.add_option("--timestamp", action="store",
|
||||
type="string", dest="timestamp",
|
||||
help='Timestamp to be used (seconds)')
|
||||
|
||||
parser.add_option("--features", action="store",
|
||||
type="string", dest="features",
|
||||
help='feature bits to be enabled: %s' %
|
||||
feature_map.keys())
|
||||
parser.add_option("--set-wmi-op-version", action="store",
|
||||
type="string", dest="wmi_op_version",
|
||||
help='WMI op interface version: %s' %
|
||||
wmi_op_version_map.keys())
|
||||
parser.add_option("--set-fw-api", action="store",
|
||||
type="string", dest="fw_api",
|
||||
help='Set firmware API used in creating the name for '
|
||||
'output file (Default: %s)' %
|
||||
DEFAULT_FW_API_VERSION)
|
||||
parser.add_option("--set-htt-op-version", action="store",
|
||||
type="string", dest="htt_op_version",
|
||||
help='HTT op interface version: %s' %
|
||||
htt_op_version_map.keys())
|
||||
parser.add_option("--firmware-codeswap", action="store", type="string",
|
||||
dest="fw_codeswap",
|
||||
help='Name of athwlan.codeswap.bin file')
|
||||
|
||||
# debug etc
|
||||
parser.add_option('--show-timestamp', action='store_true',
|
||||
dest='show_timestamp',
|
||||
help='Show timestamp in --dump-cmdline action. '
|
||||
'It is not shown by default so that the timestamp would be correct')
|
||||
parser.add_option('-d', '--debug', action='store_true', dest='debug',
|
||||
help='Enable debug messages')
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if options.create:
|
||||
try:
|
||||
return create(options)
|
||||
except FWEncoderError as e:
|
||||
print('Create failed: %s' % e)
|
||||
sys.exit(2)
|
||||
except Exception as e:
|
||||
print('Create failed: %s' % e)
|
||||
traceback.print_exc()
|
||||
sys.exit(3)
|
||||
elif options.dump:
|
||||
return dump(options, args)
|
||||
elif options.extract:
|
||||
return extract(options, args)
|
||||
elif options.info:
|
||||
return info(options, args)
|
||||
elif options.modify:
|
||||
return modify(options, args)
|
||||
elif options.crc32:
|
||||
return cmd_crc32(options, args)
|
||||
elif options.diff:
|
||||
return cmd_diff(options, args)
|
||||
else:
|
||||
print('Action command missing')
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
862
tools/scripts/ath11k/ath11k-bdencoder
Executable file
862
tools/scripts/ath11k/ath11k-bdencoder
Executable file
|
|
@ -0,0 +1,862 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# Run 'ath11k-bdencoder --help' to see the instructions
|
||||
#
|
||||
|
||||
import struct
|
||||
import ctypes
|
||||
import os.path
|
||||
import argparse
|
||||
import json
|
||||
import binascii
|
||||
import hashlib
|
||||
import tempfile
|
||||
import subprocess
|
||||
import logging
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
MAX_BUF_LEN = 20000000
|
||||
|
||||
# the signature length also includes null byte and padding
|
||||
ATH11K_BOARD_SIGNATURE = b"QCA-ATH11K-BOARD"
|
||||
ATH11K_BOARD_SIGNATURE_LEN = 20
|
||||
|
||||
PADDING_MAGIC = 0x6d
|
||||
DEFAULT_BD_API = 2
|
||||
DEFAULT_BOARD_FILE = 'board-%d.bin' % DEFAULT_BD_API
|
||||
DEFAULT_JSON_FILE = 'board-%d.json' % DEFAULT_BD_API
|
||||
TYPE_LENGTH_SIZE = 8
|
||||
|
||||
ATH11K_BD_IE_BOARD = 0
|
||||
ATH11K_BD_IE_REGDB = 1
|
||||
|
||||
ATH11K_BD_IE_BOARD_NAME = 0
|
||||
ATH11K_BD_IE_BOARD_DATA = 1
|
||||
|
||||
ATH11K_BD_IE_REGDB_NAME = 0
|
||||
ATH11K_BD_IE_REGDB_DATA = 1
|
||||
|
||||
|
||||
def padding_needed(len):
|
||||
if len % 4 != 0:
|
||||
return 4 - len % 4
|
||||
return 0
|
||||
|
||||
|
||||
def add_ie(buf, offset, id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<2i%ds%ds' % (len(value), padding_len)
|
||||
struct.pack_into(fmt, buf, offset, id, len(value), value, padding.raw)
|
||||
offset = offset + TYPE_LENGTH_SIZE + len(value) + padding_len
|
||||
|
||||
return offset
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def pretty_array_str(array):
|
||||
return '\',\''.join(array)
|
||||
|
||||
|
||||
class RegdbName():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = RegdbName()
|
||||
fmt = '<%ds' % length
|
||||
(name, ) = struct.unpack_from(fmt, buf, offset)
|
||||
self.name = name.decode()
|
||||
|
||||
logging.debug('RegdbName.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH11K_BD_IE_REGDB_NAME, self.name.encode())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'RegdbName(%s)' % self.name
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
||||
|
||||
class RegdbData():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = RegdbData()
|
||||
fmt = '<%ds' % length
|
||||
(self.data, ) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
logging.debug('RegdbData.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH11K_BD_IE_REGDB_DATA, self.data)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.data is not None:
|
||||
s = '%d B' % (len(self.data))
|
||||
else:
|
||||
s = 'n/a'
|
||||
|
||||
return 'RegdbData(%s)' % (s)
|
||||
|
||||
def __init__(self, data=None):
|
||||
self.data = data
|
||||
|
||||
|
||||
class Regdb():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
logging.debug('Regdb.parse_ie(): offset %d length %d' % (offset, length))
|
||||
|
||||
self = Regdb()
|
||||
|
||||
# looping regdb IEs
|
||||
while length > 0:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
|
||||
logging.debug('Regdb.parse_ie(): found ie_id %d ie_len %d offset %d length %d' %
|
||||
(ie_id, ie_len, offset, length))
|
||||
|
||||
if TYPE_LENGTH_SIZE + ie_len > length:
|
||||
raise Exception('Error: ie_len too big (%d > %d)' % (ie_len,
|
||||
length))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
length -= TYPE_LENGTH_SIZE
|
||||
|
||||
if ie_id == ATH11K_BD_IE_REGDB_NAME:
|
||||
self.names.append(RegdbName.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH11K_BD_IE_REGDB_DATA:
|
||||
self.data = RegdbData.parse_ie(buf, offset, ie_len)
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
length -= ie_len + padding_needed(ie_len)
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
# store position ie header of this element
|
||||
ie_offset = offset
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
for name in self.names:
|
||||
offset = name.add_to_buf(buf, offset)
|
||||
|
||||
offset = self.data.add_to_buf(buf, offset)
|
||||
|
||||
# write ie header as now we know the full length
|
||||
ie_len = offset - ie_offset - TYPE_LENGTH_SIZE
|
||||
struct.pack_into('<2i', buf, ie_offset, ATH11K_BD_IE_REGDB, ie_len)
|
||||
|
||||
return offset
|
||||
|
||||
def get_names_as_str(self):
|
||||
names = []
|
||||
for regdbname in self.names:
|
||||
names.append(regdbname.name)
|
||||
|
||||
return names
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
names = []
|
||||
for regdbname in self.names:
|
||||
names.append(str(regdbname))
|
||||
|
||||
return 'Regdb(%s, %s)' % (','.join(names), self.data)
|
||||
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.names = []
|
||||
|
||||
|
||||
class BoardName():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardName()
|
||||
fmt = '<%ds' % length
|
||||
(name, ) = struct.unpack_from(fmt, buf, offset)
|
||||
self.name = name.decode()
|
||||
|
||||
logging.debug('BoardName.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH11K_BD_IE_BOARD_NAME, self.name.encode())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'BoardName(%s)' % self.name
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
||||
|
||||
class BoardData():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardData()
|
||||
fmt = '<%ds' % length
|
||||
(self.data, ) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
logging.debug('BoardData.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH11K_BD_IE_BOARD_DATA, self.data)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.data is not None:
|
||||
s = '%d B' % (len(self.data))
|
||||
else:
|
||||
s = 'n/a'
|
||||
|
||||
return 'BoardData(%s)' % (s)
|
||||
|
||||
def __init__(self, data=None):
|
||||
self.data = data
|
||||
|
||||
|
||||
class Board():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
logging.debug('Board.parse_ie(): offset %d length %d' % (offset, length))
|
||||
|
||||
self = Board()
|
||||
|
||||
# looping board IEs
|
||||
while length > 0:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
|
||||
logging.debug('Board.parse_ie(): found ie_id %d ie_len %d offset %d length %d' %
|
||||
(ie_id, ie_len, offset, length))
|
||||
|
||||
if TYPE_LENGTH_SIZE + ie_len > length:
|
||||
raise Exception('Error: ie_len too big (%d > %d)' % (ie_len,
|
||||
length))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
length -= TYPE_LENGTH_SIZE
|
||||
|
||||
if ie_id == ATH11K_BD_IE_BOARD_NAME:
|
||||
self.names.append(BoardName.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH11K_BD_IE_BOARD_DATA:
|
||||
self.data = BoardData.parse_ie(buf, offset, ie_len)
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
length -= ie_len + padding_needed(ie_len)
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
# store position ie header of this element
|
||||
ie_offset = offset
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
for name in self.names:
|
||||
offset = name.add_to_buf(buf, offset)
|
||||
|
||||
offset = self.data.add_to_buf(buf, offset)
|
||||
|
||||
# write ie header as now we know the full length
|
||||
ie_len = offset - ie_offset - TYPE_LENGTH_SIZE
|
||||
struct.pack_into('<2i', buf, ie_offset, ATH11K_BD_IE_BOARD, ie_len)
|
||||
|
||||
return offset
|
||||
|
||||
def get_names_as_str(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(boardname.name)
|
||||
|
||||
return names
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(str(boardname))
|
||||
|
||||
return 'Board(%s, %s)' % (','.join(names), self.data)
|
||||
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.names = []
|
||||
|
||||
|
||||
class BoardContainer:
|
||||
|
||||
def add_board(self, data, names):
|
||||
boardnames = []
|
||||
for name in names:
|
||||
boardnames.append(BoardName(name))
|
||||
|
||||
board = Board()
|
||||
board.data = BoardData(data)
|
||||
board.names = boardnames
|
||||
|
||||
self.boards.append(board)
|
||||
|
||||
def add_regdb(self, data, names):
|
||||
regdbnames = []
|
||||
for name in names:
|
||||
regdbnames.append(RegdbName(name))
|
||||
|
||||
regdb = Regdb()
|
||||
regdb.data = RegdbData(data)
|
||||
regdb.names = regdbnames
|
||||
|
||||
self.regdbs.append(regdb)
|
||||
|
||||
@staticmethod
|
||||
def open_json(filename):
|
||||
self = BoardContainer()
|
||||
|
||||
if not os.path.exists(filename):
|
||||
print('mapping file %s not found' % (filename))
|
||||
return
|
||||
|
||||
f = open(filename, 'r')
|
||||
mapping = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
if 'board' in mapping[0]:
|
||||
for b in mapping[0]['board']:
|
||||
board_filename = b['data']
|
||||
f = open(board_filename, 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
self.add_board(data, b['names'])
|
||||
|
||||
if 'regdb' in mapping[0]:
|
||||
for b in mapping[0]['regdb']:
|
||||
regdb_filename = b['data']
|
||||
f = open(regdb_filename, 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
self.add_regdb(data, b['names'])
|
||||
|
||||
return self
|
||||
|
||||
def validate(self):
|
||||
allnames = []
|
||||
|
||||
for board in self.boards:
|
||||
for name in board.names:
|
||||
if name in allnames:
|
||||
# TODO: Find a better way to report problems,
|
||||
# maybe return a list of strings? Or use an
|
||||
# exception?
|
||||
print('Warning: duplicate board name: %s' % (name.name))
|
||||
return
|
||||
|
||||
allnames.append(name)
|
||||
|
||||
def _add_signature(self, buf, offset):
|
||||
signature = ATH11K_BOARD_SIGNATURE + b'\0'
|
||||
length = len(signature)
|
||||
pad_len = padding_needed(length)
|
||||
length = length + pad_len
|
||||
|
||||
padding = ctypes.create_string_buffer(pad_len)
|
||||
|
||||
for i in range(pad_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<%ds%ds' % (len(signature), pad_len)
|
||||
struct.pack_into(fmt, buf, offset, signature, padding.raw)
|
||||
offset += length
|
||||
|
||||
# make sure ATH11K_BOARD_SIGNATURE_LEN is correct
|
||||
assert ATH11K_BOARD_SIGNATURE_LEN == length
|
||||
|
||||
return offset
|
||||
|
||||
@staticmethod
|
||||
def open(name):
|
||||
self = BoardContainer()
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
buf_len = len(buf)
|
||||
|
||||
logging.debug('BoardContainer.open(): name %s' % (name))
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (len(ATH11K_BOARD_SIGNATURE))
|
||||
(signature, null) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
if signature != ATH11K_BOARD_SIGNATURE or null != 0:
|
||||
print("invalid signature found in %s" % name)
|
||||
return 1
|
||||
|
||||
offset += ATH11K_BOARD_SIGNATURE_LEN
|
||||
|
||||
# looping main IEs
|
||||
while offset < buf_len:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
logging.debug('BoardContainer.open(): found offset %d ie_id %d ie_len %d' %
|
||||
(offset, ie_id, ie_len))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
if offset + ie_len > buf_len:
|
||||
print('Error: Buffer too short (%d + %d > %d)' % (offset,
|
||||
ie_len,
|
||||
buf_len))
|
||||
return 1
|
||||
|
||||
if ie_id == ATH11K_BD_IE_BOARD:
|
||||
self.boards.append(Board.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH11K_BD_IE_REGDB:
|
||||
self.regdbs.append(Regdb.parse_ie(buf, offset, ie_len))
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
|
||||
self.validate()
|
||||
|
||||
return self
|
||||
|
||||
def write(self, name):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
fd = open(name, 'wb')
|
||||
fd.write(buf.raw[0:buf_len])
|
||||
fd.close()
|
||||
|
||||
self.validate()
|
||||
|
||||
print("board binary file '%s' is created" % name)
|
||||
|
||||
def get_bin(self):
|
||||
buf = ctypes.create_string_buffer(MAX_BUF_LEN)
|
||||
offset = 0
|
||||
|
||||
offset = self._add_signature(buf, offset)
|
||||
|
||||
for board in self.boards:
|
||||
offset = board.add_to_buf(buf, offset)
|
||||
|
||||
for regdb in self.regdbs:
|
||||
offset = regdb.add_to_buf(buf, offset)
|
||||
|
||||
# returns buffer and it's length
|
||||
return buf, offset
|
||||
|
||||
def get_summary(self, sort=False):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
s = ''
|
||||
|
||||
s += 'FileSize: %d\n' % (buf_len)
|
||||
s += 'FileCRC32: %08x\n' % (_crc32(buf[0:buf_len]))
|
||||
s += 'FileMD5: %s\n' % (hashlib.md5(buf[0:buf_len]).hexdigest())
|
||||
|
||||
boards = self.boards
|
||||
|
||||
if sort:
|
||||
boards = sorted(boards, key=lambda board: board.get_names_as_str())
|
||||
|
||||
index = 0
|
||||
for board in boards:
|
||||
if not sort:
|
||||
index_s = '[%d]' % (index)
|
||||
else:
|
||||
index_s = ''
|
||||
|
||||
s += 'BoardNames%s: \'%s\'\n' % (index_s, pretty_array_str(board.get_names_as_str()))
|
||||
s += 'BoardLength%s: %d\n' % (index_s, len(board.data.data))
|
||||
s += 'BoardCRC32%s: %08x\n' % (index_s, _crc32(board.data.data))
|
||||
s += 'BoardMD5%s: %s\n' % (index_s, hashlib.md5(board.data.data).hexdigest())
|
||||
index += 1
|
||||
|
||||
regdbs = self.regdbs
|
||||
|
||||
if sort:
|
||||
regdbs = sorted(regdbs, key=lambda regdb: regdb.get_names_as_str())
|
||||
|
||||
index = 0
|
||||
for regdb in regdbs:
|
||||
if not sort:
|
||||
index_s = '[%d]' % (index)
|
||||
else:
|
||||
index_s = ''
|
||||
|
||||
s += 'RegdbNames%s: \'%s\'\n' % (index_s, pretty_array_str(regdb.get_names_as_str()))
|
||||
s += 'RegdbLength%s: %d\n' % (index_s, len(regdb.data.data))
|
||||
s += 'RegdbCRC32%s: %08x\n' % (index_s, _crc32(regdb.data.data))
|
||||
s += 'RegdbMD5%s: %s\n' % (index_s, hashlib.md5(regdb.data.data).hexdigest())
|
||||
index += 1
|
||||
|
||||
return s
|
||||
|
||||
def __init__(self):
|
||||
self.boards = []
|
||||
self.regdbs = []
|
||||
|
||||
|
||||
def cmd_extract(args):
|
||||
cont = BoardContainer().open(args.extract)
|
||||
|
||||
mapping = []
|
||||
d = {}
|
||||
mapping.append(d)
|
||||
|
||||
mapping_board = []
|
||||
d['board'] = mapping_board
|
||||
|
||||
for board in cont.boards:
|
||||
filename = board.names[0].name + '.bin'
|
||||
|
||||
b = {}
|
||||
b['names'] = board.get_names_as_str()
|
||||
b['data'] = filename
|
||||
mapping_board.append(b)
|
||||
|
||||
f = open(filename, 'wb')
|
||||
f.write(board.data.data)
|
||||
f.close()
|
||||
|
||||
print("%s created size: %d" % (filename, len(board.data.data)))
|
||||
|
||||
mapping_regdb = []
|
||||
d['regdb'] = mapping_regdb
|
||||
|
||||
for regdb in cont.regdbs:
|
||||
filename = regdb.names[0].name + '.regdb'
|
||||
|
||||
b = {}
|
||||
b['names'] = regdb.get_names_as_str()
|
||||
b['data'] = filename
|
||||
mapping_regdb.append(b)
|
||||
|
||||
f = open(filename, 'wb')
|
||||
f.write(regdb.data.data)
|
||||
f.close()
|
||||
|
||||
print("%s created size: %d" % (filename, len(regdb.data.data)))
|
||||
|
||||
filename = DEFAULT_JSON_FILE
|
||||
f = open(filename, 'w')
|
||||
f.write(json.dumps(mapping, indent=4))
|
||||
f.close()
|
||||
|
||||
print("%s created" % (filename))
|
||||
|
||||
|
||||
def cmd_info(args):
|
||||
filename = args.info
|
||||
|
||||
cont = BoardContainer().open(filename)
|
||||
|
||||
print(cont.get_summary())
|
||||
|
||||
|
||||
def cmd_diff(args):
|
||||
if args.diff:
|
||||
filename1 = args.diff[0]
|
||||
filename2 = args.diff[1]
|
||||
else:
|
||||
filename1 = args.diffstat[0]
|
||||
filename2 = args.diffstat[1]
|
||||
|
||||
print(diff_boardfiles(filename1, filename2, args.diff))
|
||||
|
||||
|
||||
def diff_boardfiles(filename1, filename2, diff):
|
||||
result = ''
|
||||
|
||||
container1 = BoardContainer().open(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp()
|
||||
os.write(temp1_fd, container1.get_summary(sort=True).encode())
|
||||
|
||||
container2 = BoardContainer().open(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp()
|
||||
os.write(temp2_fd, container2.get_summary(sort=True).encode())
|
||||
|
||||
# this function is used both with --diff and --diffstat
|
||||
if diff:
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
print('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
print('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
result += '%s\n' % (output.decode())
|
||||
|
||||
# create simple statistics about changes in board images
|
||||
new_boards = {}
|
||||
deleted_boards = {}
|
||||
changed_boards = {}
|
||||
|
||||
for board in container2.boards:
|
||||
# convert the list to a string
|
||||
s = pretty_array_str(board.get_names_as_str())
|
||||
new_boards[s] = board
|
||||
|
||||
for board in container1.boards:
|
||||
# convert the list to a string
|
||||
names = pretty_array_str(board.get_names_as_str())
|
||||
|
||||
if names not in new_boards:
|
||||
# board image has been deleted
|
||||
deleted_boards[names] = board
|
||||
continue
|
||||
|
||||
board2 = new_boards[names]
|
||||
del new_boards[names]
|
||||
|
||||
if board.data.data == board2.data.data:
|
||||
# board image hasn't changed
|
||||
continue
|
||||
|
||||
# board image has changed
|
||||
changed_boards[names] = board2
|
||||
|
||||
result += 'New board:\n%s\n\n' % ('\n'.join(list(new_boards.keys())))
|
||||
result += 'Changed board:\n%s\n\n' % ('\n'.join(list(changed_boards.keys())))
|
||||
result += 'Deleted board:\n%s\n' % ('\n'.join(list(deleted_boards.keys())))
|
||||
|
||||
result += '%d board image(s) added, %d changed, %d deleted, %d in total\n\n' % (len(new_boards),
|
||||
len(changed_boards),
|
||||
len(deleted_boards),
|
||||
len(container2.boards))
|
||||
|
||||
# create simple statistics about changes in regdb images
|
||||
new_regdbs = {}
|
||||
deleted_regdbs = {}
|
||||
changed_regdbs = {}
|
||||
|
||||
for regdb in container2.regdbs:
|
||||
# convert the list to a string
|
||||
s = pretty_array_str(regdb.get_names_as_str())
|
||||
new_regdbs[s] = regdb
|
||||
|
||||
for regdb in container1.regdbs:
|
||||
# convert the list to a string
|
||||
names = pretty_array_str(regdb.get_names_as_str())
|
||||
|
||||
if names not in new_regdbs:
|
||||
# regdb image has been deleted
|
||||
deleted_regdbs[names] = regdb
|
||||
continue
|
||||
|
||||
regdb2 = new_regdbs[names]
|
||||
del new_regdbs[names]
|
||||
|
||||
if regdb.data.data == regdb2.data.data:
|
||||
# regdb image hasn't changed
|
||||
continue
|
||||
|
||||
# regdb image has changed
|
||||
changed_regdbs[names] = regdb2
|
||||
|
||||
result += 'New regdb:\n%s\n\n' % ('\n'.join(list(new_regdbs.keys())))
|
||||
result += 'Changed regdb:\n%s\n\n' % ('\n'.join(list(changed_regdbs.keys())))
|
||||
result += 'Deleted regdb:\n%s\n' % ('\n'.join(list(deleted_regdbs.keys())))
|
||||
|
||||
result += '%d regdb image(s) added, %d changed, %d deleted, %d in total' % (len(new_regdbs),
|
||||
len(changed_regdbs),
|
||||
len(deleted_regdbs),
|
||||
len(container2.regdbs))
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def cmd_create(args):
|
||||
mapping_file = args.create
|
||||
|
||||
if args.output:
|
||||
output = args.output
|
||||
else:
|
||||
output = DEFAULT_BOARD_FILE
|
||||
|
||||
cont = BoardContainer.open_json(mapping_file)
|
||||
cont.write(output)
|
||||
|
||||
|
||||
def cmd_add_board(args):
|
||||
if len(args.add_board) < 3:
|
||||
print('error: --add-board requires 3 or more arguments, only %d given' % (len(args.add_board)))
|
||||
sys.exit(1)
|
||||
|
||||
board_filename = args.add_board[0]
|
||||
new_filename = args.add_board[1]
|
||||
new_names = args.add_board[2:]
|
||||
|
||||
f = open(new_filename, 'rb')
|
||||
new_data = f.read()
|
||||
f.close()
|
||||
|
||||
# copy the original file for diff
|
||||
(temp_fd, temp_pathname) = tempfile.mkstemp()
|
||||
shutil.copyfile(board_filename, temp_pathname)
|
||||
|
||||
container = BoardContainer.open(board_filename)
|
||||
container.add_board(new_data, new_names)
|
||||
container.write(board_filename)
|
||||
|
||||
print(diff_boardfiles(temp_pathname, board_filename, False))
|
||||
|
||||
os.remove(temp_pathname)
|
||||
|
||||
|
||||
def main():
|
||||
description = '''ath11k board-N.bin files manegement tool
|
||||
|
||||
ath11k-bdencoder is for creating (--create), listing (--info) and
|
||||
comparing (--diff, --diffstat) ath11k board-N.bin files. The
|
||||
board-N.bin is a container format which can have unlimited number of
|
||||
actual board images ("board files"), each image containing one or
|
||||
names which ath11k uses to find the correct image.
|
||||
|
||||
For creating board files you need a mapping file in JSON which
|
||||
contains the names and filenames for the actual binary:
|
||||
|
||||
[
|
||||
{
|
||||
"board": [
|
||||
{"names": ["AAA1", "AAAA2"], "data": "A.bin"},
|
||||
{"names": ["B"], "data": "B.bin"},
|
||||
{"names": ["C"], "data": "C.bin"},
|
||||
],
|
||||
"regdb": [
|
||||
{"names": ["A"], "data": "A.regdb"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
In this example the board-N.bin will contain three board files which
|
||||
are read from files named A.bin (using names AAA1 and AAAA2 in the
|
||||
board-N.bin file), B.bin (using name B) and C.bin (using name C). The file also contains one regdb (regulatory database) from file A.regdb.
|
||||
|
||||
You can use --extract switch to see examples from real board-N.bin
|
||||
files.
|
||||
'''
|
||||
|
||||
parser = argparse.ArgumentParser(description=description,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
cmd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
cmd_group.add_argument("-c", "--create", metavar='JSON_FILE',
|
||||
help='create board-N.bin from a mapping file in JSON format')
|
||||
cmd_group.add_argument("-e", "--extract", metavar='BOARD_FILE',
|
||||
help='extract board-N.bin file to a JSON mapping file and individual board files, compatible with the format used with --create command')
|
||||
cmd_group.add_argument("-i", "--info", metavar='BOARD_FILE',
|
||||
help='show all details about a board-N.bin file')
|
||||
cmd_group.add_argument('-d', '--diff', metavar='BOARD_FILE', nargs=2,
|
||||
help='show differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-D', '--diffstat', metavar='BOARD_FILE', nargs=2,
|
||||
help='show a summary of differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-a', '--add-board', metavar='NAME', nargs='+',
|
||||
help='add a board file to an existing board-N.bin, first argument is the filename of board-N.bin to add to, second is the filename board file (board.bin) to add and then followed by one or more arguments are names used in board-N.bin')
|
||||
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='enable verbose (debug) messages')
|
||||
parser.add_argument("-o", "--output", metavar="BOARD_FILE",
|
||||
help='name of the output file, otherwise the default is: %s' %
|
||||
(DEFAULT_BOARD_FILE))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if args.create:
|
||||
return cmd_create(args)
|
||||
elif args.extract:
|
||||
return cmd_extract(args)
|
||||
elif args.info:
|
||||
return cmd_info(args)
|
||||
elif args.diff:
|
||||
return cmd_diff(args)
|
||||
elif args.diffstat:
|
||||
return cmd_diff(args)
|
||||
elif args.add_board:
|
||||
return cmd_add_board(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
529
tools/scripts/ath11k/ath11k-check
Executable file
529
tools/scripts/ath11k/ath11k-check
Executable file
|
|
@ -0,0 +1,529 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# Run 'ath11k-check --help' to see the instructions
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
import tempfile
|
||||
import queue
|
||||
import threading
|
||||
import string
|
||||
import hashlib
|
||||
import shutil
|
||||
|
||||
CHECKPATCH_COMMIT = '99b70ece33d87500ef7bee8e32cb99772c45ce14'
|
||||
CHECKPATCH_MD5SUM = 'b3c97930952745672f3408dabc244843'
|
||||
|
||||
GIT_URL = 'https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl?id=%s'
|
||||
|
||||
DRIVER_DIR = 'drivers/net/wireless/ath/ath11k/'
|
||||
|
||||
FILTER_REGEXP = r'/ath'
|
||||
|
||||
IGNORE_FILES = []
|
||||
|
||||
CHECKPATCH_IGNORE = ['MSLEEP',
|
||||
'USLEEP_RANGE',
|
||||
'PRINTK_WITHOUT_KERN_LEVEL',
|
||||
|
||||
# ath10k does not follow networking comment style
|
||||
'NETWORKING_BLOCK_COMMENT_STYLE',
|
||||
|
||||
'LINUX_VERSION_CODE',
|
||||
'COMPLEX_MACRO',
|
||||
'PREFER_DEV_LEVEL',
|
||||
'PREFER_PR_LEVEL',
|
||||
'COMPARISON_TO_NULL',
|
||||
'BIT_MACRO',
|
||||
'CONSTANT_COMPARISON',
|
||||
'MACRO_WITH_FLOW_CONTROL',
|
||||
|
||||
# Spams hundreds of lines useless 'struct should
|
||||
# normally be const' warnings, maybe a bug in
|
||||
# checkpatch?
|
||||
'CONST_STRUCT',
|
||||
|
||||
# TODO: look like valid warnings, investigate
|
||||
'MACRO_ARG_REUSE',
|
||||
'OPEN_ENDED_LINE',
|
||||
'FUNCTION_ARGUMENTS',
|
||||
'CONFIG_DESCRIPTION',
|
||||
'ASSIGNMENT_CONTINUATIONS',
|
||||
'UNNECESSARY_PARENTHESES',
|
||||
|
||||
# Not sure if these really useful warnings,
|
||||
# disable for now.
|
||||
'MACRO_ARG_PRECEDENCE',
|
||||
|
||||
'BOOL_MEMBER',
|
||||
|
||||
# TODO: ath11k uses volatile for now, fix it
|
||||
'VOLATILE',
|
||||
|
||||
# TODO: document all DT usage in ath11k
|
||||
'UNDOCUMENTED_DT_STRING',
|
||||
]
|
||||
|
||||
CHECKPATCH_OPTS = ['--strict', '-q', '--terse', '--no-summary',
|
||||
'--max-line-length=90', '--show-types']
|
||||
|
||||
checkpatch_filter = [
|
||||
('ath11k_read_simulate_fw_crash', 'LONG_LINE'),
|
||||
('qmi_wlanfw_respond_mem_req_msg_v01', 'LONG_LINE'),
|
||||
('DEFINE_EVENT', 'MACRO_ARG_UNUSED'),
|
||||
]
|
||||
|
||||
sparse_filter = [
|
||||
r'warning: dubious: x & !y',
|
||||
# sparse doesn't correctly handle guard()
|
||||
r'warning: context imbalance in .* - wrong count at exit',
|
||||
]
|
||||
|
||||
# global variables
|
||||
|
||||
logger = logging.getLogger('ath11k-check')
|
||||
|
||||
threads = 1
|
||||
|
||||
|
||||
class CPWarning():
|
||||
|
||||
def __str__(self):
|
||||
return 'CPWarning(%s, %s, %s, %s, %s)' % (self.path, self.lineno,
|
||||
self.tag, self.type,
|
||||
self.msg)
|
||||
|
||||
def __init__(self):
|
||||
self.path = ''
|
||||
self.lineno = ''
|
||||
self.type = ''
|
||||
self.msg = ''
|
||||
self.tag = ''
|
||||
|
||||
|
||||
def run_gcc(args):
|
||||
# to disable utf-8 from gcc, easier to paste that way
|
||||
os.environ['LC_CTYPE'] = 'C'
|
||||
|
||||
cmd = 'rm -f %s/*.o' % (DRIVER_DIR)
|
||||
logger.debug('%s' % cmd)
|
||||
subprocess.call(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
cmd = ['make', '-k', '-j', str(threads)]
|
||||
|
||||
if not args.no_extra:
|
||||
cmd.append('W=1')
|
||||
|
||||
cmd.append(DRIVER_DIR)
|
||||
|
||||
env = os.environ.copy()
|
||||
|
||||
# disable ccache in case it's in use, it's useless as we are
|
||||
# compiling only few files and it also breaks GCC's
|
||||
# -Wimplicit-fallthrough check
|
||||
env['CCACHE_DISABLE'] = '1'
|
||||
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=env, universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def run_sparse(args):
|
||||
cmd = ['make', '-k', '-j',
|
||||
str(threads), DRIVER_DIR, 'C=2', 'CF="-D__CHECK_ENDIAN__"']
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
drop = False
|
||||
|
||||
for f in sparse_filter:
|
||||
match = re.search(f, line)
|
||||
if not args.no_filter and match:
|
||||
logger.debug('sparse_filter: %s' % line)
|
||||
drop = True
|
||||
break
|
||||
|
||||
if not drop:
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def find_tagname(tag_map, filename, lineno):
|
||||
if filename.find('Kconfig') != -1:
|
||||
return None
|
||||
|
||||
if filename not in tag_map:
|
||||
return None
|
||||
|
||||
# we need the tags sorted per linenumber
|
||||
sorted_tags = sorted(tag_map[filename], key=lambda tup: tup[0])
|
||||
|
||||
lineno = int(lineno)
|
||||
|
||||
prev = None
|
||||
|
||||
# find the tag which is in lineno
|
||||
for (l, tag) in sorted_tags:
|
||||
if l > lineno:
|
||||
return prev
|
||||
|
||||
prev = tag
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def parse_checkpatch_warning(line):
|
||||
m = re.match(r'(.*?):(\d+): .*?:(.*?): (.*)', line, re.M | re.I)
|
||||
result = CPWarning()
|
||||
result.path = m.group(1)
|
||||
result.lineno = m.group(2)
|
||||
result.type = m.group(3)
|
||||
result.msg = m.group(4)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def is_filtered(cpwarning):
|
||||
if cpwarning.tag is None:
|
||||
return False
|
||||
|
||||
for (tag, type) in checkpatch_filter:
|
||||
matchobj = re.match(tag, cpwarning.tag)
|
||||
if matchobj is None:
|
||||
continue
|
||||
|
||||
if cpwarning.type == type:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_checkpatch_md5sum():
|
||||
path = shutil.which('checkpatch.pl')
|
||||
f = open(path, 'rb')
|
||||
md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
return md5sum
|
||||
|
||||
def get_checkpatch_cmdline():
|
||||
return ['checkpatch.pl'] + CHECKPATCH_OPTS + \
|
||||
['--ignore', ",".join(CHECKPATCH_IGNORE)]
|
||||
|
||||
|
||||
def run_checkpatch_cmd(args, q, tag_map):
|
||||
checkpatch_cmd = get_checkpatch_cmdline() + ['-f']
|
||||
|
||||
while True:
|
||||
try:
|
||||
f = q.get_nowait()
|
||||
except queue.Empty:
|
||||
# no more files to check
|
||||
break
|
||||
|
||||
cmd = checkpatch_cmd + [f]
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdoutdata, stderrdata) = p.communicate()
|
||||
|
||||
if stdoutdata is None:
|
||||
continue
|
||||
|
||||
lines = stdoutdata.splitlines()
|
||||
for line in lines:
|
||||
w = parse_checkpatch_warning(line)
|
||||
w.tag = find_tagname(tag_map, f, w.lineno)
|
||||
|
||||
if not args.no_filter and is_filtered(w):
|
||||
logger.debug('FILTERED: %s' % w)
|
||||
continue
|
||||
|
||||
logger.debug(w)
|
||||
print('%s:%s: %s' % (w.path, w.lineno, w.msg))
|
||||
|
||||
q.task_done()
|
||||
|
||||
|
||||
def run_checkpatch(args):
|
||||
md5sum = get_checkpatch_md5sum()
|
||||
if md5sum != CHECKPATCH_MD5SUM:
|
||||
print('WARNING: checkpatch.pl md5sum %s does not match with %s' %
|
||||
(md5sum, CHECKPATCH_MD5SUM))
|
||||
|
||||
# get all files which need to be checked
|
||||
cmd = 'git ls-tree HEAD %s | cut -f 2' % (DRIVER_DIR)
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
driver_files = output.splitlines()
|
||||
|
||||
# drop files we need to ignore
|
||||
for name in IGNORE_FILES:
|
||||
full_name = '%s%s' % (DRIVER_DIR, name)
|
||||
if full_name in driver_files:
|
||||
driver_files.remove(full_name)
|
||||
|
||||
logger.debug('driver_files: %s' % (driver_files))
|
||||
|
||||
# create global index file
|
||||
(fd, tmpfilename) = tempfile.mkstemp()
|
||||
f = os.fdopen(fd, 'w')
|
||||
f.write('\n'.join(driver_files))
|
||||
f.close()
|
||||
|
||||
# FIXME: do we need to call os.close(fd) still?
|
||||
|
||||
cmd = 'gtags -f %s' % (tmpfilename)
|
||||
logger.debug('%s' % (cmd))
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
os.remove(tmpfilename)
|
||||
|
||||
# tag_map[FILENAME] = [(start line, tagname)]
|
||||
tag_map = {}
|
||||
|
||||
# create tag mapping
|
||||
for f in driver_files:
|
||||
# global gives an error from Kconfig and Makefile
|
||||
if f.endswith('Kconfig') or f.endswith('Makefile'):
|
||||
continue
|
||||
|
||||
cmd = 'global -f %s' % (f)
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
lines = output.splitlines()
|
||||
for l in lines:
|
||||
columns = l.split()
|
||||
tagname = columns[0]
|
||||
line = int(columns[1])
|
||||
|
||||
if f not in tag_map:
|
||||
tag_map[f] = []
|
||||
|
||||
tag_map[f].append((line, tagname))
|
||||
|
||||
q = queue.Queue()
|
||||
|
||||
for f in driver_files:
|
||||
q.put(f)
|
||||
|
||||
# run checkpatch for all files
|
||||
for i in range(threads):
|
||||
t = threading.Thread(
|
||||
target=run_checkpatch_cmd, args=(args, q, tag_map))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
q.join()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def show_version(args):
|
||||
gcc_version = 'not found'
|
||||
sparse_version = 'not found'
|
||||
checkpatch_version = 'not found'
|
||||
checkpatch_md5sum = 'N/A'
|
||||
gtags_version = 'not found'
|
||||
|
||||
run = subprocess.check_output
|
||||
|
||||
f = open(sys.argv[0], 'rb')
|
||||
ath11kcheck_md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
try:
|
||||
gcc_version = run(['gcc', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
sparse_version = run(['sparse', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
checkpatch_version = run(['checkpatch.pl', '--version'],
|
||||
universal_newlines=True).splitlines()[1]
|
||||
checkpatch_md5sum = get_checkpatch_md5sum()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
gtags_version = run(['gtags', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
print('ath11k-check (md5sum %s)' % (ath11kcheck_md5sum))
|
||||
print()
|
||||
print('python:\t\t%s' % (sys.version))
|
||||
print('gcc:\t\t%s' % (gcc_version))
|
||||
print('sparse:\t\t%s' % (sparse_version))
|
||||
print('checkpatch.pl:\t%s (md5sum %s)' % (checkpatch_version, checkpatch_md5sum))
|
||||
print('gtags:\t\t%s' % (gtags_version))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
global threads
|
||||
|
||||
checkpatch_url = GIT_URL % (CHECKPATCH_COMMIT)
|
||||
|
||||
description = '''ath11k source code checker
|
||||
|
||||
Runs various tests (gcc, sparse and checkpatch) with filtering
|
||||
unnecessary warnings away, the goal is to have empty output from the
|
||||
script.
|
||||
|
||||
Run this from the main kernel source directory which is preconfigured
|
||||
with ath11k enabled. gcc recompilation is forced every time,
|
||||
irrespective if there are any changes in source or not. So this can be
|
||||
run multiple times and every time the same warnings will appear.
|
||||
|
||||
Requirements (all available in $PATH):
|
||||
|
||||
* gcc
|
||||
* sparse
|
||||
* checkpatch.pl
|
||||
* gtags (from package global)
|
||||
|
||||
'''
|
||||
|
||||
s = '''Installation:
|
||||
|
||||
As checkpatch is evolving this script always matches a certain version
|
||||
of checkpatch. Download the checkpatch version from the URL below and
|
||||
install it somewhere in your $$PATH:
|
||||
|
||||
$CHECKPATCH_URL
|
||||
|
||||
Alternatively if you want manually run checkpatch with the same
|
||||
settings as ath11k-check uses here's the command line:
|
||||
|
||||
$CHECKPATCH_CMDLINE
|
||||
'''
|
||||
|
||||
checkpatch_cmdline = '%s foo.patch' % ' '.join(get_checkpatch_cmdline())
|
||||
epilog = string.Template(s).substitute(CHECKPATCH_URL=checkpatch_url,
|
||||
CHECKPATCH_CMDLINE=checkpatch_cmdline)
|
||||
|
||||
parser = argparse.ArgumentParser(description=description, epilog=epilog,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
parser.add_argument('-d', '--debug', action='store_true',
|
||||
help='enable debug messages')
|
||||
|
||||
parser.add_argument('--fast', action='store_true',
|
||||
help='run only tests which finish in few seconds')
|
||||
|
||||
parser.add_argument('--no-extra', action='store_true',
|
||||
help='Do not run extra checks like W=1')
|
||||
|
||||
parser.add_argument('--no-filter', action='store_true',
|
||||
help='Don\'t filter output with regexp: %r' % (FILTER_REGEXP))
|
||||
|
||||
parser.add_argument('--version', action='store_true',
|
||||
help='Show version information about dependencies')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
timefmt = ''
|
||||
|
||||
if args.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
timefmt = '%(asctime)s '
|
||||
|
||||
logfmt = '%s%%(levelname)s: %%(message)s' % (timefmt)
|
||||
|
||||
logging.basicConfig(format=logfmt)
|
||||
|
||||
if args.version:
|
||||
show_version(args)
|
||||
|
||||
if args.fast:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = False
|
||||
else:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = True
|
||||
|
||||
try:
|
||||
cores = subprocess.check_output(['nproc'], universal_newlines=True)
|
||||
except OSError as xxx_todo_changeme:
|
||||
subprocess.CalledProcessError = xxx_todo_changeme
|
||||
cores = '4'
|
||||
logger.warning('Failed to run nproc, assuming %s cores' % (cores))
|
||||
|
||||
threads = int(cores) + 2
|
||||
|
||||
logger.debug('threads %d' % (threads))
|
||||
|
||||
if gcc:
|
||||
ret = run_gcc(args)
|
||||
if ret != 0:
|
||||
logger.debug('gcc failed: %d', ret)
|
||||
sys.exit(1)
|
||||
|
||||
if sparse:
|
||||
ret = run_sparse(args)
|
||||
if ret != 0:
|
||||
logger.debug('sparse failed: %d', ret)
|
||||
sys.exit(2)
|
||||
|
||||
if checkpatch:
|
||||
ret = run_checkpatch(args)
|
||||
if ret != 0:
|
||||
logger.debug('checkpatch failed: %d', ret)
|
||||
sys.exit(3)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1170
tools/scripts/ath11k/ath11k-fw-repo
Executable file
1170
tools/scripts/ath11k/ath11k-fw-repo
Executable file
File diff suppressed because it is too large
Load diff
684
tools/scripts/ath11k/ath11k-fwencoder
Executable file
684
tools/scripts/ath11k/ath11k-fwencoder
Executable file
|
|
@ -0,0 +1,684 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import ctypes
|
||||
import struct
|
||||
import optparse
|
||||
import time
|
||||
import math
|
||||
import logging
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
import binascii
|
||||
import tempfile
|
||||
import subprocess
|
||||
import hashlib
|
||||
|
||||
DEFAULT_FW_API_VERSION = 2
|
||||
|
||||
ATH11K_SIGNATURE = b'QCOM-ATH11K-FW'
|
||||
MAX_LEN = 50000000
|
||||
|
||||
ATH11K_FW_IE_TIMESTAMP = 0
|
||||
ATH11K_FW_IE_FEATURES = 1
|
||||
ATH11K_FW_IE_AMSS_IMAGE = 2
|
||||
ATH11K_FW_IE_M3_IMAGE = 3
|
||||
|
||||
# enum ath11k_fw_features from ath11k/fw.h
|
||||
ATH11K_FW_FEATURE_MAX = 1
|
||||
|
||||
feature_map = {
|
||||
}
|
||||
|
||||
# global variables
|
||||
logger = None
|
||||
|
||||
|
||||
class FWEncoderError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_output_name(fw_api=None):
|
||||
if fw_api is not None:
|
||||
api = fw_api
|
||||
else:
|
||||
api = DEFAULT_FW_API_VERSION
|
||||
|
||||
return 'firmware-%s.bin' % api
|
||||
|
||||
|
||||
class FirmwareContainer:
|
||||
|
||||
def add_element(self, type_id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
logger.debug('adding id %d len(value) %d'
|
||||
'padding_len %d' % (type_id,
|
||||
len(value),
|
||||
padding_len))
|
||||
fmt = '<ii%ds%ds' % (len(value), padding_len)
|
||||
struct.pack_into(fmt, self.buf, self.buf_len, type_id, len(value),
|
||||
value, padding.raw)
|
||||
self.buf_len = self.buf_len + 4 + 4 + len(value) + padding_len
|
||||
|
||||
def add_u32(self, type_id, value):
|
||||
if not type(value) is int:
|
||||
raise FWEncoderError('u32 IE %d is not int: %s' %
|
||||
(type_id, str(value)))
|
||||
|
||||
buf = ctypes.create_string_buffer(4)
|
||||
struct.pack_into("<i", buf, 0, value)
|
||||
self.add_element(type_id, buf.raw)
|
||||
|
||||
def read_u32(self, type_id):
|
||||
(val,) = struct.unpack_from("<i", self.elements[type_id])
|
||||
return val
|
||||
|
||||
def add_bitmap(self, ie, enabled, maximum):
|
||||
|
||||
if (max(enabled) >= maximum):
|
||||
logger.error("bitmap %d out of maximum (%d >= %d)" %
|
||||
(ie, max(enabled), maximum))
|
||||
return
|
||||
|
||||
bytes = [0] * maximum
|
||||
|
||||
for i in range(maximum):
|
||||
if i not in enabled:
|
||||
continue
|
||||
|
||||
max_set = i
|
||||
index = i / 8
|
||||
bit = i % 8
|
||||
bytes[index] = bytes[index] | (1 << bit)
|
||||
|
||||
# remove trailing null bits away, that changing only
|
||||
# maximum doesn't affect created binary size
|
||||
length = int(math.ceil((max_set + 1) / float(8)))
|
||||
bytes = bytes[:length]
|
||||
|
||||
buf = ctypes.create_string_buffer(length)
|
||||
|
||||
for index in range(length):
|
||||
struct.pack_into('<B', buf, index, bytes[index])
|
||||
|
||||
self.add_element(ie, buf.raw)
|
||||
|
||||
def read_bitmap(self, ie):
|
||||
buf = self.elements[ie]
|
||||
length = len(buf)
|
||||
|
||||
bits = []
|
||||
|
||||
for index in range(length):
|
||||
val = struct.unpack_from('<B', buf, index)[0]
|
||||
|
||||
for bit in range(8):
|
||||
if val & 0x1:
|
||||
bits.append(index * 8 + bit)
|
||||
|
||||
val = val >> 1
|
||||
|
||||
return bits
|
||||
|
||||
def set_signature(self, signature):
|
||||
self.signature = signature
|
||||
self.signature_len = len(signature)
|
||||
|
||||
# include the null byte
|
||||
length = len(signature) + 1
|
||||
|
||||
padding_len = padding_needed(length)
|
||||
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
fmt = '<%dsb%ds' % (len(signature), padding_len)
|
||||
struct.pack_into(fmt, self.buf, 0, signature, 0, padding.raw)
|
||||
self.buf_len = length
|
||||
|
||||
def write(self, name):
|
||||
f = open(name, 'wb')
|
||||
f.write(self.buf.raw[:self.buf_len])
|
||||
f.close()
|
||||
|
||||
return self.buf_len
|
||||
|
||||
def open(self, name):
|
||||
f = open(name, 'rb')
|
||||
self.buf = f.read()
|
||||
self.buf_len = len(self.buf)
|
||||
f.close()
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (self.signature_len)
|
||||
(signature, null) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + self.signature_len + 1
|
||||
|
||||
if signature != self.signature or null != 0:
|
||||
logger.error("Invalid signature!")
|
||||
return False
|
||||
|
||||
offset = self.signature_len + 1
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements = {}
|
||||
|
||||
while offset + 4 + 4 < self.buf_len:
|
||||
(type_id, length) = struct.unpack_from("<ii", self.buf, offset)
|
||||
offset = offset + 4 + 4
|
||||
|
||||
if offset + length > self.buf_len:
|
||||
logger.error("Buffer too short")
|
||||
return
|
||||
|
||||
fmt = '<%ds' % length
|
||||
(payload,) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + length
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements[type_id] = payload
|
||||
|
||||
return True
|
||||
|
||||
def __init__(self, signature):
|
||||
self.buf = ctypes.create_string_buffer(MAX_LEN)
|
||||
self.buf_len = 0
|
||||
|
||||
self.set_signature(signature)
|
||||
|
||||
|
||||
class Ath11kFirmwareContainer(object):
|
||||
def _load_file(self, name):
|
||||
if os.path.getsize(name) > MAX_LEN:
|
||||
raise FWEncoderError('file %s is too large, maximum size is %d' %
|
||||
(name, MAX_LEN))
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
return buf
|
||||
|
||||
def set_features(self, features):
|
||||
self.features = features.split(',')
|
||||
|
||||
enabled = []
|
||||
for capa in self.features:
|
||||
if capa not in feature_map:
|
||||
print("Error: '%s' not found from the feature map" % capa)
|
||||
return 1
|
||||
|
||||
enabled.append(feature_map[capa])
|
||||
|
||||
self.features_bitmap = enabled
|
||||
|
||||
def get_features(self):
|
||||
s = ""
|
||||
|
||||
if self.features_bitmap is None:
|
||||
return None
|
||||
|
||||
for capa in self.features_bitmap:
|
||||
# find value from the dict
|
||||
try:
|
||||
name = [key for key, value in feature_map.items()
|
||||
if value == capa][0]
|
||||
except IndexError:
|
||||
name = str(capa)
|
||||
|
||||
s = s + name + ","
|
||||
|
||||
# strip last comma
|
||||
if len(s) > 0:
|
||||
s = s[:-1]
|
||||
|
||||
return s
|
||||
|
||||
def set_amss_image(self, amss_image_name):
|
||||
self.amss_image = self._load_file(amss_image_name)
|
||||
|
||||
def get_amss_image(self):
|
||||
return self.amss_image
|
||||
|
||||
def set_m3_image(self, m3_image_name):
|
||||
self.m3_image = self._load_file(m3_image_name)
|
||||
|
||||
def get_m3_image(self):
|
||||
return self.m3_image
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self.timestamp = int(timestamp)
|
||||
|
||||
def get_timestamp(self):
|
||||
return self.timestamp
|
||||
|
||||
def get_timestamp_as_iso8601(self):
|
||||
if self.timestamp is None:
|
||||
return None
|
||||
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.gmtime(self.timestamp))
|
||||
|
||||
def get_summary(self):
|
||||
s = ''
|
||||
|
||||
s = s + 'FileSize: %s\n' % (len(self.file))
|
||||
s = s + 'FileCRC32: %08x\n' % (_crc32(self.file))
|
||||
s = s + 'FileMD5: %s\n' % (hashlib.md5(self.file).hexdigest())
|
||||
|
||||
if self.get_timestamp():
|
||||
s = s + 'Timestamp: %s\n' % (self.get_timestamp_as_iso8601())
|
||||
|
||||
if self.get_features():
|
||||
s = s + 'Features: %s\n' % (self.get_features())
|
||||
|
||||
if self.get_amss_image():
|
||||
s = s + 'AMSSImageSize: %s\n' % (len(self.get_amss_image()))
|
||||
s = s + 'AMSSImageCRC32: %08x\n' % (_crc32(self.get_amss_image()))
|
||||
|
||||
if self.get_m3_image():
|
||||
s = s + 'M3ImageSize: %s\n' % (len(self.get_m3_image()))
|
||||
s = s + 'M3ImageCRC32: %08x\n' % (_crc32(self.get_m3_image()))
|
||||
|
||||
return s.strip()
|
||||
|
||||
def load(self, filename):
|
||||
c = FirmwareContainer(ATH11K_SIGNATURE)
|
||||
c.open(filename)
|
||||
|
||||
self.file = c.buf
|
||||
|
||||
for e in c.elements:
|
||||
if e == ATH11K_FW_IE_TIMESTAMP:
|
||||
self.timestamp = c.read_u32(e)
|
||||
elif e == ATH11K_FW_IE_M3_IMAGE:
|
||||
self.m3_image = c.elements[e]
|
||||
elif e == ATH11K_FW_IE_AMSS_IMAGE:
|
||||
self.amss_image = c.elements[e]
|
||||
elif e == ATH11K_FW_IE_FEATURES:
|
||||
self.features_bitmap = c.read_bitmap(ATH11K_FW_IE_FEATURES)
|
||||
else:
|
||||
print("Unknown IE: ", e)
|
||||
|
||||
def save(self, filename):
|
||||
self.container = FirmwareContainer(ATH11K_SIGNATURE)
|
||||
|
||||
if self.timestamp:
|
||||
self.container.add_u32(ATH11K_FW_IE_TIMESTAMP, self.timestamp)
|
||||
|
||||
# FIXME: m3 should be after amss_image but that breaks the
|
||||
# current tests
|
||||
if self.m3_image:
|
||||
self.container.add_element(ATH11K_FW_IE_M3_IMAGE, self.m3_image)
|
||||
|
||||
if self.amss_image:
|
||||
self.container.add_element(ATH11K_FW_IE_AMSS_IMAGE, self.amss_image)
|
||||
|
||||
# FIXME: features should be before amss_image but that breaks
|
||||
# the current tests
|
||||
if self.features_bitmap:
|
||||
self.container.add_bitmap(ATH11K_FW_IE_FEATURES,
|
||||
self.features_bitmap,
|
||||
ATH11K_FW_FEATURE_MAX)
|
||||
|
||||
return self.container.write(filename)
|
||||
|
||||
def __init__(self):
|
||||
self.timestamp = None
|
||||
self.features = None
|
||||
self.features_bitmap = None
|
||||
self.amss_image = None
|
||||
self.m3_image = None
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def padding_needed(length):
|
||||
if length % 4 != 0:
|
||||
return 4 - length % 4
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def is_int(val):
|
||||
try:
|
||||
int(val)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def write_file(filename, buf):
|
||||
f = open(filename, 'wb')
|
||||
f.write(buf)
|
||||
f.close
|
||||
|
||||
|
||||
def info(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath11kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print(c.get_summary())
|
||||
|
||||
|
||||
def dump(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath11kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print("ath11k-fwencoder --create \\")
|
||||
|
||||
if c.get_timestamp() and options.show_timestamp:
|
||||
print("--timestamp=%u \\" % c.get_timestamp())
|
||||
|
||||
if c.get_features():
|
||||
print("--features=%s \\" % c.get_features())
|
||||
|
||||
if c.get_amss_image():
|
||||
name = "amss.bin"
|
||||
print("--amss=%s \\" % name)
|
||||
|
||||
if c.get_m3_image():
|
||||
name = "m3.bin"
|
||||
print("--m3=%s \\" % name)
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def extract(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath11kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if c.get_amss_image():
|
||||
name = "amss.bin"
|
||||
write_file(name, c.get_amss_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_amss_image())))
|
||||
|
||||
if c.get_m3_image():
|
||||
name = "m3.bin"
|
||||
write_file(name, c.get_m3_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_m3_image())))
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def modify(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath11kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if options.timestamp:
|
||||
stamp = str(int(options.timestamp))
|
||||
else:
|
||||
# if no timestamp provided use the current time so that the
|
||||
# timestamp shows the time of last modication
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.m3:
|
||||
c.set_m3_image(options.m3)
|
||||
|
||||
if options.amss:
|
||||
c.set_amss_image(options.amss)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
file_len = c.save(filename)
|
||||
|
||||
print('%s modified: %d B' % (filename, file_len))
|
||||
|
||||
|
||||
def create(options):
|
||||
output = get_output_name(options.fw_api)
|
||||
|
||||
if options.output:
|
||||
output = options.output
|
||||
|
||||
c = Ath11kFirmwareContainer()
|
||||
|
||||
# always add a timestamp
|
||||
if options.timestamp:
|
||||
stamp = int(options.timestamp)
|
||||
else:
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.m3:
|
||||
c.set_m3_image(options.m3)
|
||||
|
||||
if options.amss:
|
||||
c.set_amss_image(options.amss)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
file_len = c.save(output)
|
||||
|
||||
print('%s created: %d B' % (output, file_len))
|
||||
|
||||
|
||||
def cmd_crc32(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
f = open(filename, 'rb')
|
||||
buf = f.read()
|
||||
print('%08x' % (_crc32(buf)))
|
||||
f.close()
|
||||
|
||||
|
||||
def cmd_diff(options, args):
|
||||
if len(args) != 2:
|
||||
print('Usage: ath11k-fwencoder --diff FILE FILE')
|
||||
return 1
|
||||
|
||||
filename1 = args[0]
|
||||
filename2 = args[1]
|
||||
|
||||
c1 = Ath11kFirmwareContainer()
|
||||
c1.load(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp1_pathname, 'w')
|
||||
f.write(c1.get_summary())
|
||||
f.close()
|
||||
|
||||
c2 = Ath11kFirmwareContainer()
|
||||
c2.load(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp2_pathname, 'w')
|
||||
f.write(c2.get_summary())
|
||||
f.close()
|
||||
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
logger.error('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
logger.error('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
print(output)
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
|
||||
def main():
|
||||
global logger
|
||||
|
||||
logger = logging.getLogger('ath11k-fwencoder')
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s')
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
# actions
|
||||
parser.add_option("-c", "--create", action="store_true", dest="create",
|
||||
help='Create container file '
|
||||
'for ath11k (%s)' % get_output_name())
|
||||
parser.add_option("-D", "--dump-cmdline", action="store_true", dest="dump",
|
||||
help='Show the cmdline used to create '
|
||||
'this container file')
|
||||
parser.add_option('--dump', action='store_true', dest='dump',
|
||||
help='Same as --dump-cmdline '
|
||||
'(for backwards compatibility)')
|
||||
parser.add_option("-e", "--extract", action="store_true", dest="extract",
|
||||
help='Extract binary files from the container file '
|
||||
'and dump cmdline as well')
|
||||
parser.add_option("--info", action="store_true", dest="info",
|
||||
help='Show information about the container file')
|
||||
parser.add_option("--modify", action="store_true", dest="modify",
|
||||
help='Modify the container file')
|
||||
parser.add_option('--crc32', action='store_true', dest='crc32',
|
||||
help='Count crc32 checksum for a file')
|
||||
parser.add_option('--diff', action='store_true', dest='diff',
|
||||
help='Show differences between two firmware files')
|
||||
|
||||
# parameters
|
||||
parser.add_option("-o", "--output", action="store", type="string",
|
||||
dest="output", help='Name of output file')
|
||||
|
||||
# FW IEs, only use long style of option names!
|
||||
parser.add_option("--m3", action="store", type="string",
|
||||
dest="m3",
|
||||
help='Name of m3.bin file')
|
||||
parser.add_option("--amss", action="store", type="string",
|
||||
dest="amss",
|
||||
help='Name of amss.bin file')
|
||||
parser.add_option("--timestamp", action="store",
|
||||
type="string", dest="timestamp",
|
||||
help='Timestamp to be used (seconds)')
|
||||
|
||||
parser.add_option("--features", action="store",
|
||||
type="string", dest="features",
|
||||
help='feature bits to be enabled: %s' %
|
||||
list(feature_map.keys()))
|
||||
parser.add_option("--set-fw-api", action="store",
|
||||
type="string", dest="fw_api",
|
||||
help='Set firmware API used in creating the name for '
|
||||
'output file (Default: %s)' %
|
||||
DEFAULT_FW_API_VERSION)
|
||||
|
||||
# debug etc
|
||||
parser.add_option('--show-timestamp', action='store_true',
|
||||
dest='show_timestamp',
|
||||
help='Show timestamp in --dump-cmdline action. '
|
||||
'It is not shown by default so that the timestamp would be correct')
|
||||
parser.add_option('-d', '--debug', action='store_true', dest='debug',
|
||||
help='Enable debug messages')
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if options.create:
|
||||
try:
|
||||
return create(options)
|
||||
except FWEncoderError as e:
|
||||
print('Create failed: %s' % e)
|
||||
sys.exit(2)
|
||||
except Exception as e:
|
||||
print('Create failed: %s' % e)
|
||||
traceback.print_exc()
|
||||
sys.exit(3)
|
||||
elif options.dump:
|
||||
return dump(options, args)
|
||||
elif options.extract:
|
||||
return extract(options, args)
|
||||
elif options.info:
|
||||
return info(options, args)
|
||||
elif options.modify:
|
||||
return modify(options, args)
|
||||
elif options.crc32:
|
||||
return cmd_crc32(options, args)
|
||||
elif options.diff:
|
||||
return cmd_diff(options, args)
|
||||
else:
|
||||
print('Action command missing')
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
862
tools/scripts/ath12k/ath12k-bdencoder
Executable file
862
tools/scripts/ath12k/ath12k-bdencoder
Executable file
|
|
@ -0,0 +1,862 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# Run 'ath12k-bdencoder --help' to see the instructions
|
||||
#
|
||||
|
||||
import struct
|
||||
import ctypes
|
||||
import os.path
|
||||
import argparse
|
||||
import json
|
||||
import binascii
|
||||
import hashlib
|
||||
import tempfile
|
||||
import subprocess
|
||||
import logging
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
MAX_BUF_LEN = 3000000
|
||||
|
||||
# the signature length also includes null byte and padding
|
||||
ATH12K_BOARD_SIGNATURE = b"QCA-ATH12K-BOARD"
|
||||
ATH12K_BOARD_SIGNATURE_LEN = 20
|
||||
|
||||
PADDING_MAGIC = 0x6d
|
||||
DEFAULT_BD_API = 2
|
||||
DEFAULT_BOARD_FILE = 'board-%d.bin' % DEFAULT_BD_API
|
||||
DEFAULT_JSON_FILE = 'board-%d.json' % DEFAULT_BD_API
|
||||
TYPE_LENGTH_SIZE = 8
|
||||
|
||||
ATH12K_BD_IE_BOARD = 0
|
||||
ATH12K_BD_IE_REGDB = 1
|
||||
|
||||
ATH12K_BD_IE_BOARD_NAME = 0
|
||||
ATH12K_BD_IE_BOARD_DATA = 1
|
||||
|
||||
ATH12K_BD_IE_REGDB_NAME = 0
|
||||
ATH12K_BD_IE_REGDB_DATA = 1
|
||||
|
||||
|
||||
def padding_needed(len):
|
||||
if len % 4 != 0:
|
||||
return 4 - len % 4
|
||||
return 0
|
||||
|
||||
|
||||
def add_ie(buf, offset, id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<2i%ds%ds' % (len(value), padding_len)
|
||||
struct.pack_into(fmt, buf, offset, id, len(value), value, padding.raw)
|
||||
offset = offset + TYPE_LENGTH_SIZE + len(value) + padding_len
|
||||
|
||||
return offset
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def pretty_array_str(array):
|
||||
return '\',\''.join(array)
|
||||
|
||||
|
||||
class RegdbName():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = RegdbName()
|
||||
fmt = '<%ds' % length
|
||||
(name, ) = struct.unpack_from(fmt, buf, offset)
|
||||
self.name = name.decode()
|
||||
|
||||
logging.debug('RegdbName.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH12K_BD_IE_REGDB_NAME, self.name.encode())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'RegdbName(%s)' % self.name
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
||||
|
||||
class RegdbData():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = RegdbData()
|
||||
fmt = '<%ds' % length
|
||||
(self.data, ) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
logging.debug('RegdbData.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH12K_BD_IE_REGDB_DATA, self.data)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.data is not None:
|
||||
s = '%d B' % (len(self.data))
|
||||
else:
|
||||
s = 'n/a'
|
||||
|
||||
return 'RegdbData(%s)' % (s)
|
||||
|
||||
def __init__(self, data=None):
|
||||
self.data = data
|
||||
|
||||
|
||||
class Regdb():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
logging.debug('Regdb.parse_ie(): offset %d length %d' % (offset, length))
|
||||
|
||||
self = Regdb()
|
||||
|
||||
# looping regdb IEs
|
||||
while length > 0:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
|
||||
logging.debug('Regdb.parse_ie(): found ie_id %d ie_len %d offset %d length %d' %
|
||||
(ie_id, ie_len, offset, length))
|
||||
|
||||
if TYPE_LENGTH_SIZE + ie_len > length:
|
||||
raise Exception('Error: ie_len too big (%d > %d)' % (ie_len,
|
||||
length))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
length -= TYPE_LENGTH_SIZE
|
||||
|
||||
if ie_id == ATH12K_BD_IE_REGDB_NAME:
|
||||
self.names.append(RegdbName.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH12K_BD_IE_REGDB_DATA:
|
||||
self.data = RegdbData.parse_ie(buf, offset, ie_len)
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
length -= ie_len + padding_needed(ie_len)
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
# store position ie header of this element
|
||||
ie_offset = offset
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
for name in self.names:
|
||||
offset = name.add_to_buf(buf, offset)
|
||||
|
||||
offset = self.data.add_to_buf(buf, offset)
|
||||
|
||||
# write ie header as now we know the full length
|
||||
ie_len = offset - ie_offset - TYPE_LENGTH_SIZE
|
||||
struct.pack_into('<2i', buf, ie_offset, ATH12K_BD_IE_REGDB, ie_len)
|
||||
|
||||
return offset
|
||||
|
||||
def get_names_as_str(self):
|
||||
names = []
|
||||
for regdbname in self.names:
|
||||
names.append(regdbname.name)
|
||||
|
||||
return names
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
names = []
|
||||
for regdbname in self.names:
|
||||
names.append(str(regdbname))
|
||||
|
||||
return 'Regdb(%s, %s)' % (','.join(names), self.data)
|
||||
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.names = []
|
||||
|
||||
|
||||
class BoardName():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardName()
|
||||
fmt = '<%ds' % length
|
||||
(name, ) = struct.unpack_from(fmt, buf, offset)
|
||||
self.name = name.decode()
|
||||
|
||||
logging.debug('BoardName.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH12K_BD_IE_BOARD_NAME, self.name.encode())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
return 'BoardName(%s)' % self.name
|
||||
|
||||
def __init__(self, name=None):
|
||||
self.name = name
|
||||
|
||||
|
||||
class BoardData():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
self = BoardData()
|
||||
fmt = '<%ds' % length
|
||||
(self.data, ) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
logging.debug('BoardData.parse_ie(): offset %d length %d self %s' %
|
||||
(offset, length, self))
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
return add_ie(buf, offset, ATH12K_BD_IE_BOARD_DATA, self.data)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
if self.data is not None:
|
||||
s = '%d B' % (len(self.data))
|
||||
else:
|
||||
s = 'n/a'
|
||||
|
||||
return 'BoardData(%s)' % (s)
|
||||
|
||||
def __init__(self, data=None):
|
||||
self.data = data
|
||||
|
||||
|
||||
class Board():
|
||||
@staticmethod
|
||||
def parse_ie(buf, offset, length):
|
||||
logging.debug('Board.parse_ie(): offset %d length %d' % (offset, length))
|
||||
|
||||
self = Board()
|
||||
|
||||
# looping board IEs
|
||||
while length > 0:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
|
||||
logging.debug('Board.parse_ie(): found ie_id %d ie_len %d offset %d length %d' %
|
||||
(ie_id, ie_len, offset, length))
|
||||
|
||||
if TYPE_LENGTH_SIZE + ie_len > length:
|
||||
raise Exception('Error: ie_len too big (%d > %d)' % (ie_len,
|
||||
length))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
length -= TYPE_LENGTH_SIZE
|
||||
|
||||
if ie_id == ATH12K_BD_IE_BOARD_NAME:
|
||||
self.names.append(BoardName.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH12K_BD_IE_BOARD_DATA:
|
||||
self.data = BoardData.parse_ie(buf, offset, ie_len)
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
length -= ie_len + padding_needed(ie_len)
|
||||
|
||||
return self
|
||||
|
||||
def add_to_buf(self, buf, offset):
|
||||
# store position ie header of this element
|
||||
ie_offset = offset
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
for name in self.names:
|
||||
offset = name.add_to_buf(buf, offset)
|
||||
|
||||
offset = self.data.add_to_buf(buf, offset)
|
||||
|
||||
# write ie header as now we know the full length
|
||||
ie_len = offset - ie_offset - TYPE_LENGTH_SIZE
|
||||
struct.pack_into('<2i', buf, ie_offset, ATH12K_BD_IE_BOARD, ie_len)
|
||||
|
||||
return offset
|
||||
|
||||
def get_names_as_str(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(boardname.name)
|
||||
|
||||
return names
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
names = []
|
||||
for boardname in self.names:
|
||||
names.append(str(boardname))
|
||||
|
||||
return 'Board(%s, %s)' % (','.join(names), self.data)
|
||||
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.names = []
|
||||
|
||||
|
||||
class BoardContainer:
|
||||
|
||||
def add_board(self, data, names):
|
||||
boardnames = []
|
||||
for name in names:
|
||||
boardnames.append(BoardName(name))
|
||||
|
||||
board = Board()
|
||||
board.data = BoardData(data)
|
||||
board.names = boardnames
|
||||
|
||||
self.boards.append(board)
|
||||
|
||||
def add_regdb(self, data, names):
|
||||
regdbnames = []
|
||||
for name in names:
|
||||
regdbnames.append(RegdbName(name))
|
||||
|
||||
regdb = Regdb()
|
||||
regdb.data = RegdbData(data)
|
||||
regdb.names = regdbnames
|
||||
|
||||
self.regdbs.append(regdb)
|
||||
|
||||
@staticmethod
|
||||
def open_json(filename):
|
||||
self = BoardContainer()
|
||||
|
||||
if not os.path.exists(filename):
|
||||
print('mapping file %s not found' % (filename))
|
||||
return
|
||||
|
||||
f = open(filename, 'r')
|
||||
mapping = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
if 'board' in mapping[0]:
|
||||
for b in mapping[0]['board']:
|
||||
board_filename = b['data']
|
||||
f = open(board_filename, 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
self.add_board(data, b['names'])
|
||||
|
||||
if 'regdb' in mapping[0]:
|
||||
for b in mapping[0]['regdb']:
|
||||
regdb_filename = b['data']
|
||||
f = open(regdb_filename, 'rb')
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
self.add_regdb(data, b['names'])
|
||||
|
||||
return self
|
||||
|
||||
def validate(self):
|
||||
allnames = []
|
||||
|
||||
for board in self.boards:
|
||||
for name in board.names:
|
||||
if name in allnames:
|
||||
# TODO: Find a better way to report problems,
|
||||
# maybe return a list of strings? Or use an
|
||||
# exception?
|
||||
print('Warning: duplicate board name: %s' % (name.name))
|
||||
return
|
||||
|
||||
allnames.append(name)
|
||||
|
||||
def _add_signature(self, buf, offset):
|
||||
signature = ATH12K_BOARD_SIGNATURE + b'\0'
|
||||
length = len(signature)
|
||||
pad_len = padding_needed(length)
|
||||
length = length + pad_len
|
||||
|
||||
padding = ctypes.create_string_buffer(pad_len)
|
||||
|
||||
for i in range(pad_len):
|
||||
struct.pack_into('<B', padding, i, PADDING_MAGIC)
|
||||
|
||||
fmt = '<%ds%ds' % (len(signature), pad_len)
|
||||
struct.pack_into(fmt, buf, offset, signature, padding.raw)
|
||||
offset += length
|
||||
|
||||
# make sure ATH12K_BOARD_SIGNATURE_LEN is correct
|
||||
assert ATH12K_BOARD_SIGNATURE_LEN == length
|
||||
|
||||
return offset
|
||||
|
||||
@staticmethod
|
||||
def open(name):
|
||||
self = BoardContainer()
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
buf_len = len(buf)
|
||||
|
||||
logging.debug('BoardContainer.open(): name %s' % (name))
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (len(ATH12K_BOARD_SIGNATURE))
|
||||
(signature, null) = struct.unpack_from(fmt, buf, offset)
|
||||
|
||||
if signature != ATH12K_BOARD_SIGNATURE or null != 0:
|
||||
print("invalid signature found in %s" % name)
|
||||
return 1
|
||||
|
||||
offset += ATH12K_BOARD_SIGNATURE_LEN
|
||||
|
||||
# looping main IEs
|
||||
while offset < buf_len:
|
||||
(ie_id, ie_len) = struct.unpack_from('<2i', buf, offset)
|
||||
logging.debug('BoardContainer.open(): found offset %d ie_id %d ie_len %d' %
|
||||
(offset, ie_id, ie_len))
|
||||
|
||||
offset += TYPE_LENGTH_SIZE
|
||||
|
||||
if offset + ie_len > buf_len:
|
||||
print('Error: Buffer too short (%d + %d > %d)' % (offset,
|
||||
ie_len,
|
||||
buf_len))
|
||||
return 1
|
||||
|
||||
if ie_id == ATH12K_BD_IE_BOARD:
|
||||
self.boards.append(Board.parse_ie(buf, offset, ie_len))
|
||||
elif ie_id == ATH12K_BD_IE_REGDB:
|
||||
self.regdbs.append(Regdb.parse_ie(buf, offset, ie_len))
|
||||
|
||||
offset += ie_len + padding_needed(ie_len)
|
||||
|
||||
self.validate()
|
||||
|
||||
return self
|
||||
|
||||
def write(self, name):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
fd = open(name, 'wb')
|
||||
fd.write(buf.raw[0:buf_len])
|
||||
fd.close()
|
||||
|
||||
self.validate()
|
||||
|
||||
print("board binary file '%s' is created" % name)
|
||||
|
||||
def get_bin(self):
|
||||
buf = ctypes.create_string_buffer(MAX_BUF_LEN)
|
||||
offset = 0
|
||||
|
||||
offset = self._add_signature(buf, offset)
|
||||
|
||||
for board in self.boards:
|
||||
offset = board.add_to_buf(buf, offset)
|
||||
|
||||
for regdb in self.regdbs:
|
||||
offset = regdb.add_to_buf(buf, offset)
|
||||
|
||||
# returns buffer and it's length
|
||||
return buf, offset
|
||||
|
||||
def get_summary(self, sort=False):
|
||||
(buf, buf_len) = self.get_bin()
|
||||
|
||||
s = ''
|
||||
|
||||
s += 'FileSize: %d\n' % (buf_len)
|
||||
s += 'FileCRC32: %08x\n' % (_crc32(buf[0:buf_len]))
|
||||
s += 'FileMD5: %s\n' % (hashlib.md5(buf[0:buf_len]).hexdigest())
|
||||
|
||||
boards = self.boards
|
||||
|
||||
if sort:
|
||||
boards = sorted(boards, key=lambda board: board.get_names_as_str())
|
||||
|
||||
index = 0
|
||||
for board in boards:
|
||||
if not sort:
|
||||
index_s = '[%d]' % (index)
|
||||
else:
|
||||
index_s = ''
|
||||
|
||||
s += 'BoardNames%s: \'%s\'\n' % (index_s, pretty_array_str(board.get_names_as_str()))
|
||||
s += 'BoardLength%s: %d\n' % (index_s, len(board.data.data))
|
||||
s += 'BoardCRC32%s: %08x\n' % (index_s, _crc32(board.data.data))
|
||||
s += 'BoardMD5%s: %s\n' % (index_s, hashlib.md5(board.data.data).hexdigest())
|
||||
index += 1
|
||||
|
||||
regdbs = self.regdbs
|
||||
|
||||
if sort:
|
||||
regdbs = sorted(regdbs, key=lambda regdb: regdb.get_names_as_str())
|
||||
|
||||
index = 0
|
||||
for regdb in regdbs:
|
||||
if not sort:
|
||||
index_s = '[%d]' % (index)
|
||||
else:
|
||||
index_s = ''
|
||||
|
||||
s += 'RegdbNames%s: \'%s\'\n' % (index_s, pretty_array_str(regdb.get_names_as_str()))
|
||||
s += 'RegdbLength%s: %d\n' % (index_s, len(regdb.data.data))
|
||||
s += 'RegdbCRC32%s: %08x\n' % (index_s, _crc32(regdb.data.data))
|
||||
s += 'RegdbMD5%s: %s\n' % (index_s, hashlib.md5(regdb.data.data).hexdigest())
|
||||
index += 1
|
||||
|
||||
return s
|
||||
|
||||
def __init__(self):
|
||||
self.boards = []
|
||||
self.regdbs = []
|
||||
|
||||
|
||||
def cmd_extract(args):
|
||||
cont = BoardContainer().open(args.extract)
|
||||
|
||||
mapping = []
|
||||
d = {}
|
||||
mapping.append(d)
|
||||
|
||||
mapping_board = []
|
||||
d['board'] = mapping_board
|
||||
|
||||
for board in cont.boards:
|
||||
filename = board.names[0].name + '.bin'
|
||||
|
||||
b = {}
|
||||
b['names'] = board.get_names_as_str()
|
||||
b['data'] = filename
|
||||
mapping_board.append(b)
|
||||
|
||||
f = open(filename, 'wb')
|
||||
f.write(board.data.data)
|
||||
f.close()
|
||||
|
||||
print("%s created size: %d" % (filename, len(board.data.data)))
|
||||
|
||||
mapping_regdb = []
|
||||
d['regdb'] = mapping_regdb
|
||||
|
||||
for regdb in cont.regdbs:
|
||||
filename = regdb.names[0].name + '.regdb'
|
||||
|
||||
b = {}
|
||||
b['names'] = regdb.get_names_as_str()
|
||||
b['data'] = filename
|
||||
mapping_regdb.append(b)
|
||||
|
||||
f = open(filename, 'wb')
|
||||
f.write(regdb.data.data)
|
||||
f.close()
|
||||
|
||||
print("%s created size: %d" % (filename, len(regdb.data.data)))
|
||||
|
||||
filename = DEFAULT_JSON_FILE
|
||||
f = open(filename, 'w')
|
||||
f.write(json.dumps(mapping, indent=4))
|
||||
f.close()
|
||||
|
||||
print("%s created" % (filename))
|
||||
|
||||
|
||||
def cmd_info(args):
|
||||
filename = args.info
|
||||
|
||||
cont = BoardContainer().open(filename)
|
||||
|
||||
print(cont.get_summary())
|
||||
|
||||
|
||||
def cmd_diff(args):
|
||||
if args.diff:
|
||||
filename1 = args.diff[0]
|
||||
filename2 = args.diff[1]
|
||||
else:
|
||||
filename1 = args.diffstat[0]
|
||||
filename2 = args.diffstat[1]
|
||||
|
||||
print(diff_boardfiles(filename1, filename2, args.diff))
|
||||
|
||||
|
||||
def diff_boardfiles(filename1, filename2, diff):
|
||||
result = ''
|
||||
|
||||
container1 = BoardContainer().open(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp()
|
||||
os.write(temp1_fd, container1.get_summary(sort=True).encode())
|
||||
|
||||
container2 = BoardContainer().open(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp()
|
||||
os.write(temp2_fd, container2.get_summary(sort=True).encode())
|
||||
|
||||
# this function is used both with --diff and --diffstat
|
||||
if diff:
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
print('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
print('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
result += '%s\n' % (output.decode())
|
||||
|
||||
# create simple statistics about changes in board images
|
||||
new_boards = {}
|
||||
deleted_boards = {}
|
||||
changed_boards = {}
|
||||
|
||||
for board in container2.boards:
|
||||
# convert the list to a string
|
||||
s = pretty_array_str(board.get_names_as_str())
|
||||
new_boards[s] = board
|
||||
|
||||
for board in container1.boards:
|
||||
# convert the list to a string
|
||||
names = pretty_array_str(board.get_names_as_str())
|
||||
|
||||
if names not in new_boards:
|
||||
# board image has been deleted
|
||||
deleted_boards[names] = board
|
||||
continue
|
||||
|
||||
board2 = new_boards[names]
|
||||
del new_boards[names]
|
||||
|
||||
if board.data.data == board2.data.data:
|
||||
# board image hasn't changed
|
||||
continue
|
||||
|
||||
# board image has changed
|
||||
changed_boards[names] = board2
|
||||
|
||||
result += 'New board:\n%s\n\n' % ('\n'.join(list(new_boards.keys())))
|
||||
result += 'Changed board:\n%s\n\n' % ('\n'.join(list(changed_boards.keys())))
|
||||
result += 'Deleted board:\n%s\n' % ('\n'.join(list(deleted_boards.keys())))
|
||||
|
||||
result += '%d board image(s) added, %d changed, %d deleted, %d in total\n\n' % (len(new_boards),
|
||||
len(changed_boards),
|
||||
len(deleted_boards),
|
||||
len(container2.boards))
|
||||
|
||||
# create simple statistics about changes in regdb images
|
||||
new_regdbs = {}
|
||||
deleted_regdbs = {}
|
||||
changed_regdbs = {}
|
||||
|
||||
for regdb in container2.regdbs:
|
||||
# convert the list to a string
|
||||
s = pretty_array_str(regdb.get_names_as_str())
|
||||
new_regdbs[s] = regdb
|
||||
|
||||
for regdb in container1.regdbs:
|
||||
# convert the list to a string
|
||||
names = pretty_array_str(regdb.get_names_as_str())
|
||||
|
||||
if names not in new_regdbs:
|
||||
# regdb image has been deleted
|
||||
deleted_regdbs[names] = regdb
|
||||
continue
|
||||
|
||||
regdb2 = new_regdbs[names]
|
||||
del new_regdbs[names]
|
||||
|
||||
if regdb.data.data == regdb2.data.data:
|
||||
# regdb image hasn't changed
|
||||
continue
|
||||
|
||||
# regdb image has changed
|
||||
changed_regdbs[names] = regdb2
|
||||
|
||||
result += 'New regdb:\n%s\n\n' % ('\n'.join(list(new_regdbs.keys())))
|
||||
result += 'Changed regdb:\n%s\n\n' % ('\n'.join(list(changed_regdbs.keys())))
|
||||
result += 'Deleted regdb:\n%s\n' % ('\n'.join(list(deleted_regdbs.keys())))
|
||||
|
||||
result += '%d regdb image(s) added, %d changed, %d deleted, %d in total' % (len(new_regdbs),
|
||||
len(changed_regdbs),
|
||||
len(deleted_regdbs),
|
||||
len(container2.regdbs))
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def cmd_create(args):
|
||||
mapping_file = args.create
|
||||
|
||||
if args.output:
|
||||
output = args.output
|
||||
else:
|
||||
output = DEFAULT_BOARD_FILE
|
||||
|
||||
cont = BoardContainer.open_json(mapping_file)
|
||||
cont.write(output)
|
||||
|
||||
|
||||
def cmd_add_board(args):
|
||||
if len(args.add_board) < 3:
|
||||
print('error: --add-board requires 3 or more arguments, only %d given' % (len(args.add_board)))
|
||||
sys.exit(1)
|
||||
|
||||
board_filename = args.add_board[0]
|
||||
new_filename = args.add_board[1]
|
||||
new_names = args.add_board[2:]
|
||||
|
||||
f = open(new_filename, 'rb')
|
||||
new_data = f.read()
|
||||
f.close()
|
||||
|
||||
# copy the original file for diff
|
||||
(temp_fd, temp_pathname) = tempfile.mkstemp()
|
||||
shutil.copyfile(board_filename, temp_pathname)
|
||||
|
||||
container = BoardContainer.open(board_filename)
|
||||
container.add_board(new_data, new_names)
|
||||
container.write(board_filename)
|
||||
|
||||
print(diff_boardfiles(temp_pathname, board_filename, False))
|
||||
|
||||
os.remove(temp_pathname)
|
||||
|
||||
|
||||
def main():
|
||||
description = '''ath12k board-N.bin files manegement tool
|
||||
|
||||
ath12k-bdencoder is for creating (--create), listing (--info) and
|
||||
comparing (--diff, --diffstat) ath12k board-N.bin files. The
|
||||
board-N.bin is a container format which can have unlimited number of
|
||||
actual board images ("board files"), each image containing one or
|
||||
names which ath12k uses to find the correct image.
|
||||
|
||||
For creating board files you need a mapping file in JSON which
|
||||
contains the names and filenames for the actual binary:
|
||||
|
||||
[
|
||||
{
|
||||
"board": [
|
||||
{"names": ["AAA1", "AAAA2"], "data": "A.bin"},
|
||||
{"names": ["B"], "data": "B.bin"},
|
||||
{"names": ["C"], "data": "C.bin"},
|
||||
],
|
||||
"regdb": [
|
||||
{"names": ["A"], "data": "A.regdb"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
In this example the board-N.bin will contain three board files which
|
||||
are read from files named A.bin (using names AAA1 and AAAA2 in the
|
||||
board-N.bin file), B.bin (using name B) and C.bin (using name C). The file also contains one regdb (regulatory database) from file A.regdb.
|
||||
|
||||
You can use --extract switch to see examples from real board-N.bin
|
||||
files.
|
||||
'''
|
||||
|
||||
parser = argparse.ArgumentParser(description=description,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
cmd_group = parser.add_mutually_exclusive_group(required=True)
|
||||
cmd_group.add_argument("-c", "--create", metavar='JSON_FILE',
|
||||
help='create board-N.bin from a mapping file in JSON format')
|
||||
cmd_group.add_argument("-e", "--extract", metavar='BOARD_FILE',
|
||||
help='extract board-N.bin file to a JSON mapping file and individual board files, compatible with the format used with --create command')
|
||||
cmd_group.add_argument("-i", "--info", metavar='BOARD_FILE',
|
||||
help='show all details about a board-N.bin file')
|
||||
cmd_group.add_argument('-d', '--diff', metavar='BOARD_FILE', nargs=2,
|
||||
help='show differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-D', '--diffstat', metavar='BOARD_FILE', nargs=2,
|
||||
help='show a summary of differences between two board-N.bin files')
|
||||
cmd_group.add_argument('-a', '--add-board', metavar='NAME', nargs='+',
|
||||
help='add a board file to an existing board-N.bin, first argument is the filename of board-N.bin to add to, second is the filename board file (board.bin) to add and then followed by one or more arguments are names used in board-N.bin')
|
||||
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='enable verbose (debug) messages')
|
||||
parser.add_argument("-o", "--output", metavar="BOARD_FILE",
|
||||
help='name of the output file, otherwise the default is: %s' %
|
||||
(DEFAULT_BOARD_FILE))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if args.create:
|
||||
return cmd_create(args)
|
||||
elif args.extract:
|
||||
return cmd_extract(args)
|
||||
elif args.info:
|
||||
return cmd_info(args)
|
||||
elif args.diff:
|
||||
return cmd_diff(args)
|
||||
elif args.diffstat:
|
||||
return cmd_diff(args)
|
||||
elif args.add_board:
|
||||
return cmd_add_board(args)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
614
tools/scripts/ath12k/ath12k-check
Executable file
614
tools/scripts/ath12k/ath12k-check
Executable file
|
|
@ -0,0 +1,614 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
# Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# Run 'ath12k-check --help' to see the instructions
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
import tempfile
|
||||
import queue
|
||||
import threading
|
||||
import string
|
||||
import hashlib
|
||||
import shutil
|
||||
|
||||
CHECKPATCH_COMMIT = '99b70ece33d87500ef7bee8e32cb99772c45ce14'
|
||||
CHECKPATCH_MD5SUM = 'b3c97930952745672f3408dabc244843'
|
||||
|
||||
GIT_URL = 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl?id=%s'
|
||||
|
||||
DRIVER_DIR = 'drivers/net/wireless/ath/ath12k/'
|
||||
|
||||
FILTER_REGEXP = r'/ath'
|
||||
|
||||
# Example: CONFIG_CC_VERSION_TEXT="x86_64-linux-gcc (GCC) 13.2.0"
|
||||
CONFIG_CC_REGEXP = r'^CONFIG_CC_VERSION_TEXT="(.*)"$'
|
||||
|
||||
IGNORE_FILES = []
|
||||
|
||||
CHECKPATCH_IGNORE = [
|
||||
# some find extra parentheses helpful so ignore the warnings
|
||||
'UNNECESSARY_PARENTHESES',
|
||||
]
|
||||
|
||||
CHECKPATCH_OPTS = ['--strict', '-q', '--terse', '--no-summary',
|
||||
'--max-line-length=90', '--show-types']
|
||||
|
||||
checkpatch_filter = [
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_eht_non_mumimo_user', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_ndp', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_eht_sig_non_ofdma', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_non_ofdma_users', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_user_info', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_hal_rx_parse_usig_overflow', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_parse_he_sig_b1_mu', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_parse_he_sig_b2_mu', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_parse_he_sig_mu', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_rx_handle_ofdma_info', 'LONG_LINE'),
|
||||
('ath12k_wifi7_dp_mon_rx_populate_mu_user_info', 'LONG_LINE'),
|
||||
('qmi_wlanfw_respond_mem_req_msg_v01', 'LONG_LINE'),
|
||||
('qmi_wlanfw_host_cap_req_msg_v01', 'LONG_LINE'),
|
||||
('qmi_wlfw_qdss_trace_config_download_req_msg_v01_ei', 'LONG_LINE'),
|
||||
('qmi_wlanfw_qdss_trace_config_download_resp_msg_v01_ei', 'LONG_LINE'),
|
||||
|
||||
# workaround for long lines in
|
||||
# qmi_wlfw_qdss_trace_config_download_req_msg_v01_ei, for some
|
||||
# reason gtags claim they are part of
|
||||
# ATH12K_QMI_MAX_CHUNK_SIZE
|
||||
('ATH12K_QMI_MAX_CHUNK_SIZE', 'LONG_LINE'),
|
||||
|
||||
# allow long line copyrights
|
||||
# note gtags returns None so search for the literal string
|
||||
('Copyright (c)', 'LONG_LINE_COMMENT'),
|
||||
|
||||
# trace.h has warnings which don't make sense to fix
|
||||
('TRACE_SYSTEM', 'OPEN_ENDED_LINE'),
|
||||
|
||||
# couldn't figure out how to make checkpatch happy with these macros
|
||||
('SVC', 'COMPLEX_MACRO'),
|
||||
('C2S', 'COMPLEX_MACRO'),
|
||||
('C2S', 'MACRO_WITH_FLOW_CONTROL'),
|
||||
|
||||
# this use of volatile should be ok
|
||||
('ath12k_hal_srng_access_begin', 'VOLATILE'),
|
||||
('ath12k_hal_srng_access_end', 'VOLATILE'),
|
||||
('hal_srng', 'VOLATILE'),
|
||||
|
||||
# __ath12k_dbg has to use dev_printk() so that debug_mask always work
|
||||
('__ath12k_dbg', 'PREFER_DEV_LEVEL'),
|
||||
('__ath12k_dbg', 'PREFER_PR_LEVEL'),
|
||||
|
||||
# couldn't figure a way to avoid the reuse warning
|
||||
('for_each_ar', 'MACRO_ARG_REUSE'),
|
||||
]
|
||||
|
||||
sparse_filter = [
|
||||
# sparse doesn't correctly handle guard()
|
||||
r'warning: context imbalance in .* - wrong count at exit',
|
||||
]
|
||||
|
||||
# global variables
|
||||
|
||||
logger = logging.getLogger('ath12k-check')
|
||||
|
||||
threads = 1
|
||||
|
||||
|
||||
class CPWarning():
|
||||
|
||||
def __str__(self):
|
||||
return 'CPWarning(%s, %s, %s, %s, %s)' % (self.path, self.lineno,
|
||||
self.tag, self.type,
|
||||
self.msg)
|
||||
|
||||
def __init__(self):
|
||||
self.path = ''
|
||||
self.lineno = ''
|
||||
self.type = ''
|
||||
self.msg = ''
|
||||
self.tag = ''
|
||||
|
||||
|
||||
def run_gcc(args):
|
||||
# to disable utf-8 from gcc, easier to paste that way
|
||||
os.environ['LC_CTYPE'] = 'C'
|
||||
|
||||
cmd = 'find %s -name "*.o" -type f -delete' % (DRIVER_DIR)
|
||||
logger.debug('%s' % cmd)
|
||||
subprocess.call(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
cmd = ['make', '-k', '-j', str(threads)]
|
||||
|
||||
if not args.no_extra:
|
||||
cmd.append('W=1')
|
||||
|
||||
cmd.append(DRIVER_DIR)
|
||||
|
||||
env = os.environ.copy()
|
||||
|
||||
# disable ccache in case it's in use, it's useless as we are
|
||||
# compiling only few files and it also breaks GCC's
|
||||
# -Wimplicit-fallthrough check
|
||||
env['CCACHE_DISABLE'] = '1'
|
||||
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=env, universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def run_sparse(args):
|
||||
cmd = ['make', '-k', '-j',
|
||||
str(threads), DRIVER_DIR, 'C=2', 'CF="-D__CHECK_ENDIAN__"']
|
||||
logger.debug('%s' % cmd)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
|
||||
stderr = stderr.strip()
|
||||
|
||||
if len(stderr) > 0:
|
||||
for line in stderr.splitlines():
|
||||
match = re.search(FILTER_REGEXP, line)
|
||||
if not args.no_filter and not match:
|
||||
logger.debug('FILTERED: %s' % line)
|
||||
continue
|
||||
|
||||
drop = False
|
||||
|
||||
for f in sparse_filter:
|
||||
match = re.search(f, line)
|
||||
if not args.no_filter and match:
|
||||
logger.debug('sparse_filter: %s' % line)
|
||||
drop = True
|
||||
break
|
||||
|
||||
if not drop:
|
||||
print(line.strip())
|
||||
|
||||
return p.returncode
|
||||
|
||||
|
||||
def find_tagname(tag_map, filename, lineno):
|
||||
if filename.find('Kconfig') != -1:
|
||||
return None
|
||||
|
||||
if filename not in tag_map:
|
||||
return None
|
||||
|
||||
# we need the tags sorted per linenumber
|
||||
sorted_tags = sorted(tag_map[filename], key=lambda tup: tup[0])
|
||||
|
||||
lineno = int(lineno)
|
||||
|
||||
prev = None
|
||||
|
||||
# find the tag which is in lineno
|
||||
for (l, tag) in sorted_tags:
|
||||
if l > lineno:
|
||||
return prev
|
||||
|
||||
prev = tag
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def parse_checkpatch_warning(line):
|
||||
m = re.match(r'(.*?):(\d+): .*?:(.*?): (.*)', line, re.M | re.I)
|
||||
result = CPWarning()
|
||||
result.path = m.group(1)
|
||||
result.lineno = m.group(2)
|
||||
result.type = m.group(3)
|
||||
result.msg = m.group(4)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def is_filtered(cpwarning):
|
||||
for (tag, type) in checkpatch_filter:
|
||||
if cpwarning.tag is not None:
|
||||
# the global tool was able to find a tag name for this
|
||||
# line so use it directly
|
||||
matchobj = re.match(tag, cpwarning.tag)
|
||||
if matchobj is None:
|
||||
continue
|
||||
|
||||
if cpwarning.type == type:
|
||||
return True
|
||||
else:
|
||||
# the global tool was not able to find a tag name for this
|
||||
# line so instead check the actual line in the file
|
||||
f = open(cpwarning.path)
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
lineno = int(cpwarning.lineno) - 1
|
||||
lines = buf.splitlines()
|
||||
line = lines[lineno]
|
||||
logger.debug('file %r tag %r line %r' % (cpwarning.path, tag, line))
|
||||
|
||||
if tag in line:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_checkpatch_md5sum():
|
||||
path = shutil.which('checkpatch.pl')
|
||||
f = open(path, 'rb')
|
||||
md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
return md5sum
|
||||
|
||||
def get_checkpatch_cmdline():
|
||||
return ['checkpatch.pl'] + CHECKPATCH_OPTS + \
|
||||
['--ignore', ",".join(CHECKPATCH_IGNORE)]
|
||||
|
||||
|
||||
def run_checkpatch_cmd(args, q, tag_map):
|
||||
checkpatch_cmd = get_checkpatch_cmdline() + ['-f']
|
||||
|
||||
while True:
|
||||
try:
|
||||
f = q.get_nowait()
|
||||
except queue.Empty:
|
||||
# no more files to check
|
||||
break
|
||||
|
||||
cmd = checkpatch_cmd + [f]
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
(stdoutdata, stderrdata) = p.communicate()
|
||||
|
||||
if stdoutdata is None:
|
||||
continue
|
||||
|
||||
lines = stdoutdata.splitlines()
|
||||
for line in lines:
|
||||
w = parse_checkpatch_warning(line)
|
||||
w.tag = find_tagname(tag_map, f, w.lineno)
|
||||
|
||||
if not args.no_filter and is_filtered(w):
|
||||
logger.debug('FILTERED: %s' % w)
|
||||
continue
|
||||
|
||||
logger.debug(w)
|
||||
print('%s:%s: %s' % (w.path, w.lineno, w.msg))
|
||||
|
||||
q.task_done()
|
||||
|
||||
# get all driver files which are commited to git, includes Kconfig, Makefile etc
|
||||
def get_commited_files():
|
||||
cmd = ['git', 'ls-tree', '-r', '--name-only', 'HEAD', DRIVER_DIR]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
return output.splitlines()
|
||||
|
||||
def run_checkpatch(args):
|
||||
md5sum = get_checkpatch_md5sum()
|
||||
if md5sum != CHECKPATCH_MD5SUM:
|
||||
print('WARNING: checkpatch.pl md5sum %s does not match with %s' %
|
||||
(md5sum, CHECKPATCH_MD5SUM))
|
||||
|
||||
driver_files = get_commited_files()
|
||||
|
||||
# drop files we need to ignore
|
||||
for name in IGNORE_FILES:
|
||||
full_name = '%s%s' % (DRIVER_DIR, name)
|
||||
if full_name in driver_files:
|
||||
driver_files.remove(full_name)
|
||||
|
||||
logger.debug('driver_files: %s' % (driver_files))
|
||||
|
||||
# create global index file
|
||||
(fd, tmpfilename) = tempfile.mkstemp()
|
||||
f = os.fdopen(fd, 'w')
|
||||
f.write('\n'.join(driver_files))
|
||||
f.close()
|
||||
|
||||
# FIXME: do we need to call os.close(fd) still?
|
||||
|
||||
cmd = 'gtags -f %s' % (tmpfilename)
|
||||
logger.debug('%s' % (cmd))
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
|
||||
os.remove(tmpfilename)
|
||||
|
||||
# tag_map[FILENAME] = [(start line, tagname)]
|
||||
tag_map = {}
|
||||
|
||||
# create tag mapping
|
||||
for f in driver_files:
|
||||
# global gives an error from Kconfig and Makefile
|
||||
if f.endswith('Kconfig') or f.endswith('Makefile'):
|
||||
continue
|
||||
|
||||
cmd = 'global -f %s' % (f)
|
||||
output = subprocess.check_output(cmd, shell=True, universal_newlines=True)
|
||||
lines = output.splitlines()
|
||||
for l in lines:
|
||||
columns = l.split()
|
||||
tagname = columns[0]
|
||||
line = int(columns[1])
|
||||
|
||||
if f not in tag_map:
|
||||
tag_map[f] = []
|
||||
|
||||
tag_map[f].append((line, tagname))
|
||||
|
||||
q = queue.Queue()
|
||||
|
||||
for f in driver_files:
|
||||
q.put(f)
|
||||
|
||||
# run checkpatch for all files
|
||||
for i in range(threads):
|
||||
t = threading.Thread(
|
||||
target=run_checkpatch_cmd, args=(args, q, tag_map))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
q.join()
|
||||
|
||||
return 0
|
||||
|
||||
def run_kdoc(args):
|
||||
p = subprocess.run(['scripts/kernel-doc', '-Werror', '-none'] +
|
||||
get_commited_files())
|
||||
return p.returncode
|
||||
|
||||
def show_version(args):
|
||||
host_gcc_version = 'not found'
|
||||
config_cc_version = 'not found'
|
||||
sparse_version = 'not found'
|
||||
checkpatch_version = 'not found'
|
||||
checkpatch_md5sum = 'N/A'
|
||||
gtags_version = 'not found'
|
||||
|
||||
run = subprocess.check_output
|
||||
|
||||
f = open(sys.argv[0], 'rb')
|
||||
ath12kcheck_md5sum = hashlib.md5(f.read()).hexdigest()
|
||||
f.close()
|
||||
|
||||
try:
|
||||
host_gcc_version = run(['gcc', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
f = open('.config')
|
||||
m = re.search(CONFIG_CC_REGEXP, f.read(), re.MULTILINE)
|
||||
if m is not None:
|
||||
config_cc_version = m.group(1)
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
sparse_version = run(['sparse', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
checkpatch_version = run(['checkpatch.pl', '--version'],
|
||||
universal_newlines=True).splitlines()[1]
|
||||
checkpatch_md5sum = get_checkpatch_md5sum()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
gtags_version = run(['gtags', '--version'],
|
||||
universal_newlines=True).splitlines()[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
print('ath12k-check (md5sum %s)' % (ath12kcheck_md5sum))
|
||||
print()
|
||||
print('python:\t\t%s' % (sys.version))
|
||||
print('host gcc:\t%s' % (host_gcc_version))
|
||||
print('config cc:\t%s' % (config_cc_version))
|
||||
print('sparse:\t\t%s' % (sparse_version))
|
||||
print('checkpatch.pl:\t%s (md5sum %s)' % (checkpatch_version, checkpatch_md5sum))
|
||||
print('gtags:\t\t%s' % (gtags_version))
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
global threads
|
||||
|
||||
checkpatch_url = GIT_URL % (CHECKPATCH_COMMIT)
|
||||
|
||||
description = '''ath12k source code checker
|
||||
|
||||
Runs various tests (gcc, sparse and checkpatch) with filtering
|
||||
unnecessary warnings away, the goal is to have empty output from the
|
||||
script.
|
||||
|
||||
Run this from the main kernel source directory which is preconfigured
|
||||
with ath12k enabled. gcc recompilation of ath12k is forced every time,
|
||||
irrespective if there are any changes in source or not. So this can be
|
||||
run multiple times and every time the same warnings will appear.
|
||||
|
||||
Requirements (all available in $PATH):
|
||||
|
||||
* gcc
|
||||
* sparse
|
||||
* checkpatch.pl
|
||||
* gtags (from package global)
|
||||
|
||||
'''
|
||||
|
||||
s = '''Installation:
|
||||
|
||||
It is assumed below that ~/bin is part of user's $$PATH. If it's not,
|
||||
replace ~/bin with a suitable directory.
|
||||
|
||||
To install or update to the latest version of ath12k-check:
|
||||
|
||||
wget https://github.com/qca/qca-swiss-army-knife/raw/master/tools/scripts/ath12k/ath12k-check
|
||||
cp ath12k-check ~/bin/
|
||||
|
||||
It's strongly recommend to use the latest GCC version from crosstool:
|
||||
|
||||
https://mirrors.edge.kernel.org/pub/tools/crosstool/
|
||||
|
||||
Unpack the compiler for example to /opt/cross/ and in the Linux kernel
|
||||
sources create a new file called GNUmakefile with contents:
|
||||
|
||||
ARCH=x86
|
||||
CROSS_COMPILE=/opt/cross/gcc-13.2.0-nolibc/x86_64-linux/bin/x86_64-linux-
|
||||
export ARCH
|
||||
export CROSS_COMPILE
|
||||
|
||||
Now the kernel will be compiled with the compiler from /opt/cross.
|
||||
|
||||
Latest development version of sparse is needed, install it manually
|
||||
from the git repository:
|
||||
|
||||
git clone https://git.kernel.org/pub/scm/devel/sparse/sparse.git/
|
||||
cd sparse
|
||||
make
|
||||
cp sparse ~/bin/
|
||||
|
||||
As checkpatch is evolving and new tests are added, it's important that
|
||||
a correct version of checkpatch is used. If a wrong version is used
|
||||
ath12k-check will warn about that. To download the correct checkpatch
|
||||
version and install it to ~/bin:
|
||||
|
||||
wget -O checkpatch.pl $CHECKPATCH_URL
|
||||
cp checkpatch.pl ~/bin/
|
||||
|
||||
Note that the URL in above wget command is dynamically created and
|
||||
will change everytime ath12k-check is updated to use a new version of
|
||||
checkpatch.pl
|
||||
|
||||
For gtags program you need to install package named global, for
|
||||
example in Debian/Ubuntu you can do that using apt:
|
||||
|
||||
apt install global
|
||||
|
||||
Alternatively (but not recommended!) if you want manually run
|
||||
checkpatch with the same settings as ath12k-check uses here's the
|
||||
command line:
|
||||
|
||||
$CHECKPATCH_CMDLINE
|
||||
'''
|
||||
|
||||
checkpatch_cmdline = '%s foo.patch' % ' '.join(get_checkpatch_cmdline())
|
||||
epilog = string.Template(s).substitute(CHECKPATCH_URL=checkpatch_url,
|
||||
CHECKPATCH_CMDLINE=checkpatch_cmdline)
|
||||
|
||||
parser = argparse.ArgumentParser(description=description, epilog=epilog,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
parser.add_argument('-d', '--debug', action='store_true',
|
||||
help='enable debug messages')
|
||||
|
||||
parser.add_argument('--fast', action='store_true',
|
||||
help='run only tests which finish in few seconds')
|
||||
|
||||
parser.add_argument('--no-extra', action='store_true',
|
||||
help='Do not run extra checks like W=1')
|
||||
|
||||
parser.add_argument('--no-filter', action='store_true',
|
||||
help='Don\'t filter output with regexp: %r' % (FILTER_REGEXP))
|
||||
|
||||
parser.add_argument('--version', action='store_true',
|
||||
help='Show version information about dependencies')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
timefmt = ''
|
||||
|
||||
if args.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
timefmt = '%(asctime)s '
|
||||
|
||||
logfmt = '%s%%(levelname)s: %%(message)s' % (timefmt)
|
||||
|
||||
logging.basicConfig(format=logfmt)
|
||||
|
||||
if args.version:
|
||||
show_version(args)
|
||||
|
||||
if args.fast:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = False
|
||||
else:
|
||||
gcc = True
|
||||
sparse = True
|
||||
checkpatch = True
|
||||
|
||||
try:
|
||||
cores = subprocess.check_output(['nproc'], universal_newlines=True)
|
||||
except OSError as xxx_todo_changeme:
|
||||
subprocess.CalledProcessError = xxx_todo_changeme
|
||||
cores = '4'
|
||||
logger.warning('Failed to run nproc, assuming %s cores' % (cores))
|
||||
|
||||
threads = int(cores) + 2
|
||||
|
||||
logger.debug('threads %d' % (threads))
|
||||
|
||||
if gcc:
|
||||
ret = run_gcc(args)
|
||||
if ret != 0:
|
||||
logger.debug('gcc failed: %d', ret)
|
||||
sys.exit(1)
|
||||
|
||||
if sparse:
|
||||
ret = run_sparse(args)
|
||||
if ret != 0:
|
||||
logger.debug('sparse failed: %d', ret)
|
||||
sys.exit(2)
|
||||
|
||||
if checkpatch:
|
||||
ret = run_checkpatch(args)
|
||||
if ret != 0:
|
||||
logger.debug('checkpatch failed: %d', ret)
|
||||
sys.exit(3)
|
||||
|
||||
ret = run_kdoc(args)
|
||||
if ret != 0:
|
||||
logger.debug('kernel-doc failed: %d', ret)
|
||||
sys.exit(4)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1185
tools/scripts/ath12k/ath12k-fw-repo
Executable file
1185
tools/scripts/ath12k/ath12k-fw-repo
Executable file
File diff suppressed because it is too large
Load diff
724
tools/scripts/ath12k/ath12k-fwencoder
Executable file
724
tools/scripts/ath12k/ath12k-fwencoder
Executable file
|
|
@ -0,0 +1,724 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
|
||||
# Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
# Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import ctypes
|
||||
import struct
|
||||
import optparse
|
||||
import time
|
||||
import math
|
||||
import logging
|
||||
import sys
|
||||
import os.path
|
||||
import traceback
|
||||
import binascii
|
||||
import tempfile
|
||||
import subprocess
|
||||
import hashlib
|
||||
|
||||
DEFAULT_FW_API_VERSION = 2
|
||||
|
||||
ATH12K_SIGNATURE = b'QCOM-ATH12K-FW'
|
||||
MAX_LEN = 50000000
|
||||
|
||||
ATH12K_FW_IE_TIMESTAMP = 0
|
||||
ATH12K_FW_IE_FEATURES = 1
|
||||
ATH12K_FW_IE_AMSS_IMAGE = 2
|
||||
ATH12K_FW_IE_M3_IMAGE = 3
|
||||
ATH12K_FW_IE_AMSS_DUALMAC_IMAGE = 4
|
||||
|
||||
# enum ath12k_fw_features from ath12k/fw.h
|
||||
ATH12K_FW_FEATURE_MULTI_QRTR_ID = 0
|
||||
ATH12K_FW_FEATURE_MLO = 1
|
||||
ATH12K_FW_FEATURE_MAX = 2
|
||||
|
||||
feature_map = {
|
||||
'multi-qrtr-id': ATH12K_FW_FEATURE_MULTI_QRTR_ID,
|
||||
'mlo': ATH12K_FW_FEATURE_MLO,
|
||||
}
|
||||
|
||||
# global variables
|
||||
logger = None
|
||||
|
||||
|
||||
class FWEncoderError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_output_name(fw_api=None):
|
||||
if fw_api is not None:
|
||||
api = fw_api
|
||||
else:
|
||||
api = DEFAULT_FW_API_VERSION
|
||||
|
||||
return 'firmware-%s.bin' % api
|
||||
|
||||
|
||||
class FirmwareContainer:
|
||||
|
||||
def add_element(self, type_id, value):
|
||||
length = len(value)
|
||||
padding_len = padding_needed(length)
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
logger.debug('adding id %d len(value) %d'
|
||||
'padding_len %d' % (type_id,
|
||||
len(value),
|
||||
padding_len))
|
||||
fmt = '<ii%ds%ds' % (len(value), padding_len)
|
||||
struct.pack_into(fmt, self.buf, self.buf_len, type_id, len(value),
|
||||
value, padding.raw)
|
||||
self.buf_len = self.buf_len + 4 + 4 + len(value) + padding_len
|
||||
|
||||
def add_u32(self, type_id, value):
|
||||
if not type(value) is int:
|
||||
raise FWEncoderError('u32 IE %d is not int: %s' %
|
||||
(type_id, str(value)))
|
||||
|
||||
buf = ctypes.create_string_buffer(4)
|
||||
struct.pack_into("<i", buf, 0, value)
|
||||
self.add_element(type_id, buf.raw)
|
||||
|
||||
def read_u32(self, type_id):
|
||||
(val,) = struct.unpack_from("<i", self.elements[type_id])
|
||||
return val
|
||||
|
||||
def add_bitmap(self, ie, enabled, maximum):
|
||||
|
||||
if (max(enabled) >= maximum):
|
||||
logger.error("bitmap %d out of maximum (%d >= %d)" %
|
||||
(ie, max(enabled), maximum))
|
||||
return
|
||||
|
||||
bytes = [0] * maximum
|
||||
|
||||
for i in range(maximum):
|
||||
if i not in enabled:
|
||||
continue
|
||||
|
||||
max_set = i
|
||||
index = int(i / 8)
|
||||
bit = i % 8
|
||||
bytes[index] = bytes[index] | (1 << bit)
|
||||
|
||||
# remove trailing null bits away, that changing only
|
||||
# maximum doesn't affect created binary size
|
||||
length = int(math.ceil((max_set + 1) / float(8)))
|
||||
bytes = bytes[:length]
|
||||
|
||||
buf = ctypes.create_string_buffer(length)
|
||||
|
||||
for index in range(length):
|
||||
struct.pack_into('<B', buf, index, bytes[index])
|
||||
|
||||
self.add_element(ie, buf.raw)
|
||||
|
||||
def read_bitmap(self, ie):
|
||||
buf = self.elements[ie]
|
||||
length = len(buf)
|
||||
|
||||
bits = []
|
||||
|
||||
for index in range(length):
|
||||
val = struct.unpack_from('<B', buf, index)[0]
|
||||
|
||||
for bit in range(8):
|
||||
if val & 0x1:
|
||||
bits.append(index * 8 + bit)
|
||||
|
||||
val = val >> 1
|
||||
|
||||
return bits
|
||||
|
||||
def set_signature(self, signature):
|
||||
self.signature = signature
|
||||
self.signature_len = len(signature)
|
||||
|
||||
# include the null byte
|
||||
length = len(signature) + 1
|
||||
|
||||
padding_len = padding_needed(length)
|
||||
|
||||
length = length + padding_len
|
||||
|
||||
padding = ctypes.create_string_buffer(padding_len)
|
||||
|
||||
for i in range(padding_len):
|
||||
struct.pack_into('<B', padding, i, 0x77)
|
||||
|
||||
fmt = '<%dsb%ds' % (len(signature), padding_len)
|
||||
struct.pack_into(fmt, self.buf, 0, signature, 0, padding.raw)
|
||||
self.buf_len = length
|
||||
|
||||
def write(self, name):
|
||||
f = open(name, 'wb')
|
||||
f.write(self.buf.raw[:self.buf_len])
|
||||
f.close()
|
||||
|
||||
return self.buf_len
|
||||
|
||||
def open(self, name):
|
||||
f = open(name, 'rb')
|
||||
self.buf = f.read()
|
||||
self.buf_len = len(self.buf)
|
||||
f.close()
|
||||
|
||||
offset = 0
|
||||
|
||||
fmt = '<%dsb' % (self.signature_len)
|
||||
(signature, null) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + self.signature_len + 1
|
||||
|
||||
if signature != self.signature or null != 0:
|
||||
logger.error("Invalid signature!")
|
||||
return False
|
||||
|
||||
offset = self.signature_len + 1
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements = {}
|
||||
|
||||
while offset + 4 + 4 < self.buf_len:
|
||||
(type_id, length) = struct.unpack_from("<ii", self.buf, offset)
|
||||
offset = offset + 4 + 4
|
||||
|
||||
if offset + length > self.buf_len:
|
||||
logger.error("Buffer too short")
|
||||
return
|
||||
|
||||
fmt = '<%ds' % length
|
||||
(payload,) = struct.unpack_from(fmt, self.buf, offset)
|
||||
offset = offset + length
|
||||
offset = offset + padding_needed(offset)
|
||||
|
||||
self.elements[type_id] = payload
|
||||
|
||||
return True
|
||||
|
||||
def __init__(self, signature):
|
||||
self.buf = ctypes.create_string_buffer(MAX_LEN)
|
||||
self.buf_len = 0
|
||||
|
||||
self.set_signature(signature)
|
||||
|
||||
|
||||
class Ath12kFirmwareContainer(object):
|
||||
def _load_file(self, name):
|
||||
if os.path.getsize(name) > MAX_LEN:
|
||||
raise FWEncoderError('file %s is too large, maximum size is %d' %
|
||||
(name, MAX_LEN))
|
||||
|
||||
f = open(name, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
return buf
|
||||
|
||||
def set_features(self, features):
|
||||
self.features = features.split(',')
|
||||
|
||||
enabled = []
|
||||
for capa in self.features:
|
||||
if capa not in feature_map:
|
||||
print("Error: '%s' not found from the feature map" % capa)
|
||||
return 1
|
||||
|
||||
enabled.append(feature_map[capa])
|
||||
|
||||
self.features_bitmap = enabled
|
||||
|
||||
def get_features(self):
|
||||
s = ""
|
||||
|
||||
if self.features_bitmap is None:
|
||||
return None
|
||||
|
||||
for capa in self.features_bitmap:
|
||||
# find value from the dict
|
||||
try:
|
||||
name = [key for key, value in feature_map.items()
|
||||
if value == capa][0]
|
||||
except IndexError:
|
||||
name = str(capa)
|
||||
|
||||
s = s + name + ","
|
||||
|
||||
# strip last comma
|
||||
if len(s) > 0:
|
||||
s = s[:-1]
|
||||
|
||||
return s
|
||||
|
||||
def set_amss_image(self, amss_image_name):
|
||||
self.amss_image = self._load_file(amss_image_name)
|
||||
|
||||
def get_amss_image(self):
|
||||
return self.amss_image
|
||||
|
||||
def set_amss_dualmac_image(self, amss_dualmac_image_name):
|
||||
self.amss_dualmac_image = self._load_file(amss_dualmac_image_name)
|
||||
|
||||
def get_amss_dualmac_image(self):
|
||||
return self.amss_dualmac_image
|
||||
|
||||
def set_m3_image(self, m3_image_name):
|
||||
self.m3_image = self._load_file(m3_image_name)
|
||||
|
||||
def get_m3_image(self):
|
||||
return self.m3_image
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self.timestamp = int(timestamp)
|
||||
|
||||
def get_timestamp(self):
|
||||
return self.timestamp
|
||||
|
||||
def get_timestamp_as_iso8601(self):
|
||||
if self.timestamp is None:
|
||||
return None
|
||||
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.gmtime(self.timestamp))
|
||||
|
||||
def get_summary(self):
|
||||
s = ''
|
||||
|
||||
s = s + 'FileSize: %s\n' % (len(self.file))
|
||||
s = s + 'FileCRC32: %08x\n' % (_crc32(self.file))
|
||||
s = s + 'FileMD5: %s\n' % (hashlib.md5(self.file).hexdigest())
|
||||
|
||||
if self.get_timestamp():
|
||||
s = s + 'Timestamp: %s\n' % (self.get_timestamp_as_iso8601())
|
||||
|
||||
if self.get_features():
|
||||
s = s + 'Features: %s\n' % (self.get_features())
|
||||
|
||||
if self.get_amss_image():
|
||||
s = s + 'AMSSImageSize: %s\n' % (len(self.get_amss_image()))
|
||||
s = s + 'AMSSImageCRC32: %08x\n' % (_crc32(self.get_amss_image()))
|
||||
|
||||
if self.get_amss_dualmac_image():
|
||||
s = s + 'AMSSDualMacImageSize: %s\n' % (len(self.get_amss_dualmac_image()))
|
||||
s = s + 'AMSSDualMacImageCRC32: %08x\n' % (_crc32(self.get_amss_dualmac_image()))
|
||||
|
||||
if self.get_m3_image():
|
||||
s = s + 'M3ImageSize: %s\n' % (len(self.get_m3_image()))
|
||||
s = s + 'M3ImageCRC32: %08x\n' % (_crc32(self.get_m3_image()))
|
||||
|
||||
return s.strip()
|
||||
|
||||
def load(self, filename):
|
||||
c = FirmwareContainer(ATH12K_SIGNATURE)
|
||||
c.open(filename)
|
||||
|
||||
self.file = c.buf
|
||||
|
||||
for e in c.elements:
|
||||
if e == ATH12K_FW_IE_TIMESTAMP:
|
||||
self.timestamp = c.read_u32(e)
|
||||
elif e == ATH12K_FW_IE_M3_IMAGE:
|
||||
self.m3_image = c.elements[e]
|
||||
elif e == ATH12K_FW_IE_AMSS_IMAGE:
|
||||
self.amss_image = c.elements[e]
|
||||
elif e == ATH12K_FW_IE_AMSS_DUALMAC_IMAGE:
|
||||
self.amss_dualmac_image = c.elements[e]
|
||||
elif e == ATH12K_FW_IE_FEATURES:
|
||||
self.features_bitmap = c.read_bitmap(ATH12K_FW_IE_FEATURES)
|
||||
else:
|
||||
print("Unknown IE: ", e)
|
||||
|
||||
def save(self, filename):
|
||||
self.container = FirmwareContainer(ATH12K_SIGNATURE)
|
||||
|
||||
if self.timestamp:
|
||||
self.container.add_u32(ATH12K_FW_IE_TIMESTAMP, self.timestamp)
|
||||
|
||||
# FIXME: m3 should be after amss_image but that breaks the
|
||||
# current tests
|
||||
if self.m3_image:
|
||||
self.container.add_element(ATH12K_FW_IE_M3_IMAGE, self.m3_image)
|
||||
|
||||
if self.amss_image:
|
||||
self.container.add_element(ATH12K_FW_IE_AMSS_IMAGE, self.amss_image)
|
||||
|
||||
if self.amss_dualmac_image:
|
||||
self.container.add_element(ATH12K_FW_IE_AMSS_DUALMAC_IMAGE, self.amss_dualmac_image)
|
||||
|
||||
# FIXME: features should be before amss_image but that breaks
|
||||
# the current tests
|
||||
if self.features_bitmap:
|
||||
self.container.add_bitmap(ATH12K_FW_IE_FEATURES,
|
||||
self.features_bitmap,
|
||||
ATH12K_FW_FEATURE_MAX)
|
||||
|
||||
return self.container.write(filename)
|
||||
|
||||
def __init__(self):
|
||||
self.timestamp = None
|
||||
self.features = None
|
||||
self.features_bitmap = None
|
||||
self.amss_image = None
|
||||
self.m3_image = None
|
||||
self.amss_dualmac_image = None
|
||||
|
||||
|
||||
# to workaround annoying python feature of returning negative hex values
|
||||
def hex32(val):
|
||||
return val & 0xffffffff
|
||||
|
||||
|
||||
# match with kernel crc32_le(0, buf, buf_len) implementation
|
||||
def _crc32(buf):
|
||||
return hex32(~(hex32(binascii.crc32(buf, 0xffffffff))))
|
||||
|
||||
|
||||
def padding_needed(length):
|
||||
if length % 4 != 0:
|
||||
return 4 - length % 4
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def is_int(val):
|
||||
try:
|
||||
int(val)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def write_file(filename, buf):
|
||||
f = open(filename, 'wb')
|
||||
f.write(buf)
|
||||
f.close
|
||||
|
||||
|
||||
def info(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath12kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print(c.get_summary())
|
||||
|
||||
|
||||
def dump(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath12kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
print("ath12k-fwencoder --create \\")
|
||||
|
||||
if c.get_timestamp() and options.show_timestamp:
|
||||
print("--timestamp=%u \\" % c.get_timestamp())
|
||||
|
||||
if c.get_features():
|
||||
print("--features=%s \\" % c.get_features())
|
||||
|
||||
if c.get_amss_image():
|
||||
name = "amss.bin"
|
||||
print("--amss=%s \\" % name)
|
||||
|
||||
if c.get_amss_dualmac_image():
|
||||
name = "amss_dualmac.bin"
|
||||
print("--amss_dualmac=%s \\" % name)
|
||||
|
||||
if c.get_m3_image():
|
||||
name = "m3.bin"
|
||||
print("--m3=%s \\" % name)
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def extract(options, args):
|
||||
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath12kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if c.get_amss_image():
|
||||
name = "amss.bin"
|
||||
write_file(name, c.get_amss_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_amss_image())))
|
||||
|
||||
if c.get_amss_dualmac_image():
|
||||
name = "amss_dualmac.bin"
|
||||
write_file(name, c.get_amss_dualmac_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_amss_dualmac_image())))
|
||||
|
||||
if c.get_m3_image():
|
||||
name = "m3.bin"
|
||||
write_file(name, c.get_m3_image())
|
||||
print('%s extracted: %d B' % (name, len(c.get_m3_image())))
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def modify(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
c = Ath12kFirmwareContainer()
|
||||
c.load(filename)
|
||||
|
||||
if options.timestamp:
|
||||
stamp = str(int(options.timestamp))
|
||||
else:
|
||||
# if no timestamp provided use the current time so that the
|
||||
# timestamp shows the time of last modication
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.m3:
|
||||
c.set_m3_image(options.m3)
|
||||
|
||||
if options.amss:
|
||||
c.set_amss_image(options.amss)
|
||||
|
||||
if options.amss_dualmac:
|
||||
c.set_amss_dualmac_image(options.amss_dualmac)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
file_len = c.save(filename)
|
||||
|
||||
print('%s modified: %d B' % (filename, file_len))
|
||||
|
||||
|
||||
def create(options):
|
||||
output = get_output_name(options.fw_api)
|
||||
|
||||
if options.output:
|
||||
output = options.output
|
||||
|
||||
c = Ath12kFirmwareContainer()
|
||||
|
||||
# always add a timestamp
|
||||
if options.timestamp:
|
||||
stamp = int(options.timestamp)
|
||||
else:
|
||||
stamp = int(time.time())
|
||||
|
||||
c.set_timestamp(stamp)
|
||||
|
||||
if options.m3:
|
||||
c.set_m3_image(options.m3)
|
||||
|
||||
if options.amss:
|
||||
c.set_amss_image(options.amss)
|
||||
|
||||
if options.amss_dualmac:
|
||||
c.set_amss_dualmac_image(options.amss_dualmac)
|
||||
|
||||
if options.features:
|
||||
c.set_features(options.features)
|
||||
|
||||
file_len = c.save(output)
|
||||
|
||||
print('%s created: %d B' % (output, file_len))
|
||||
|
||||
|
||||
def cmd_crc32(options, args):
|
||||
if len(args) != 1:
|
||||
print('Filename missing')
|
||||
return 1
|
||||
|
||||
filename = args[0]
|
||||
|
||||
f = open(filename, 'rb')
|
||||
buf = f.read()
|
||||
print('%08x' % (_crc32(buf)))
|
||||
f.close()
|
||||
|
||||
|
||||
def cmd_diff(options, args):
|
||||
if len(args) != 2:
|
||||
print('Usage: ath12k-fwencoder --diff FILE FILE')
|
||||
return 1
|
||||
|
||||
filename1 = args[0]
|
||||
filename2 = args[1]
|
||||
|
||||
c1 = Ath12kFirmwareContainer()
|
||||
c1.load(filename1)
|
||||
(temp1_fd, temp1_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp1_pathname, 'w')
|
||||
f.write(c1.get_summary())
|
||||
f.close()
|
||||
|
||||
c2 = Ath12kFirmwareContainer()
|
||||
c2.load(filename2)
|
||||
(temp2_fd, temp2_pathname) = tempfile.mkstemp(text=True)
|
||||
|
||||
# for some reason text=True is not working with mkstemp() so open
|
||||
# the file manually
|
||||
f = open(temp2_pathname, 'w')
|
||||
f.write(c2.get_summary())
|
||||
f.close()
|
||||
|
||||
# '--less-mode' and '--auto-page' would be nice when running on
|
||||
# terminal but don't know how to get the control character
|
||||
# through. For terminal detection sys.stdout.isatty() can be used.
|
||||
cmd = ['wdiff', temp1_pathname, temp2_pathname]
|
||||
|
||||
# wdiff is braindead and returns 1 in a succesfull case
|
||||
try:
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
output = e.output
|
||||
else:
|
||||
logger.error('Failed to run wdiff: %d\n%s' % (e.returncode, e.output))
|
||||
return 1
|
||||
except OSError as e:
|
||||
logger.error('Failed to run wdiff: %s' % (e))
|
||||
return 1
|
||||
|
||||
print(output)
|
||||
|
||||
os.close(temp1_fd)
|
||||
os.close(temp2_fd)
|
||||
|
||||
|
||||
def main():
|
||||
global logger
|
||||
|
||||
logger = logging.getLogger('ath12k-fwencoder')
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s')
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
# actions
|
||||
parser.add_option("-c", "--create", action="store_true", dest="create",
|
||||
help='Create container file '
|
||||
'for ath12k (%s)' % get_output_name())
|
||||
parser.add_option("-D", "--dump-cmdline", action="store_true", dest="dump",
|
||||
help='Show the cmdline used to create '
|
||||
'this container file')
|
||||
parser.add_option('--dump', action='store_true', dest='dump',
|
||||
help='Same as --dump-cmdline '
|
||||
'(for backwards compatibility)')
|
||||
parser.add_option("-e", "--extract", action="store_true", dest="extract",
|
||||
help='Extract binary files from the container file '
|
||||
'and dump cmdline as well')
|
||||
parser.add_option("--info", action="store_true", dest="info",
|
||||
help='Show information about the container file')
|
||||
parser.add_option("--modify", action="store_true", dest="modify",
|
||||
help='Modify the container file')
|
||||
parser.add_option('--crc32', action='store_true', dest='crc32',
|
||||
help='Count crc32 checksum for a file')
|
||||
parser.add_option('--diff', action='store_true', dest='diff',
|
||||
help='Show differences between two firmware files')
|
||||
|
||||
# parameters
|
||||
parser.add_option("-o", "--output", action="store", type="string",
|
||||
dest="output", help='Name of output file')
|
||||
|
||||
# FW IEs, only use long style of option names!
|
||||
parser.add_option("--m3", action="store", type="string",
|
||||
dest="m3",
|
||||
help='Name of m3.bin file')
|
||||
parser.add_option("--amss", action="store", type="string",
|
||||
dest="amss",
|
||||
help='Name of amss.bin file')
|
||||
parser.add_option("--amss_dualmac", action="store", type="string",
|
||||
dest="amss_dualmac",
|
||||
help='Name of amss_dualmac.bin file')
|
||||
parser.add_option("--timestamp", action="store",
|
||||
type="string", dest="timestamp",
|
||||
help='Timestamp to be used (seconds)')
|
||||
|
||||
parser.add_option("--features", action="store",
|
||||
type="string", dest="features",
|
||||
help='feature bits to be enabled: %s' %
|
||||
list(feature_map.keys()))
|
||||
parser.add_option("--set-fw-api", action="store",
|
||||
type="string", dest="fw_api",
|
||||
help='Set firmware API used in creating the name for '
|
||||
'output file (Default: %s)' %
|
||||
DEFAULT_FW_API_VERSION)
|
||||
|
||||
# debug etc
|
||||
parser.add_option('--show-timestamp', action='store_true',
|
||||
dest='show_timestamp',
|
||||
help='Show timestamp in --dump-cmdline action. '
|
||||
'It is not shown by default so that the timestamp would be correct')
|
||||
parser.add_option('-d', '--debug', action='store_true', dest='debug',
|
||||
help='Enable debug messages')
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if options.create:
|
||||
try:
|
||||
return create(options)
|
||||
except FWEncoderError as e:
|
||||
print('Create failed: %s' % e)
|
||||
sys.exit(2)
|
||||
except Exception as e:
|
||||
print('Create failed: %s' % e)
|
||||
traceback.print_exc()
|
||||
sys.exit(3)
|
||||
elif options.dump:
|
||||
return dump(options, args)
|
||||
elif options.extract:
|
||||
return extract(options, args)
|
||||
elif options.info:
|
||||
return info(options, args)
|
||||
elif options.modify:
|
||||
return modify(options, args)
|
||||
elif options.crc32:
|
||||
return cmd_crc32(options, args)
|
||||
elif options.diff:
|
||||
return cmd_diff(options, args)
|
||||
else:
|
||||
print('Action command missing')
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2010 Atheros Communications Inc.
|
||||
#
|
||||
|
|
@ -117,7 +117,7 @@ def powertx_rate1 (val):
|
|||
ofdm_rates["12"] = (val >> 16) & 0xff
|
||||
ofdm_rates["18"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 1", val)
|
||||
print("%010s: 0x%08x" % ("Rate 1", val))
|
||||
|
||||
def powertx_rate2 (val):
|
||||
ofdm_rates["24"] = (val >> 0) & 0xff;
|
||||
|
|
@ -125,7 +125,7 @@ def powertx_rate2 (val):
|
|||
ofdm_rates["48"] = (val >> 16) & 0xff
|
||||
ofdm_rates["54"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 2", val)
|
||||
print("%010s: 0x%08x" % ("Rate 2", val))
|
||||
|
||||
def powertx_rate3 (val):
|
||||
cck_rates["1L"] = (val >> 0) & 0xff;
|
||||
|
|
@ -134,7 +134,7 @@ def powertx_rate3 (val):
|
|||
cck_rates["2L"] = (val >> 16) & 0xff;
|
||||
cck_rates["2S"] = (val >> 24) & 0xff;
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 3", val)
|
||||
print("%010s: 0x%08x" % ("Rate 3", val))
|
||||
|
||||
def powertx_rate4 (val):
|
||||
cck_rates["5.5L"] = (val >> 0) & 0xff;
|
||||
|
|
@ -142,7 +142,7 @@ def powertx_rate4 (val):
|
|||
cck_rates["11L"] = (val >> 16) & 0xff
|
||||
cck_rates["11S"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 4", val)
|
||||
print("%010s: 0x%08x" % ("Rate 4", val))
|
||||
|
||||
def powertx_rate5 (val):
|
||||
mcs_rates_ht20["0"] = (val >> 0) & 0xff;
|
||||
|
|
@ -165,7 +165,7 @@ def powertx_rate5 (val):
|
|||
|
||||
mcs_rates_ht20["5"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 5", val)
|
||||
print("%010s: 0x%08x" % ("Rate 5", val))
|
||||
|
||||
def powertx_rate6 (val):
|
||||
mcs_rates_ht20["6"] = (val >> 0) & 0xff;
|
||||
|
|
@ -173,7 +173,7 @@ def powertx_rate6 (val):
|
|||
mcs_rates_ht20["12"] = (val >> 16) & 0xff
|
||||
mcs_rates_ht20["13"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 6", val)
|
||||
print("%010s: 0x%08x" % ("Rate 6", val))
|
||||
|
||||
def powertx_rate7 (val):
|
||||
mcs_rates_ht40["0"] = (val >> 0) & 0xff;
|
||||
|
|
@ -196,7 +196,7 @@ def powertx_rate7 (val):
|
|||
|
||||
mcs_rates_ht40["5"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 7", val)
|
||||
print("%010s: 0x%08x" % ("Rate 7", val))
|
||||
|
||||
def powertx_rate8 (val):
|
||||
mcs_rates_ht40["6"] = (val >> 0) & 0xff;
|
||||
|
|
@ -204,7 +204,7 @@ def powertx_rate8 (val):
|
|||
mcs_rates_ht40["12"] = (val >> 16) & 0xff
|
||||
mcs_rates_ht40["13"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 8", val)
|
||||
print("%010s: 0x%08x" % ("Rate 8", val))
|
||||
|
||||
# What is 40 dup CCK, 40 dup OFDM, 20 ext cck, 20 ext ODFM ?
|
||||
def powertx_rate9 (val):
|
||||
|
|
@ -213,7 +213,7 @@ def powertx_rate9 (val):
|
|||
ext_dup_rates["20 ext CCK"] = (val >> 16) & 0xff
|
||||
ext_dup_rates["20 ext OFDM"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 9", val)
|
||||
print("%010s: 0x%08x" % ("Rate 9", val))
|
||||
|
||||
def powertx_rate10 (val):
|
||||
mcs_rates_ht20["14"] = (val >> 0) & 0xff;
|
||||
|
|
@ -221,7 +221,7 @@ def powertx_rate10 (val):
|
|||
mcs_rates_ht20["20"] = (val >> 16) & 0xff
|
||||
mcs_rates_ht20["21"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 10", val)
|
||||
print("%010s: 0x%08x" % ("Rate 10", val))
|
||||
|
||||
def powertx_rate11 (val):
|
||||
mcs_rates_ht20["22"] = (val >> 0) & 0xff;
|
||||
|
|
@ -230,7 +230,7 @@ def powertx_rate11 (val):
|
|||
mcs_rates_ht40["22"] = (val >> 16) & 0xff
|
||||
mcs_rates_ht40["23"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 11", val)
|
||||
print("%010s: 0x%08x" % ("Rate 11", val))
|
||||
|
||||
def powertx_rate12 (val):
|
||||
mcs_rates_ht40["14"] = (val >> 0) & 0xff;
|
||||
|
|
@ -238,7 +238,7 @@ def powertx_rate12 (val):
|
|||
mcs_rates_ht40["20"] = (val >> 16) & 0xff
|
||||
mcs_rates_ht40["21"] = (val >> 24) & 0xff
|
||||
|
||||
print "%010s: 0x%08x" % ("Rate 12", val)
|
||||
print("%010s: 0x%08x" % ("Rate 12", val))
|
||||
|
||||
registers = {
|
||||
"0x00a3c0" : powertx_rate1,
|
||||
|
|
@ -256,43 +256,43 @@ registers = {
|
|||
}
|
||||
|
||||
def process_cck_rates():
|
||||
print "CCK Rates"
|
||||
print "======================"
|
||||
for rate, double_dbm in cck_rates.iteritems():
|
||||
print("CCK Rates")
|
||||
print("======================")
|
||||
for rate, double_dbm in cck_rates.items():
|
||||
dbm = "%.2f dBm" % (double_dbm / 2)
|
||||
print "%010s %010s" % (rate + " Mbps", dbm)
|
||||
print("%010s %010s" % (rate + " Mbps", dbm))
|
||||
|
||||
def process_ofdm_rates():
|
||||
print "OFDM Rates"
|
||||
print "======================"
|
||||
for rate, double_dbm in sorted(map(lambda (k,v): (int(k,0), v), ofdm_rates.iteritems())):
|
||||
print("OFDM Rates")
|
||||
print("======================")
|
||||
for rate, double_dbm in sorted(ofdm_rates.items(), key=lambda i: int(i[0], 0)):
|
||||
rate_s = "%s" % rate
|
||||
dbm = "%.02f dBm" % (double_dbm / 2)
|
||||
print "%010s %010s" % (rate_s + " Mbps", dbm)
|
||||
print("%010s %010s" % (rate_s + " Mbps", dbm))
|
||||
|
||||
def process_mcs_ht20_rates():
|
||||
print "MCS20 Rates"
|
||||
print "======================"
|
||||
for rate, double_dbm in sorted(map(lambda (k,v): (int(k,0), v), mcs_rates_ht20.iteritems())):
|
||||
print("MCS20 Rates")
|
||||
print("======================")
|
||||
for rate, double_dbm in sorted(mcs_rates_ht20.items(), key=lambda i: int(i[0], 0)):
|
||||
rate_s = "%s" % rate
|
||||
dbm = "%.02f dBm" % (double_dbm / 2)
|
||||
print "%010s %010s" % ("MCS" + rate_s, dbm)
|
||||
print("%010s %010s" % ("MCS" + rate_s, dbm))
|
||||
|
||||
|
||||
def process_mcs_ht40_rates():
|
||||
print "MCS40 Rates"
|
||||
print "======================"
|
||||
for rate, double_dbm in sorted(map(lambda (k,v): (int(k,0), v), mcs_rates_ht40.iteritems())):
|
||||
print("MCS40 Rates")
|
||||
print("======================")
|
||||
for rate, double_dbm in sorted(mcs_rates_ht40.items(), key=lambda i: int(i[0], 0)):
|
||||
rate_s = "%s" % rate
|
||||
dbm = "%.2f dBm" % (double_dbm / 2)
|
||||
print "%010s %010s" % ("MCS" + rate_s, dbm)
|
||||
print("%010s %010s" % ("MCS" + rate_s, dbm))
|
||||
|
||||
def process_ext_dup_rates():
|
||||
print "EXT-DUP Rates"
|
||||
print "=========================="
|
||||
for rate, double_dbm in ext_dup_rates.iteritems():
|
||||
print("EXT-DUP Rates")
|
||||
print("==========================")
|
||||
for rate, double_dbm in ext_dup_rates.items():
|
||||
dbm = "%.2f dBm" % (double_dbm / 2)
|
||||
print "%015s %010s" % (rate, dbm)
|
||||
print("%015s %010s" % (rate, dbm))
|
||||
|
||||
def print_power_reg (reg, val):
|
||||
if not reg in map(lambda x: int(x, 0), registers.keys()):
|
||||
|
|
@ -300,12 +300,12 @@ def print_power_reg (reg, val):
|
|||
registers.get("0x%06x" % reg)(val)
|
||||
|
||||
try:
|
||||
print "Power register"
|
||||
print "======================"
|
||||
print("Power register")
|
||||
print("======================")
|
||||
for line in sys.stdin.readlines():
|
||||
reg, val = map(lambda x: int(x, 0), string.split(line))
|
||||
reg, val = map(lambda x: int(x, 0), line.split())
|
||||
print_power_reg(reg, val)
|
||||
print "-------------------------------------"
|
||||
print("-------------------------------------")
|
||||
|
||||
process_cck_rates()
|
||||
process_ofdm_rates()
|
||||
|
|
|
|||
1109
tracing/plugins/ath10k.py
Normal file
1109
tracing/plugins/ath10k.py
Normal file
File diff suppressed because it is too large
Load diff
471
tracing/plugins/ath10k_pktlog.py
Normal file
471
tracing/plugins/ath10k_pktlog.py
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
#
|
||||
# Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# trace-cmd pktlog plugin for ath10k, QCA Linux wireless driver
|
||||
#
|
||||
# TODO:
|
||||
#
|
||||
# o create class for struct ieee80211_hdr each packet headers with
|
||||
# pack() and unpack() methods
|
||||
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
DEBUG = 1
|
||||
|
||||
CUR_PKTLOG_VER = 10010
|
||||
PKTLOG_MAGIC_NUM = 7735225
|
||||
|
||||
IEEE80211_FCTL_TODS = 0x0100
|
||||
IEEE80211_FCTL_FROMDS = 0x0200
|
||||
TARGET_NUM_MSDU_DESC = (1024 + 400)
|
||||
MAX_PKT_INFO_MSDU_ID = 192
|
||||
MAX_10_4_PKT_INFO_MSDU_ID = 1
|
||||
PKTLOG_MAX_TXCTL_WORDS = 57
|
||||
|
||||
# must match with enum ath10k_hw_rev from ath10k and existing values
|
||||
# should not change
|
||||
ATH10K_PKTLOG_HW_QCA988X = 0
|
||||
ATH10K_PKTLOG_HW_QCA6174 = 1
|
||||
ATH10K_PKTLOG_HW_QCA99X0 = 2
|
||||
ATH10K_PKTLOG_HW_QCA9888 = 3
|
||||
ATH10K_PKTLOG_HW_QCA9984 = 4
|
||||
ATH10K_PKTLOG_HW_QCA9377 = 5
|
||||
ATH10K_PKTLOG_HW_QCA40XX = 6
|
||||
ATH10K_PKTLOG_HW_QCA9887 = 7
|
||||
|
||||
ATH10K_PKTLOG_TYPE_TX_CTRL = 1
|
||||
ATH10K_PKTLOG_TYPE_TX_STAT = 2
|
||||
ATH10K_PKTLOG_TYPE_TX_MSDU_ID = 3
|
||||
ATH10K_PKTLOG_TYPE_TX_FRM_HDR = 4
|
||||
ATH10K_PKTLOG_TYPE_RX_STAT = 5
|
||||
ATH10K_PKTLOG_TYPE_RC_FIND = 6
|
||||
ATH10K_PKTLOG_TYPE_RC_UPDATE = 7
|
||||
ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR = 8
|
||||
ATH10K_PKTLOG_TYPE_DBG_PRINT = 9
|
||||
|
||||
ATH10K_PKTLOG_FLG_TYPE_LOCAL_S = 0
|
||||
ATH10K_PKTLOG_FLG_TYPE_REMOTE_S = 1
|
||||
ATH10K_PKTLOG_FLG_TYPE_CLONE_S = 2
|
||||
ATH10K_PKTLOG_FLG_TYPE_UNKNOWN_S = 3
|
||||
|
||||
# sizeof(ath10k_pktlog_txctl) = 12 + 4 * 57
|
||||
ATH10K_PKTLOG_TXCTL_LEN = 240
|
||||
ATH10K_PKTLOG_MAX_TXCTL_WORDS = 57
|
||||
# sizeof(ath10k_pktlog_10_4_txctl)2 = 16 + 4 * 153
|
||||
ATH10K_PKTLOG_10_4_TXCTL_LEN = 624
|
||||
ATH10K_PKTLOG_10_4_MAX_TXCTL_WORDS = 153
|
||||
|
||||
msdu_len_tbl = {}
|
||||
output_file = None
|
||||
frm_hdr = None
|
||||
|
||||
|
||||
def dbg(msg):
|
||||
if DEBUG == 0:
|
||||
return
|
||||
|
||||
print(msg)
|
||||
|
||||
|
||||
def hexdump(buf, prefix=None):
|
||||
s = binascii.b2a_hex(buf)
|
||||
s_len = len(s)
|
||||
result = ""
|
||||
|
||||
if prefix is None:
|
||||
prefix = ""
|
||||
|
||||
for i in range(s_len / 2):
|
||||
if i % 16 == 0:
|
||||
result = result + ("%s%04x: " % (prefix, i))
|
||||
|
||||
result = result + (s[2 * i] + s[2 * i + 1] + " ")
|
||||
|
||||
if (i + 1) % 16 == 0:
|
||||
result = result + "\n"
|
||||
|
||||
# FIXME: if len(s) % 16 == 0 there's an extra \n in the end
|
||||
|
||||
return result
|
||||
|
||||
# struct ath10k_pktlog_hdr {
|
||||
# unsigned short flags;
|
||||
# unsigned short missed_cnt;
|
||||
# unsigned short log_type;
|
||||
# unsigned short size;
|
||||
# unsigned int timestamp;
|
||||
# unsigned char payload[0];
|
||||
# } __attribute__((__packed__));
|
||||
|
||||
|
||||
class Ath10kPktlogHdr:
|
||||
# 2 + 2 + 2 + 2 + 4 = 12
|
||||
hdr_len = 12
|
||||
struct_fmt = '<HHHHI'
|
||||
|
||||
def unpack(self, buf, offset=0):
|
||||
(self.flags, self.missed_cnt, self.log_type,
|
||||
self.size, self.timestamp) = struct.unpack_from(self.struct_fmt, buf, 0)
|
||||
|
||||
payload_len = len(buf) - self.hdr_len
|
||||
if payload_len < self.size:
|
||||
raise Exception('Payload length invalid: %d != %d' %
|
||||
(payload_len, self.size))
|
||||
|
||||
self.payload = buf[self.hdr_len:]
|
||||
|
||||
# excludes payload, you have to write that separately!
|
||||
def pack(self):
|
||||
return struct.pack(self.struct_fmt,
|
||||
self.flags,
|
||||
self.missed_cnt,
|
||||
self.log_type,
|
||||
self.size,
|
||||
self.timestamp)
|
||||
|
||||
def __str__(self):
|
||||
return 'flags %04x miss %d log_type %d size %d timestamp %d\n' % \
|
||||
(self.flags, self.missed_cnt,
|
||||
self.log_type, self.size, self.timestamp)
|
||||
|
||||
def __init__(self):
|
||||
self.flags = 0
|
||||
self.missed_cnt = 0
|
||||
self.log_type = 0
|
||||
self.size = 0
|
||||
self.timestamp = 0
|
||||
self.payload = []
|
||||
|
||||
# struct ath10k_pktlog_10_4_hdr {
|
||||
# unsigned short flags;
|
||||
# unsigned short missed_cnt;
|
||||
# unsigned short log_type;
|
||||
# unsigned short size;
|
||||
# unsigned int timestamp;
|
||||
# unsigned int type_specific_data;
|
||||
# unsigned char payload[0];
|
||||
# } __attribute__((__packed__));
|
||||
|
||||
|
||||
class Ath10kPktlog_10_4_Hdr:
|
||||
# 2 + 2 + 2 + 2 + 4 + 4 = 16
|
||||
hdr_len = 16
|
||||
struct_fmt = '<HHHHII'
|
||||
|
||||
def unpack(self, buf, offset=0):
|
||||
(self.flags, self.missed_cnt, self.log_type,
|
||||
self.size, self.timestamp, self.type_specific_data) = struct.unpack_from(self.struct_fmt, buf, 0)
|
||||
|
||||
payload_len = len(buf) - self.hdr_len
|
||||
|
||||
if payload_len != self.size:
|
||||
raise Exception('Payload length invalid: %d != %d' %
|
||||
(payload_len, self.size))
|
||||
|
||||
self.payload = buf[self.hdr_len:]
|
||||
|
||||
# excludes payload, you have to write that separately!
|
||||
def pack(self):
|
||||
return struct.pack(self.struct_fmt,
|
||||
self.flags,
|
||||
self.missed_cnt,
|
||||
self.log_type,
|
||||
self.size,
|
||||
self.timestamp,
|
||||
self.type_specific_data)
|
||||
|
||||
def __str__(self):
|
||||
return 'flags %04x miss %d log_type %d size %d timestamp %d type_specific_data %d\n' % \
|
||||
(self.flags, self.missed_cnt, self.log_type,
|
||||
self.size, self.timestamp, self.type_specific_data)
|
||||
|
||||
def __init__(self):
|
||||
self.flags = 0
|
||||
self.missed_cnt = 0
|
||||
self.log_type = 0
|
||||
self.size = 0
|
||||
self.timestamp = 0
|
||||
self.type_specific_data = 0
|
||||
self.payload = []
|
||||
|
||||
|
||||
def output_open():
|
||||
global output_file
|
||||
|
||||
# apparently no way to close the file as the python plugin doesn't
|
||||
# have unregister() callback
|
||||
output_file = open('pktlog.dat', 'wb')
|
||||
|
||||
buf = struct.pack('II', PKTLOG_MAGIC_NUM, CUR_PKTLOG_VER)
|
||||
output_write(buf)
|
||||
|
||||
|
||||
def output_write(buf):
|
||||
global output_file
|
||||
|
||||
output_file.write(buf)
|
||||
|
||||
|
||||
def pktlog_tx_frm_hdr(frame):
|
||||
global frm_hdr
|
||||
|
||||
try:
|
||||
# struct ieee80211_hdr
|
||||
(frame_control, duration_id, addr1a, addr1b, addr1c, addr2a, addr2b, addr2c,
|
||||
addr3a, addr3b, addr3c, seq_ctrl) = struct.unpack_from('<HHI2BI2BI2BH', frame, 0)
|
||||
except struct.error as e:
|
||||
dbg('failed to parse struct ieee80211_hdr: %s' % (e))
|
||||
return
|
||||
|
||||
if frame_control & IEEE80211_FCTL_TODS:
|
||||
bssid_tail = (addr1b << 8) | addr1c
|
||||
sa_tail = (addr2b << 8) | addr2c
|
||||
da_tail = (addr3b << 8) | addr3c
|
||||
elif frame_control & IEEE80211_FCTL_FROMDS:
|
||||
bssid_tail = (addr2b << 8) | addr2c
|
||||
sa_tail = (addr3b << 8) | addr3c
|
||||
da_tail = (addr1b << 8) | addr1c
|
||||
else:
|
||||
bssid_tail = (addr3b << 8) | addr3c
|
||||
sa_tail = (addr2b << 8) | addr2c
|
||||
da_tail = (addr1b << 8) | addr1c
|
||||
|
||||
resvd = 0
|
||||
|
||||
frm_hdr = struct.pack('HHHHHH', frame_control, seq_ctrl, bssid_tail,
|
||||
sa_tail, da_tail, resvd)
|
||||
dbg('frm_hdr %d B' % len(frm_hdr))
|
||||
|
||||
|
||||
def pktlog_tx_ctrl(buf, hw_type):
|
||||
global frm_hdr
|
||||
|
||||
if hw_type == ATH10K_PKTLOG_HW_QCA988X:
|
||||
hdr = Ath10kPktlogHdr()
|
||||
hdr.unpack(buf)
|
||||
hdr.size = ATH10K_PKTLOG_TXCTL_LEN
|
||||
num_txctls = ATH10K_PKTLOG_MAX_TXCTL_WORDS
|
||||
elif hw_type in [ATH10K_PKTLOG_HW_QCA99X0, ATH10K_PKTLOG_HW_QCA40XX,
|
||||
ATH10K_PKTLOG_HW_QCA9888, ATH10K_PKTLOG_HW_QCA9984]:
|
||||
hdr = Ath10kPktlog_10_4_Hdr()
|
||||
hdr.unpack(buf)
|
||||
hdr.size = ATH10K_PKTLOG_10_4_TXCTL_LEN
|
||||
num_txctls = ATH10K_PKTLOG_10_4_MAX_TXCTL_WORDS
|
||||
|
||||
output_write(hdr.pack())
|
||||
|
||||
# write struct ath10k_pktlog_frame
|
||||
if frm_hdr:
|
||||
output_write(frm_hdr)
|
||||
else:
|
||||
tmp = struct.pack('HHHHHH', 0, 0, 0, 0, 0, 0)
|
||||
output_write(tmp)
|
||||
|
||||
txdesc_ctl = hdr.payload[0:]
|
||||
for i in range(num_txctls):
|
||||
if len(txdesc_ctl) >= 4:
|
||||
txctl, = struct.unpack_from('<I', txdesc_ctl)
|
||||
txdesc_ctl = txdesc_ctl[4:]
|
||||
else:
|
||||
txctl = 0
|
||||
output_write(struct.pack('I', txctl))
|
||||
|
||||
|
||||
def pktlog_tx_msdu_id(buf, hw_type):
|
||||
global msdu_len_tbl
|
||||
|
||||
if hw_type == ATH10K_PKTLOG_HW_QCA988X:
|
||||
hdr = Ath10kPktlogHdr()
|
||||
hdr.unpack(buf)
|
||||
hdr.size = 4 + (192 / 8) + 2 * 192
|
||||
|
||||
# write struct ath10k_pktlog_hdr
|
||||
output_write(hdr.pack())
|
||||
|
||||
# parse struct msdu_id_info
|
||||
# hdr (12) + num_msdu (4) + bound_bmap (24) = 40
|
||||
msdu_info = hdr.payload[0:28]
|
||||
id = hdr.payload[28:]
|
||||
num_msdu, = struct.unpack_from('I', msdu_info)
|
||||
output_write(msdu_info)
|
||||
|
||||
max_pkt_info_msdu_id = MAX_PKT_INFO_MSDU_ID
|
||||
elif hw_type in [ATH10K_PKTLOG_HW_QCA99X0, ATH10K_PKTLOG_HW_QCA40XX,
|
||||
ATH10K_PKTLOG_HW_QCA9888, ATH10K_PKTLOG_HW_QCA9984]:
|
||||
hdr = Ath10kPktlog_10_4_Hdr()
|
||||
hdr.unpack(buf)
|
||||
|
||||
# write struct ath10k_pktlog_10_4_hdr
|
||||
output_write(hdr.pack())
|
||||
|
||||
# parse struct msdu_id_info
|
||||
# hdr (16) + num_msdu (4) + bound_bmap (1) = 21
|
||||
msdu_info = hdr.payload[0:5]
|
||||
id = hdr.payload[5:]
|
||||
num_msdu, = struct.unpack_from('I', msdu_info)
|
||||
output_write(msdu_info)
|
||||
|
||||
max_pkt_info_msdu_id = MAX_10_4_PKT_INFO_MSDU_ID
|
||||
|
||||
for i in range(max_pkt_info_msdu_id):
|
||||
if num_msdu > 0:
|
||||
num_msdu = num_msdu - 1
|
||||
msdu_id, = struct.unpack_from('<H', id)
|
||||
id = id[2:]
|
||||
if msdu_id not in msdu_len_tbl:
|
||||
dbg('msdu_id %d not found from msdu_len_tbl' % (msdu_id))
|
||||
msdu_len = 0
|
||||
else:
|
||||
msdu_len = msdu_len_tbl[msdu_id]
|
||||
else:
|
||||
msdu_len = 0
|
||||
output_write(struct.pack('H', msdu_len))
|
||||
|
||||
|
||||
def ath10k_htt_pktlog_handler(pevent, trace_seq, event):
|
||||
hw_type = int(event.get('hw_type', ATH10K_PKTLOG_HW_QCA988X))
|
||||
|
||||
buf = event['pktlog'].data
|
||||
offset = 0
|
||||
|
||||
if hw_type == ATH10K_PKTLOG_HW_QCA988X:
|
||||
hdr = Ath10kPktlogHdr()
|
||||
elif hw_type in [ATH10K_PKTLOG_HW_QCA99X0, ATH10K_PKTLOG_HW_QCA40XX,
|
||||
ATH10K_PKTLOG_HW_QCA9888, ATH10K_PKTLOG_HW_QCA9984]:
|
||||
hdr = Ath10kPktlog_10_4_Hdr()
|
||||
|
||||
hdr.unpack(buf, offset)
|
||||
offset = offset + hdr.hdr_len
|
||||
|
||||
trace_seq.puts('%s\n' % (hdr))
|
||||
|
||||
if hdr.log_type == ATH10K_PKTLOG_TYPE_TX_FRM_HDR:
|
||||
pktlog_tx_frm_hdr(buf[hdr.hdr_len:])
|
||||
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_CTRL:
|
||||
pktlog_tx_ctrl(buf, hw_type)
|
||||
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_MSDU_ID:
|
||||
pktlog_tx_msdu_id(buf, hw_type)
|
||||
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_STAT or \
|
||||
hdr.log_type == ATH10K_PKTLOG_TYPE_RX_STAT or \
|
||||
hdr.log_type == ATH10K_PKTLOG_TYPE_RC_FIND or \
|
||||
hdr.log_type == ATH10K_PKTLOG_TYPE_RC_UPDATE:
|
||||
output_write(buf[0: offset + hdr.size])
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
def ath10k_htt_rx_desc_handler(pevent, trace_seq, event):
|
||||
hw_type = int(event.get('hw_type', ATH10K_PKTLOG_HW_QCA988X))
|
||||
|
||||
rxdesc = event['rxdesc'].data
|
||||
|
||||
trace_seq.puts('len %d\n' % (len(rxdesc)))
|
||||
|
||||
if hw_type == ATH10K_PKTLOG_HW_QCA988X:
|
||||
hdr = Ath10kPktlogHdr()
|
||||
hdr.flags = (1 << ATH10K_PKTLOG_FLG_TYPE_REMOTE_S)
|
||||
hdr.missed_cnt = 0
|
||||
hdr.log_type = ATH10K_PKTLOG_TYPE_RX_STAT
|
||||
# rx_desc size for QCA988x chipsets is 248
|
||||
hdr.size = 248
|
||||
output_write(hdr.pack())
|
||||
output_write(rxdesc[0: 32])
|
||||
output_write(rxdesc[36: 56])
|
||||
output_write(rxdesc[76: 208])
|
||||
output_write(rxdesc[228:])
|
||||
|
||||
elif hw_type in [ATH10K_PKTLOG_HW_QCA99X0, ATH10K_PKTLOG_HW_QCA40XX]:
|
||||
hdr = Ath10kPktlog_10_4_Hdr()
|
||||
hdr.flags = (1 << ATH10K_PKTLOG_FLG_TYPE_REMOTE_S)
|
||||
hdr.missed_cnt = 0
|
||||
hdr.log_type = ATH10K_PKTLOG_TYPE_RX_STAT
|
||||
hdr.type_specific_data = 0
|
||||
hdr.size = len(rxdesc)
|
||||
output_write(hdr.pack())
|
||||
output_write(rxdesc)
|
||||
|
||||
elif hw_type in [ATH10K_PKTLOG_HW_QCA9888, ATH10K_PKTLOG_HW_QCA9984]:
|
||||
hdr = Ath10kPktlog_10_4_Hdr()
|
||||
hdr.flags = (1 << ATH10K_PKTLOG_FLG_TYPE_REMOTE_S)
|
||||
hdr.missed_cnt = 0
|
||||
hdr.log_type = ATH10K_PKTLOG_TYPE_RX_STAT
|
||||
hdr.type_specific_data = 0
|
||||
# rx_desc size for QCA9984 and QCA9889 chipsets is 296
|
||||
hdr.size = 296
|
||||
output_write(hdr.pack())
|
||||
output_write(rxdesc[0: 4])
|
||||
output_write(rxdesc[4: 8])
|
||||
output_write(rxdesc[12: 24])
|
||||
output_write(rxdesc[24: 40])
|
||||
output_write(rxdesc[44: 84])
|
||||
output_write(rxdesc[100: 104])
|
||||
output_write(rxdesc[104: 144])
|
||||
output_write(rxdesc[144: 256])
|
||||
output_write(rxdesc[292:])
|
||||
|
||||
|
||||
def ath10k_htt_tx_handler(pevent, trace_seq, event):
|
||||
global msdu_len_tbl
|
||||
msdu_id = int(event['msdu_id'])
|
||||
msdu_len = int(event['msdu_len'])
|
||||
|
||||
trace_seq.puts('msdu_id %d msdu_len %d\n' % (msdu_id, msdu_len))
|
||||
|
||||
if msdu_id > TARGET_NUM_MSDU_DESC:
|
||||
dbg('Invalid msdu_id in tx: %d' % (msdu_id))
|
||||
return
|
||||
|
||||
msdu_len_tbl[msdu_id] = msdu_len
|
||||
|
||||
|
||||
def ath10k_txrx_tx_unref_handler(pevent, trace_seq, event):
|
||||
global msdu_len_tbl
|
||||
msdu_id = int(event['msdu_id'])
|
||||
|
||||
trace_seq.puts('msdu_id %d\n' % (msdu_id))
|
||||
|
||||
if msdu_id > TARGET_NUM_MSDU_DESC:
|
||||
dbg('Invalid msdu_id from unref: %d' % (msdu_id))
|
||||
return
|
||||
|
||||
msdu_len_tbl[msdu_id] = 0
|
||||
|
||||
|
||||
def ath10k_tx_hdr_handler(pevent, trace_seq, event):
|
||||
buf = event['data'].data
|
||||
|
||||
pktlog_tx_frm_hdr(buf[0:])
|
||||
|
||||
|
||||
def register(pevent):
|
||||
|
||||
output_open()
|
||||
|
||||
pevent.register_event_handler("ath10k", "ath10k_htt_pktlog",
|
||||
lambda *args:
|
||||
ath10k_htt_pktlog_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath10k", "ath10k_htt_rx_desc",
|
||||
lambda *args:
|
||||
ath10k_htt_rx_desc_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath10k", "ath10k_htt_tx",
|
||||
lambda *args:
|
||||
ath10k_htt_tx_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath10k", "ath10k_txrx_tx_unref",
|
||||
lambda *args:
|
||||
ath10k_txrx_tx_unref_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath10k", "ath10k_tx_hdr",
|
||||
lambda *args:
|
||||
ath10k_tx_hdr_handler(pevent, *args))
|
||||
251
tracing/plugins/ath6kl.py
Normal file
251
tracing/plugins/ath6kl.py
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
#
|
||||
# Copyright (c) 2012 Qualcomm Atheros, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# To install the plugin:
|
||||
#
|
||||
# cp ath6kl.py ~/.trace-cmd/plugins/
|
||||
#
|
||||
# When making changes to the plugin use -V to see all python errors/warnings:
|
||||
#
|
||||
# trace-cmd report -V trace.dat
|
||||
|
||||
import tracecmd
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
def hexdump(buf, prefix=None):
|
||||
s = binascii.b2a_hex(buf)
|
||||
s_len = len(s)
|
||||
result = ""
|
||||
|
||||
if prefix == None:
|
||||
prefix = ""
|
||||
|
||||
for i in range(s_len / 2):
|
||||
if i % 16 == 0:
|
||||
result = result + ("%s%04x: " % (prefix, i))
|
||||
|
||||
result = result + (s[2*i] + s[2*i+1] + " ")
|
||||
|
||||
if (i + 1) % 16 == 0:
|
||||
result = result + "\n"
|
||||
|
||||
# FIXME: if len(s) % 16 == 0 there's an extra \n in the end
|
||||
|
||||
return result
|
||||
|
||||
def wmi_event_bssinfo(pevent, trace_seq, event, buf):
|
||||
hdr = struct.unpack("<HBB6BH", buf[0:12])
|
||||
channel = hdr[0]
|
||||
frame_type = hdr[1]
|
||||
snr = hdr[2]
|
||||
bssid = hdr[3]
|
||||
ie_mask = hdr[4]
|
||||
|
||||
trace_seq.puts("\t\t\tWMI_BSSINFO_EVENTID channel %d frame_type 0x%x snr %d ie_mask 0x%x\n" %
|
||||
(channel, frame_type, snr, ie_mask))
|
||||
|
||||
wmi_event_handlers = [
|
||||
[0x1004, wmi_event_bssinfo ],
|
||||
]
|
||||
|
||||
def wmi_cmd_set_bss_filter_handler(pevent, trace_seq, event, buf):
|
||||
hdr = struct.unpack("<BBHI", buf[0:8])
|
||||
bss_filter = hdr[0]
|
||||
ie_mask = hdr[3]
|
||||
|
||||
trace_seq.puts("\t\t\tWMI_SET_BSS_FILTER_CMDID bss_filter 0x%x ie_mask 0x%08x\n" %
|
||||
(bss_filter, ie_mask))
|
||||
|
||||
def wmi_cmd_set_probed_ssid_handler(pevent, trace_seq, event, buf):
|
||||
hdr = struct.unpack("<BBB", buf[0:3])
|
||||
entry_index = hdr[0]
|
||||
flag = hdr[1]
|
||||
ssid_len = hdr[2]
|
||||
|
||||
# fmt = "<" + ssid_len + "s"
|
||||
# hdr = struct.unpack(fmt, buf[3:3 + ssid_len])
|
||||
|
||||
trace_seq.puts("\t\t\tWMI_SET_PROBED_SSID_CMDID entry_index 0x%x flag 0x%08x ssid_len %d\n" %
|
||||
(entry_index, flag, ssid_len))
|
||||
|
||||
# FIXME: print SSID
|
||||
# for c in hdr[0]:
|
||||
# print ascii(c)
|
||||
|
||||
wmi_cmd_handlers = [
|
||||
[9, wmi_cmd_set_bss_filter_handler ],
|
||||
[10, wmi_cmd_set_probed_ssid_handler ],
|
||||
]
|
||||
|
||||
WMI_CMD_HDR_IF_ID_MASK = 0xf
|
||||
|
||||
def ath6kl_wmi_cmd_handler(pevent, trace_seq, event):
|
||||
buf_len = long(event['buf_len'])
|
||||
buf = event['buf'].data
|
||||
|
||||
hdr = struct.unpack("<HHH", buf[0:6])
|
||||
cmd_id = hdr[0]
|
||||
if_idx = hdr[1] & WMI_CMD_HDR_IF_ID_MASK
|
||||
|
||||
trace_seq.puts("id 0x%x len %d if_idx %d\n" % (cmd_id, buf_len, if_idx))
|
||||
|
||||
for (wmi_id, handler) in wmi_cmd_handlers:
|
||||
if wmi_id == cmd_id:
|
||||
handler(pevent, trace_seq, event, buf[6:])
|
||||
break
|
||||
|
||||
def ath6kl_wmi_event_handler(pevent, trace_seq, event):
|
||||
buf_len = long(event['buf_len'])
|
||||
buf = event['buf'].data
|
||||
|
||||
hdr = struct.unpack("<HHH", buf[0:6])
|
||||
cmd_id = hdr[0]
|
||||
if_idx = hdr[1] & WMI_CMD_HDR_IF_ID_MASK
|
||||
|
||||
trace_seq.puts("id 0x%x len %d if_idx %d\n" % (cmd_id, buf_len, if_idx))
|
||||
|
||||
for (wmi_id, handler) in wmi_event_handlers:
|
||||
if wmi_id == cmd_id:
|
||||
handler(pevent, trace_seq, event, buf[6:])
|
||||
break
|
||||
|
||||
def ath6kl_htc_tx_handler(pevent, trace_seq, event):
|
||||
buf_len = long(event['buf_len'])
|
||||
buf = event['buf'].data
|
||||
|
||||
hdr = struct.unpack("<BBHBB", buf[0:6])
|
||||
endpoint = hdr[0]
|
||||
flags = hdr[1]
|
||||
payload_len = hdr[2]
|
||||
ctrl0 = hdr[3]
|
||||
ctrl1 = hdr[4]
|
||||
|
||||
seqno = ctrl1
|
||||
|
||||
trace_seq.puts("seqno %d endpoint %d payload_len %d flags 0x%x\n" %
|
||||
(seqno, endpoint, payload_len, flags))
|
||||
|
||||
if flags != 0:
|
||||
trace_seq.puts("\t\t\t\t\t\t")
|
||||
|
||||
if flags & 0x1:
|
||||
trace_seq.puts(" NEED_CREDIT_UPDATE")
|
||||
|
||||
if flags & 0x2:
|
||||
trace_seq.puts(" SEND_BUNDLE")
|
||||
|
||||
if flags & 0x4:
|
||||
trace_seq.puts(" FIXUP_NETBUF")
|
||||
|
||||
if flags != 0:
|
||||
trace_seq.puts("\n")
|
||||
|
||||
def ath6kl_htc_rx_handler(pevent, trace_seq, event):
|
||||
buf_len = long(event['buf_len'])
|
||||
buf = event['buf'].data
|
||||
|
||||
hdr = struct.unpack("<BBHBB", buf[0:6])
|
||||
endpoint = hdr[0]
|
||||
flags = hdr[1]
|
||||
payload_len = hdr[2]
|
||||
ctrl0 = hdr[3]
|
||||
ctrl1 = hdr[4]
|
||||
|
||||
seqno = ctrl1
|
||||
bundle_count = (flags & 0xf0) >> 4
|
||||
|
||||
trace_seq.puts("seqno %d endpoint %d payload_len %d flags 0x%x bundle_count %d\n" %
|
||||
(seqno, endpoint, payload_len, flags, bundle_count))
|
||||
|
||||
if (flags & 0xf) != 0:
|
||||
trace_seq.puts("\t\t\t\t\t\t")
|
||||
|
||||
if flags & 0x1:
|
||||
trace_seq.puts(" UNUSED")
|
||||
|
||||
if flags & 0x2:
|
||||
trace_seq.puts(" TRAILER")
|
||||
|
||||
if (flags & 0xf) != 0:
|
||||
trace_seq.puts("\n")
|
||||
|
||||
def ath6kl_sdio_handler(pevent, trace_seq, event):
|
||||
tx = long(event['tx'])
|
||||
addr = event['addr']
|
||||
flags = event['flags']
|
||||
|
||||
buf_len = long(event['buf_len'])
|
||||
buf = event['buf'].data
|
||||
|
||||
if tx == 1:
|
||||
direction = "tx"
|
||||
else:
|
||||
direction = "rx"
|
||||
|
||||
trace_seq.puts("%s addr 0x%x flags 0x%x buf_len %d\n" %
|
||||
(direction, addr, flags, buf_len))
|
||||
trace_seq.puts("%s\n" % hexdump(buf))
|
||||
|
||||
def ath6kl_sdio_scat_handler(pevent, trace_seq, event):
|
||||
tx = long(event['tx'])
|
||||
addr = long(event['addr'])
|
||||
flags = long(event['flags'])
|
||||
entries = long(event['entries'])
|
||||
total_len = long(event['total_len'])
|
||||
|
||||
len_array_data = event['len_array'].data
|
||||
data = event['data'].data
|
||||
|
||||
if tx == 1:
|
||||
direction = "tx"
|
||||
else:
|
||||
direction = "rx"
|
||||
|
||||
trace_seq.puts("%s addr 0x%x flags 0x%x entries %d total_len %d\n" %
|
||||
(direction, addr, flags, entries, total_len))
|
||||
|
||||
offset = 0
|
||||
|
||||
len_array = struct.unpack("<%dI" % entries, len_array_data[0:8])
|
||||
|
||||
for i in range(entries):
|
||||
length = len_array[i]
|
||||
start = offset
|
||||
end = start + length
|
||||
|
||||
trace_seq.puts("%s\n" % hexdump(data[start:end]))
|
||||
|
||||
offset = offset + length
|
||||
|
||||
def register(pevent):
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_wmi_cmd",
|
||||
lambda *args:
|
||||
ath6kl_wmi_cmd_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_wmi_event",
|
||||
lambda *args:
|
||||
ath6kl_wmi_event_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_htc_tx",
|
||||
lambda *args:
|
||||
ath6kl_htc_tx_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_htc_rx",
|
||||
lambda *args:
|
||||
ath6kl_htc_rx_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_sdio",
|
||||
lambda *args:
|
||||
ath6kl_sdio_handler(pevent, *args))
|
||||
pevent.register_event_handler("ath6kl", "ath6kl_sdio_scat",
|
||||
lambda *args:
|
||||
ath6kl_sdio_scat_handler(pevent, *args))
|
||||
Loading…
Add table
Reference in a new issue