@@ -753,39 +753,48 @@ static int RAMFUNCTION wolfBoot_swap_and_final_erase(int resume)
753753#endif /* !DISABLE_BACKUP && !CUSTOM_PARTITION_TRAILER */
754754
755755#if !defined(DISABLE_BACKUP ) && defined(CUSTOM_PARTITION_TRAILER )
756- /**
757- * @brief Final step of the swap with a custom trailer, power-fail safe.
758- *
759- * Resetting a custom trailer to NEW rewrites it, once per sector flag, so
760- * UPDATE leaves UPDATING first (FINAL_FLAGS only clears bits, written in
761- * place): a resumed swap would otherwise swap again the sectors already
762- * reset to NEW. BOOT is set before the UPDATE trailer is reset: once that
763- * reset starts, a cut can only leave an erased trailer, which reads as NEW.
764- *
765- * @param resume If 1, only completes a final step interrupted by a cut
766- * @param bootState State to set in BOOT (TESTING, or SUCCESS on rollback)
767- * @return 0 if the final step ran, -1 if there was nothing to resume
768- */
769- static int RAMFUNCTION wolfBoot_custom_trailer_final (int resume ,
770- uint8_t bootState )
756+ /* UPDATE states of a rollback: header versions are mixed during the swap, so
757+ * the direction is recorded when it starts. ROLLBACK, FINAL_FLAGS and
758+ * FINAL_ROLLBACK are reached from the previous state by programming only, so
759+ * they are written in place: a trailer rewrite could be cut half-way. */
760+ #ifndef WOLFBOOT_FLAGS_INVERT
761+ #define IMG_STATE_ROLLBACK 0x60
762+ #define IMG_STATE_FINAL_ROLLBACK 0x20
763+ #else
764+ #define IMG_STATE_ROLLBACK 0x9F
765+ #define IMG_STATE_FINAL_ROLLBACK 0xDF
766+ #endif
767+
768+ /* Resetting the sector flags rewrites the custom trailer, once per flag:
769+ * UPDATE leaves UPDATING first, or a resumed swap would swap again the
770+ * sectors already reset. BOOT is set before: a cut in the reset then leaves
771+ * at worst an erased trailer, which reads as NEW. */
772+ static int RAMFUNCTION wolfBoot_custom_trailer_final (int resume , int rollback )
771773{
772774 uint8_t updateState ;
773775 uint32_t sector ;
774776
775- if (resume && ((wolfBoot_get_partition_state (PART_UPDATE ,
776- & updateState ) != 0 ) || (updateState != IMG_STATE_FINAL_FLAGS )))
777- return -1 ;
777+ if (resume ) {
778+ if (wolfBoot_get_partition_state (PART_UPDATE , & updateState ) != 0 )
779+ return -1 ;
780+ if (updateState == IMG_STATE_FINAL_FLAGS )
781+ rollback = 0 ;
782+ else if (updateState == IMG_STATE_FINAL_ROLLBACK )
783+ rollback = 1 ;
784+ else
785+ return -1 ;
786+ }
778787
779788 hal_flash_unlock ();
780789#ifdef EXT_FLASH
781790 ext_flash_unlock ();
782791#endif
783- if (!resume )
784- wolfBoot_set_partition_state (PART_UPDATE , IMG_STATE_FINAL_FLAGS );
785- /* Mark boot partition as TESTING - this tells bootloader to fallback if update fails */
786- wolfBoot_set_partition_state ( PART_BOOT , bootState );
787- /* Reset the sector flags, so a fallback swaps every sector again, then
788- * consume the update partition */
792+ if (!resume ) {
793+ wolfBoot_set_partition_state (PART_UPDATE ,
794+ rollback ? IMG_STATE_FINAL_ROLLBACK : IMG_STATE_FINAL_FLAGS );
795+ }
796+ wolfBoot_set_partition_state ( PART_BOOT ,
797+ rollback ? IMG_STATE_SUCCESS : IMG_STATE_TESTING );
789798 for (sector = 0 ; (sector * WOLFBOOT_SECTOR_SIZE ) < WOLFBOOT_PARTITION_SIZE ;
790799 sector ++ )
791800 wolfBoot_set_update_sector_flag (sector , SECT_FLAG_NEW );
@@ -1302,6 +1311,13 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
13021311#endif
13031312
13041313 wolfBoot_get_update_sector_flag (0 , & flag );
1314+ #if !defined(DISABLE_BACKUP ) && defined(CUSTOM_PARTITION_TRAILER )
1315+ if (flag != SECT_FLAG_NEW ) {
1316+ uint8_t updateState ;
1317+ rollback_needed = (wolfBoot_get_partition_state (PART_UPDATE ,
1318+ & updateState ) == 0 ) && (updateState == IMG_STATE_ROLLBACK );
1319+ }
1320+ #endif
13051321 /* Check the first sector to detect interrupted update */
13061322 if (flag == SECT_FLAG_NEW ) {
13071323 if (((update_type & HDR_IMG_TYPE_PART_MASK ) != HDR_IMG_TYPE_APP ) ||
@@ -1425,6 +1441,10 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
14251441 #ifdef EXT_FLASH
14261442 ext_flash_unlock ();
14271443 #endif
1444+ #ifdef CUSTOM_PARTITION_TRAILER
1445+ if (rollback_needed )
1446+ wolfBoot_set_partition_state (PART_UPDATE , IMG_STATE_ROLLBACK );
1447+ #endif
14281448 /* Interruptible swap
14291449 * The status is saved in the sector flags of the update partition.
14301450 * If something goes wrong, the operation will be resumed upon reboot.
@@ -1575,9 +1595,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
15751595 }
15761596#endif
15771597#else
1578- /* A custom trailer is not erased with the partitions */
1579- (void )wolfBoot_custom_trailer_final (0 ,
1580- rollback_needed ? IMG_STATE_SUCCESS : IMG_STATE_TESTING );
1598+ (void )wolfBoot_custom_trailer_final (0 , rollback_needed );
15811599#endif
15821600
15831601#else /* DISABLE_BACKUP */
@@ -1880,9 +1898,8 @@ void RAMFUNCTION wolfBoot_start(void)
18801898 if ((resumedFinalErase != 0 ) ||
18811899 ((bootRet == 0 ) && (bootState == IMG_STATE_TESTING )))
18821900#elif !defined(DISABLE_BACKUP )
1883- /* resume the final step in case the power failed before it finished:
1884- * the new image boots in TESTING */
1885- if (wolfBoot_custom_trailer_final (1 , IMG_STATE_TESTING ) != 0 )
1901+ /* resume the final step in case the power failed before it finished */
1902+ if (wolfBoot_custom_trailer_final (1 , 0 ) != 0 )
18861903#endif
18871904 {
18881905 /* Check if the BOOT partition is still in TESTING,
0 commit comments