def writeFromFile(self, file, fileformat="bin"): ih = IntelHex() ih.loadfile(file, fileformat) bytesToWrite = ih.tobinarray() return self.write(bytesToWrite)
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 verifyFile(self, file, fileformat="bin"): ih = IntelHex() ih.loadfile(file, fileformat) bytesToVerify = ih.tobinarray() return self.verify(bytesToVerify)
def load_image(self, path): retst = True self.data_buffer = bytearray() if path.lower().endswith(".bin"): with open(path, "rb") as f: self.data_buffer = f.read() f.close() elif path.lower().endswith(".hex"): ihex = IntelHex() try: ihex.loadfile(path, format="hex") except Exception as e: wx.MessageBox("Could not read from file: %s\n\n%s" % (path, str(e)), "ERROR", wx.OK | wx.ICON_ERROR) retst = False else: dhex = ihex.todict() self.data_buffer = bytearray([0xFF] * (max(dhex.keys()) + 1)) for i, val in dhex.items(): self.data_buffer[i] = val elif path.lower().endswith((".s19", ".srec")): srec = SRecFile() try: srec.open(path) except Exception as e: wx.MessageBox("Could not read from file: %s\n\n%s" % (path, str(e)), "ERROR", wx.OK | wx.ICON_ERROR) retst = False else: self.data_buffer = srec.data else: retst = False wx.MessageBox("Not supported file Type !", "ERROR", wx.OK | wx.ICON_ERROR) return retst
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 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 writeFromFile(self, file, fileformat="bin"): try: ih = IntelHex() ih.loadfile(file, fileformat) bytesToWrite = ih.tobinarray() return self.write(bytesToWrite) except BaseException: raise RuntimeError("Failed to write from File") from BaseException
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 write(addr, offset, file): if file.lower().endswith('.bin'): with open(file, "rb") as f: data = f.read() f.close() elif file.lower().endswith('.hex'): ihex = IntelHex() try: ihex.loadfile(file, format='hex') except Exception as e: raise Exception('Could not read from file: %s \n [%s]' % (file, str(e))) else: dhex = ihex.todict() data = bytearray([0xFF]*(max(dhex.keys()) + 1)) for i, val in dhex.items(): data[i] = val else: srec = kboot.SRecFile() try: srec.open(file) except Exception as e: raise Exception('Could not read from file: %s \n [%s]' % (file, str(e))) else: data = srec.data if addr == 0: addr = srec.start_addr if offset < len(data): data = data[offset:] click.echo('\n Writing into MCU memory, please wait !\n') # Read Flash Sector Size of connected MCU flashSectorSize = KBOOT.get_property(kboot.Property.FlashSectorSize)['raw_value'] # Align Erase Start Address and Len to Flash Sector Size saddr = (addr & ~(flashSectorSize - 1)) slen = (len(data) & ~(flashSectorSize - 1)) if (len(data) % flashSectorSize) > 0: slen += flashSectorSize # Erase specified region in MCU Flash memory KBOOT.flash_erase_region(saddr, slen) # Write data into MCU Flash memory KBOOT.write_memory(addr, data) # Disconnect KBoot device KBOOT.disconnect() click.secho(" Done Successfully. \n")
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
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_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
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 hex2bin(hex_file, flash_size): # Load application hex file and convert to bin file ih = IntelHex() fileextension = hex_file[-3:] ih.loadfile(hex_file, format=fileextension) appstart = ih.minaddr() # print("\n", "Start Address: %#06x" % (appstart)) start_app = ih.tobinarray(end=flash_size - 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() return appstart
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 load_image(self, path): retst = True self.data_buffer = bytearray() if path.lower().endswith('.bin'): with open(path, "rb") as f: self.data_buffer = f.read() f.close() elif path.lower().endswith('.hex'): ihex = IntelHex() try: ihex.loadfile(path, format='hex') except Exception as e: wx.MessageBox( "Could not read from file: %s\n\n%s" % (path, str(e)), 'ERROR', wx.OK | wx.ICON_ERROR) retst = False else: dhex = ihex.todict() self.data_buffer = bytearray([0xFF] * (max(dhex.keys()) + 1)) for i, val in dhex.items(): self.data_buffer[i] = val elif path.lower().endswith(('.s19', '.srec')): srec = SRecFile() try: srec.open(path) except Exception as e: wx.MessageBox( "Could not read from file: %s\n\n%s" % (path, str(e)), 'ERROR', wx.OK | wx.ICON_ERROR) retst = False else: self.data_buffer = srec.data else: retst = False wx.MessageBox('Not supported file Type !', 'ERROR', wx.OK | wx.ICON_ERROR) return retst
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
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)
def program_hex_nrf53(self, erase_arg, program_commands): # program_hex() helper for nRF53. # *********************** NOTE ******************************* # self.hex_ can contain code for both the application core and # the network core. # # We can't assume, for example, that # CONFIG_SOC_NRF5340_CPUAPP=y means self.hex_ only contains # data for the app core's flash: the user can put arbitrary # addresses into one of the files in HEX_FILES_TO_MERGE. # # Therefore, on this family, we may need to generate two new # hex files, one for each core, and flash them individually # with the correct '--coprocessor' arguments. # # Kind of hacky, but it works, and nrfjprog is not capable of # flashing to both cores at once. If self.hex_ only affects # one core's flash, then we skip the extra work to save time. # ************************************************************ def add_program_cmd(hex_file, coprocessor): program_commands.append([ 'nrfjprog', '--program', hex_file, erase_arg, '-f', 'NRF53', '--snr', self.dev_id, '--coprocessor', coprocessor ] + self.tool_opt) full_hex = IntelHex() full_hex.loadfile(self.hex_, format='hex') min_addr, max_addr = full_hex.minaddr(), full_hex.maxaddr() # Base address of network coprocessor's flash. From nRF5340 # OPS. We should get this from DTS instead if multiple values # are possible, but this is fine for now. net_base = 0x01000000 if min_addr < net_base <= max_addr: net_hex, app_hex = IntelHex(), IntelHex() for start, stop in full_hex.segments(): segment_hex = net_hex if start >= net_base else app_hex segment_hex.merge(full_hex[start:stop]) hex_path = Path(self.hex_) hex_dir, hex_name = hex_path.parent, hex_path.name net_hex_file = os.fspath(hex_dir / f'GENERATED_CP_NETWORK_{hex_name}') app_hex_file = os.fspath(hex_dir / f'GENERATED_CP_APPLICATION_{hex_name}') self.logger.info( f'{self.hex_} targets both nRF53 coprocessors; ' f'splitting it into: {net_hex_file} and {app_hex_file}') net_hex.write_hex_file(net_hex_file) app_hex.write_hex_file(app_hex_file) add_program_cmd(net_hex_file, 'CP_NETWORK') add_program_cmd(app_hex_file, 'CP_APPLICATION') else: coprocessor = 'CP_NETWORK' if max_addr >= net_base else 'CP_APPLICATION' add_program_cmd(self.hex_, coprocessor)
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(" * Power off and power on SkyBean") self.handle = serial.Serial(self.port, self.speed, timeout=2) done = False while (not done): c = self.handle.read(1) if c == b'b': break i = 0 first = True while (not done): i += 1 time.sleep(0.1) self.handle.write(b'ebl') str = self.handle.read(10) if (str == b'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("Bootloader version %d" % ver) #self.handle.setTimeout(2) def erase(self): print("Erasing application...", end=' ') sys.stdout.flush() self.handle.write(b'e') c = self.read() if c == b'd': print("done") else: raise Exception("Unexpected character (%c = %d)" % (c, ord(c))) def boot(self): print("Booting application...") self.handle.write(b'b') def prog(self): done = False adr = self.hex.minaddr() print("Programing application...") while (not done): self.handle.write(b'p') adrh = (adr & 0xFF0000) >> 16 adrm = (adr & 0x00FF00) >> 8 adrl = (adr & 0x0000FF) >> 0 self.handle.write(bytes([adrl])) self.handle.write(bytes([adrm])) self.handle.write(bytes([adrh])) max_size = 64 size = self.hex.maxaddr() - adr if (size > max_size): size = max_size sizel = bytes([size & 0x00FF]) sizeh = bytes([(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(bytes([low])) self.handle.write(bytes([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) print(".", end=' ') sys.stdout.flush() c = self.read() if c != b'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() if hasattr(sys, "_MEIPASS"): filename = os.path.join(sys._MEIPASS, filename) self.load(filename) self.open() self.erase() self.prog() # self.verify() self.boot() end = time.clock() print() print("Programming done! (%.2f seconds)\n" % (end - start))
from intelhex import IntelHex input_string = input("Enter filename of intel hex file:") lh = IntelHex() lh.loadfile(input_string, format='hex') f = open("h.txt", 'w') f.write("uint8_t array[") f.write(str(len(lh))) f.write("] = { ") pydict = lh.todict() for line in pydict.values(): f.write(str(hex(line))) f.write(", ") f.seek(f.tell() - 2, 0) f.write(" };") f.close()
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.timeout=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)
class NrfJprogBinaryRunner(ZephyrBinaryRunner): '''Runner front-end for nrfjprog.''' def __init__(self, cfg, family, softreset, dev_id, erase=False, tool_opt=[], force=False, recover=False): super().__init__(cfg) self.hex_ = cfg.hex_file self.family = family self.softreset = softreset self.dev_id = dev_id self.erase = bool(erase) self.force = force self.recover = bool(recover) self.tool_opt = [] for opts in [shlex.split(opt) for opt in tool_opt]: self.tool_opt += opts @classmethod def name(cls): return 'nrfjprog' @classmethod def capabilities(cls): return RunnerCaps(commands={'flash'}, dev_id=True, erase=True) @classmethod def dev_id_help(cls) -> str: return '''Device identifier. Use it to select the J-Link Serial Number of the device connected over USB. '*' matches one or more characters/digits''' @classmethod def do_add_parser(cls, parser): parser.add_argument('--nrf-family', choices=['NRF51', 'NRF52', 'NRF53', 'NRF91'], help='''MCU family; still accepted for compatibility only''') parser.add_argument('--softreset', required=False, action='store_true', help='use reset instead of pinreset') parser.add_argument('--snr', required=False, dest='dev_id', action=partial(depr_action, replacement='-i/--dev-id'), help='Deprecated: use -i/--dev-id instead') parser.add_argument('--tool-opt', default=[], action='append', help='''Additional options for nrfjprog, e.g. "--recover"''') parser.add_argument( '--force', required=False, action='store_true', help='Flash even if the result cannot be guaranteed.') parser.add_argument('--recover', required=False, action='store_true', help='''erase all user available non-volatile memory and disable read back protection before flashing (erases flash for both cores on nRF53)''') @classmethod def do_create(cls, cfg, args): return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset, args.dev_id, erase=args.erase, tool_opt=args.tool_opt, force=args.force, recover=args.recover) def ensure_snr(self): if not self.dev_id or "*" in self.dev_id: self.dev_id = self.get_board_snr(self.dev_id or "*") self.dev_id = self.dev_id.lstrip("0") def get_boards(self): snrs = self.check_output(['nrfjprog', '--ids']) snrs = snrs.decode(sys.getdefaultencoding()).strip().splitlines() if not snrs: raise RuntimeError('"nrfjprog --ids" did not find a board; ' 'is the board connected?') return snrs @staticmethod def verify_snr(snr): if snr == '0': raise RuntimeError('"nrfjprog --ids" returned 0; ' 'is a debugger already connected?') def get_board_snr(self, glob): # Use nrfjprog --ids to discover connected boards. # # If there's exactly one board connected, it's safe to assume # the user wants that one. Otherwise, bail unless there are # multiple boards and we are connected to a terminal, in which # case use print() and input() to ask what the user wants. re_glob = escape(glob).replace(r"\*", ".+") snrs = [snr for snr in self.get_boards() if fullmatch(re_glob, snr)] if len(snrs) == 0: raise RuntimeError('There are no boards connected{}.'.format( f" matching '{glob}'" if glob != "*" else "")) elif len(snrs) == 1: board_snr = snrs[0] self.verify_snr(board_snr) print("Using board {}".format(board_snr)) return board_snr elif not sys.stdin.isatty(): raise RuntimeError( f'refusing to guess which of {len(snrs)} ' 'connected boards to use. (Interactive prompts ' 'disabled since standard input is not a terminal.) ' 'Please specify a serial number on the command line.') snrs = sorted(snrs) print('There are multiple boards connected{}.'.format( f" matching '{glob}'" if glob != "*" else "")) for i, snr in enumerate(snrs, 1): print('{}. {}'.format(i, snr)) p = 'Please select one with desired serial number (1-{}): '.format( len(snrs)) while True: try: value = input(p) except EOFError: sys.exit(0) try: value = int(value) except ValueError: continue if 1 <= value <= len(snrs): break return snrs[value - 1] def ensure_family(self): # Ensure self.family is set. if self.family is not None: return if self.build_conf.getboolean('CONFIG_SOC_SERIES_NRF51X'): self.family = 'NRF51' elif self.build_conf.getboolean('CONFIG_SOC_SERIES_NRF52X'): self.family = 'NRF52' elif self.build_conf.getboolean('CONFIG_SOC_SERIES_NRF53X'): self.family = 'NRF53' elif self.build_conf.getboolean('CONFIG_SOC_SERIES_NRF91X'): self.family = 'NRF91' else: raise RuntimeError(f'unknown nRF; update {__file__}') def hex_refers_region(self, region_start, region_end): for segment_start, _ in self.hex_contents.segments(): if region_start <= segment_start <= region_end: return True return False def check_force_uicr(self): # On SoCs without --sectoranduicrerase, we want to fail by # default if the application contains UICR data and we're not sure # that the flash will succeed. # A map from SoCs which need this check to their UICR address # ranges. If self.family isn't in here, do nothing. uicr_ranges = { 'NRF53': ((0x00FF8000, 0x00FF8800), (0x01FF8000, 0x01FF8800)), 'NRF91': ((0x00FF8000, 0x00FF8800), ), } if self.uicr_data_ok or self.family not in uicr_ranges: return for region_start, region_end in uicr_ranges[self.family]: if self.hex_refers_region(region_start, region_end): # Hex file has UICR contents, and that's not OK. raise RuntimeError( 'The hex file contains data placed in the UICR, which ' 'needs a full erase before reprogramming. Run west ' 'flash again with --force, --erase, or --recover.') @property def uicr_data_ok(self): # True if it's OK to try to flash even with UICR data # in the image; False otherwise. return self.force or self.erase or self.recover def recover_target(self): if self.family == 'NRF53': self.logger.info( 'Recovering and erasing flash memory for both the network ' 'and application cores.') else: self.logger.info('Recovering and erasing all flash memory.') if self.family == 'NRF53': self.check_call([ 'nrfjprog', '--recover', '-f', self.family, '--coprocessor', 'CP_NETWORK', '--snr', self.dev_id ]) self.check_call( ['nrfjprog', '--recover', '-f', self.family, '--snr', self.dev_id]) def program_hex(self): # Get the nrfjprog command use to actually program self.hex_. self.logger.info('Flashing file: {}'.format(self.hex_)) # What type of erase argument should we pass to nrfjprog? if self.erase: erase_arg = '--chiperase' else: if self.family == 'NRF52': erase_arg = '--sectoranduicrerase' else: erase_arg = '--sectorerase' xip_ranges = { 'NRF52': (0x12000000, 0x19FFFFFF), 'NRF53': (0x10000000, 0x1FFFFFFF), } qspi_erase_opt = [] if self.family in xip_ranges: xip_start, xip_end = xip_ranges[self.family] if self.hex_refers_region(xip_start, xip_end): qspi_erase_opt = ['--qspisectorerase'] # What nrfjprog commands do we need to flash this target? program_commands = [] if self.family == 'NRF53': # nRF53 requires special treatment due to the extra coprocessor. self.program_hex_nrf53(erase_arg, qspi_erase_opt, program_commands) else: # It's important for tool_opt to come last, so it can override # any options that we set here. program_commands.append( ['nrfjprog', '--program', self.hex_, erase_arg] + qspi_erase_opt + ['--verify', '-f', self.family, '--snr', self.dev_id] + self.tool_opt) try: for command in program_commands: self.check_call(command) except subprocess.CalledProcessError as cpe: if cpe.returncode == UnavailableOperationBecauseProtectionError: if self.family == 'NRF53': family_help = ( ' Note: your target is an nRF53; all flash memory ' 'for both the network and application cores will be ' 'erased prior to reflashing.') else: family_help = ( ' Note: this will recover and erase all flash memory ' 'prior to reflashing.') self.logger.error( 'Flashing failed because the target ' 'must be recovered.\n' ' To fix, run "west flash --recover" instead.\n' + family_help) raise def program_hex_nrf53(self, erase_arg, qspi_erase_opt, program_commands): # program_hex() helper for nRF53. # *********************** NOTE ******************************* # self.hex_ can contain code for both the application core and # the network core. # # We can't assume, for example, that # CONFIG_SOC_NRF5340_CPUAPP=y means self.hex_ only contains # data for the app core's flash: the user can put arbitrary # addresses into one of the files in HEX_FILES_TO_MERGE. # # Therefore, on this family, we may need to generate two new # hex files, one for each core, and flash them individually # with the correct '--coprocessor' arguments. # # Kind of hacky, but it works, and nrfjprog is not capable of # flashing to both cores at once. If self.hex_ only affects # one core's flash, then we skip the extra work to save time. # ************************************************************ def add_program_cmd(hex_file, coprocessor, qspi_erase_opt): program_commands.append( ['nrfjprog', '--program', hex_file, erase_arg] + qspi_erase_opt + [ '--verify', '-f', 'NRF53', '--snr', self.dev_id, '--coprocessor', coprocessor ] + self.tool_opt) # Address range of the network coprocessor's flash. From nRF5340 OPS. # We should get this from DTS instead if multiple values are possible, # but this is fine for now. net_flash_start = 0x01000000 net_flash_end = 0x0103FFFF # If there is nothing in the hex file for the network core, # only the application core is programmed. if not self.hex_refers_region(net_flash_start, net_flash_end): add_program_cmd(self.hex_, 'CP_APPLICATION', qspi_erase_opt) # If there is some content that addresses a region beyond the network # core flash range, two hex files are generated and the two cores # are programmed one by one. elif self.hex_contents.minaddr() < net_flash_start or \ self.hex_contents.maxaddr() > net_flash_end: net_hex, app_hex = IntelHex(), IntelHex() for start, end in self.hex_contents.segments(): if net_flash_start <= start <= net_flash_end: net_hex.merge(self.hex_contents[start:end]) else: app_hex.merge(self.hex_contents[start:end]) hex_path = Path(self.hex_) hex_dir, hex_name = hex_path.parent, hex_path.name net_hex_file = os.fspath(hex_dir / f'GENERATED_CP_NETWORK_{hex_name}') app_hex_file = os.fspath(hex_dir / f'GENERATED_CP_APPLICATION_{hex_name}') self.logger.info( f'{self.hex_} targets both nRF53 coprocessors; ' f'splitting it into: {net_hex_file} and {app_hex_file}') net_hex.write_hex_file(net_hex_file) app_hex.write_hex_file(app_hex_file) add_program_cmd(net_hex_file, 'CP_NETWORK', []) add_program_cmd(app_hex_file, 'CP_APPLICATION', qspi_erase_opt) # Otherwise, only the network core is programmed. else: add_program_cmd(self.hex_, 'CP_NETWORK', []) def reset_target(self): if self.family == 'NRF52' and not self.softreset: self.check_call([ 'nrfjprog', '--pinresetenable', '-f', self.family, '--snr', self.dev_id ]) # Enable pin reset if self.softreset: self.check_call([ 'nrfjprog', '--reset', '-f', self.family, '--snr', self.dev_id ]) else: self.check_call([ 'nrfjprog', '--pinreset', '-f', self.family, '--snr', self.dev_id ]) def do_run(self, command, **kwargs): self.require('nrfjprog') self.ensure_output('hex') if IntelHex is None: raise RuntimeError('one or more Python dependencies were missing; ' 'see the getting started guide for details on ' 'how to fix') self.hex_contents = IntelHex() try: self.hex_contents.loadfile(self.hex_, format='hex') except FileNotFoundError: pass self.ensure_snr() self.ensure_family() self.check_force_uicr() if self.recover: self.recover_target() self.program_hex() self.reset_target() self.logger.info(f'Board with serial number {self.dev_id} ' 'flashed successfully.')
#!/usr/bin/python import sys from intelhex import IntelHex print('Number of arguments:', len(sys.argv), 'arguments.') print('Argument List:', str(sys.argv)) if (len(sys.argv) > 2): print( 'Too many arguments, use this instead: python dump_hex.py <hex_file>.hex' ) exit(-1) hex_file = IntelHex() hex_file.loadfile(sys.argv[1], format='hex') file = open((str(sys.argv[1]) + ".txt"), 'w') print('Dumping hex file contents into: ' + (str(sys.argv[1]) + ".txt")) hex_file.dump(file) file.close()
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)
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
def import_file(filename): ih = IntelHex() ih.loadfile(filename, format='bin') return ih