def main(arguments):
    # If using ANSI coloring is available, initialize colorama
    if fail_color:
        init()

    # Import intelhex if avaialable, otherwise fail
    try:
        from intelhex import IntelHex
    except:
        return fail(
            'error: You do not have \'intelhex\' installed. Please run \'pip install intelhex\' then retry.'
        )

    # Ensure the right number of arguments are supplied
    if not len(arguments) == 3:
        return fail(
            'error: Improper use of merge_hex.py.\nUSAGE: merge_hex.py input_file1 input_file2 output_file.'
        )

    # Get the two hex files, merge them, and save the result
    orig = IntelHex(arguments[0])
    convert_start_addr(orig)

    new = IntelHex(arguments[1])
    convert_start_addr(new)

    orig.merge(new, overlap='replace')
    orig.write_hex_file(arguments[2])
Example #2
0
def main_mergehex():
    if len(sys.argv) < 3:
        print(
            'usage: %s <file1.hex> <file2.hex> [...] [-s <secret_attestation_key>] <output.hex>'
        )
        sys.exit(1)

    def flash_addr(num):
        return 0x08000000 + num * 2048

    args = sys.argv[:]

    # generic / hacker attestation key
    secret_attestation_key = (
        "1b2626ecc8f69b0f69e34fb236d76466ba12ac16c3ab5750ba064e8b90e02448"
    )

    # user supplied, optional
    for i, x in enumerate(args):
        if x == '-s':
            secret_attestation_key = args[i + 1]
            args = args[:i] + args[i + 2 :]
            break

    # TODO put definitions somewhere else
    PAGES = 128
    APPLICATION_END_PAGE = PAGES - 19
    AUTH_WORD_ADDR = flash_addr(APPLICATION_END_PAGE) - 8
    ATTEST_ADDR = flash_addr(PAGES - 15)

    first = IntelHex(args[1])
    for i in range(2, len(args) - 1):
        print('merging %s with ' % (args[1]), args[i])
        first.merge(IntelHex(args[i]), overlap='replace')

    first[flash_addr(APPLICATION_END_PAGE - 1)] = 0x41
    first[flash_addr(APPLICATION_END_PAGE - 1) + 1] = 0x41

    first[AUTH_WORD_ADDR - 4] = 0
    first[AUTH_WORD_ADDR - 1] = 0
    first[AUTH_WORD_ADDR - 2] = 0
    first[AUTH_WORD_ADDR - 3] = 0

    first[AUTH_WORD_ADDR] = 0
    first[AUTH_WORD_ADDR + 1] = 0
    first[AUTH_WORD_ADDR + 2] = 0
    first[AUTH_WORD_ADDR + 3] = 0

    first[AUTH_WORD_ADDR + 4] = 0xFF
    first[AUTH_WORD_ADDR + 5] = 0xFF
    first[AUTH_WORD_ADDR + 6] = 0xFF
    first[AUTH_WORD_ADDR + 7] = 0xFF

    if secret_attestation_key is not None:
        key = unhexlify(secret_attestation_key)

        for i, x in enumerate(key):
            first[ATTEST_ADDR + i] = x

    first.tofile(args[len(args) - 1], format='hex')
Example #3
0
    def binary_hook(t_self, resources, _, binf):
        """Hook that merges the soft device with the bin file"""
        # Scan to find the actual paths of soft device
        sdf = None
        for softdevice_and_offset_entry\
            in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
            for hexf in resources.hex_files:
                if hexf.find(softdevice_and_offset_entry['name']) != -1:
                    t_self.notify.debug("SoftDevice file found %s." %
                                        softdevice_and_offset_entry['name'])
                    sdf = hexf

                if sdf is not None:
                    break
            if sdf is not None:
                break

        if sdf is None:
            t_self.notify.debug("Hex file not found. Aborting.")
            return

        # Look for bootloader file that matches this soft device or bootloader
        # override image
        blf = None
        if t_self.target.MERGE_BOOTLOADER is True:
            for hexf in resources.hex_files:
                if hexf.find(t_self.target.OVERRIDE_BOOTLOADER_FILENAME) != -1:
                    t_self.notify.debug(
                        "Bootloader file found %s." %
                        t_self.target.OVERRIDE_BOOTLOADER_FILENAME)
                    blf = hexf
                    break
                elif hexf.find(softdevice_and_offset_entry['boot']) != -1:
                    t_self.notify.debug("Bootloader file found %s." %
                                        softdevice_and_offset_entry['boot'])
                    blf = hexf
                    break

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        _, ext = os.path.splitext(binf)
        if ext == ".hex":
            binh.loadhex(binf)
        elif ext == ".bin":
            binh.loadbin(binf, softdevice_and_offset_entry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            t_self.notify.debug("Merge SoftDevice file %s" %
                                softdevice_and_offset_entry['name'])
            sdh = IntelHex(sdf)
            binh.merge(sdh)

        if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
            t_self.notify.debug("Merge BootLoader file %s" % blf)
            blh = IntelHex(blf)
            binh.merge(blh)

        with open(binf.replace(".bin", ".hex"), "w") as fileout:
            binh.write_hex_file(fileout, write_start_addr=False)
Example #4
0
def main(options, args):
    # If using ANSI coloring is available, initialize colorama
    if fail_color:
        init()

    # Import intelhex if avaialable, otherwise fail
    try:
        from intelhex import IntelHex
    except:
        return fail(
            'error: You do not have \'intelhex\' installed. Please run \'pip install intelhex\' then retry.'
        )

    if len(options.output) is 0:
        print "No output file specified"
        exit(1)

    if len(args) < 2:
        return fail('Only one file was provided to merge.')
        exit(0)

    # Get the first hex file, merge the remainder and save the result
    orig = IntelHex(args[0])
    convert_start_addr(orig)

    args = args[1:]

    for arg in args:
        other = IntelHex(arg)
        convert_start_addr(other)
        orig.merge(other, overlap='replace')

    orig.write_hex_file(options.output)
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 #6
0
def build_image(stack, app, passkey, out):
    passkey_index = 0
    signature = 0xdeadbeef

    ih = IntelHex(app)

    for i in range(0, len(ih)):
        if ih[i] == (signature & 0xff) and ih[i + 1] == (
            (signature >> 8) & 0xff) and ih[i + 2] == (
                (signature >> 16) & 0xff) and ih[i + 3] == ((signature >> 24)
                                                            & 0xff):
            if passkey_index == 0:
                passkey_index = i
            else:
                raise RuntimeError('Found passkey signature twice?!')

    if passkey_index == 0:
        raise RuntimeError('Passkey signature was not found!')

    print('Setting new passkey %06d' % passkey)
    ih[passkey_index] = passkey & 0xff
    ih[passkey_index + 1] = (passkey >> 8) & 0xff
    ih[passkey_index + 2] = (passkey >> 16) & 0xff
    ih[passkey_index + 3] = (passkey >> 24) & 0xff

    stack = IntelHex(stack)
    ih.merge(stack)
    ih.write_hex_file(out, byte_count=32)
Example #7
0
    def binary_hook(t_self, resources, elf, binf):
        for hexf in resources.hex_files:
            found = False
            for softdeviceAndOffsetEntry in NRF51822.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
                if hexf.find(softdeviceAndOffsetEntry['name']) != -1:
                    found = True
                    break
            if found:
                break
        else:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        t_self.debug("Patching Hex file %s" % softdeviceAndOffsetEntry['name'])
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=softdeviceAndOffsetEntry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            sdh = IntelHex(hexf)
            binh.merge(sdh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            binh.tofile(f, format='hex')
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')
Example #9
0
    def binary_hook(t_self, resources, elf, binf):
        # Scan to find the actual paths of soft device and bootloader files
        sdf = None
        blf = None
        for hexf in resources.hex_files:
            if hexf.find(t_self.target.EXPECTED_BOOTLOADER_FILENAME) != -1:
                blf = hexf
            else:
                for softdeviceAndOffsetEntry in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
                    if hexf.find(softdeviceAndOffsetEntry['name']) != -1:
                        sdf = hexf
                        break

        if sdf is None:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=softdeviceAndOffsetEntry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            t_self.debug("Merge SoftDevice file %s" % softdeviceAndOffsetEntry['name'])
            sdh = IntelHex(sdf)
            binh.merge(sdh)

        if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
            t_self.debug("Merge BootLoader file %s" % t_self.target.EXPECTED_BOOTLOADER_FILENAME)
            blh = IntelHex(blf)
            binh.merge(blh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            binh.tofile(f, format='hex')
Example #10
0
def merge_region_list(region_list, destination, padding=b'\xFF'):
    """Merege the region_list into a single image

    Positional Arguments:
    region_list - list of regions, which should contain filenames
    destination - file name to write all regions to
    padding - bytes to fill gapps with
    """
    merged = IntelHex()

    print("Merging Regions:")

    for region in region_list:
        if region.active and not region.filename:
            raise ToolException("Active region has no contents: No file found.")
        if region.filename:
            print("  Filling region %s with %s" % (region.name, region.filename))
            part = intelhex_offset(region.filename, offset=region.start)
            part_size = (part.maxaddr() - part.minaddr()) + 1
            if part_size > region.size:
                raise ToolException("Contents of region %s does not fit"
                                    % region.name)
            merged.merge(part)
            pad_size = region.size - part_size
            if pad_size > 0 and region != region_list[-1]:
                print("  Padding region %s with 0x%x bytes" % (region.name, pad_size))
                merged.puts(merged.maxaddr() + 1, padding * pad_size)

    if not exists(dirname(destination)):
        makedirs(dirname(destination))
    print("Space used after regions merged: 0x%x" %
          (merged.maxaddr() - merged.minaddr() + 1))
    with open(destination, "wb+") as output:
        merged.tofile(output, format='bin')
Example #11
0
def merge_region_list(region_list, destination, padding=b'\xFF'):
    """Merege the region_list into a single image

    Positional Arguments:
    region_list - list of regions, which should contain filenames
    destination - file name to write all regions to
    padding - bytes to fill gapps with
    """
    merged = IntelHex()

    print("Merging Regions:")

    for region in region_list:
        if region.active and not region.filename:
            raise ToolException("Active region has no contents: No file found.")
        if region.filename:
            print("  Filling region %s with %s" % (region.name, region.filename))
            part = intelhex_offset(region.filename, offset=region.start)
            part_size = (part.maxaddr() - part.minaddr()) + 1
            if part_size > region.size:
                raise ToolException("Contents of region %s does not fit"
                                    % region.name)
            merged.merge(part)
            pad_size = region.size - part_size
            if pad_size > 0 and region != region_list[-1]:
                print("  Padding region %s with 0x%x bytes" % (region.name, pad_size))
                merged.puts(merged.maxaddr() + 1, padding * pad_size)

    if not exists(dirname(destination)):
        makedirs(dirname(destination))
    print("Space used after regions merged: 0x%x" %
          (merged.maxaddr() - merged.minaddr() + 1))
    with open(destination, "wb+") as output:
        merged.tofile(output, format='bin')
Example #12
0
    def binary_hook(t_self, resources, elf, binf):
        # Scan to find the actual paths of soft device and bootloader files
        sdf = None
        blf = None
        for hexf in resources.hex_files:
            if hexf.find(t_self.target.EXPECTED_BOOTLOADER_FILENAME) != -1:
                blf = hexf
            else:
                for softdeviceAndOffsetEntry in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
                    if hexf.find(softdeviceAndOffsetEntry['name']) != -1:
                        sdf = hexf
                        break

        if sdf is None:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=softdeviceAndOffsetEntry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            t_self.debug("Merge SoftDevice file %s" % softdeviceAndOffsetEntry['name'])
            sdh = IntelHex(sdf)
            binh.merge(sdh)

        if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
            t_self.debug("Merge BootLoader file %s" % t_self.target.EXPECTED_BOOTLOADER_FILENAME)
            blh = IntelHex(blf)
            binh.merge(blh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            binh.tofile(f, format='hex')
Example #13
0
    def binary_hook(t_self, resources, elf, binf):
        for hexf in resources.hex_files:
            found = False
            for softdeviceAndOffsetEntry in NRF51822.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
                if hexf.find(softdeviceAndOffsetEntry['name']) != -1:
                    found = True
                    break
            if found:
                break
        else:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        t_self.debug("Patching Hex file %s" % softdeviceAndOffsetEntry['name'])
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=softdeviceAndOffsetEntry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            sdh = IntelHex(hexf)
            binh.merge(sdh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            binh.tofile(f, format='hex')
Example #14
0
def combine(out_file, startup_hex, bootloader_hex, firmware_hex, bin_out):
    """This command makes a firmare file for initial programming of a "clean"
    defice. The firmware file is made by combining together the Start-up code,
    the Bootloader, and, optionally, the Main Firmware.
    """

    # Create initial firmware: begin with a HEX file of the Start-up code
    out_ih = IntelHex(startup_hex)

    # Read and process a HEX file of the Bootloader
    bootloader_ih = IntelHex(bootloader_hex)
    memmap = get_memmap(intelhex_to_bytes(bootloader_ih))
    intelhex_add_icr(bootloader_ih, memmap['bootloader_size'])
    out_ih.merge(bootloader_ih, overlap='ignore')

    # Read and process a HEX file of the Main Firmware if specified
    if firmware_hex:
        main_ih = IntelHex(firmware_hex)
        if main_ih.minaddr() != memmap['main_firmware_start']:
            raise click.ClickException(
                "Main Firmware is incomatible with the Bootloader")
        intelhex_add_icr(main_ih, memmap['main_firmware_size'])
        out_ih.merge(main_ih, overlap='ignore')

    # Write resulting firmware in HEX or binary format
    if bin_out:
        file_obj = open(out_file, "wb")
        file_obj.write(intelhex_to_bytes(out_ih))
        file_obj.close()
    else:
        out_ih.write_hex_file(out_file)
Example #15
0
    def binary_hook(t_self, resources, _, binf):
        """Hook that merges the soft device with the bin file"""
        # Scan to find the actual paths of soft device
        sdf = None
        for softdevice_and_offset_entry\
            in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
            for hexf in resources.hex_files:
                if hexf.find(softdevice_and_offset_entry['name']) != -1:
                    t_self.debug("SoftDevice file found %s."
                                 % softdevice_and_offset_entry['name'])
                    sdf = hexf

                if sdf is not None:
                    break
            if sdf is not None:
                break

        if sdf is None:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Look for bootloader file that matches this soft device or bootloader
        # override image
        blf = None
        if t_self.target.MERGE_BOOTLOADER is True:
            for hexf in resources.hex_files:
                if hexf.find(t_self.target.OVERRIDE_BOOTLOADER_FILENAME) != -1:
                    t_self.debug("Bootloader file found %s."
                                 % t_self.target.OVERRIDE_BOOTLOADER_FILENAME)
                    blf = hexf
                    break
                elif hexf.find(softdevice_and_offset_entry['boot']) != -1:
                    t_self.debug("Bootloader file found %s."
                                 % softdevice_and_offset_entry['boot'])
                    blf = hexf
                    break

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        _, ext = os.path.splitext(binf)
        if ext == ".hex":
            binh.loadhex(binf)
        elif ext == ".bin":
            binh.loadbin(binf, softdevice_and_offset_entry['offset'])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            t_self.debug("Merge SoftDevice file %s"
                         % softdevice_and_offset_entry['name'])
            sdh = IntelHex(sdf)
            binh.merge(sdh)

        if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
            t_self.debug("Merge BootLoader file %s" % blf)
            blh = IntelHex(blf)
            binh.merge(blh)

        with open(binf.replace(".bin", ".hex"), "w") as fileout:
            binh.write_hex_file(fileout, write_start_addr=False)
Example #16
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 #17
0
def mergehex(fn_1, fn_2):
    """
    merge two hex files write back to file 1.
    """
    ih_1 = IntelHex(fn_1)
    ih_2 = IntelHex(fn_2)
    ih_1.merge(ih_2)

    ih_1.tofile(fn_1, format='hex')
Example #18
0
def lpc55s69_complete(t_self, non_secure_bin, secure_bin):
    assert os.path.isfile(secure_bin)
    assert os.path.isfile(non_secure_bin)

    ns_hex = IntelHex(non_secure_bin)
    s_hex = IntelHex()
    s_hex.loadbin(secure_bin)

    s_hex.merge(ns_hex, overlap='ignore')
    s_hex.tofile(non_secure_bin, 'hex')
Example #19
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 #20
0
class MergeHex:
    def __init__(self, *args):
        self._ihex = IntelHex()
        for ihex in args:
            self.add(ihex)

    def add(self, ihex):
        self._ihex.merge(ihex, overlap='replace')

    def merged(self):
        return self._ihex
Example #21
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--output", required=True, type=pathlib.Path)
    parser.add_argument("--ds_hex", required=True, type=pathlib.Path)
    parser.add_argument("--xs_hex", required=True, type=pathlib.Path)

    option = parser.parse_args()

    ds_hex = IntelHex(str(option.ds_hex))
    xs_hex = IntelHex(str(option.xs_hex))
    ds_hex.merge(xs_hex)
    ds_hex.write_hex_file(option.output)
def merge_hex_files(output, input_hex_files):
    ih = IntelHex()

    for hex_file_path in input_hex_files:
        to_merge = IntelHex(hex_file_path)

        # Since 'arm-none-eabi-objcopy' incorrectly inserts record type '03 - Start Segment Address', we need to remove
        # the start_addr to avoid conflicts when merging.
        to_merge.start_addr = None

        ih.merge(to_merge)
    ih.write_hex_file(output)
Example #23
0
def mergehex(input_hex_files, output_hex_file, attestation_key=None):
    """Merges hex files, and patches in the attestation key.

    If no attestation key is passed, uses default Solo Hacker one.

    Note that later hex files replace data of earlier ones, if they overlap.
    """

    if attestation_key is None:
        # generic / hacker attestation key
        attestation_key = (
            "1b2626ecc8f69b0f69e34fb236d76466ba12ac16c3ab5750ba064e8b90e02448")

    # TODO put definitions somewhere else
    def flash_addr(num):
        return 0x08000000 + num * 2048

    PAGES = 128
    APPLICATION_END_PAGE = PAGES - 19
    AUTH_WORD_ADDR = flash_addr(APPLICATION_END_PAGE) - 8
    ATTEST_ADDR = flash_addr(PAGES - 15)

    first = IntelHex(input_hex_files[0])
    for input_hex_file in input_hex_files[1:]:
        print(f"merging {first} with {input_hex_file}")
        first.merge(IntelHex(input_hex_file), overlap="replace")

    first[flash_addr(APPLICATION_END_PAGE - 1)] = 0x41
    first[flash_addr(APPLICATION_END_PAGE - 1) + 1] = 0x41

    first[AUTH_WORD_ADDR - 4] = 0
    first[AUTH_WORD_ADDR - 1] = 0
    first[AUTH_WORD_ADDR - 2] = 0
    first[AUTH_WORD_ADDR - 3] = 0

    first[AUTH_WORD_ADDR] = 0
    first[AUTH_WORD_ADDR + 1] = 0
    first[AUTH_WORD_ADDR + 2] = 0
    first[AUTH_WORD_ADDR + 3] = 0

    first[AUTH_WORD_ADDR + 4] = 0xFF
    first[AUTH_WORD_ADDR + 5] = 0xFF
    first[AUTH_WORD_ADDR + 6] = 0xFF
    first[AUTH_WORD_ADDR + 7] = 0xFF

    # patch in the attestation key
    key = binascii.unhexlify(attestation_key)

    for i, x in enumerate(key):
        first[ATTEST_ADDR + i] = x

    first.tofile(output_hex_file, format="hex")
Example #24
0
    def binary_hook(t_self, resources, elf, binf):

        # Scan to find the actual paths of soft device
        sdf = None
        for softdeviceAndOffsetEntry in t_self.target.EXPECTED_SOFTDEVICES_WITH_OFFSETS:
            for hexf in resources.hex_files:
                if hexf.find(softdeviceAndOffsetEntry["name"]) != -1:
                    t_self.debug("SoftDevice file found %s." % softdeviceAndOffsetEntry["name"])
                    sdf = hexf

                if sdf is not None:
                    break
            if sdf is not None:
                break

        if sdf is None:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Look for bootloader file that matches this soft device or bootloader override image
        blf = None
        if t_self.target.MERGE_BOOTLOADER is True:
            for hexf in resources.hex_files:
                if hexf.find(t_self.target.OVERRIDE_BOOTLOADER_FILENAME) != -1:
                    t_self.debug("Bootloader file found %s." % t_self.target.OVERRIDE_BOOTLOADER_FILENAME)
                    blf = hexf
                    break
                elif hexf.find(softdeviceAndOffsetEntry["boot"]) != -1:
                    t_self.debug("Bootloader file found %s." % softdeviceAndOffsetEntry["boot"])
                    blf = hexf
                    break

        # Merge user code with softdevice
        from intelhex import IntelHex

        binh = IntelHex()
        binh.loadbin(binf, offset=softdeviceAndOffsetEntry["offset"])

        if t_self.target.MERGE_SOFT_DEVICE is True:
            t_self.debug("Merge SoftDevice file %s" % softdeviceAndOffsetEntry["name"])
            sdh = IntelHex(sdf)
            binh.merge(sdh)

        if t_self.target.MERGE_BOOTLOADER is True and blf is not None:
            t_self.debug("Merge BootLoader file %s" % blf)
            blh = IntelHex(blf)
            binh.merge(blh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            binh.tofile(f, format="hex")
Example #25
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 #26
0
def merge_hex_files(output, input_hex_files, overlap):
    ih = IntelHex()

    for hex_file_path in input_hex_files:
        to_merge = IntelHex(hex_file_path)

        # Since 'arm-none-eabi-objcopy' incorrectly inserts record
        # type '03 - Start Segment Address', we need to remove the
        # start_addr to avoid conflicts when merging.
        to_merge.start_addr = None

        try:
            ih.merge(to_merge, overlap=overlap)
        except AddressOverlapError:
            raise AddressOverlapError("{} has merge issues".format(hex_file_path))

    ih.write_hex_file(output)
Example #27
0
    def merge_secure(t_self, resources, ns_elf, ns_hex):
        t_self.notify.info("Merging non-secure image with secure image")
        configured_secure_image_filename = t_self.target.secure_image_filename
        t_self.notify.info("Non-secure elf image %s" % ns_elf)
        t_self.notify.info("Non-secure hex image %s" % ns_hex)
        t_self.notify.info("Finding secure image %s" % configured_secure_image_filename)
        s_hex = find_secure_image(
            t_self.notify,
            resources,
            ns_hex,
            configured_secure_image_filename,
            FileType.HEX
        )
        t_self.notify.info("Found secure image %s" % s_hex)

        _, ext = os.path.splitext(s_hex)
        if ext != ".hex":
            t_self.notify.debug("Secure image %s must be in Intel HEX format" % s_hex)
            return
        if not os.path.isfile(s_hex):
            t_self.notify.debug("Secure image %s must be regular file" % s_hex)
            return

        ns_main, ext = os.path.splitext(ns_hex)
        if ext != ".hex":
            t_self.notify.debug("Non-secure image %s must be in Intel HEX format" % s_hex)
            return
        if not os.path.isfile(ns_hex):
            t_self.notify.debug("Non-secure image %s must be regular file" % s_hex)
            return

        # Keep original non-secure before merge with secure
        ns_nosecure_hex = ns_main + "_no-secure-merge" + ext
        t_self.notify.info("Keep no-secure-merge image %s" % ns_nosecure_hex)
        shutil.copy2(ns_hex, ns_nosecure_hex)

        # Merge secure and non-secure and save to non-secure (override it)
        from intelhex import IntelHex
        s_ih = IntelHex()
        s_ih.loadhex(s_hex)
        ns_ih = IntelHex()
        ns_ih.loadhex(ns_hex)
        ns_ih.start_addr = None
        s_ih.merge(ns_ih)
        s_ih.tofile(ns_hex, 'hex')
Example #28
0
def merge_region_list(region_list, destination, notify, padding=b'\xFF'):
    """Merge the region_list into a single image

    Positional Arguments:
    region_list - list of regions, which should contain filenames
    destination - file name to write all regions to
    padding - bytes to fill gapps with
    """
    merged = IntelHex()
    _, format = splitext(destination)

    notify.info("Merging Regions")

    for region in region_list:
        if region.active and not region.filename:
            raise ToolException("Active region has no contents: No file found.")
        if isinstance(region.filename, list):
            header_basename, _ = splitext(destination)
            header_filename = header_basename + "_header.hex"
            _fill_header(region_list, region).tofile(header_filename, format='hex')
            region = region._replace(filename=header_filename)
        if region.filename:
            notify.info("  Filling region %s with %s" % (region.name, region.filename))
            part = intelhex_offset(region.filename, offset=region.start)
            part.start_addr = None
            part_size = (part.maxaddr() - part.minaddr()) + 1
            if part_size > region.size:
                raise ToolException("Contents of region %s does not fit"
                                    % region.name)
            merged.merge(part)
            pad_size = region.size - part_size
            if pad_size > 0 and region != region_list[-1]:
                notify.info("  Padding region %s with 0x%x bytes" %
                            (region.name, pad_size))
                if format is ".hex":
                    """The offset will be in the hex file generated when we're done,
                    so we can skip padding here"""
                else:
                    merged.puts(merged.maxaddr() + 1, padding * pad_size)

    if not exists(dirname(destination)):
        makedirs(dirname(destination))
    notify.info("Space used after regions merged: 0x%x" %
                (merged.maxaddr() - merged.minaddr() + 1))
    merged.tofile(destination, format=format.strip("."))
Example #29
0
    def binary_hook(t_self, resources, elf, binf):
        for hexf in resources.hex_files:
            if hexf.find(NRF51822.EXPECTED_SOFTDEVICE) != -1:
                break
        else:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=NRF51822.APPCODE_OFFSET)

        sdh = IntelHex(hexf)
        sdh.merge(binh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
            sdh.tofile(f, format='hex')
Example #30
0
    def binary_hook(t_self, resources, elf, binf):
        for hexf in resources.hex_files:
            if hexf.find(NRF51822.EXPECTED_SOFTDEVICE) != -1:
                break
        else:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset = NRF51822.APPCODE_OFFSET)

        sdh = IntelHex(hexf)
        sdh.merge(binh)

        with open(binf.replace(".bin", ".hex"), "w") as f:
           sdh.tofile(f, format = 'hex')
Example #31
0
    def test_bl_pieces(self, mock_intelhex_offset, mock_exists, mock_isabs):
        """

        :param mock_intelhex_offset: mock intel_hex_ofset call
        :param mock_exists: mock the file exists call
        :param mock_isabs: mock the isabs call
        :return:
        """
        """
        Test that merge region fails as expected when part size overflows region size.
        """
        cfg = Config('NRF52_DK')
        mock_exists.return_value = True
        mock_isabs.return_value = True
        max = 0x960
        #create mock MBR and BL and merge them
        mbr = IntelHex()
        for v in range(max):
            mbr[v] = v

        bl = IntelHex()
        min = 0x16000
        max = 0x22000
        for v in range(min, max):
            bl[v] = v
        mbr.merge(bl)

        mock_intelhex_offset.return_value = mbr

        # Place application within the bootloader and verify
        # that config exception is generated
        cfg.target.bootloader_img = True
        cfg.target.app_offset = min + 0x200
        cfg.target.restrict_size = '4096'

        ce = False
        if cfg.has_regions:
            try:
                for r in list(cfg.regions):
                    print(r)
            except ConfigException:
                    ce = True

        self.assertTrue(ce)
Example #32
0
def main(arguments):
    # If using ANSI coloring is available, initialize colorama
    if fail_color:
        init()

    # Import intelhex if avaialable, otherwise fail
    try:
        from intelhex import IntelHex
    except:
        return fail('error: You do not have \'intelhex\' installed. Please run \'pip install intelhex\' then retry.')

    # Ensure the right number of arguments are supplied
    if not len(arguments) == 3:
        return fail('error: Improper use of merge_hex.py.\nUSAGE: merge_hex.py input_file1 input_file2 output_file.')

    # Get the two hex files, merge them, and save the result
    orig = IntelHex(arguments[0])
    new = IntelHex(arguments[1])
    orig.merge(new, overlap='replace')
    orig.write_hex_file(arguments[2])
Example #33
0
def merge_hex_executables(target, source, env):
    """Combine all hex files into a singular executable file."""
    output_name = str(target[0])

    hex_final = IntelHex()
    for image in source:
        file = str(image)
        root, ext = os.path.splitext(file)
        file_format = ext[1:]
        if file_format == 'elf':
            file = root + '.hex'
        hex_data = IntelHex(file)

        # merge will throw errors on mismatched Start Segment Addresses, which we don't need
        # See <https://stackoverflow.com/questions/26295776/what-are-the-intel-hex-records-type-03-or-05-doing-in-ihex-program-for-arm>
        hex_data.start_addr = None
        hex_final.merge(hex_data, overlap='error')

    with open(output_name, 'w') as outfile:
        hex_final.write_hex_file(outfile)
Example #34
0
 def binary_hook(t_self, resources, elf, binf):
     for hexf in resources.hex_files:
         if hexf.find(NRF51822.EXPECTED_SOFTDEVICE) != -1:
             break
     else:
         t_self.debug("Hex file not found. Aborting.")
         return
     
     # Merge user code with softdevice
     from intelhex import IntelHex
     binh = IntelHex()
     binh.loadbin(binf, offset = NRF51822.APPCODE_OFFSET)
     
     sdh = IntelHex(hexf)
     sdh.merge(binh)
     
     # Remove UICR section
     del sdh[NRF51822.UICR_START:NRF51822.UICR_END+1]
     
     with open(binf, "wb") as f:
         sdh.tofile(f, format = 'bin')
Example #35
0
    def binary_hook(t_self, resources, elf, binf):
        for hexf in resources.hex_files:
            if hexf.find(NRF51822.EXPECTED_SOFTDEVICE) != -1:
                break
        else:
            t_self.debug("Hex file not found. Aborting.")
            return

        # Merge user code with softdevice
        from intelhex import IntelHex
        binh = IntelHex()
        binh.loadbin(binf, offset=NRF51822.APPCODE_OFFSET)

        sdh = IntelHex(hexf)
        sdh.merge(binh)

        # Remove UICR section
        del sdh[NRF51822.UICR_START:NRF51822.UICR_END + 1]

        with open(binf, "wb") as f:
            sdh.tofile(f, format='bin')
Example #36
0
def provisionDevice(
    model
):  # create New Device Account , create backupHex file, Flash the device
    FactoryDevHex = IntelHex("BootAppConfig.hex")
    keySectionApp = IntelHex()  # contain key  section of hex file
    #update key section
    #keys A4T4 is stored for "AT" in eeprom
    if (not fbLoginSucess()):
        printE("Login to provision")
        return
    #register new device and load SN
    maxSn = fbReadDb("FirmwareMeta/" + model + "/MaxSn")
    fbWriteDb("FirmwareMeta/" + model + "/MaxSn", maxSn + 1)

    DevSn = base36encode(maxSn, 6)
    userid = model + DevSn  # 8 bytes
    passkey = get_random_password_string(8)  #pass key 8 bytes

    #get model key From Server, makeure for any new device modle key is generated manually
    ModelKey = fbReadDb("FirmwareMeta/" + model +
                        "/ModelKey")  # "MODEL"+model+"0" #8 bytes

    fbWriteDb("FirmwareMeta/" + model + "/DevSnKeys/" + userid, passkey)
    #mearge hex file with keys and generate device hex file

    keysection = userid + passkey + ModelKey + passkey  # last passkey is just filler
    eepKeySection = insertByteAfterOne(
        bytes(passkey + ModelKey, 'utf-8'), 0
    )  # this keys are also loaded into EEP so that user need not have to to FDR
    keysectionFlash = insertByteAfterOne(bytes(
        keysection, 'utf-8'), 0x34)  # 34 in msb signify flash constant
    keySectionApp.puts(KEY_START_ADD * FLASH_WORD_SIZE, keysectionFlash)
    keySectionApp.puts(EEP_KEY_START_ADD * FLASH_WORD_SIZE, eepKeySection)
    FactoryDevHex.merge(keySectionApp)
    FactoryDevHex.write_hex_file("Factory" + model + DevSn + ".hex",
                                 False)  # don't write start address

    currentDevPath = "Factory" + model + DevSn + ".hex"
    return currentDevPath
def combine(bootloader_fn, app_fn, app_addr, hdr_addr, bootloader_addr,
            output_fn, version, no_bootloader):
    # read bootloader
    bootloader_format = bootloader_fn.split('.')[-1]
    bootloader = IntelHex()
    if not no_bootloader:
        if bootloader_format == 'hex':
            bootloader.fromfile(bootloader_fn, bootloader_format)
        elif bootloader_format == 'bin':
            bootloader.loadbin(bootloader_fn, bootloader_addr)
        else:
            print('Bootloader format can only be .bin or .hex')
            exit(-1)

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

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

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

    # write output file
    output.tofile(output_fn, format=output_format)
Example #38
0
    def merge_hex(self, hex1, hex2, target):
        ih = IntelHex(hex1)
        ih.merge(IntelHex(hex2))

        ih.write_hex_file(target)
Example #39
0
if not os.path.exists(sys.argv[1]):
	sys.exit("Unable open build %s" % sys.argv[1])
if not os.path.exists(sys.argv[2]):
	sys.exit("Unable open build %s" % sys.argv[2])
build_filename = sys.argv[1]
prog_filename = sys.argv[2]

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

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

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

# done
Example #40
0
    print_console_header()

    # Parse and merge hex files
    #iterate over input hexfiles, intelhexify them
    #if we cannot merge or open the hex files, the script is hosed, print and abort
    ihs = []
    inputFileNames = []
    mergedHex = IntelHex()

    for f in vargs.hexfile:
        try:
            ih = IntelHex(f)
            inputFileNames.append(f.name)
            ihs.append(ih)
            try:
                mergedHex.merge(ih, overlap='replace')
            except:
                print("Fatal Error: -- FAILED merge due to overlap when merging " + f.name)
                sys.exit(1)
        except:
            print("Fatal Error: -- FAILED parsing input hex file(s)")
            sys.exit(1)

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

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

Example #41
0
def generateFlashAndEepromHex(originalFlashHexName, bootloaderHexName, serialNumber, AESKey1, AESKey2, UIDKey, UID, newFlashHexName, newEeepromHex, verbose):
	FW_MAX_LENGTH = 28672
	BL_MAX_LENGTH = 4096
	AES_KEY_LENGTH = 256/8
	AES_BLOCK_LENGTH = 128/8
	UID_REQUEST_KEY_LENGTH = 16
	UID_KEY_LENGTH = 6
	
	# Check for original firmware file presence
	if not os.path.isfile(originalFlashHexName):
		print "Couldn't find firmware hex file", originalFlashHexName
		return False
				
	# Check for bootloader file presence
	if not os.path.isfile(bootloaderHexName):
		print "Couldn't find bootloader hex file", bootloaderHexName
		return False
		
	# Check AES Key Length
	if len(AESKey1) != AES_KEY_LENGTH:
		print "Wrong AES Key1 length!"
		return False
		
	# Check AES Key Length
	if len(AESKey2) != AES_KEY_LENGTH:
		print "Wrong AES Key2 length!"
		return False
		
	# Check UID Req Key Length
	if len(UIDKey) != UID_REQUEST_KEY_LENGTH:
		print "Wrong UID request key length!"
		return False
		
	# Check UID Key Length
	if len(UID) != UID_KEY_LENGTH:
		print "Wrong UID key length!"
		return False
		
	# Read firmware Hex
	flashHex = IntelHex(originalFlashHexName)
	if len(flashHex) > FW_MAX_LENGTH:
		print "Firmware file too long:", len(flashHex), "bytes long"
		return False
	else:	
		if verbose == True:
			print "Firmware file is", len(flashHex), "bytes long"
	
	# Read bootloader hex
	bootloaderHex = IntelHex(bootloaderHexName)
	if len(bootloaderHex) > BL_MAX_LENGTH:
		print "Bootloader file too long:", len(bootloaderHex), "bytes long"
		return False
	else:	
		if verbose == True:
			print "Bootloader file is", len(bootloaderHex), "bytes long"
	
	# Merge firmware with bootloader	
	flashHex.merge(bootloaderHex)
	
	# Print hash if need
	if verbose == True:
		print "Original Firmware/Bootloader Hash:", hashlib.sha1(flashHex.tobinarray()).hexdigest()
		
	# Check there's nothing where we want to put the serial number
	if flashHex[0x7F7C] != 0xFF:
		print "No space to write serial number inside the bootloader hex!"
		return False

	# Include serial number in the hex to be flashed
	flashHex[0x7F7C] = (serialNumber >> 24) & 0x000000FF
	flashHex[0x7F7D] = (serialNumber >> 16) & 0x000000FF
	flashHex[0x7F7E] = (serialNumber >> 8) & 0x000000FF
	flashHex[0x7F7F] = (serialNumber >> 0) & 0x000000FF
	
	# Write production firmware file
	flashHex.tofile(newFlashHexName, format="hex")
	
	# Generate blank eeprom file
	eepromHex = IntelHex()
	for i in range(0x400):
		eepromHex[i] = 0xFF
		
	# Modify the byte in eeprom to indicate normal boot
	# Address 0: 0xDEAD, little endian
	eepromHex[0] = 0xAD
	eepromHex[1] = 0xDE
	# Address 2: 0xAB (bootloader password set)
	eepromHex[2] = 0xAB
	# Address 98: mass production boolean 
	eepromHex[98] = 0xCD
	# Address 999: boolean specifiying that uid key is set
	eepromHex[999] = 0xBB
	# Address 1000: UID request key
	eepromHex[1000:1000+UID_REQUEST_KEY_LENGTH] = UIDKey
	# Address 1016: UID key
	eepromHex[1000+UID_REQUEST_KEY_LENGTH:1000+UID_REQUEST_KEY_LENGTH+UID_KEY_LENGTH] = UID
	# Address 0x03: 32 bytes of AES key 1 + 30 first bytes of AES key 2
	eepromHex[3:3+AES_KEY_LENGTH] = AESKey1
	eepromHex[3+AES_KEY_LENGTH:3+AES_KEY_LENGTH+30] = AESKey2[0:30]
	# Last 2 bytes in EEPROM: last 2 AESKey 2 bytes
	eepromHex[0x400-2] = AESKey2[30]
	eepromHex[0x400-1] = AESKey2[31]
	
	# Write new eeprom file
	eepromHex.tofile(newEeepromHex, format="hex")
Example #42
0
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:
    print ' probably already merged, data overlap! CHECK THIS!'
finally:
    hx_fn = 'DKSF_' + ver + '_HX.hex'
    print 'Writing', hx_fn, '...',
    ih.write_hex_file(hx_fn)
    print 'Ok'

npf = ''
npf += fwstart
npf += code 
npf += fwend
npf += resstart
npf += res
Example #43
0
    print_console_header()

    # Parse and merge hex files
    # iterate over input hexfiles, intelhexify them
    # if we cannot merge or open the hex files, the script is hosed, print and abort
    ihs = []
    inputFileNames = []
    mergedHex = IntelHex()

    for f in vargs.hexfile:
        try:
            ih = IntelHex(f)
            inputFileNames.append(f.name)
            ihs.append(ih)
            try:
                mergedHex.merge(ih, overlap="replace")
            except:
                print("Fatal Error: -- FAILED merge due to overlap when merging " + f.name)
                sys.exit(1)
        except:
            print("Fatal Error: -- FAILED parsing input hex file(s)")
            sys.exit(1)

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

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

    # Cut off / fill with --fill.