Example #1
0
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') 
Example #2
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.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)
Example #3
0
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())
Example #4
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()

        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)
Example #5
0
    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))
Example #6
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)
Example #7
0
    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
Example #8
0
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')
Example #9
0
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")
Example #10
0
class FormatIntelHex(FormatReader, FormatWriter):
    def __init__(self):
        self.hexinstance = IntelHex()


    def load_file(self, filename=None):
        if filename is None:
            raise FormatError("Filename not specified.")

        file_extension = os.path.splitext(filename)[1][1 : ].lower()

        try:
            if file_extension == "bin":
                self.hexinstance.loadbin(filename)
            else:
                self.hexinstance.loadhex(filename)
        except:
            raise FormatError("Could not open %s file \"%s\"." %
                              (file_extension.upper(), filename))


    def save_file(self, filename):
        if filename is None:
            raise FormatError("Filename not specified.")

        file_extension = os.path.splitext(filename)[1][1 : ].lower()

        try:
            if file_extension == "bin":
                self.hexinstance.tofile(filename, format="bin")
            else:
                self.hexinstance.tofile(filename, format="hex")
        except:
            raise FormatError("Could not save %s file \"%s\"." %
                              (file_extension.upper(), filename))


    def add_section(self, start, data):
        self.hexinstance[start : start + len(data)] = data


    def get_sections(self):
        sections = dict()

        if self.hexinstance.minaddr() is not None:
            sections[None] = FormatIntelHex_Section(self.hexinstance)

        return sections


    @staticmethod
    def get_name():
        return "Intel HEX File Parser"


    @staticmethod
    def get_extensions():
        return ["hex", "eep"]
Example #11
0
    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)
Example #12
0
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()
Example #13
0
    def build_target_firmware(self, parent_test):
        """
        Build test firmware for the board

        Login credentials must have been set with set_build_login.
        """
        prebuilt = self._target_dir is not None
        build_login = (self._username is not None and
                       self._password is not None)
        assert prebuilt or build_login
        if prebuilt:
            destdir = self._target_dir
        else:
            destdir = 'tmp'
        build_name = board_id_to_build_target[self.get_board_id()]
        name_base = os.path.normpath(destdir + os.sep + build_name)
        self._target_hex_path = name_base + '.hex'
        self._target_bin_path = name_base + '.bin'
        # Build target test image if a prebuild location is not specified
        if not prebuilt:
            test_info = parent_test.create_subtest('build_target_test_firmware')
            if not os.path.isdir(destdir):
                os.mkdir(destdir)
            # Remove previous build files
            if os.path.isfile(self._target_hex_path):
                os.remove(self._target_hex_path)
            if os.path.isfile(self._target_bin_path):
                os.remove(self._target_bin_path)
            test_info.info('Starting remote build')
            start = time.time()
            built_file = mbedapi.build_repo(self._username, self._password,
                                            TEST_REPO, build_name, destdir)
            stop = time.time()
            test_info.info("Build took %s seconds" % (stop - start))
            extension = os.path.splitext(built_file)[1].lower()
            assert extension == '.hex' or extension == '.bin'
            if extension == '.hex':
                intel_hex = IntelHex(built_file)
                # Only supporting devices with the starting
                # address at 0 currently
                assert intel_hex.minaddr() == 0
                intel_hex.tobinfile(self._target_bin_path)
                os.rename(built_file, self._target_hex_path)
            if extension == '.bin':
                intel_hex = IntelHex()
                intel_hex.loadbin(built_file, offset=0)
                intel_hex.tofile(self._target_hex_path, 'hex')
                os.rename(built_file, self._target_bin_path)
        # Assert that required files are present
        assert os.path.isfile(self._target_hex_path)
        assert os.path.isfile(self._target_bin_path)
        self._target_firmware_present = True
Example #14
0
def build_target_bundle(directory, username, password, parent_test=None):
    """Build target firmware package"""
    if parent_test is None:
        parent_test = TestInfoStub()
    target_names = info.TARGET_NAME_TO_BOARD_ID.keys()
    for build_name in target_names:
        name_base = os.path.normpath(directory + os.sep + build_name)
        target_hex_path = name_base + '.hex'
        target_bin_path = name_base + '.bin'

        # Build target test image
        test_info = parent_test.create_subtest('Building target %s' %
                                               build_name)
        if not os.path.isdir(directory):
            os.mkdir(directory)
        # Remove previous build files
        if os.path.isfile(target_hex_path):
            os.remove(target_hex_path)
        if os.path.isfile(target_bin_path):
            os.remove(target_bin_path)
        test_info.info('Starting remote build')
        start = time.time()
        built_file = mbedapi.build_repo(username, password,
                                        TEST_REPO, build_name,
                                        directory)
        stop = time.time()
        test_info.info("Build took %s seconds" % (stop - start))
        extension = os.path.splitext(built_file)[1].lower()
        assert extension == '.hex' or extension == '.bin'
        if extension == '.hex':
            intel_hex = IntelHex(built_file)
            # Only supporting devices with the starting
            # address at 0 currently
            assert intel_hex.minaddr() == 0
            intel_hex.tobinfile(target_bin_path)
            os.rename(built_file, target_hex_path)
        if extension == '.bin':
            intel_hex = IntelHex()
            intel_hex.loadbin(built_file, offset=0)
            intel_hex.tofile(target_hex_path, 'hex')
            os.rename(built_file, target_bin_path)

        # Assert that required files are present
        assert os.path.isfile(target_hex_path)
        assert os.path.isfile(target_bin_path)
Example #15
0
    def add_firmware(self, filename_hex, fw_info):
        ihex = IntelHex(filename_hex)
        # We remove configuration data from TSB firmware (last 16 bytes)
        # beginnin with TSB ...
        fw_data = ihex.tobinstr()
        fw_info.tsb_fwconf = ""

        fw_parts = fw_data.rsplit("TSB", 1)
        if len(fw_parts) == 2:
            fw_data = fw_parts[0]
            fw_info.tsb_fwconf = fw_parts[1]
        
        fw_info.tsb_start = ihex.minaddr()
        fw_md5 = hashlib.md5(fw_data).hexdigest()
        
        if not self.tsbdb.has_key(fw_md5):
            self.tsbdb[fw_md5] = [ fw_data ]
            
        self.add_firmware_info(fw_md5, fw_info)
Example #16
0
    def load(self, path):
        """Load an image from a given file"""
        ext = os.path.splitext(path)[1][1:].lower()
        try:
            if ext == INTEL_HEX_EXT:
                ih = IntelHex(path)
                self.payload = ih.tobinarray()
                self.base_addr = ih.minaddr()
            else:
                with open(path, 'rb') as f:
                    self.payload = f.read()
        except FileNotFoundError:
            raise click.UsageError("Input file not found")

        # Add the image header if needed.
        if self.pad_header and self.header_size > 0:
            if self.base_addr:
                # Adjust base_addr for new header
                self.base_addr -= self.header_size
            self.payload = bytes([self.erased_val] * self.header_size) + \
                self.payload

        self.check_header()
Example #17
0
    def load_ihex(self, filename):
        """
            Load from intel hex format
        """
        self.logger.info("Loading from hexfile '{}'".format(filename))
        from intelhex import IntelHex

        ih = IntelHex()
        ih.loadhex(filename)
        data = ih.tobinarray()
        start_address = ih.minaddr()
        self.logger.info("Loaded {0:d} bytes from ihex starting at address 0x{1:04X}".format(len(data), start_address))

        # Size check
        if len(data) > self.device.flash_size:
            raise Exception("ihex too large for flash")

        # Offset to actual flash start
        if start_address < self.device.flash_start:
            self.logger.info("Adjusting flash offset to address 0x{:04X}".format(self.device.flash_start))
            start_address += self.device.flash_start

        return data, start_address
Example #18
0
def _build_record(slot_number, image_path, record_type, args):
    """Builds the appropriate record for the slot given the specified record type"""
    hex_data = IntelHex(image_path)
    hex_data.padding = 0xFF

    offset = hex_data.minaddr()
    bin_data = bytearray(hex_data.tobinarray(offset, hex_data.maxaddr()))

    if slot_number == 0:  # If slot is controller
        if record_type == 2:  # kReflashControllerTile
            return ReflashControllerRecord(bin_data, offset)
        elif record_type == 3:  # kExecuteRPCWithoutCheck
            pass  # Not implemented yet
        elif record_type == 4:  # kExecuteRPCWithCheck
            pass  # Not implemented yet
        elif record_type == 5:  # kResetController
            pass  # Not implemented yet
        elif record_type == 6:  # kEnhancedReflashControllerTile
            if args['reboot'] == "True":
                skip_reboot_flag = 0
            else:
                skip_reboot_flag = 1
            return EnhancedReflashControllerRecord(bin_data,
                                                   offset,
                                                   flags=skip_reboot_flag)
        else:
            raise BuildError("Invalid record type for this slot.",
                             slot=slot_number,
                             record=record_type)
    else:  # If slot is a tile
        if record_type == 1:  # kReflashExternalTile
            return ReflashTileRecord(slot_number, bin_data, offset)
        else:
            raise BuildError("Invalid record type for this slot.",
                             slot=slot_number,
                             record=record_type)
Example #19
0
	show_help()
	sys.exit(1)
if not os.path.exists(sys.argv[1]):
	sys.exit("Unable open build %s" % sys.argv[1])
if not os.path.exists(sys.argv[2]):
	sys.exit("Unable open build %s" % sys.argv[2])
build_filename = sys.argv[1]
prog_filename = sys.argv[2]

# open the build and prog
# note open build via StringIO so we can add to it
build = IntelHex(StringIO.StringIO(open(build_filename, "r").read()))
prog = IntelHex(prog_filename)

# merge program into build
prog_header_addr = prog.minaddr()
prog.start_addr = build.start_addr # we need this to make the merge work smoothly
build.merge(prog)

# add pointer to program header to the bootstrap
header_tbl_addr = 0x08000204
header_tbl_len = 2 #@todo get this from 0x0800200 as uint32_t
header_tbl_format = "<LL"
header_tbl = list(struct.unpack(header_tbl_format, build.gets(header_tbl_addr, header_tbl_len * 4)))
k = 0
while header_tbl[k] != 0xffffffff:
	if k > header_tbl_len:
		sys.exit("bootstrap program table full [you have too many programs]!");
	k += 1
header_tbl[k] = prog_header_addr
build.puts(header_tbl_addr, struct.pack(header_tbl_format, *header_tbl))
Example #20
0
                    + f.name)
                sys.exit(1)
        except:
            print("Fatal Error: -- FAILED parsing input hex file(s)")
            sys.exit(1)

    #print information about the input hex files
    print_args_info(inputFileNames, vargs.out, vargs.outbin, vargs.oadtype,
                    vargs.imgtype, mergedHex)

    #Now that we have a merged hex image, lets do a bunch of arg checking
    #since mergedHex is an merge of all input hexes, it can be treated as an argument to the script
    argument_sanity_check(vargs, mergedHex)

    # Cut off / fill with --fill.
    startAddr = mergedHex.minaddr()
    endAddr = mergedHex.addresses()[-1] + 1  # Inclusive address

    if startAddr % OAD_BLOCK_SIZE:
        print(
            "Fatal Error: -- Start address 0x%X is not divisible by 16. Exiting"
        )
        sys.exit(1)

    # DevMon rounds up to nearest sector. Why not, if they want to waste time and space.
    if vargs.round is not None:
        endAddr = ((endAddr + INT_FL_PG_SIZE) & ~(INT_FL_PG_SIZE - 1))
        print('endAddr round', hex(endAddr))

    if vargs.range is not None:
        if vargs.range[0] is not None: startAddr = vargs.range[0]
Example #21
0
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()
        self.__progress = 0.0
        self.blocksize = 128
        self.__currentblock = 0

    def setArg(self, argname, value):
        if argname == "blocksize":
            self.blocksize = value

    # .blocksize property
    def setBlocksize(self, value):
        self.__blocksize = value
        self.__blocks = self.__size // self.__blocksize
        if self.__size % self.__blocksize != 0:
            self.__blocks = self.__blocks + 1
        #print("Block count = {}".format(self.__blocks))

    def getBlocksize(self):
        return self.__blocksize

    blocksize = property(getBlocksize, setBlocksize)

    def __waitBufferResponse(self, channel, offset):
        endtime = time.time() + 0.5
        while True:
            try:
                rframe = self.can.recv(0.5)
            except connection.Timeout:
                pass
            else:
                if rframe.arbitration_id == 0x7E0 + channel + 1:
                    if (rframe.data[0] + (rframe.data[1] << 8)) == offset:
                        break
                    else:
                        raise connection.BadOffset
            now = time.time()
            if now > endtime:
                raise connection.Timeout
        return True

    def __fillBuffer(self, ch, address, data):
        length = len(data)
        print("Address 0x{:08X} {}".format(address, address))
        sframe = can.Message(arbitration_id=0x7E0 + ch,
                             is_extended_id=False,
                             data=[
                                 0x01, address & 0xFF, (address & 0xFF00) >> 8,
                                 (address & 0xFF0000) >> 16,
                                 (address & 0xFF000000) >> 24, 0, 1
                             ])
        self.can.send(sframe)
        endtime = time.time() + 0.5
        while True:  # Channel wait loop
            try:
                rframe = self.can.recv(1)
            except connection.Timeout:
                pass
            else:
                if rframe.arbitration_id == sframe.arbitration_id+1 and \
                    rframe.data == sframe.data:
                    break
            now = time.time()
            if now > endtime:
                raise connection.Timeout
        for n in range(length // 8):
            # print("[{:02}: ".format(n), end='')
            # for each in data[(8*n):(8*n) + 8]:
            #     print("{:02X} ".format(each), end='')
            # print("]")
            sframe.data = data[(8 * n):(8 * n) + 8]
            sframe.dlc = 8
            self.can.send(sframe)
            self.__waitBufferResponse(ch, (n + 1) * 8)
            #time.sleep(0.3)
            # TODO Need to deal with the abort from the uC somewhere
        return True

    def __erasePage(self, ch, address):
        sframe = can.Message(arbitration_id=0x7E0 + ch,
                             is_extended_id=False,
                             data=[
                                 0x02, address & 0xFF, (address & 0xFF00) >> 8,
                                 (address & 0xFF0000) >> 16,
                                 (address & 0xFF000000) >> 24
                             ])
        self.can.send(sframe)
        endtime = time.time() + 0.5
        while True:  # Channel wait loop
            try:
                rframe = self.can.recv(0.1)
            except connection.Timeout:
                pass
            else:
                if rframe.arbitration_id == sframe.arbitration_id+1 and \
                    rframe.data == sframe.data:
                    break
            now = time.time()
            if now > endtime:
                raise connection.Timeout
        return True

    def __writePage(self, ch, address):
        sframe = can.Message(arbitration_id=0x7E0 + ch,
                             is_extended_id=False,
                             data=[
                                 0x03, address & 0xFF, (address & 0xFF00) >> 8,
                                 (address & 0xFF0000) >> 16,
                                 (address & 0xFF000000) >> 24
                             ])
        self.can.send(sframe)
        endtime = time.time() + 0.5
        while True:  # Channel wait loop
            try:
                rframe = self.can.recv(1)
            except connection.Timeout:
                pass
            else:
                if rframe.arbitration_id == sframe.arbitration_id+1 and \
                    rframe.data == sframe.data:
                    break
            now = time.time()
            if now > endtime:
                raise connection.Timeout

    def __sendComplete(self, ch):
        sframe = can.Message(arbitration_id = 0x7E0 + ch, is_extended_id =False,
                             data=[0x05, self.__checksum & 0xFF, (self.__checksum & 0xFF00) >> 8, \
                                   self.__size & 0xFF, (self.__size & 0xFF00) >> 8, \
                                   (self.__size & 0xFF0000) >> 16, (self.__size & 0xFF000000) >> 24])
        self.can.send(sframe)
        endtime = time.time() + 0.5
        while True:  # Channel wait loop
            try:
                rframe = self.can.recv(1)
            except connection.Timeout:
                pass
            else:
                if rframe.arbitration_id == sframe.arbitration_id+1 and \
                    rframe.data == sframe.data:
                    break
            now = time.time()
            if now > endtime:
                raise connection.Timeout

    # TODO Need to make sure this fails properly when something goes wrong and
    #      it might be nice to have some retires on blocks that fail.  Might
    #      make this more robust.
    # TODO We are not sending partial frames.  This probably isn't a big deal
    #      but it's not exactly like the specification.  Maybe change the spec,
    #      that might simplify the bootloader
    def download(self):
        data = []
        FirmwareBase.start_download(self)
        for n in range(self.__blocks * self.__blocksize):
            data.append(self.__ih[n])

        for block in range(self.__blocks):
            try:
                address = block * self.__blocksize
                self.sendStatus("Writing Block %d of %d" %
                                (block + 1, self.__blocks))
                self.sendProgress(float(block) / float(self.__blocks))
                self.__currentblock = block
                while (self.__fillBuffer(
                        self.channel, address,
                        data[address:address + self.blocksize]) == False):
                    if self.kill:
                        self.sendProgress(0.0)
                        self.sendStatus("Download Stopped")
                        return
                        #raise firmware.FirmwareError("Canceled")

                # Erase Page
                #print( "Erase Page Address = {}".format(address))
                self.__erasePage(self.channel, address)

                # Write Page
                #print("Write Page Address = {}".format(address))
                self.__writePage(self.channel, address)
            except connection.Timeout:
                self.sendProgress(0.0)
                self.sendStatus("FAIL: Timeout Writing Data")
                return
            except connection.BadOffset:
                self.sendProgress(0.0)
                self.sendStatus("FAIL: Bad Block Offset Received")
                return

        #self.__progress = 1.0
        #print("Download Complete Checksum".format(hex(self.__checksum), "Size", self.__size))
        try:
            self.__sendComplete(self.channel)
            self.sendStatus("Download Complete Checksum 0x%X, Size %d" %
                            (self.__checksum, self.__size))
            self.sendProgress(1.0)
        except connection.Timeout:
            self.sendProgress(0.0)
            self.sendStatus("FAIL: Timeout While Finalizing Download")
Example #22
0
    def create_encrypted_image(self, hex_file, aes_key_file, aes_header,
                               host_key_id, dev_key_id, out_file_encrypt,
                               padding_value=0):
        """
        Creates encrypted image for encrypted programming
        Format:
        Row 1 - keys ID (byte 1 - host key ID, byte 2 - dev key ID)
        Row 2 - AES header
        Other - encrypted image data
        """
        # Write keys ID and AES header
        out_file_path = os.path.abspath(out_file_encrypt)
        with open(out_file_path, 'w') as f:
            f.write(str(host_key_id).zfill(2))
            f.write(str(dev_key_id).zfill(2) + '\n')
            f.write(aes_header + '\n')

        ih = IntelHex(hex_file)
        hex_data_dict = ih.todict()
        if 'start_addr' in hex_data_dict:
            del hex_data_dict['start_addr']
        logger.debug(f'hex_data_dict={hex_data_dict}')

        # Add padding
        ih.padding = padding_value
        data_to_program = dict()
        file_len = ih.maxaddr() - ih.minaddr()
        if file_len % FLASH_ROW_SIZE != 0:
            address_offset = (file_len // FLASH_ROW_SIZE + 1) * FLASH_ROW_SIZE
            max_address = ih.minaddr() + address_offset
        else:
            max_address = ih.maxaddr()
        for i in range(ih.minaddr(), max_address):
            data_to_program[i] = ih[i]

        sorted_address_keys = sorted(data_to_program)
        for key in sorted_address_keys:
            logger.debug('0x%08X: %02X' % (key, data_to_program[key]))

        logger.debug('Data bytes length: %s' % len(sorted_address_keys))
        if len(sorted_address_keys) % FLASH_ROW_SIZE != 0:
            logger.error('Data bytes length is not multiple '
                         'by FLASH_ROW_SIZE (%s)' % FLASH_ROW_SIZE)
            return

        sorted_bytes_values = []
        for key in sorted_address_keys:
            sorted_bytes_values.append(data_to_program[key])

        logger.debug('-' * 30 + ' Virgin rows ' + '-' * 30)
        address_row_bytes_dict = {}
        rows_of_bytes = list(AesHeaderStrategy.chunks_list(sorted_bytes_values,
                                                           FLASH_ROW_SIZE))
        flash_addresses = list(AesHeaderStrategy.chunks_list(
            sorted_address_keys, FLASH_ROW_SIZE))
        for i in range(len(flash_addresses)):
            flash_addresses[i] = flash_addresses[i][0]
            address_row_bytes_dict[flash_addresses[i]] = rows_of_bytes[i]
            out_data = '0x%08X %s' % (flash_addresses[i], ''.join(
                map(AesHeaderStrategy.hex_str_wo_header, rows_of_bytes[i])))
            logger.debug(out_data)

        logger.debug('-' * 30 + ' Encrypted rows ' + '-' * 30)
        addr_rows_bin = {}
        aes_key, aes_iv = read_key_from_file(aes_key_file)
        aes = AESCipherCBC(aes_key, aes_iv)
        with open(out_file_path, 'a') as encrypted_rows_out:
            for i in range(len(flash_addresses)):
                rows_in_binary_format = bytes(rows_of_bytes[i])
                encrypted_row = aes.encrypt(rows_in_binary_format)
                encrypted_row = bytes(list(encrypted_row))

                addr_rows_bin[flash_addresses[i]] = encrypted_row
                out_data = '%08X%s' % (flash_addresses[i],
                                       addr_rows_bin[flash_addresses[i]].hex())
                logger.debug(out_data)
                encrypted_rows_out.write(out_data + '\n')
        logger.info(f'Created encrypted image \'{out_file_path}\'')

import hashlib
import sys
import argparse
from intelhex import IntelHex


def parse_args():
    parser = argparse.ArgumentParser(
        description="Hash data from file.",
        formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument("--infile", "-i", "--in", "-in", required=True,
                        help="Hash the contents of the specified file. If a *.hex file is given, the contents will "
                             "first be converted to binary. For all other file types, no conversion is done.")
    return parser.parse_args()


if __name__ == "__main__":
    args = parse_args()

    if args.infile.endswith('.hex'):
        ih = IntelHex(args.infile)
        if len(ih) - 1 != (ih.maxaddr() - ih.minaddr()):
            raise RuntimeError("Non-contiguous hex file not supported.")
        to_hash = ih.tobinstr()
    else:
        to_hash = open(args.infile, 'rb').read()
    sys.stdout.buffer.write(hashlib.sha256(to_hash).digest())
            else:
                c = 0
            crc_out = crc_out >> 1
            crc_out = crc_out ^ ((d ^ c) & crc_poly)
        return crc_out


if __name__ == '__main__':

    args = get_args()
    ih = IntelHex()
    ih.padding = 0x00
    print("-I Reading file {}...".format(args.ihex))
    ih.fromfile(args.ihex, format='hex')  # fromfile is the recommended way
    print("-I- Done")
    min_addr = ih.minaddr()
    max_addr = ih.maxaddr()
    print("-I- Start address : {}".format(min_addr))
    print("-I- End address : {}".format(max_addr))

    # See http://python-intelhex.readthedocs.io/en/latest/part2-5.html

    mem_array = OrderedDict()

    # Not sure if we need a +1 on the max_addr
    for i in range(min_addr, max_addr, 4):
        data = ih.tobinarray(start=i, size=4)
        mem_array[i] = (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + (
            data[0] << 0)

    # Just for debugging
Example #25
0
 mb = Microboot()
 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
    CRIS = 0x00
    NNB = 0xFF
    if not selectNode(CRIS, NNB, connection, verbose): exit(1)

    #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])
Example #27
0
    def post_process(self):
        logging.info("Processing binaries")

        fw_info_fmt = '<I16s128s16s128s16s'

        fw_info_addr = int(self.settings["FW_INFO_ADDR"], 16)

        # 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"] + '}')

        # get KV meta start
        kv_meta_addr = fw_info_addr + struct.calcsize(fw_info_fmt)
        kv_meta_len = KVMetaField().size()

        bindata = ih.tobinstr()

        kv_meta_data = []

        while True:
            kv_meta = KVMetaField().unpack(bindata[kv_meta_addr:kv_meta_addr +
                                                   kv_meta_len])

            kv_meta_addr += kv_meta_len

            if kv_meta.param_name == "kvstart":
                continue

            elif kv_meta.param_name == "kvend":
                break

            else:
                kv_meta_data.append(kv_meta)

        kv_meta_by_hash = {}

        logging.info("Hash type: FNV1A_32")

        # create lookups by 32 bit hash
        index = 0
        for kv in kv_meta_data:
            hash32 = fnv1a_32(str(kv.param_name))

            if hash32 in kv_meta_by_hash:
                raise Exception("Hash collision!")

            kv_meta_by_hash[hash32] = (kv, index)

            index += 1

        # sort indexes
        sorted_hashes = sorted(kv_meta_by_hash.keys())

        # create binary look up table
        kv_index = ''
        for a in sorted_hashes:
            kv_index += struct.pack('<LB', a, kv_meta_by_hash[a][1])

        # write to end of hex file
        ih.puts(ih.maxaddr() + 1, kv_index)

        size = ih.maxaddr() - ih.minaddr() + 1

        # get os info
        try:
            os_project = get_project_builder(self.settings["OS_PROJECT"],
                                             target=self.target_type)
        except KeyError:
            os_project = ""

        # create firmware info structure
        fw_info = struct.pack(fw_info_fmt, size, fwid.bytes,
                              os_project.proj_name, os_project.version,
                              str(self.settings['PROJ_NAME']), self.version)

        # insert fw info into hex
        ih.puts(fw_info_addr, 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("fwinfo: %x" % (fw_info_addr))
        logging.info("kv index len: %d" % (len(kv_index)))
        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.settings['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"],
                                             target=self.target_type)

        # create loader image
        loader_hex = os.path.join(loader_project.target_dir, "main.hex")
        self.merge_hex('main.hex', loader_hex, 'loader_image.hex')

        # create sha256 of binary
        sha256 = hashlib.sha256(ih.tobinstr())

        # create manifest file
        data = {
            'name': self.settings['FULL_NAME'],
            'timestamp': datetime.utcnow().isoformat(),
            'sha256': sha256.hexdigest(),
            'fwid': self.settings['FWID'],
            'version': self.version
        }

        with open('manifest.txt', 'w+') as f:
            f.write(json.dumps(data))

        # create firmware zip file
        zf = zipfile.ZipFile('chromatron_main_fw.zip', 'w')
        zf.write('manifest.txt')
        zf.write('firmware.bin')
        zf.close()

        # create second, project specific zip
        # we'll remove the first zip after
        # we update the firmware tools
        zf = zipfile.ZipFile('%s.zip' % (self.settings['PROJ_NAME']), 'w')
        zf.write('manifest.txt')
        zf.write('firmware.bin')
        zf.close()

        # change back to original dir
        os.chdir(cwd)

        logging.info("Package dir: %s" % (get_build_package_dir()))

        # make sure we have the firmware package dir
        try:
            os.makedirs(get_build_package_dir())

        except OSError:
            pass

        # copy firmware zip
        try:
            shutil.copy(
                os.path.join(self.target_dir, '%s.zip' % (self.proj_name)),
                get_build_package_dir())

        except IOError:
            raise AppZipNotFound

        # update build date
        with open(
                os.path.join(get_build_package_dir(),
                             firmware_package.PUBLISHED_AT_FILENAME),
                'w') as f:
            f.write(util.now().isoformat())
    # Here's how easy it is to erase the memory, and then verify that it's blank
    print("Erasing the EEPROM...this may take 10s of seconds")
    programmer.erase()
    print("Erase Completed!")
    print("Now performing a blank check...")
    isBlank = programmer.blankCheck()
    print("isBlank = {}".format(isBlank))

    print("Reading the entire EEPROM")
    data = programmer.read()

    print("Creating a .bin and .hex file with the data read from the EEPROM")
    ih.frombytes(data)

    print("Min Addr: {}, Max Addr: {}".format(str(ih.minaddr()),
                                              str(ih.maxaddr())))
    print("Now saving the file to disk just to demo how easy it is")
    ih.tofile("testFileErased-00.hex", format="hex")
    ih.tofile("testFileErased-00.bin", format="bin")

    # Reading / Writing / Verifying EEPROMs from bin or hex files is also very
    # easy:
    print("Manually modifying the data file")
    dataFile = "testFile.bin"
    ih[0] = 0xDE
    ih[1] = 0xAD
    ih[2] = 0xBE
    ih[3] = 0xEF

    print("Now writing the modified file to EEPROM")
Example #29
0
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)
Example #30
0
# check args
def auto_int(x):
    return int(x,0)
parser = ArgumentParser('add_header.py read a mos header, update it with given properties and length and checksum and write it back to stdout')
parser.add_argument('-p', '--pid', type=auto_int, help='option to change the pid for this program')
parser.add_argument('-k', '--key', type=auto_int, help='option to change the key for this program')
parser.add_argument('--hw', type=auto_int, help='option to change the hardware id for this program')
parser.add_argument('filename', nargs=1, help='mandatory hex file to read header data from')
args = parser.parse_args()
filename = args.filename[0]
if not os.path.exists(filename):
	sys.exit("Unable open %s" % filename)

# open the full program (open via StringIO so we can write back to filename if desired)
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
Example #31
0
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()
Example #32
0
    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)
Example #33
0
def _build_reflash_script_action(target, source, env):
    """Create a TRUB script containing tile and controller reflashes and/or sensorgraph

    If the app_info is provided, then the final source file will be a sensorgraph.
    All subsequent files in source must be in intel hex format. This is guaranteed
    by the ensure_image_is_hex call in build_update_script.
    """

    out_path = str(target[0])
    source = [str(x) for x in source]
    records = []

    if env['USE_SAFEUPDATE']:
        sgf_off = SendRPCRecord(8, 0x2005,
                                bytearray([0]))  # Disable Sensorgraph
        records.append(sgf_off)
        safemode_enable = SendRPCRecord(8, 0x1006,
                                        bytearray([1]))  # Enable Safemode
        records.append(safemode_enable)

    # Update application firmwares
    if env['SLOTS'] is not None:
        for (controller, slot_id), image_path in zip(env['SLOTS'], source):
            hex_data = IntelHex(image_path)
            hex_data.padding = 0xFF

            offset = hex_data.minaddr()
            bin_data = bytearray(
                hex_data.tobinarray(offset, hex_data.maxaddr()))

            if controller:
                record = ReflashControllerRecord(bin_data, offset)
            else:
                record = ReflashTileRecord(slot_id, bin_data, offset)

            records.append(record)

    # Update sensorgraph
    if env['UPDATE_SENSORGRAPH']:
        sensor_graph_file = source[-1]
        sensor_graph = compile_sgf(sensor_graph_file)
        output = format_script(sensor_graph)
        records += UpdateScript.FromBinary(output).records

    # Update App and OS Tag
    os_info = env['OS_INFO']
    app_info = env['APP_INFO']
    if os_info is not None:
        os_tag, os_version = os_info
        records.append(SetDeviceTagRecord(os_tag=os_tag,
                                          os_version=os_version))
    if app_info is not None:
        app_tag, app_version = app_info
        records.append(
            SetDeviceTagRecord(app_tag=app_tag, app_version=app_version))

    if env['USE_SAFEUPDATE']:
        safemode_disable = SendRPCRecord(8, 0x1006,
                                         bytearray([0]))  # Disable safemode
        records.append(safemode_disable)
        sgf_on = SendRPCRecord(8, 0x2005, bytearray([1]))  # Enable Sensorgraph
        records.append(sgf_on)

    script = UpdateScript(records)

    with open(out_path, "wb") as outfile:
        outfile.write(script.encode())
Example #34
0
"""

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
ih.puts(0x1000, struct.pack('<L', cksum))
Example #35
0
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))
Example #36
0
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)
Example #37
0
 def load(self, path):
     ih = IntelHex(path)
     return ih.tobinarray(), ih.minaddr()
Example #38
0
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)
Example #39
0
def DoIP_Flash_Hex(componentID,
                   ihexFP,
                   hostECUAddr='1111',
                   serverECUAddr='2004',
                   targetIP='172.26.200.101',
                   verbose=False,
                   multiSegment=True):
    # get necessary dependencies
    import progressbar

    t_FlashStart = time.time()

    print '\nFlashing ' + ihexFP + ' to component ID : ' + componentID + '\n'

    # start a DoIP client
    DoIPClient = DoIP_Client(ECUAddr=hostECUAddr)
    DoIPClient.SetVerbosity(verbose)

    if DoIPClient._TCP_Socket:
        downloadErr = False
        DoIPClient.ConnectToDoIPServer(address=targetIP,
                                       port=13400,
                                       routingActivation=True,
                                       targetECUAddr=serverECUAddr)

        if DoIPClient._isTCPConnected and DoIPClient._isRoutingActivated:

            print "Switching to programming diagnostic session"
            if DoIPClient.DoIPSwitchDiagnosticSession(PyUDS.PRGS) == 0:
                print "Successfully switched to programming diagnostic session\n"

                #reset connection to server
                DoIPClient.DisconnectFromDoIPServer()
                DoIPClient.ConnectToDoIPServer(address=targetIP,
                                               port=13400,
                                               routingActivation=True,
                                               targetECUAddr=serverECUAddr)

                if DoIPClient._isTCPConnected and DoIPClient._isRoutingActivated:

                    # # # initial seed key exchange # # #
                    # to do : implement seed key exchange

                    # read DIDs
                    print "Starting pre-download checks..."
                    print "\tReading old tester finger print"
                    if DoIPClient.DoIPReadDID(PyUDS.DID_REFPRNT) == 0:
                        print "\tRead success"
                        print "\tWriting new tester finger print"
                        # to do: we will need to replace the first line with the date
                        if DoIPClient.DoIPWriteDID(PyUDS.DID_WRFPRNT, '180727' + \
                                     '484F4E472D2D4849' + \
                                     '4C2D544553542D54' + \
                                     '45414D0304050607' + \
                                     '08090A0B0C0D0E0F' + \
                                     '0001020304050607' + \
                                     '5858585858585858') == 0:
                            print "\tWrite success"
                            print "\tVerifying new tester finger print"

                            # compare with the date here
                            if DoIPClient.DoIPReadDID(PyUDS.DID_REFPRNT) == 0:
                                # read and store old BL SW ID
                                # to-do: decipher and store relevant info
                                print "\tRead success"
                                print "\tReading Bootloader SW ID"
                                if DoIPClient.DoIPReadDID(
                                        PyUDS.DID_BOOTSID) == 0:

                                    # read and store old APP and CAL SW ID
                                    # to-do: decipher and store relevant info
                                    print "\tRead success"
                                    print "\tReading Application and Calibration SW ID"
                                    if DoIPClient.DoIPReadDID(
                                            PyUDS.DID_APCASID) == 0:
                                        print "\tRead success"
                                        print "Pre-download checks complete\n"

                                        # Erase component memory for target component
                                        if DoIPClient.DoIPEraseMemory(
                                                componentID) == 0:
                                            print "Erase memory success\n"
                                        else:
                                            downloadErr = True
                                    else:
                                        downloadErr = True
                                else:
                                    downloadErr = True
                            else:
                                downloadErr = True
                        else:
                            downloadErr = True
                    else:
                        downloadErr = True

                    if not downloadErr:
                        print "Loading hex file: " + ihexFP
                        from intelhex import IntelHex
                        ih = IntelHex()
                        ih.loadhex(ihexFP)

                        if multiSegment:
                            print "Downloading in multiple segments..."
                            segments = ih.segments()
                        else:
                            print "Downloading in a single filled segment..."
                            minAddr = ih.minaddr()
                            maxAddr = ih.maxaddr()
                            segments = [(ih.minaddr(), ih.maxaddr())]

                        for (minAddr, maxAddr) in segments:

                            if multiSegment:
                                maxAddr -= 1

                            memSize = maxAddr - minAddr + 1

                            minAddrStr = "%.8X" % minAddr
                            maxAddrStr = "%.8X" % maxAddr
                            memSizeStr = "%.8X" % memSize
                            print "\tStart Address: " + minAddrStr + " (%.10d)" % minAddr
                            print "\tEnd Address:   " + maxAddrStr + " (%.10d)" % maxAddr
                            print "\tTotal Memory:  " + memSizeStr + " (%.10d)\n" % memSize

                            # request download here. Set maxBlockByteCount to valu from request download
                            maxBlockByteCount = DoIPClient.DoIPRequestDownload(
                                minAddrStr, memSizeStr)
                            if maxBlockByteCount >= 2:
                                maxBlockByteCount -= 2  # subtract 2 for SID and index
                            else:
                                print "Error while requesting download data. Exiting out of flash sequencing"
                                downloadErr = True
                                break

                            blockByteCount = 0
                            hexDataStr = ''
                            hexDataList = []

                            for address in range(minAddr, maxAddr + 1):
                                # print '%.8X\t%.2X' % (address,ih[address])
                                hexDataStr = hexDataStr + '%.2X' % ih[address]
                                blockByteCount += 1
                                if blockByteCount == maxBlockByteCount:
                                    hexDataList.append(hexDataStr)
                                    hexDataStr = ''
                                    blockByteCount = 0
                            hexDataList.append(hexDataStr)
                            blockIndex = 1

                            # turn off verbosity, less you be spammed!
                            if DoIPClient._isVerbose:
                                DoIPClient.SetVerbosity(False)

                            print "Transfering Data -- Max block size(bytes): 0x%.4X (%d)" % (
                                maxBlockByteCount, maxBlockByteCount)

                            # start download progress bar
                            bar = progressbar.ProgressBar(
                                maxval=len(hexDataList),
                                widgets=[
                                    progressbar.Bar('=', '[', ']'), ' ',
                                    progressbar.Percentage()
                                ])
                            bar.start()
                            bar.update(blockIndex)

                            t_Start = time.time()

                            # begin transferring data
                            for block in hexDataList:
                                blockIndexStr = '%.2X' % (blockIndex & 0xFF)
                                if DoIPClient.DoIPTransferData(
                                        blockIndexStr, block) != 0:
                                    downloadErr = True
                                    break
                                bar.update(blockIndex)
                                blockIndex += 1

                            bar.finish()

                            if not downloadErr:
                                if DoIPClient.DoIPRequestTransferExit() == 0:
                                    t_Finish = time.time()
                                    t_Download = int(t_Finish - t_Start)
                                    hr_Download = t_Download / 3600
                                    min_Download = t_Download / 60 - hr_Download * 60
                                    sec_Download = t_Download - hr_Download * 3600 - min_Download * 60
                                    print "Download complete. Elapsed download time: %.0fdhr %.0fmin %.0fdsec" % (
                                        hr_Download, min_Download,
                                        sec_Download)
                                    print 'Total Blocks sent: 		%d' % (
                                        len(hexDataList))
                                    print 'Block size(bytes): 		%d' % (
                                        len(hexDataList[0]) / 2)
                                    print 'Final block size(bytes):	%d\n' % (
                                        len(hexDataList[len(hexDataList) - 1])
                                        / 2)

                                else:
                                    print "Request transfer exit failure. Exiting out of flash sequence"
                                    downloadErr = True
                                    break
                            else:
                                print "Transfer data failure. Exiting out of flash sequence"
                                downloadErr = True
                                break

                        # reset verbosity
                        if verbose:
                            DoIPClient.SetVerbosity(True)

                        if not downloadErr:
                            # request check memory
                            if DoIPClient.DoIPCheckMemory(componentID) == 0:
                                if DoIPClient._RxDoIPMsg.payload[9] == '0':
                                    print "Check memory passed. Authorizing software update\n"
                                # if pass, then authorize application . to do: application authorization
                                else:
                                    print "Check memory failed. Software update is invalid. Exiting out of update sequence\n"

                                print "Switching to default diagnostic session..."
                                print "\tWarning :: ECU will reset"
                                if DoIPClient._DoIPUDSSend(PyUDS.DSC +
                                                           PyUDS.DS) == 0:
                                    print "Successfully switched to default diagnostic session\n"
                                    print "Software update success!!\n"

                                    t_FlashEnd = time.time()
                                    t_Flash = int(t_FlashEnd - t_FlashStart)
                                    hr_Flash = t_Flash / 3600
                                    min_Flash = t_Flash / 60 - hr_Flash * 60
                                    sec_Flash = t_Flash - hr_Flash * 3600 - min_Flash * 60
                                    print "-----------------------------------------------------------------------------------"
                                    print "Flash sequence complete. Elapsed flash time: %.0fdhr %.0fmin %.0fdsec \n" % (
                                        hr_Flash, min_Flash, sec_Flash)
                                    print "-----------------------------------------------------------------------------------"

                            else:
                                print "Error while checking memory. Exiting out of flash sequence."
                        else:
                            print "Error during post transfer operations.\n"

                        # disconnect from the server gracefully please
                        print "Exiting out of flash sequence...\n"
                        DoIPClient.DisconnectFromDoIPServer()
                        time.sleep(5)

                    else:
                        print "Error while performing pre-programming procedure. Exiting flash sequence."
                else:
                    print "Error while reconnecting to ECU or during routing activation. Exiting flash sequence."
            else:
                print "Error while switching to programming diagnostic session. Exiting flash sequence."
        else:
            print "Error while connect to ECU and//or activate routing. Exiting flash sequence."
    else:
        print "Error while creating flash client. Unable to initiate flash sequence."
Example #40
0
 mb = Microboot()
 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)
 beginProgress("Writing")
Example #41
0
    show_help()
    sys.exit(1)
if not os.path.exists(sys.argv[1]):
    sys.exit("Unable open build %s" % sys.argv[1])
if not os.path.exists(sys.argv[2]):
    sys.exit("Unable open build %s" % sys.argv[2])
build_filename = sys.argv[1]
prog_filename = sys.argv[2]

# open the build and prog
# note open build via StringIO so we can add to it
build = IntelHex(StringIO.StringIO(open(build_filename, "r").read()))
prog = IntelHex(prog_filename)

# merge program into build
prog_header_addr = prog.minaddr()
prog.start_addr = build.start_addr  # we need this to make the merge work smoothly
build.merge(prog)

# add pointer to program header to the bootstrap
header_tbl_addr = 0x08000204
header_tbl_len = 2  #@todo get this from 0x0800200 as uint32_t
header_tbl_format = "<LL"
header_tbl = list(
    struct.unpack(header_tbl_format,
                  build.gets(header_tbl_addr, header_tbl_len * 4)))
k = 0
while header_tbl[k] != 0xffffffff:
    if k > header_tbl_len:
        sys.exit("bootstrap program table full [you have too many programs]!")
    k += 1
Example #42
0
def main():
	# Rather than at the beginning of the files, constants are here
	HASH_LENGH = 128/8									# Hash length (128 bits)
	AES_KEY_LENGTH = 256/8								# AES key length (256 bits)
	FW_MAX_LENGTH = 28672								# Maximum firmware length, depends on size allocated to bootloader
	FLASH_SECTOR_0_LENGTH = 264*8						# Length in bytes of sector 0a in external flash (to change for 16Mb & 32Mb flash!)
	STORAGE_SPACE = 65536 - FLASH_SECTOR_0_LENGTH		# Uint16_t addressing space - sector 0a length (dedicated to other storage...)
	BUNDLE_MAX_LENGTH = STORAGE_SPACE - FW_MAX_LENGTH - HASH_LENGH - AES_KEY_LENGTH
	
	# Robust RNG
	rng = Random.new()

	# Check that all required files are here
	if isfile("bundle.img"):
		print "Bundle file found"
	else:
		print "Couldn't find bundle file"
		return
		
	if isfile("Mooltipass.hex"):
		print "Firmware file found"
	else:
		print "Couldn't find firmware file"
		return
	
	# Read bundle and firmware data
	firmware = IntelHex("Mooltipass.hex")
	fd = open("bundle.img", 'rb')
	bundle = fd.read()
	fd.close()	
	
	# Check that the firmware data actually starts at address 0
	if firmware.minaddr() != 0:
		print "Firmware start address isn't correct"
		return
		
	# Check that the bundle & firmware data aren't bigger than they should be
	if len(bundle) > BUNDLE_MAX_LENGTH:
		print "Bundle file too long:", len(bundle), "bytes long"
		return
	else:	
		print "Bundle file is ", len(bundle), "bytes long"
	if len(firmware) > FW_MAX_LENGTH:
		print "Firmware file too long:", len(firmware), "bytes long"
		return
	else:	
		print "Firmware file is ", len(firmware), "bytes long"
		
	# Generate new random AES key, encrypt it with the old one
	new_aes_key = rng.read(AES_KEY_LENGTH)
	new_aes_key = array('B',[0]*AES_KEY_LENGTH) # TO REMOVE!
	cipher = AES.new(getAesKeyForMooltipass(0), AES.MODE_ECB, array('B',[0]*AES.block_size))	# IV ignored in ECB
	enc_password = cipher.encrypt(new_aes_key)
	if len(enc_password) != AES_KEY_LENGTH:
		print "Encoded password is too long!"
		return		
		
	# Generate beginning of update file data: bundle | padding | firmware | new aes key encoded
	update_file_data = array('B')
	update_file_data.extend(bytearray(bundle))
	update_file_data.extend(array('B',[0]*(STORAGE_SPACE-HASH_LENGH-AES_KEY_LENGTH-FW_MAX_LENGTH-len(bundle))))
	update_file_data.extend(firmware.tobinarray())
	update_file_data.extend(array('B',[0]*(STORAGE_SPACE-HASH_LENGH-AES_KEY_LENGTH-len(update_file_data))))
	update_file_data.extend(bytearray(enc_password))
	
	# Check length
	if len(update_file_data) != (STORAGE_SPACE - HASH_LENGH):
		print "Problem with update file length!"
		return
		
	# Generate CBCMAC, IV is ZEROS
	cipher = AES.new(getAesKeyForMooltipass(0), AES.MODE_CBC, array('B',[0]*AES.block_size))
	cbc_mac = cipher.encrypt(update_file_data)[-AES.block_size:]
		
	# Append it to update file data: bundle | padding | firmware | new aes key encoded | cbcmac
	update_file_data.extend(bytearray(cbc_mac))
	
	# Check length
	if len(update_file_data) != STORAGE_SPACE:
		print "Problem with update file length!"
		return
		
	# Write our update image file
	data_fd = open("updatefile.img", 'wb')
	data_fd.write(update_file_data)
	data_fd.close()
	print "Update file written!"
Example #43
0
class ShdlcFirmwareImage(object):
    """
    This class represents a firmware image for an SHDLC device. It is used to
    load and verify Intel-Hex files for performing firmware updates over SHDLC.

    Since the different SHDLC devices use different memory layouts, this class
    needs to know the bootloader base address and application base address (see
    constructor parameters). Drivers for specific SHDLC devices should create a
    subclass to provide a new type which already contains the correct
    addresses, so users don't have to care about these details.

    .. note:: This class is intended only for devices which contain the SHDLC
              bootloader. Devices which support firmware updates with another
              system aren't supported by this class.

    .. note:: The package ``intelhex`` must be installed to use this class. See
              :ref:`firmware-updater-dependencies` for details.
    """

    _PRODUCT_TYPE_SIZE = 4  # Product type size

    def __init__(self,
                 hexfile,
                 bl_start_addr,
                 app_start_addr,
                 signature=b'\x4A\x47\x4F\x4B',
                 bl_version_offset=0x1004):
        """
        Constructor which loads and parses the firmware from a hex file.

        :param str/file hexfile:    The filename or file-like object containing
                                    the firmware in Intel-Hex format (\\*.hex).
        :param int bl_start_addr:   The base address of the bootloader inside
                                    the firmware image.
        :param int app_start_addr:  The base address of the application
                                    inside the firmware image.
        :param bytes signature:     Signature bytes used for the application.
        :param int bl_version_offset: Bootloader version address offset.

        :raise ~sensirion_shdlc_driver.errors.ShdlcFirmwareImageSignatureError:
            If the signature of the image is invalid.
        """
        # Import intelhex here to allow importing the firmware_image module
        # without having the intelhex package installed (it's an optional
        # dependency, so it might be missing).
        from intelhex import IntelHex
        self._bl_start_addr = int(bl_start_addr)
        self._app_start_addr = int(app_start_addr)
        self._signature = bytes(bytearray(signature))
        self._bl_version_offset = int(bl_version_offset)
        self._app_data_index = 0
        self._data = IntelHex(hexfile)
        self._data.padding = 0xFF  # is returned when reading undefined regions
        log.debug(
            "Loaded hex file: {} [minaddr=0x{:08X}, maxaddr=0x{:08X}]".format(
                hexfile, self._data.minaddr(), self._data.maxaddr()))
        self._check_signature()
        log.debug("Signature: OK")
        self._product_type = self._read_product_type()
        log.debug("Product type: 0x{:08X}".format(self._product_type))
        self._bootloader_version = self._read_bootloader_version()
        log.debug("Bootloader version: {}".format(self._bootloader_version))
        self._application_version = self._read_application_version()
        log.debug("Application version: {}".format(self._application_version))
        self._app_data = self._read_application_data()
        log.debug("Application size: {:.2f} kB".format(self.size / 1024))
        self._checksum = self._calc_application_checksum()
        log.debug("Application checksum: 0x{:02X}".format(self._checksum))

    @property
    def product_type(self):
        """
        Get the product type for which the loaded firmware is made.

        :return: Product type as an integer.
        :rtype: int
        """
        return self._product_type

    @property
    def bootloader_version(self):
        """
        Get the bootloader version which is contained in the loaded image.

        :return: Bootloader version (note: debug flag is not supported, it's
                 always False).
        :rtype: ~sensirion_shdlc_driver.types.FirmwareVersion
        """
        return self._bootloader_version

    @property
    def application_version(self):
        """
        Get the application firmware version which is contained in the loaded
        image.

        :return: Application firmware version (note: debug flag is not
                 supported, it's always False).
        :rtype: ~sensirion_shdlc_driver.types.FirmwareVersion
        """
        return self._application_version

    @property
    def checksum(self):
        """
        Get the checksum over the application firmware part of the loaded
        image. This is the checksum which needs to be sent to the product
        bootloader.

        :return: Checksum as a byte.
        :rtype: byte
        """
        return self._checksum

    @property
    def size(self):
        """
        Get the size of the application firmware.

        :return: Size in bytes.
        :rtype: int
        """
        return len(self._app_data)

    @property
    def available_bytes(self):
        """
        Get the count of available bytes left.

        :return: Count of available bytes.
        :rtype: int
        """
        return len(self._app_data) - self._app_data_index

    def read(self, size=-1):
        """
        Read the next bytes of the application firmware.

        :param int size:    Maximum count of bytes to read (-1 reads all
                            available)
        :return:            Firmware data block.
        :rtype: bytes
        """
        if size < 0:
            size = self.available_bytes
        else:
            size = min(size, self.available_bytes)
        data = self._app_data[self._app_data_index:self._app_data_index + size]
        self._app_data_index += len(data)
        return bytes(data)  # immutable type to avoid modifying image data

    def _check_signature(self):
        """
        Check the signature of the loaded image and throw an exception if it's
        invalid.
        """
        signature = self._read_bytes(self._app_start_addr,
                                     len(self._signature))
        if signature != self._signature:
            raise ShdlcFirmwareImageSignatureError(signature)

    def _read_product_type(self):
        """
        Read the product type from the loaded image.

        :return: The read product type.
        :rtype: int
        """
        address = self._app_start_addr + len(self._signature)
        return self._read_uint32(address)

    def _read_bootloader_version(self):
        """
        Read the bootloader version from the loaded image.

        :return: The read bootloader version.
        :rtype: ~sensirion_shdlc_driver.types.FirmwareVersion
        """
        addr_major = self._bl_start_addr + self._bl_version_offset + 1
        addr_minor = self._bl_start_addr + self._bl_version_offset
        return FirmwareVersion(major=self._data[addr_major],
                               minor=self._data[addr_minor],
                               debug=False)

    def _read_application_version(self):
        """
        Read the application version from the loaded image.

        :return: The read application version.
        :rtype: ~sensirion_shdlc_driver.types.FirmwareVersion
        """
        addr_major = self._app_start_addr + len(self._signature) + \
            self._PRODUCT_TYPE_SIZE + 1
        addr_minor = self._app_start_addr + len(self._signature) + \
            self._PRODUCT_TYPE_SIZE
        return FirmwareVersion(major=self._data[addr_major],
                               minor=self._data[addr_minor],
                               debug=False)

    def _read_application_data(self):
        """
        Read the application data block from the loaded image.

        :return: The read application data block.
        :rtype: bytearray
        """
        # Skip the signature because it must not be sent to the bootloader!
        start_addr = self._app_start_addr + len(self._signature)
        if self._bl_start_addr > self._app_start_addr:
            end_addr = self._bl_start_addr - 1  # Don't include bootloader
        else:
            end_addr = self._data.maxaddr()
        return bytearray(self._data.tobinarray(start=start_addr, end=end_addr))

    def _read_uint32(self, address):
        """
        Read an uint32 at a specific image address.

        :param int address: The address to read from.
        :return: The integer at the specified address.
        :rtype: int
        """
        return unpack("<I", self._data.tobinarray(start=address, size=4))[0]

    def _read_bytes(self, address, number_of_bytes):
        """
        Read at a specific image address.

        :param int address: The address to read from.
        :param int number_of_bytes: Number of bytes to read
        :return: The bytes from the specified address.
        :rtype: bytes
        """
        return self._data.tobinstr(start=address, size=number_of_bytes)

    def _calc_application_checksum(self):
        """
        Calculate the checksum over the application data, as needed for the
        firmware download command.

        :return: Checksum of application data
        :rtype: byte
        """
        return (sum(self._app_data) % 256) ^ 0xFF
Example #44
0
                    address = int(address, 0) & 0xFFFFFFFF
                except ValueError:
                    print("Address %s invalid." % address)
                    sys.exit(1)
                if not os.path.isfile(binfile):
                    print("Unreadable file '%s'." % binfile)
                    sys.exit(1)
                target.append({
                    'address': address,
                    'data': open(binfile, 'rb').read()
                })

        if options.hexfiles:
            for hex in options.hexfiles:
                ih = IntelHex(hex)
                address = ih.minaddr()
                data = ih.tobinstr()
                try:
                    address = address & 0xFFFFFFFF
                except ValueError:
                    print("Address %s invalid." % address)
                    sys.exit(1)
                target.append({'address': address, 'data': data})

        outfile = args[0]
        device = DEFAULT_DEVICE
        if options.device:
            device = options.device
        try:
            v, d = map(lambda x: int(x, 0) & 0xFFFF, device.split(':', 1))
        except:
Example #45
0
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))
Example #46
0
    if not selectNode(CRIS, NNB, connection, verbose): exit(1)

    #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)
Example #47
0
class MainApp(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.ih = IntelHex()
        self.ab = ArduinoBootloader()
        self.working_thread = None
        self.progress_queue = Queue(100)
        self.protocol = "Stk500v1"
        self.baudrate = 115200

    def build(self):
        return Builder.load_string(KV)

    def on_sel_programmer(self, baudrate, protocol):
        self.baudrate = baudrate
        self.protocol = protocol

    def on_flash(self):
        del self.ih

        try:
            self.ih = IntelHex()
            self.ih.fromfile(self.root.ids.file_name.text, format='hex')
        except FileNotFoundError:
            self.root.ids.file_info.text = "File not found"
            return
        except AddressOverlapError:
            self.root.ids.file_info.text = "File with address overlapped"
            return

        self.root.ids.file_info.text = "start address: {} size: {} bytes".format(
            self.ih.minaddr(), self.ih.maxaddr())
        """The firmware update is done in a worker thread because the main 
           thread in Kivy is in charge of updating the widgets."""
        self.root.ids.progress.value = 0
        self.working_thread = threading.Thread(target=self.thread_flash)
        self.working_thread.start()

    def thread_flash(self):
        """If the communication with the bootloader through the serial port could be
           established, obtains the information of the processor and the bootloader."""
        res_val = False
        """First you have to select the communication protocol used by the bootloader of 
        the Arduino board. The Stk500V1 is the one used by the Nano or Uno, and depending 
        on the Old or New version, the communication speed varies, for the new one you 
        have to use 115200 and for the old 57600.
        
        The communication protocol for boards based on Mega 2560 is Stk500v2 at 115200."""
        prg = self.ab.select_programmer(self.protocol)

        if prg.open(speed=self.baudrate):
            if prg.board_request():
                self.progress_queue.put(["board_request"])
                Clock.schedule_once(self.progress_callback, 1 / 1000)

            if prg.cpu_signature():
                self.progress_queue.put(["cpu_signature"])
                Clock.schedule_once(self.progress_callback, 1 / 1000)
            """Iterate the firmware file into chunks of the page size in bytes, and 
               use the write flash command to update the cpu."""
            for address in range(0, self.ih.maxaddr(), self.ab.cpu_page_size):
                buffer = self.ih.tobinarray(start=address,
                                            size=self.ab.cpu_page_size)
                res_val = prg.write_memory(buffer, address)
                if not res_val:
                    break

                self.progress_queue.put(["write", address / self.ih.maxaddr()])
                Clock.schedule_once(self.progress_callback, 1 / 1000)
            """If the write was successful, re-iterate the firmware file, and use the 
               read flash command to update and compare them."""
            if res_val:
                for address in range(0, self.ih.maxaddr(),
                                     self.ab.cpu_page_size):
                    buffer = self.ih.tobinarray(start=address,
                                                size=self.ab.cpu_page_size)
                    read_buffer = prg.read_memory(address,
                                                  self.ab.cpu_page_size)
                    if not len(read_buffer) or (buffer != read_buffer):
                        res_val = False
                        break

                    self.progress_queue.put(
                        ["read", address / self.ih.maxaddr()])
                    Clock.schedule_once(self.progress_callback, 1 / 1000)

            self.progress_queue.put(
                ["result", "ok" if res_val else "error", address])
            Clock.schedule_once(self.progress_callback, 1 / 1000)

            prg.leave_bootloader()

            prg.close()
        else:
            self.progress_queue.put(["open_error"])
            Clock.schedule_once(self.progress_callback, 1 / 1000)

    def progress_callback(self, dt):
        """In kivy only the main thread can update the widgets. Schedule a clock
           event to read the message from the queue and update the progress."""
        value = self.progress_queue.get()

        if value[0] == "open_error":
            self.root.ids.status.text = "Can't open bootloader {} at baudrate {}".format(
                self.protocol, self.baudrate)

        if value[0] == "board_request":
            self.root.ids.sw_version.text = self.ab.sw_version
            self.root.ids.hw_version.text = self.ab.hw_version
            self.root.ids.prg_name.text = self.ab.programmer_name

        if value[0] == "cpu_signature":
            self.root.ids.cpu_version.text = self.ab.cpu_name

        if value[0] == "write":
            self.root.ids.status.text = "Writing flash %{:.2f}".format(
                value[1] * 100)
            self.root.ids.progress.value = value[1]

        if value[0] == "read":
            self.root.ids.status.text = "Reading and verifying flash %{:.2f}".format(
                value[1] * 100)
            self.root.ids.progress.value = value[1]

        if value[0] == "result" and value[1] == "ok":
            self.root.ids.status.text = "Download done"
            self.root.ids.progress.value = 1

        if value[0] == "result" and value[1] == "error":
            self.root.ids.status.text = "Error writing"
Example #48
0
                print("Fatal Error: -- FAILED merge due to overlap when merging " + f.name)
                sys.exit(1)
        except:
            print("Fatal Error: -- FAILED parsing input hex file(s)")
            sys.exit(1)

    #print information about the input hex files
    print_args_info(inputFileNames, vargs.out, vargs.outbin, vargs.oadtype, vargs.imgtype)

    #Now that we have a merged hex image, lets do a bunch of arg checking
    #since mergedHex is an merge of all input hexes, it can be treated as an argument to the script
    argument_sanity_check(vargs, mergedHex)


    # Cut off / fill with --fill.
    startAddr = mergedHex.minaddr()
    endAddr = mergedHex.addresses()[-1] + 1  # Inclusive address

    if startAddr % OAD_BLOCK_SIZE:
        print("Fatal Error: -- Start address 0x%X is not divisible by 16. Exiting")
        sys.exit(1)

    # DevMon rounds up to nearest sector. Why not, if they want to waste time and space.
    if vargs.round is not None:
        endAddr = ((endAddr + INT_FL_PG_SIZE) & ~(INT_FL_PG_SIZE-1))
        print ('endAddr round', hex(endAddr))

    if vargs.range is not None:
        if vargs.range[0] is not None: startAddr = vargs.range[0]
        if vargs.range[1] is not None: endAddr = vargs.range[1]
Example #49
0
                    type=auto_int,
                    help='option to change the key for this program')
parser.add_argument('--hw',
                    type=auto_int,
                    help='option to change the hardware id for this program')
parser.add_argument('filename',
                    nargs=1,
                    help='mandatory hex file to read header data from')
args = parser.parse_args()
filename = args.filename[0]
if not os.path.exists(filename):
    sys.exit("Unable open %s" % filename)

# open the full program (open via StringIO so we can write back to filename if desired)
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
Example #50
0
def merge_region_list(region_list,
                      destination,
                      notify,
                      config,
                      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 gaps with
    """
    merged = IntelHex()
    _, format = splitext(destination)
    notify.info("Merging Regions")
    # Merged file list: Keep track of binary/hex files that we have already
    # merged. e.g In some cases, bootloader may be split into multiple parts,
    # but all internally referring to the same bootloader file.
    merged_list = []

    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 and (region.filename not in merged_list):
            notify.info("  Filling region %s with %s" %
                        (region.name, region.filename))
            part = intelhex_offset(region.filename, offset=region.start)
            part.start_addr = None
            # Normally, we assume that part.maxddr() can be beyond
            # end of rom. If the size is restricted with config, don't
            # allow this.
            if config.target.restrict_size is not 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_list.append(region.filename)
            merged.merge(part)
        elif region.filename in merged_list:
            notify.info("  Skipping %s as it is merged previously" %
                        (region.name))

    # Hex file can have gaps, so no padding needed. While other formats may
    # need padding. Iterate through segments and pad the gaps.
    if format != ".hex":
        # begin patching from the end of the first segment
        _, begin = merged.segments()[0]
        for start, stop in merged.segments()[1:]:
            pad_size = start - begin
            merged.puts(begin, padding * pad_size)
            begin = stop + 1

    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("."))
Example #51
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
Example #52
0
def main():
    # Check if one input argument is provided
    if len(sys.argv) != 2:
        print "Usage:", sys.argv[0], "bootloader.hex"
        sys.exit(1)

    # Input arguments
    hexfile = sys.argv[1]

    # Check if file exists
    if not os.path.isfile(hexfile):
        print "Error: File does not exist."
        sys.exit(2)

    # Read bootloader data
    bootloader = IntelHex(hexfile)
    bootloader_bin = bootloader.tobinarray()
    #bootloader.dump()

    # Start address
    loaderStart = bootloader.minaddr()

    # Given a start address, deduce where the bootloader ends
    end_addresses = {
        0x1000: 0x2000,
        0x1C00: 0x2000,
        0x1D00: 0x2000,
        0x1E00: 0x2000,
        0x3000: 0x4000,
        0x3800: 0x4000,
        0x3E00: 0x4000,
        0x7000: 0x8000,
        0x7800: 0x8000,
        0x7E00: 0x8000,
        0xF800: 0x10000,
        0x1F000: 0x20000,
        0x1FC00: 0x20000,
        0x3E000: 0x40000,
    }
    if not loaderStart in end_addresses:
        print "Error: Unkown bootloader start address."
        sys.exit(3)
    loaderEnd = end_addresses[loaderStart]

    # Len
    loaderLen = loaderEnd - loaderStart
    if loaderLen < len(bootloader_bin):
        print "Error: Invalid bootloader length."
        sys.exit(4)

    # Calculate md5sum from hexfile and add padding bytes with 0xFF
    md5 = hashlib.md5()
    md5.update(bootloader_bin)
    padding = [0xFF] * (loaderLen - len(bootloader_bin))
    md5.update(bytearray(padding))

    # Calculatae md5sum from the original file so we know which disk file it came from
    filemd5 = hashlib.md5()
    fd = open(hexfile, 'rb')
    filemd5.update(fd.read())
    fd.close()

    # Filename without full path and without ".hex"
    filename = os.path.splitext(os.path.basename(hexfile))[0]

    # Print header
    print '// File =', filename + ".hex"
    print '// Loader start:', hex(loaderStart), 'length', loaderLen
    print '// Bootloader MD5 sum =', md5.hexdigest()
    print '// Original file MD5 sum =', filemd5.hexdigest()
    print
    print 'const uint8_t', filename + '_hex [] PROGMEM = {'

    # Print data
    line = ""
    for i in range(len(bootloader_bin)):
        line += hex(bootloader_bin[i]) + ', '
        if i % 16 == 15:
            print line
            line = ''
    if line:
        print line

    # Print footer
    print '}; // end of', filename + '_hex'
Example #53
0
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)
Example #54
0
          print("Address:file couple '%s' invalid." % arg)
          sys.exit(1)
        try:
          address = int(address,0) & 0xFFFFFFFF
        except ValueError:
          print("Address %s invalid." % address)
          sys.exit(1)
        if not os.path.isfile(binfile):
          print("Unreadable file '%s'." % binfile)
          sys.exit(1)
        target.append({ 'address': address, 'data': open(binfile,'rb').read() })
    
    if options.hexfiles:
      for hex in options.hexfiles:
        ih = IntelHex(hex)
        address = ih.minaddr()
        data = ih.tobinstr()
        try:
          address = address & 0xFFFFFFFF
        except ValueError:
          print("Address %s invalid." % address)
          sys.exit(1)
        target.append({ 'address': address, 'data': data })

    revision = DEFAULT_REVISION
    if options.revision:
        try:
            rev2byte(options.revision)
            revision  = options.revision
        except ValueError:
            print("Invalid revision value.")
def bundlePackAndSign(bundleName, firmwareName, oldAesKey, newAesKey, updateFileName, verbose):
	# Rather than at the beginning of the files, constants are here
	VERSION_LENGTH = 4									# FW version length
	HASH_LENGH = 128/8									# Hash length (128 bits)
	AES_KEY_LENGTH = 256/8								# AES key length (256 bits)
	FW_VERSION_LENGTH = 4								# Length of the firmware version in the bundle
	AES_KEY_UPDATE_FLAG_LGTH = 1						# Length of the tag which specifies a firmware udpate
	FW_MAX_LENGTH = 28672								# Maximum firmware length, depends on size allocated to bootloader
	FLASH_SECTOR_0_LENGTH = 264*8						# Length in bytes of sector 0a in external flash (to change for 16Mb & 32Mb flash!)
	STORAGE_SPACE = 65536 - FLASH_SECTOR_0_LENGTH		# Uint16_t addressing space - sector 0a length (dedicated to other storage...)
	BUNDLE_MAX_LENGTH = STORAGE_SPACE - FW_MAX_LENGTH - HASH_LENGH - AES_KEY_LENGTH - FW_VERSION_LENGTH - AES_KEY_UPDATE_FLAG_LGTH
	
	# Robust RNG
	rng = Random.new()
	
	# Extracted firmware version
	firmware_version = None
	
	# AES Key Update Bool
	aes_key_update_bool = True

	# Check that all required files are here
	if isfile(bundleName):
		if verbose == True:
			print "Bundle file found"
	else:
		print "Couldn't find bundle file"
		return False
		
	if isfile(firmwareName):
		if verbose == True:
			print "Firmware file found"
	else:
		print "Couldn't find firmware file"
		return False
	
	# Read bundle and firmware data
	firmware = IntelHex(firmwareName)
	firmware_bin = firmware.tobinarray()
	fd = open(bundleName, 'rb')
	bundle = fd.read()
	fd.close()	
	
	# Check that the firmware data actually starts at address 0
	if firmware.minaddr() != 0:
		print "Firmware start address isn't correct"
		return False
		
	# Check that the bundle & firmware data aren't bigger than they should be
	if len(bundle) > BUNDLE_MAX_LENGTH:
		print "Bundle file too long:", len(bundle), "bytes long"
		return False
	else:	
		if verbose == True:
			print "Bundle file is", len(bundle), "bytes long"
		
	if len(firmware) > FW_MAX_LENGTH-VERSION_LENGTH:
		print "Firmware file too long:", len(firmware), "bytes long"
		return False
	else:	
		if verbose == True:
			print "Firmware file is", len(firmware), "bytes long"
	
	if verbose == True:
		print "Remaining space in MCU flash:", FW_MAX_LENGTH - len(firmware), "bytes"
	
	if verbose == True:
		print "Remaining space in bundle:", STORAGE_SPACE - FW_MAX_LENGTH - HASH_LENGH - AES_KEY_LENGTH - FW_VERSION_LENGTH - AES_KEY_UPDATE_FLAG_LGTH - len(bundle), "bytes"
		
	# Beta testers devices have their aes key set to 00000... and the bootloader will always perform a key update
	if oldAesKey == "0000000000000000000000000000000000000000000000000000000000000000" and newAesKey == None:
		if verbose == True:
			print "Bundle update for beta testers unit, setting 00000... as new AES key"
		newAesKey = "0000000000000000000000000000000000000000000000000000000000000000"
		
	# If no new aes key is specified, don't set the aes key update flag
	if newAesKey == None:
		if verbose == True:
			print "No new AES key set"
		aes_key_update_bool = False
	else:
		if verbose == True:
			print "Encrypting new AES key"
		
	# If needed, check the new aes key
	if aes_key_update_bool == True:
		new_aes_key = array('B', newAesKey.decode("hex"))
		if len(new_aes_key) != AES_KEY_LENGTH:
			print "Wrong New AES Key Length:", len(new_aes_key)
			return False
		
	# Convert & check the old aes key
	old_aes_key = array('B', oldAesKey.decode("hex"))
	if len(old_aes_key) != AES_KEY_LENGTH:
		print "Wrong Old AES Key Length:", len(oldAesKey)
		return False

	# Get version number
	for i in range(len(firmware_bin) - 3):
		if chr(firmware_bin[i]) == 'v' and \
		chr(firmware_bin[i + 1]) >= '1' and chr(firmware_bin[i + 1]) <= '9' and \
		chr(firmware_bin[i + 2]) == '.' and \
		chr(firmware_bin[i + 3]) >= '0' and chr(firmware_bin[i + 3]) <= '9':
			firmware_version = firmware_bin[i:i+4]
			if verbose == True:
				print "Extracted firmware version:", "".join(chr(firmware_version[j]) for j in range(0, 4))
			break;
			
	# Write it in the last 4 bytes of the firmware hex
	firmware[FW_MAX_LENGTH-4] = firmware_version[0]
	firmware[FW_MAX_LENGTH-3] = firmware_version[1]
	firmware[FW_MAX_LENGTH-2] = firmware_version[2]
	firmware[FW_MAX_LENGTH-1] = firmware_version[3]
			
	# Check if we extracted the firmware version and it has the correct length
	if firmware_version == None or len(firmware_version) != FW_VERSION_LENGTH:
		print "Problem while extracting firmware version"
		return False

	# If needed, encrypt the new AES key with the old one
	if aes_key_update_bool == True:
		cipher = AES.new(old_aes_key, AES.MODE_ECB, array('B',[0]*AES.block_size))	# IV ignored in ECB
		enc_password = cipher.encrypt(new_aes_key)
		if len(enc_password) != AES_KEY_LENGTH:
			print "Encoded password is too long!"
			return False
	else:
		enc_password = [255]*AES_KEY_LENGTH
		
	# Generate beginning of update file data: bundle | padding | firmware version | new aes key bool | firmware | padding | new aes key encoded
	update_file_data = array('B')
	update_file_data.extend(bytearray(bundle))
	update_file_data.extend(array('B',[0]*(STORAGE_SPACE-HASH_LENGH-AES_KEY_LENGTH-FW_MAX_LENGTH-FW_VERSION_LENGTH-AES_KEY_UPDATE_FLAG_LGTH-len(bundle))))
	update_file_data.extend(firmware_version)
	if aes_key_update_bool == True:
		update_file_data.append(255)
	else:
		update_file_data.append(0)
	update_file_data.extend(firmware.tobinarray())
	update_file_data.extend(array('B',[0]*(STORAGE_SPACE-HASH_LENGH-AES_KEY_LENGTH-len(update_file_data))))
	update_file_data.extend(bytearray(enc_password))
	
	# Check length
	if len(update_file_data) != (STORAGE_SPACE - HASH_LENGH):
		print "Problem with update file length!"
		return False
		
	# Generate CBCMAC, IV is ZEROS
	cipher = AES.new(old_aes_key, AES.MODE_CBC, array('B',[0]*AES.block_size))
	cbc_mac = cipher.encrypt(update_file_data)[-AES.block_size:]
		
	# Append it to update file data: bundle | padding | firmware version | new aes key bool | firmware | padding | new aes key encoded | cbcmac
	update_file_data.extend(bytearray(cbc_mac))
	
	# Check length
	if len(update_file_data) != STORAGE_SPACE:
		print "Problem with update file length!"
		return False
		
	# Write our update image file
	data_fd = open(updateFileName, 'wb')
	data_fd.write(update_file_data)
	data_fd.close()
	if verbose == True:
		print "Update file written!"
	return True
Example #56
0
                mergedHex.merge(ih, overlap='replace')
            except:
                print(
                    "Fatal Error: -- FAILED merge due to overlap when merging "
                    + f.name)
                sys.exit(1)
        except:
            print("Fatal Error: -- FAILED parsing input hex file(s)")
            sys.exit(1)

    #print information about the input hex files
    print_args_info(inputFileNames, vargs.out, vargs.outbin, vargs.oadtype,
                    vargs.imgtype, mergedHex)

    # Cut off / fill with --fill.
    startAddr = mergedHex.minaddr()
    endAddr = mergedHex.addresses()[-1] + 1  # Inclusive address

    if startAddr % vargs.blockSize:
        print(
            "Fatal Error: -- Start address 0x%X is not divisible by 16. Exiting"
            % startAddr)
        sys.exit(1)

    if vargs.range is not None:
        if vargs.range[0] is not None: startAddr = vargs.range[0]
        if vargs.range[1] is not None: endAddr = vargs.range[1]

    # Make sure the last address is divisible by the block size
    remainder = endAddr % vargs.blockSize
    if remainder:
Example #57
0
 def get_file_buf(self, filename):
     fil = open(filename, 'r')
     hexfile = IntelHex(fil)
     glog.info('Min addr >> ', hexfile.minaddr())
     assert hexfile.minaddr() == 0
     return hexfile.tobinstr()