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