1#! /usr/bin/env python3
2
3import os, sys, re, struct, platform, getopt, subprocess
4from sys import platform as _platform
5import array,hashlib,struct
6
7def update_crc16(crcin, byte):
8    crc = crcin
9    calculen = byte | 0x100
10    crc <<= 1
11    calculen <<= 1
12    if calculen & 0x100 > 0:
13        crc += 1
14    if crc & 0x10000 > 0:
15        crc ^= 0x1021
16    while((calculen & 0x10000) == 0):
17        crc <<= 1
18        calculen <<= 1
19        if calculen & 0x100 > 0:
20            crc += 1
21        if crc & 0x10000 > 0:
22            crc ^= 0x1021
23
24    return crc & 0xFFFF
25
26def crc16_calculate(data, len):
27    crc = 0
28    for i in range(0, len):
29        crc = update_crc16(crc, data[i])
30    crc = update_crc16(crc, 0)
31    crc = update_crc16(crc, 0)
32    return crc & 0xFFFF
33
34def hashcalculate(type, indata):
35    if type == "md5":
36        hashmethod = hashlib.md5()
37    elif type == "sha256":
38        hashmethod = hashlib.sha256()
39    else:
40        print("don't support other hash type")
41        return 0
42    hashmethod.update(indata)
43    value = hashmethod.digest()
44    return value
45
46def print_usage():
47    print("")
48    print("Usage: Merge a bin file into an exist bin file, create one if target is not exist")
49    print(sys.argv[0])
50    print("Optional Usage:")
51    print(" [-o] <target binary file>")
52    print(" [-m] <image magic type>")
53    print(" [-h | --help] Display usage")
54    print(" [<input binary file>]")
55    sys.stdout.flush()
56
57def main():
58    try:
59        opts, args = getopt.getopt(sys.argv[1:], 'o:m:h')
60    except getopt.GetoptError as err:
61        print(str(err))
62        print_usage()
63        sys.exit(2)
64
65    if not len(args) == 3:
66        print_usage()
67        sys.exit(2)
68    else:
69        INPUT_FILE = args[0]
70    if not os.path.exists(INPUT_FILE):
71        print("Please input a binary file")
72        sys.exit(2)
73    for opt, arg in opts:
74        if opt == "-o":
75            OUTPUT_FILE = arg
76        elif opt == "-m":
77            magic_str = arg
78        elif opt == "-h":
79            print_usage()
80            sys.exit()
81    try:
82        with open(INPUT_FILE, 'rb') as hfin:
83            imagedata = hfin.read()
84            #print("filelen = " + str(len(imagedata)))
85    except FileNotFoundError:
86        print(INPUT_FILE + " is not exist!")
87        sys.exit(2)
88    except:
89        print("read " + INPUT_FILE + " failed!")
90        sys.exit(2)
91
92    image_alignment = 0xffffffff
93    imagedata += struct.pack('<I', image_alignment)
94    image_info_magic = 0xefefefef
95    image_valid_len = len(imagedata)
96    image_md5 = hashcalculate("md5", imagedata)
97    image_num = 0x01
98    image_res = 0x00
99    image_crc16 = crc16_calculate(bytearray(imagedata), image_valid_len)
100
101    newimagedata = imagedata[0:image_valid_len]
102    newimagedata += struct.pack('<I', image_info_magic)
103    newimagedata += struct.pack('<I', image_valid_len)
104    newimagedata += image_md5
105    newimagedata += struct.pack('B', image_num)
106    newimagedata += struct.pack('B', image_res)
107    newimagedata += struct.pack('<H', image_crc16)
108
109    OUTPUT_FILE = INPUT_FILE+".md5"
110    try:
111        with open(OUTPUT_FILE, 'wb') as imagefout:
112            imagefout.write(newimagedata)
113    except FileNotFoundError:
114        print("output file path error!")
115        sys.exit(2)
116    except:
117        print("output write error!")
118        sys.exit(2)
119
120    os.remove(INPUT_FILE)
121    os.rename(OUTPUT_FILE,INPUT_FILE)
122
123if __name__ == "__main__":
124    try:
125        main()
126    except KeyboardInterrupt:
127        pass
128