1414// CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
1515
1616#define MAX_PARTITIONS (24) // ESP_PARTITION_TABLE_MAX_ENTRIES
17- #define ALIGN_BLOCK (val , alignment ) ((int)(((val) + (alignment - 1)) / alignment) * alignment)
1817
1918#define RETRO_GO_IMG_MAGIC "RG_IMG_0"
2019typedef struct
@@ -35,7 +34,7 @@ typedef struct
3534 struct {int offset , size ;} dst ;
3635} flash_task_t ;
3736
38- static size_t gp_buffer_size = 0x20000 ;
37+ static size_t gp_buffer_size = 0x10000 ;
3938static void * gp_buffer = NULL ;
4039static rg_app_t * app ;
4140
@@ -47,6 +46,8 @@ static rg_app_t *app;
4746 rg_gui_alert(_("Error"), FORMAT(error_message)); \
4847 goto fail; \
4948 }
49+ #define ALIGN_BLOCK (val , alignment ) ((int)(((val) + (alignment - 1)) / alignment) * alignment)
50+ #define CHECK_OVERLAP (start1 , end1 , start2 , end2 ) ((end1) > (start2) && (end2) > (start1))
5051
5152static bool fread_at (void * output , int offset , int length , FILE * fp )
5253{
@@ -159,11 +160,6 @@ static bool do_flash(flash_task_t *queue, size_t queue_count, FILE *fp)
159160 return false;
160161}
161162
162- static bool do_update_dangerous (const char * filename )
163- {
164- return false;
165- }
166-
167163static bool do_update (const char * filename )
168164{
169165 esp_partition_info_t partition_table [MAX_PARTITIONS ] = {0 };
@@ -180,43 +176,94 @@ static bool do_update(const char *filename)
180176 if (!parse_file (partition_table , & num_partitions , fp ))
181177 goto fail ;
182178
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 ;
185185 for (size_t i = 0 ; i < num_partitions ; ++ i )
186186 {
187187 const esp_partition_info_t * src = & partition_table [i ];
188188 const esp_partition_t * dst = esp_partition_find_first (src -> type , ESP_PARTITION_SUBTYPE_ANY , (char * )src -> label );
189189
190190 if (src -> type != PART_TYPE_APP || (src -> subtype & 0xF0 ) != PART_SUBTYPE_OTA_FLAG )
191191 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 )
197193 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 );
200194 else
201195 {
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+ }
209211 }
210212 }
211213
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+ }
213230
214- if (queue_count == 0 )
231+ if (dangerous )
215232 {
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+ };
218263 }
219264
265+ rg_display_clear (C_BLACK );
266+
220267 if (!do_flash (queue , queue_count , fp ))
221268 goto fail ;
222269
0 commit comments