Example #1
0
 def save_image(self, path):
     if self.data_buffer:
         if path.lower().endswith(".bin"):
             with open(path, "wb") as f:
                 f.write(self.data_buffer)
                 f.close()
         elif path.lower().endswith(".hex"):
             ihex = IntelHex()
             ihex.frombytes(self.data_buffer, 0)
             ihex.start_addr = self.FlashStartAddress
             try:
                 ihex.tofile(path, format="hex")
             except Exception as e:
                 wx.MessageBox(
                     "Could not write into file: %s\n\n%s" % (path, str(e)), "ERROR", wx.OK | wx.ICON_ERROR
                 )
         elif path.lower().endswith((".s19", ".srec")):
             srec = SRecFile()
             srec.header = "KBOOT"
             srec.start_addr = self.FlashStartAddress
             srec.data = self.data_buffer
             try:
                 srec.save(path)
             except Exception as e:
                 wx.MessageBox(
                     "Could not write into file: %s\n\n%s" % (path, str(e)), "ERROR", wx.OK | wx.ICON_ERROR
                 )
         else:
             wx.MessageBox("Not supported file Type !", "ERROR", wx.OK | wx.ICON_ERROR)
     else:
         wx.MessageBox("No data to save", "INFO", wx.OK | wx.ICON_INFORMATION)
def append_validation_data(signature, input_file, public_key, offset,
                           output_hex, output_bin, magic_value):
    ih = IntelHex(input_file)
    ih.start_addr = None  # OBJCOPY incorrectly inserts x86 specific records, remove the start_addr as it is wrong.

    minimum_offset = ((ih.maxaddr() // 4) + 1) * 4
    if offset != 0 and offset < minimum_offset:
        raise RuntimeError(
            f'Incorrect offset, must be bigger than {hex(minimum_offset)}')

    # Parse comma-separated string of uint32s into hex string. Each is encoded in little-endian byte order
    parsed_magic_value = b''.join(
        [struct.pack('<I', int(m, 0)) for m in magic_value.split(',')])

    validation_data = get_validation_data(signature_bytes=signature,
                                          input_hex=ih,
                                          public_key=public_key,
                                          magic_value=parsed_magic_value)
    validation_data_hex = IntelHex()

    # If no offset is given, append metadata right after input hex file (word aligned).
    if offset == 0:
        offset = minimum_offset

    validation_data_hex.frombytes(validation_data, offset)

    ih.merge(validation_data_hex)
    ih.write_hex_file(output_hex)

    if output_bin:
        ih.tofile(output_bin.name, format='bin')
def sign_and_append_validation_data(pem_file, input_file, offset, output_file,
                                    magic_value, pk_hash_len):
    ih = IntelHex(input_file)
    ih.start_addr = None  # OBJCOPY incorrectly inserts x86 specific records, remove the start_addr as it is wrong.

    minimum_offset = ((ih.maxaddr() // 4) + 1) * 4
    if offset != 0 and offset < minimum_offset:
        raise RuntimeError("Incorrect offset, must be bigger than %x" %
                           minimum_offset)

    # Parse comma-separated string of uint32s into hex string. Each in is encoded
    # in little-endian byte order
    parsed_magic_value = b''.join(
        [struct.pack("<I", int(m, 0)) for m in magic_value.split(",")])

    validation_data = get_validation_data(pem_file=pem_file,
                                          input_hex=ih,
                                          magic_value=parsed_magic_value,
                                          pk_hash_len=pk_hash_len)
    validation_data_hex = IntelHex()

    # If no offset is given, append metadata right after input hex file (word aligned).
    if offset == 0:
        offset = minimum_offset

    validation_data_hex.frombytes(validation_data, offset)

    ih.merge(validation_data_hex)
    ih.write_hex_file(output_file)
Example #4
0
def generate_provision_hex_file(s0_address, s1_address, hashes,
                                provision_address, output, max_size,
                                num_counter_slots_version):
    # Add addresses
    provision_data = struct.pack('III', s0_address, s1_address, len(hashes))
    for mhash in hashes:
        provision_data += struct.pack('I', 0xFFFFFFFF)  # Invalidation token
        provision_data += mhash

    num_counters = 1 if num_counter_slots_version > 0 else 0
    provision_data += struct.pack('H', 1)  # Type "counter collection"
    provision_data += struct.pack('H', num_counters)

    if num_counters == 1:
        if num_counter_slots_version % 2 == 1:
            num_counter_slots_version += 1
            print(
                f'Monotonic counter slots rounded up to {num_counter_slots_version}'
            )
        provision_data += struct.pack('H', 1)  # counter description
        provision_data += struct.pack('H', num_counter_slots_version)

    assert (len(provision_data) + (2 * num_counter_slots_version)
            ) <= max_size, """Provisioning data doesn't fit.
Reduce the number of public keys or counter slots and try again."""

    ih = IntelHex()
    ih.frombytes(provision_data, offset=provision_address)
    ih.write_hex_file(output)
Example #5
0
 def save(self, path, hex_addr=None):
     """Save an image from a given file"""
     ext = os.path.splitext(path)[1][1:].lower()
     if ext == INTEL_HEX_EXT:
         # input was in binary format, but HEX needs to know the base addr
         if self.base_addr is None and hex_addr is None:
             raise click.UsageError("No address exists in input file "
                                    "neither was it provided by user")
         h = IntelHex()
         if hex_addr is not None:
             self.base_addr = hex_addr
         h.frombytes(bytes=self.payload, offset=self.base_addr)
         if self.pad:
             trailer_size = self._trailer_size(self.align, self.max_sectors,
                                               self.overwrite_only,
                                               self.enckey,
                                               self.save_enctlv,
                                               self.enctlv_len)
             trailer_addr = (self.base_addr + self.slot_size) - trailer_size
             padding = bytes([self.erased_val] *
                             (trailer_size - len(boot_magic))) + boot_magic
             h.puts(trailer_addr, padding)
         h.tofile(path, 'hex')
     else:
         if self.pad:
             self.pad_to(self.slot_size)
         with open(path, 'wb') as f:
             f.write(self.payload)
Example #6
0
 def save_image(self, path):
     if self.data_buffer:
         if path.lower().endswith('.bin'):
             with open(path, "wb") as f:
                 f.write(self.data_buffer)
                 f.close()
         elif path.lower().endswith('.hex'):
             ihex = IntelHex()
             ihex.frombytes(self.data_buffer, 0)
             ihex.start_addr = self.FlashStartAddress
             try:
                 ihex.tofile(path, format='hex')
             except Exception as e:
                 wx.MessageBox(
                     "Could not write into file: %s\n\n%s" % (path, str(e)),
                     'ERROR', wx.OK | wx.ICON_ERROR)
         elif path.lower().endswith(('.s19', '.srec')):
             srec = SRecFile()
             srec.header = "KBOOT"
             srec.start_addr = self.FlashStartAddress
             srec.data = self.data_buffer
             try:
                 srec.save(path)
             except Exception as e:
                 wx.MessageBox(
                     "Could not write into file: %s\n\n%s" % (path, str(e)),
                     'ERROR', wx.OK | wx.ICON_ERROR)
         else:
             wx.MessageBox('Not supported file Type !', 'ERROR',
                           wx.OK | wx.ICON_ERROR)
     else:
         wx.MessageBox('No data to save', 'INFO',
                       wx.OK | wx.ICON_INFORMATION)
Example #7
0
def generate_provision_hex_file(s0_address, s1_address, hashes, provision_address, output):
    # Add addresses
    provision_data = struct.pack('III', s0_address, s1_address, len(hashes))
    provision_data += b''.join(hashes)

    ih = IntelHex()
    ih.frombytes(provision_data, offset=provision_address)
    ih.write_hex_file(output)
Example #8
0
    def save(self, path):
        """Save an image from a given file"""
        ext = os.path.splitext(path)[1][1:].lower()

        if ext != INTEL_HEX_EXT:
            raise Exception("Only hex input file supported")

        h = IntelHex()
        h.frombytes(bytes=self.payload, offset=self.load_address)
        h.tofile(path, 'hex')
Example #9
0
def generate_provision_hex_file(s0_address, s1_address, hashes, provision_address, output):
    # Add addresses
    provision_data = struct.pack('III', s0_address, s1_address, len(hashes))
    for mhash in hashes:
        provision_data += struct.pack('I', 0xFFFFFFFF) # Invalidation token
        provision_data += mhash

    ih = IntelHex()
    ih.frombytes(provision_data, offset=provision_address)
    ih.write_hex_file(output)
Example #10
0
def test_read_micropython(mock_read_flash):
    """Test read_micropython() with default arguments."""
    data_bytes = bytes([x for x in range(256)] * 4)
    intel_hex = IntelHex()
    intel_hex.frombytes(data_bytes)
    ihex_str = ihex_to_str(intel_hex)
    mock_read_flash.return_value = (0, data_bytes)

    result = cmds.read_micropython()

    assert result == ihex_str
Example #11
0
 def setUp(cls):
     random.seed(420)
     cls._bin_data = bytes([random.randint(0, 0xFF) for i in range(10000)])
     ihex = IntelHex()
     ihex.frombytes(cls._bin_data)
     hex_data = io.StringIO()
     ihex.write_hex_file(hex_data, write_start_addr=False)
     cls._hex_data = codecs.encode(hex_data.getvalue(), encoding='ascii')
     cls._args = [
         'python3', 'qpsk/encoder.py', '-s', '48000', '-y', '6000', '-b',
         '1K', '-f', '1K:40', '-a', '0', '-w', '10', '-p', '256'
     ]
Example #12
0
def patch(message_func, ihex, hexf, align=256):
    update_checksum = False
    update_metadata = False

    # calculate checksum of the program section, detect metadata
    checksum = 0
    for start, end in ihex.segments():
        if start == CY_CHECKSUM_ADDR:
            # checksum section found in the original hex
            update_checksum = True
        if start == CY_META_ADDR:
            # metadata section found in the original hex
            update_metadata = True
        if start >= CY_PROGRAM_SIZE:
            continue
        segment = ihex.tobinarray(start, end)
        checksum += sum(segment)

    # only update checksum if it was found in the original hex
    if update_checksum:
        lowchecksum = checksum & 0x0FFFF
        message_func("Calculated checksum for %s is 0x%04x" %
                     (hexf, lowchecksum))

        checksum_str = pack('>H', lowchecksum)
        ihex.frombytes(array('B', checksum_str), offset=CY_CHECKSUM_ADDR)

    # only update metadata if it was found in the original hex
    if update_metadata:
        signature = unpack(
            '>L', ihex.tobinstr(start=CY_META_SILICON_ID_ADDR, size=4))[0]
        sigcheck = pack('>L', (checksum + signature) & 0x0FFFF)
        ihex.frombytes(array('B', sigcheck), offset=CY_META_CHECKSUM_ADDR)

    # align flash segments
    align_mask = align - 1
    alignments = IntelHex()
    for start, end in ihex.segments():
        if start >= CY_PROGRAM_SIZE:
            continue
        aligned_start = start & ~align_mask
        if start != aligned_start:
            message_func("Aligning start from 0x%x to 0x%x" %
                         (start, aligned_start))
            alignments.frombytes(ihex.tobinarray(aligned_start, start - 1),
                                 aligned_start)
        aligned_end = end & ~align_mask
        if end != aligned_end:
            aligned_end += align
            message_func("Aligning end from 0x%x to 0x%x" % (end, aligned_end))
            alignments.frombytes(ihex.tobinarray(end, aligned_end - 1), end)
    ihex.merge(alignments, 'ignore')
Example #13
0
 def save(self, path):
     """Save an image from a given file"""
     ext = os.path.splitext(path)[1][1:].lower()
     if ext == INTEL_HEX_EXT:
         # input was in binary format, but HEX needs to know the base addr
         if self.slot_address is None:
             raise Exception("Input file does not provide a slot address")
         h = IntelHex()
         h.frombytes(bytes=self.payload, offset=self.slot_address)
         h.tofile(path, 'hex')
     else:
         with open(path, 'wb') as f:
             f.write(self.payload)
def patch_file(in_file, out_file, hex_file):
    with open(in_file, 'rb') as i:
        data = i.read()
        padding = bytes([0xFF])
        data = data.ljust(BL_SIZE, padding)
        data = patch_data(data)
        with open(out_file, 'wb') as df:
            df.write(data)

        if len(hex_file) > 0:
            from intelhex import IntelHex
            out = IntelHex()
            out.frombytes(data, offset=BL_START)
            out.write_hex_file(hex_file)
Example #15
0
    def generate(self, workspace, outBin=None, outHex=None, skip=False):
        self.generated = False
        self.generatedBinary = None
        if self.valid:
            try:
                p = workspace.getParameters(self.parameters)

                if p is not None:
                    if p.generateBinary(workspace, self):
                        if outBin is not None:
                            path = os.path.join(outBin, self.parameters)
                            if not os.path.isdir(path):
                                os.makedirs(path)

                            self.destinationBin = os.path.join(
                                path, self.name + ".bin")

                            sink = open(self.destinationBin, 'wb')
                            sink.write(p.generatedBinary)
                        else:
                            self.destinationBin = None

                        if outHex is not None:
                            path = os.path.join(outHex, self.parameters)
                            if not os.path.isdir(path):
                                os.makedirs(path)

                            self.destinationHex = os.path.join(
                                path, self.name + ".hex")

                            ih = IntelHex()
                            ih.frombytes(p.generatedBinary)
                            ih.tofile(self.destinationHex, "hex")
                        else:
                            self.destinationHex = None

                        self.generated = True
                    else:
                        self.reason = p.reason
                else:
                    self.reason = "Cannot find a valid parameters file for '" + self.parameters + "'"

                return self.generated
            except IOError as e:
                self.reason = CoreConsole.error(
                    str(e.strerror) + " [" +
                    CoreConsole.highlightFilename(e.filename) + "]")
                CoreConsole.fail("ParametersTarget::generate: " + self.reason)

        return False
Example #16
0
    def generate(self, workspace, outBin=None, outHex=None,skip=False):
        self.generated = False
        self.generatedBinary = None
        if self.valid:
            try:
                p = workspace.getParameters(self.parameters)

                if p is not None:
                    if p.generateBinary(workspace, self):
                        if outBin is not None:
                            path = os.path.join(outBin, self.parameters)
                            if not os.path.isdir(path):
                                os.makedirs(path)

                            self.destinationBin = os.path.join(path, self.name + ".bin")

                            sink = open(self.destinationBin, 'wb')
                            sink.write(p.generatedBinary)
                        else:
                            self.destinationBin = None

                        if outHex is not None:
                            path = os.path.join(outHex, self.parameters)
                            if not os.path.isdir(path):
                                os.makedirs(path)

                            self.destinationHex = os.path.join(path, self.name + ".hex")

                            ih = IntelHex()
                            ih.frombytes(p.generatedBinary)
                            ih.tofile(self.destinationHex, "hex")
                        else:
                            self.destinationHex = None

                        self.generated = True
                    else:
                        self.reason = p.reason
                else:
                    self.reason = "Cannot find a valid parameters file for '" + self.parameters + "'"

                return self.generated
            except IOError as e:
                self.reason = CoreConsole.error(str(e.strerror) + " [" + CoreConsole.highlightFilename(e.filename) + "]")
                CoreConsole.fail("ParametersTarget::generate: " + self.reason)

        return False
Example #17
0
    def readToFile(self, file, fileformat="bin"):

        result = False

        readData = self.read()

        ih = IntelHex()
        ih.frombytes(readData)

        if fileformat in ("bin", "hex"):
            ih.tofile(file, format=fileformat)
            result = True
        else:
            raise DriverCapabilityError(
                "Invalid Format. readToFile() does not support format={}".
                format(format))

        return result
def split_bin_to_ihex(file_name, base_addr, max_block_size):
    """Split a binary file to the blocks and load the blocks to IntelHex
       objects. Return the list of IntelHex objects.
    """
    # Block size must be aligned to 2 byte boundary (workaround for rf#2088)
    assert max_block_size % 2 == 0
    ihex_list = []
    with open(file_name, 'rb') as f:
        while True:
            block = bytearray(f.read(max_block_size))
            if not block:
                break
            # Align the last block to 2 byte boundary (workaround for rf#2088)
            if len(block) % 2 != 0:
                block.append(0xFF)
            ihex = IntelHex()
            ihex.frombytes(block, base_addr)
            ihex_list.append(ihex)
    return ihex_list
Example #19
0
def _bytes_to_pretty_hex(data, offset=0x0000):
    """Convert a list of bytes to a nicely formatted ASCII decoded hex string.

    :param data: List of integers, each representing a single byte.
    :param offset: Start address offset.
    :return: A string with the formatted hex data.
    """
    i_hex = IntelHex()
    i_hex.frombytes(data, offset)

    fake_file = StringIO()
    try:
        i_hex.dump(tofile=fake_file, width=16, withpadding=False)
    except IOError as e:
        sys.stderr.write("ERROR: File write: {}\n{}".format(fake_file, str(e)))
        return

    pretty_hex_str = fake_file.getvalue()
    fake_file.close()
    return pretty_hex_str
Example #20
0
def _bytes_to_intel_hex(data, offset=0x0000):
    """Take a list of bytes and return a string in the Intel Hex format.

    :param data: List of integers, each representing a single byte.
    :param offset: Start address offset.
    :return: A string with the Intel Hex encoded data.
    """
    i_hex = IntelHex()
    i_hex.frombytes(data, offset)

    fake_file = StringIO()
    try:
        i_hex.tofile(fake_file, format="hex")
    except IOError as e:
        sys.stderr.write("ERROR: File write: {}\n{}".format(fake_file, str(e)))
        return

    intel_hex_str = fake_file.getvalue()
    fake_file.close()
    return intel_hex_str
Example #21
0
def patch(message_func, ihex, hexf, align=256):
    #calculate checksum
    checksum = 0
    for start, end in ihex.segments():
        if start >= 0x090000000:
            continue
        segment = ihex.tobinarray(start, end)
        checksum += sum(segment)

    lowchecksum = checksum & 0x0FFFF
    message_func("Calculated checksum for %s is 0x%04x" % (hexf, lowchecksum))

    # update checksum
    checksum_str = pack('>H', lowchecksum)
    ihex.frombytes(array('B', checksum_str), offset=0x90300000)

    # update metadata
    signature = unpack('>L', ihex.tobinstr(start=0x90500002, size=4))[0]
    sigcheck = pack('>L', (checksum + signature) & 0x0FFFF)
    ihex.frombytes(array('B', sigcheck), offset=0x90500008)

    # align flash segments
    align_mask = align - 1
    alignments = IntelHex()
    for start, end in ihex.segments():
        if start >= 0x090000000:
            continue
        aligned_start = start & ~align_mask
        if start != aligned_start:
            message_func("Aligning start from 0x%x to 0x%x" %
                         (start, aligned_start))
            alignments.frombytes(ihex.tobinarray(aligned_start, start - 1),
                                 aligned_start)
        aligned_end = end & ~align_mask
        if end != aligned_end:
            aligned_end += align
            message_func("Aligning end from 0x%x to 0x%x" % (end, aligned_end))
            alignments.frombytes(ihex.tobinarray(end, aligned_end - 1), end)
    ihex.merge(alignments)
Example #22
0
def read(addr, length, compress, file):

    click.echo("\n Reading from MCU memory, please wait !\n")

    # Call KBoot flash erase all function
    data = KBOOT.read_memory(addr, length)

    # Disconnect KBoot Device
    KBOOT.disconnect()

    if file is None:
        click.echo(hexdump(data, addr, compress))
    else:
        if file.lower().endswith('.bin'):
            with open(file, "wb") as f:
                f.write(data)
                f.close()
        elif file.lower().endswith('.hex'):
            ihex = IntelHex()
            ihex.frombytes(data, 0)
            ihex.start_addr = addr
            try:
                ihex.tofile(file, format='hex')
            except Exception as e:
                raise Exception('Could not write to file: %s \n [%s]' % (file, str(e)))
        else:
            srec = kboot.SRecFile()
            srec.header = "pyKBoot"
            srec.start_addr = addr
            srec.data = data
            try:
                srec.save(file)
            except Exception as e:
                raise Exception('Could not write to file: %s \n [%s]' % (file, str(e)))

        click.secho(" Successfully saved into: %s. \n" % file)
Example #23
0
class Hex_File(object):
    """
    This class handles patching the hex file with new device key and unicast address.            
    """
    def __init__(self, options):
        """
        Initializer function.
        
        Keyword arguments:
        options -- Object created by parser.parse_args() that holds all the parameter values.
        """
        try:
            self.hf_db = MeshDB(options.db_input_file)
            self.hf_hex_file = IntelHex(options.hex_input_file)
            self.hf_number_of_nodes = len(self.hf_db.nodes)
            self.hf_start_node = options.start_node
            self.hf_mesh_sdk_version = options.mesh_sdk_version
            self.hf_clone_copies = options.clone_copies
            if (self.hf_mesh_sdk_version == 400):
                self.START_OF_FLASH_MANAGER_OFFSET = 0x50
                self.UNICAST_ADDRESS_OFFSET_1 = 0x1C
                self.UNICAST_ADDRESS_OFFSET_2 = 0x4C
            else:
                #Else assuming v3.2.0 of Nordic Mesh SDK
                self.START_OF_FLASH_MANAGER_OFFSET = 0x40
                self.UNICAST_ADDRESS_OFFSET_1 = 0x1C
                self.UNICAST_ADDRESS_OFFSET_2 = 0x3C
            logging.debug('Start node is {0}'.format(self.hf_start_node))
            if self.hf_start_node is not None:
                self.hf_working_node = self.hf_db.nodes[self.hf_start_node]
            else:
                self.hf_working_node = self.hf_db.nodes[(
                    self.hf_number_of_nodes - 1)]
            self.hf_output_hex_fw_name = options.hex_output_file
            self.hf_new_device_key = options.device_key
            self.hf_new_unicast_addr = options.unicast_address
            self.hf_new_node_name = options.node_name
            self._hf_iteration = 0
        except Exception as ex:
            logging.exception("Initialization error")

    def _generate_new_device_key(self):
        return uuid.uuid4().int.to_bytes(16, byteorder="big", signed=False)

    def patch_hex_file(self):
        """
        This function patches the hex file with the new device key and the new unicast address.        
        """
        try:
            logging.debug('Patching for Mesh SDK version {0}'.format(
                self.hf_mesh_sdk_version))
            #Get the device key from the database file
            self.hf_device_key = self.hf_working_node.device_key
            #Convert hex data to byte string so we can easily find the device key
            self.hf_input_hex_fw_bytestr = self.hf_hex_file.tobinstr()
            #Convert hex data to byte array that will represent the output patched hex file
            self.hf_output_hex_fw_bytearray = self.hf_hex_file.tobinarray()
            #Find the index where the device key starts
            logging.debug('Looking for device key {0}'.format(
                self.hf_device_key.hex()))
            self.hf_device_key_index = self.hf_input_hex_fw_bytestr.find(
                self.hf_device_key)
            if (self.hf_device_key_index == -1):
                logging.info(
                    'Device key not found! Are you sure the correct node is specified (--start-node)? '
                )
                raise ValueError(
                    'Device key not found in hex file!  Aborting!')
            logging.info("Device key found at location {0}".format(
                hex(self.hf_device_key_index)))
            #Sanity check: for the infinitesimally small chance that the device key occurs elsewhere in the hex file naturally!
            #Check for Flash Manager Area signature: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.meshsdk.v4.0.0%2Fmd_doc_libraries_flash_manager.html
            self.hf_expected_start_of_flash_manager_index = (
                self.hf_device_key_index - self.START_OF_FLASH_MANAGER_OFFSET)
            #This is where signature should be
            self.hf_flash_manager_sign_found = self.hf_input_hex_fw_bytestr.startswith(
                bytearray.fromhex('08041010'),
                (self.hf_expected_start_of_flash_manager_index),
                (self.hf_expected_start_of_flash_manager_index + 16))
            if (self.hf_flash_manager_sign_found == False):
                logging.info(
                    'Flash Area Manager signature not found at expected location {0}'
                    .format(hex(
                        self.hf_expected_start_of_flash_manager_index)))
                raise ValueError(
                    'Flash Area Manager signature not found at expected location {0}'
                    .format(hex(
                        self.hf_expected_start_of_flash_manager_index)))
            else:
                logging.info(
                    'Flash Area Manager signature found at expected location {0}'
                    .format(hex(
                        self.hf_expected_start_of_flash_manager_index)))
            #Get offset for both occurences of device handle which also need to be updated per device
            self.hf_expected_device_uc_addr_index = (
                self.hf_expected_start_of_flash_manager_index +
                self.UNICAST_ADDRESS_OFFSET_1)
            self.hf_expected_device_uc_addr_index_second = (
                self.hf_expected_start_of_flash_manager_index +
                self.UNICAST_ADDRESS_OFFSET_2)
            #Create new unicast address by reading all existing unicast addresses in the db file, finding the max, and incrementing the largest one by one.
            if self.hf_new_unicast_addr is None:
                #Create a list of unicast addresses from the db file
                self.unicast_address_list = []
                for i in self.hf_db.nodes:
                    self.unicast_address_list.append(i.unicast_address)
                #Find highest unicast address and increment by 1 to create new unicast address
                self.next_unicast_address = max(self.unicast_address_list) + 1
                logging.debug('Next available unicast address is {0}'.format(
                    hex(self.next_unicast_address)))
                self.hf_new_unicast_addr = self.next_unicast_address

            for x in range(self.hf_clone_copies):
                ####Patch and write the cloned fw
                #Update device unicast address in output bytearray
                self.hf_output_hex_fw_bytearray[
                    self.
                    hf_expected_device_uc_addr_index] = self.hf_new_unicast_addr
                self.hf_output_hex_fw_bytearray[
                    self.
                    hf_expected_device_uc_addr_index_second] = self.hf_new_unicast_addr
                #Generate new device key only if not specified on command line
                if (self.hf_new_device_key is None):
                    self.hf_new_device_key = self._generate_new_device_key()
                #Replace key in bytearray with new key
                for i in range(0, 16):
                    self.hf_output_hex_fw_bytearray[
                        self.hf_device_key_index +
                        i] = self.hf_new_device_key[i]
                #Create output IntelHex object...
                self.hf_output_hex_fw = IntelHex()
                #...and load it up with patched data
                self.hf_output_hex_fw.frombytes(
                    self.hf_output_hex_fw_bytearray)
                #Write out new patched fw file
                #New file name for each clone, except first one
                if (self._hf_iteration == 0):
                    logging.debug('Creating {0}'.format(
                        self.hf_output_hex_fw_name))
                    self.hf_output_hex_fw.write_hex_file(
                        self.hf_output_hex_fw_name)
                else:
                    self._hf_output_hex_fw_name_list = re.split(
                        '(\W)', self.hf_output_hex_fw_name)
                    self._hf_output_hex_fw_name = self._hf_output_hex_fw_name_list[
                        0] + "_" + str(self._hf_iteration) + "".join(
                            self._hf_output_hex_fw_name_list[1:])
                    logging.debug('Creating {0}'.format(
                        self._hf_output_hex_fw_name))
                    self.hf_output_hex_fw.write_hex_file(
                        self._hf_output_hex_fw_name)
                self._hf_iteration += 1
                ####Done patching and write the cloned fw

                ####Update JSON file with new node information
                #Create a new node for the new firmware in the JSON file by shallow copying from the original node in the JSON file
                self.hf_new_node = copy.copy(self.hf_working_node)
                #Update device address and unicast address
                self.hf_new_node.device_key = self.hf_new_device_key.hex()
                self.hf_new_node.unicast_address = self.hf_new_unicast_addr
                self.hf_db.nodes.append(self.hf_new_node)
                #Update node name
                if (self.hf_new_node_name is None):
                    self.hf_new_node.name += "_" + str(
                        self.hf_new_unicast_addr)
                else:
                    self.hf_new_node.name = self.hf_new_node_name
                #Store to file
                self.hf_db.store()
                ####Done updating JSON file with new node information

                ####Reinitialize variables for next iteration, if any
                #Reset the device key so new one is generated in next iteration in case multiple clones are requested.
                #This also means if device key is specified on command-line and multiple clones requested then only first
                #fw clone will have that specified key & the rest of clones will have auto-generated keys.
                self.hf_new_device_key = None
                #Increment unicast address for next node, if there are more iterations.
                #This also means if unicast address is specified on command-line and multiple clones requested then only first
                #fw clone will have that specified unicast address & the rest of clones will have unique unicast addresses generated by
                #incrementing command-line specified node by 1.
                self.hf_new_unicast_addr = self.hf_new_unicast_addr + 1
                #Reset node name to none for next iteration, if there are more iterations
                #This also means if node name is specified on command-line and multiple clones requested then only first
                #fw clone will have that node name & the rest of clones will have auto-generated node names.
                self.hf_new_node_name = None
                ####Done reinitializing variables for next iteration, if any
        except Exception as ex:
            logging.exception("Hex file patching error")
Example #24
0
def generateNewHex():
	tmp=open(bin_dir+program_name+"_modified.hex","w+");
	ih=IntelHex(bin_dir+program_name+".hex");
	binary=ih.tobinarray();
	for p in pointers:
		if 'rjmp' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeJMP(destination,offset,binary);
		elif 'jmp' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset); 
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeJMP(destination,offset,binary);
		elif 'rcall' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeCALL(destination,offset,binary);
		elif 'call' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeCALL(destination,offset,binary);
		elif 'br' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			opcode=p.split(":")[4];
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeBR(destination,offset,binary,opcode);
		elif 'nop' in p:
			offset=int(p.split(":")[1],16);
			binary.insert(offset,0x00);
			binary.insert(offset+1,0x00);
		elif 'jump_link' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			insertOpcodeJMP(destination,offset,binary);
		elif 'global_ctors' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeGLOBAL_CTORS(destination,offset,binary);
		elif 'vpointer' in p:
			offset=int(p.split(":")[1],16)-0x800000-0x100+offsetDataInSRAM;
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeVPointers(destination,offset,binary);
		elif 'ldi_data_offset' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeLDI_destination(destination,offset,binary);
		elif 'prologues' in p:
			offset=int(p.split(":")[1],16);
			destination=p.split(":")[3];
			ad=destination.split("0x")[1];
			while (len(ad)<4):
				ad='0'+ad;
			pc=address2pc(int(ad[0:2],16),int(ad[2:4],16));
			destination="0x"+h(pc)+l(pc);
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			binary.pop(offset);
			insertOpcodeLDI_destination(destination,offset,binary);
	ih.frombytes(binary);
	ih.write_hex_file(tmp);
    # However the key features of the programmer are for erase, read, write,
    # and verify functionality

    # 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
Example #26
0
 def save(self, path):
     h = IntelHex()
     h.frombytes(bytes=self.payload, offset=self.base_addr)
     h.tofile(path, 'hex')