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])
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')
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)
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)
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)
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')
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')
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')
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)
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)
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
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')
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')
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
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
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)
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")
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")
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
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)
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')
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("."))
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')
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')
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)
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])
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)
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')
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')
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)
def merge_hex(self, hex1, hex2, target): ih = IntelHex(hex1) ih.merge(IntelHex(hex2)) ih.write_hex_file(target)
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
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)
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")
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
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.