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,96 @@ 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 (src -> pos .offset < 0x10000 )
193+ RG_LOGW ("Skipping partition %.16s: Forbidden region." , (char * )src -> label );
194+ else if (dst == running_partition )
197195 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 );
200196 else
201197 {
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+ }
209213 }
210214 }
211215
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+ }
213232
214- if (queue_count == 0 )
233+ if (dangerous )
215234 {
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+ };
218265 }
219266
267+ rg_display_clear (C_BLACK );
268+
220269 if (!do_flash (queue , queue_count , fp ))
221270 goto fail ;
222271
0 commit comments