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,94 @@ 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 (dst == running_partition )
197
193
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
194
else
201
195
{
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 ;
196
+ updatable_partitions ++ ;
197
+ if (!dst )
198
+ RG_LOGW ("Skipping partition %.16s: No match found." , (char * )src -> label );
199
+ else if (dst -> size < src -> pos .size )
200
+ RG_LOGW ("Skipping partition %.16s: New partition is bigger." , (char * )src -> label );
201
+ else
202
+ {
203
+ RG_LOGI ("Partition %.16s can be updated!" , (char * )src -> label );
204
+ flash_task_t * task = memset (& queue [queue_count ++ ], 0 , sizeof (flash_task_t ));
205
+ memcpy (task -> name , src -> label , 16 );
206
+ task -> src .offset = src -> pos .offset ;
207
+ task -> src .size = src -> pos .size ;
208
+ task -> dst .offset = dst -> address ;
209
+ task -> dst .size = dst -> size ;
210
+ }
209
211
}
210
212
}
211
213
212
- rg_display_clear (C_BLACK );
214
+ if (updatable_partitions != queue_count )
215
+ {
216
+ // Some partitions can't be updated with this method, we have to attempt a dangerous update instead!
217
+ RG_LOGW ("Some partitions cannot be updated in this mode. updatable_partitions=%d, queue_count=%d" ,
218
+ updatable_partitions , queue_count );
219
+ #if CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
220
+ // The presence of a factory app that is NOT the current app indicates that we're controlled by
221
+ // odroid-go-firmware or odroid-go-multifirmware and it isn't safe to do arbitrary flash writes
222
+ if (factory_partition && factory_partition != running_partition )
223
+ rg_gui_alert (_ ("Error" ), "Probably running under odroid-go-multifirmware, cannot do full update!" );
224
+ else
225
+ dangerous = true;
226
+ #else
227
+ rg_gui_alert (_ ("Error" ), "CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set, cannot do full update!\n" );
228
+ #endif
229
+ }
213
230
214
- if (queue_count == 0 )
231
+ if (dangerous )
215
232
{
216
- // Try dangerous update
217
- // goto fail;
233
+ RG_LOGW ("Performing a dangerous update!" );
234
+ queue_count = 0 ;
235
+ for (size_t i = 0 ; i < num_partitions ; ++ i )
236
+ {
237
+ const esp_partition_info_t * src = & partition_table [i ];
238
+ if (src -> type != PART_TYPE_APP || (src -> subtype & 0xF0 ) != PART_SUBTYPE_OTA_FLAG )
239
+ RG_LOGW ("Skipping partition %.16s: Unsupported type." , (char * )src -> label );
240
+ else if (src -> pos .offset < 0x10000 )
241
+ RG_LOGW ("Skipping partition %.16s: Forbidden region." , (char * )src -> label );
242
+ // FIXME: Instead of skipping an overlaping partition, we should attempt to relocate it.
243
+ else if (CHECK_OVERLAP (src -> pos .offset , src -> pos .offset + src -> pos .size ,
244
+ running_partition -> address , running_partition -> address + running_partition -> size ))
245
+ RG_LOGW ("Skipping partition %.16s: Overlap with self." , (char * )src -> label );
246
+ else
247
+ {
248
+ RG_LOGI ("Partition %.16s can be updated!" , (char * )src -> label );
249
+ flash_task_t * task = memset (& queue [queue_count ++ ], 0 , sizeof (flash_task_t ));
250
+ memcpy (task -> name , src -> label , 16 );
251
+ task -> src .offset = src -> pos .offset ;
252
+ task -> src .size = src -> pos .size ;
253
+ task -> dst .offset = src -> pos .offset ;
254
+ task -> dst .size = src -> pos .size ;
255
+ }
256
+ }
257
+
258
+ queue [queue_count ++ ] = (flash_task_t ){
259
+ .name = "partition_table" ,
260
+ .src = {ESP_PARTITION_TABLE_OFFSET , ESP_PARTITION_TABLE_MAX_LEN },
261
+ .dst = {ESP_PARTITION_TABLE_OFFSET , ESP_PARTITION_TABLE_MAX_LEN },
262
+ };
218
263
}
219
264
265
+ rg_display_clear (C_BLACK );
266
+
220
267
if (!do_flash (queue , queue_count , fp ))
221
268
goto fail ;
222
269
0 commit comments