Example #1
0
    def replace_image_body(self, orig, repl, padding):
        """
        Replaces original image with the replacement image
        :param orig: The image to be replaced
        :param repl: The image to replace with
        :param padding: Padding value
        """
        orig_ih = IntelHex()
        orig_ih.padding = padding
        orig_ih.loadhex(orig)

        repl_ih = IntelHex()
        repl_ih.padding = padding
        repl_ih.loadhex(repl)
        minaddr = repl_ih.minaddr()
        maxaddr = repl_ih.maxaddr()

        # This adds padding if the image is not aligned to 16 Bytes
        pad_len = (maxaddr - minaddr + self.header_size) % 16
        if pad_len > 0:
            pad_len = 16 - pad_len

        for i in range(repl_ih.minaddr(), repl_ih.maxaddr() + pad_len):
            orig_ih[i] = repl_ih[i]

        orig_ih.tofile(orig, pathlib.Path(orig).suffix[1:])
Example #2
0
def get_firmware_hex_image(firmwareFile, filesystemFile):
    hex = IntelHex(firmwareFile)
    hex.padding = 0x00

    filesystemHex = IntelHex(filesystemFile)
    filesystemHex.padding = 0x00
    hex.merge(filesystemHex)

    hexImage = hex.tobinstr(FIRMWARE_START_ADDRESS, FILESYSTEM_END_ADDRESS)
    return hexImage
Example #3
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 #4
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 #5
0
def merge_images(hexf0, hexf1=None):
    ihex = IntelHex()
    ihex.padding = 0x00
    ihex.loadfile(hexf0, "hex")
    if hexf1 is not None:
        # Merge the CM0+ image
        ihex1 = IntelHex(hexf1)
        ihex.merge(ihex1, 'ignore')
    return ihex
Example #6
0
def hex_crc(args):
    ihex_file = args.file[0]
    programSize = int(args.size[0])

    from intelhex import IntelHex

    ih = IntelHex()
    ih.loadfile(ihex_file, format="hex")
    ih.padding = 0xFF
    bin = ih.tobinarray(size=programSize)
    crc = stm32_crc32_bytes(0xffffffff, bin)
    print(hex(crc))

    return 0
Example #7
0
def hex_crc(args):
    ihex_file = args.file[0]
    programSize = int(args.size[0])

    from intelhex import IntelHex

    ih = IntelHex()
    ih.loadfile(ihex_file, format="hex")
    ih.padding = 0xFF
    bin = ih.tobinarray(size=programSize)
    crc = stm32_crc32_bytes(0xffffffff, bin)
    print(hex(crc))

    return 0
def merge_images(hexf0, hexf1=None):
    ihex = IntelHex()
    ihex.padding = 0x00
    ihex.loadfile(hexf0, "hex")
    if hexf1 is not None:
        # get chip ID from metadata and compare
        ihex1 = IntelHex(hexf1)
        type0 = ihex.tobinarray(start=0x90500002, size=4)
        type1 = ihex1.tobinarray(start=0x90500002, size=4)
        if type0 != type1:
            raise HookError(
                "Incompatible processor type: %s in '%s' and 0x%s in '%s'" %
                (hexf0, type0, hexf1, type1))
        ihex.merge(ihex1, 'ignore')
    return ihex
Example #9
0
def read_hexdata(hex_path):
    ih = IntelHex(hex_path)
    ih.padding = 0x00
    print(len(ih), MAX_BINLEN, ih.start_addr, ih.minaddr(), ih.maxaddr())
    print(ih.segments())
    print(ih[0], ih[1], ih[2])
    #print([x for x in ih[0:2]])
            
    if (ih[1] == 0x38 and ih[2] == 0x00):
        print(">>> Fixing hex file")
        ih[0] = ih[0x37FB]
        ih[1] = ih[0x37FC]
        ih[2] = ih[0x37FD]
        ih[0x37FB] = 0x00;
        ih[0x37FC] = 0x00
        ih[0x37FD] = 0x00
    print(ih[0], ih[1], ih[2])
    return ih.tobinarray(size=MAX_BINLEN)
Example #10
0
    def _process_image(self):
        """
        Read image address and size and calculate image hash
        """
        ih = IntelHex(self.image)
        ih.padding = 0x00

        image_addr = ih.minaddr()
        image_size = ih.maxaddr() - ih.minaddr() + 1

        sha256 = hashlib.sha256()
        sha256.update(ih.tobinarray(start=image_addr, size=image_size))

        image_hash = sha256.digest()

        image_attr = dict()
        image_attr['image_hash'] = image_hash
        image_attr['image_addr'] = image_addr
        image_attr['image_size'] = image_size
        image_attr['image_id'] = self.image_id
        image_attr['version'] = self.version

        return image_attr
Example #11
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 #12
0
def main(argv):
    inputfile = ''
    port = ''
    split = 1024
    usage_string = 'huzzah_exotag_firmware.py -i <inputfile> -p <comm port:/dev/ttyUSB or \\\.\COM12>'
    try:
        opts, args = getopt.getopt(argv, "hi:p:s:",
                                   ["file=", "port=", "split="])
    except getopt.GetoptError:
        print()
        sys.exit(2)
    if not opts:
        print("no arguments provided ")
        print(usage_string)
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(usage_string)
            sys.exit()
        elif opt in ("-i", "--file"):
            inputfile = arg
        elif opt in ("-p", "--port"):
            port = arg
        elif opt in ("-s", "--split"):
            split = int(arg)
        else:
            print("wrong arguments: " + opt)
            print(usage_string)

    print('input file: ' + inputfile)
    print('output port: ' + port)
    print('split in bytes: %d' % split)

    if inputfile.endswith('.hex'):
        ih = IntelHex()  # create empty object
        ih.padding = 0xFF
        ih.fromfile(inputfile, format='hex')  # also load from hex
        ascii_bin = binascii.hexlify(ih.tobinstr())
        #sys.exit()

    elif inputfile.endswith(
            '.bin'
    ):  #reconsider the extension here, the routine actually handles ascii
        with open(inputfile, 'r') as f:
            read_data = f.read()
            f.closed
        read_data = read_data.rstrip('\r\n')
        print(read_data)
        print([n for n in read_data])
        ascii_bin = read_data
        #binascii.unhexlify(read_data)
        #sys.exit()

    #print(ascii_bin)

    crc_result = binascii.crc32(ascii_bin) & 0xffffffff
    print("CRC = %08x" % crc_result)
    #sys.exit()

    exotag_uart = serial.Serial(port, 115200, timeout=1)
    exotag_uart_io = io.TextIOWrapper(
        io.BufferedRWPair(exotag_uart, exotag_uart))

    print('send start update: ' + unicode('exotag=update\r'))
    exotag_uart_io.write(unicode('exotag=update'.rstrip() + '\r'))
    exotag_uart_io.flush()
    time.sleep(1)
    #print (exotag_uart.readline())

    print('write')
    for i in range(0, len(ascii_bin), split):
        print((ascii_bin[i:i + split]))
        exotag_uart.write((ascii_bin[i:i + split]))
        exotag_uart_io.flush()
        time.sleep(1)

    print(binascii.hexlify(struct.pack("<I", crc_result)))
    exotag_uart.write('!'.encode() + struct.pack("<I", crc_result))
    exotag_uart_io.flush()
    #time.sleep(1)
    print('send end of firmware update')
    exotag_uart_io.write(unicode('~'))
    exotag_uart_io.flush()

    print('read exotag messages')
    exotag_string = exotag_uart_io.read()
    print("***********************\r\n" + exotag_string +
          "\r\n***********************")

    if (-1 != exotag_string.find('firmware update: SUCCESS')):

        print('tell huzzah to push update to exotag')
        exotag_uart_io.write(unicode('exotag=program'.rstrip() + '\r'))
        exotag_uart_io.flush()
        #time.sleep(10)

        print('read exotag messages')
        time.sleep(5)
        exotag_string = exotag_uart_io.read()
        print("***********************\r\n" + exotag_string +
              "\r\n***********************")
        if (-1 != exotag_string.find(
                'EFM8 flash write read-back verify success')):
            print(
                'EFM8 flash write read-back verify success - indicates SUCCESS'
            )

        print('reset exotag')
        exotag_uart_io.write(unicode('exotag=reset'.rstrip() + '\r'))
        exotag_uart_io.flush()
        time.sleep(5)
        exotag_string = exotag_uart_io.read()
        print("***********************\r\n" + exotag_string +
              "\r\n***********************")

    exotag_uart.close()
Example #13
0
    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 16
    remainder = endAddr % OAD_BLOCK_SIZE
    if remainder:
        print("Last address was 0x%0X. Expanded to 0x%0X to be divisible by OAD block size" % (endAddr, endAddr+(OAD_BLOCK_SIZE-remainder)) )
        endAddr += OAD_BLOCK_SIZE - remainder

    #if specified, the script will pad the image with the pad value
    fillHex = IntelHex()
    fillHex.puts(startAddr, struct.pack('B', vargs.fill) * (endAddr))
    mergedHex.merge(fillHex, 'ignore')
    mergedHex = mergedHex[startAddr:endAddr] # +1 since the last address is not inclusive
    mergedHex.padding = vargs.fill


    #if we are calculating metadata
    #Offchip OAD production images and NP images don't have embedded metadata headers, skip meta data calc for these
    #All onchip OAD images need metdata placement
    if not(vargs.oadtype == 'offchip' and (vargs.imgtype == 'production' or vargs.imgtype == 'np')):
        # Place metadata, onchip production image expects header at 0x600
        if vargs.oadtype == 'onchip' and vargs.imgtype == 'production':
            residentHdr = OadHdr._make(struct.unpack(OAD_HDR_FMT, mergedHex.tobinstr(INT_FL_OAD_IMG_A_META_BEGIN, INT_FL_OAD_IMG_A_META_BEGIN+15)))
        else:
            residentHdr = OadHdr._make(struct.unpack(OAD_HDR_FMT, mergedHex.tobinstr(startAddr, startAddr+15)))
        metaAddr = vargs.meta
        if metaAddr is None:
            # Try first address, ideally there should be free space at the beginning of the image
            #in the reserved image metadata sector
Example #14
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}\'')
Example #15
0
from intelhex import IntelHex

ih = IntelHex()
ih.padding = 0
ih.fromfile("sbos.hex", format="hex")
start = ih.segments()[0][0]
ih.tobinfile("sbos.bin", start=start, size=8192)
Example #16
0
def load(mw, transport, args):
    bl = MW.Bootloader()
    bl.start()
    sleep(1)

    retval = 1

    uid = MW.BootMsg.UID.getUIDFromHexString(args.uid[0])
    ihex_file = args.file[0]

    if not uid in bl.getSlaves():
        print("Device is not in bootload mode")
        return 1

    if not bl.select(uid):
        print("Cannot select device")
        return 1

    try_again = True

    if try_again:
        desc = bl.describe_v3(uid)
        if desc is None:
            try_again = True
        else:
            print("TARGET:" + formatDescription_V3(uid, desc))
            try_again = False

    if try_again:
        desc = bl.describe_v2(uid)
        if desc is None:
            try_again = True
        else:
            print("TARGET:" + formatDescription_V2(uid, desc))
            try_again = False

    if try_again:
        retval = 1
    else:
        programSize = desc.program

        ih = IntelHex()
        ih.loadfile(ihex_file, format="hex")
        ih.padding = 0xFF
        bin = ih.tobinarray(size=programSize)
        crc = stm32_crc32_bytes(0xffffffff, bin)
        print("CRC: " + hex(crc))

        what = args.what[0]
        if what == 'program':
            if not bl.eraseProgram(uid):
                print("Cannot erase program")
                return 1

        with open(ihex_file) as f:
            data = f.read().splitlines()

        write_ihex(bl, data, crc)

        if what == 'program':
            if not bl.write_program_crc(uid, crc):
                print("Cannot write CRC")
                return 1

    bl.deselect(uid)

    bl.stop()

    return retval
# Copyright (C) 2015 Herbert Poetzl

import sys
import serial
import struct

from intelhex import IntelHex
from smbus import SMBus
from time import sleep
from icsp import *

tty = "/dev/ttyPS1"
sel = sys.argv[1] if len(sys.argv) > 1 else "P"

ih = IntelHex(sys.argv[2])
ih.padding = 0xFF


def ih_data(ih, addr, count=32):
    data = []
    mask = 0xFFFF
    for n in range(count):
        l, h = ih[(addr + n)*2], ih[(addr + n)*2 + 1]
        val = (h << 8)|l
        mask &= val
        data.append(val)
    return data, mask



ser = serial.Serial(
Example #18
0
def load(mw, transport, args):
    bl = MW.Bootloader()
    bl.start()
    sleep(1)

    retval = 1

    uid = MW.BootMsg.UID.getUIDFromHexString(args.uid[0])
    ihex_file = args.file[0]

    if not uid in bl.getSlaves():
        print("Device is not in bootload mode")
        return 1

    if not bl.select(uid):
        print("Cannot select device")
        return 1

    try_again = True

    if try_again:
        desc = bl.describe_v3(uid)
        if desc is None:
            try_again = True
        else:
            print("TARGET:" + formatDescription_V3(uid, desc))
            try_again = False

    if try_again:
        desc = bl.describe_v2(uid)
        if desc is None:
            try_again = True
        else:
            print("TARGET:" + formatDescription_V2(uid, desc))
            try_again = False

    if try_again:
        retval = 1
    else:
        programSize = desc.program
        
        ih = IntelHex()
        ih.loadfile(ihex_file, format="hex")
        ih.padding = 0xFF
        bin = ih.tobinarray(size=programSize)
        crc = stm32_crc32_bytes(0xffffffff, bin)
        print("CRC: " + hex(crc))

        what = args.what[0]
        if what == 'program':
            if not bl.eraseProgram(uid):
                print("Cannot erase program")
                return 1

        with open(ihex_file) as f:
            data = f.read().splitlines()

        write_ihex(bl, data, crc)

        if what == 'program':
            if not bl.write_program_crc(uid, crc):
                print("Cannot write CRC")
                return 1

    bl.deselect(uid)

    bl.stop()

    return retval
Example #19
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 #20
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 #21
0
if len(hexfnlist) == 0:
    raise ApplicationError, 'No any DKSF*.hex files found!'
hexfn = sorted(hexfnlist, key=os.path.getmtime)[-1]
print
print os.path.abspath(hexfn)

bootfn = glob.glob('..\\..\\Bootloader_Debug\\Exe\\*.hex')
if len(bootfn) != 1:
    raise ApplicationError, 'More than one bootloader .hex file found!'
bootfn = os.path.abspath(bootfn[0])
print bootfn

ih = IntelHex(hexfn)
blih = IntelHex(bootfn)

ih.padding = 0xff
code = ih.tobinstr(start=fw_offset, end=fw_offset+fw_length-1)
res = ih.tobinstr(start=res_offset, end=res_offset+res_length-1)

ver_data_offset = code.index(verdatastart) + len(verdatastart)
model, version, subversion, litera, assmcode =\
    struct.unpack_from('<HHHcB', code, ver_data_offset)
ver = str(model) + '.' + str(version) + '.' + str(subversion) + '.' + litera + '-' + str(assmcode)
print 'Extracted version data:', ver

print 'Merging bootloader file...',
ih.start_addr = None # program start addr record will be from BL part
try:
    ih.merge(blih, overlap='error')
    print 'Ok'
except AddressOverlapError:
Example #22
0
def main(argv):

    options = myargs(argv)
    print("options: {}".format(options))

    if not options.policy_path:
        options.policy_path = 'policy'

    tools = CySecureTools(
        options.target_name,
        options.policy_path + "/" + options.policy_file + '.json')
    if (options.toolchain == 'ARM'):
        fromelf_cmd = options.toolchain_path + "/bin/fromelf"
        app_elf_file = options.build_dir + "/" + options.app_name + ".elf"
        fromelf_result_dir = options.build_dir + "/" + "fromelf_result"
        # Check if gcc tools path is valid
        if (os.path.isdir(options.toolchain_path) == False):
            print("ERROR: 'ARM Compiler' tools folder not found in path: {}".
                  format(options.toolchain_path))
            exit(-1)

        # Check if elf is valid
        if (os.path.isfile(app_elf_file) == False):
            print("ERROR: ELF file not found in path: {}\r\n".format(
                app_elf_file))
            exit(-1)

        # Split elf file into sections
        shell_cmd = [
            fromelf_cmd, '--i32', '--output=' + fromelf_result_dir,
            app_elf_file
        ]
        ret = exec_shell_command(shell_cmd)
        if (ret != 0):
            exit(ret)

        em_eeprom_hex = fromelf_result_dir + "/" + ".cy_em_eeprom"
        app_hex_path = options.build_dir + '/' + options.app_name + '.hex'
        if (os.path.isfile(em_eeprom_hex) == True):
            sections_list = [
                f for f in os.listdir(fromelf_result_dir)
                if os.path.isfile(os.path.join(fromelf_result_dir, f))
            ]
            sections_list.remove('.cy_em_eeprom')
            flash = IntelHex()

            for section in sections_list:
                sect = IntelHex(fromelf_result_dir + "/" + section)
                flash.merge(sect, overlap='replace')

            flash.write_hex_file(app_hex_path, False)

        CM0_app_src_path = options.cm0_app_path + '/' + options.cm0_app_name + '.hex'
        CM0_app_dst_path = options.build_dir + '/' + options.cm0_app_name + '.hex'

        # CySecureTools Image ID for CM4 Applications is
        # 1) 1 for single-stage,
        # 2) 16 in case of multi-stage,
        # Image ID for CM0 Applications is always 1
        if (options.core == "CM4"):
            if (options.secure_boot_stage == "single"):
                # Sign CM4 image
                tools.sign_image(app_hex_path, 1)
            else:
                # Sign CM4 image
                tools.sign_image(app_hex_path, 16)
                # Make a copy of CM0P app image in build folder
                shutil.copy2(CM0_app_src_path, CM0_app_dst_path)

                # Sign CM0 image
                tools.sign_image(CM0_app_dst_path, 1)

                # Merge CM0, CM4 into a single hex file
                ihex = IntelHex()
                ihex.padding = 0x00
                ihex.loadfile(app_hex_path, 'hex')                 \
                                        ihex.merge(IntelHex(CM0_app_dst_path), 'ignore')                 \
                                        ihex.write_hex_file(app_hex_path, write_start_addr=False, byte_count=16)
        else:
            tools.sign_image(app_hex_path, 1)

        if (os.path.isfile(em_eeprom_hex) == True):
            # Add emulated EEPROM Section back
            flash = IntelHex(app_hex_path)
            eeprom = IntelHex(em_eeprom_hex)
            flash.merge(eeprom)
            flash.write_hex_file(app_hex_path, False)
    else:
        gcc_objcopy_eabi_cmd = options.toolchain_path + '/bin/arm-none-eabi-objcopy'
        app_elf_file = options.build_dir + "/" + options.app_name + ".elf"

        # Check if gcc tools path is valid
        if (os.path.isdir(options.toolchain_path) == False):
            print("ERROR: GCC tools folder not found in path: {}".format(
                options.toolchain_path))
            exit(-1)

        # Check if elf is valid
        if (os.path.isfile(app_elf_file) == False):
            print("ERROR: ELF file not found in path: {}\r\n".format(
                app_elf_file))
            exit(-1)

        # Strip away emulated EEPROM section from hex file before signing
        shell_cmd = [
            gcc_objcopy_eabi_cmd, '-R', '.cy_em_eeprom', '-O', 'ihex',
            app_elf_file, options.build_dir + "/" + options.app_name + ".hex"
        ]
        ret = exec_shell_command(shell_cmd)
        if (ret != 0):
            exit(ret)

        # Store emulated eeprom section in a seperate hex file
        shell_cmd = [
            gcc_objcopy_eabi_cmd, '-j', '.cy_em_eeprom', '-O', 'ihex',
            options.build_dir + "/" + options.app_name + ".elf",
            options.build_dir + "/em_eeprom.hex"
        ]
        ret = exec_shell_command(shell_cmd)
        if (ret != 0):
            exit(ret)

        app_hex_path = options.build_dir + '/' + options.app_name + '.hex'
        CM0_app_src_path = options.cm0_app_path + '/' + options.cm0_app_name + '.hex'
        CM0_app_dst_path = options.build_dir + '/' + options.cm0_app_name + '.hex'

        # CySecureTools Image ID for CM4 Applications is
        # 1) 1 for single-stage,
        # 2) 16 in case of multi-stage,
        # Image ID for CM0 Applications is always 1
        if (options.core == "CM4"):
            if (options.secure_boot_stage == "single"):
                # Sign CM4 image
                tools.sign_image(app_hex_path, 1)
            else:
                # Sign CM4 image
                tools.sign_image(app_hex_path, 16)
                # Make a copy of CM0P app image in build folder
                shutil.copy2(CM0_app_src_path, CM0_app_dst_path)

                # Sign CM0 image
                tools.sign_image(CM0_app_dst_path, 1)

                # Merge CM0, CM4 into a single hex file
                ihex = IntelHex()
                ihex.padding = 0x00
                ihex.loadfile(app_hex_path, 'hex')                 \
                                ihex.merge(IntelHex(CM0_app_dst_path), 'ignore')                 \
                                ihex.write_hex_file(app_hex_path, write_start_addr=False, byte_count=16)
        else:
            tools.sign_image(app_hex_path, 1)

        # Add emulated EEPROM Section back
        flash = IntelHex(app_hex_path)
        eeprom = IntelHex(options.build_dir + "/em_eeprom.hex")
        flash.merge(eeprom)
        flash.write_hex_file(app_hex_path, False)

    exit(0)
Example #23
0
# read out the header
header = ih2header(prog)

# optional updates
if args.pid != None and args.pid >= 0 and args.pid < 256:
    header['pid'] = args.pid
if args.key != None:
    header['key'] = args.key
if args.hw != None:
    header['hw_id'] = args.hw

# update the header len
l = prog.maxaddr() - prog.minaddr() + 1
header['len'] = l
prog = header2ih(prog,
                 header)  # put the length back into the intel hex file for crc

# update the header crc (note we do no include the CRC word in the CRC)
crc_start_addr = prog.minaddr() + 4
prog.padding = 0xff
buf = prog.tobinstr(start=crc_start_addr)
crc.crc_init(crc.stm32f10x_crc_h)
crc = crc.crc_buf(crc.stm32f10x_crc_h, buf, len(buf)) & 0xffffffff
header['crc'] = crc
prog = header2ih(
    prog,
    header)  # put the crc back into the intel hex file so we can write it out

# write header back to hex file
prog.write_hex_file(sys.stdout)
Example #24
0
    def updateFirmware(self, hexFilePath, newDeviceAddress=None):
        hexFile = IntelHex(source=hexFilePath)
        hexFile.padding = FLASH_PADDING
        appBinary = hexFile.tobinarray(start=APP_START_ADDRESS,
                                       end=NV_SETTINGS_END)
        crcBinary = hexFile.tobinarray(start=CHECKSUM_DESCRIPTOR_START,
                                       end=CHECKSUM_DESCRIPTOR_END)

        if newDeviceAddress:
            self._logger.debug(
                "Modifying the last byte in NV settings to change Device I2C Addrress to {0:#0X}"
                .format(newDeviceAddress))
            if (newDeviceAddress < IQS5xx_DEFAULT_ADDRESS) or (
                    newDeviceAddress > IQS5xx_MAX_ADDRESS):
                raise ValueError(
                    "Invalid I2C Address. Use something in the range [%x, %x]"
                    % (IQS5xx_DEFAULT_ADDRESS, IQS5xx_MAX_ADDRESS))
            appBinary[-1] = newDeviceAddress

        # Step 1 - Enter Bootloader
        self._logger.debug("Entering Bootloader")
        bootloaderAddress = 0x40 ^ self.address
        bootloaderDevice = i2c.get_i2c_device(bootloaderAddress)
        self.holdReset(100)
        bootloaderEntered = False
        for i in range(10):
            try:
                version = bootloaderDevice.readU16(BL_CMD_READ_VERSION,
                                                   little_endian=False)
                bootloaderEntered = True
            except:
                pass
        if not bootloaderEntered:
            raise IOError("Timeout while trying to enter bootlaoder")
        self._logger.debug("Bootloader entered successfully")

        # Step 2 - Read and verify the bootloader version number
        self._logger.debug("Reading Bootloader version")
        if version != BL_VERSION:
            raise Exception(
                "Incompatible bootloader version detected: {0:#0X}".format(
                    version))
        self._logger.debug("Bootloader version is compatible: 0x%02X", version)

        # Step 3 - Write the new application firmware and settings
        self._logger.debug("Starting to write Application and NV settings")
        for blockNum in range(APP_SIZE_BLOCKS + NV_SETTINGS_SIZE_BLOCKS):
            blockAddress = APP_START_ADDRESS + (blockNum * BLOCK_SIZE)
            self._logger.debug(
                'Writing 64-byte block {0}/{1} at address {2:#0X}'.format(
                    blockNum + 1, APP_SIZE_BLOCKS + NV_SETTINGS_SIZE_BLOCKS,
                    blockAddress))
            data = bytearray(BLOCK_SIZE + 2)
            data[0] = (blockAddress >> 8) & 0xFF
            data[1] = blockAddress & 0xFF
            data[2:] = appBinary[blockNum * BLOCK_SIZE:(blockNum + 1) *
                                 BLOCK_SIZE]
            bootloaderDevice.writeBytes(data)
            time.sleep(.010)  # give the device time to write to flash

        # Step 4 - Write the checksum descriptor section
        self._logger.debug("Writing CRC section")
        blockAddress = CHECKSUM_DESCRIPTOR_START
        data = bytearray(BLOCK_SIZE + 2)
        data[0] = (blockAddress >> 8) & 0xFF
        data[1] = blockAddress & 0xFF
        data[2:] = crcBinary[0:]
        bootloaderDevice.writeBytes(data)
        time.sleep(0.010)  # give the device time to write to flash

        # Step 5 - Perform CRC and read back settins section
        time.sleep(0.1)
        self._logger.debug("Performing CRC calculation")
        bootloaderDevice.writeRaw8(BL_CMD_RUN_CRC)
        time.sleep(0.2)
        crcStatus = bootloaderDevice.readRaw8()
        if crcStatus != BL_CRC_PASS:
            raise Exception("CRC Failure")
        self._logger.debug("CRC Success")

        self._logger.debug("Reading back NV settings and comparing")
        for blockNum in range(NV_SETTINGS_SIZE_BLOCKS):
            blockAddress = NV_SETTINGS_START + (blockNum * BLOCK_SIZE)
            self._logger.debug(
                'Reading 64-byte block {0}/{1} at address {2:#0X}'.format(
                    blockNum + 1, NV_SETTINGS_SIZE_BLOCKS, blockAddress))
            data = bytearray(3)
            data[0] = BL_CMD_READ_64_BYTES
            data[1] = (blockAddress >> 8) & 0xFF
            data[2] = blockAddress & 0xFF
            reply = bootloaderDevice.writeRawListReadRawList(data, BLOCK_SIZE)
            expectedReply = appBinary[(APP_SIZE_BLOCKS + blockNum) *
                                      BLOCK_SIZE:(APP_SIZE_BLOCKS + blockNum +
                                                  1) * BLOCK_SIZE].tostring()
            if reply != expectedReply:
                raise Exception(
                    "Unexpected values while reading back NV Setting: {0} \nExpected values: {1}"
                    .format(bytesToHexString(reply),
                            bytesToHexString(expectedReply)))
        self._logger.debug("NV Settings match expected values")

        # Step 6 - Execute application
        self._logger.debug("Execute Application")
        bootloaderDevice.writeRaw8(BL_CMD_EXECUTE_APP)

        if newDeviceAddress:
            self.address = newDeviceAddress
Example #25
0
    # Make sure the last address is divisible by 16
    remainder = endAddr % OAD_BLOCK_SIZE
    if remainder:
        print(
            "Last address was 0x%0X. Expanded to 0x%0X to be divisible by OAD block size"
            % (endAddr, endAddr + (OAD_BLOCK_SIZE - remainder)))
        endAddr += OAD_BLOCK_SIZE - remainder

    #if specified, the script will pad the image with the pad value
    fillHex = IntelHex()
    fillHex.puts(startAddr, struct.pack('B', vargs.fill) * (endAddr))
    mergedHex.merge(fillHex, 'ignore')
    mergedHex = mergedHex[
        startAddr:endAddr]  # +1 since the last address is not inclusive
    mergedHex.padding = vargs.fill

    #if we are calculating metadata
    #Offchip OAD production images and NP images don't have embedded metadata headers, skip meta data calc for these
    #All onchip OAD images need metdata placement
    if not (vargs.oadtype == 'offchip' and
            (vargs.imgtype == 'production' or vargs.imgtype == 'np')):
        # Place metadata, onchip production image expects header at 0x600
        if vargs.oadtype == 'onchip' and vargs.imgtype == 'production':
            residentHdr = OadHdr._make(
                struct.unpack(
                    OAD_HDR_FMT,
                    mergedHex.tobinstr(INT_FL_OAD_IMG_A_META_BEGIN,
                                       INT_FL_OAD_IMG_A_META_BEGIN + 15)))
        else:
            residentHdr = OadHdr._make(
Example #26
0
import sys
import serial
import struct

from intelhex import IntelHex
from smbus import SMBus
from time import sleep
from axiom_icsp import *
from axiom_via import *

tty = "/dev/ttyPS1"

sel = sys.argv[1]

ih = IntelHex(sys.argv[2])
ih.padding = 0xFF


def ih_data(ih, addr, count=32):
    data = []
    mask = 0xFFFF
    for n in range(count):
        l, h = ih[(addr + n) * 2], ih[(addr + n) * 2 + 1]
        val = (h << 8) | l
        mask &= val
        data.append(val)
    return data, mask


ser = serial.Serial(
    port=tty,
Example #27
0
header_addr = prog.minaddr() # all programs require there header to be located at the start

# read out the header
header = ih2header(prog)

# optional updates
if args.pid != None and args.pid >= 0 and args.pid < 256:
	header['pid'] = args.pid
if args.key != None:
	header['key'] = args.key
if args.hw != None:
	header['hw_id'] = args.hw

# update the header len
l = prog.maxaddr() - prog.minaddr() + 1
header['len'] = l
prog = header2ih(prog, header) # put the length back into the intel hex file for crc

# update the header crc (note we do no include the CRC word in the CRC)
crc_start_addr = prog.minaddr() + 4
prog.padding = 0xff
buf = prog.tobinstr(start=crc_start_addr)
crc.crc_init(crc.stm32f10x_crc_h)
crc = crc.crc_buf(crc.stm32f10x_crc_h, buf, len(buf)) & 0xffffffff
header['crc'] = crc
prog = header2ih(prog, header) # put the crc back into the intel hex file so we can write it out

# write header back to hex file
prog.write_hex_file(sys.stdout)

Example #28
0
def get_bootloader_hex_image(bootoaderFile):
    hex = IntelHex(bootoaderFile)
    hex.padding = 0x00

    hexImage = hex.tobinstr(BOOTLOADER_START_ADDRESS, BOOTLOADER_END_ADDRESS)
    return hexImage
                d = 0

            if (crc_out & 0x1):
                c = 0xFFFFFFFF
            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)
Example #30
0

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, with all non-specified area being set to 0xff. '
        '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)
        ih.padding = 0xff  # Allows hashing with empty regions
        to_hash = ih.tobinstr()
    else:
        to_hash = open(args.infile, 'rb').read()
    sys.stdout.buffer.write(hashlib.sha256(to_hash).digest())
Example #31
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-s',
        '--sample-rate',
        dest='sample_rate',
        type=int,
        required=True,
        help='Sample rate in Hz. Must be a multiple of the symbol rate.')
    parser.add_argument('-y',
                        '--symbol-rate',
                        dest='symbol_rate',
                        type=int,
                        required=True,
                        help='Symbol rate in Hz.')
    parser.add_argument(
        '-b',
        '--block-size',
        dest='block_size',
        required=True,
        help='The number of bytes that the target will write at a time. '
        'Must be a multiple of the packet size.')
    parser.add_argument(
        '-w',
        '--write-time',
        dest='write_time',
        required=True,
        help='Amount of time in milliseconds required by the target to write '
        'a block.')
    parser.add_argument(
        '-f',
        '--flash-spec',
        dest='flash_spec',
        required=True,
        nargs='+',
        help='Flash page specification which describes the layout of the '
        'target\'s flash memory. This is a list of '
        'specifiers of the form "SIZE:ETIME[:NUM]", where SIZE is the '
        'size in bytes of the page (and must be a multiple of the block '
        'size), ETIME is the amount of time in milliseconds to allow for '
        'the page erase to complete, and NUM optionally specifies the '
        'number of these pages (if NUM is not given, then this specifier '
        'will be used for all remaining pages). For example, a simple '
        'layout consisting of 1KB pages that require 50ms each to erase '
        'could be specified as "1024:50", while a more complex layout '
        'like that of the STM32F405 could be specified as '
        '"16K:500:4 64K:1100:1 128K:2000:7".')
    parser.add_argument(
        '-a',
        '--start-address',
        dest='start_address',
        required=True,
        help='Flash memory address at which the firmware will be written. '
        'If a "+" is prepended, this will be interpreted as an offset from '
        'the base address, otherwise as an absolute address. Must align '
        'to a page.')
    parser.add_argument(
        '-x',
        '--base-address',
        dest='base_address',
        default='0',
        help='Base address of the target\'s flash memory. Default 0.')
    parser.add_argument(
        '-p',
        '--packet-size',
        dest='packet_size',
        default='256',
        help='Packet size in bytes. Must be a multiple of 4. Default 256.')
    parser.add_argument(
        '--fill',
        dest='fill_byte',
        default='0xFF',
        help='Byte value to use to fill gaps and pad lengths. Default 0xFF.')
    parser.add_argument('-e',
                        '--seed',
                        dest='crc_seed',
                        default='0',
                        help='CRC32 seed. Default 0.')
    parser.add_argument(
        '-t',
        '--file-type',
        dest='file_type',
        choices=['hex', 'bin', 'auto'],
        default='auto',
        help='Input file type. If a hex file is used, all '
        'content before the start address will be ignored. A bin file is '
        'always assumed to start at the start address. Default auto.')
    parser.add_argument('-i',
                        '--input-file',
                        dest='input_file',
                        default='-',
                        help='Input file (bin or hex). Default stdin.')
    parser.add_argument(
        '-o',
        '--output-file',
        dest='output_file',
        default=None,
        help='Output wav file. The default is derived from the input file name '
        'if one is given, otherwise stdout.')
    args = parser.parse_args()

    if args.input_file == '-':
        input_file = sys.stdin.buffer
        if args.output_file == None:
            args.output_file = '-'
    else:
        input_file = open(args.input_file, 'rb')
        (root, ext) = os.path.splitext(args.input_file)
        if args.file_type == 'auto' and ext in ['.bin', '.hex']:
            args.file_type = ext[1:]
        if args.output_file == None:
            args.output_file = root + '.wav'

    data = input_file.read()
    if input_file is not sys.stdin.buffer:
        input_file.close()

    if args.file_type == 'auto':
        is_hex = all(map(lambda x: chr(x) in string.hexdigits + ':\r\n', data))
        args.file_type = 'hex' if is_hex else 'bin'

    base_address = int(args.base_address, 0)
    if args.start_address.startswith('+'):
        start_address = base_address + int(args.start_address[1:], 0)
    else:
        start_address = int(args.start_address, 0)

    fill_byte = int(args.fill_byte, 0)

    if args.file_type == 'hex':
        from intelhex import IntelHex
        ihex = IntelHex(io.StringIO(data.decode('ascii')))[start_address:]
        ihex.padding = fill_byte
        data = ihex.tobinstr()

    if args.output_file == '-':
        output_file = sys.stdout.buffer
    else:
        output_file = args.output_file

    arrangement = Arrangement(flash_spec=args.flash_spec,
                              reserved_size=start_address - base_address,
                              block_size=parse_size(args.block_size),
                              fill_byte=fill_byte,
                              write_time=float(args.write_time),
                              data=data)

    encoder = Encoder(symbol_rate=args.symbol_rate,
                      packet_size=parse_size(args.packet_size),
                      crc_seed=int(args.crc_seed, 0))

    symbols = encoder.encode(arrangement)

    assert (args.sample_rate % args.symbol_rate) == 0
    modulator = QPSKModulator(args.sample_rate, args.symbol_rate)
    signal = modulator.modulate(symbols)

    writer = wave.open(output_file, 'wb')
    writer.setframerate(args.sample_rate)
    writer.setsampwidth(2)
    writer.setnchannels(1)
    writer.writeframes(signal.tobytes())
    writer.close()
Example #32
0
def main():
    if len(sys.argv) < 3:
        print("Usage: %s  <bin file> <cyad file>")
        sys.exit()

    bin_file = sys.argv[1]
    cyad_file = sys.argv[2]

    if not os.path.isfile(bin_file):
        print("bin file path %s does not exist. Exiting..." % (bin_file))
        sys.exit()
    else:
        print("bin file: " + bin_file)

    if not os.path.isfile(cyad_file):
        print("cyad path %s does not exist. Exiting..." % (cyad_file))
        sys.exit()
    else:
        print("cyad file: " + cyad_file)

    with open(bin_file, mode='rb') as bfp:
        b = bytearray(bfp.read())
        print("binary loade, len %d" % len(b))

    # Now merge in the cyad
    bdata = bytearray()

    # default
    deviceid = int(CYPD2104_20FNXI, 16)

    with open(cyad_file) as cyfp:
        cnt = 0
        for line in cyfp:
            if cnt == 0:
                if CYPD2104_20FNXI in line:
                    deviceid = int(CYPD2104_20FNXI, 16)
                    print("device is CYPD2104_20FNXI")
                elif CYPD2122_20FNXIT in line:
                    deviceid = int(CYPD2122_20FNXIT, 16)
                    print("device is CYPD2122_20FNXIT")
                else:
                    print("unk device: %s" % (line))
            else:
                line = line.strip()

                if cnt == 1:
                    cyad_addr = int(line[1:9], 16) >> 1
                    print("addr: %x" % cyad_addr)

                data = line[11:len(line) - 2]
                bdata.extend(binascii.unhexlify(data))

            cnt += 1

        # merge cyad with program data
        bend = b[cyad_addr + len(bdata):]
        b = b[:cyad_addr]
        b.extend(bdata)
        b.extend(bend)

        # update csums
        updateCfgCsum(cyad_addr, b)

    # calculate the binary checksum
    csum = calcChecksum(b)
    csum_short = csum & 0xFFFF

    # Create the device record meta data
    DiDR = createDeviceIdRecord(csum, deviceid)

    # create the hex file string
    sio = StringIO()
    ihex = IntelHex()
    ihex.start_addr = None
    ihex.padding = 0x00

    # ihex failed to decode a character, so doing it one by one
    for i, c in enumerate(b):
        ihex[i] = c

    # write out the ihex string
    ihex.write_hex_file(sio)
    hexstr = sio.getvalue()
    sio.close()

    # remove the EOF so we can add the cypress metadata
    hexstr = hexstr[:hexstr.rfind(ihex_eof)]

    # metadata stoarge
    suffix = []

    # add checksum short
    suffix.append(":0200000490303A")
    suffix.append(makedataline(csum_short.to_bytes(2, byteorder='big'), 0, 0))

    # metadata
    suffix.append(":0200000490402A")
    suffix.append(
        ":200000000000000000000000000000000000000000000000000000000000000000000000E0"
    )

    # Device id record
    suffix.append(":0200000490501A")
    suffix.append(makedataline(DiDR, 0, 0))

    # chip level protection
    suffix.append(":0200000490600A")
    suffix.append(":0100000001FE")

    # EOF
    suffix.append(ihex_eof)

    tail = '\n'.join(suffix)

    hexstr = hexstr + tail

    with open("out.hex", mode='w') as ofp:
        ofp.write(hexstr)