text: #!/usr/bin/env python3
  # SPDX-License-Identifier: BSD-2-Clause
  #
  # Copyright (c) 2017-2018, STMicroelectronics
  #
  import argparse
  import struct
  import mmap
  
  header_size = 256
  hdr_magic_number = 0x324D5453  # magic ='S' 'T' 'M' 0x32
  hdr_header_ver_variant = 0
  hdr_header_ver_minor = 0
  hdr_header_ver_major = 1
  hdr_version_number = 0
  hdr_option_flags = 1           # bit0=1 no signature
  hdr_edcsa_algo = 1
  
  
  def get_size(file):
      file.seek(0, 2)        # End of the file
      size = file.tell()
      return size
  
  
  def stm32image_checksum(dest_fd, sizedest):
      csum = 0
      if sizedest < header_size:
          return 0
      dest_fd.seek(header_size, 0)
      length = sizedest - header_size
      while length > 0:
          csum += ord(dest_fd.read(1))
          length -= 1
      return csum
  
  
  def stm32image_set_header(dest_fd, load, entry, bintype):
      sizedest = get_size(dest_fd)
  
      checksum = stm32image_checksum(dest_fd, sizedest)
  
      dest_fd.seek(0, 0)
  
      # Magic number
      dest_fd.write(struct.pack('<I', hdr_magic_number))
  
      # Image signature (empty)
      dest_fd.write(b'\x00' * 64)
  
      # Image checksum ... EDCSA algorithm
      dest_fd.write(struct.pack('<IBBBBIIIIIIII',
                    checksum,
                    hdr_header_ver_variant,
                    hdr_header_ver_minor,
                    hdr_header_ver_major,
                    0,
                    sizedest - header_size,
                    entry,
                    0,
                    load,
                    0,
                    hdr_version_number,
                    hdr_option_flags,
                    hdr_edcsa_algo))
  
      # EDCSA public key (empty)
      dest_fd.write(b'\x00' * 64)
  
      # Padding
      dest_fd.write(b'\x00' * 83)
      dest_fd.write(struct.pack('<B', bintype))
      dest_fd.close()
  
  
  def stm32image_create_header_file(source, dest, load, entry, bintype):
      dest_fd = open(dest, 'w+b')
      src_fd = open(source, 'rb')
  
      dest_fd.write(b'\x00' * header_size)
  
      sizesrc = get_size(src_fd)
      if sizesrc > 0:
          mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ)
          dest_fd.write(mmsrc[:sizesrc])
          mmsrc.close()
  
      src_fd.close()
  
      stm32image_set_header(dest_fd, load, entry, bintype)
  
      dest_fd.close()
  
  
  def int_parse(str):
      return int(str, 0)
  
  
  def get_args():
      parser = argparse.ArgumentParser()
      parser.add_argument('--source',
                          required=True,
                          help='Source file')
  
      parser.add_argument('--dest',
                          required=True,
                          help='Destination file')
  
      parser.add_argument('--load',
                          required=True, type=int_parse,
                          help='Load address')
  
      parser.add_argument('--entry',
                          required=True, type=int_parse,
                          help='Entry point')
  
      parser.add_argument('--bintype',
                          required=True, type=int_parse,
                          help='Binary identification')
  
      return parser.parse_args()
  
  
  def main():
      args = get_args()
      source_file = args.source
      destination_file = args.dest
      load_address = args.load
      entry_point = args.entry
      binary_type = args.bintype
  
      stm32image_create_header_file(source_file,
                                    destination_file,
                                    load_address,
                                    entry_point,
                                    binary_type)
  
  
  if __name__ == "__main__":
      main()
  