def main(): '''Main program''' # Determine program name, for error messages. pgmname = os.path.split(sys.argv[0])[-1] # Determine help text width. try: help_width = int(os.environ['COLUMNS']) except (KeyError, ValueError): help_width = 80 help_width -= 2 parser = argparse.ArgumentParser( prog = pgmname, formatter_class = argparse.RawDescriptionHelpFormatter, description = textwrap.fill( "A tool to prepare EFR32 stack hex file for v4.0 to v5.0 upgrade.")) parser.add_argument("infilespec", metavar = "INFILESPEC", help = "stack hex file") parser.add_argument("--output", "-o", metavar = "OUTFILESPEC", help = "output file") try: args = parser.parse_args() memory = hextool.Memory() hextool.load_intel_hex(memory, filename = args.infilespec) # Move first page off stack just before the v3 bootloader data. first_page = memory[memory.min_address:memory.min_address + PAGE_SIZE] memory.cursor = FIRST_PAGE_ADDRESS memory += first_page del memory[memory.min_address:memory.min_address + PAGE_SIZE] if args.output is not None: # Save output file. hextool.save_intel_hex(memory, filename=args.output) else: hextool.save_intel_hex(memory, filename=args.infilespec) except (ValueError, IOError, OSError) as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 0
def __init__(self, file_spec = None, data = None, version = (0, 0, 0, 0)): if file_spec == None and data == None: raise ValueError("no data given") elif file_spec != None and data != None: raise ValueError("file_spec and data are mutually exclusive") # Set default values. self.area_id = 0x00000000 self.version = version self.compressed = False self.encrypted = False if data: # Data given, make a copy of it. self.data = bytearray(data) self.raw_data = bytearray(data) else: # File specification given, parse it. version, self.area_id, filename = self.parse_file_spec(file_spec) self.version = self.parse_version(version) # Read data from file. memory = hextool.Memory() hextool.load_intel_hex(memory, filename = filename) if memory.num_ranges == 0: # No data found in file. raise ValueError("file contains no data: '%s'" % filename) elif (memory.max_address - memory.min_address > self.MAX_NUM_BYTES_PER_FILE): raise ValueError("file too big: '%s'" % filename) # Convert Memory object to a flat bytearray. self.data = memory[memory.min_address:memory.max_address] self.raw_data = memory[memory.min_address:memory.max_address] # Create a file header for uncompressed, unencrypted data. self.header = self.make_file_header(self.area_id, len(self.data), *self.version)
def main(): '''Main program''' # Determine program name, for error messages. pgmname = os.path.split(sys.argv[0])[-1] # Create a parser for parsing the command line and printing error messages. parser = create_argument_parser(pgmname) try: # Parse command line arguments. args = parse_arguments(parser) # Parse configuration file. config = BootloaderConfig.from_ini_files(args.configfile, args.symbols) # Check that config is valid # ValueError exception will be raised in case of invalid config config.check_config() # Check the key chosen is declared try: chosenkey = config.keys[args.keyname] except KeyError: raise ValueError("key not found: '%s'" % args.keyname) except (ValueError, IOError, OSError, configparser.Error) as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 if False: # DEBUG: Show config. for key in config.keys.items(): print(key) # Create a Memory object for storing the bootloader. bootloader = hextool.Memory() if args.bootloader: # Read bootloader. hextool.load_intel_hex(bootloader, filename=args.bootloader) in_files = [] # List of InFile objects # (header, area_id, version, data) scratchpad_data = [] # List of scratchpad data blocks ver_major, ver_minor, ver_maint, ver_devel = (0, 0, 0, 0) if AES_TEST: # Run AES test. See aes_test1() in utils/aes.c for details. in_files.append(InFile(data=test_data)) scratchpad_data.append(test_icb) elif CMAC_TEST: # Run CMAC / OMAC1 test. See aes_omac1_test1() # in utils/aes.c for details. scratchpad_data.append(test_data) else: # Read input files. try: for file_spec in args.infilespec: # Create an InFile object. in_file = InFile(file_spec=file_spec, version=(0, 0, 0, args.otapseq)) # Compress data in-place. in_file.compress() in_files.append(in_file) except (ValueError, IOError, OSError) as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 # Create secure header, which is also the initial counter block (ICB). secure_header = get_random_bytes(16) scratchpad_data.append(secure_header) if not CMAC_TEST: try: # Create an AES Counter (CTR) mode cipher using secure # header as the 16-byte initial counter block (ICB). cipher = create_cipher(secure_header, chosenkey.encryption) # Encrypt each input file. for in_file in in_files: # Encrypt data in-place. in_file.encrypt(cipher) # Add file header to scratchpad data. scratchpad_data.append(in_file.header) # Add compressed, encrypted file data to scratchpad data. scratchpad_data.append(in_file.data) except ValueError as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 # Calculate and add CMAC / OMAC1 tag. try: cmac = calculate_cmac(scratchpad_data, chosenkey.authentication) scratchpad_data.insert(0, cmac) except ValueError as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 if not AES_TEST and not CMAC_TEST: # Create a scratchpad header. try: scratchpad_header = make_scratchpad_header(args.otapseq, scratchpad_data) except ValueError as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 else: scratchpad_header = bytes() # Write output file and optionally the programming image file. try: with open(args.outfile, "wb") as f: # A combi scratchpad file starts with a 16-byte tag. f.write(SCRATCHPAD_V1_TAG) # Combi scratchpad files have the scratchpad header in front of # the scratchpad contents. The firmware rearranges the data in # Flash memory while storing the scratchpad. f.write(scratchpad_header) # Write scratchpad contents. for data in scratchpad_data: f.write(data) if args.genprog == None: return 0 # Combine bootloader, memory area specification, keys and scratchpad. file_without_scr = args.genprog.rsplit('.',1)[0] + \ "_without_scratchpad.hex" if config.is_scratchpad_internal(): # Generate a programming image (bootloader + scratchpad file) # and save it as Intel HEX. memory = gen_prog_image(config, bootloader, scratchpad_header, scratchpad_data) hextool.save_intel_hex(memory, filename=args.genprog) # Also generate a programming image without scratchpad # (bl+stack+app) for debug purposes and save it as Intel HEX. memory = gen_prog_image_without_scratchpad(config, bootloader, scratchpad_data, in_files) hextool.save_intel_hex(memory, filename=file_without_scr) else: # config.is_scratchpad_internal(): # Generate a programming image without scratchpad (bl+stack+app). # and save it as Intel HEX. memory = gen_prog_image_without_scratchpad(config, bootloader, scratchpad_data, in_files) hextool.save_intel_hex(memory, filename=file_without_scr) except (ValueError, IOError, OSError) as exc: sys.stdout.write("%s: %s\n" % (pgmname, exc)) return 1 return 0
def __init__(self, config, bootloader): self.config = config bl_without_config = hextool.Memory() hextool.load_intel_hex(bl_without_config, filename=bootloader) self.bootloader = self.gen_bootloader(bl_without_config) self.infiles = [] # List of data blocks
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # hextoarray32.py - A tool to convert an hex file to an array of 32-bit numbers import sys import os import struct import hextool LINE_INDENT = " " LINE_LENGTH = 72 # Open hex file and convert it to byte array memory = hextool.Memory() hextool.load_intel_hex(memory, filename=sys.argv[1]) # For EFR32 delete range in special registers [0xfe04000-0xfe04200] del memory[0xfe04000:0xfe04200] data = memory[memory.min_address:memory.max_address] # Open outfile and write uint32 array with open(sys.argv[2], "w") as f: line = LINE_INDENT for pos in range(0, len(data), 4): if pos != 0: line += ", " if len(line) >= LINE_LENGTH: f.write(line) f.write("\n")