def dumpV2(self, all): start_address = 0x3ff2 if all else 0x37f8 cmd_verif = [0xa6, 0, 0, 0, 0, 0, 0, 0] cmd_verif[1] = 5 + 8 # find block of 8 0xFF at the end of the device memory block = [0xff] * 8 found = False data = [d ^ self.scrambleCodeV2[i % 8] for i, d in enumerate(block)] for address in range(start_address, -1, -1): print('Looking for 0xFF block at address 0x{:04X}'.format( address), end='\n') cmd_verif[3:5] = address & 0xFF, (address >> 8) & 0xFF r, _ = self.cmd_verify_v2(bin_str_of_list(cmd_verif + data)) if r == 0: print('\nFound 0xFF block at address 0x{:04X}'.format(address)) found = True break if not found: print('\nUnable to find 0xFF block') return memdump = IntelHex() memdump.puts(address, bin_str_of_list(block)) print('Starting flash dumping') for i in reversed(block): print('{:02X} '.format(i), end='') sys.stdout.flush() nTry = 0 nBytes = 0 for address in range(address - 1, -1, -1): block[1:] = block[:-1] # shift cmd_verif[3:5] = address & 0xFF, (address >> 8) & 0xFF found = False for i in range(256): val = stats[i] block[0] = val nTry += 1 data = [d ^ self.scrambleCodeV2[i % 8] for i, d in enumerate(block)] r, _ = self.cmd_verify_v2(bin_str_of_list(cmd_verif + data),9) if r == 0: # verification ok, we found the correct byte print('{:02X} '.format(val), end='') sys.stdout.flush() found = True nBytes += 1 memdump[address] = val break if not found: raise ValueError('Unable to find correct ' 'byte for address 0x{:04X}'.format(address)) output_bin = 'out.bin' output_hex = 'out.hex' print('\nDone, writing output files {} and {}'.format(output_bin, output_hex)) print('Ntry = {} {:.2f}try/bytes'.format(nTry, float(nTry) / nBytes)) memdump.tobinfile(output_bin) memdump.tofile(output_hex, format='hex')
def post_process(self): logging.info("Processing binaries") # save original dir cwd = os.getcwd() # change to target dir os.chdir(self.target_dir) ih = IntelHex('main.hex') fwid = uuid.UUID('{' + self.settings["FWID"] + '}') size = ih.maxaddr() - ih.minaddr() + 1 # get os info os_project = get_project_builder(self.settings["OS_PROJECT"]) # create firmware info structure fw_info = struct.pack('<I16s128s16s128s16s', size, fwid.bytes, os_project.proj_name, os_project.version, self.proj_name, self.version) # insert fw info into hex ih.puts(0x120, fw_info) # compute crc crc_func = crcmod.predefined.mkCrcFun('crc-aug-ccitt') crc = crc_func(ih.tobinstr()) logging.info("size: %d" % (size)) logging.info("fwid: %s" % (fwid)) logging.info("crc: 0x%x" % (crc)) logging.info("os name: %s" % (os_project.proj_name)) logging.info("os version: %s" % (os_project.version)) logging.info("app name: %s" % (self.proj_name)) logging.info("app version: %s" % (self.version)) ih.puts(ih.maxaddr() + 1, struct.pack('>H', crc)) ih.write_hex_file('main.hex') ih.tobinfile('firmware.bin') # get loader info loader_project = get_project_builder(self.settings["LOADER_PROJECT"]) # create loader image loader_hex = os.path.join(loader_project.target_dir, "main.hex") self.merge_hex('main.hex', loader_hex, 'loader_image.hex') # change back to original dir os.chdir(cwd)
def tofile(self, outfile: Union[str, IO]) -> None: ih = IntelHex() ih.puts(self.base or 0, bytes(self.fw)) if Firmware._ishex(outfile): if not isinstance(outfile, str): outfile = io.TextIOWrapper(outfile) ih.write_hex_file(outfile) else: ih.tobinfile(outfile)
def dump(self): end_address = 0x3ff0 # send the key b = '\xa6\x04' + struct.pack('BBBB', *scrambleCode) self.xcmd(b, 0) # find block of 16 0xFF at the end of the device memory block = [0xff] * 16 found = False for address in range(end_address, -1, -1): print('\rLooking for address 0x{:04X}'.format(address), end='') r = self.cmd('\xa7\16' + struct.pack('<H', address) + bin_str_of_list(scramble(block))) if r == 0: print('\nFound 0xFF block at address 0x{:04X}'.format(address)) found = True break if not found: print('\nUnable to find 0xFF block') return memdump = IntelHex() memdump.puts(address, bin_str_of_list(block)) print('Starting flash dumping') base = [0xa7, 16, 0, 0] nTry = 0 nBytes = 0 for address in range(address - 1, - 1, -1): block[1:] = block[:-1] # shift base[2:4] = address & 0xFF, address >> 8 found = False for i in range(256): i = stats[i] block[0] = i nTry += 1 r = self.cmd(bin_str_of_list(base + scramble(block)), 4) if r == 0: # verification ok, we found the correct byte print('{:02X} '.format(i), end='') sys.stdout.flush() found = True nBytes += 1 memdump[address] = i break if not found: raise ValueError('Unable to find correct ' 'byte for address 0x{:04X}'.format(address)) output_bin = 'out.bin' output_hex = 'out.hex' print('\nDone, writing output files {} and {}'.format(output_bin, output_hex)) print('Ntry = {} {:.2f}try/bytes'.format(nTry, float(nTry) / nBytes)) memdump.tobinfile(output_bin) memdump.tofile(output_hex, format='hex')
def build_target_firmware(self, parent_test): """ Build test firmware for the board Login credentials must have been set with set_build_login. """ prebuilt = self._target_dir is not None build_login = (self._username is not None and self._password is not None) assert prebuilt or build_login if prebuilt: destdir = self._target_dir else: destdir = 'tmp' build_name = board_id_to_build_target[self.get_board_id()] name_base = os.path.normpath(destdir + os.sep + build_name) self._target_hex_path = name_base + '.hex' self._target_bin_path = name_base + '.bin' # Build target test image if a prebuild location is not specified if not prebuilt: test_info = parent_test.create_subtest('build_target_test_firmware') if not os.path.isdir(destdir): os.mkdir(destdir) # Remove previous build files if os.path.isfile(self._target_hex_path): os.remove(self._target_hex_path) if os.path.isfile(self._target_bin_path): os.remove(self._target_bin_path) test_info.info('Starting remote build') start = time.time() built_file = mbedapi.build_repo(self._username, self._password, TEST_REPO, build_name, destdir) stop = time.time() test_info.info("Build took %s seconds" % (stop - start)) extension = os.path.splitext(built_file)[1].lower() assert extension == '.hex' or extension == '.bin' if extension == '.hex': intel_hex = IntelHex(built_file) # Only supporting devices with the starting # address at 0 currently assert intel_hex.minaddr() == 0 intel_hex.tobinfile(self._target_bin_path) os.rename(built_file, self._target_hex_path) if extension == '.bin': intel_hex = IntelHex() intel_hex.loadbin(built_file, offset=0) intel_hex.tofile(self._target_hex_path, 'hex') os.rename(built_file, self._target_bin_path) # Assert that required files are present assert os.path.isfile(self._target_hex_path) assert os.path.isfile(self._target_bin_path) self._target_firmware_present = True
def program(self, args): board = self._setup() board.flash.init() tmp_bin_file = 'tmp.bin' if args.sectorsanduicrerase: self._erase_uicr(board.target) # TODO: May not be needed if pyOCD does this. Double check before removing. hex_file = IntelHex(args.file) hex_file.tobinfile(tmp_bin_file) board.flash.flashBinary(tmp_bin_file, chip_erase=args.eraseall, fast_verify=args.verify) if args.debugreset or args.pinreset or args.systemreset: board.target.reset() os.remove(tmp_bin_file)
def build_target_bundle(directory, username, password, parent_test=None): """Build target firmware package""" if parent_test is None: parent_test = TestInfoStub() target_names = info.TARGET_NAME_TO_BOARD_ID.keys() for build_name in target_names: name_base = os.path.normpath(directory + os.sep + build_name) target_hex_path = name_base + '.hex' target_bin_path = name_base + '.bin' # Build target test image test_info = parent_test.create_subtest('Building target %s' % build_name) if not os.path.isdir(directory): os.mkdir(directory) # Remove previous build files if os.path.isfile(target_hex_path): os.remove(target_hex_path) if os.path.isfile(target_bin_path): os.remove(target_bin_path) test_info.info('Starting remote build') start = time.time() built_file = mbedapi.build_repo(username, password, TEST_REPO, build_name, directory) stop = time.time() test_info.info("Build took %s seconds" % (stop - start)) extension = os.path.splitext(built_file)[1].lower() assert extension == '.hex' or extension == '.bin' if extension == '.hex': intel_hex = IntelHex(built_file) # Only supporting devices with the starting # address at 0 currently assert intel_hex.minaddr() == 0 intel_hex.tobinfile(target_bin_path) os.rename(built_file, target_hex_path) if extension == '.bin': intel_hex = IntelHex() intel_hex.loadbin(built_file, offset=0) intel_hex.tofile(target_hex_path, 'hex') os.rename(built_file, target_bin_path) # Assert that required files are present assert os.path.isfile(target_hex_path) assert os.path.isfile(target_bin_path)
def build_target_bundle(directory, username, password, parent_test=None): """Build target firmware package""" if parent_test is None: parent_test = TestInfoStub() target_names = info.TARGET_WITH_COMPILE_API_LIST for build_name in target_names: name_base = os.path.normpath(directory + os.sep + build_name) target_hex_path = name_base + '.hex' target_bin_path = name_base + '.bin' # Build target test image test_info = parent_test.create_subtest('Building target %s' % build_name) if not os.path.isdir(directory): os.mkdir(directory) # Remove previous build files if os.path.isfile(target_hex_path): os.remove(target_hex_path) if os.path.isfile(target_bin_path): os.remove(target_bin_path) test_info.info('Starting remote build') start = time.time() built_file = mbedapi.build_repo(username, password, TEST_REPO, build_name, directory) stop = time.time() test_info.info("Build took %s seconds" % (stop - start)) extension = os.path.splitext(built_file)[1].lower() assert extension == '.hex' or extension == '.bin' if extension == '.hex': intel_hex = IntelHex(built_file) # Only supporting devices with the starting # address at 0 currently assert intel_hex.minaddr() == 0 intel_hex.tobinfile(target_bin_path) os.rename(built_file, target_hex_path) if extension == '.bin': intel_hex = IntelHex() intel_hex.loadbin(built_file, offset=0) intel_hex.tofile(target_hex_path, 'hex') os.rename(built_file, target_bin_path) # Assert that required files are present assert os.path.isfile(target_hex_path) assert os.path.isfile(target_bin_path)
def separate(): softdeviceDir = os.getcwd() + r'/softdevice/' if not os.path.exists(softdeviceDir): print u'创建softdevice文件夹' os.mkdir(softdeviceDir) # softdeviceFileDir, softdeviceFileName = os.path.split(config.SOFTDEVICE_FILE) # softdeviceFileName, softdeviceFileExt = os.path.splitext(softdeviceFileName) # mianFileName = softdeviceDir + softdeviceFileName + '_main.bin' # uicrFileName = softdeviceDir + softdeviceFileName + '_uicr.bin' mianFileName = softdeviceDir + 'softdevice_main.bin' uicrFileName = softdeviceDir + 'softdevice_uicr.bin' softdeviceFile = IntelHex(config.SOFTDEVICE_FILE) softdeviceFile.tobinfile(fobj=mianFileName, start=0, size=80*1024) softdeviceFile.tobinfile(fobj=uicrFileName, start=0x10001000, size=0x20)
def program(self, args): board = self._setup() board.flash.init() tmp_bin_file = 'tmp.bin' if args.sectorsanduicrerase: # TODO: May not be needed if pyOCD does this. Double check before # removing. self._erase_uicr(board.target) hex_file = IntelHex(args.file) hex_file.tobinfile(tmp_bin_file) board.flash.flashBinary( tmp_bin_file, chip_erase=args.eraseall, fast_verify=args.verify) if args.debugreset or args.pinreset or args.systemreset: board.target.reset() os.remove(tmp_bin_file)
from intelhex import IntelHex ih = IntelHex() ih.padding = 0 ih.fromfile("sbos.hex", format="hex") start = ih.segments()[0][0] ih.tobinfile("sbos.bin", start=start, size=8192)
help="output file name", default="output.bin") args = parser.parse_args() if not args.input: print("Input file must be specified") if os.path.exists(args.output): try: os.path.delete(args.output) except FileError as e: print("File error ({0}): {1}".format(e.errno, e.strerror)) except: print("Filesystem Error!") try: if (os.path.exists(args.input) == False): errorHandler("Application file missing!") filename, file_ext = os.path.splitext(args.input) #convert hex to bin if file_ext == ".hex": print("Convert HEX to Binary: " + args.input) ih = IntelHex(args.input) ih.tobinfile(args.output) else: print("File is not HEX type; aborting!") except FileError as e: print("File error ({0}): {1}".format(e.errno, e.strerror)) except: errorHandler("Filesystem Error!")
def dump_header(infile, image, header): inhex = IntelHex(infile) (start, end) = inhex.segments()[0] inhex.tobinfile(image, start=start, end=end - 1) (start, end) = inhex.segments()[-1] inhex.tobinfile(header, start=start, end=end - 1)
class PartitionCreator: """ Class to create nrfconnect partition containing FactoryData :param offset: This is a partition offset where data will be stored in device's flash memory :param length: This is a maximum partition size :param input: This is a path to input JSON file :param output: This is a path to output directory """ def __init__(self, offset: int, length: int, input: str, output: str) -> None: self._ih = IntelHex() self._length = length self._offset = offset self._data_ready = False self._output = output self._input = input try: self.__data_to_save = self._convert_to_dict(self._load_json()) except IOError: sys.exit(-1) def generate_cbor(self): """ Generates .cbor file using cbor2 library. It generate a CBORTag 55799 which is user-specific tag """ if self.__data_to_save: # prepare raw data from Json cbor_data = cbor.dumps(self.__data_to_save) return cbor_data def create_hex(self, data: bytes): """ Creates .hex file from CBOR. This file can be write directly to device. """ if len(data) > self._length: raise ValueError( "generated CBOR file exceeds declared maximum partition size! {} > {}" .format(len(data), self._length)) self._ih.putsz(self._offset, data) self._ih.write_hex_file(self._output + ".hex", True) self._data_ready = True return True def create_bin(self): """ Creates raw binary data of created previously .hex file """ if not self._data_ready: log.error("Please create hex file first!") return False self._ih.tobinfile(self._output + ".bin") return True @staticmethod def _convert_to_dict(data): """ Converts a list containing tuples ("key_name", "key_value") to a dictionary If "key_value" of data entry is a string-type variable and contains a HEX_PREFIX algorithm decodes it to hex format to be sure that a cbor file will contain proper bytes. If "key_value" of data entry is a dictionary, algorithm appends it to the created dictionary. """ output_dict = dict() for entry in data: if not isinstance(entry, dict): log.debug("Processing entry {}".format(entry)) if isinstance(data[entry], str) and data[entry].startswith(HEX_PREFIX): output_dict[entry] = codecs.decode( data[entry][len(HEX_PREFIX):], "hex") elif isinstance(data[entry], str): output_dict[entry] = data[entry].encode("utf-8") else: output_dict[entry] = data[entry] else: output_dict[entry] = entry return output_dict def _load_json(self): """ Loads file containing a JSON data and converts it to JSON format :raises IOError: if provided JSON file can not be read out. """ try: with open(self._input, "rb") as json_file: return json.loads(json_file.read()) except IOError as e: log.error("Can not read Json file {}".format(self._input)) raise e
def m2354_tfm_bin(t_self, non_secure_image, secure_bin): assert os.path.isfile(secure_bin) assert os.path.isfile(non_secure_image) secure_bin = abspath(secure_bin) non_secure_image = abspath(non_secure_image) build_dir = dirname(non_secure_image) tempdir = path_join(build_dir, 'temp') if not isdir(tempdir): os.makedirs(tempdir) flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h') bl2_bin = path_join(SECURE_ROOT, 'bl2.bin') s_bin_basename = splitext(basename(secure_bin))[0] ns_bin_basename, output_ext = splitext(basename(non_secure_image)) # Convert NS image to BIN format if it is HEX if output_ext == ".hex": non_secure_bin = abspath(path_join(tempdir, ns_bin_basename + ".bin")) ns_ih = IntelHex(non_secure_image) ns_ih.tobinfile(non_secure_bin) else: non_secure_bin = non_secure_image signing_key = path_join(SCRIPT_DIR, 'nuvoton_m2354-root-rsa-3072.pem') assert os.path.isfile(signing_key) # Find Python 3 command name across platforms python3_cmd = "python3" if shutil.which( "python3") is not None else "python" # Specify image version # # MCUboot image version format: Major.Minor.Revision+Build # # Requirements for image version: # 1. Major.Minor.Revision must be non-decremental when used to derive security # counter (-s 'auto'). # 2. Make Major.Minor.Revision+Build incremental to identify the firmware # itself uniquely through psa_fwu_query(). # 3. Get around MCUboot failure with: # [INF] Starting bootloader # [INF] Swap type: none # [ERR] Failed to add Image 0 data to shared memory area # [ERR] Unable to find bootable image # This is because TF-M underestimates MAX_BOOT_RECORD_SZ for boot record # where Major.Minor.Revision will pack into during signing. The more digits # of the Major.Minor.Revision, the larger the needed boot record size. And # then MCUboot errors in boot_save_boot_status(). # # To meet all the above requirements, we apply the following policy: # 1. To not change MAX_BOOT_RECORD_SZ in TF-M, specify Major.Minor.Revision # with TF-M version instead of modified Unix timestamp. This needs less digits to # fit into MAX_BOOT_RECORD_SZ. # 2. To make Major.Minor.Revision+Build incremental, specify the Build part with # modified Unix timestamp. # 3. To make security counter non-decremental, we can derive it from # Major.Minor.Revision (-s 'auto') or explicitly specify it with modified # Unix timestamp, depending on security consideration. # # NOTE: To get around Y2038 problem, we modify Unix timestamp by setting new base # point. Using 32-bit unsigned integer to hold the modified Unix timestamp, # it will break (wrap around) after Y2156 (2106 + 2020 - 1970). # https://en.wikipedia.org/wiki/Year_2038_problem # modified_timestamp = int(datetime.now().timestamp()) - int( datetime(2020, 1, 1).timestamp()) img_ver_major = 1 # Instead of (modified_timestamp >> 24) & 0xFF img_ver_minor = 4 # Instead of (modified_timestamp >> 16) & 0xFF img_ver_revision = 0 # Instead of modified_timestamp & 0xFFFF img_ver_build = modified_timestamp # wrapper.py command template cmd_wrapper = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "wrapper.py"), "-v", "{}.{}.{}+{}".format(img_ver_major, img_ver_minor, img_ver_revision, img_ver_build), "-k", "SIGNING_KEY_PATH", "--layout", "IMAGE_MACRO_PATH", "--public-key-format", 'full', "--align", '1', # Reasons for removing padding and boot magic option "--pad": # 1. PSA FWU API psa_fwu_install() will be responsible for writing boot magic to enable upgradeable. # 2. The image size gets smaller instead of slot size. #"--pad", "--pad-header", "-H", '0x400', "--overwrite-only", "-s", 'auto', # Or modified_timestamp "-d", '(IMAGE_ID,MAJOR.MINOR.REVISION+BUILD)', "RAW_BIN_PATH", "SIGNED_BIN_PATH", ] pos_wrapper_signing_key = cmd_wrapper.index("-k") + 1 pos_wrapper_layout = cmd_wrapper.index("--layout") + 1 pos_wrapper_dependency = cmd_wrapper.index("-d") + 1 pos_wrapper_raw_bin = len(cmd_wrapper) - 2 pos_wrapper_signed_bin = len(cmd_wrapper) - 1 # assemble.py command template cmd_assemble = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "assemble.py"), "--layout", "IMAGE_MACRO_PATH", "-s", "SECURE_BIN_PATH", "-n", "NONSECURE_BIN_PATH", "-o", "CONCATENATED_BIN_PATH", ] pos_assemble_layout = cmd_assemble.index("--layout") + 1 pos_assemble_secure_bin = cmd_assemble.index("-s") + 1 pos_assemble_nonsecure_bin = cmd_assemble.index("-n") + 1 pos_assemble_concat_bin = cmd_assemble.index("-o") + 1 # If second signing key is passed down, go signing separately; otherwise, go signing together. if os.path.isfile( path_join(SECURE_ROOT, 'partition', 'signing_layout_ns_preprocessed.h')): signing_key_1 = 'nuvoton_m2354-root-rsa-3072_1.pem' else: signing_key_1 = None if signing_key_1 is not None: signing_key_1 = path_join(SCRIPT_DIR, signing_key_1) assert os.path.isfile(signing_key_1) image_macros_s = path_join(SECURE_ROOT, 'partition', 'signing_layout_s_preprocessed.h') image_macros_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_ns_preprocessed.h') assert os.path.isfile(image_macros_s) assert os.path.isfile(image_macros_ns) s_signed_bin = abspath(path_join(tempdir, 'tfm_s_signed' + '.bin')) ns_signed_bin = abspath( path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + '.bin')) signed_concat_bin = abspath( path_join( tempdir, 'tfm_s_signed_' + ns_bin_basename + '_signed_concat' + '.bin')) s_update_bin = abspath( path_join(build_dir, s_bin_basename + '_update' + '.bin')) ns_update_bin = abspath( path_join(build_dir, ns_bin_basename + '_update' + '.bin')) #1. Run wrapper to sign the secure TF-M binary cmd_wrapper[pos_wrapper_signing_key] = signing_key cmd_wrapper[pos_wrapper_layout] = image_macros_s cmd_wrapper[ pos_wrapper_dependency] = '(1,0.0.0+0)' # Minimum version of non-secure image required for upgrading to the secure image cmd_wrapper[pos_wrapper_raw_bin] = secure_bin cmd_wrapper[pos_wrapper_signed_bin] = s_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "TF-M Secure" + " binary, Error code: " + str(retcode)) return #2. Run wrapper to sign the non-secure mbed binary cmd_wrapper[pos_wrapper_signing_key] = signing_key_1 cmd_wrapper[pos_wrapper_layout] = image_macros_ns cmd_wrapper[ pos_wrapper_dependency] = '(0,0.0.0+0)' # Minimum version of secure image required for upgrading to the non-secure image cmd_wrapper[pos_wrapper_raw_bin] = non_secure_bin cmd_wrapper[pos_wrapper_signed_bin] = ns_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "TF-M Secure" + " binary, Error code: " + str(retcode)) return #3. Concatenate signed secure TF-M binary and signed non-secure mbed binary cmd_assemble[pos_assemble_layout] = image_macros_s cmd_assemble[pos_assemble_secure_bin] = s_signed_bin cmd_assemble[pos_assemble_nonsecure_bin] = ns_signed_bin cmd_assemble[pos_assemble_concat_bin] = signed_concat_bin retcode = run_cmd(cmd_assemble, MBED_OS_ROOT) if retcode: raise Exception("Unable to concatenate " + "Secure TF-M (signed)/Non-secure Mbed (signed)" + " binaries, Error code: " + str(retcode)) return #4. Concatenate MCUboot and concatenated signed secure TF-M binary/signed non-secure mbed binary flash_area_0_offset = find_flash_area_0_offset(flash_layout) out_ih = IntelHex() out_ih.loadbin(bl2_bin) out_ih.loadbin(signed_concat_bin, flash_area_0_offset) out_ih.tofile(non_secure_image, 'hex' if output_ext == ".hex" else "bin") # Generate firmware update file for PSA Firmware Update shutil.copy(s_signed_bin, s_update_bin) shutil.copy(ns_signed_bin, ns_update_bin) else: image_macros_s_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_preprocessed.h') assert os.path.isfile(image_macros_s_ns) concat_bin = abspath( path_join(tempdir, 'tfm_s_' + ns_bin_basename + ".bin")) concat_signed_bin = abspath( path_join(tempdir, 'tfm_s_' + ns_bin_basename + '_signed' + ".bin")) update_bin = abspath( path_join(build_dir, ns_bin_basename + '_update' + '.bin')) #1. Concatenate secure TFM and non-secure mbed binaries cmd_assemble[pos_assemble_layout] = image_macros_s_ns cmd_assemble[pos_assemble_secure_bin] = secure_bin cmd_assemble[pos_assemble_nonsecure_bin] = non_secure_bin cmd_assemble[pos_assemble_concat_bin] = concat_bin retcode = run_cmd(cmd_assemble, MBED_OS_ROOT) if retcode: raise Exception("Unable to concatenate " + "Secure TF-M/Non-secure Mbed" + " binaries, Error code: " + str(retcode)) return #2. Run wrapper to sign the concatenated binary cmd_wrapper[pos_wrapper_signing_key] = signing_key cmd_wrapper[pos_wrapper_layout] = image_macros_s_ns cmd_wrapper[ pos_wrapper_dependency] = '(1,0.0.0+0)' # No effect for single image boot cmd_wrapper[pos_wrapper_raw_bin] = concat_bin cmd_wrapper[pos_wrapper_signed_bin] = concat_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "concatenated" + " binary, Error code: " + str(retcode)) return #3. Concatenate MCUboot and signed binary flash_area_0_offset = find_flash_area_0_offset(flash_layout) out_ih = IntelHex() out_ih.loadbin(bl2_bin) out_ih.loadbin(concat_signed_bin, flash_area_0_offset) out_ih.tofile(non_secure_image, 'hex' if output_ext == ".hex" else "bin") # Generate firmware update file for PSA Firmware Update shutil.copy(concat_signed_bin, update_bin)
def main(): parser = argparse.ArgumentParser( "Create the flash data for a queercon 14 badge.") # 0x000000 - reserved # 0x001000 - first ID in here # 0x002000 - main conf in here # 0x003000 - boot anim here # 0x004000 - tiles live in here # 0x008000 - backup conf here # 0x009000 - second ID copy here # 0x00a000 - icons live in here # 0x010000 - frames live here # 0x200000 - end of memory (real) parser.add_argument( '--workaround', action='store_true', help= "Work around the issue where we cannot use odd numbered pages. Note that this must be paired with using the `skipodd` versions of the flash functions on the badge." ) parser.add_argument('--boot-addr', type=int, default=0x003000, help="Address of the boot animation struct") parser.add_argument('--poof-addr', type=int, default=0x004000, help="Address of the boot animation struct") parser.add_argument('--tile-addr', type=int, default=0x005000, help="Address of the tile animation buffer") parser.add_argument('--game-addr', type=int, default=0x00a000, help="Address of the game animation struct") parser.add_argument('--frame-addr', type=int, default=0x010000, help='Starting offset for animation frames') parser.add_argument('--id-addr', type=int, default=0x001000, help="Address of the badge ID.") parser.add_argument('--id-addr2', type=int, default=0x009000, help="Address of the badge ID.") parser.add_argument('-o', '--hexpath', action='store', type=str, default='a.bin', help='Output file path') parser.add_argument('-d', '--frame-delay', type=int, default=30, help="Default frame delay for animations") parser.add_argument('-n', '--handle', action='store', type=str, default='Human') parser.add_argument('id', type=int, action='store', default=1) args = parser.parse_args() flash = IntelHex() all_frames = [] curr_frame_index = 0 tile_animations = [] # This is a bit sequence game_animations = [] # This is a bit sequence (not nested) put_bytes_at(flash, 0, [0xaa], args.workaround) # OK. The badge will handle the main and backup confs. # All we need along those lines is to give it the ID. put_bytes_at(flash, args.id_addr, map(ord, struct.pack('<H', args.id)), args.workaround) put_bytes_at(flash, args.id_addr2, map(ord, struct.pack('<H', args.id)), args.workaround) # Load up the boot animation imgs = image_list_from_directory('_badge_graphics/bootup') boot_anim = anim_struct_bytes( 0, len(imgs), get_frame_delay('_badge_graphics/bootup', args.frame_delay)) put_bytes_at(flash, args.boot_addr, boot_anim, args.workaround) all_frames += imgs imgs = image_list_from_directory('_badge_graphics/poof') poof_anim = anim_struct_bytes( len(all_frames), len(imgs), get_frame_delay('_badge_graphics/poof', args.frame_delay)) put_bytes_at(flash, args.poof_addr, poof_anim, args.workaround) all_frames += imgs # Load up the tile animations assert os.path.isdir('_badge_graphics/tiles') # TODO: Demeter for dirname in os.listdir('_badge_graphics/tiles'): dpath = os.path.join('_badge_graphics/tiles', dirname) if not os.path.isdir(dpath): continue # Each of these corresponds to a tile. imgs = image_list_from_directory(dpath) tile_animations += anim_struct_bytes( len(all_frames), # starting index len(imgs), # length get_frame_delay(dpath, args.frame_delay) # delay ) all_frames += imgs put_bytes_at(flash, args.tile_addr, tile_animations, args.workaround) # Load up the game icons # These are a little different. They look, for now, like: # typedef struct { # uint16_t mate_icon_id; # uint16_t result_icon_id; # uint16_t arm_anim_id; # uint8_t sufficient_flag; # uint8_t other_arm_id; # } mate_spec_t; # typedef struct { # uint16_t id; # screen_anim_t animation; # mate_spec_t arms[4]; # } game_icon_t; icon_connections = make_game.get_icons() icon_id = 0 assert os.path.isdir('_badge_graphics/game') # TODO: Demeter for dirname in os.listdir('_badge_graphics/game'): dpath = os.path.join('_badge_graphics/game', dirname) if not os.path.isdir(dpath): continue # Each of these corresponds to an icon. imgs = image_list_from_directory(dpath) game_animations += icon_struct_bytes( icon_id, anim_struct_bytes( len(all_frames), # starting index len(imgs), # length get_frame_delay(dpath, args.frame_delay) # delay # TODO: Demeter ), icon_connections[icon_id]) all_frames += imgs icon_id += 1 put_bytes_at(flash, args.game_addr, game_animations, args.workaround) # OK, so now we've got the animation structs for the boot-up, # game, and tiles all loaded up. Now we just need to add # all the actual frames. # This part's pretty easy, actually. flattened_frames = reduce(lambda a, b: a + b, map(bmp_bytes, all_frames)) last_byte = put_bytes_at(flash, args.frame_addr, flattened_frames, args.workaround) if args.hexpath.endswith('.hex'): flash.write_hex_file(args.hexpath) else: flash.tobinfile(args.hexpath) print last_byte
def tfm_sign_image_tgt(tfm_import_path, signing_key, non_secure_bin): SECURE_ROOT = abspath(tfm_import_path) secure_bin = path_join(SECURE_ROOT, 'tfm_s.bin') assert os.path.isfile(secure_bin) non_secure_bin = abspath(non_secure_bin) assert os.path.isfile(non_secure_bin) build_dir = dirname(non_secure_bin) tempdir = path_join(build_dir, 'temp') if not isdir(tempdir): os.makedirs(tempdir) flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h') bl2_bin = path_join(SECURE_ROOT, 'bl2.bin') image_macros_s_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_preprocessed.h') ns_bin_basename = splitext(basename(non_secure_bin))[0] concatenated_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + ".bin")) signed_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + ".bin")) signed_nopad_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed_nopad' + ".bin")) assert os.path.isfile(image_macros_s_ns) signing_key = path_join(SECURE_ROOT, 'signing_key', signing_key) assert os.path.isfile(signing_key) # Find Python 3 command name across platforms python3_cmd = "python3" if shutil.which("python3") is not None else "python" #1. Concatenate secure TFM and non-secure mbed binaries cmd = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "assemble.py"), "--layout", image_macros_s_ns, "-s", secure_bin, "-n", non_secure_bin, "-o", concatenated_bin, ] retcode = run_cmd(cmd, MBED_OS_ROOT) if retcode: raise Exception("Unable to concatenate " + "TF-M Secure/Mbed Non-secure" + " binaries, Error code: " + str(retcode)) return #2.1 Run wrapper to sign the concatenated binary with padding ("--pad"), so upgradeable by mcuboot cmd = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa","tfm", "bin_utils", "wrapper.py"), "-v", '1.2.0', "-k", signing_key, "--layout", image_macros_s_ns, "--public-key-format", 'full', "--align", '1', "--pad", "--pad-header", "-H", '0x400', "--overwrite-only", "-s", 'auto', "-d", '(0,0.0.0+0)', concatenated_bin, signed_bin, ] retcode = run_cmd(cmd, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "concatenated" + " binary, Error code: " + str(retcode)) return #2.2. Re-run above but without padding ("--pad"), so non-upgradeable by mcuboot cmd.remove("--pad") cmd.pop() cmd.append(signed_nopad_bin) retcode = run_cmd(cmd, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "concatenated" + " binary, Error code: " + str(retcode)) return #3. Concatenate mcuboot and signed binary and overwrite mbed built bin/hex file flash_area_0_offset = find_flash_area_0_offset(flash_layout) out_ih = IntelHex() out_ih.loadbin(bl2_bin) out_ih.loadbin(signed_nopad_bin, flash_area_0_offset) out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex') out_ih.tobinfile(non_secure_bin)
def main(): # Default param hex_path = "D:\Projects\Keil Project\WS_test_boot\MDK-ARM\WS_test_task" input_hex = '' firmware_addr = '0x8030000' c_file_name = 'firmware' bin_file = 'app.bin' bin_out = False try: opts, args = getopt.getopt(sys.argv[1:], 'hi:o:b', ["input=", "offset=", "bin"]) except getopt.GetoptError as err: usage() # print help information and exit: SystemExit(2) for o, a in opts: if o in ('-h'): usage() return elif o in ("-i", "--input"): hex_path = a elif o in ("-o", "--offset"): firmware_addr = a elif o in ("-b", "--bin"): bin_out = True else: return print("Undefined param" + o) # Copy hex hex_path = find_hex_path(hex_path) try: shutil.copy(hex_path, os.getcwd()) except: print('[ERROR] : .hex path is EMPTY') raise SystemExit(0) input_hex = hex_path.split('\\')[-1] with open(input_hex, 'rb+') as f: last = get_last_line(f, -1) prelast = get_last_line(f, -2) if ':040000' in prelast: # delete expanded addres pos = f.tell() - len(last) - len(prelast) f.seek(pos, os.SEEK_SET) f.truncate() f.write(bytes(last, "utf8")) # Create bin ih = IntelHex(input_hex) ih.tobinfile(bin_file) if os.path.isfile(c_file_name + '.h'): os.remove(c_file_name + '.h') print('[INFO]: Input HEX: ' + input_hex) print('[INFO]: Input bin: ' + bin_file) print('[INFO]: Firmware addr: ' + firmware_addr) create_array(bin_file, c_file_name, offset=firmware_addr) print('[INFO]: ' + c_file_name + '.h' + ' -- Created successful') if not bin_out: os.remove(bin_file) os.remove(input_hex)
def generatebin(self): if self.hexfilename.text() != "" and self.binfilename.text() != "": hex = IntelHex(self.lastfiledir + "/" + self.hexfilename.text()) hex.tobinfile(self.lastfiledir + "/" + self.binfilename.text()) self.statusbar.showMessage("格式转换完毕", msecs=2000)
def tfm_sign_image(tfm_import_path, signing_key, signing_key_1, non_secure_bin): SECURE_ROOT = abspath(tfm_import_path) secure_bin = path_join(SECURE_ROOT, 'tfm_s.bin') assert os.path.isfile(secure_bin) non_secure_bin = abspath(non_secure_bin) assert os.path.isfile(non_secure_bin) build_dir = dirname(non_secure_bin) tempdir = path_join(build_dir, 'temp') if not isdir(tempdir): os.makedirs(tempdir) flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h') bl2_bin = path_join(SECURE_ROOT, 'bl2.bin') s_bin_basename = splitext(basename(secure_bin))[0] ns_bin_basename = splitext(basename(non_secure_bin))[0] signing_key = path_join(SECURE_ROOT, 'signing_key', signing_key) assert os.path.isfile(signing_key) # Find Python 3 command name across platforms python3_cmd = "python3" if shutil.which( "python3") is not None else "python" img_ver_major = 1 img_ver_minor = 3 img_ver_revision = 0 img_ver_build = 0 # wrapper.py command template cmd_wrapper = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "wrapper.py"), "-v", "{}.{}.{}+{}".format(img_ver_major, img_ver_minor, img_ver_revision, img_ver_build), "-k", "SIGNING_KEY_PATH", "--layout", "IMAGE_MACRO_PATH", "--public-key-format", 'full', "--align", '1', # Reasons for removing padding and boot magic option "--pad": # 1. PSA FWU API psa_fwu_install() will be responsible for writing boot magic to enable upgradeable. # 2. The image size gets smaller instead of slot size. #"--pad", "--pad-header", "-H", '0x400', "--overwrite-only", "-s", 'auto', "-d", '(IMAGE_ID,MAJOR.MINOR.REVISION+BUILD)', "RAW_BIN_PATH", "SIGNED_BIN_PATH", ] pos_wrapper_signing_key = cmd_wrapper.index("-k") + 1 pos_wrapper_layout = cmd_wrapper.index("--layout") + 1 pos_wrapper_dependency = cmd_wrapper.index("-d") + 1 pos_wrapper_raw_bin = len(cmd_wrapper) - 2 pos_wrapper_signed_bin = len(cmd_wrapper) - 1 # assemble.py command template cmd_assemble = [ python3_cmd, path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "assemble.py"), "--layout", "IMAGE_MACRO_PATH", "-s", "SECURE_BIN_PATH", "-n", "NONSECURE_BIN_PATH", "-o", "CONCATENATED_BIN_PATH", ] pos_assemble_layout = cmd_assemble.index("--layout") + 1 pos_assemble_secure_bin = cmd_assemble.index("-s") + 1 pos_assemble_nonsecure_bin = cmd_assemble.index("-n") + 1 pos_assemble_concat_bin = cmd_assemble.index("-o") + 1 # If second signing key is passed down, go signing separately; otherwise, go signing together. if signing_key_1 is not None: signing_key_1 = path_join(SECURE_ROOT, 'signing_key', signing_key_1) assert os.path.isfile(signing_key_1) image_macros_s = path_join(SECURE_ROOT, 'partition', 'signing_layout_s_preprocessed.h') image_macros_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_ns_preprocessed.h') assert os.path.isfile(image_macros_s) assert os.path.isfile(image_macros_ns) s_signed_bin = abspath(path_join(tempdir, 'tfm_s_signed' + '.bin')) ns_signed_bin = abspath( path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + '.bin')) signed_concat_bin = abspath( path_join( tempdir, 'tfm_s_signed_' + ns_bin_basename + '_signed_concat' + '.bin')) s_update_bin = abspath( path_join(build_dir, s_bin_basename + '_update' + '.bin')) ns_update_bin = abspath( path_join(build_dir, ns_bin_basename + '_update' + '.bin')) #1. Run wrapper to sign the secure TF-M binary cmd_wrapper[pos_wrapper_signing_key] = signing_key cmd_wrapper[pos_wrapper_layout] = image_macros_s cmd_wrapper[ pos_wrapper_dependency] = '(1,0.0.0+0)' # Minimum version of non-secure image required for upgrading to the secure image cmd_wrapper[pos_wrapper_raw_bin] = secure_bin cmd_wrapper[pos_wrapper_signed_bin] = s_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "TF-M Secure" + " binary, Error code: " + str(retcode)) return #2. Run wrapper to sign the non-secure mbed binary cmd_wrapper[pos_wrapper_signing_key] = signing_key_1 cmd_wrapper[pos_wrapper_layout] = image_macros_ns cmd_wrapper[ pos_wrapper_dependency] = '(0,0.0.0+0)' # Minimum version of secure image required for upgrading to the non-secure image cmd_wrapper[pos_wrapper_raw_bin] = non_secure_bin cmd_wrapper[pos_wrapper_signed_bin] = ns_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "TF-M Secure" + " binary, Error code: " + str(retcode)) return #3. Concatenate signed secure TF-M binary and signed non-secure mbed binary cmd_assemble[pos_assemble_layout] = image_macros_s cmd_assemble[pos_assemble_secure_bin] = s_signed_bin cmd_assemble[pos_assemble_nonsecure_bin] = ns_signed_bin cmd_assemble[pos_assemble_concat_bin] = signed_concat_bin retcode = run_cmd(cmd_assemble, MBED_OS_ROOT) if retcode: raise Exception("Unable to concatenate " + "Secure TF-M (signed)/Non-secure Mbed (signed)" + " binaries, Error code: " + str(retcode)) return #4. Concatenate MCUboot and concatenated signed secure TF-M binary/signed non-secure mbed binary flash_area_0_offset = find_flash_area_0_offset(flash_layout) out_ih = IntelHex() out_ih.loadbin(bl2_bin) out_ih.loadbin(signed_concat_bin, flash_area_0_offset) out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex') out_ih.tobinfile(non_secure_bin) # Generate firmware update file for PSA Firmware Update shutil.copy(s_signed_bin, s_update_bin) shutil.copy(ns_signed_bin, ns_update_bin) else: image_macros_s_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_preprocessed.h') assert os.path.isfile(image_macros_s_ns) concat_bin = abspath( path_join(tempdir, 'tfm_s_' + ns_bin_basename + ".bin")) concat_signed_bin = abspath( path_join(tempdir, 'tfm_s_' + ns_bin_basename + '_signed' + ".bin")) update_bin = abspath( path_join(build_dir, ns_bin_basename + '_update' + '.bin')) #1. Concatenate secure TFM and non-secure mbed binaries cmd_assemble[pos_assemble_layout] = image_macros_s_ns cmd_assemble[pos_assemble_secure_bin] = secure_bin cmd_assemble[pos_assemble_nonsecure_bin] = non_secure_bin cmd_assemble[pos_assemble_concat_bin] = concat_bin retcode = run_cmd(cmd_assemble, MBED_OS_ROOT) if retcode: raise Exception("Unable to concatenate " + "Secure TF-M/Non-secure Mbed" + " binaries, Error code: " + str(retcode)) return #2. Run wrapper to sign the concatenated binary cmd_wrapper[pos_wrapper_signing_key] = signing_key cmd_wrapper[pos_wrapper_layout] = image_macros_s_ns cmd_wrapper[ pos_wrapper_dependency] = '(1,0.0.0+0)' # No effect for single image boot cmd_wrapper[pos_wrapper_raw_bin] = concat_bin cmd_wrapper[pos_wrapper_signed_bin] = concat_signed_bin retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT) if retcode: raise Exception("Unable to sign " + "concatenated" + " binary, Error code: " + str(retcode)) return #3. Concatenate MCUboot and signed binary flash_area_0_offset = find_flash_area_0_offset(flash_layout) out_ih = IntelHex() out_ih.loadbin(bl2_bin) out_ih.loadbin(concat_signed_bin, flash_area_0_offset) out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex') out_ih.tobinfile(non_secure_bin) # Generate firmware update file for PSA Firmware Update shutil.copy(concat_signed_bin, update_bin)
class FWInfo: def __init__(self, app_hex_file, sd_hex_file, app_version, ebin_file=None, aes_key=None, aes_iv=None, mbr_size=DEFAULT_MBR_SIZE, padding=DEFAULT_PADDING): self.ihex = IntelHex() self.ihex.padding = padding & 0xff if sd_hex_file: self.ihex.merge( IntelHex(sd_hex_file)) # default response to overlap is error. if app_hex_file: self.ihex.merge(IntelHex(app_hex_file)) else: raise OTAGeneratorError("Application hex file is required.") # Check for MBR overlap and find fp_base. start, end = self.ihex.segments()[0] # segment 0. fp_base = 0 if sd_hex_file is None: if start < mbr_size: raise OTAGeneratorError( "Application overlaps with MBR {:x}.".format(mbr_size)) else: fp_base = start else: if end > mbr_size: raise OTAGeneratorError( "Integrated MBR with softdevice is " " larger than given MBR size. {:x} > {:x}".format( end, mbr_size)) else: fp_base = self.ihex.segments()[1][ 0] # start address of next segment. # self.ihex.write_hex_file("ota.hex") # self.ihex.tobinfile("ota.pbin", start = fp_base) self.ebin_file = ebin_file self.fw_info = {} self.fw_info.setdefault('fp_base', fp_base) self.fw_info.setdefault('app_version', app_version) self.fw_info.setdefault('ebin_hash', '') self.fw_info.setdefault('pbin_hash', '') if aes_key is None: aes_key = os.urandom(AES_KEY_SIZE) else: aes_key = bytes.fromhex(aes_key) if aes_iv is None: aes_iv = os.urandom(AES_KEY_SIZE) else: aes_iv = bytes.fromhex(aes_iv) self.fw_info.setdefault('aes_key', aes_key) self.fw_info.setdefault('aes_iv', aes_iv) self.fw_info.setdefault('ebin_size', 0) self.fw_info.setdefault('pbin_size', 0) self._compute_fw_info() def _compute_fw_info(self): try: writer = FWInfoWriter(self.fw_info['aes_key'], self.fw_info['aes_iv'], self.ebin_file) self.ihex.tobinfile(writer, start=self.fw_info['fp_base']) writer.close() self.fw_info['pbin_size'] = writer.pbin_size self.fw_info['ebin_size'] = writer.ebin_size self.fw_info['ebin_hash'] = writer.ebin_hash.digest() self.fw_info['pbin_hash'] = writer.pbin_hash.digest() except Exception as e: raise (e) if self.fw_info['ebin_size'] == 0: raise OTAGeneratorError("No output generated.") def to_nrf52_hex_string(self): """ Keep the struct members type, order same in C code. """ """ struct { unsigned long version; unsigned long fp_base; unsigned long pbin_size; unsigned long ebin_size; unsigned char aes_key[16]; unsigned char aes_iv[16]; unsigned char pbin_hash[32]; unsigned char ebin_hash[32]; } """ fw_info_struct = struct.pack( "<LLLL16s16s32s32s", self.fw_info['app_version'], self.fw_info['fp_base'], self.fw_info['pbin_size'], self.fw_info['ebin_size'], self.fw_info['aes_key'], self.fw_info['aes_iv'], self.fw_info['pbin_hash'], self.fw_info['ebin_hash']) return fw_info_struct.hex() def gen_bl_settings_init_code(self, cfile): pbin_hash_str = "" for b in self.fw_info['pbin_hash']: pbin_hash_str += hex(b) + ',' ebin_hash_str = "" for b in self.fw_info['ebin_hash']: ebin_hash_str += hex(b) + ',' aes_key_str = "" for b in self.fw_info['aes_key']: aes_key_str += hex(b) + ',' aes_iv_str = "" for b in self.fw_info['aes_iv']: aes_iv_str += hex(b) + ',' with open(str(cfile), "w") as fobj: fobj.write( BL_SETTINGS_C_GEN.format(bl_settings_code=BL_SETTINGS_CODE, version=self.fw_info['app_version'], fp_base=self.fw_info['fp_base'], pbin_size=self.fw_info['pbin_size'], pbin_hash=pbin_hash_str, ebin_hash=ebin_hash_str, aes_key=aes_key_str, aes_iv=aes_iv_str, ebin_size=self.fw_info['ebin_size']))
import subprocess subprocess.check_call( [sys.executable, '-m', 'pip', 'install', 'intelhex', '--user']) from intelhex import IntelHex except: traceback.print_exc() print( "\n*** Please try manually with raised privileges: 'sudo python -m pip install intelhex'\n" ) sys.exit(1) if len(sys.argv) >= 4: binfile = sys.argv[1] hexfile1 = sys.argv[2] hexfile2 = sys.argv[3] else: print('Usage: python hexfile.py outfile hexfile1 hexfile2') sys.exit(1) try: c7 = IntelHex(hexfile1) c4 = IntelHex(hexfile2) c7.merge(c4, overlap='ignore') fout = open(binfile, 'wb') c7.tobinfile(fout) fout.close() print('Combined image file ' + binfile + ' created') except: traceback.print_exc() sys.exit(1)
mac = None if args.savemac: mac = jlink.make_mac_bin(None, device) else: mac = jlink.make_mac_bin(args.mac, None) if args.app: appStr = args.app #get size of app and create binary file filename, extension = os.path.splitext(args.app) appSize = 0 if extension == '.hex': utils.deleteIfExists('temp.bin', None) ih = IntelHex(args.app) ih.tobinfile('temp.bin') appSize = os.path.getsize('temp.bin') else: appSize = os.path.getsize(args.app) jlink.make_bl_settings_bin(appSize) print(appSize) utils.deleteIfExists('temp.bin', None) else: jlink.make_bl_settings_bin(0) #validate existence of all necessary binary files; application validated earlier in script if cfg.softdevice.compatible == 'True': if not os.path.exists(softdeviceStr): if args.softdevice != 'none': utils.errorHandler(
def post_process(self): logging.info("Processing binaries") fw_info_fmt = '<I16s128s16s128s16s' fw_info_addr = int(self.settings["FW_INFO_ADDR"], 16) # save original dir cwd = os.getcwd() # change to target dir os.chdir(self.target_dir) ih = IntelHex('main.hex') fwid = uuid.UUID('{' + self.settings["FWID"] + '}') # get KV meta start kv_meta_addr = fw_info_addr + struct.calcsize(fw_info_fmt) kv_meta_len = KVMetaField().size() bindata = ih.tobinstr() kv_meta_data = [] while True: kv_meta = KVMetaField().unpack(bindata[kv_meta_addr:kv_meta_addr + kv_meta_len]) kv_meta_addr += kv_meta_len if kv_meta.param_name == "kvstart": continue elif kv_meta.param_name == "kvend": break else: kv_meta_data.append(kv_meta) kv_meta_by_hash = {} logging.info("Hash type: FNV1A_32") # create lookups by 32 bit hash index = 0 for kv in kv_meta_data: hash32 = fnv1a_32(str(kv.param_name)) if hash32 in kv_meta_by_hash: raise Exception("Hash collision!") kv_meta_by_hash[hash32] = (kv, index) index += 1 # sort indexes sorted_hashes = sorted(kv_meta_by_hash.keys()) # create binary look up table kv_index = '' for a in sorted_hashes: kv_index += struct.pack('<LB', a, kv_meta_by_hash[a][1]) # write to end of hex file ih.puts(ih.maxaddr() + 1, kv_index) size = ih.maxaddr() - ih.minaddr() + 1 # get os info try: os_project = get_project_builder(self.settings["OS_PROJECT"], target=self.target_type) except KeyError: os_project = "" # create firmware info structure fw_info = struct.pack(fw_info_fmt, size, fwid.bytes, os_project.proj_name, os_project.version, str(self.settings['PROJ_NAME']), self.version) # insert fw info into hex ih.puts(fw_info_addr, fw_info) # compute crc crc_func = crcmod.predefined.mkCrcFun('crc-aug-ccitt') crc = crc_func(ih.tobinstr()) logging.info("size: %d" % (size)) logging.info("fwid: %s" % (fwid)) logging.info("fwinfo: %x" % (fw_info_addr)) logging.info("kv index len: %d" % (len(kv_index))) logging.info("crc: 0x%x" % (crc)) logging.info("os name: %s" % (os_project.proj_name)) logging.info("os version: %s" % (os_project.version)) logging.info("app name: %s" % (self.settings['PROJ_NAME'])) logging.info("app version: %s" % (self.version)) ih.puts(ih.maxaddr() + 1, struct.pack('>H', crc)) ih.write_hex_file('main.hex') ih.tobinfile('firmware.bin') # get loader info loader_project = get_project_builder(self.settings["LOADER_PROJECT"], target=self.target_type) # create loader image loader_hex = os.path.join(loader_project.target_dir, "main.hex") self.merge_hex('main.hex', loader_hex, 'loader_image.hex') # create sha256 of binary sha256 = hashlib.sha256(ih.tobinstr()) # create manifest file data = { 'name': self.settings['FULL_NAME'], 'timestamp': datetime.utcnow().isoformat(), 'sha256': sha256.hexdigest(), 'fwid': self.settings['FWID'], 'version': self.version } with open('manifest.txt', 'w+') as f: f.write(json.dumps(data)) # create firmware zip file zf = zipfile.ZipFile('chromatron_main_fw.zip', 'w') zf.write('manifest.txt') zf.write('firmware.bin') zf.close() # create second, project specific zip # we'll remove the first zip after # we update the firmware tools zf = zipfile.ZipFile('%s.zip' % (self.settings['PROJ_NAME']), 'w') zf.write('manifest.txt') zf.write('firmware.bin') zf.close() # change back to original dir os.chdir(cwd) logging.info("Package dir: %s" % (get_build_package_dir())) # make sure we have the firmware package dir try: os.makedirs(get_build_package_dir()) except OSError: pass # copy firmware zip try: shutil.copy( os.path.join(self.target_dir, '%s.zip' % (self.proj_name)), get_build_package_dir()) except IOError: raise AppZipNotFound # update build date with open( os.path.join(get_build_package_dir(), firmware_package.PUBLISHED_AT_FILENAME), 'w') as f: f.write(util.now().isoformat())
#!/usr/bin/python import sys from intelhex import IntelHex basename = sys.argv[1].rsplit(".", 1)[0] outfile = open(basename + ".rmh", 'w') outfile_bin = open(basename + ".bin", 'wb') ih = IntelHex(sys.argv[1]) arr = ih.tobinarray() outfile.write("@0000\n") for i, e in enumerate(arr): outfile.write("{0:02x}\n".format(e)) ih.tobinfile(outfile_bin)
line = sp.read(45) lines.append(line) if line == b":00000001FF\r\n": break if line == '': break sublines = [line.decode() for line in lines] return ''.join(sublines) def usage(): print("usage: {} <serial_port> <bootloader_filename>".format(sys.argv[0])) # Ensure we have proper-ish arguments. if len(sys.argv) != 3: usage() sys.exit(0) serial_port = sys.argv[1] out_file = sys.argv[2] # Read the bootloader into an intel hex file... raw_ihex = read_bootloader_ihex(sys.argv[1]) # ... and produce the output binary. ihex = IntelHex(StringIO(raw_ihex)) ihex.tobinfile(out_file)