forked from Flipper-XFW/Xtreme-Firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flash.py
executable file
·175 lines (158 loc) · 6.35 KB
/
flash.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/env python3
from flipper.app import App
from flipper.assets.coprobin import CoproBinary
from flipper.cube import CubeProgrammer
STATEMENT = "AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE"
class Main(App):
def init(self):
self.subparsers = self.parser.add_subparsers(help="sub-command help")
# Wipe
self.parser_wipe = self.subparsers.add_parser("wipe", help="Wipe MCU Flash")
self._addArgsSWD(self.parser_wipe)
self.parser_wipe.set_defaults(func=self.wipe)
# Core 1 boot
self.parser_core1bootloader = self.subparsers.add_parser(
"core1bootloader", help="Flash Core1 Bootloader"
)
self._addArgsSWD(self.parser_core1bootloader)
self.parser_core1bootloader.add_argument(
"bootloader", type=str, help="Bootloader binary"
)
self.parser_core1bootloader.set_defaults(func=self.core1bootloader)
# Core 1 firmware
self.parser_core1firmware = self.subparsers.add_parser(
"core1firmware", help="Flash Core1 Firmware"
)
self._addArgsSWD(self.parser_core1firmware)
self.parser_core1firmware.add_argument(
"firmware", type=str, help="Firmware binary"
)
self.parser_core1firmware.set_defaults(func=self.core1firmware)
# Core 1 all
self.parser_core1 = self.subparsers.add_parser(
"core1", help="Flash Core1 Bootloader and Firmware"
)
self._addArgsSWD(self.parser_core1)
self.parser_core1.add_argument("bootloader", type=str, help="Bootloader binary")
self.parser_core1.add_argument("firmware", type=str, help="Firmware binary")
self.parser_core1.set_defaults(func=self.core1)
# Core 2 fus
self.parser_core2fus = self.subparsers.add_parser(
"core2fus", help="Flash Core2 Firmware Update Service"
)
self._addArgsSWD(self.parser_core2fus)
self.parser_core2fus.add_argument(
"--statement",
type=str,
help="NEVER FLASH FUS, IT WILL ERASE CRYPTO ENCLAVE",
required=True,
)
self.parser_core2fus.add_argument(
"fus_address", type=str, help="Firmware Update Service Address"
)
self.parser_core2fus.add_argument(
"fus", type=str, help="Firmware Update Service Binary"
)
self.parser_core2fus.set_defaults(func=self.core2fus)
# Core 2 radio stack
self.parser_core2radio = self.subparsers.add_parser(
"core2radio", help="Flash Core2 Radio stack"
)
self._addArgsSWD(self.parser_core2radio)
self.parser_core2radio.add_argument(
"radio", type=str, help="Radio Stack Binary"
)
self.parser_core2radio.add_argument(
"--addr",
dest="radio_address",
help="Radio Stack Binary Address, as per release_notes",
type=lambda x: int(x, 16),
default=0,
required=False,
)
self.parser_core2radio.set_defaults(func=self.core2radio)
def _addArgsSWD(self, parser):
parser.add_argument(
"--port", type=str, help="Port to connect: swd or usb1", default="swd"
)
parser.add_argument("--serial", type=str, help="ST-Link Serial Number")
def _getCubeParams(self):
return {
"port": self.args.port,
"serial": self.args.serial,
}
def wipe(self):
self.logger.info("Wiping flash")
cp = CubeProgrammer(self._getCubeParams())
self.logger.info("Setting RDP to 0xBB")
cp.setOptionBytes({"RDP": ("0xBB", "rw")})
self.logger.info("Verifying RDP")
r = cp.checkOptionBytes({"RDP": ("0xBB", "rw")})
assert r is True
self.logger.info(f"Result: {r}")
self.logger.info("Setting RDP to 0xAA")
cp.setOptionBytes({"RDP": ("0xAA", "rw")})
self.logger.info("Verifying RDP")
r = cp.checkOptionBytes({"RDP": ("0xAA", "rw")})
assert r is True
self.logger.info(f"Result: {r}")
self.logger.info("Complete")
return 0
def core1bootloader(self):
self.logger.info("Flashing bootloader")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08000000", self.args.bootloader)
self.logger.info("Complete")
cp.resetTarget()
return 0
def core1firmware(self):
self.logger.info("Flashing firmware")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08008000", self.args.firmware)
self.logger.info("Complete")
cp.resetTarget()
return 0
def core1(self):
self.logger.info("Flashing bootloader")
cp = CubeProgrammer(self._getCubeParams())
cp.flashBin("0x08000000", self.args.bootloader)
self.logger.info("Flashing firmware")
cp.flashBin("0x08008000", self.args.firmware)
cp.resetTarget()
self.logger.info("Complete")
return 0
def core2fus(self):
if self.args.statement != STATEMENT:
self.logger.error(
"PLEASE DON'T. THIS FEATURE INTENDED ONLY FOR FACTORY FLASHING"
)
return 1
self.logger.info("Flashing Firmware Update Service")
cp = CubeProgrammer(self._getCubeParams())
cp.flashCore2(self.args.fus_address, self.args.fus)
self.logger.info("Complete")
return 0
def core2radio(self):
stack_info = CoproBinary(self.args.radio)
if not stack_info.is_stack():
self.logger.error("Not a Radio Stack")
return 1
self.logger.info(f"Will flash {stack_info.img_sig.get_version()}")
radio_address = self.args.radio_address
if not radio_address:
radio_address = stack_info.get_flash_load_addr()
self.logger.warning(
f"Radio address not provided, guessed as 0x{radio_address:X}"
)
if radio_address > 0x080E0000:
self.logger.error("I KNOW WHAT YOU DID LAST SUMMER")
return 1
cp = CubeProgrammer(self._getCubeParams())
self.logger.info("Removing Current Radio Stack")
cp.deleteCore2RadioStack()
self.logger.info("Flashing Radio Stack")
cp.flashCore2(radio_address, self.args.radio)
self.logger.info("Complete")
return 0
if __name__ == "__main__":
Main()()