#!/usr/bin/env python3 """Reject nRF52 ELFs with an unsafe compiled buttonless Bluetooth DFU handoff.""" import argparse from pathlib import Path import struct import sys SCRIPT_DIR = Path(__file__).resolve().parent if "__file__" in globals() else Path("scripts").resolve() sys.path.insert(0, str(SCRIPT_DIR)) from firmware_elf import FirmwareElf HELPER_NAME = "mesh_nrf52_dfu_jump" # Assembled Cortex-M4/Thumb helper. These instructions are entirely local: no # relocation or compiler-generated C stack access can change with image layout. # The only post-transition stack writes construct the explicit handler-mode # exception frame. The normal FreeRTOS thread path performs no stack access. HELPER_CODE = bytes.fromhex( "72b6eff305830168426881f30888002080f3148880f3118880f31388" "bff34f8fbff36f8f002b03d16ff0000e62b6104788b0009001900290" "039004906ff00000059006924ff0045007906ff0060e62b67047" ) def branch_targets(code, start): """Decode direct Thumb-2 BL/B.W targets without depending on objdump.""" for offset in range(0, len(code) - 3, 2): first, second = struct.unpack_from("> 10) & 1 i1 = 1 ^ ((second >> 13) & 1) ^ sign i2 = 1 ^ ((second >> 11) & 1) ^ sign immediate = (sign << 24) | (i1 << 23) | (i2 << 22) immediate |= (first & 0x3FF) << 12 | (second & 0x7FF) << 1 if sign: immediate -= 1 << 25 yield start + offset + 4 + immediate def writes_control(code): for offset in range(0, len(code) - 3, 2): first, second = struct.unpack_from("