feat(stm32mp1): retry 3 times FWU trial boot
If we reboot 3 times in trial mode, BL2 will select previous boot image.
Signed-off-by: Nicolas Toromanoff <nicolas.toromanoff@foss.st.com>
Change-Id: I82b423cc84f0471fdb6fa7c393fc5fe411d25c06
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index e129dfd..5cc3390 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -485,22 +485,46 @@
#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
/*
- * Eventually, this function will return the
- * boot index to be passed on to the Update
- * Agent after performing certain checks like
- * a watchdog timeout, or Auth failure while
- * trying to load from a certain bank.
- * For now, since we do not have that logic
- * implemented, just pass the active_index
- * read from the metadata.
+ * In each boot in non-trial mode, we set the BKP register to
+ * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
+ *
+ * As long as the update agent didn't update the "accepted" field in metadata
+ * (i.e. we are in trial mode), we select the new active_index.
+ * To avoid infinite boot loop at trial boot we decrement a BKP register.
+ * If this counter is 0:
+ * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
+ * - a power-off occurs before the update agent was able to update the
+ * "accepted' field
+ * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
+ * we select the previous_active_index.
*/
+#define INVALID_BOOT_IDX 0xFFFFFFFF
+
uint32_t plat_fwu_get_boot_idx(void)
{
- const struct fwu_metadata *metadata;
+ /*
+ * Select boot index and update boot counter only once per boot
+ * even if this function is called several times.
+ */
+ static uint32_t boot_idx = INVALID_BOOT_IDX;
+ const struct fwu_metadata *data;
- metadata = fwu_get_metadata();
+ data = fwu_get_metadata();
- return metadata->active_index;
+ if (boot_idx == INVALID_BOOT_IDX) {
+ boot_idx = data->active_index;
+ if (fwu_is_trial_run_state()) {
+ if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
+ WARN("Trial FWU fails %u times\n",
+ FWU_MAX_TRIAL_REBOOT);
+ boot_idx = data->previous_active_index;
+ }
+ } else {
+ stm32_set_max_fwu_trial_boot_cnt();
+ }
+ }
+
+ return boot_idx;
}
static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index d8d1c13..0010cd8 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -129,6 +129,8 @@
#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT
void stm32mp1_fwu_set_boot_idx(void);
+uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void);
+void stm32_set_max_fwu_trial_boot_cnt(void);
#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */
#endif /* STM32MP_COMMON_H */