Example #1
1
def check_fw(path):
    """Check that firmware is valid and return dict with binary data."""
    try:
        intel_hex = IntelHex()
        with open(path, 'r') as file_handle:
            intel_hex.fromfile(file_handle, format='hex')
        bin_string = intel_hex.tobinstr()
    except (IntelHexError, TypeError, ValueError) as exception:
        _LOGGER.error(exception)
        return
    pads = len(bin_string) % 128  # 128 bytes per page for atmega328
    for _ in range(128 - pads):  # pad up to even 128 bytes
        bin_string += b'\xff'
    fware = {
        'path': path,
        'blocks': int(len(bin_string) / FIRMWARE_BLOCK_SIZE),
        'crc': compute_crc(bin_string),
        'data': bin_string,
    }
    return fware
def main():
    args = parser.parse_args()
    base_hex = IntelHex()
    # Merge in hex files
    for file_name in args.hex:
        file_name = os.path.expanduser(file_name)
        new_hex_data = IntelHex()
        print "opening file %s" % file_name
        new_hex_data.fromfile(file_name, format='hex')
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Merge in binary files
    for file_name, addr_str in args.bin:
        file_name = os.path.expanduser(file_name)
        offset = int(addr_str, 0)
        new_hex_data = IntelHex()
        new_hex_data.loadbin(file_name, offset=offset)
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Write out data
    print_hex_info(os.path.expanduser(args.output_file), base_hex)
    with open(os.path.expanduser(args.output_file), 'wb') as output_file:
        base_hex.tofile(output_file, 'hex')
    if args.output_bin_file is not None:
        with open(os.path.expanduser(args.output_bin_file), 'wb') as output_file:
            base_hex.tofile(output_file, 'bin')
Example #3
0
def main():
    args = parser.parse_args()
    base_hex = IntelHex()
    # Merge in hex files
    for file_name in args.hex:
        file_name = os.path.expanduser(file_name)
        new_hex_data = IntelHex()
        print "opening file %s" % file_name
        new_hex_data.fromfile(file_name, format='hex')
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Merge in binary files
    for file_name, addr_str in args.bin:
        file_name = os.path.expanduser(file_name)
        offset = int(addr_str, 0)
        new_hex_data = IntelHex()
        new_hex_data.loadbin(file_name, offset=offset)
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Write out data
    print_hex_info(os.path.expanduser(args.output_file), base_hex)
    with open(os.path.expanduser(args.output_file), 'wb') as output_file:
        base_hex.tofile(output_file, 'hex')
    if args.output_bin_file is not None:
        with open(os.path.expanduser(args.output_bin_file),
                  'wb') as output_file:
            base_hex.tofile(output_file, 'bin')
Example #4
0
class FirmwareTool:

    def __init__(self, firmware, version, hexfile=None):
        self.ffi = FFI()
        try:
            self.schema = PRESET_SCHEMATA[firmware][version](self.ffi)
        except KeyError:
            raise NotImplementedError(
                "don't know how to read version {}".format(version))
        else:
            self.ffi.cdef(self.schema.cdef())

        if hexfile is not None:
            self.ih = IntelHex()
            self.ih.fromfile(hexfile, format='hex')

            # without this, the program will just silently exit if it
            # segfaults trying to read values from the CFFI object
            faulthandler.enable()

            self.nvram_data = self.ffi.new(
                '{} *'.format(self.schema.root_type()))
            nvram_buffer = self.ffi.buffer(self.nvram_data)

            # address from the ansible.sym symbol table
            nvram_dump = self.ih.tobinarray(
                self.schema.address(),
                self.schema.address() + len(nvram_buffer) - 1
            )
            nvram_buffer[:] = nvram_dump
Example #5
0
def _compute_crc(hex_file_path):
    # Read in hex file
    new_hex_file = IntelHex()
    new_hex_file.padding = 0xFF
    new_hex_file.fromfile(hex_file_path, format='hex')

    # Get the starting and ending address
    addresses = new_hex_file.addresses()
    addresses.sort()
    start_end_pairs = list(_ranges(addresses))
    regions = len(start_end_pairs)
    assert regions == 1, ("Error - only 1 region allowed in "
                          "hex file %i found." % regions)
    start, end = start_end_pairs[0]

    # Compute checksum over the range (don't include data at location of crc)
    size = end - start + 1
    crc_size = size - 4
    data = new_hex_file.tobinarray(start=start, size=crc_size)
    data_crc32 = binascii.crc32(data) & 0xFFFFFFFF

    # Grab the crc from the image
    embedded_crc32 = (((new_hex_file[end - 3] & 0xFF) << 0) |
                      ((new_hex_file[end - 2] & 0xFF) << 8) |
                      ((new_hex_file[end - 1] & 0xFF) << 16) |
                      ((new_hex_file[end - 0] & 0xFF) << 24))
    return data_crc32, embedded_crc32
Example #6
0
    def check_only(self, name):
        # FIXME refactor
        # copy from program_file
        if name.lower().endswith(".json"):
            data = json.loads(open(name, "r").read())
            fw = base64.b64decode(helpers.from_websafe(data["firmware"]).encode())
            sig = base64.b64decode(helpers.from_websafe(data["signature"]).encode())
            ih = IntelHex()
            tmp = tempfile.NamedTemporaryFile(delete=False)
            tmp.write(fw)
            tmp.seek(0)
            tmp.close()
            ih.fromfile(tmp.name, format="hex")
        else:
            if not name.lower().endswith(".hex"):
                print('Warning, assuming "%s" is an Intel Hex file.' % name)
            sig = None
            ih = IntelHex()
            ih.fromfile(name, format="hex")

        if sig is None:
            sig = b"A" * 64

        if self.do_reboot:
            self.verify_flash(sig)
Example #7
0
    def test_write_atmega4809_eeprom_uses_hexfile_address(self):
        filename = "{}eeprom.hex".format(TESTFILE_FOLDER)
        offset = 16
        numbytes = 8
        info = Backend.get_device_info('atmega4809')
        device_memory_info = deviceinfo.DeviceMemoryInfo(info)
        eeprom_info = device_memory_info.memory_info_by_name(
            MemoryNames.EEPROM)

        mem_tuple = self._generate_memorytuple(numbytes, eeprom_info)
        write_memory_to_hex(filename, mem_tuple, offset)

        hexfile = IntelHex()
        hexfile.fromfile(filename, format='hex')

        segments = hexfile.segments()

        segment = segments[0]
        start = segment[0]
        stop = segment[1]
        hexadr = eeprom_info[DeviceMemoryInfoKeys.HEXFILE_ADDRESS]
        self.assertEqual(start,
                         hexadr + offset,
                         msg="Unexpected start hex address")
        self.assertEqual(stop,
                         hexadr + offset + numbytes,
                         msg="Unexpected stop hex address")
Example #8
0
    def write_flash_hex(self, flash_file):
        flash_hex = IntelHex()
        flash_hex.fromfile(flash_file, "hex")

        if flash_hex.maxaddr() >= self.application_size:
            raise KpBoot32u4Error(
                "Hex file doesn't fit in flash. Maximum flash address is {}, but"
                " the given file writes to address {}.".format(
                    self.application_size,
                    flash_hex.maxaddr(),
                ))

        segments = flash_hex.segments()

        # checks if a given page is a part of any of the segments in the hex
        # file
        def is_page_used(p_start, p_end):
            for (seg_start, seg_end) in segments:
                if seg_start <= p_start < seg_end:
                    return True
                if seg_start <= p_end < seg_end:
                    return True
            return False

        # flash is only page accessible, so look at each page in the hex file
        # and see if it needs to be written
        for start in range(0, self.application_size, self.page_size):
            end = start + self.page_size
            if not is_page_used(start, end):
                continue
            # Get the data for the current page and write it
            data = bytearray(flash_hex.tobinstr(start, end - 1))
            self.write_flash_page(start, data)
Example #9
0
def _compute_crc(hex_file_path):
    # Read in hex file
    new_hex_file = IntelHex()
    new_hex_file.padding = 0xFF
    new_hex_file.fromfile(hex_file_path, format='hex')

    # Get the starting and ending address
    addresses = new_hex_file.addresses()
    addresses.sort()
    start_end_pairs = list(_ranges(addresses))
    regions = len(start_end_pairs)
    assert regions == 1, ("Error - only 1 region allowed in "
                          "hex file %i found." % regions)
    start, end = start_end_pairs[0]

    # Compute checksum over the range (don't include data at location of crc)
    size = end - start + 1
    crc_size = size - 4
    data = new_hex_file.tobinarray(start=start, size=crc_size)
    data_crc32 = binascii.crc32(data) & 0xFFFFFFFF

    # Grab the crc from the image
    embedded_crc32 = (((new_hex_file[end - 3] & 0xFF) << 0) |
                      ((new_hex_file[end - 2] & 0xFF) << 8) |
                      ((new_hex_file[end - 1] & 0xFF) << 16) |
                      ((new_hex_file[end - 0] & 0xFF) << 24))
    return data_crc32, embedded_crc32
Example #10
0
def read_memories_from_hex(filename, device_memory_info):
    """
    Read the content of a hexfile

    :param filename: Name/path of hex file to read from
    :param device_memory_info: DeviceMemoryInfo instance for the device the hex file is intended for
    :returns: list of namedtuples with three fields: data, offset and memory_info.  data contains a byte array
        of raw data bytes, offset is the start address within the memory the data starts at and memory_info
        is a dictionary with the memory info as defined in pymcuprog.deviceinfo.deviceinfo
    """
    hexfile = IntelHex()
    hexfile.fromfile(filename, format='hex')

    memory_segments = []
    for segment in hexfile.segments():
        start = segment[0]
        stop = segment[1]

        subsegment_start = start
        subsegment_stop = start
        while subsegment_stop < stop:
            current_memory_info = device_memory_info.memory_info_by_address(
                subsegment_start, DeviceMemoryInfoKeys.HEXFILE_ADDRESS,
                DeviceMemoryInfoKeys.HEXFILE_SIZE)

            if current_memory_info is None:
                raise IndexError(
                    "Hexfile contains data at hex address 0x{:X} which is outside any memory"
                    .format(subsegment_start))

            current_hexfile_address = current_memory_info[
                DeviceMemoryInfoKeys.HEXFILE_ADDRESS]
            current_hexfile_size = current_memory_info[
                DeviceMemoryInfoKeys.HEXFILE_SIZE]
            subsegment_stop = current_hexfile_address + current_hexfile_size
            if stop < subsegment_stop:
                # Reached end of segment
                subsegment_stop = stop
            memory_tuple = namedtuple('MemorySegment',
                                      'data offset memory_info')

            data = hexfile.tobinarray(start=subsegment_start,
                                      end=subsegment_stop - 1)
            current_size = current_memory_info[DeviceMemoryInfoKeys.SIZE]
            if current_hexfile_size == current_size * 2:
                # There are phantom bytes in the hexfile (PIC16 EEPROM), so every 2nd byte should be removed
                data = remove_phantom_bytes(data)

            memory_tuple.data = data
            memory_tuple.memory_info = current_memory_info
            memory_tuple.offset = subsegment_start - current_hexfile_address

            memory_segments.append(copy.deepcopy(memory_tuple))

            subsegment_start = subsegment_stop

    return memory_segments
Example #11
0
 def _loadhex(self, fw: Union[str, IO]) -> None:
     ih = IntelHex()
     ih.fromfile(fw, format='hex')
     self.fw = bytearray(ih.tobinstr())
     if self.base is None:
         self.base = ih.minaddr()
     else:
         if self.base != ih.minaddr():
             raise ValueError('inconsistent base address')
Example #12
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 #13
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 #14
0
    def write_eeprom_hex(self, eep_file):
        eep_hex = IntelHex()
        eep_hex.fromfile(eep_file, "hex")

        segments = eep_hex.segments()

        # eeprom is byte addressable, so write all the bytes in each segment
        for (start, end) in segments:
            data = bytearray(eep_hex.tobinstr(start, end - 1))
            self.write_eeprom(start, data)
Example #15
0
 def from_hex(self, filename, offset):
     ih = IntelHex()
     ih.fromfile(filename, format='hex')
     self.__cycles_number = ih[offset] * 256 + ih[offset + 1]
     cmd_number = ih[offset + 2]
     offset += 3
     self.__commands = []
     for i in range(0, cmd_number):
         (cmd, offset) = self.__hex_to_cmd(ih, offset)
         self.__commands.append(cmd)
Example #16
0
    def test_write_and_read_eeprom_pic16f18446(self):
        """
        This test exercises the write_memory_to_hex function (single segment)
        """
        filename = "{}eeprom.hex".format(TESTFILE_FOLDER)
        offset = 0
        info = Backend.get_device_info('pic16f18446')
        device_memory_info = deviceinfo.DeviceMemoryInfo(info)
        eeprom_info = device_memory_info.memory_info_by_name(
            MemoryNames.EEPROM)
        numbytes_eeprom = eeprom_info[DeviceMemoryInfoKeys.SIZE]

        mem_tuple_eeprom = self._generate_memorytuple(numbytes_eeprom,
                                                      eeprom_info)

        write_memory_to_hex(filename, mem_tuple_eeprom, offset)
        segments_read = read_memories_from_hex(filename, device_memory_info)

        for segment_read in segments_read:
            memory_name = segment_read.memory_info[DeviceMemoryInfoKeys.NAME]
            # When writing multiple segments all will start from relative offset 0
            self.assertEqual(segment_read.offset,
                             offset,
                             msg="Incorrect offset for {}".format(memory_name))
            if memory_name == MemoryNames.EEPROM:
                self.assertEqual(segment_read.data,
                                 mem_tuple_eeprom.data,
                                 msg="Incorrect EEPROM data")
            else:
                self.fail("Unexpected memory: {}".format(memory_name))

        # Sanity check to see that the phantom bytes actually were added by the write to hex
        hexfile = IntelHex()
        hexfile.fromfile(filename, format='hex')
        hexadr = eeprom_info[DeviceMemoryInfoKeys.HEXFILE_ADDRESS]
        data_read = hexfile.tobinarray(start=hexadr,
                                       end=hexadr + numbytes_eeprom * 2 - 1)
        self.assertEqual(
            len(data_read),
            numbytes_eeprom * 2,
            msg=
            "EEPROM should include twice as many bytes as was written due to the phantom bytes"
        )
        index = 0
        for index in range(numbytes_eeprom):
            self.assertEqual(
                data_read[index * 2],
                mem_tuple_eeprom.data[index],
                msg="Incorrect EEROM data in written hex at index {}".format(
                    index * 2))
            self.assertEqual(
                data_read[index * 2 + 1],
                0x00,
                msg="Incorrect phantom byte in written hex at index {}".format(
                    index * 2 + 1))
Example #17
0
    def to_eep_file(self, eep_file_name):
        """Save the configuration to an EEPROM-file."""
        hex_file = IntelHex()

        # Change any existing files instead of overwriting them.
        if os.path.isfile(eep_file_name):
            hex_file.fromfile(eep_file_name, format='hex')

        data = self.to_bytes(crc=True)
        hex_file.puts(Config.START_ADDRESS, data)
        hex_file.write_hex_file(eep_file_name, byte_count=0x20)
Example #18
0
def sign_firmware_for_version(sk_name,
                              hex_file,
                              APPLICATION_END_PAGE,
                              PAGES=128):
    # Maybe this is not the optimal module...

    import base64
    import binascii
    from hashlib import sha256

    from ecdsa import SigningKey
    from intelhex import IntelHex

    sk = SigningKey.from_pem(open(sk_name).read())
    fw = open(hex_file, "r").read()
    fw = base64.b64encode(fw.encode())
    fw = helpers.to_websafe(fw.decode())
    ih = IntelHex()
    ih.fromfile(hex_file, format="hex")
    # start of firmware and the size of the flash region allocated for it.
    # TODO put this somewhere else.
    START = ih.segments()[0][0]
    # keep in sync with targets/stm32l432/src/memory_layout.h
    PAGE_SIZE = 2048
    END = (0x08000000 + ((PAGES - APPLICATION_END_PAGE) * PAGE_SIZE)) - 8

    ih = IntelHex(hex_file)
    # segs = ih.segments()
    arr = ih.tobinarray(start=START, size=END - START)

    im_size = END - START

    print("im_size: ", im_size)
    print("firmware_size: ", len(arr))

    byts = (arr).tobytes() if hasattr(arr, "tobytes") else (arr).tostring()
    h = sha256()
    h.update(byts)
    sig = binascii.unhexlify(h.hexdigest())
    print("hash", binascii.hexlify(sig))
    sig = sk.sign_digest(sig)

    print("sig", binascii.hexlify(sig))

    sig = base64.b64encode(sig)
    sig = helpers.to_websafe(sig.decode())

    # msg = {'data': read()}
    msg = {"firmware": fw, "signature": sig}
    return msg
Example #19
0
    def from_eep_file(cls, eep_file_name):
        """Create an ErrorLog instance with the content from the EEPROM-file."""
        hex_file = IntelHex()
        hex_file.fromfile(eep_file_name, format='hex')

        log = cls()
        for addr in range(ErrorLog._START_ADDRESS, ErrorLog._END_ADDRESS, ErrorMessage.size()):
            data = hex_file.gets(addr, ErrorMessage.size())

            error_message = ErrorMessage.from_bytes(data)
            if error_message:
                log.append(error_message)

        return log
Example #20
0
    def program_file(self, name):

        if name.lower().endswith(".json"):
            data = json.loads(open(name, "r").read())
            fw = base64.b64decode(
                helpers.from_websafe(data["firmware"]).encode())
            sig = base64.b64decode(
                helpers.from_websafe(data["signature"]).encode())
            ih = IntelHex()
            tmp = tempfile.NamedTemporaryFile(delete=False)
            tmp.write(fw)
            tmp.seek(0)
            tmp.close()
            ih.fromfile(tmp.name, format="hex")
        else:
            if not name.lower().endswith(".hex"):
                print('Warning, assuming "%s" is an Intel Hex file.' % name)
            sig = None
            ih = IntelHex()
            ih.fromfile(name, format="hex")

        if self.exchange == self.exchange_hid:
            chunk = 2048
        else:
            chunk = 240

        seg = ih.segments()[0]
        size = seg[1] - seg[0]
        total = 0
        t1 = time.time() * 1000
        print("erasing firmware...")
        for i in range(seg[0], seg[1], chunk):
            s = i
            e = min(i + chunk, seg[1])
            data = ih.tobinarray(start=i, size=e - s)
            self.write_flash(i, data)
            total += chunk
            progress = total / float(size) * 100
            sys.stdout.write("updating firmware %.2f%%...\r" % progress)
        sys.stdout.write("updated firmware 100%             \r\n")
        t2 = time.time() * 1000
        print("time: %.2f s" % ((t2 - t1) / 1000.0))

        if sig is None:
            sig = b"A" * 64

        if self.do_reboot:
            self.verify_flash(sig)

        return sig
Example #21
0
def LoadHex(file):
    
    try:
        # Load the hex file
        ih=IntelHex()
        ih.fromfile(file,format='hex')

        bf = ih.tobinarray() #convert to bin array

    except ValueError:
        print(f'Error {ValueError} in LoadHex function with argument : {file}')
        CleanExit()
    
    return bf
Example #22
0
class IHexFile:
    def __init__(self):
        self.ihex = IntelHex()
        self.fileName = "None Loaded"
        self.fileLoaded = False
        self.faultList = {}

    def loadFromFile(self, infilename):
        self.ihex.fromfile(infilename, format='hex')
        self.fileName = infilename
        self.fileLoaded = True
        self.minAddress = self.ihex.minaddr()
        self.maxAddress = self.ihex.maxaddr()
        return "OK"

    def writeToFile(self, outfilename):
        if not self.fileLoaded:
            return "No File Loaded"
        else:
            self.ihex.write_hex_file(outfilename)
            return "OK"

    def writeHexDump(self, fname):
        if not self.fileLoaded:
            return "No File Loaded"
        else:
            f = open(fname, 'w')
            self.ihex.dump(f)
            f.close()
            return "Wrote " + fname

    def faultInjection(self, address, value):
        if not self.fileLoaded:
            return "No Hex File Loaded"
        elif address > self.maxAddress or address < self.minAddress:
            return "Address out of Range"
        else:
            self.ihex[address] = value
            self.ihex[address + 1] = value
            self.faultList[address] = value
            #How to handle Low and High Byte!!!
            return "OK"

    def viewFaults(self):
        if not self.fileLoaded:
            return "No Hex File Loaded"
        else:
            return self.faultList
Example #23
0
    def program_file(self, name):

        if name.lower().endswith('.json'):
            data = json.loads(open(name, 'r').read())
            fw = base64.b64decode(from_websafe(data['firmware']).encode())
            sig = base64.b64decode(from_websafe(data['signature']).encode())
            ih = IntelHex()
            tmp = tempfile.NamedTemporaryFile(delete=False)
            tmp.write(fw)
            tmp.seek(0)
            tmp.close()
            ih.fromfile(tmp.name, format='hex')
        else:
            if not name.lower().endswith('.hex'):
                print('Warning, assuming "%s" is an Intel Hex file.' % name)
            sig = None
            ih = IntelHex()
            ih.fromfile(name, format='hex')

        if self.exchange == self.exchange_hid:
            chunk = 2048
        else:
            chunk = 240

        seg = ih.segments()[0]
        size = seg[1] - seg[0]
        total = 0
        t1 = time.time() * 1000
        print('erasing...')
        for i in range(seg[0], seg[1], chunk):
            s = i
            e = min(i + chunk, seg[1])
            data = ih.tobinarray(start=i, size=e - s)
            self.write_flash(i, data)
            total += chunk
            progress = total / float(size) * 100
            sys.stdout.write('downloading %.2f%%...\r' % progress)
        sys.stdout.write('downloaded 100%             \r\n')
        t2 = time.time() * 1000
        print('time: %.2f s' % ((t2 - t1) / 1000.0))

        print('Verifying...')
        if self.do_reboot:
            if sig is not None:
                self.verify_flash(sig)
            else:
                self.verify_flash(b'A' * 64)
Example #24
0
def load_fw(path):
    """Open firmware file and return a binary string."""
    fname = os.path.realpath(path)
    exists = os.path.isfile(fname)
    if not exists or not os.access(fname, os.R_OK):
        _LOGGER.error('Firmware path %s does not exist or is not readable',
                      path)
        return None
    try:
        intel_hex = IntelHex()
        with open(path, 'r') as file_handle:
            intel_hex.fromfile(file_handle, format='hex')
        return intel_hex.tobinstr()
    except (IntelHexError, TypeError, ValueError) as exc:
        _LOGGER.error('Firmware not valid, check the hex file at %s: %s', path,
                      exc)
        return None
def combine(bootloader_fn, app_fn, app_addr, hdr_addr, bootloader_addr,
            output_fn, version, no_bootloader):
    # read bootloader
    bootloader_format = bootloader_fn.split('.')[-1]
    bootloader = IntelHex()
    if not no_bootloader:
        if bootloader_format == 'hex':
            bootloader.fromfile(bootloader_fn, bootloader_format)
        elif bootloader_format == 'bin':
            bootloader.loadbin(bootloader_fn, bootloader_addr)
        else:
            print('Bootloader format can only be .bin or .hex')
            exit(-1)

    # read application
    app_format = app_fn.split('.')[-1]
    app = IntelHex()
    if app_format == 'hex':
        app.fromfile(app_fn, app_format)
    elif app_format == 'bin':
        app.loadbin(app_fn, app_addr)
    else:
        print('Application format can only be .bin or .hex')
        exit(-1)

    # create firmware header
    header = IntelHex()
    fw_header = create_header(app.tobinstr(), version)
    header.puts(hdr_addr, fw_header)

    # combine
    output_format = output_fn.split('.')[-1]
    output = IntelHex()
    if not no_bootloader:
        print("Writing bootloader to address 0x%08x-0x%08x." %
              (bootloader.addresses()[0], bootloader.addresses()[-1]))
        output.merge(bootloader, overlap='error')
    print("Writing header to address 0x%08x-0x%08x." %
          (header.addresses()[0], header.addresses()[-1]))
    output.merge(header, overlap='error')
    print("Writing application to address 0x%08x-0x%08x." %
          (app.addresses()[0], app.addresses()[-1]))
    output.merge(app, overlap='error')

    # write output file
    output.tofile(output_fn, format=output_format)
def dump_sections(args):
    ''' Find all sections in the image file and dump their name and offset '''
    try:
        hexfile = IntelHex()
        hexfile.fromfile(args.image_file[0], format='hex')
        content = hexfile.tobinarray()

    except HexRecordError:
        # Not a valid HEX file, so assume we are dealing with a binary image
        args.image_file[0].seek(0)
        content = args.image_file[0].read(MAX_FILE_SIZE + 1)

    if len(content) > MAX_FILE_SIZE:
        print('ERROR: Binary image file larger than 16 kBytes')
        sys.exit(1)

    available_sections = dict()
    for section_name in SECTIONS.values():
        available_sections[section_name] = 0

    error_found = False

    section_name, version, offset = find_section(content, 0)
    while section_name is not None:
        try:
            available_sections[section_name] += 1
            if args.verbose:
                print('Found "{:s}", version {:d} at offset 0x{:x}'.format(
                    section_name, version, offset))
        except KeyError:
            print('ERROR: Unknown section {}'.format(section_name))
            error_found = True

        section_name, version, offset = find_section(content, offset + 1)

    for section_name in available_sections:
        if available_sections[section_name] == 0:
            error_found = True
            print('ERROR: Section "{}" is missing'.format(section_name))
        elif available_sections[section_name] > 1:
            error_found = True
            print('ERROR: Multiple "{}" sections found'.format(section_name))

    if error_found:
        sys.exit(1)
Example #27
0
    def slurp(self, filename):
        if filename.endswith('.bit') or filename.endswith('.bin'):
            with open(filename, 'rb') as f:
                return f.read()

        elif filename.endswith('.hex'):
            with open(filename, 'rb') as f:
                return bytes("".join(chr(int(i, 16)) for i in f.read().split()))

        elif filename.endswith('.mcs'):
            ih = IntelHex()
            ih.fromfile(filename, format='hex')
            bitstream = ih.tobinstr(start=0, end=ih.maxaddr())
            bitstream = _mirror_each_byte(bitstream)
            return bitstream

        else:
            raise ValueError('Unknown bitstream extension')
Example #28
0
    def from_eep_file(cls, eep_file_name):
        """Create an Config instance with data from an EEPROM-file."""
        hex_file = IntelHex()
        hex_file.fromfile(eep_file_name, format='hex')

        data = hex_file.gets(Config.START_ADDRESS, Config.size())
        parameters = struct.unpack(Config._FMT_CRC, data)

        stored_crc = parameters[-1]
        # Remove the two last bytes to exclude the stored CRC value from the
        # CRC calculation.
        calculated_crc = Config.calculate_crc(data[:-2])

        if stored_crc != calculated_crc:
            raise ConfigCrcException('CRC mismatch')

        # Remove last element with the stored CRC since it's only used for
        # validation.
        return cls(*parameters[:-1])
Example #29
0
def check_fw(path):
    """Check that firmware is valid and return dict with binary data."""
    try:
        intel_hex = IntelHex()
        with open(path, 'r') as file_handle:
            intel_hex.fromfile(file_handle, format='hex')
        bin_string = intel_hex.tobinstr()
    except (IntelHexError, TypeError, ValueError) as exception:
        _LOGGER.error(exception)
        return
    pads = len(bin_string) % 128  # 128 bytes per page for atmega328
    for _ in range(128 - pads):  # pad up to even 128 bytes
        bin_string += b'\xff'
    fware = {
        'path': path,
        'blocks': int(len(bin_string) / FIRMWARE_BLOCK_SIZE),
        'crc': compute_crc(bin_string),
        'data': bin_string,
    }
    return fware
Example #30
0
def read_image_file(image_file):
    '''
    Read the given image file. First we try to read the file as Intel-hex, if
    that fails we assume it is a binary image.

    The file handle is closed before returning the IntelHex object containing
    the image data.
    '''

    hexfile = IntelHex()
    try:
        hexfile.fromfile(image_file, format='hex')

    except HexRecordError:
        # Not a valid HEX file, so assume we are dealing with a binary image
        image_file.seek(0)
        hexfile.fromfile(image_file, format='bin')

    image_file.close()
    return hexfile
Example #31
0
def GetHexCrc(file):
    # convert hex to bin
    ih = IntelHex()
    ih.fromfile(file, format='hex')
    bf = ih.tobinarray()

    #pad the array (flash size) for CRC calculation 220kb
    while len(bf) < (220 * 1024):
        bf.append(255)

    # calculate checksum for APP_HEX
    crc32_func = crcmod.mkCrcFun(int(0x104c11db7),
                                 initCrc=int(0xffffffff),
                                 rev=False,
                                 xorOut=0)

    checksum_val = crc32_func(bytearray(bf))
    checksum_val = f'0x{checksum_val:X}'

    return checksum_val
Example #32
0
def read_image_file(image_file):
    '''
    Read the given image file. First we try to read the file as Intel-hex, if
    that fails we assume it is a binary image.

    The file handle is closed before returning the IntelHex object containing
    the image data.
    '''

    hexfile = IntelHex()
    try:
        hexfile.fromfile(image_file, format='hex')

    except HexRecordError:
        # Not a valid HEX file, so assume we are dealing with a binary image
        image_file.seek(0)
        hexfile.fromfile(image_file, format='bin')

    image_file.close()
    return hexfile
Example #33
0
class RomMemory:
    """docstring for RomMemory"""
    pagesize = 256
    numpages = 128
    size = pagesize * numpages

    def __init__(self):
        self.rom = IntelHex()
        self.size = 0

    def OpenHex(self, filename):
        self.rom = IntelHex()
        try:
            self.rom.fromfile(filename, format='hex')
        except:
            return None

        self.size = len(self.rom.tobinarray())
        return True

    def OpenBin(self, filename):
        self.rom = IntelHex()

        try:
            self.rom = fromfile(filename, format='bin')
        except:
            return None

        self.size = len(self.rom.tobinarray())

        return True

    def Print(self):
        self.rom.dump()

    def ReadPage(self, numpage):
        return self.rom.tobinarray(start=numpage * self.pagesize,
                                   size=self.pagesize)

    def ReadBytes(self, address, count):
        return self.rom.tobinarray(start=address, size=count)
Example #34
0
def combine(bootloader_fn, app_fn, app_addr, hdr_addr, bootloader_addr,
            output_fn, version, no_bootloader):
    ih = IntelHex()

    bootloader_format = bootloader_fn.split('.')[-1]

    # write the bootloader
    if not no_bootloader:
        print("Using bootloader %s" % bootloader_fn)
        if bootloader_format == 'hex':
            print("Loading bootloader from hex file.")
            ih.fromfile(bootloader_fn, format=bootloader_format)
        elif bootloader_format == 'bin':
            print("Loading bootloader to address 0x%08x." % bootloader_addr)
            ih.loadbin(bootloader_fn, offset=bootloader_addr)
        else:
            print('Bootloader format can only be .bin or .hex')
            exit(-1)

    # write firmware header
    app_format = app_fn.split('.')[-1]
    if app_format == 'bin':
        with open(app_fn, 'rb') as fd:
            app_blob = fd.read()
    elif app_format == 'hex':
        application = IntelHex(app_fn)
        app_blob = application.tobinstr()
    FirmwareHeader = create_header(app_blob, version)
    print("Writing header to address 0x%08x." % hdr_addr)
    ih.puts(hdr_addr, FirmwareHeader)

    # write the application
    if app_format == 'bin':
        print("Loading application to address 0x%08x." % app_addr)
        ih.loadbin(app_fn, offset=app_addr)
    elif app_format == 'hex':
        print("Loading application from hex file")
        ih.fromfile(app_fn, format=app_format)

    # output to file
    ih.tofile(output_fn, format=output_fn.split('.')[-1])
Example #35
0
def main():
    args = parser.parse_args()
    base_hex = IntelHex()
    # Merge in hex files
    for file_name in args.hex:
        new_hex_data = IntelHex()
        print "opening file %s" % file_name
        new_hex_data.fromfile(file_name, format='hex')
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Merge in binary files
    for file_name, addr_str in args.bin:
        offset = int(addr_str, 0)
        new_hex_data = IntelHex()
        new_hex_data.loadbin(file_name, offset=offset)
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Write out data
    print_hex_info(args.output_file, base_hex)
    with open(args.output_file, 'wb') as output_file:
        base_hex.tofile(output_file, 'hex')
Example #36
0
def main():
    args = parser.parse_args()
    base_hex = IntelHex()
    # Merge in hex files
    for file_name in args.hex:
        new_hex_data = IntelHex()
        print "opening file %s" % file_name
        new_hex_data.fromfile(file_name, format='hex')
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Merge in binary files
    for file_name, addr_str in args.bin:
        offset = int(addr_str, 0)
        new_hex_data = IntelHex()
        new_hex_data.loadbin(file_name, offset=offset)
        print_hex_info(file_name, new_hex_data)
        base_hex = merge_hex(base_hex, new_hex_data)
    # Write out data
    print_hex_info(args.output_file, base_hex)
    with open(args.output_file, 'wb') as output_file:
        base_hex.tofile(output_file, 'hex')
Example #37
0
    def _download(self, addr, filename):
        """Downloads a binary file to the target system
        
        Args:
            addr: Start address where the binary file is stored
            filename: File name of the binary file
        """

        import platform
        if platform.architecture()[0] == '64bit':        
            filenamebuf = c_char_p(filename.encode('UTF-8'))
            c_addr = c_uint32(addr)
            self.jl.JLINK_DownloadFile(filenamebuf, c_addr)
        else:
            from intelhex import IntelHex
            ih = IntelHex()
            
            extension = os.path.splitext(filename)[1][1:]
            ih.fromfile(filename,format=extension)
            
            for (a, d) in zip(ih.addresses(), ih.tobinarray()):
                self.wr_mem(8, addr+a, d)
Example #38
0
def get_firmware_object(sk_name, hex_file):
    from ecdsa import SigningKey, NIST256p

    sk = SigningKey.from_pem(open(sk_name).read())
    fw = open(hex_file, "r").read()
    fw = base64.b64encode(fw.encode())
    fw = to_websafe(fw.decode())
    ih = IntelHex()
    ih.fromfile(hex_file, format="hex")
    # start of firmware and the size of the flash region allocated for it.
    # TODO put this somewhere else.
    START = ih.segments()[0][0]
    END = (0x08000000 + ((128 - 19) * 2048)) - 8

    ih = IntelHex(hex_file)
    segs = ih.segments()
    arr = ih.tobinarray(start=START, size=END - START)

    im_size = END - START

    print("im_size: ", im_size)
    print("firmware_size: ", len(arr))

    byts = (arr).tobytes() if hasattr(arr, "tobytes") else (arr).tostring()
    h = sha256()
    h.update(byts)
    sig = binascii.unhexlify(h.hexdigest())
    print("hash", binascii.hexlify(sig))
    sig = sk.sign_digest(sig)

    print("sig", binascii.hexlify(sig))

    sig = base64.b64encode(sig)
    sig = to_websafe(sig.decode())

    # msg = {'data': read()}
    msg = {"firmware": fw, "signature": sig}
    return msg
Example #39
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--scan",
                        help="Scans for Bluetooth low energy devices",
                        action="store_true")
    parser.add_argument(
        "--device",
        help="Connects to given bluetooth device and give OTA information")
    parser.add_argument(
        "--program",
        help=
        "Writes firmware image onto device. Due to erase procedure, you might get"
        +
        "an error on a non-empty device and have to try the same command a second time."
    )
    args = parser.parse_args()
    ota_service = None

    if args.scan:
        scanner = Scanner()
        devices = scanner.scan(5.0)

        for dev in devices:
            print("Device %s (%s), RSSI=%d dB, connectable=%r" %
                  (dev.addr, dev.addrType, dev.rssi, dev.connectable))
            for (adtype, desc, value) in dev.getScanData():
                print("  %s = %s" % (desc, value))

    if args.device:
        peripheral = Peripheral(args.device, ADDR_TYPE_RANDOM)
        ota_service = Ota(peripheral)

    if args.device and args.program:
        ih = IntelHex()
        ih.fromfile(args.program, format='hex')
        ota_service.program(ih)
Example #40
0
    s += "WIDTH = %d;\n" % data_width
    s += "ADDRESS_RADIX = %s;\n" % addr_radix
    s += "DATA_RADIX = %s;\n" % data_radix
    return s


def mif_data(data={}, minaddr=MIN_ADDR, maxaddr=MAX_ADDR, gap_fill=GAP_FILL):
    s = "CONTENT\n"
    s += "BEGIN\n"
    s += "[%x..%x] : %x;\n" % (minaddr, maxaddr - 1, gap_fill)
    for k in data.keys():
        if isinstance(k, Number):
            s += "%x : %x;\n" % (k, data[k])
    s += "END;\n"
    return s


if __name__ == "__main__":
    ih = IntelHex()
    ih.fromfile(sys.stdin, format="hex")
    data = ih.todict()

    for a in range(0, 4096, 4):
        if data.has_key(a):
            d = data[a] + (data[a + 1] << 8) + (data[a + 2] << 16) + (data[a + 3] << 24)
            del data[a], data[a + 1], data[a + 2], data[a + 3]
            data[a] = d

    print mif_header(32, 0, 4096)
    print mif_data(data, 0, 4096, 0x00000013)
Example #41
0
     filename = name + ".hex"
 if not exists(filename):
   print "Error: You must specify a filename.\n"
   showUsage()
 # Set up the device interface
 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:
Example #42
0
def sendblock(command,payload):
	if len(payload)!=16:
		raise Exception('Payload length incorrect')

	magicnumber=0x59

	checksum=(magicnumber-(sum(payload)+command))&0xff
	ser.write(payload)
	ser.write([checksum])
	ser.write([command])

ser=serial.Serial('com6',57600,timeout=0.1)

ih=IntelHex()
ih.fromfile('Blinky104.hex',format='hex')

while True:
	try:
		print("Connecting...")
		""" send dummy packet to sync RX/TX """
		sendblock(0x00,[1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8])
		ser.timeout=0.05
		ackdat=ser.read(1)

		if len(ackdat)==1:
			print("\t",ackdat)
		else:
			print("timeout")
			continue