patch_reset.py (1250B)
1 #!/usr/bin/env python3 2 """Instala comun_early_reset como vector de reset de un .bin de la PicoCalc. 3 4 El cargador de la SD salta a vector[1] sin limpiar interrupciones; nuestra rutina 5 las limpia y despues sigue al _reset_handler del SDK (cuya direccion se escribe en 6 la constante comun_real_reset). 7 8 Uso: patch_reset.py programa.elf programa.bin""" 9 import struct, subprocess, sys 10 11 elf, binf = sys.argv[1], sys.argv[2] 12 syms = {} 13 for line in subprocess.check_output(["arm-none-eabi-nm", elf], text=True).splitlines(): 14 parts = line.split() 15 if len(parts) == 3: 16 syms[parts[2]] = int(parts[0], 16) 17 base = syms["__vectors"] 18 shim, real, var = syms["comun_early_reset"], syms["_reset_handler"], syms["comun_real_reset"] 19 data = bytearray(open(binf, "rb").read()) 20 old_reset = struct.unpack_from("<I", data, 4)[0] 21 assert old_reset == (real | 1), "vector[1] inesperado: %#x (reset real %#x)" % (old_reset, real) 22 assert struct.unpack_from("<I", data, var - base)[0] == 0xDEADBEEF, "no encuentro comun_real_reset en el .bin" 23 struct.pack_into("<I", data, var - base, real | 1) 24 struct.pack_into("<I", data, 4, shim | 1) 25 open(binf, "wb").write(data) 26 print("vector de reset: %#x -> comun_early_reset %#x (sigue a %#x)" % (old_reset, shim | 1, real | 1))