Files
banban/tools/verify_wss_package.py
chenjintao 3deb51d838 Adapt WSS to new boards and use MQTT domain for eSIM connectivity
Preserve main GNSS and volume behavior while porting verified TLS, receive fixes and full-handshake optimizations. Add MQTT connection diagnostics and route MQTT through banban.api.talkingq.com:1883.

Include migration documentation and regression tools. Firmware builds and package checks passed; user confirmed new-board connectivity after switching the MQTT host to the domain.
2026-09-16 17:27:21 +08:00

68 lines
4.6 KiB
Python

"""Verify the new-board WSS package, including enabled GNSS task entry points."""
import hashlib
import json
import re
import subprocess
import sys
import zipfile
from pathlib import Path
root = Path(__file__).resolve().parents[1]
package = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/new-board/EG800AKCN_11LG-new-board-wss-x25519.zip'
output = package.parent
output.mkdir(parents=True, exist_ok=True)
objdump = root / 'ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi/bin/arm-none-eabi-objdump.exe'
app = root / 'ql-application/threadx/build/app.elf'
symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')), str(app)], text=True)
required = ['talkingq_parse_wss_url', 'talkingq_root_ca', 'rws_check_handshake', 'rws_ssl_conn',
'mbedtls_ssl_set_hostname', 'mbedtls_ssl_get_verify_result', 'mbedtls_ssl_conf_authmode',
'mbedtls_ctr_drbg_random', 'mbedtls_sha1', 'mbedtls_base64_encode', 'mbedtls_ssl_handshake_step',
'rws_tls_preferred_curves']
for symbol in required:
assert re.search(r'\b' + symbol + r'$', symbols, re.M), 'Missing linked symbol: ' + symbol
kernel_symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')),
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
kernel_required = ['ecdsa_verify_restartable', 'mbedtls_ecdsa_read_signature',
'mbedtls_gcm_crypt_and_tag', 'mbedtls_x509_time_is_future',
'mbedtls_x509_time_is_past', 'mbedtls_platform_gmtime_r', 'mbedtls_time',
'ecp_mod_p256', 'ecp_mod_p384', 'ecp_mod_p521']
for symbol in kernel_required:
assert re.search(r'\b' + symbol + r'$', kernel_symbols, re.M), 'Missing kernel capability: ' + symbol
clock_body = subprocess.check_output([str(objdump), '-d', '--disassemble=x509_get_current_time',
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
assert '<mbedtls_platform_gmtime_r>' in clock_body and '<GetCurrentCompTime>' not in clock_body
(output / 'x509-clock.disasm.txt').write_text(clock_body)
report = {'package': package.name, 'sha256': hashlib.sha256(package.read_bytes()).hexdigest(),
'board': 'new board with GNSS enabled',
'linked_symbols': required, 'kernel_symbols': kernel_required,
'hardware_test': 'New-board package awaits device testing; legacy board verified X25519 full handshake at 1455 ms on 2026-09-16',
'backend': '2026-09-16 11:32 CST: WSS 443 /ws HTTP 101; 8080 plaintext WS'}
with zipfile.ZipFile(package) as archive:
assert archive.testzip() is None, 'ZIP CRC failure'
for name, source in {'cp.bin': 'ql-kernel/threadx/build/release_kernel.bin',
'customer_app.bin': 'ql-application/threadx/build/app.bin'}.items():
data = archive.read(name)
assert data == (root / source).read_bytes(), 'Stale image: ' + name
report[name] = {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()}
assert b'wss://banban.api.talkingq.com:443/ws' in archive.read('customer_app.bin')
assert b'WSS TLS handshake total=' in archive.read('customer_app.bin')
assert b'WSS TLS full handshake: prefer X25519' in archive.read('customer_app.bin')
assert b'Legacy board:' not in archive.read('customer_app.bin')
assert b'Legacy board:' not in archive.read('cp.bin')
assert b'gnss_Task_Ref' in archive.read('customer_app.bin')
report['download_manifest'] = json.loads(archive.read('download.json'))
task_create_address = int(re.search(r'^([0-9a-fA-F]+) T ql_rtos_task_create$', symbols, re.M).group(1), 16)
for symbol, binary, expected in [
('quec_get_gnssid_task', root / 'ql-kernel/threadx/build/kernel.axf', '<quec_rtos_task_create>'),
('app_gnss_init', app, '0x%08x' % (task_create_address | 1)),
('set_gnss_mode', app, 'strb')]:
body = subprocess.check_output([str(objdump), '-d', '--disassemble=' + symbol, str(binary)], text=True)
assert '<' + symbol + '>:' in body and expected in body, 'GNSS entry point disabled or unexpected code: ' + symbol
(output / (symbol + '.disasm.txt')).write_text(body)
for symbol, table in [('quec_get_ocname_by_gnss_task', kernel_symbols), ('quec_gnss_test', symbols)]:
assert re.search(r'\b' + symbol + r'$', table, re.M), 'Missing GNSS worker: ' + symbol
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, GNSS task creation, WSS URL, ECDSA/GCM/RTC/NIST kernel symbols and handshake timing logs'
(output / 'verification.json').write_text(json.dumps(report, indent=2))
print(report['verification'])
print('SHA256:', report['sha256'])