diff --git a/sys/include/riotboot/flashwrite.h b/sys/include/riotboot/flashwrite.h index b211994c9510..fe13d41349b3 100644 --- a/sys/include/riotboot/flashwrite.h +++ b/sys/include/riotboot/flashwrite.h @@ -224,6 +224,32 @@ static inline int riotboot_flashwrite_finish(riotboot_flashwrite_t *state) RIOTBOOT_FLASHWRITE_SKIPLEN); } +/** + * @brief Invalidate a slot header (riotboot version) + * + * This function invalidates the target slot. + * + * @note If this function is called with only one valid slot, + * the invalidation will fail in order to keep one valid + * image to run after reboot + * + * @param[in] slot Target slot to invalidate + * + * @returns 0 on success, <0 otherwise + */ +int riotboot_flashwrite_invalidate(int slot); + +/** + * @brief Invalidate the latest firmware version (riotboot version) + * + * This function invalidates the slot having the most recent firmware revision + * + * @note This function requires two valid images to succeed + * + * @returns 0 on success, <0 otherwise + */ +int riotboot_flashwrite_invalidate_latest(void); + /** * @brief Get a slot's size * diff --git a/sys/riotboot/flashwrite.c b/sys/riotboot/flashwrite.c index fcd6833c03f7..a9d102dbdad6 100644 --- a/sys/riotboot/flashwrite.c +++ b/sys/riotboot/flashwrite.c @@ -24,11 +24,17 @@ #include #include "riotboot/flashwrite.h" +#include "riotboot/slot.h" #include "od.h" #define LOG_PREFIX "riotboot_flashwrite: " #include "log.h" +/** + * @brief Magic number used to invalidate a slot + */ +#define INVALIDATE_HDR 0xAA + static inline size_t min(size_t a, size_t b) { return a <= b ? a : b; @@ -150,6 +156,34 @@ int riotboot_flashwrite_putbytes(riotboot_flashwrite_t *state, return 0; } +int riotboot_flashwrite_invalidate(int slot) +{ + if (riotboot_slot_numof == 1) { + LOG_WARNING(LOG_PREFIX "abort, only one slot configured\n"); + return -1; + } + if (riotboot_slot_validate(1 - slot) != 0) { + LOG_WARNING(LOG_PREFIX "abort, can not erase slot[%d], other slot[%d] is invalid\n",slot, 1 - slot); + return -2; + } + + uint8_t data_flash[4]; + memset(data_flash, INVALIDATE_HDR, sizeof(data_flash)); + + flashpage_write((void *)riotboot_slot_get_hdr(slot), data_flash, sizeof(data_flash)); + + return 0; +} + +int riotboot_flashwrite_invalidate_latest(void) +{ + int _slot_to_revert; + _slot_to_revert = (riotboot_slot_get_hdr(riotboot_slot_other())->version + > riotboot_slot_get_hdr(riotboot_slot_current())->version) + ? riotboot_slot_other() : riotboot_slot_current(); + return riotboot_flashwrite_invalidate(_slot_to_revert); +} + int riotboot_flashwrite_finish_raw(riotboot_flashwrite_t *state, const uint8_t *bytes, size_t len) {