@@ -377,8 +377,17 @@ bool ovms_partition_table_upgrade_store(OvmsWriter* writer)
377377 OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
378378 writer->puts (" Added new store2 partition to partition table" );
379379
380+ // Erase the region to ensure a clean start with auto reformatting on mount
381+ writer->printf (" Erasing store2 data (%" PRId32 " bytes)...\n " , p->data .entry .size );
382+ if (spi_flash_erase_range (p->data .entry .address , p->data .entry .size ) != ESP_OK )
383+ {
384+ writer->puts (" Warning: erasing store2 data failed, may need manual erase/reflash if formatting fails" );
385+ // This is only an issue if store2 is also corrupted and doesn't trigger a reformat
386+ // on the following mount attempt -- in this case the user will need to reflash via USB
387+ }
388+
380389 // Then we need to add the MD5 checksum record
381- p++;
390+ p++; // safe to assume we have one of the max 96 partition slots left to use
382391 ovms_partition_table_void_entry (p);
383392 p->magic_id = PARTITION_MD5_MAGIC ;
384393 OVMS_MD5_Final (p->data .md5 .digest , &md5_ctx);
@@ -411,6 +420,11 @@ bool ovms_partition_table_downgrade_store(OvmsWriter* writer)
411420 return false ;
412421 }
413422
423+ if (ovms_store2_mounted)
424+ {
425+ ovms_partition_table_unmount_store2 (writer);
426+ }
427+
414428 size_t offset = ovms_partition_table_find ();
415429 if (offset == 0 )
416430 {
@@ -430,22 +444,23 @@ bool ovms_partition_table_downgrade_store(OvmsWriter* writer)
430444 OVMS_MD5_Init (&md5_ctx);
431445 for (; p->magic_id == PARTITION_ENTRY_MAGIC ; p++)
432446 {
433- if (p->magic_id == PARTITION_ENTRY_MAGIC &&
434- p->data .entry .type == ESP_PARTITION_TYPE_DATA &&
447+ if (p->data .entry .type == ESP_PARTITION_TYPE_DATA &&
435448 p->data .entry .subtype == ESP_PARTITION_SUBTYPE_DATA_FAT &&
436449 p->data .entry .address == 0xe10000 &&
437450 p->data .entry .size == 0x1f0000 )
438451 {
439452 // We have found the store2 partition
440453 writer->puts (" Removing store2 partition from partition table" );
441454 memset ((void *)p, 0 , sizeof (ovms_esp_partition_t ));
455+ // safe to assume this is our last partition, so we can assign this slot to the terminating MD5 checksum:
442456 p->magic_id = PARTITION_MD5_MAGIC ;
443457 OVMS_MD5_Final (p->data .md5 .digest , &md5_ctx);
444458 p++; ovms_partition_table_void_entry (p); // Clear the following redundant MD5 checksum record
445459 if (ovms_partition_table_rewrite (table, writer))
446460 {
447461 writer->puts (" Store partition downgraded successfully - reboot required" );
448462 partition_table_type = OVMS_FlashPartition_30;
463+ ovms_partition_table_free (table);
449464 return true ;
450465 }
451466 }
@@ -596,7 +611,7 @@ static bool copy_store_ensure_dir(const std::string& dst, OvmsWriter* writer, un
596611
597612// Copy a single file from the source to the destination
598613static void copy_store_one_file (OvmsWriter* writer, const std::string& src, const std::string& dst,
599- uint8_t * buf, size_t buf_size, unsigned & files_copied, unsigned & errors)
614+ off_t expected_size, uint8_t * buf, size_t buf_size, unsigned & files_copied, unsigned & errors)
600615 {
601616 struct stat st_src;
602617 if (stat (src.c_str (), &st_src) != 0 )
@@ -615,12 +630,19 @@ static void copy_store_one_file(OvmsWriter* writer, const std::string& src, cons
615630 struct stat st_dst;
616631 if (stat (dst.c_str (), &st_dst) == 0 )
617632 {
618- if (S_ISREG (st_dst.st_mode )) return ;
619- writer->printf (" Error: destination exists but is not a file: %s\n " , dst.c_str ());
620- errors++;
621- return ;
633+ if (!S_ISREG (st_dst.st_mode ))
634+ {
635+ writer->printf (" Error: destination exists but is not a file: %s\n " , dst.c_str ());
636+ errors++;
637+ return ;
638+ }
639+ else if (st_dst.st_size == expected_size)
640+ {
641+ // skip, file already copied (Note: won't detect same size changes)
642+ return ;
643+ }
622644 }
623- if (errno != ENOENT )
645+ else if (errno != ENOENT )
624646 {
625647 writer->printf (" Error: stat %s: %s\n " , dst.c_str (), strerror (errno));
626648 errors++;
@@ -647,6 +669,7 @@ static void copy_store_one_file(OvmsWriter* writer, const std::string& src, cons
647669 writer->printf (" Copy file: %s -> %s\n " , src.c_str (), dst.c_str ());
648670
649671 bool io_ok = true ;
672+ off_t copied_size = 0 ;
650673 for (;;)
651674 {
652675 ssize_t nr = read (fd_in, buf, buf_size);
@@ -676,6 +699,7 @@ static void copy_store_one_file(OvmsWriter* writer, const std::string& src, cons
676699 off += (size_t )nw;
677700 }
678701 if (!io_ok) break ;
702+ copied_size += nr;
679703 }
680704
681705 if (close (fd_in) != 0 )
@@ -696,6 +720,13 @@ static void copy_store_one_file(OvmsWriter* writer, const std::string& src, cons
696720 io_ok = false ;
697721 }
698722
723+ if (io_ok && copied_size != expected_size)
724+ {
725+ writer->printf (" Error: size mismatch on %s: %ld bytes copied, %ld expected (/store corrupted)\n " ,
726+ src.c_str (), copied_size, expected_size);
727+ io_ok = false ;
728+ }
729+
699730 if (!io_ok)
700731 {
701732 if (unlink (dst.c_str ()) != 0 && errno != ENOENT )
@@ -837,7 +868,7 @@ bool ovms_partition_table_copy_store(OvmsWriter* writer)
837868 }
838869 else if (S_ISREG (st_ent.st_mode ))
839870 {
840- copy_store_one_file (writer, child_src, child_dst, buf, kBufSize , files_copied, errors);
871+ copy_store_one_file (writer, child_src, child_dst, st_ent. st_size , buf, kBufSize , files_copied, errors);
841872 }
842873 else
843874 {
@@ -854,6 +885,7 @@ bool ovms_partition_table_copy_store(OvmsWriter* writer)
854885 }
855886
856887 free (buf);
888+
857889 writer->printf (" Copy finished: %u files copied, %u errors\n " , files_copied, errors);
858890 return (errors == 0 );
859891 }
@@ -923,78 +955,75 @@ bool ovms_partition_table_upgrade_factory(OvmsWriter* writer)
923955 OVMS_MD5_Init (&md5_ctx);
924956 for (; p->magic_id == PARTITION_ENTRY_MAGIC ; p++)
925957 {
926- if (p->magic_id == PARTITION_ENTRY_MAGIC )
958+ if (p->data . entry . type == ESP_PARTITION_TYPE_APP && p-> data . entry . subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY )
927959 {
928- if (p->data .entry .type == ESP_PARTITION_TYPE_APP && p->data .entry .subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY )
929- {
930- // We have found the factory partition, so we need to change it to OTA 0
931- factory_offset = p->data .entry .address ;
932- p->data .entry .subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0 ;
933- p->data .entry .size = 0x700000 ;
934- memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
935- strncpy (p->data .entry .label , " ota_0" , sizeof (p->data .entry .label ));
936- OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
937- writer->printf (" 0x%08" PRIx32 " Converted factory partition to 6MB OTA 0\n " , factory_offset);
938- }
939- else if (p->data .entry .type == ESP_PARTITION_TYPE_APP && p->data .entry .subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0 )
940- {
941- // We have found the OTA 0 partition, so we need to change it to OTA 1
942- ota1_offset = factory_offset + 0x700000 ;
943- p->data .entry .subtype = ESP_PARTITION_SUBTYPE_APP_OTA_1 ;
944- p->data .entry .address = ota1_offset;
945- p->data .entry .size = 0x700000 ;
946- memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
947- strncpy (p->data .entry .label , " ota_1" , sizeof (p->data .entry .label ));
948- OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
949- writer->printf (" 0x%08" PRIx32 " Converted OTA 0 partition to 6MB OTA 1\n " , ota1_offset);
950- }
951- else if (p->data .entry .type == ESP_PARTITION_TYPE_APP && p->data .entry .subtype == ESP_PARTITION_SUBTYPE_APP_OTA_1 )
960+ // We have found the factory partition, so we need to change it to OTA 0
961+ factory_offset = p->data .entry .address ;
962+ p->data .entry .subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0 ;
963+ p->data .entry .size = 0x700000 ;
964+ memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
965+ strncpy (p->data .entry .label , " ota_0" , sizeof (p->data .entry .label ));
966+ OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
967+ writer->printf (" 0x%08" PRIx32 " Converted factory partition to 6MB OTA 0\n " , factory_offset);
968+ }
969+ else if (p->data .entry .type == ESP_PARTITION_TYPE_APP && p->data .entry .subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0 )
970+ {
971+ // We have found the OTA 0 partition, so we need to change it to OTA 1
972+ ota1_offset = factory_offset + 0x700000 ; // safe to assume we found the factory_offset here
973+ p->data .entry .subtype = ESP_PARTITION_SUBTYPE_APP_OTA_1 ;
974+ p->data .entry .address = ota1_offset;
975+ p->data .entry .size = 0x700000 ;
976+ memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
977+ strncpy (p->data .entry .label , " ota_1" , sizeof (p->data .entry .label ));
978+ OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
979+ writer->printf (" 0x%08" PRIx32 " Converted OTA 0 partition to 6MB OTA 1\n " , ota1_offset);
980+ }
981+ else if (p->data .entry .type == ESP_PARTITION_TYPE_APP && p->data .entry .subtype == ESP_PARTITION_SUBTYPE_APP_OTA_1 )
982+ {
983+ // We have found the old OTA 1 partition, so now have
984+ // p[0] -> OTA_1
985+ // p[1] -> old store
986+ // p[2] -> new store
987+ // p[3] -> MD5 checksum
988+ // We need to set this as the new store, the one after as the checksum, and then clear the two following that
989+ memcpy ((void *)p, (void *)&p[2 ], sizeof (ovms_esp_partition_t ));
990+ memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
991+ strncpy (p->data .entry .label , " store" , sizeof (p->data .entry .label ));
992+ OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
993+ writer->printf (" 0x%08" PRIx32 " Moved %s/%s partition up two positions\n " ,
994+ p->data .entry .address ,
995+ ovms_partition_type_name ((esp_partition_type_t )p->data .entry .type ),
996+ ovms_partition_subtype_name ((esp_partition_type_t )p->data .entry .type , (esp_partition_subtype_t )p->data .entry .subtype ));
997+ p++; // now @ old store, make this the new MD5 checksum slot:
998+ ovms_partition_table_void_entry (p);
999+ p->magic_id = PARTITION_MD5_MAGIC ;
1000+ OVMS_MD5_Final (p->data .md5 .digest , &md5_ctx);
1001+ writer->puts (" Recalculated MD5 checksum" );
1002+ ovms_partition_table_void_entry (&p[1 ]); // void previous new store
1003+ ovms_partition_table_void_entry (&p[2 ]); // void previous MD5 checksum
1004+ if (ovms_partition_table_rewrite (table, writer))
9521005 {
953- // We have found the old OTA 1 partition, so now have
954- // p[0] -> OTA_1
955- // p[1] -> old store
956- // p[2] -> new store
957- // p[3] -> MD5 checksum
958- // We need to set this as the new store, the one after as the checksum, and then clear the two following that
959- memcpy ((void *)p, (void *)&p[2 ], sizeof (ovms_esp_partition_t ));
960- memset ((void *)p->data .entry .label , 0 , sizeof (p->data .entry .label ));
961- strncpy (p->data .entry .label , " store" , sizeof (p->data .entry .label ));
962- OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
963- writer->printf (" 0x%08" PRIx32 " Moved %s/%s partition up two positions\n " ,
964- p->data .entry .address ,
965- ovms_partition_type_name ((esp_partition_type_t )p->data .entry .type ),
966- ovms_partition_subtype_name ((esp_partition_type_t )p->data .entry .type , (esp_partition_subtype_t )p->data .entry .subtype ));
967- p++;
968- ovms_partition_table_void_entry (p);
969- p->magic_id = PARTITION_MD5_MAGIC ;
970- OVMS_MD5_Final (p->data .md5 .digest , &md5_ctx);
971- writer->puts (" Recalculated MD5 checksum" );
972- ovms_partition_table_void_entry (&p[1 ]);
973- ovms_partition_table_void_entry (&p[2 ]);
974- if (ovms_partition_table_rewrite (table, writer))
975- {
976- writer->puts (" Partition table upgraded successfully - reboot required" );
977- partition_table_type = OVMS_FlashPartition_35;
978- ovms_partition_table_free (table);
979- return true ;
980- }
981- else
982- {
983- ovms_partition_table_free (table);
984- writer->puts (" Error: Failed to upgrade partition table" );
985- return false ;
986- }
1006+ writer->puts (" Partition table upgraded successfully - reboot required" );
1007+ partition_table_type = OVMS_FlashPartition_35;
1008+ ovms_partition_table_free (table);
1009+ return true ;
9871010 }
9881011 else
9891012 {
990- // Just update the MD5 checksum
991- OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
992- writer->printf (" 0x%08" PRIx32 " Skipping over %s/%s partition\n " ,
993- p->data .entry .address ,
994- ovms_partition_type_name ((esp_partition_type_t )p->data .entry .type ),
995- ovms_partition_subtype_name ((esp_partition_type_t )p->data .entry .type , (esp_partition_subtype_t )p->data .entry .subtype ));
1013+ ovms_partition_table_free (table);
1014+ writer->puts (" Error: Failed to upgrade partition table" );
1015+ return false ;
9961016 }
9971017 }
1018+ else
1019+ {
1020+ // Just update the MD5 checksum
1021+ OVMS_MD5_Update (&md5_ctx, (const uint8_t *)p, sizeof (ovms_esp_partition_t ));
1022+ writer->printf (" 0x%08" PRIx32 " Skipping over %s/%s partition\n " ,
1023+ p->data .entry .address ,
1024+ ovms_partition_type_name ((esp_partition_type_t )p->data .entry .type ),
1025+ ovms_partition_subtype_name ((esp_partition_type_t )p->data .entry .type , (esp_partition_subtype_t )p->data .entry .subtype ));
1026+ }
9981027 }
9991028
10001029 ovms_partition_table_free (table);
@@ -1033,4 +1062,4 @@ bool ovms_partition_table_rewrite(ovms_esp_partition_t* table, OvmsWriter* write
10331062void ovms_partition_table_void_entry (ovms_esp_partition_t * entry)
10341063 {
10351064 memset ((void *)entry, 0xff , sizeof (ovms_esp_partition_t ));
1036- }
1065+ }
0 commit comments