forked from srobo/dfu-bootloader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
insert_serial.py
executable file
·93 lines (72 loc) · 2.62 KB
/
insert_serial.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
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python3
import argparse
from pathlib import Path
def pad_serial(serial_num, length=16):
""
# Trim and pad to one below length to allow for a null terminator
serial_num_truncated = serial_num[:length - 1]
serial_num_padded = serial_num_truncated.ljust(length - 1, '\0')
return serial_num_padded + '\0'
def insert_bin_serial(data, serial_num, addr):
""
data_array = bytearray(data) # make the data mutable
serial_bytes = serial_num.encode('ascii')
length = len(serial_bytes)
# insert serial using slicing
data_array[addr:(addr + length)] = serial_bytes
return bytes(data_array)
def ExistingFile(val):
""" To be used as an argparse argument type
Tests the file exists without opening it to avoid issues with files
not being closed: https://bugs.python.org/issue13824
"""
f = Path(val)
try:
if not f.is_file():
raise argparse.ArgumentTypeError(f'File not found {val}')
except PermissionError as e:
raise argparse.ArgumentTypeError(e)
return f
def ValidPath(val):
""" To be used as an argparse argument type
Tests the filepath exists without creating it to avoid issues with
files not being closed: https://bugs.python.org/issue13824
"""
f = Path(val)
try:
if not f.parent.is_dir():
raise argparse.ArgumentTypeError(f'Path does not exist {val}')
except PermissionError as e:
raise argparse.ArgumentTypeError(e)
return f
def main():
parser = argparse.ArgumentParser(
description="Insert a serial number into a pre-compiled binary"
)
parser.add_argument(
'-a', '--address', type=int, default=0x1FE0,
help=(
"The address offset from the start of the file to place the "
"serial number (defaults to 0x1FE0)"
)
)
parser.add_argument(
'-l', '--length', type=int, default=16,
help="The length of the serial number placeholder, including the null terminator (defaults to 16)"
)
parser.add_argument('serial_num', help="The value to set the serial number to.")
parser.add_argument(
'infile', type=ExistingFile,
help="The template file to insert the serial number into.",
)
parser.add_argument(
'outfile', type=ValidPath,
help="The file to write the output to.",
)
args = parser.parse_args()
data = args.infile.read_bytes()
serial_num = pad_serial(args.serial_num, args.length)
new_data = insert_bin_serial(data, serial_num, args.address)
args.outfile.write_bytes(new_data)
if __name__ == "__main__":
main()