def replace_image_body(self, orig, repl, padding): """ Replaces original image with the replacement image :param orig: The image to be replaced :param repl: The image to replace with :param padding: Padding value """ orig_ih = IntelHex() orig_ih.padding = padding orig_ih.loadhex(orig) repl_ih = IntelHex() repl_ih.padding = padding repl_ih.loadhex(repl) minaddr = repl_ih.minaddr() maxaddr = repl_ih.maxaddr() # This adds padding if the image is not aligned to 16 Bytes pad_len = (maxaddr - minaddr + self.header_size) % 16 if pad_len > 0: pad_len = 16 - pad_len for i in range(repl_ih.minaddr(), repl_ih.maxaddr() + pad_len): orig_ih[i] = repl_ih[i] orig_ih.tofile(orig, pathlib.Path(orig).suffix[1:])
def get_firmware_hex_image(firmwareFile, filesystemFile): hex = IntelHex(firmwareFile) hex.padding = 0x00 filesystemHex = IntelHex(filesystemFile) filesystemHex.padding = 0x00 hex.merge(filesystemHex) hexImage = hex.tobinstr(FIRMWARE_START_ADDRESS, FILESYSTEM_END_ADDRESS) return hexImage
def _compute_crc(hex_file_path): # Read in hex file new_hex_file = IntelHex() new_hex_file.padding = 0xFF new_hex_file.fromfile(hex_file_path, format='hex') # Get the starting and ending address addresses = new_hex_file.addresses() addresses.sort() start_end_pairs = list(_ranges(addresses)) regions = len(start_end_pairs) assert regions == 1, ("Error - only 1 region allowed in " "hex file %i found." % regions) start, end = start_end_pairs[0] # Compute checksum over the range (don't include data at location of crc) size = end - start + 1 crc_size = size - 4 data = new_hex_file.tobinarray(start=start, size=crc_size) data_crc32 = binascii.crc32(data) & 0xFFFFFFFF # Grab the crc from the image embedded_crc32 = (((new_hex_file[end - 3] & 0xFF) << 0) | ((new_hex_file[end - 2] & 0xFF) << 8) | ((new_hex_file[end - 1] & 0xFF) << 16) | ((new_hex_file[end - 0] & 0xFF) << 24)) return data_crc32, embedded_crc32
def merge_images(hexf0, hexf1=None): ihex = IntelHex() ihex.padding = 0x00 ihex.loadfile(hexf0, "hex") if hexf1 is not None: # Merge the CM0+ image ihex1 = IntelHex(hexf1) ihex.merge(ihex1, 'ignore') return ihex
def hex_crc(args): ihex_file = args.file[0] programSize = int(args.size[0]) from intelhex import IntelHex ih = IntelHex() ih.loadfile(ihex_file, format="hex") ih.padding = 0xFF bin = ih.tobinarray(size=programSize) crc = stm32_crc32_bytes(0xffffffff, bin) print(hex(crc)) return 0
def merge_images(hexf0, hexf1=None): ihex = IntelHex() ihex.padding = 0x00 ihex.loadfile(hexf0, "hex") if hexf1 is not None: # get chip ID from metadata and compare ihex1 = IntelHex(hexf1) type0 = ihex.tobinarray(start=0x90500002, size=4) type1 = ihex1.tobinarray(start=0x90500002, size=4) if type0 != type1: raise HookError( "Incompatible processor type: %s in '%s' and 0x%s in '%s'" % (hexf0, type0, hexf1, type1)) ihex.merge(ihex1, 'ignore') return ihex
def read_hexdata(hex_path): ih = IntelHex(hex_path) ih.padding = 0x00 print(len(ih), MAX_BINLEN, ih.start_addr, ih.minaddr(), ih.maxaddr()) print(ih.segments()) print(ih[0], ih[1], ih[2]) #print([x for x in ih[0:2]]) if (ih[1] == 0x38 and ih[2] == 0x00): print(">>> Fixing hex file") ih[0] = ih[0x37FB] ih[1] = ih[0x37FC] ih[2] = ih[0x37FD] ih[0x37FB] = 0x00; ih[0x37FC] = 0x00 ih[0x37FD] = 0x00 print(ih[0], ih[1], ih[2]) return ih.tobinarray(size=MAX_BINLEN)
def _process_image(self): """ Read image address and size and calculate image hash """ ih = IntelHex(self.image) ih.padding = 0x00 image_addr = ih.minaddr() image_size = ih.maxaddr() - ih.minaddr() + 1 sha256 = hashlib.sha256() sha256.update(ih.tobinarray(start=image_addr, size=image_size)) image_hash = sha256.digest() image_attr = dict() image_attr['image_hash'] = image_hash image_attr['image_addr'] = image_addr image_attr['image_size'] = image_size image_attr['image_id'] = self.image_id image_attr['version'] = self.version return image_attr
def _build_record(slot_number, image_path, record_type, args): """Builds the appropriate record for the slot given the specified record type""" hex_data = IntelHex(image_path) hex_data.padding = 0xFF offset = hex_data.minaddr() bin_data = bytearray(hex_data.tobinarray(offset, hex_data.maxaddr())) if slot_number == 0: # If slot is controller if record_type == 2: # kReflashControllerTile return ReflashControllerRecord(bin_data, offset) elif record_type == 3: # kExecuteRPCWithoutCheck pass # Not implemented yet elif record_type == 4: # kExecuteRPCWithCheck pass # Not implemented yet elif record_type == 5: # kResetController pass # Not implemented yet elif record_type == 6: # kEnhancedReflashControllerTile if args['reboot'] == "True": skip_reboot_flag = 0 else: skip_reboot_flag = 1 return EnhancedReflashControllerRecord(bin_data, offset, flags=skip_reboot_flag) else: raise BuildError("Invalid record type for this slot.", slot=slot_number, record=record_type) else: # If slot is a tile if record_type == 1: # kReflashExternalTile return ReflashTileRecord(slot_number, bin_data, offset) else: raise BuildError("Invalid record type for this slot.", slot=slot_number, record=record_type)
def main(argv): inputfile = '' port = '' split = 1024 usage_string = 'huzzah_exotag_firmware.py -i <inputfile> -p <comm port:/dev/ttyUSB or \\\.\COM12>' try: opts, args = getopt.getopt(argv, "hi:p:s:", ["file=", "port=", "split="]) except getopt.GetoptError: print() sys.exit(2) if not opts: print("no arguments provided ") print(usage_string) sys.exit(2) for opt, arg in opts: if opt == '-h': print(usage_string) sys.exit() elif opt in ("-i", "--file"): inputfile = arg elif opt in ("-p", "--port"): port = arg elif opt in ("-s", "--split"): split = int(arg) else: print("wrong arguments: " + opt) print(usage_string) print('input file: ' + inputfile) print('output port: ' + port) print('split in bytes: %d' % split) if inputfile.endswith('.hex'): ih = IntelHex() # create empty object ih.padding = 0xFF ih.fromfile(inputfile, format='hex') # also load from hex ascii_bin = binascii.hexlify(ih.tobinstr()) #sys.exit() elif inputfile.endswith( '.bin' ): #reconsider the extension here, the routine actually handles ascii with open(inputfile, 'r') as f: read_data = f.read() f.closed read_data = read_data.rstrip('\r\n') print(read_data) print([n for n in read_data]) ascii_bin = read_data #binascii.unhexlify(read_data) #sys.exit() #print(ascii_bin) crc_result = binascii.crc32(ascii_bin) & 0xffffffff print("CRC = %08x" % crc_result) #sys.exit() exotag_uart = serial.Serial(port, 115200, timeout=1) exotag_uart_io = io.TextIOWrapper( io.BufferedRWPair(exotag_uart, exotag_uart)) print('send start update: ' + unicode('exotag=update\r')) exotag_uart_io.write(unicode('exotag=update'.rstrip() + '\r')) exotag_uart_io.flush() time.sleep(1) #print (exotag_uart.readline()) print('write') for i in range(0, len(ascii_bin), split): print((ascii_bin[i:i + split])) exotag_uart.write((ascii_bin[i:i + split])) exotag_uart_io.flush() time.sleep(1) print(binascii.hexlify(struct.pack("<I", crc_result))) exotag_uart.write('!'.encode() + struct.pack("<I", crc_result)) exotag_uart_io.flush() #time.sleep(1) print('send end of firmware update') exotag_uart_io.write(unicode('~')) exotag_uart_io.flush() print('read exotag messages') exotag_string = exotag_uart_io.read() print("***********************\r\n" + exotag_string + "\r\n***********************") if (-1 != exotag_string.find('firmware update: SUCCESS')): print('tell huzzah to push update to exotag') exotag_uart_io.write(unicode('exotag=program'.rstrip() + '\r')) exotag_uart_io.flush() #time.sleep(10) print('read exotag messages') time.sleep(5) exotag_string = exotag_uart_io.read() print("***********************\r\n" + exotag_string + "\r\n***********************") if (-1 != exotag_string.find( 'EFM8 flash write read-back verify success')): print( 'EFM8 flash write read-back verify success - indicates SUCCESS' ) print('reset exotag') exotag_uart_io.write(unicode('exotag=reset'.rstrip() + '\r')) exotag_uart_io.flush() time.sleep(5) exotag_string = exotag_uart_io.read() print("***********************\r\n" + exotag_string + "\r\n***********************") exotag_uart.close()
if vargs.range is not None: if vargs.range[0] is not None: startAddr = vargs.range[0] if vargs.range[1] is not None: endAddr = vargs.range[1] # Make sure the last address is divisible by 16 remainder = endAddr % OAD_BLOCK_SIZE if remainder: print("Last address was 0x%0X. Expanded to 0x%0X to be divisible by OAD block size" % (endAddr, endAddr+(OAD_BLOCK_SIZE-remainder)) ) endAddr += OAD_BLOCK_SIZE - remainder #if specified, the script will pad the image with the pad value fillHex = IntelHex() fillHex.puts(startAddr, struct.pack('B', vargs.fill) * (endAddr)) mergedHex.merge(fillHex, 'ignore') mergedHex = mergedHex[startAddr:endAddr] # +1 since the last address is not inclusive mergedHex.padding = vargs.fill #if we are calculating metadata #Offchip OAD production images and NP images don't have embedded metadata headers, skip meta data calc for these #All onchip OAD images need metdata placement if not(vargs.oadtype == 'offchip' and (vargs.imgtype == 'production' or vargs.imgtype == 'np')): # Place metadata, onchip production image expects header at 0x600 if vargs.oadtype == 'onchip' and vargs.imgtype == 'production': residentHdr = OadHdr._make(struct.unpack(OAD_HDR_FMT, mergedHex.tobinstr(INT_FL_OAD_IMG_A_META_BEGIN, INT_FL_OAD_IMG_A_META_BEGIN+15))) else: residentHdr = OadHdr._make(struct.unpack(OAD_HDR_FMT, mergedHex.tobinstr(startAddr, startAddr+15))) metaAddr = vargs.meta if metaAddr is None: # Try first address, ideally there should be free space at the beginning of the image #in the reserved image metadata sector
def create_encrypted_image(self, hex_file, aes_key_file, aes_header, host_key_id, dev_key_id, out_file_encrypt, padding_value=0): """ Creates encrypted image for encrypted programming Format: Row 1 - keys ID (byte 1 - host key ID, byte 2 - dev key ID) Row 2 - AES header Other - encrypted image data """ # Write keys ID and AES header out_file_path = os.path.abspath(out_file_encrypt) with open(out_file_path, 'w') as f: f.write(str(host_key_id).zfill(2)) f.write(str(dev_key_id).zfill(2) + '\n') f.write(aes_header + '\n') ih = IntelHex(hex_file) hex_data_dict = ih.todict() if 'start_addr' in hex_data_dict: del hex_data_dict['start_addr'] logger.debug(f'hex_data_dict={hex_data_dict}') # Add padding ih.padding = padding_value data_to_program = dict() file_len = ih.maxaddr() - ih.minaddr() if file_len % FLASH_ROW_SIZE != 0: address_offset = (file_len // FLASH_ROW_SIZE + 1) * FLASH_ROW_SIZE max_address = ih.minaddr() + address_offset else: max_address = ih.maxaddr() for i in range(ih.minaddr(), max_address): data_to_program[i] = ih[i] sorted_address_keys = sorted(data_to_program) for key in sorted_address_keys: logger.debug('0x%08X: %02X' % (key, data_to_program[key])) logger.debug('Data bytes length: %s' % len(sorted_address_keys)) if len(sorted_address_keys) % FLASH_ROW_SIZE != 0: logger.error('Data bytes length is not multiple ' 'by FLASH_ROW_SIZE (%s)' % FLASH_ROW_SIZE) return sorted_bytes_values = [] for key in sorted_address_keys: sorted_bytes_values.append(data_to_program[key]) logger.debug('-' * 30 + ' Virgin rows ' + '-' * 30) address_row_bytes_dict = {} rows_of_bytes = list(AesHeaderStrategy.chunks_list(sorted_bytes_values, FLASH_ROW_SIZE)) flash_addresses = list(AesHeaderStrategy.chunks_list( sorted_address_keys, FLASH_ROW_SIZE)) for i in range(len(flash_addresses)): flash_addresses[i] = flash_addresses[i][0] address_row_bytes_dict[flash_addresses[i]] = rows_of_bytes[i] out_data = '0x%08X %s' % (flash_addresses[i], ''.join( map(AesHeaderStrategy.hex_str_wo_header, rows_of_bytes[i]))) logger.debug(out_data) logger.debug('-' * 30 + ' Encrypted rows ' + '-' * 30) addr_rows_bin = {} aes_key, aes_iv = read_key_from_file(aes_key_file) aes = AESCipherCBC(aes_key, aes_iv) with open(out_file_path, 'a') as encrypted_rows_out: for i in range(len(flash_addresses)): rows_in_binary_format = bytes(rows_of_bytes[i]) encrypted_row = aes.encrypt(rows_in_binary_format) encrypted_row = bytes(list(encrypted_row)) addr_rows_bin[flash_addresses[i]] = encrypted_row out_data = '%08X%s' % (flash_addresses[i], addr_rows_bin[flash_addresses[i]].hex()) logger.debug(out_data) encrypted_rows_out.write(out_data + '\n') logger.info(f'Created encrypted image \'{out_file_path}\'')
from intelhex import IntelHex ih = IntelHex() ih.padding = 0 ih.fromfile("sbos.hex", format="hex") start = ih.segments()[0][0] ih.tobinfile("sbos.bin", start=start, size=8192)
def load(mw, transport, args): bl = MW.Bootloader() bl.start() sleep(1) retval = 1 uid = MW.BootMsg.UID.getUIDFromHexString(args.uid[0]) ihex_file = args.file[0] if not uid in bl.getSlaves(): print("Device is not in bootload mode") return 1 if not bl.select(uid): print("Cannot select device") return 1 try_again = True if try_again: desc = bl.describe_v3(uid) if desc is None: try_again = True else: print("TARGET:" + formatDescription_V3(uid, desc)) try_again = False if try_again: desc = bl.describe_v2(uid) if desc is None: try_again = True else: print("TARGET:" + formatDescription_V2(uid, desc)) try_again = False if try_again: retval = 1 else: programSize = desc.program ih = IntelHex() ih.loadfile(ihex_file, format="hex") ih.padding = 0xFF bin = ih.tobinarray(size=programSize) crc = stm32_crc32_bytes(0xffffffff, bin) print("CRC: " + hex(crc)) what = args.what[0] if what == 'program': if not bl.eraseProgram(uid): print("Cannot erase program") return 1 with open(ihex_file) as f: data = f.read().splitlines() write_ihex(bl, data, crc) if what == 'program': if not bl.write_program_crc(uid, crc): print("Cannot write CRC") return 1 bl.deselect(uid) bl.stop() return retval
# Copyright (C) 2015 Herbert Poetzl import sys import serial import struct from intelhex import IntelHex from smbus import SMBus from time import sleep from icsp import * tty = "/dev/ttyPS1" sel = sys.argv[1] if len(sys.argv) > 1 else "P" ih = IntelHex(sys.argv[2]) ih.padding = 0xFF def ih_data(ih, addr, count=32): data = [] mask = 0xFFFF for n in range(count): l, h = ih[(addr + n)*2], ih[(addr + n)*2 + 1] val = (h << 8)|l mask &= val data.append(val) return data, mask ser = serial.Serial(
def _build_reflash_script_action(target, source, env): """Create a TRUB script containing tile and controller reflashes and/or sensorgraph If the app_info is provided, then the final source file will be a sensorgraph. All subsequent files in source must be in intel hex format. This is guaranteed by the ensure_image_is_hex call in build_update_script. """ out_path = str(target[0]) source = [str(x) for x in source] records = [] if env['USE_SAFEUPDATE']: sgf_off = SendRPCRecord(8, 0x2005, bytearray([0])) # Disable Sensorgraph records.append(sgf_off) safemode_enable = SendRPCRecord(8, 0x1006, bytearray([1])) # Enable Safemode records.append(safemode_enable) # Update application firmwares if env['SLOTS'] is not None: for (controller, slot_id), image_path in zip(env['SLOTS'], source): hex_data = IntelHex(image_path) hex_data.padding = 0xFF offset = hex_data.minaddr() bin_data = bytearray( hex_data.tobinarray(offset, hex_data.maxaddr())) if controller: record = ReflashControllerRecord(bin_data, offset) else: record = ReflashTileRecord(slot_id, bin_data, offset) records.append(record) # Update sensorgraph if env['UPDATE_SENSORGRAPH']: sensor_graph_file = source[-1] sensor_graph = compile_sgf(sensor_graph_file) output = format_script(sensor_graph) records += UpdateScript.FromBinary(output).records # Update App and OS Tag os_info = env['OS_INFO'] app_info = env['APP_INFO'] if os_info is not None: os_tag, os_version = os_info records.append(SetDeviceTagRecord(os_tag=os_tag, os_version=os_version)) if app_info is not None: app_tag, app_version = app_info records.append( SetDeviceTagRecord(app_tag=app_tag, app_version=app_version)) if env['USE_SAFEUPDATE']: safemode_disable = SendRPCRecord(8, 0x1006, bytearray([0])) # Disable safemode records.append(safemode_disable) sgf_on = SendRPCRecord(8, 0x2005, bytearray([1])) # Enable Sensorgraph records.append(sgf_on) script = UpdateScript(records) with open(out_path, "wb") as outfile: outfile.write(script.encode())
def sign_image(self, hex_file, image_id, image_type, encrypt_key=None, erased_val=None, boot_record='default'): """ Signs hex file with the key specified in the policy file. Converts binary file of the signed image. Creates copy of unsigned hex file. Encrypts UPGRADE image if the policy file contains encryption key :param hex_file: The hex file to sign. :param image_id: The ID of the firmware in policy file. :param image_type: The image type. :param encrypt_key: path to public key file for the image encryption :param erased_val: The value that is read back from erased flash :param boot_record: Create CBOR encoded boot record TLV. The sw_type represents the role of the software component (e.g. CoFM for coprocessor firmware). [max. 12 characters] :return: Path to the signed files. One file per slot. """ result = [] slot = self.parser.get_slot(image_id) if erased_val: self.erased_val = erased_val ih_padding = int(erased_val, 0) logger.warning(f'Custom value {erased_val} will be used as an ' f'erased value for all regions and memory types. ' f'Typical correct values for internal and ' f'external Flash memory are 0x00 and 0xFF ' f'respectively.') else: default_erased_val = self._default_erased_value(image_type, slot) ih_padding = int(default_erased_val, 0) if slot is None: logger.error( f'Image with ID {image_id} not found in \'{self.policy_file}\'' ) return None unsigned_hex = '{0}_{2}{1}'.format(*os.path.splitext(hex_file) + ('unsigned', )) copy2(hex_file, unsigned_hex) boot_ih = IntelHex() boot_ih.padding = ih_padding boot_ih.loadfile(hex_file, 'hex') base_addr = boot_ih.minaddr() boot_bin = f'{hex_file}.bin' hex2bin(boot_ih, boot_bin) encrypted_boot = False first_image_result = None # indicates first image signing success for image in slot['resources']: if image_type: if image['type'] != image_type.upper(): continue # skip generating hex file if sign type defined and not same as current image type if image['type'] == ImageType.UPGRADE.name: if 'upgrade' not in slot or not slot['upgrade']: continue # skip generating hex file for UPGRADE slot if it is disabled encryption = self.parser.encryption_enabled(slot['id']) if encryption: if encrypt_key is None: encrypt_key = self.parser.encrypt_key(slot['id']) if encrypt_key is None: raise ValueError('Encryption key not specified') else: if not os.path.isfile(encrypt_key): raise FileNotFoundError( f'Encryption key \'{encrypt_key}\' not found') else: encrypt_key = None if image['type'] == ImageType.BOOT.name: if first_image_result is False: continue hex_out = self.sign_single_hex(slot, image['type'], boot_bin, hex_file, start_addr=base_addr, boot_record=boot_record, encrypt_key=encrypt_key) encrypted_boot = encrypt_key is not None first_image_result = hex_out is not None os.remove(boot_bin) else: if first_image_result is False: continue output_name = '{0}_{2}{1}'.format(*os.path.splitext(hex_file) + ('upgrade', )) hex_out = self.sign_single_hex(slot, image['type'], unsigned_hex, output_name, encrypt_key, boot_record=boot_record) first_image_result = hex_out is not None if hex_out: bin_out = '{0}.bin'.format(os.path.splitext(hex_out)[0]) if not erased_val: default_erased_val = self._default_erased_value( image_type, slot) ih_padding = int(default_erased_val, 0) upgrade_ih = IntelHex() upgrade_ih.padding = ih_padding upgrade_ih.loadfile(hex_out, 'hex') hex2bin(upgrade_ih, bin_out) bin2hex(bin_out, output_name, offset=int(image['address'])) os.remove(bin_out) if hex_out: result.append(hex_out) if encrypted_boot: self.replace_image_body(hex_file, unsigned_hex, ih_padding) if image_type: if ImageType.UPGRADE.name == image_type.upper(): os.remove(hex_file) result = tuple(result) if len(result) > 0 else None return result
if len(hexfnlist) == 0: raise ApplicationError, 'No any DKSF*.hex files found!' hexfn = sorted(hexfnlist, key=os.path.getmtime)[-1] print print os.path.abspath(hexfn) bootfn = glob.glob('..\\..\\Bootloader_Debug\\Exe\\*.hex') if len(bootfn) != 1: raise ApplicationError, 'More than one bootloader .hex file found!' bootfn = os.path.abspath(bootfn[0]) print bootfn ih = IntelHex(hexfn) blih = IntelHex(bootfn) ih.padding = 0xff code = ih.tobinstr(start=fw_offset, end=fw_offset+fw_length-1) res = ih.tobinstr(start=res_offset, end=res_offset+res_length-1) ver_data_offset = code.index(verdatastart) + len(verdatastart) model, version, subversion, litera, assmcode =\ struct.unpack_from('<HHHcB', code, ver_data_offset) ver = str(model) + '.' + str(version) + '.' + str(subversion) + '.' + litera + '-' + str(assmcode) print 'Extracted version data:', ver print 'Merging bootloader file...', ih.start_addr = None # program start addr record will be from BL part try: ih.merge(blih, overlap='error') print 'Ok' except AddressOverlapError:
def main(argv): options = myargs(argv) print("options: {}".format(options)) if not options.policy_path: options.policy_path = 'policy' tools = CySecureTools( options.target_name, options.policy_path + "/" + options.policy_file + '.json') if (options.toolchain == 'ARM'): fromelf_cmd = options.toolchain_path + "/bin/fromelf" app_elf_file = options.build_dir + "/" + options.app_name + ".elf" fromelf_result_dir = options.build_dir + "/" + "fromelf_result" # Check if gcc tools path is valid if (os.path.isdir(options.toolchain_path) == False): print("ERROR: 'ARM Compiler' tools folder not found in path: {}". format(options.toolchain_path)) exit(-1) # Check if elf is valid if (os.path.isfile(app_elf_file) == False): print("ERROR: ELF file not found in path: {}\r\n".format( app_elf_file)) exit(-1) # Split elf file into sections shell_cmd = [ fromelf_cmd, '--i32', '--output=' + fromelf_result_dir, app_elf_file ] ret = exec_shell_command(shell_cmd) if (ret != 0): exit(ret) em_eeprom_hex = fromelf_result_dir + "/" + ".cy_em_eeprom" app_hex_path = options.build_dir + '/' + options.app_name + '.hex' if (os.path.isfile(em_eeprom_hex) == True): sections_list = [ f for f in os.listdir(fromelf_result_dir) if os.path.isfile(os.path.join(fromelf_result_dir, f)) ] sections_list.remove('.cy_em_eeprom') flash = IntelHex() for section in sections_list: sect = IntelHex(fromelf_result_dir + "/" + section) flash.merge(sect, overlap='replace') flash.write_hex_file(app_hex_path, False) CM0_app_src_path = options.cm0_app_path + '/' + options.cm0_app_name + '.hex' CM0_app_dst_path = options.build_dir + '/' + options.cm0_app_name + '.hex' # CySecureTools Image ID for CM4 Applications is # 1) 1 for single-stage, # 2) 16 in case of multi-stage, # Image ID for CM0 Applications is always 1 if (options.core == "CM4"): if (options.secure_boot_stage == "single"): # Sign CM4 image tools.sign_image(app_hex_path, 1) else: # Sign CM4 image tools.sign_image(app_hex_path, 16) # Make a copy of CM0P app image in build folder shutil.copy2(CM0_app_src_path, CM0_app_dst_path) # Sign CM0 image tools.sign_image(CM0_app_dst_path, 1) # Merge CM0, CM4 into a single hex file ihex = IntelHex() ihex.padding = 0x00 ihex.loadfile(app_hex_path, 'hex') \ ihex.merge(IntelHex(CM0_app_dst_path), 'ignore') \ ihex.write_hex_file(app_hex_path, write_start_addr=False, byte_count=16) else: tools.sign_image(app_hex_path, 1) if (os.path.isfile(em_eeprom_hex) == True): # Add emulated EEPROM Section back flash = IntelHex(app_hex_path) eeprom = IntelHex(em_eeprom_hex) flash.merge(eeprom) flash.write_hex_file(app_hex_path, False) else: gcc_objcopy_eabi_cmd = options.toolchain_path + '/bin/arm-none-eabi-objcopy' app_elf_file = options.build_dir + "/" + options.app_name + ".elf" # Check if gcc tools path is valid if (os.path.isdir(options.toolchain_path) == False): print("ERROR: GCC tools folder not found in path: {}".format( options.toolchain_path)) exit(-1) # Check if elf is valid if (os.path.isfile(app_elf_file) == False): print("ERROR: ELF file not found in path: {}\r\n".format( app_elf_file)) exit(-1) # Strip away emulated EEPROM section from hex file before signing shell_cmd = [ gcc_objcopy_eabi_cmd, '-R', '.cy_em_eeprom', '-O', 'ihex', app_elf_file, options.build_dir + "/" + options.app_name + ".hex" ] ret = exec_shell_command(shell_cmd) if (ret != 0): exit(ret) # Store emulated eeprom section in a seperate hex file shell_cmd = [ gcc_objcopy_eabi_cmd, '-j', '.cy_em_eeprom', '-O', 'ihex', options.build_dir + "/" + options.app_name + ".elf", options.build_dir + "/em_eeprom.hex" ] ret = exec_shell_command(shell_cmd) if (ret != 0): exit(ret) app_hex_path = options.build_dir + '/' + options.app_name + '.hex' CM0_app_src_path = options.cm0_app_path + '/' + options.cm0_app_name + '.hex' CM0_app_dst_path = options.build_dir + '/' + options.cm0_app_name + '.hex' # CySecureTools Image ID for CM4 Applications is # 1) 1 for single-stage, # 2) 16 in case of multi-stage, # Image ID for CM0 Applications is always 1 if (options.core == "CM4"): if (options.secure_boot_stage == "single"): # Sign CM4 image tools.sign_image(app_hex_path, 1) else: # Sign CM4 image tools.sign_image(app_hex_path, 16) # Make a copy of CM0P app image in build folder shutil.copy2(CM0_app_src_path, CM0_app_dst_path) # Sign CM0 image tools.sign_image(CM0_app_dst_path, 1) # Merge CM0, CM4 into a single hex file ihex = IntelHex() ihex.padding = 0x00 ihex.loadfile(app_hex_path, 'hex') \ ihex.merge(IntelHex(CM0_app_dst_path), 'ignore') \ ihex.write_hex_file(app_hex_path, write_start_addr=False, byte_count=16) else: tools.sign_image(app_hex_path, 1) # Add emulated EEPROM Section back flash = IntelHex(app_hex_path) eeprom = IntelHex(options.build_dir + "/em_eeprom.hex") flash.merge(eeprom) flash.write_hex_file(app_hex_path, False) exit(0)
# read out the header header = ih2header(prog) # optional updates if args.pid != None and args.pid >= 0 and args.pid < 256: header['pid'] = args.pid if args.key != None: header['key'] = args.key if args.hw != None: header['hw_id'] = args.hw # update the header len l = prog.maxaddr() - prog.minaddr() + 1 header['len'] = l prog = header2ih(prog, header) # put the length back into the intel hex file for crc # update the header crc (note we do no include the CRC word in the CRC) crc_start_addr = prog.minaddr() + 4 prog.padding = 0xff buf = prog.tobinstr(start=crc_start_addr) crc.crc_init(crc.stm32f10x_crc_h) crc = crc.crc_buf(crc.stm32f10x_crc_h, buf, len(buf)) & 0xffffffff header['crc'] = crc prog = header2ih( prog, header) # put the crc back into the intel hex file so we can write it out # write header back to hex file prog.write_hex_file(sys.stdout)
def updateFirmware(self, hexFilePath, newDeviceAddress=None): hexFile = IntelHex(source=hexFilePath) hexFile.padding = FLASH_PADDING appBinary = hexFile.tobinarray(start=APP_START_ADDRESS, end=NV_SETTINGS_END) crcBinary = hexFile.tobinarray(start=CHECKSUM_DESCRIPTOR_START, end=CHECKSUM_DESCRIPTOR_END) if newDeviceAddress: self._logger.debug( "Modifying the last byte in NV settings to change Device I2C Addrress to {0:#0X}" .format(newDeviceAddress)) if (newDeviceAddress < IQS5xx_DEFAULT_ADDRESS) or ( newDeviceAddress > IQS5xx_MAX_ADDRESS): raise ValueError( "Invalid I2C Address. Use something in the range [%x, %x]" % (IQS5xx_DEFAULT_ADDRESS, IQS5xx_MAX_ADDRESS)) appBinary[-1] = newDeviceAddress # Step 1 - Enter Bootloader self._logger.debug("Entering Bootloader") bootloaderAddress = 0x40 ^ self.address bootloaderDevice = i2c.get_i2c_device(bootloaderAddress) self.holdReset(100) bootloaderEntered = False for i in range(10): try: version = bootloaderDevice.readU16(BL_CMD_READ_VERSION, little_endian=False) bootloaderEntered = True except: pass if not bootloaderEntered: raise IOError("Timeout while trying to enter bootlaoder") self._logger.debug("Bootloader entered successfully") # Step 2 - Read and verify the bootloader version number self._logger.debug("Reading Bootloader version") if version != BL_VERSION: raise Exception( "Incompatible bootloader version detected: {0:#0X}".format( version)) self._logger.debug("Bootloader version is compatible: 0x%02X", version) # Step 3 - Write the new application firmware and settings self._logger.debug("Starting to write Application and NV settings") for blockNum in range(APP_SIZE_BLOCKS + NV_SETTINGS_SIZE_BLOCKS): blockAddress = APP_START_ADDRESS + (blockNum * BLOCK_SIZE) self._logger.debug( 'Writing 64-byte block {0}/{1} at address {2:#0X}'.format( blockNum + 1, APP_SIZE_BLOCKS + NV_SETTINGS_SIZE_BLOCKS, blockAddress)) data = bytearray(BLOCK_SIZE + 2) data[0] = (blockAddress >> 8) & 0xFF data[1] = blockAddress & 0xFF data[2:] = appBinary[blockNum * BLOCK_SIZE:(blockNum + 1) * BLOCK_SIZE] bootloaderDevice.writeBytes(data) time.sleep(.010) # give the device time to write to flash # Step 4 - Write the checksum descriptor section self._logger.debug("Writing CRC section") blockAddress = CHECKSUM_DESCRIPTOR_START data = bytearray(BLOCK_SIZE + 2) data[0] = (blockAddress >> 8) & 0xFF data[1] = blockAddress & 0xFF data[2:] = crcBinary[0:] bootloaderDevice.writeBytes(data) time.sleep(0.010) # give the device time to write to flash # Step 5 - Perform CRC and read back settins section time.sleep(0.1) self._logger.debug("Performing CRC calculation") bootloaderDevice.writeRaw8(BL_CMD_RUN_CRC) time.sleep(0.2) crcStatus = bootloaderDevice.readRaw8() if crcStatus != BL_CRC_PASS: raise Exception("CRC Failure") self._logger.debug("CRC Success") self._logger.debug("Reading back NV settings and comparing") for blockNum in range(NV_SETTINGS_SIZE_BLOCKS): blockAddress = NV_SETTINGS_START + (blockNum * BLOCK_SIZE) self._logger.debug( 'Reading 64-byte block {0}/{1} at address {2:#0X}'.format( blockNum + 1, NV_SETTINGS_SIZE_BLOCKS, blockAddress)) data = bytearray(3) data[0] = BL_CMD_READ_64_BYTES data[1] = (blockAddress >> 8) & 0xFF data[2] = blockAddress & 0xFF reply = bootloaderDevice.writeRawListReadRawList(data, BLOCK_SIZE) expectedReply = appBinary[(APP_SIZE_BLOCKS + blockNum) * BLOCK_SIZE:(APP_SIZE_BLOCKS + blockNum + 1) * BLOCK_SIZE].tostring() if reply != expectedReply: raise Exception( "Unexpected values while reading back NV Setting: {0} \nExpected values: {1}" .format(bytesToHexString(reply), bytesToHexString(expectedReply))) self._logger.debug("NV Settings match expected values") # Step 6 - Execute application self._logger.debug("Execute Application") bootloaderDevice.writeRaw8(BL_CMD_EXECUTE_APP) if newDeviceAddress: self.address = newDeviceAddress
# Make sure the last address is divisible by 16 remainder = endAddr % OAD_BLOCK_SIZE if remainder: print( "Last address was 0x%0X. Expanded to 0x%0X to be divisible by OAD block size" % (endAddr, endAddr + (OAD_BLOCK_SIZE - remainder))) endAddr += OAD_BLOCK_SIZE - remainder #if specified, the script will pad the image with the pad value fillHex = IntelHex() fillHex.puts(startAddr, struct.pack('B', vargs.fill) * (endAddr)) mergedHex.merge(fillHex, 'ignore') mergedHex = mergedHex[ startAddr:endAddr] # +1 since the last address is not inclusive mergedHex.padding = vargs.fill #if we are calculating metadata #Offchip OAD production images and NP images don't have embedded metadata headers, skip meta data calc for these #All onchip OAD images need metdata placement if not (vargs.oadtype == 'offchip' and (vargs.imgtype == 'production' or vargs.imgtype == 'np')): # Place metadata, onchip production image expects header at 0x600 if vargs.oadtype == 'onchip' and vargs.imgtype == 'production': residentHdr = OadHdr._make( struct.unpack( OAD_HDR_FMT, mergedHex.tobinstr(INT_FL_OAD_IMG_A_META_BEGIN, INT_FL_OAD_IMG_A_META_BEGIN + 15))) else: residentHdr = OadHdr._make(
import sys import serial import struct from intelhex import IntelHex from smbus import SMBus from time import sleep from axiom_icsp import * from axiom_via import * tty = "/dev/ttyPS1" sel = sys.argv[1] ih = IntelHex(sys.argv[2]) ih.padding = 0xFF def ih_data(ih, addr, count=32): data = [] mask = 0xFFFF for n in range(count): l, h = ih[(addr + n) * 2], ih[(addr + n) * 2 + 1] val = (h << 8) | l mask &= val data.append(val) return data, mask ser = serial.Serial( port=tty,
header_addr = prog.minaddr() # all programs require there header to be located at the start # read out the header header = ih2header(prog) # optional updates if args.pid != None and args.pid >= 0 and args.pid < 256: header['pid'] = args.pid if args.key != None: header['key'] = args.key if args.hw != None: header['hw_id'] = args.hw # update the header len l = prog.maxaddr() - prog.minaddr() + 1 header['len'] = l prog = header2ih(prog, header) # put the length back into the intel hex file for crc # update the header crc (note we do no include the CRC word in the CRC) crc_start_addr = prog.minaddr() + 4 prog.padding = 0xff buf = prog.tobinstr(start=crc_start_addr) crc.crc_init(crc.stm32f10x_crc_h) crc = crc.crc_buf(crc.stm32f10x_crc_h, buf, len(buf)) & 0xffffffff header['crc'] = crc prog = header2ih(prog, header) # put the crc back into the intel hex file so we can write it out # write header back to hex file prog.write_hex_file(sys.stdout)
def get_bootloader_hex_image(bootoaderFile): hex = IntelHex(bootoaderFile) hex.padding = 0x00 hexImage = hex.tobinstr(BOOTLOADER_START_ADDRESS, BOOTLOADER_END_ADDRESS) return hexImage
d = 0 if (crc_out & 0x1): c = 0xFFFFFFFF else: c = 0 crc_out = crc_out >> 1 crc_out = crc_out ^ ((d ^ c) & crc_poly) return crc_out if __name__ == '__main__': args = get_args() ih = IntelHex() ih.padding = 0x00 print("-I Reading file {}...".format(args.ihex)) ih.fromfile(args.ihex, format='hex') # fromfile is the recommended way print("-I- Done") min_addr = ih.minaddr() max_addr = ih.maxaddr() print("-I- Start address : {}".format(min_addr)) print("-I- End address : {}".format(max_addr)) # See http://python-intelhex.readthedocs.io/en/latest/part2-5.html mem_array = OrderedDict() # Not sure if we need a +1 on the max_addr for i in range(min_addr, max_addr, 4): data = ih.tobinarray(start=i, size=4)
def parse_args(): parser = argparse.ArgumentParser( description='Hash data from file.', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '--infile', '-i', '--in', '-in', required=True, help= 'Hash the contents of the specified file. If a *.hex file is given, the contents will ' 'first be converted to binary, with all non-specified area being set to 0xff. ' 'For all other file types, no conversion is done.') return parser.parse_args() if __name__ == '__main__': args = parse_args() if args.infile.endswith('.hex'): ih = IntelHex(args.infile) ih.padding = 0xff # Allows hashing with empty regions to_hash = ih.tobinstr() else: to_hash = open(args.infile, 'rb').read() sys.stdout.buffer.write(hashlib.sha256(to_hash).digest())
def main(): parser = argparse.ArgumentParser() parser.add_argument( '-s', '--sample-rate', dest='sample_rate', type=int, required=True, help='Sample rate in Hz. Must be a multiple of the symbol rate.') parser.add_argument('-y', '--symbol-rate', dest='symbol_rate', type=int, required=True, help='Symbol rate in Hz.') parser.add_argument( '-b', '--block-size', dest='block_size', required=True, help='The number of bytes that the target will write at a time. ' 'Must be a multiple of the packet size.') parser.add_argument( '-w', '--write-time', dest='write_time', required=True, help='Amount of time in milliseconds required by the target to write ' 'a block.') parser.add_argument( '-f', '--flash-spec', dest='flash_spec', required=True, nargs='+', help='Flash page specification which describes the layout of the ' 'target\'s flash memory. This is a list of ' 'specifiers of the form "SIZE:ETIME[:NUM]", where SIZE is the ' 'size in bytes of the page (and must be a multiple of the block ' 'size), ETIME is the amount of time in milliseconds to allow for ' 'the page erase to complete, and NUM optionally specifies the ' 'number of these pages (if NUM is not given, then this specifier ' 'will be used for all remaining pages). For example, a simple ' 'layout consisting of 1KB pages that require 50ms each to erase ' 'could be specified as "1024:50", while a more complex layout ' 'like that of the STM32F405 could be specified as ' '"16K:500:4 64K:1100:1 128K:2000:7".') parser.add_argument( '-a', '--start-address', dest='start_address', required=True, help='Flash memory address at which the firmware will be written. ' 'If a "+" is prepended, this will be interpreted as an offset from ' 'the base address, otherwise as an absolute address. Must align ' 'to a page.') parser.add_argument( '-x', '--base-address', dest='base_address', default='0', help='Base address of the target\'s flash memory. Default 0.') parser.add_argument( '-p', '--packet-size', dest='packet_size', default='256', help='Packet size in bytes. Must be a multiple of 4. Default 256.') parser.add_argument( '--fill', dest='fill_byte', default='0xFF', help='Byte value to use to fill gaps and pad lengths. Default 0xFF.') parser.add_argument('-e', '--seed', dest='crc_seed', default='0', help='CRC32 seed. Default 0.') parser.add_argument( '-t', '--file-type', dest='file_type', choices=['hex', 'bin', 'auto'], default='auto', help='Input file type. If a hex file is used, all ' 'content before the start address will be ignored. A bin file is ' 'always assumed to start at the start address. Default auto.') parser.add_argument('-i', '--input-file', dest='input_file', default='-', help='Input file (bin or hex). Default stdin.') parser.add_argument( '-o', '--output-file', dest='output_file', default=None, help='Output wav file. The default is derived from the input file name ' 'if one is given, otherwise stdout.') args = parser.parse_args() if args.input_file == '-': input_file = sys.stdin.buffer if args.output_file == None: args.output_file = '-' else: input_file = open(args.input_file, 'rb') (root, ext) = os.path.splitext(args.input_file) if args.file_type == 'auto' and ext in ['.bin', '.hex']: args.file_type = ext[1:] if args.output_file == None: args.output_file = root + '.wav' data = input_file.read() if input_file is not sys.stdin.buffer: input_file.close() if args.file_type == 'auto': is_hex = all(map(lambda x: chr(x) in string.hexdigits + ':\r\n', data)) args.file_type = 'hex' if is_hex else 'bin' base_address = int(args.base_address, 0) if args.start_address.startswith('+'): start_address = base_address + int(args.start_address[1:], 0) else: start_address = int(args.start_address, 0) fill_byte = int(args.fill_byte, 0) if args.file_type == 'hex': from intelhex import IntelHex ihex = IntelHex(io.StringIO(data.decode('ascii')))[start_address:] ihex.padding = fill_byte data = ihex.tobinstr() if args.output_file == '-': output_file = sys.stdout.buffer else: output_file = args.output_file arrangement = Arrangement(flash_spec=args.flash_spec, reserved_size=start_address - base_address, block_size=parse_size(args.block_size), fill_byte=fill_byte, write_time=float(args.write_time), data=data) encoder = Encoder(symbol_rate=args.symbol_rate, packet_size=parse_size(args.packet_size), crc_seed=int(args.crc_seed, 0)) symbols = encoder.encode(arrangement) assert (args.sample_rate % args.symbol_rate) == 0 modulator = QPSKModulator(args.sample_rate, args.symbol_rate) signal = modulator.modulate(symbols) writer = wave.open(output_file, 'wb') writer.setframerate(args.sample_rate) writer.setsampwidth(2) writer.setnchannels(1) writer.writeframes(signal.tobytes()) writer.close()
def main(): if len(sys.argv) < 3: print("Usage: %s <bin file> <cyad file>") sys.exit() bin_file = sys.argv[1] cyad_file = sys.argv[2] if not os.path.isfile(bin_file): print("bin file path %s does not exist. Exiting..." % (bin_file)) sys.exit() else: print("bin file: " + bin_file) if not os.path.isfile(cyad_file): print("cyad path %s does not exist. Exiting..." % (cyad_file)) sys.exit() else: print("cyad file: " + cyad_file) with open(bin_file, mode='rb') as bfp: b = bytearray(bfp.read()) print("binary loade, len %d" % len(b)) # Now merge in the cyad bdata = bytearray() # default deviceid = int(CYPD2104_20FNXI, 16) with open(cyad_file) as cyfp: cnt = 0 for line in cyfp: if cnt == 0: if CYPD2104_20FNXI in line: deviceid = int(CYPD2104_20FNXI, 16) print("device is CYPD2104_20FNXI") elif CYPD2122_20FNXIT in line: deviceid = int(CYPD2122_20FNXIT, 16) print("device is CYPD2122_20FNXIT") else: print("unk device: %s" % (line)) else: line = line.strip() if cnt == 1: cyad_addr = int(line[1:9], 16) >> 1 print("addr: %x" % cyad_addr) data = line[11:len(line) - 2] bdata.extend(binascii.unhexlify(data)) cnt += 1 # merge cyad with program data bend = b[cyad_addr + len(bdata):] b = b[:cyad_addr] b.extend(bdata) b.extend(bend) # update csums updateCfgCsum(cyad_addr, b) # calculate the binary checksum csum = calcChecksum(b) csum_short = csum & 0xFFFF # Create the device record meta data DiDR = createDeviceIdRecord(csum, deviceid) # create the hex file string sio = StringIO() ihex = IntelHex() ihex.start_addr = None ihex.padding = 0x00 # ihex failed to decode a character, so doing it one by one for i, c in enumerate(b): ihex[i] = c # write out the ihex string ihex.write_hex_file(sio) hexstr = sio.getvalue() sio.close() # remove the EOF so we can add the cypress metadata hexstr = hexstr[:hexstr.rfind(ihex_eof)] # metadata stoarge suffix = [] # add checksum short suffix.append(":0200000490303A") suffix.append(makedataline(csum_short.to_bytes(2, byteorder='big'), 0, 0)) # metadata suffix.append(":0200000490402A") suffix.append( ":200000000000000000000000000000000000000000000000000000000000000000000000E0" ) # Device id record suffix.append(":0200000490501A") suffix.append(makedataline(DiDR, 0, 0)) # chip level protection suffix.append(":0200000490600A") suffix.append(":0100000001FE") # EOF suffix.append(ihex_eof) tail = '\n'.join(suffix) hexstr = hexstr + tail with open("out.hex", mode='w') as ofp: ofp.write(hexstr)