1
1
#!/usr/bin/env python3
2
2
3
- import io
4
3
import math
5
4
import os
6
5
import shutil
7
6
import tarfile
8
7
import zlib
9
8
from os .path import exists , join
10
9
11
- import heatshrink2
12
10
from flipper .app import App
13
11
from flipper .assets .coprobin import CoproBinary , get_stack_type
14
12
from flipper .assets .heatshrink_stream import HeatshrinkDataStreamHeader
@@ -35,7 +33,12 @@ class Main(App):
35
33
)
36
34
37
35
FLASH_BASE = 0x8000000
38
- MIN_LFS_PAGES = 6
36
+ FLASH_PAGE_SIZE = 4 * 1024
37
+ MIN_GAP_PAGES = 2
38
+
39
+ # Update stage file larger than that is not loadable without fix
40
+ # https://github.com/flipperdevices/flipperzero-firmware/pull/3676
41
+ UPDATER_SIZE_THRESHOLD = 128 * 1024
39
42
40
43
HEATSHRINK_WINDOW_SIZE = 13
41
44
HEATSHRINK_LOOKAHEAD_SIZE = 6
@@ -117,7 +120,7 @@ def generate(self):
117
120
self .logger .error (
118
121
f"You are trying to bundle a non-standard stack type '{ self .args .radiotype } '."
119
122
)
120
- self .disclaimer ()
123
+ self .show_disclaimer ()
121
124
return 1
122
125
123
126
if radio_addr == 0 :
@@ -130,7 +133,9 @@ def generate(self):
130
133
if not exists (self .args .directory ):
131
134
os .makedirs (self .args .directory )
132
135
136
+ updater_stage_size = os .stat (self .args .stage ).st_size
133
137
shutil .copyfile (self .args .stage , join (self .args .directory , stage_basename ))
138
+
134
139
dfu_size = 0
135
140
if self .args .dfu :
136
141
dfu_size = os .stat (self .args .dfu ).st_size
@@ -146,10 +151,10 @@ def generate(self):
146
151
):
147
152
return 3
148
153
149
- if not self .layout_check (dfu_size , radio_addr ):
154
+ if not self .layout_check (updater_stage_size , dfu_size , radio_addr ):
150
155
self .logger .warn ("Memory layout looks suspicious" )
151
- if not self .args .disclaimer = = "yes" :
152
- self .disclaimer ()
156
+ if self .args .disclaimer ! = "yes" :
157
+ self .show_disclaimer ()
153
158
return 2
154
159
155
160
if self .args .splash :
@@ -198,22 +203,33 @@ def generate(self):
198
203
199
204
return 0
200
205
201
- def layout_check (self , fw_size , radio_addr ):
206
+ def layout_check (self , stage_size , fw_size , radio_addr ):
207
+ if stage_size > self .UPDATER_SIZE_THRESHOLD :
208
+ self .logger .warn (
209
+ f"Updater size { stage_size } b > { self .UPDATER_SIZE_THRESHOLD } b and is not loadable on older firmwares!"
210
+ )
211
+
202
212
if fw_size == 0 or radio_addr == 0 :
203
213
self .logger .info ("Cannot validate layout for partial package" )
204
214
return True
205
215
206
- lfs_span = radio_addr - self .FLASH_BASE - fw_size
207
- self .logger .debug (f"Expected LFS size: { lfs_span } " )
208
- lfs_span_pages = lfs_span / (4 * 1024 )
209
- if lfs_span_pages < self .MIN_LFS_PAGES :
216
+ fw2stack_gap = radio_addr - self .FLASH_BASE - fw_size
217
+ self .logger .debug (f"Expected reserved space size: { fw2stack_gap } " )
218
+ fw2stack_gap_pages = fw2stack_gap / self .FLASH_PAGE_SIZE
219
+ if fw2stack_gap_pages < 0 :
220
+ self .logger .warn (
221
+ f"Firmware image overlaps C2 region and is not programmable!"
222
+ )
223
+ return False
224
+
225
+ elif fw2stack_gap_pages < self .MIN_GAP_PAGES :
210
226
self .logger .warn (
211
- f"Expected LFS size is too small (~{ int (lfs_span_pages )} pages )"
227
+ f"Expected reserved flash size is too small (~{ int (fw2stack_gap_pages )} page(s), need >= { self . MIN_GAP_PAGES } page(s) )"
212
228
)
213
229
return False
214
230
return True
215
231
216
- def disclaimer (self ):
232
+ def show_disclaimer (self ):
217
233
self .logger .error (
218
234
"You might brick your device into a state in which you'd need an SWD programmer to fix it."
219
235
)
0 commit comments