14
14
// CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
15
15
16
16
#define MAX_PARTITIONS (24) // ESP_PARTITION_TABLE_MAX_ENTRIES
17
- #define ALIGN_BLOCK (val , alignment ) ((int)(((val) + (alignment - 1)) / alignment) * alignment)
18
17
19
18
#define RETRO_GO_IMG_MAGIC "RG_IMG_0"
20
19
typedef struct
@@ -35,7 +34,7 @@ typedef struct
35
34
struct {int offset , size ;} dst ;
36
35
} flash_task_t ;
37
36
38
- static size_t gp_buffer_size = 0x20000 ;
37
+ static size_t gp_buffer_size = 0x10000 ;
39
38
static void * gp_buffer = NULL ;
40
39
static rg_app_t * app ;
41
40
@@ -47,6 +46,8 @@ static rg_app_t *app;
47
46
rg_gui_alert(_("Error"), FORMAT(error_message)); \
48
47
goto fail; \
49
48
}
49
+ #define ALIGN_BLOCK (val , alignment ) ((int)(((val) + (alignment - 1)) / alignment) * alignment)
50
+ #define CHECK_OVERLAP (start1 , end1 , start2 , end2 ) ((end1) > (start2) && (end2) > (start1))
50
51
51
52
static bool fread_at (void * output , int offset , int length , FILE * fp )
52
53
{
@@ -159,11 +160,6 @@ static bool do_flash(flash_task_t *queue, size_t queue_count, FILE *fp)
159
160
return false;
160
161
}
161
162
162
- static bool do_update_dangerous (const char * filename )
163
- {
164
- return false;
165
- }
166
-
167
163
static bool do_update (const char * filename )
168
164
{
169
165
esp_partition_info_t partition_table [MAX_PARTITIONS ] = {0 };
@@ -180,43 +176,96 @@ static bool do_update(const char *filename)
180
176
if (!parse_file (partition_table , & num_partitions , fp ))
181
177
goto fail ;
182
178
183
- const char * current_partition = esp_ota_get_running_partition ()-> label ;
184
- // At this time we only flash partitions of type app and subtype ota_X
179
+ const esp_partition_t * running_partition = esp_ota_get_running_partition ();
180
+ const esp_partition_t * factory_partition = esp_partition_find_first (0x00 , 0x00 , NULL );
181
+ bool dangerous = false;
182
+
183
+ RG_LOGW ("Checking if we can perform a standard update..." );
184
+ size_t updatable_partitions = 0 ;
185
185
for (size_t i = 0 ; i < num_partitions ; ++ i )
186
186
{
187
187
const esp_partition_info_t * src = & partition_table [i ];
188
188
const esp_partition_t * dst = esp_partition_find_first (src -> type , ESP_PARTITION_SUBTYPE_ANY , (char * )src -> label );
189
189
190
190
if (src -> type != PART_TYPE_APP || (src -> subtype & 0xF0 ) != PART_SUBTYPE_OTA_FLAG )
191
191
RG_LOGW ("Skipping partition %.16s: Unsupported type." , (char * )src -> label );
192
- else if (!dst )
193
- RG_LOGW ("Skipping partition %.16s: No match found." , (char * )src -> label );
194
- else if ((dst -> subtype & 0xF0 ) != PART_SUBTYPE_OTA_FLAG )
195
- RG_LOGW ("Skipping partition %.16s: Not an OTA partition." , (char * )src -> label );
196
- else if (strncmp (current_partition , dst -> label , 16 ) == 0 )
192
+ else if (src -> pos .offset < 0x10000 )
193
+ RG_LOGW ("Skipping partition %.16s: Forbidden region." , (char * )src -> label );
194
+ else if (dst == running_partition )
197
195
RG_LOGW ("Skipping partition %.16s: Currently running." , (char * )src -> label );
198
- else if (dst -> size < src -> pos .size )
199
- RG_LOGW ("Skipping partition %.16s: New partition is bigger." , (char * )src -> label );
200
196
else
201
197
{
202
- RG_LOGI ("Partition %.16s can be updated!" , (char * )src -> label );
203
- flash_task_t * task = memset (& queue [queue_count ++ ], 0 , sizeof (flash_task_t ));
204
- memcpy (task -> name , src -> label , 16 );
205
- task -> src .offset = src -> pos .offset ;
206
- task -> src .size = src -> pos .size ;
207
- task -> dst .offset = dst -> address ;
208
- task -> dst .size = dst -> size ;
198
+ updatable_partitions ++ ;
199
+ if (!dst )
200
+ RG_LOGW ("Skipping partition %.16s: No match found." , (char * )src -> label );
201
+ else if (dst -> size < src -> pos .size )
202
+ RG_LOGW ("Skipping partition %.16s: New partition is bigger." , (char * )src -> label );
203
+ else
204
+ {
205
+ RG_LOGI ("Partition %.16s can be updated!" , (char * )src -> label );
206
+ flash_task_t * task = memset (& queue [queue_count ++ ], 0 , sizeof (flash_task_t ));
207
+ memcpy (task -> name , src -> label , 16 );
208
+ task -> src .offset = src -> pos .offset ;
209
+ task -> src .size = src -> pos .size ;
210
+ task -> dst .offset = dst -> address ;
211
+ task -> dst .size = dst -> size ;
212
+ }
209
213
}
210
214
}
211
215
212
- rg_display_clear (C_BLACK );
216
+ if (updatable_partitions != queue_count )
217
+ {
218
+ // Some partitions can't be updated with this method, we have to attempt a dangerous update instead!
219
+ RG_LOGW ("Some partitions cannot be updated in this mode. updatable_partitions=%d, queue_count=%d" ,
220
+ updatable_partitions , queue_count );
221
+ #if CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
222
+ // The presence of a factory app that is NOT the current app indicates that we're controlled by
223
+ // odroid-go-firmware or odroid-go-multifirmware and it isn't safe to do arbitrary flash writes
224
+ if (factory_partition && factory_partition != running_partition )
225
+ rg_gui_alert (_ ("Error" ), "Probably running under odroid-go-multifirmware, cannot do full update!" );
226
+ else
227
+ dangerous = true;
228
+ #else
229
+ rg_gui_alert (_ ("Error" ), "CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set, cannot do full update!\n" );
230
+ #endif
231
+ }
213
232
214
- if (queue_count == 0 )
233
+ if (dangerous )
215
234
{
216
- // Try dangerous update
217
- // goto fail;
235
+ RG_LOGW ("Performing a dangerous update!" );
236
+ queue_count = 0 ;
237
+ for (size_t i = 0 ; i < num_partitions ; ++ i )
238
+ {
239
+ const esp_partition_info_t * src = & partition_table [i ];
240
+ if (src -> type != PART_TYPE_APP || (src -> subtype & 0xF0 ) != PART_SUBTYPE_OTA_FLAG )
241
+ RG_LOGW ("Skipping partition %.16s: Unsupported type." , (char * )src -> label );
242
+ else if (src -> pos .offset < 0x10000 )
243
+ RG_LOGW ("Skipping partition %.16s: Forbidden region." , (char * )src -> label );
244
+ // FIXME: Instead of skipping an overlaping partition, we should attempt to relocate it.
245
+ else if (CHECK_OVERLAP (src -> pos .offset , src -> pos .offset + src -> pos .size ,
246
+ running_partition -> address , running_partition -> address + running_partition -> size ))
247
+ RG_LOGW ("Skipping partition %.16s: Overlap with self." , (char * )src -> label );
248
+ else
249
+ {
250
+ RG_LOGI ("Partition %.16s can be updated!" , (char * )src -> label );
251
+ flash_task_t * task = memset (& queue [queue_count ++ ], 0 , sizeof (flash_task_t ));
252
+ memcpy (task -> name , src -> label , 16 );
253
+ task -> src .offset = src -> pos .offset ;
254
+ task -> src .size = src -> pos .size ;
255
+ task -> dst .offset = src -> pos .offset ;
256
+ task -> dst .size = src -> pos .size ;
257
+ }
258
+ }
259
+
260
+ queue [queue_count ++ ] = (flash_task_t ){
261
+ .name = "partition_table" ,
262
+ .src = {ESP_PARTITION_TABLE_OFFSET , ESP_PARTITION_TABLE_MAX_LEN },
263
+ .dst = {ESP_PARTITION_TABLE_OFFSET , ESP_PARTITION_TABLE_MAX_LEN },
264
+ };
218
265
}
219
266
267
+ rg_display_clear (C_BLACK );
268
+
220
269
if (!do_flash (queue , queue_count , fp ))
221
270
goto fail ;
222
271
0 commit comments