"""Check actual ARMCC kernel / GCC APP TLS layouts and enabled features.""" import json import os from pathlib import Path import struct import subprocess root = Path(__file__).resolve().parents[1] output = root / 'artifacts/wss/new-board' output.mkdir(parents=True, exist_ok=True) toolchain = root / 'ql-cross-tool/win32/owtoolchain' gcc = toolchain / 'gcc-arm-none-eabi/bin/arm-none-eabi-gcc.exe' objcopy = gcc.with_name('arm-none-eabi-objcopy.exe') armcc = toolchain / 'ARM_Compiler_5/bin/armcc.exe' types = ['ssl_context', 'ssl_config', 'net_context', 'x509_crt', 'pk_context', 'entropy_context', 'ctr_drbg_context', 'ecp_group', 'ecp_point', 'mpi', 'ssl_handshake_params', 'ecdh_context'] fields = {'ssl_context': ['conf', 'state', 'in_buf', 'out_buf', 'session', 'handshake', 'hostname'], 'ssl_config': ['ca_chain', 'cert_profile', 'f_rng', 'p_rng', 'curve_list'], 'net_context': ['fd', 'cid'], 'x509_crt': ['pk', 'sig', 'next'], 'ssl_handshake_params': ['ecdh_ctx'], 'ecdh_context': ['grp_id']} labels = ['sizeof(mbedtls_' + t + ')' for t in types] labels += ['offsetof(mbedtls_' + t + ', ' + f + ')' for t, fs in fields.items() for f in fs] source = output / 'tls_layout.c' source.write_text('#include \n#include "mbedtls/ssl_internal.h"\n' '#include "mbedtls/net_sockets.h"\n#include "mbedtls/entropy.h"\n' '#include "mbedtls/ctr_drbg.h"\n' 'const unsigned int talkingq_tls_layout[] = {\n' + ',\n'.join(labels) + '\n};\n') env = os.environ.copy() env['ARMLMD_LICENSE_FILE'] = str(toolchain / 'license.dat') layouts, macros = {}, {} for target in ['kernel', 'app']: include = root / ('ql-kernel' if target == 'kernel' else 'ql-application') / 'threadx/common/include' obj = output / (target + '-tls-layout.o') flags = ['-I' + str(include), '-DQUECTEL_OPEN_CPU'] if target == 'kernel': command = [str(armcc), '--cpu', 'Cortex-R5F', '--fpu=softvfp+vfpv3_d16', '--gnu', '--thumb', '-c', str(source), '-o', str(obj)] + flags section = '.constdata' else: command = [str(gcc), '-mcpu=cortex-r5', '-mthumb', '-mfloat-abi=softfp', '-mfpu=vfpv3-d16', '-c', str(source), '-o', str(obj)] + flags section = '.rodata' subprocess.run(command, env=env, check=True) binary = obj.with_suffix('.bin') subprocess.run([str(objcopy), '-O', 'binary', '-j', section, str(obj), str(binary)], check=True) data = binary.read_bytes() assert len(data) == len(labels) * 4, (target, len(data)) layouts[target] = dict(zip(labels, struct.unpack('<' + 'I' * len(labels), data))) defines = subprocess.check_output([str(gcc), '-E', '-dM', '-x', 'c', '-include', 'mbedtls/config.h', 'NUL'] + flags, text=True) macros[target] = sorted(line for line in defines.splitlines() if line.startswith('#define MBEDTLS_') or line.startswith('#define QUECTEL_MBEDTLS_')) assert layouts['kernel'] == layouts['app'], json.dumps(layouts, indent=2) assert macros['kernel'] == macros['app'], json.dumps({k: sorted(set(macros[k]) - set(macros['app' if k == 'kernel' else 'kernel'])) for k in macros}) for feature in ['ECDSA_C', 'ECP_NIST_OPTIM', 'KEY_EXCHANGE_ECDHE_ECDSA_ENABLED', 'GCM_C', 'HAVE_TIME_DATE', 'PLATFORM_TIME_ALT']: assert any(line.startswith('#define MBEDTLS_' + feature + ' ') for line in macros['kernel']) report = {'result': 'PASS', 'layout': layouts['kernel'], 'features': macros['kernel']} (output / 'tls-abi.json').write_text(json.dumps(report, indent=2)) print('PASS: ARMCC kernel / GCC APP TLS sizes, field offsets and feature macros agree') print(json.dumps(layouts['kernel'], indent=2))