#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
#
# SPDX-License-Identifier: LGPL-2.1+

import struct
import zlib
import argparse

def main(bin_fn, dfu_fn, pad, vid, pid, rev):

    # read binary file
    with open(bin_fn, 'rb') as f:
        blob = f.read()

    # pad blob to a specific size
    if pad:
        while len(blob) < int(pad, 16):
            blob += b'\0'

    # create DFU footer with checksum
    blob += struct.pack('<HHHH3sB',
                        int(rev, 16),   # version
                        int(pid, 16),   # PID
                        int(vid, 16),   # VID
                        0x0100,         # DFU version
                        b'UFD',         # signature
                        0x10)           # hdrlen
    crc32 = zlib.crc32(blob) ^ 0xffffffff
    blob += struct.pack('<L', crc32)

    # write binary file
    with open(dfu_fn, 'wb') as f:
        f.write(blob)

if __name__ == "__main__":

    # parse args
    parser = argparse.ArgumentParser(description='Add DFU footer on firmware')
    parser.add_argument('--bin', help='Path to the .bin file', required=True)
    parser.add_argument('--dfu', help='Output DFU file path', required=True)
    parser.add_argument('--pad', help='Pad to a specific size, e.g. 0x4000', default=None)
    parser.add_argument('--vid', help='Vendor ID, e.g. 0x273f', required=True)
    parser.add_argument('--pid', help='Product ID, e.g. 0x1002', required=True)
    parser.add_argument('--rev', help='Revision, e.g. 0x1000', required=True)
    args = parser.parse_args()
    main(args.bin, args.dfu, args.pad, args.vid, args.pid, args.rev)

Add a helper script to add a DFU header