mtk-wifi-fw/tests/test_elf.py

78 lines
3 KiB
Python

"""ELF emitter tests: structural validity + segment fidelity.
Validates with readelf where available and always with a programmatic
re-parse against the container's own region table.
"""
import os
import struct
import subprocess
import sys
import unittest
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / 'tools'))
import mtk_fw_elf as E # noqa: E402
FW = Path(os.environ.get('MTK_FW_DIR', '/lib/firmware/mediatek'))
def blobs():
return sorted(FW.glob('mt79*_wm.bin')) + sorted(FW.glob('mt79*_wa.bin')) \
+ sorted(FW.glob('mt79*_rom_patch.bin'))
class Emitter(unittest.TestCase):
def test_structure_and_fidelity(self):
found = blobs()
if not found:
self.skipTest('no mediatek blobs')
for p in found:
with self.subTest(blob=p.name):
d = p.read_bytes()
if 'patch' in p.name:
regions = list(E.patch_regions(d))
else:
regions = list(E.ram_regions(d))
regions = [(a, dat) for a, dat in regions if dat]
elf = E.build_elf(regions)
# ehdr sanity
self.assertEqual(elf[:4], b'\x7fELF')
etype, mach, _, entry, phoff = struct.unpack_from('<HHIII', elf, 16)
self.assertEqual((etype, mach), (2, 167))
self.assertEqual(phoff, 52)
phentsize, phnum = struct.unpack_from('<HH', elf, 42)
self.assertEqual((phentsize, phnum), (32, len(regions)))
# segment fidelity
for i, (addr, dat) in enumerate(regions):
p_type, p_off, p_va, p_pa, p_filesz, p_memsz = \
struct.unpack_from('<IIIIII', elf, phoff + i * 32)
self.assertEqual((p_type, p_va, p_pa), (1, addr, addr))
self.assertEqual((p_filesz, p_memsz), (len(dat),) * 2)
self.assertEqual(elf[p_off:p_off + p_filesz], dat)
def test_readelf_accepts(self):
found = blobs()
if not found:
self.skipTest('no mediatek blobs')
if subprocess.run(['which', 'readelf'], capture_output=True).returncode:
self.skipTest('readelf unavailable')
import tempfile
for p in found[:4]:
with self.subTest(blob=p.name):
d = p.read_bytes()
regs = list(E.patch_regions(d) if 'patch' in p.name
else E.ram_regions(d))
elf = E.build_elf(regs)
with tempfile.NamedTemporaryFile(suffix='.elf') as f:
f.write(elf)
f.flush()
r = subprocess.run(['readelf', '-l', f.name],
capture_output=True, text=True)
self.assertEqual(r.returncode, 0, r.stderr)
self.assertIn('LOAD', r.stdout)
if __name__ == '__main__':
unittest.main()