def prepare_can_iface(): if '/' not in args.iface: logger.debug('Using iface %r as SocketCAN', args.iface) execute_shell_command( 'ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875', args.iface, args.iface, CAN_BITRATE) else: logger.debug('Using iface %r as SLCAN', args.iface) # We don't want the SLCAN daemon to interfere... execute_shell_command('killall -INT slcand &> /dev/null', ignore_failure=True) time.sleep(1) # Making sure the interface can be open with open(args.iface, 'bw') as _f: pass
def load_firmware(firmware_data): with tempfile.TemporaryDirectory('-drwatson') as tmpdir: logger.debug('Executable scratchpad directory: %r', tmpdir) fn = lambda x: os.path.join(tmpdir, x) runtc = lambda fmt, *a, **kw: execute_shell_command( TOOLCHAIN_PREFIX + fmt, *a, **kw) # Generating ELF from the downloaded binary with open(fn('fw.bin'), 'wb') as f: f.write(firmware_data) with open(fn('link.ld'), 'w') as f: f.write('SECTIONS { . = %s; .text : { *(.text) } }' % FLASH_OFFSET) runtc('ld -b binary -r -o %s %s', fn('tmp.elf'), fn('fw.bin')) runtc( 'objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load %s', fn('tmp.elf')) runtc('ld %s -T %s -o %s', fn('tmp.elf'), fn('link.ld'), fn('output.elf')) # Loading the ELF onto the target with open(fn('script.gdb'), 'w') as f: f.write('\n'.join([ 'target extended-remote %s' % glob_one(DEBUGGER_PORT_GDB_GLOB), 'mon swdp_scan', 'attach 1', 'load', 'compare-sections', 'kill', 'quit 0' ])) runtc('gdb %s --batch -x %s -return-child-result -silent', fn('output.elf'), fn('script.gdb'))
def load_firmware(firmware_data): with tempfile.TemporaryDirectory('-drwatson') as tmpdir: logger.debug('Executable scratchpad directory: %r', tmpdir) fn = lambda x: os.path.join(tmpdir, x) runtc = lambda fmt, *a, **kw: execute_shell_command(TOOLCHAIN_PREFIX + fmt, *a, **kw) # Generating ELF from the downloaded binary with open(fn('fw.bin'), 'wb') as f: f.write(firmware_data) with open(fn('link.ld'), 'w') as f: f.write('SECTIONS { . = %s; .text : { *(.text) } }' % FLASH_OFFSET) runtc('ld -b binary -r -o %s %s', fn('tmp.elf'), fn('fw.bin')) runtc('objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load %s', fn('tmp.elf')) runtc('ld %s -T %s -o %s', fn('tmp.elf'), fn('link.ld'), fn('output.elf')) # Loading the ELF onto the target with open(fn('script.gdb'), 'w') as f: f.write('\n'.join([ 'target extended-remote %s' % glob_one(DEBUGGER_PORT_GDB_GLOB), 'mon swdp_scan', 'attach 1', 'load', #'compare-sections', # Commented out because this command breaks the GDB session on GDB 8.x. Why tho? 'kill', 'quit 0' ])) runtc('gdb %s --batch -x %s -return-child-result -silent', fn('output.elf'), fn('script.gdb'))
def load_firmware(firmware_data): with tempfile.TemporaryDirectory("-drwatson") as tmpdir: logger.debug("Executable scratchpad directory: %r", tmpdir) fn = lambda x: os.path.join(tmpdir, x) runtc = lambda fmt, *a, **kw: execute_shell_command(TOOLCHAIN_PREFIX + fmt, *a, **kw) # Generating ELF from the downloaded binary with open(fn("fw.bin"), "wb") as f: f.write(firmware_data) with open(fn("link.ld"), "w") as f: f.write("SECTIONS { . = %s; .text : { *(.text) } }" % FLASH_OFFSET) runtc("ld -b binary -r -o %s %s", fn("tmp.elf"), fn("fw.bin")) runtc("objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load %s", fn("tmp.elf")) runtc("ld %s -T %s -o %s", fn("tmp.elf"), fn("link.ld"), fn("output.elf")) # Loading the ELF onto the target with open(fn("script.gdb"), "w") as f: f.write( "\n".join( [ "target extended-remote %s" % glob_one(DEBUGGER_PORT_GDB_GLOB), "mon swdp_scan", "attach 1", "load", "compare-sections", "kill", "quit 0", ] ) ) runtc("gdb %s --batch -x %s -return-child-result -silent", fn("output.elf"), fn("script.gdb"))
def process_one_device(set_device_info): execute_shell_command('ifconfig %s down && ifconfig %s up', args.iface, args.iface) if not args.only_sign: # Flashing firmware without signature with closing(bootloader.BootloaderInterface(args.iface)) as bli: input('\n'.join([ '1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)', '2. Power on the device and connect it to CAN bus', '3. Press ENTER' ])) with CLIWaitCursor(): load_and_start_firmware(bli, firmware_base) # Testing the device input('\n'.join([ '1. Make sure that LED indicators are blinking', '2. Test button operation', '3. Press ENTER' ])) # Installing signature with closing(bootloader.BootloaderInterface(args.iface)) as bli: info("Now we're going to sign the device") input('\n'.join([ '1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)', '2. Reset the device (e.g. cycle power)', '3. Press ENTER' ])) with CLIWaitCursor(): info('Reading unique ID...') unique_id = bli.read_unique_id() set_device_info(PRODUCT_NAME, unique_id) info('Requesting signature for unique ID %s', ' '.join(['%02x' % x for x in unique_id])) gensign_response = api.generate_signature(unique_id, PRODUCT_NAME) info( 'Signature has been generated successfully [%s], patching the firmware...', ['existing', 'NEW'][gensign_response.new]) firmware_with_signature = firmware_base.ljust( SIGNATURE_OFFSET, b'\xFF') + gensign_response.signature load_and_start_firmware(bli, firmware_with_signature)
def init_can_iface(): if '/' not in args.iface: logger.debug('Using iface %r as SocketCAN', args.iface) execute_shell_command('ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875', args.iface, args.iface, CAN_BITRATE) return args.iface else: logger.debug('Using iface %r as SLCAN', args.iface) # We don't want the SLCAN daemon to interfere... execute_shell_command('killall -INT slcand &> /dev/null', ignore_failure=True) time.sleep(1) # Making sure the interface can be open with open(args.iface, 'bw') as _f: pass return args.iface
def process_one_device(set_device_info): execute_shell_command('ifconfig %s down && ifconfig %s up', args.iface, args.iface) if not args.only_sign: # Flashing firmware without signature with closing(bootloader.BootloaderInterface(args.iface)) as bli: input('\n'.join(['1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)', '2. Power on the device and connect it to CAN bus', '3. Press ENTER'])) with CLIWaitCursor(): load_and_start_firmware(bli, firmware_base) # Testing the device input('\n'.join(['1. Make sure that LED indicators are blinking', '2. Test button operation', '3. Press ENTER'])) # Installing signature with closing(bootloader.BootloaderInterface(args.iface)) as bli: info("Now we're going to sign the device") input('\n'.join(['1. Set PIO0_3 low, PIO0_1 low (J4 closed, J3 open)', '2. Reset the device (e.g. cycle power)', '3. Press ENTER'])) with CLIWaitCursor(): info('Reading unique ID...') unique_id = bli.read_unique_id() set_device_info(PRODUCT_NAME, unique_id) info('Requesting signature for unique ID %s', ' '.join(['%02x' % x for x in unique_id])) gensign_response = api.generate_signature(unique_id, PRODUCT_NAME) info('Signature has been generated successfully [%s], patching the firmware...', ['existing', 'NEW'][gensign_response.new]) firmware_with_signature = firmware_base.ljust(SIGNATURE_OFFSET, b'\xFF') + gensign_response.signature load_and_start_firmware(bli, firmware_with_signature)
f.write(firmware_with_signature) os.chmod(image_name, 0o666) info('Signed image stored into %r', image_name) with CLIWaitCursor(): firmware_base = download(args.firmware) assert 0 < len(firmware_base) <= SIGNATURE_OFFSET, 'Firmware size is incorrect' if args.generate_signed_image_for: generate_signed_image_for(args.generate_signed_image_for) exit(0) if not args.iface: fatal('Iface is required') execute_shell_command('ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875', args.iface, args.iface, bootloader.CAN_BITRATE, ignore_failure=True) def load_and_start_firmware(bootloader_interface, firmware_image): while True: try: info('Flashing the firmware [%d bytes]...', len(firmware_image)) bootloader_interface.unlock() bootloader_interface.load_firmware(firmware_image) except Exception as ex: error('Flashing failed: %r', ex) if not input('Try harder?', yes_no=True): abort('Flashing failed') else: input('Set PIO0_1 high (J4 open), then press ENTER') info('Starting the firmware...')
with CLIWaitCursor(): firmware_base = download(args.firmware) assert 0 < len( firmware_base) <= SIGNATURE_OFFSET, 'Firmware size is incorrect' if args.generate_signed_image_for: generate_signed_image_for(args.generate_signed_image_for) exit(0) if not args.iface: fatal('Iface is required') execute_shell_command( 'ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875', args.iface, args.iface, bootloader.CAN_BITRATE, ignore_failure=True) def load_and_start_firmware(bootloader_interface, firmware_image): while True: try: info('Flashing the firmware [%d bytes]...', len(firmware_image)) bootloader_interface.unlock() bootloader_interface.load_firmware(firmware_image) except Exception as ex: error('Flashing failed: %r', ex) if not input('Try harder?', yes_no=True): abort('Flashing failed') else:
def init_can_iface(): if '/' not in args.iface: logger.debug('Using iface %r as SocketCAN', args.iface) execute_shell_command( 'ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875', args.iface, args.iface, CAN_BITRATE) return args.iface else: logger.debug('Using iface %r as SLCAN', args.iface) speed_code = { 1000000: 8, 500000: 6, 250000: 5, 125000: 4, 100000: 3 }[CAN_BITRATE] execute_shell_command('killall -INT slcand &> /dev/null', ignore_failure=True) time.sleep(1) tty = os.path.realpath(args.iface).replace('/dev/', '') logger.debug('TTY %r', tty) execute_shell_command('slcan_attach -f -o -s%d /dev/%s', speed_code, tty) execute_shell_command('slcand %s', tty) iface_name = 'slcan0' time.sleep(1) execute_shell_command('ifconfig %s up', iface_name) execute_shell_command('ifconfig %s txqueuelen 1000', iface_name) return iface_name
def init_can_iface(): if "/" not in args.iface: logger.debug("Using iface %r as SocketCAN", args.iface) execute_shell_command( "ifconfig %s down && ip link set %s up type can bitrate %d sample-point 0.875", args.iface, args.iface, CAN_BITRATE, ) return args.iface else: logger.debug("Using iface %r as SLCAN", args.iface) speed_code = {1000000: 8, 500000: 6, 250000: 5, 125000: 4, 100000: 3}[CAN_BITRATE] execute_shell_command("killall -INT slcand &> /dev/null", ignore_failure=True) time.sleep(1) tty = os.path.realpath(args.iface).replace("/dev/", "") logger.debug("TTY %r", tty) execute_shell_command("slcan_attach -f -o -s%d /dev/%s", speed_code, tty) execute_shell_command("slcand %s", tty) iface_name = "slcan0" time.sleep(1) execute_shell_command("ifconfig %s up", iface_name) execute_shell_command("ifconfig %s txqueuelen 1000", iface_name) return iface_name