1bceeadceSEtienne Carriere#!/usr/bin/env python3 2bceeadceSEtienne Carriere# SPDX-License-Identifier: BSD-2-Clause 3bceeadceSEtienne Carriere# 4bceeadceSEtienne Carriere# Copyright (c) 2017-2018, STMicroelectronics 5bceeadceSEtienne Carriere# 6bceeadceSEtienne Carriereimport argparse 7bceeadceSEtienne Carriereimport struct 8bceeadceSEtienne Carriereimport mmap 9bceeadceSEtienne Carriere 10bceeadceSEtienne Carriereheader_size = 256 11bceeadceSEtienne Carrierehdr_magic_number = 0x324D5453 # magic ='S' 'T' 'M' 0x32 12bceeadceSEtienne Carrierehdr_header_ver_variant = 0 13bceeadceSEtienne Carrierehdr_header_ver_minor = 0 14bceeadceSEtienne Carrierehdr_header_ver_major = 1 15bceeadceSEtienne Carrierehdr_version_number = 0 16bceeadceSEtienne Carrierehdr_option_flags = 1 # bit0=1 no signature 17bceeadceSEtienne Carrierehdr_edcsa_algo = 1 18bceeadceSEtienne Carriere 19bceeadceSEtienne Carriere 20bceeadceSEtienne Carrieredef get_size(file): 21bceeadceSEtienne Carriere file.seek(0, 2) # End of the file 22bceeadceSEtienne Carriere size = file.tell() 23bceeadceSEtienne Carriere return size 24bceeadceSEtienne Carriere 25bceeadceSEtienne Carriere 26bceeadceSEtienne Carrieredef stm32image_checksum(dest_fd, sizedest): 27bceeadceSEtienne Carriere csum = 0 28bceeadceSEtienne Carriere if sizedest < header_size: 29bceeadceSEtienne Carriere return 0 30bceeadceSEtienne Carriere dest_fd.seek(header_size, 0) 31bceeadceSEtienne Carriere length = sizedest - header_size 32bceeadceSEtienne Carriere while length > 0: 33bceeadceSEtienne Carriere csum += ord(dest_fd.read(1)) 34bceeadceSEtienne Carriere length -= 1 35bceeadceSEtienne Carriere return csum 36bceeadceSEtienne Carriere 37bceeadceSEtienne Carriere 38*ed4b5e39SEtienne Carrieredef stm32image_set_header(dest_fd, load, entry, bintype): 39bceeadceSEtienne Carriere sizedest = get_size(dest_fd) 40bceeadceSEtienne Carriere 41bceeadceSEtienne Carriere checksum = stm32image_checksum(dest_fd, sizedest) 42bceeadceSEtienne Carriere 43bceeadceSEtienne Carriere dest_fd.seek(0, 0) 44bceeadceSEtienne Carriere 45bceeadceSEtienne Carriere # Magic number 46bceeadceSEtienne Carriere dest_fd.write(struct.pack('<I', hdr_magic_number)) 47bceeadceSEtienne Carriere 48bceeadceSEtienne Carriere # Image signature (empty) 49bceeadceSEtienne Carriere dest_fd.write(b'\x00' * 64) 50bceeadceSEtienne Carriere 51bceeadceSEtienne Carriere # Image checksum ... EDCSA algorithm 52bceeadceSEtienne Carriere dest_fd.write(struct.pack('<IBBBBIIIIIIII', 53bceeadceSEtienne Carriere checksum, 54bceeadceSEtienne Carriere hdr_header_ver_variant, 55bceeadceSEtienne Carriere hdr_header_ver_minor, 56bceeadceSEtienne Carriere hdr_header_ver_major, 57bceeadceSEtienne Carriere 0, 58bceeadceSEtienne Carriere sizedest - header_size, 59bceeadceSEtienne Carriere entry, 60bceeadceSEtienne Carriere 0, 61bceeadceSEtienne Carriere load, 62bceeadceSEtienne Carriere 0, 63bceeadceSEtienne Carriere hdr_version_number, 64bceeadceSEtienne Carriere hdr_option_flags, 65bceeadceSEtienne Carriere hdr_edcsa_algo)) 66bceeadceSEtienne Carriere 67bceeadceSEtienne Carriere # EDCSA public key (empty) 68bceeadceSEtienne Carriere dest_fd.write(b'\x00' * 64) 69bceeadceSEtienne Carriere 70bceeadceSEtienne Carriere # Padding 71*ed4b5e39SEtienne Carriere dest_fd.write(b'\x00' * 83) 72*ed4b5e39SEtienne Carriere dest_fd.write(struct.pack('<B', bintype)) 73bceeadceSEtienne Carriere dest_fd.close() 74bceeadceSEtienne Carriere 75bceeadceSEtienne Carriere 76*ed4b5e39SEtienne Carrieredef stm32image_create_header_file(source, dest, load, entry, bintype): 77bceeadceSEtienne Carriere dest_fd = open(dest, 'w+b') 78bceeadceSEtienne Carriere src_fd = open(source, 'rb') 79bceeadceSEtienne Carriere 80bceeadceSEtienne Carriere dest_fd.write(b'\x00' * header_size) 81bceeadceSEtienne Carriere 82bceeadceSEtienne Carriere sizesrc = get_size(src_fd) 83bceeadceSEtienne Carriere if sizesrc > 0: 84bceeadceSEtienne Carriere mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) 85bceeadceSEtienne Carriere dest_fd.write(mmsrc[:sizesrc]) 86bceeadceSEtienne Carriere mmsrc.close() 87bceeadceSEtienne Carriere 88bceeadceSEtienne Carriere src_fd.close() 89bceeadceSEtienne Carriere 90*ed4b5e39SEtienne Carriere stm32image_set_header(dest_fd, load, entry, bintype) 91bceeadceSEtienne Carriere 92bceeadceSEtienne Carriere dest_fd.close() 93bceeadceSEtienne Carriere 94bceeadceSEtienne Carriere 95bceeadceSEtienne Carrieredef int_parse(str): 96bceeadceSEtienne Carriere return int(str, 0) 97bceeadceSEtienne Carriere 98bceeadceSEtienne Carriere 99bceeadceSEtienne Carrieredef get_args(): 100bceeadceSEtienne Carriere parser = argparse.ArgumentParser() 101bceeadceSEtienne Carriere parser.add_argument('--source', 102bceeadceSEtienne Carriere required=True, 103bceeadceSEtienne Carriere help='Source file') 104bceeadceSEtienne Carriere 105bceeadceSEtienne Carriere parser.add_argument('--dest', 106bceeadceSEtienne Carriere required=True, 107bceeadceSEtienne Carriere help='Destination file') 108bceeadceSEtienne Carriere 109bceeadceSEtienne Carriere parser.add_argument('--load', 110bceeadceSEtienne Carriere required=True, type=int_parse, 111bceeadceSEtienne Carriere help='Load address') 112bceeadceSEtienne Carriere 113bceeadceSEtienne Carriere parser.add_argument('--entry', 114bceeadceSEtienne Carriere required=True, type=int_parse, 115bceeadceSEtienne Carriere help='Entry point') 116bceeadceSEtienne Carriere 117*ed4b5e39SEtienne Carriere parser.add_argument('--bintype', 118*ed4b5e39SEtienne Carriere required=True, type=int_parse, 119*ed4b5e39SEtienne Carriere help='Binary identification') 120*ed4b5e39SEtienne Carriere 121bceeadceSEtienne Carriere return parser.parse_args() 122bceeadceSEtienne Carriere 123bceeadceSEtienne Carriere 124bceeadceSEtienne Carrieredef main(): 125bceeadceSEtienne Carriere args = get_args() 126bceeadceSEtienne Carriere source_file = args.source 127bceeadceSEtienne Carriere destination_file = args.dest 128bceeadceSEtienne Carriere load_address = args.load 129bceeadceSEtienne Carriere entry_point = args.entry 130*ed4b5e39SEtienne Carriere binary_type = args.bintype 131bceeadceSEtienne Carriere 132bceeadceSEtienne Carriere stm32image_create_header_file(source_file, 133bceeadceSEtienne Carriere destination_file, 134bceeadceSEtienne Carriere load_address, 135*ed4b5e39SEtienne Carriere entry_point, 136*ed4b5e39SEtienne Carriere binary_type) 137bceeadceSEtienne Carriere 138bceeadceSEtienne Carriere 139bceeadceSEtienne Carriereif __name__ == "__main__": 140bceeadceSEtienne Carriere main() 141