-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathcalcsum.py
84 lines (57 loc) · 2.37 KB
/
calcsum.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import argparse
import mmap
import os
import struct
import sys
HEADER_LENGTH = 20
HEADER_MAGIC = 0x12345678
HEADER_RESERVED = 0x332255FF
PAYLOAD_LENGTH = 0x2ffe + 0x1000
def main() -> None:
parser = argparse.ArgumentParser(description='SWTG Update Firmware Checksum Calculator')
parser.add_argument('-u', '--update', help='Re-calculate sums', action='store_true')
parser.add_argument('firmware', type=argparse.FileType('r+b'))
args = parser.parse_args()
print_or_exit = print if args.update else sys.exit
with args.firmware as f:
with mmap.mmap(f.fileno(), 0) as mm:
header = bytearray(mm.read(HEADER_LENGTH))
magic, length, header_sum, payload_sum, reserved = struct.unpack('>5I', header)
print(f"magic: {magic:08x}",
f"length: {length:08x}",
f"header sum: {header_sum:08x}",
f"payload sum: {payload_sum:08x}",
f"reserved: {reserved:08x}",
header.hex(), sep='\n')
if magic != HEADER_MAGIC:
sys.exit('Invalid header magic')
if length + HEADER_LENGTH != mm.size():
sys.exit('Invalid header file length')
# Placeholder for the header sum
header[8:12] = b'\x00' * 4
if header_sum != sum(header):
print_or_exit('Invalid header checksum')
# Calculate payload sum...
calc_sum = sum(mm.read(PAYLOAD_LENGTH))
# Skip payload header
mm.seek(HEADER_LENGTH, os.SEEK_CUR)
# Placeholder for payload header sum
calc_sum += 0xff * HEADER_LENGTH
# Resume payload sum
calc_sum += sum(mm.read())
if calc_sum != payload_sum:
print_or_exit('Invalid payload checksum')
if args.update:
# Update the payload sum
header[12:16] = struct.pack('>I', calc_sum)
# Calculate the header sum
calc_sum = sum(header)
# Update the header sum
header[8:12] = struct.pack('>I', calc_sum)
print(header.hex())
# Update headers
mm[:HEADER_LENGTH] = header
mm[PAYLOAD_LENGTH+HEADER_LENGTH:PAYLOAD_LENGTH+HEADER_LENGTH*2] = header
sys.exit(0)
if __name__ == '__main__':
main()