class Driver(FirmwareBase): def __init__(self, filename, node, vcode, conn): FirmwareBase.__init__(self, filename, node, vcode, conn) self.__ih = IntelHex() self.__ih.loadhex(filename) cs = crc.crc16() for each in range(self.__ih.minaddr(), self.__ih.maxaddr()+1): cs.addByte(self.__ih[each]) self.__size = self.__ih.maxaddr()+1 self.__checksum = cs.getResult() def download(self): progress = 0.0 self.sendStatus("Starting Download to Node " + str(self.destNode)) while True: if self.kill==True: self.sendProgress(0.0) self.sendStatus("Download Stopped") return time.sleep(0.1) self.sendProgress(progress) progress = progress + 0.01 if progress > 1: break self.sendProgress(1.0) self.sendStatus("Download Successful")
def write_flash_hex(self, flash_file): flash_hex = IntelHex() flash_hex.fromfile(flash_file, "hex") if flash_hex.maxaddr() >= self.application_size: raise KpBoot32u4Error( "Hex file doesn't fit in flash. Maximum flash address is {}, but" " the given file writes to address {}.".format( self.application_size, flash_hex.maxaddr(), )) segments = flash_hex.segments() # checks if a given page is a part of any of the segments in the hex # file def is_page_used(p_start, p_end): for (seg_start, seg_end) in segments: if seg_start <= p_start < seg_end: return True if seg_start <= p_end < seg_end: return True return False # flash is only page accessible, so look at each page in the hex file # and see if it needs to be written for start in range(0, self.application_size, self.page_size): end = start + self.page_size if not is_page_used(start, end): continue # Get the data for the current page and write it data = bytearray(flash_hex.tobinstr(start, end - 1)) self.write_flash_page(start, data)
class Driver(FirmwareBase): def __init__(self, filename): FirmwareBase.__init__(self) self.__ih = IntelHex() self.__ih.loadhex(filename) cs = crc.crc16() for each in range(self.__ih.minaddr(), self.__ih.maxaddr()+1): cs.addByte(self.__ih[each]) self.__size = self.__ih.maxaddr()+1 self.__checksum = cs.getResult() def download(self): progress = 0.0 self.sendStatus("Starting Download to Node " + str(self.destNode)) while True: if self.kill==True: self.sendProgress(0.0) self.sendStatus("Download Stopped") return time.sleep(0.1) self.sendProgress(progress) progress = progress + 0.01 if progress > 1: break self.sendProgress(1.0) self.sendStatus("Download Successful")
def convert_hex(basename): hex_name = basename + '.hex' print('Reading %s' % hex_name) ih = IntelHex(hex_name) # f = open(basename + '.txt', 'w') # open file for writing # ih.dump(f) # dump to file object # f.close() # close file size = ih.maxaddr() - ih.minaddr() + 1 print('- Start: %x' % ih.minaddr()) print('- End: %x' % ih.maxaddr()) with open(basename + '.h', 'w') as fout: fout.write(header.replace('BASENAME', basename)) with open(basename + '.c', 'w') as fout: fout.write(code_start.replace('BASENAME', basename)) fout.write(' ') for i in range(0, size): if i % 1000 == 0: print('- Write %05u/%05u' % (i, size)) byte = ih[ih.minaddr() + i] fout.write("0x{0:02x}, ".format(byte)) if (i & 0x0f) == 0x0f: fout.write('\n ') fout.write(code_end) print('Done\n')
def convert_hex(basename): hex_name = basename + '.hex' print ('Reading %s' % hex_name) ih = IntelHex(hex_name) # f = open(basename + '.txt', 'w') # open file for writing # ih.dump(f) # dump to file object # f.close() # close file size = ih.maxaddr() - ih.minaddr() + 1 print '- Start: %x' % ih.minaddr() print '- End: %x' % ih.maxaddr() with open(basename + '.h', 'w') as fout: fout.write(header.replace('BASENAME',basename)); with open(basename + '.c', 'w') as fout: fout.write(code_start.replace('BASENAME',basename)); fout.write(' ') for i in range(0,size): if i % 1000 == 0: print ('- Write %05u/%05u' % (i, size)) byte = ih[ih.minaddr() + i] fout.write("0x{0:02x}, ".format(byte)) if (i & 0x0f) == 0x0f: fout.write('\n ') fout.write(code_end); print ('Done\n')
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 diff(hex_filename_1, hex_filename_2): hex_1 = IntelHex(hex_filename_1) hex_2 = IntelHex(hex_filename_2) max_address = max(hex_1.maxaddr(), hex_2.maxaddr()) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * WIDTH * 2)) print('| Addr | {0} | {1} |'.format( hex_filename_1.split('/')[-1].ljust(WIDTH * 2), hex_filename_2.split('/')[-1].ljust(WIDTH * 2))) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * WIDTH * 2)) for address in xrange(0, max_address, WIDTH): data_1 = [] data_2 = [] for offset in xrange(WIDTH): data_1.append(hex_1[address + offset]) data_2.append(hex_2[address + offset]) formatted_address = '{:06X}'.format(address) formatted_data_1 = ''.join('{:02X}'.format(byte) for byte in data_1) formatted_data_2 = '='.ljust(WIDTH * 2) if data_1 != data_2: formatted_data_2 = ''.join('{:02X}'.format(byte) for byte in data_2).rjust(WIDTH * 2) print('| {0} | {1} | {2} |'.format(formatted_address, formatted_data_1, formatted_data_2)) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * WIDTH * 2))
def merge_region_list(region_list, destination, padding=b'\xFF'): """Merege the region_list into a single image Positional Arguments: region_list - list of regions, which should contain filenames destination - file name to write all regions to padding - bytes to fill gapps with """ merged = IntelHex() print("Merging Regions:") for region in region_list: if region.active and not region.filename: raise ToolException("Active region has no contents: No file found.") if region.filename: print(" Filling region %s with %s" % (region.name, region.filename)) part = intelhex_offset(region.filename, offset=region.start) part_size = (part.maxaddr() - part.minaddr()) + 1 if part_size > region.size: raise ToolException("Contents of region %s does not fit" % region.name) merged.merge(part) pad_size = region.size - part_size if pad_size > 0 and region != region_list[-1]: print(" Padding region %s with 0x%x bytes" % (region.name, pad_size)) merged.puts(merged.maxaddr() + 1, padding * pad_size) if not exists(dirname(destination)): makedirs(dirname(destination)) print("Space used after regions merged: 0x%x" % (merged.maxaddr() - merged.minaddr() + 1)) with open(destination, "wb+") as output: merged.tofile(output, format='bin')
class Hex2BinConv: def __init__(self, out): self.hex = IntelHex() self.out = out def load(self, filename): print print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size / 1024.0, size) def conv(self, label): done = False adr = self.hex.minaddr() max_adr = self.hex.maxaddr() out_file = open(self.out, "wb") lab_str = "" if label == "ee": f = open("../utils/build/build_number.txt", "r") number = int(f.readline()) f.close() # lab_str += struct.pack("<H", number) else: for i in range(32): if i >= len(label): c = chr(0) else: c = label[i] lab_str += c out_file.write(lab_str) print " label: %s" % lab_str print "Converting HEX 2 BIN ...", while adr <= max_adr: out_file.write(chr(self.hex[adr])) adr += 1 out_file.close() print "Done" def batch(self, filename, label): start = time.clock() self.load(filename) self.conv(label) end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
class Hex2BinConv(): def __init__(self, out): self.hex = IntelHex() self.out = out def load(self, filename): print print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size / 1024.0, size) def conv(self, label): done = False adr = self.hex.minaddr() max_adr = self.hex.maxaddr() out_file = open(self.out, "wb") lab_str = '' if (label == "ee"): f = open("../utils/build/build_number.txt", "r") number = int(f.readline()) f.close() #lab_str += struct.pack("<H", number) else: for i in range(32): if i >= len(label): c = chr(0) else: c = label[i] lab_str += c out_file.write(lab_str) print " label: %s" % lab_str print "Converting HEX 2 BIN ...", while (adr <= max_adr): out_file.write(chr(self.hex[adr])) adr += 1 out_file.close() print "Done" def batch(self, filename, label): start = time.clock() self.load(filename) self.conv(label) end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
def post_process(self): logging.info("Processing binaries") # save original dir cwd = os.getcwd() # change to target dir os.chdir(self.target_dir) ih = IntelHex('main.hex') fwid = uuid.UUID('{' + self.settings["FWID"] + '}') size = ih.maxaddr() - ih.minaddr() + 1 # get os info os_project = get_project_builder(self.settings["OS_PROJECT"]) # create firmware info structure fw_info = struct.pack('<I16s128s16s128s16s', size, fwid.bytes, os_project.proj_name, os_project.version, self.proj_name, self.version) # insert fw info into hex ih.puts(0x120, fw_info) # compute crc crc_func = crcmod.predefined.mkCrcFun('crc-aug-ccitt') crc = crc_func(ih.tobinstr()) logging.info("size: %d" % (size)) logging.info("fwid: %s" % (fwid)) logging.info("crc: 0x%x" % (crc)) logging.info("os name: %s" % (os_project.proj_name)) logging.info("os version: %s" % (os_project.version)) logging.info("app name: %s" % (self.proj_name)) logging.info("app version: %s" % (self.version)) ih.puts(ih.maxaddr() + 1, struct.pack('>H', crc)) ih.write_hex_file('main.hex') ih.tobinfile('firmware.bin') # get loader info loader_project = get_project_builder(self.settings["LOADER_PROJECT"]) # create loader image loader_hex = os.path.join(loader_project.target_dir, "main.hex") self.merge_hex('main.hex', loader_hex, 'loader_image.hex') # change back to original dir os.chdir(cwd)
def main(): try: os.remove(RESULT) except OSError: pass ihx = IntelHex() ihx.fromfile(TARGET, format='hex') addr_min, addr_max = ihx.minaddr(), ihx.maxaddr() print hex(addr_min), hex(addr_max) ihx.tofile(TEST, format='hex') d = Disassembler() function = ihx.tobinarray()[FUNC_START:] blocks = d.parse(function, 0, FUNC_START) for b in blocks: print '-' * 40 print repr(b) print '-' * 40 blocks = sum(blocks) data = blocks.assemble(FUNC_START, externalize_labels=True) print 'Stream:', ' '.join('%02x' % b for b in bytearray(data)) data_length = len(data) print 'Writing %d bytes.' % data_length ihx.puts(FUNC_START, data) appendix = Block() label_nops = Label('look_mah_no_ops') appendix += Block(label_nops, nop, nop, nop, nop) appendix += Block(Data('\xef\xbe')) appendix += Block(Data(0xbeef)) appendix += Block(Data(label_nops)) end = ihx.maxaddr() + 1 data = appendix.assemble(end, externalize_labels=True) data_length = len(data) print 'Writing %d bytes.' % data_length ihx.puts(end, data) ihx.tofile(RESULT, format='hex') patched = IntelHex() patched.fromfile(RESULT, format='hex') check = ihx.tobinarray()[FUNC_START:FUNC_START + data_length] print 'Stream:', ' '.join('%02x' % b for b in bytearray(data)) print hex(patched.minaddr()), hex(patched.maxaddr())
def writeImage(self, filename): #Sends an CMD_WRITE to the bootloader #This is method is a generator, that returns its progresses to the caller. #In this way, it's possible for the caller to live-print messages about #writing progress ih = IntelHex() ih.loadhex(filename) yield {"saddr": ih.minaddr(), "eaddr": ih.maxaddr()} global sad addr = ih.minaddr() sad = addr content = ih.todict() abort = False resend = 0 while addr <= ih.maxaddr(): if not resend: data = [] saddr = addr for i in range(16): try: data.append(content[addr]) except KeyError: #if the HEX file doesn't contain a value for the given address #we "pad" it with 0xFF, which corresponds to the erase value data.append(0xFF) addr += 1 try: if resend >= 3: abort = True break self.serial.flushInput() self.serial.write( self._create_cmd_message( [CMD_WRITE] + map(ord, struct.pack("I", saddr)))) ret = self.serial.read(1) if len(ret) == 1: if struct.unpack("b", ret)[0] != ACK: raise ProgramModeError("Write abort") else: raise TimeoutError("Timeout error") encdata = data # self._encryptMessage(data) self.serial.flushInput() self.serial.write(self._create_cmd_message(data)) ret = self.serial.read(1) if len(ret) == 1: if struct.unpack("b", ret)[0] != ACK: raise ProgramModeError("Write abort") else: raise TimeoutError("Timeout error") yield {"loc": saddr, "resend": resend} resend = 0 except (TimeoutError, ProgramModeError): resend += 1 yield {"success": not abort}
class Hex2BinConv(): def __init__(self, out): self.hex = IntelHex() self.out = out def load(self, filename): print print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size/1024, size) def conv(self, label): done = False adr = self.hex.minaddr() max_adr = self.hex.maxaddr() out_file = open(self.out, "wb"); lab_str = ''; for i in range(32): if i >= len(label): c = chr(0) else: c = label[i] lab_str += c print " label: %s" % lab_str print "Converting HEX 2 BIN ...", out_file.write(lab_str) while(adr <= max_adr): out_file.write(chr(self.hex[adr])) adr += 1 out_file.close() print "Done" def batch(self, filename, label): start = time.clock() self.load(filename) self.conv(label) end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
def _main(): """Append credentials to a prebuilt hex file, download it via a J-Link debug probe, allow the hex file to run, verify the result code, and then erase the hex file. """ args = _add_and_parse_args() nrfjprog_api = None nrfjprog_probe = None try: hex_path = HEX_PATH if args.in_file: hex_path = args.in_file intel_hex = IntelHex(hex_path) if intel_hex.maxaddr() >= CRED_PAGE_ADDR: if hex_path == HEX_PATH: print("error: Prebuilt hex file is too large.") _close_and_exit(nrfjprog_api, -3) elif (intel_hex.maxaddr() < FW_RESULT_CODE_ADDR or intel_hex.gets(CRED_PAGE_ADDR, 4) != MAGIC_NUMBER_BYTES): print("error: Magic number not found in hex file.") _close_and_exit(nrfjprog_api, -2) else: intel_hex.puts(CRED_PAGE_ADDR, MAGIC_NUMBER_BYTES) intel_hex.puts(CRED_COUNT_ADDR, struct.pack('B', 0x00)) if not args.out_file or args.program_app: nrfjprog_api, nrfjprog_probe = _connect_to_jlink(args) _append_creds(intel_hex, args) if args.out_file: intel_hex.tofile(args.out_file, "hex") else: # Create a temporary file to pass to pynrfjprog and then delete it when finished. tmp_file = os.path.sep.join((tempfile.mkdtemp(), TMP_FILE_NAME)) intel_hex.tofile(tmp_file, "hex") _write_firmware(nrfjprog_probe, tmp_file) time.sleep(args.fw_delay) result_code = nrfjprog_probe.read(FW_RESULT_CODE_ADDR) if result_code: print("error: Firmware result is 0x{:X}".format(result_code)) _close_and_exit(nrfjprog_api, -4) imei_bytes = nrfjprog_probe.read(IMEI_ADDR, IMEI_LEN + 1) if (IMEI_LEN != imei_bytes.find(BLANK_FLASH_VALUE) or not imei_bytes[:IMEI_LEN].isdigit()): print("error: IMEI does not look valid.") _close_and_exit(nrfjprog_api, -5) print(imei_bytes[:-1].decode()) nrfjprog_probe.erase(HighLevel.EraseAction.ERASE_ALL) os.remove(tmp_file) os.removedirs(os.path.dirname(tmp_file)) if args.program_app: _write_firmware(nrfjprog_probe, args.program_app) _close_and_exit(nrfjprog_api, 0) except Exception as ex: print("error: " + str(ex)) _close_and_exit(nrfjprog_api, -2)
def _write_ihx(self, filename): ihx = IntelHex(filename) print "Erasing." min_sector = rounddown_multiple(ihx.minaddr(), SECTORSIZE) max_sector = roundup_multiple(ihx.maxaddr(), SECTORSIZE) for addr in range(min_sector, max_sector, SECTORSIZE): self._erase_sector(addr) print "Writing." min_page = rounddown_multiple(ihx.minaddr(), PAGESIZE) max_page = roundup_multiple(ihx.maxaddr(), PAGESIZE) for addr in range(min_page, max_page, PAGESIZE): self._write(addr, ihx.tobinstr(start=addr, size=PAGESIZE))
class Hex2BinConv(): def __init__(self, out): self.hex = IntelHex() self.out = out def load(self, filename): print print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size/1024, size) def conv(self, label): done = False adr = self.hex.minaddr() max_adr = self.hex.maxaddr() tmp_file = open("tmp.bin", "wb") out_file = open(self.out, "w") print "Converting HEX 2 BIN ...", while(adr <= max_adr): tmp_file.write(chr(self.hex[adr])) adr += 1 tmp_file.close() tmp_file = open("tmp.bin", "r") base64.encode(tmp_file, out_file) out_file.close() print "Done" def batch(self, filename, label): start = time.clock() self.load(filename) self.conv(label) end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
def load_hex(): """ Load hex or binary file. :return: intelhex object """ if args.verbose: print("Loading %s..." % args.source) try: ih = IntelHex() if args.format == "hex": ih.loadhex(args.source) else: ih.loadbin(args.source, args.start_addr) except Exception as e: print(e) exit(1) if args.verbose: print(" Start: 0x%08x" % ih.minaddr()) print(" End : 0x%08x" % ih.maxaddr()) return ih
def append_validation_data(signature, input_file, public_key, offset, output_hex, output_bin, magic_value): ih = IntelHex(input_file) ih.start_addr = None # OBJCOPY incorrectly inserts x86 specific records, remove the start_addr as it is wrong. minimum_offset = ((ih.maxaddr() // 4) + 1) * 4 if offset != 0 and offset < minimum_offset: raise RuntimeError( f'Incorrect offset, must be bigger than {hex(minimum_offset)}') # Parse comma-separated string of uint32s into hex string. Each is encoded in little-endian byte order parsed_magic_value = b''.join( [struct.pack('<I', int(m, 0)) for m in magic_value.split(',')]) validation_data = get_validation_data(signature_bytes=signature, input_hex=ih, public_key=public_key, magic_value=parsed_magic_value) validation_data_hex = IntelHex() # If no offset is given, append metadata right after input hex file (word aligned). if offset == 0: offset = minimum_offset validation_data_hex.frombytes(validation_data, offset) ih.merge(validation_data_hex) ih.write_hex_file(output_hex) if output_bin: ih.tofile(output_bin.name, format='bin')
def addInfo(hex_file, flash_size, VMajor, Vminor): # Load application hex file and convert to byte array # The hex file must have a start address corresponding to BOOTSIZE*512 # Array size is increased to multiples of Flash page size and is padded with 0xFF # Information is added at the beginning of file flashsize = flash_size ih = IntelHex() fileextension = hex_file[-3:] ih.loadfile(hex_file, format=fileextension) append = ih.maxaddr() if (append > flashsize): print("Error: Flashsize input: %#06x, " % (flashsize) + "Minimum size needed: %#06x." % (append)) sys.exit(1) appstart = ih.minaddr() print("\n", "Start Address: %#06x" % (appstart)) flashsize = ((append & 0xFFFFFE00) + 0x200 ) # Round to multiple page number and add 0x200 # Pack integers in a binary string start_address = struct.pack( "<i", appstart) # Start address of the application image app_image_size = struct.pack("<i", flashsize - appstart) # Length of the application image version = (VMajor << 16) + Vminor app_image_version = struct.pack( "<i", version) # Version of the application image start_app = ih.tobinarray(end=flashsize - 1) bin_start_file = os.path.splitext(hex_file)[0] + ".bin" # Save original file fq = open(bin_start_file, 'wb') fq.write(start_app) fq.close() # Add info to file, new flashsize = flashsize + 0x200 app = ih.tobinarray(end=flashsize - 1) bin_file = os.path.splitext(hex_file)[0] + "_w_info.bin" # Save to bin file f = open(bin_file, 'wb') # Write the information section f.write(b"INFO") f.write(start_address) f.write(app_image_size) f.write(app_image_version) # Round to page size (512) and fill with 0xFF counter = 0 while counter < 112: # 128B(page size) - 16B(information section size) counter += 1 f.write(b"\xFF") f.write(b"STX0") f.write(app) f.close()
def convert_ihex_syx(source, byte_width: int = 32) -> bytearray: ihex = IntelHex(source) syx = bytearray() # HEADER syx.extend(reset_bytes()) syx.extend(b'\x00\x51') # id syx.extend(b'\x00' + ihex.gets(ihex.minaddr() + 0x102, 1)) syx.extend(b'\x00' + ihex.gets(ihex.minaddr() + 0x101, 1)) syx.extend(b'\x00' + ihex.gets(ihex.minaddr() + 0x100, 1)) syx.append(0xF7) # PAYLOAD for i in range(ihex.minaddr() + byte_width, ihex.maxaddr(), byte_width): syx.extend(reset_bytes(eol=b'\x72')) syx.extend(block(ihex, i, byte_width)) syx.append(0xF7) syx.extend(reset_bytes(eol=b'\x73')) syx.extend(block(ihex, ihex.minaddr(), byte_width)) syx.append(0xF7) # CHECKSUM syx.extend(reset_bytes(eol=b'\x76')) syx.extend(b'\x00' + b'Firmware') syx.extend(b'\x00\x00\x00\x00\x00\x00\x00\x00') syx.append(0xF7) return syx
def sign_and_append_validation_data(pem_file, input_file, offset, output_file, magic_value, pk_hash_len): ih = IntelHex(input_file) ih.start_addr = None # OBJCOPY incorrectly inserts x86 specific records, remove the start_addr as it is wrong. minimum_offset = ((ih.maxaddr() // 4) + 1) * 4 if offset != 0 and offset < minimum_offset: raise RuntimeError("Incorrect offset, must be bigger than %x" % minimum_offset) # Parse comma-separated string of uint32s into hex string. Each in is encoded # in little-endian byte order parsed_magic_value = b''.join( [struct.pack("<I", int(m, 0)) for m in magic_value.split(",")]) validation_data = get_validation_data(pem_file=pem_file, input_hex=ih, magic_value=parsed_magic_value, pk_hash_len=pk_hash_len) validation_data_hex = IntelHex() # If no offset is given, append metadata right after input hex file (word aligned). if offset == 0: offset = minimum_offset validation_data_hex.frombytes(validation_data, offset) ih.merge(validation_data_hex) ih.write_hex_file(output_file)
def load_hex(firmwareFile, keystr, portName): if keystr is None: key = None else: key = binascii.unhexlify(keystr) print('Reading target file: "%s"' % firmwareFile) if os.path.isfile(firmwareFile): ih = IntelHex(firmwareFile) else: raise Exception('Target file is not exists "%s"' % firmwareFile) hexItems = ih.todict() print('Start address: 0x%08x' % ih.minaddr()) print('End address: 0x%08x' % ih.maxaddr()) print('Total code size: %u bytes' % (len(hexItems) - 1)) client = BootInit(portName) Connect(client) print('Device name: %s' % GetDeviceName(client)) print('CPU name: %s' % GetMcuName(client)) print('MCU ID: %x' % GetMcuId(client)) print('Bootloader version: %d' % GetBootVersionCount(client)) pageCount = GetPageCount(client) print('Flash page count: %u (%u)' % pageCount) print('Total Flash size: %u' % (GetFlashSize(client))) # for i in range(0, pageCount[0]): # pageSize = GetPageSize(client, i) # print ("page %i size = %i" % (i, pageSize)) page = 0 pageSize = GetPageSize(client, page) pageEnd = GetPageAddress(client, page) + pageSize pageData = [] for addr, value in hexItems.items(): if not isinstance(addr, int): continue while addr >= pageEnd: if len(pageData) > 0: BootPrettyWritePage(client, pageData, page, 0, key) page += 1 pageSize = GetPageSize(client, page) pageEnd = GetPageAddress(client, page) + pageSize pageData = [] pageData.append(value) # align data to be written on 8 byte boundary align = (8 - (len(pageData) & 7)) & 7 for i in range(align): pageData.append(0) # write last page BootPrettyWritePage(client, pageData, page, 0, key) print("Success") print("Reseting system") Reset(client)
class Hex2BinConv(): def __init__(self, out): self.hex = IntelHex() self.out = out def load(self, filename): print print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size / 1024, size) def conv(self, label): done = False adr = self.hex.minaddr() max_adr = self.hex.maxaddr() tmp_file = open("tmp.bin", "wb") out_file = open(self.out, "w") print "Converting HEX 2 BIN ...", while (adr <= max_adr): tmp_file.write(chr(self.hex[adr])) adr += 1 tmp_file.close() tmp_file = open("tmp.bin", "r") base64.encode(tmp_file, out_file) out_file.close() print "Done" def batch(self, filename, label): start = time.clock() self.load(filename) self.conv(label) end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
def merge_region_list(region_list, destination, notify, padding=b'\xFF'): """Merge the region_list into a single image Positional Arguments: region_list - list of regions, which should contain filenames destination - file name to write all regions to padding - bytes to fill gapps with """ merged = IntelHex() _, format = splitext(destination) notify.info("Merging Regions") for region in region_list: if region.active and not region.filename: raise ToolException("Active region has no contents: No file found.") if isinstance(region.filename, list): header_basename, _ = splitext(destination) header_filename = header_basename + "_header.hex" _fill_header(region_list, region).tofile(header_filename, format='hex') region = region._replace(filename=header_filename) if region.filename: notify.info(" Filling region %s with %s" % (region.name, region.filename)) part = intelhex_offset(region.filename, offset=region.start) part.start_addr = None part_size = (part.maxaddr() - part.minaddr()) + 1 if part_size > region.size: raise ToolException("Contents of region %s does not fit" % region.name) merged.merge(part) pad_size = region.size - part_size if pad_size > 0 and region != region_list[-1]: notify.info(" Padding region %s with 0x%x bytes" % (region.name, pad_size)) if format is ".hex": """The offset will be in the hex file generated when we're done, so we can skip padding here""" else: merged.puts(merged.maxaddr() + 1, padding * pad_size) if not exists(dirname(destination)): makedirs(dirname(destination)) notify.info("Space used after regions merged: 0x%x" % (merged.maxaddr() - merged.minaddr() + 1)) merged.tofile(destination, format=format.strip("."))
class STM32Firmware(FirmwareBase): def __init__(self, filename, node, vcode, conn): super().__init__(filename, node, vcode, conn) self._ih = IntelHex(filename) def __send_recv(self, data, expected_ret): msg = can.Message(arbitration_id=TWOWAY_CONN_CHANS + self.channel * 2, is_extended_id=False, data=data) self.can.send(msg) t0 = time.time() while True: rframe = self.can.recv() if (rframe.arbitration_id == TWOWAY_CONN_CHANS + self.channel * 2 + 1): #print("response to set_addr", rframe) if rframe.data[0] != expected_ret: raise IOError( f"Expected {expected_ret} but received {rframe.data[0]}" ) break if (time.time() - t0) > 1: raise IOError("Timeout waiting for response") def __sectors_used(self): for sect, bnds in SECTORS.items(): s = set(range(bnds[0], bnds[1])).intersection( set(range(self._ih.minaddr(), self._ih.maxaddr()))) if len(s) > 0: yield sect def update_fw(self): self.start_download() # This will set self.channel # Erase necessary sectors for sect in self.__sectors_used(): self.__send_recv([sect], 0x1) # send code specifying done with erasing self.__send_recv([0xff], 0x2) for ns, (start_addr, stop_addr) in enumerate(self._ih.segments()): print(f"Segment {ns+1} of {len(self._ih.segments())}") self.__send_recv( struct.pack('II', start_addr, stop_addr - start_addr), 0x3) # Send data for n in tqdm.tqdm(list(range(start_addr, stop_addr - 8, 8))): self.__send_recv( bytearray([self._ih[xx] for xx in range(n, n + 8)]), 0x4) # last msg has a different return code self.__send_recv( bytearray([self._ih[xx] for xx in range(n, n + 8)]), 0x5) # Send addr 0, 0 to state we're done. self.__send_recv(struct.pack('II', 0, 0), 0x6)
def burnHex(cmd, hexFileName, trampoline=False, blockSize=16) : hexFile = IntelHex(hexFileName) if (trampoline) : insertTrampoline(hexFile) print hexFile, hexFile.minaddr(), hexFile.maxaddr() end = hexFile.maxaddr()+1 if (end % 64 != 0) : end = end & ~63; end += 64; for i in range(hexFile.minaddr(), end, blockSize) : row = ["%s %04d %d" % (cmd, i, blockSize)] + [hexFile[x] for x in range(i,i+blockSize)] line = " ".join([str(x) for x in row]) + "\n" print 'Writing: ', line port.write(line) doRead()
def test_read_skips_bootloader_and_signature(fw): """ Test if the "read()" method does not return the bootloader content and the signature. This is important to keep the bootloader working after a failed firmware update, so it's not possible to break devices. """ hexfile = IntelHex(fw.get('HEXFILE')) data = fw.get('IMAGE').read() assert len(data) == hexfile.maxaddr() - fw.get('APP_ADDR') - \ len(fw.get('SIGNATURE', b'\x4A\x47\x4F\x4B')) + 1
def loadfromfile(self, fwname="Tamer.hex", eename="Tamer.eep", name="clocktamer", fuses="5e:d8:f4"): # def loadfromfile(self, fwname="Tamer.hex", eename="Tamer.eep", name="clocktamer", fuses="5e:d9:f4"): ih = IntelHex(fwname) ihe = IntelHex(eename) self.h_off = 0xffff self.h_name = name self.h_fw_size = int(math.ceil(float(ih.maxaddr()) / self.blocksize))* self.blocksize self.h_ee_size = int(math.ceil(float(ihe.maxaddr()) / self.blocksize))* self.blocksize self.h_flags = 0 self.h_lock = 0xff self.h_f = int(fuses[0:2], 16) self.h_fh = int(fuses[3:5], 16) self.h_fe = int(fuses[6:8], 16) self.fw_data = array.array('B', [ ih[i] for i in xrange(self.h_fw_size) ]) self.ee_data = array.array('B', [ ihe[i] for i in xrange(self.h_ee_size) ])
def diff(hex_filename_1, hex_filename_2): hex_1 = IntelHex(hex_filename_1) hex_2 = IntelHex(hex_filename_2) max_address = max(hex_1.maxaddr(), hex_2.maxaddr()) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * (WIDTH * 2 + 7))) print('| Addr | {0} | {1} |'.format( hex_filename_1.split('/')[-1].ljust(WIDTH * 2 + 7), hex_filename_2.split('/')[-1].ljust(WIDTH * 2 + 7))) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * (WIDTH * 2 + 7))) print('| | {0} | {0} |'.format( '=0 =3 =4 =7 =8 =B =C =F +0 +3 +4 +7 +8 +B +C +F' )) previous_data_1, previous_data_2 = None, None start_skip = None end_skip = None for address in xrange(0, max_address, WIDTH): data_1 = [] data_2 = [] for offset in xrange(WIDTH): data_1.append(hex_1[address + offset]) data_2.append(hex_2[address + offset]) # Reducing output if data_1 == previous_data_1 and data_2 == previous_data_2: previous_data_1, previous_data_2 = data_1, data_2 if start_skip is None: start_skip = address end_skip = address continue else: if start_skip is not None: _print('...', previous_data_1, previous_data_2) _print(end_skip, previous_data_1, previous_data_2) start_skip = None end_skip = None previous_data_1, previous_data_2 = data_1, data_2 # Printing _print(address, data_1, data_2) print('+-{0}-+-{1}-+-{1}-+'.format('-' * 6, '-' * (WIDTH * 2 + 7)))
def read_from_file(file_path): if file_path.lower().endswith('.hex'): try: from intelhex import IntelHex except ImportError: print( 'To open HEX files install IntelHex library:\npip install IntelHex\npip3 install IntelHex' ) sys.exit(3) ih = IntelHex() ih.loadhex(file_path) logging.info('Was readed 0x{0:X} ({0}) byte(s): 0x{1:X}..{2:X}'.format( ih.maxaddr() - ih.minaddr() + 1, ih.minaddr(), ih.maxaddr())) return bytearray(ih.gets(ih.minaddr(), ih.maxaddr() - ih.minaddr() + 1)) logging.info('Read from binary file "{0}"'.format(file_path)) f = BinFormat() f.read(file_path) logging.info('Was readed 0x{0:X} ({0}) byte(s)'.format(len(f.data))) return f.data
def load_hexfile(self, hexfile: str) -> None: ih = IntelHex() ih.loadhex(hexfile) beg = ih.minaddr() end = ih.maxaddr() + 1 mem = bytes(ih.gets(beg, end - beg)) try: self.emu.mem_write(beg, mem) except: print('Error loading %s at 0x%08x (%d bytes):' % (hexfile, beg, len(mem))) raise
def main(): if len(sys.argv) > 1: currentworkdir = os.path.abspath(os.path.dirname(sys.argv[0])) evenfilepath = str(os.path.abspath(sys.argv[1])) oddfilepath = str(os.path.abspath(sys.argv[2])) newfilepath = os.path.join(currentworkdir , "output.hex") tempfileeven = open(evenfilepath, "r") tempfileodd = open(oddfilepath, "r") evenfile = IntelHex() evenfile.loadfile(tempfileeven,evenfilepath.split(".")[-1]) #evenfile = IntelHex(evenfilepath) oddfile = IntelHex() oddfile.loadfile(tempfileodd,oddfilepath.split(".")[-1]) #oddfile = IntelHex(oddfilepath) evendict = evenfile.todict() odddict = oddfile.todict() newdict = {} newindex = 0 if evenfile.maxaddr() >= oddfile.maxaddr(): maxaddr = evenfile.maxaddr() else: maxaddr = oddfile.maxaddr() #for i in range(len(evendict)): for i in range(0,maxaddr+1): #Evtl immer bei 0 und nicht bei inputfile.minaddr() anfangen try: newdict[newindex] = evendict[i] except KeyError: #Leere Adressen werden manchmal beim Speichern übersprungen #newdicteven[newindex] = 0xFF pass newindex+=1 try: newdict[newindex] = odddict[i] except KeyError: #Leere Adressen werden manchmal beim Speichern übersprungen #newdicteven[newindex] = 0xFF pass newindex+=1 newhex = IntelHex(newdict) output = open(newfilepath, 'w') newhex.write_hex_file(output) output.close()
def install_app(self, app_manifest: AppManifest): hex_file = IntelHex(app_manifest.get_binary()) code_length = hex_file.maxaddr() - hex_file.minaddr() + 1 data_length = app_manifest.data_size code_length -= data_length assert code_length % 64 == 0 # code length must be aligned flags = app_manifest.get_application_flags() # not handled yet params = app_manifest.serialize_parameters() main_address = hex_file.start_addr["EIP"] - hex_file.minaddr() data = struct.pack(">IIIII", code_length, data_length, len(params), flags, main_address) self.apdu_secure_exchange(LedgerSecureIns.CREATE_APP, data) hex_file.puts(hex_file.maxaddr() + 1, params) for segment in hex_file.segments(): self._load_segment(hex_file, segment) self.apdu_secure_exchange(LedgerSecureIns.COMMIT)
def create_payload_section(hex_file, section_name, platform): ih = IntelHex(hex_file) attr = {'bl_attr_base_addr': ih.minaddr()} if platform: attr['bl_attr_platform'] = platform entry = ih.start_addr.get('EIP', ih.start_addr.get('IP', None)) if isinstance(entry, int): attr['bl_attr_entry_point'] = entry exp_len = ih.maxaddr() - ih.minaddr() + 1 if exp_len > MAX_PAYLOAD_SIZE: raise click.ClickException(f"Error while parsing '{hex_file.name}'") pl_bytes = ih.tobinstr() if len(pl_bytes) != exp_len: raise click.ClickException(f"Error while parsing '{hex_file.name}'") return PayloadSection(name=section_name, payload=pl_bytes, attributes=attr)
def dfu_send_image(self): """ Send hex to peer in chunks of 20 bytes. """ if not self.connected: return padding = [0x00] * 12 # Open the hex file to be sent ih = IntelHex(self.hexfile_path) updating_sd = False updating_bl = False updating_app = False bl_start_address = 0x30000 bl_end_address = 0x40000 app_start_address = 0xFFFFFFFF if ih.minaddr() < 0x1004: updating_sd = True sd_end_address_str = ih.gets(0x3008, 4) sd_end_address = int(sd_end_address_str[::-1].encode('hex'), 16) if ih.minaddr() > 0x13FFC: if ih.minaddr() < 0x30000: updating_app = True app_start_address = ih.minaddr() if ih.maxaddr() > 0x30000: while bl_start_address < 0x40000: try: bl_loader_start = ih.gets(bl_start_address, 4) init_sp = int(bl_loader_start[::-1].encode('hex'), 16) if init_sp > 0x20000000: updating_bl = True break else: bl_start_address = bl_start_address + 0x1000 except Exception, e: bl_start_address = bl_start_address + 0x1000 while bl_start_address < bl_end_address: try: bl_loader_start = ih.gets(bl_end_address, 4) bl_end_address = bl_end_address + 0x04 break except Exception, e: bl_end_address = bl_end_address - 0x04
class IHexFile: def __init__(self): self.ihex = IntelHex() self.fileName = "None Loaded" self.fileLoaded = False self.faultList = {} def loadFromFile(self, infilename): self.ihex.fromfile(infilename, format='hex') self.fileName = infilename self.fileLoaded = True self.minAddress = self.ihex.minaddr() self.maxAddress = self.ihex.maxaddr() return "OK" def writeToFile(self, outfilename): if not self.fileLoaded: return "No File Loaded" else: self.ihex.write_hex_file(outfilename) return "OK" def writeHexDump(self, fname): if not self.fileLoaded: return "No File Loaded" else: f = open(fname, 'w') self.ihex.dump(f) f.close() return "Wrote " + fname def faultInjection(self, address, value): if not self.fileLoaded: return "No Hex File Loaded" elif address > self.maxAddress or address < self.minAddress: return "Address out of Range" else: self.ihex[address] = value self.ihex[address + 1] = value self.faultList[address] = value #How to handle Low and High Byte!!! return "OK" def viewFaults(self): if not self.fileLoaded: return "No Hex File Loaded" else: return self.faultList
def write_hex_file(self, fname): print "Loading input file", fname ih = IntelHex(fname) input_crc = atmel_crc(ih.tobinstr(start=0, end=self.memsize, pad=0xff)) print "Size=%s; CRC=%s"%(ih.maxaddr(), hex(input_crc)) print "Erasing...", self.erase() print "done" print "Flashing...", self.program(ih) dev_crc = self.app_crc() print "Checked CRC is", hex(dev_crc) if input_crc == dev_crc: print "CRC matches" print "Resetting" self.reset() else: print "CRC DOES NOT MATCH"
class Firmware(): """A Class that represents the firmware logic.""" def __init__(self, canbus, filename, srcnode=247): """canbus is a canbus.Connection() object and filename is a string that is the path to the Intel Hex file that we are downloading""" self.__canbus = canbus self.ih = IntelHex(filename) self.__srcnode = srcnode cs = crc.crc16() for each in range(self.ih.minaddr(), self.ih.maxaddr()+1): cs.addByte(self.ih[each]) self.__size = self.ih.maxaddr()+1 self.__checksum = cs.getResult() self.lock = threading.Lock() self.__progress = 0.0 self.__blocks = self.__size / 128 + 1 self.__currentblock = 0 self.__blocksize = 128 self.kill = False # Download support functions def __tryChannel(self, ch): """Waits for a half a second to see if there is any traffic on any of the channels""" result = self.__canbus.error() if result != 0x00: self.__canbus.close() self.__canbus.open() endtime = time.time() + 0.5 ch.ClearAll() while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: ch.TestFrame(rframe) now = time.time() if now > endtime: break def __tryFirmwareReq(self, ch, node): """Requests a firmware load, waits for 1/2 a second and determines if the response is correct and if so returns True returns False on timeout""" channel = ch.GetFreeChannel() sframe = {} sframe["id"] = 1792 + self.__srcnode sframe["data"] = [] sframe["data"].append(node) sframe["data"].append(7) sframe["data"].append(1) sframe["data"].append(0xF7) sframe["data"].append(channel) self.__canbus.sendFrame(sframe) endtime = time.time() + 0.5 ch.ClearAll() while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: if rframe["id"] == (1792 + node) and \ rframe["data"][0] == self.__srcnode: break now = time.time() if now > endtime: return False return True def __fillBuffer(self, ch, address, data): sframe = {} sframe["id"] =1760 + ch sframe["data"] = [0x01, address & 0xFF, (address & 0xFF00) >> 8, 128] self.__canbus.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: if rframe["id"] == sframe["id"]+1 and \ rframe["data"] == sframe["data"]: break now = time.time() if now > endtime: return False for n in range(self.__blocksize / 8): print data[address + (8*n):address + (8*n) + 8] self.lock.acquire() self.__progress = float(address + 8*n) / float(self.size) self.lock.release() sframe['data'] = data[address + (8*n):address + (8*n) + 8] print sframe self.__canbus.sendFrame(sframe) #time.sleep(0.3) # TODO Need to deal with the abort from the uC somewhere def __erasePage(self, ch, address): sframe = {} sframe["id"] =1760 + ch sframe["data"] = [0x02, address & 0xFF, (address & 0xFF00) >> 8, 64] self.__canbus.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: if rframe["id"] == sframe["id"]+1 and \ rframe["data"] == sframe["data"]: break now = time.time() if now > endtime: return False def __writePage(self, ch, address): sframe = {} sframe["id"] =1760 + ch sframe["data"] = [0x03, address & 0xFF, (address & 0xFF00) >> 8] self.__canbus.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: if rframe["id"] == sframe["id"]+1 and \ rframe["data"] == sframe["data"]: break now = time.time() if now > endtime: return False def __sendComplete(self, ch): sframe = {} sframe["id"] =1760 + ch sframe["data"] = [0x05, self.__checksum & 0xFF, (self.__checksum & 0xFF00) >> 8, \ self.__size & 0xFF, (self.__size & 0xFF00) >> 8] self.__canbus.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.__canbus.recvFrame() except canbus.DeviceTimeout: pass else: if rframe["id"] == sframe["id"]+1 and \ rframe["data"] == sframe["data"]: break now = time.time() if now > endtime: return False def Download(self, node): ch = Channels() data = [] while True: # Firmware load request loop self.__tryChannel(ch) # send firmware request if self.__tryFirmwareReq(ch, node): break if self.kill: exit(-1) # Here we are in the Firmware load mode of the node # Get our firmware bytes into a normal list channel = ch.GetFreeChannel() for n in range(self.__blocks * self.__blocksize): data.append(self.ih[n]) for block in range(self.__blocks): address = block * 128 print "Buffer Fill at %d" % (address) self.lock.acquire() self.__currentblock = block self.lock.release() self.__fillBuffer(channel, address, data) # TODO Deal with timeout of above # Erase Page print "Erase Page Address =", address self.__erasePage(channel ,address) # Write Page print "Write Page Address =", address self.__writePage(channel ,address) self.__progress = 1.0 print "Download Complete Checksum", hex(self.__checksum), "Size", self.__size self.__sendComplete(channel) def getProgress(self): self.lock.acquire() progress = self.__progress self.lock.release() return progress def getCurrentBlock(self): self.lock.acquire() progress = self.__currentblock self.lock.release() return progress def getBlocks(self): return self.__blocks def getSize(self): return self.__size def getChecksum(self): return self.__checksum def Connect(self): self.__canbus.connect() self.__canbus.init() self.__canbus.open() #time.sleep(3) #can.close() currentblock = property(getCurrentBlock) progress = property(getProgress) blocks = property(getBlocks) size = property(getSize) checksum = property(getChecksum)
#connected, now what? #first, verify that this is an AT90CAN128 # selectMemorySpace(SIGNATURE_SPACE, CRIS, connection, verbose) #first, select the Flash memory space # selectMemorySpace(FLASH_SPACE, CRIS, connection, verbose) # selectMemoryPage(0, CRIS, connection, verbose) #now, read the HEX file, and start writing ih = IntelHex(hexfile) address = ih.minaddr() max = ih.maxaddr() if(max > 0xFFFF): #have to do this in two pages max = 0xFFFF #now, start programming eraseMemory(CRIS, connection, verbose) writeMemory(ih, ih.minaddr(), ih.minaddr(), max, CRIS, connection, verbose) #and now, verify verifyMemory(ih, CRIS, connection, verbose) #finally, set bootloader flag, and start application selectMemorySpace(EEPROM_SPACE, CRIS, connection, verbose) writeMemory([0x00, 0x00], 0x00, 0x0FF8, 0x0FF9, CRIS, connection, verbose) frame = makeframestring(CRIS, CAN_DISPLAY_DATA, [0x00, 0x0F, 0xF7, 0x0F, 0xFF]) connection.network.send(frame) resp_frame = connection.network.receive()
The outputted file will always be exactly 32768 bytes long. """ import binascii, sys, struct from intelhex import IntelHex if len(sys.argv) != 3: print __doc__ % sys.argv[0] sys.exit(1) ih = IntelHex(sys.argv[1]) out = open(sys.argv[2], 'wb') # Sanity checks, very important if ih.maxaddr() < 0x1004 or ih.maxaddr() > 32767: print "Insane hexfile: min=0x%x max=0x%x" % (ih.minaddr(), ih.maxaddr()) sys.exit(2) print "Length: %d / 28672" % (ih.maxaddr() - 4096 + 1) print "Free: %d" % (28672 - (ih.maxaddr() - 4096 + 1)) # Hack to force tobinstr() to write data from addres 0. IntelHex will # only write data from the first location with initialized data, skipping # over any uninitialized data beforehand. This initializes address 0, # forcing IntelHex to do what I want. ih[0]=ih[0] sumdata = (ih.tobinstr())[0x1004:] sumdata += '\xff' * (0x6ffc - len(sumdata)) cksum = binascii.crc32(sumdata) & 0xffffffff print "Checksum: 0x%08x" % cksum
prog = IntelHex(StringIO.StringIO(open(filename, "r").read())) 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)
class Driver(FirmwareBase): def __init__(self, filename, can): FirmwareBase.__init__(self) self.__ih = IntelHex() self.__ih.loadhex(filename) self.can = can cs = crc.crc16() for each in range(self.__ih.minaddr(), self.__ih.maxaddr()+1): cs.addByte(self.__ih[each]) self.__size = self.__ih.maxaddr()+1 self.__checksum = cs.getResult() self.__progress = 0.0 self.__blocksize = 128 self.__blocks = self.__size / self.__blocksize + 1 self.__currentblock = 0 def __fillBuffer(self, ch, address, data): sframe = canbus.Frame(1760 + ch, [0x01, address & 0xFF, (address & 0xFF00) >> 8, 128]) self.can.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.can.recvFrame() except canbus.DeviceTimeout: pass else: if rframe.id == sframe.id+1 and \ rframe.data == sframe.data: break now = time.time() if now > endtime: return False for n in range(self.__blocksize / 8): #print data[address + (8*n):address + (8*n) + 8] sframe.data = data[address + (8*n):address + (8*n) + 8] self.can.sendFrame(sframe) #time.sleep(0.3) # TODO Need to deal with the abort from the uC somewhere return True def __erasePage(self, ch, address): sframe = canbus.Frame(1760 + ch, [0x02, address & 0xFF, (address & 0xFF00) >> 8, 64]) self.can.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.can.recvFrame() except canbus.DeviceTimeout: pass else: if rframe.id == sframe.id+1 and \ rframe.data == sframe.data: break now = time.time() if now > endtime: return False def __writePage(self, ch, address): sframe = canbus.Frame(1760 + ch, [0x03, address & 0xFF, (address & 0xFF00) >> 8]) self.can.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.can.recvFrame() except canbus.DeviceTimeout: pass else: if rframe.id == sframe.id+1 and \ rframe.data == sframe.data: break now = time.time() if now > endtime: return False def __sendComplete(self, ch): sframe = canbus.Frame(1760 + ch, [0x05, self.__checksum & 0xFF, (self.__checksum & 0xFF00) >> 8, \ self.__size & 0xFF, (self.__size & 0xFF00) >> 8]) self.can.sendFrame(sframe) endtime = time.time() + 0.5 while True: # Channel wait loop try: rframe = self.can.recvFrame() except canbus.DeviceTimeout: pass else: if rframe.id == sframe.id+1 and \ rframe.data == sframe.data: break now = time.time() if now > endtime: return False def download(self, node): data=[] channel = FirmwareBase.start_download(self, node) for n in range(self.__blocks * self.__blocksize): data.append(self.__ih[n]) for block in range(self.__blocks): address = block * 128 #print "Buffer Fill at %d" % (address) self.sendStatus("Writing Block %d of %d" % (block, self.__blocks)) self.sendProgress(float(block) / float(self.__blocks)) self.__currentblock = block while(self.__fillBuffer(channel, address, data)==False): if self.kill: self.sendProgress(0.0) self.sendStatus("Download Stopped") return #raise firmware.FirmwareError("Canceled") # Erase Page #print "Erase Page Address =", address self.__erasePage(channel ,address) # Write Page #print "Write Page Address =", address self.__writePage(channel ,address) #self.__progress = 1.0 #print "Download Complete Checksum", hex(self.__checksum), "Size", self.__size self.__sendComplete(channel) self.sendStatus("Download Complete Checksum 0x%X, Size %d" % (self.__checksum, self.__size)) self.sendProgress(1.0) #FirmwareBase.end_download()
class StaxProg(): def __init__(self, port, speed): port = port speed = speed self.hex = IntelHex() self.port = port self.speed = speed def load(self, filename): print "Loading application from hex" self.hex.loadfile(filename, "hex") size = self.hex.maxaddr() - self.hex.minaddr() print " size: %0.2f KiB (%d B)" % (size/1024, size) def read(self): c = self.handle.read() return c def open(self): print "Programer ready connect SkyBean...", sys.stdout.flush() self.handle = serial.Serial(self.port, self.speed, timeout=.2) done = False i = 0 first = True while (not done): i += 1 time.sleep(0.1) self.handle.write("ebl") str = self.handle.read(10) if (str == 'bootloader'): done = True verh = ord(self.handle.read(1)) verl = ord(self.handle.read(1)) ver = (verh << 8) | verl else: if first: # print "Unable to reset automatically. Press reset now." sys.stdout.flush() first = False self.handle.flushInput(); time.sleep(.1) if (i > 1000): raise Exception("Unable to acquire bootloader control") print "done" print "Bootloader version %d" % ver self.handle.setTimeout(2) def erase(self): print "Erasing application...", sys.stdout.flush() self.handle.write('e') c = self.read() if c == 'd': print "done" else: raise Exception("Unexpected character (%c = %d)" % (c, ord(c))) def boot(self): print "Booting application..." self.handle.write('b') def prog(self): done = False adr = self.hex.minaddr() # self.handle.write('s') # adrh = (self.hex.maxaddr() & 0xFF0000) >> 16 # adrm = (self.hex.maxaddr() & 0x00FF00) >> 8 # adrl = (self.hex.maxaddr() & 0x0000FF) >> 0 # # self.handle.write(chr(adrl)) # self.handle.write(chr(adrm)) # self.handle.write(chr(adrh)) print "Programing application..." while(not done): self.handle.write('p') adrh = (adr & 0xFF0000) >> 16 adrm = (adr & 0x00FF00) >> 8 adrl = (adr & 0x0000FF) >> 0 self.handle.write(chr(adrl)) self.handle.write(chr(adrm)) self.handle.write(chr(adrh)) max_size = 64 size = self.hex.maxaddr() - adr if (size > max_size): size = max_size sizel = chr(size & 0x00FF) sizeh = chr((size & 0xFF00) >> 8) self.handle.write(sizel) self.handle.write(sizeh) for i in range(size): low = self.hex[adr + i*2] high = self.hex[adr + i*2 + 1] self.handle.write(chr(low)) self.handle.write(chr(high)) adr += size << 1 if adr >= self.hex.maxaddr(): adr = self.hex.maxaddr() done = True print " adr 0x%04X size %03X (%3.0f%%)" % (adr, size, (float(adr)/float(self.hex.maxaddr()))*100) sys.stdout.flush() c = self.read() if c != 'd': a = self.read() raise Exception("Unexpected character (%c = %d)" % (a, ord(a))) print "Done" def verify(self): print "Verifying application..." #atxmega128a3 app section size # max_adr = 0x20000 self.handle.write('s') adrh = (self.hex.maxaddr() & 0xFF0000) >> 16 adrm = (self.hex.maxaddr() & 0x00FF00) >> 8 adrl = (self.hex.maxaddr() & 0x0000FF) >> 0 self.handle.write(chr(adrl)) self.handle.write(chr(adrm)) self.handle.write(chr(adrh)) max_adr = self.hex.maxaddr() size = 512 done = False adr = 0 read_data = [] while (not done): self.handle.write('r') adrh = (adr & 0xFF0000) >> 16 adrm = (adr & 0x00FF00) >> 8 adrl = (adr & 0x0000FF) >> 0 self.handle.write(chr(adrl)) self.handle.write(chr(adrm)) self.handle.write(chr(adrh)) if (size > max_adr - adr): size = (max_adr - adr) * 2 sizel = chr(size & 0x00FF) sizeh = chr((size & 0xFF00) >> 8) self.handle.write(sizel) self.handle.write(sizeh) for i in range(size): cadr = adr + i data = ord(self.handle.read()) if (cadr >= self.hex.minaddr() and cadr <= self.hex.maxaddr()): read_data.append(data) else: if (data is not 0xFF): print "FF expected on %06X" % cadr adr += size if (adr >= max_adr): adr = max_adr done = True print " adr 0x%04X size %03X (%3.0f%%)" % (adr, size/2, (float(adr)/float(self.hex.maxaddr()))*100) sys.stdout.flush() if (self.hex.tobinarray() == read_data): print "Verification OK" else: print "Verification FAILED" print self.hex.tobinarray() print read_data wrong = 0 for i in range(self.hex.maxaddr() - self.hex.minaddr()): cadr = i + self.hex.minaddr() if (self.hex._buf[cadr] is not read_data[cadr]): wrong += 1 print "Wrong bytes %d/%d (%d %%)" % (wrong, self.hex.maxaddr(), (wrong*100)/self.hex.maxaddr()) def batch(self, filename): start = time.clock() self.load(filename) self.open() self.erase() self.prog() #self.verify() self.boot() end = time.clock() print print "That's all folks! (%.2f seconds)" % (end - start)
info = mb.getDeviceInfo(device) if info is None: print "Unsupported device type '%s'." % device exit(1) # Set up logging if requested if g_logFile is not None: mb.logger = logFunction # Load the HEX file hexfile = IntelHex() hexfile.fromfile(filename, format='hex') if device == "attiny85": # Adjust the code to move the RESET vector hexfile = adjustStartup(info, hexfile) # Set up for the write start = hexfile.minaddr() length = (hexfile.maxaddr() - start) + 1 data = list() for index in range(length): data.append(hexfile[start + index]) print "Writing %d bytes (%04X:%04X) from file '%s'." % (length, start, start + length - 1, filename) print "Target is a '%s' on port '%s'." % (device, port) # Write the data try: mb.connect(device, port) except Exception, ex: print "Error: Could not connect to device, error message is:" print " " + str(ex) exit(1) mb.write(start, length, data) # Now verify print "Verifying data ..."
# - We will look to see if there room for metadata based on start addr # - remember that for current on OAD solution metadata must reside # - in one of two places defined by EXT_FL_OAD_META_BEGIN, INT_FL_OAD_META_BEGIN #first lets assume the first 16B are meta data and see that proves correct if vargs.oadtype == 'onchip' and vargs.imgtype == 'production': hexHdr = 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: hexHdr = OadHdr._make(struct.unpack(OAD_HDR_FMT, mergedHex.tobinstr(startAddr, startAddr+15))) if vargs.oadtype == 'onchip' and vargs.imgtype == 'production': crcBin = mergedHex.tobinstr(INT_FL_OAD_IMG_A_META_BEGIN+4, INT_FL_OAD_IMG_A_END-1) localLen = int(math.ceil((INT_FL_OAD_IMG_A_END - INT_FL_OAD_IMG_A_META_BEGIN) / 4.0)) else: crcBin = mergedHex.tobinstr(startAddr+4, endAddr-1) localLen = int(math.ceil((mergedHex.maxaddr() - mergedHex.minaddr()) / 4.0)) localCrc = crc16(crcBin) #if the resident header checks out, then we will assume metaAddr==startAddr #note that the script will still over-write what is currently there if localCrc == hexHdr.crc and hexHdr.crcShdw == 0xFFFF \ and hexHdr.imgLen <= localLen: metaAddr = startAddr print("Resident metadata detected, using metaAddr = startAddr") print("Note: Resident metadata will still be overwritten") else: # See if the range leaves room if vargs.range is None or vargs.range[0] is None: # First address was not specified, expand backwards if vargs.oadtype == 'onchip' and vargs.imgtype == 'production':
def dumpHex(hexFileName) : hexFile = IntelHex(hexFileName) for i in range(hexFile.minaddr(), hexFile.maxaddr()+1, 16) : row = [str(i)] + [ str(hexFile[j]) for j in range(i, i+16)] print(" ".join(row))