Added "Reserve RTC FAST memory for custom purposes" option.
Added a boot counter.
config BOOTLOADER_RESERVE_RTC_SIZE
hex
- default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+ default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
default 0
help
Reserve RTC FAST memory for Skip image validation. This option in bytes.
When a wakeup occurs (from Deep sleep), the bootloader retrieves it and
loads the application without validation.
+ config BOOTLOADER_CUSTOM_RESERVE_RTC
+ bool "Reserve RTC FAST memory for custom purposes"
+ default n
+ help
+ This option allows the customer to place data in the RTC FAST memory,
+ this area remains valid when rebooted, except for power loss.
+ This memory is located at a fixed address and is available
+ for both the bootloader and the application.
+ (The application and bootoloader must be compiled with the same option).
+ The RTC FAST memory has access only through PRO_CPU.
+
+ config BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE
+ hex "Size in bytes for custom purposes"
+ range 0 0x10
+ default 0
+ depends on BOOTLOADER_CUSTOM_RESERVE_RTC
+ help
+ This option reserves in RTC FAST memory the area for custom purposes.
+ If you want to create your own bootloader and save more information
+ in this area of memory, you can increase it. It must be a multiple of 4 bytes.
+ This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
+
endmenu # Bootloader
bootloader_reset();
}
+#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+ // If this boot is a wake up from the deep sleep then go to the short way,
+ // try to load the application which worked before deep sleep.
+ // It skips a lot of checks due to it was done before (while first boot).
+ bootloader_utility_load_boot_image_from_deep_sleep();
+ // If it is not successful try to load an application as usual.
+#endif
+
// 2. Select the number of boot partition
bootloader_state_t bs = { 0 };
int boot_index = select_partition_number(&bs);
*/
void bootloader_common_vddsdio_configure(void);
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
+/**
+ * @brief Returns partition from rtc_retain_mem
+ *
+ * Uses to get the partition of application which was worked before to go to the deep sleep.
+ * This partition was stored in rtc_retain_mem.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ * Make sure that this function is used only PRO_CPU.
+ *
+ * @return partition: If rtc_retain_mem is valid.
+ * - NULL: If it is not valid.
+ */
+esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void);
+
+/**
+ * @brief Update the partition and reboot_counter in rtc_retain_mem.
+ *
+ * This function saves the partition of application for fast booting from the deep sleep.
+ * An algorithm uses this partition to avoid reading the otadata and does not validate an image.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ * Make sure that this function is used only PRO_CPU.
+ *
+ * @param[in] partition App partition description. Can be NULL, in this case rtc_retain_mem.partition is not updated.
+ * @param[in] reboot_counter If true then update reboot_counter.
+ *
+ */
+void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter);
+
+/**
+ * @brief Reset entire rtc_retain_mem.
+ *
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ * Make sure that this function is used only PRO_CPU.
+ */
+void bootloader_common_reset_rtc_retain_mem(void);
+
+/**
+ * @brief Returns reboot_counter from rtc_retain_mem
+ *
+ * The reboot_counter counts the number of reboots. Reset only when power is off.
+ * The very first launch of the application will be from 1.
+ * Overflow is not possible, it will stop at the value UINT16_MAX.
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ * Make sure that this function is used only PRO_CPU.
+ *
+ * @return reboot_counter: 1..65535
+ * - 0: If rtc_retain_mem is not valid.
+ */
+uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void);
+
+/**
+ * @brief Returns rtc_retain_mem
+ *
+ * Note: This function operates the RTC FAST memory which available only for PRO_CPU.
+ * Make sure that this function is used only PRO_CPU.
+ *
+ * @return rtc_retain_mem
+ */
+rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void);
+
+#endif
+
#ifdef __cplusplus
}
#endif
#endif
} esp_image_load_mode_t;
+typedef struct {
+ esp_partition_pos_t partition; /*!< Partition of application which worked before goes to the deep sleep. */
+ uint16_t reboot_counter; /*!< Reboot counter. Reset only when power is off. */
+ uint16_t reserve; /*!< Reserve */
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+ uint8_t custom[CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE]; /*!< Reserve for custom propose */
+#endif
+ uint32_t crc; /*!< Check sum crc32 */
+} rtc_retain_mem_t;
+
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+_Static_assert(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
+#endif
+
+#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
+_Static_assert(CONFIG_BOOTLOADER_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
+#endif
+
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
+#endif
+
+#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
+_Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved RTC area must exceed size of rtc_retain_mem_t");
+#endif
+
/**
* @brief Verify and (optionally, in bootloader mode) load an app image.
*
*/
__attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index);
+#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
+/**
+ * @brief Load that application which was worked before we go to the deep sleep.
+ *
+ * Checks the reboot reason if it is the deep sleep and has a valid partition in the RTC memory
+ * then try to load the application which was worked before we go to the deep sleep.
+ *
+ */
+void bootloader_utility_load_boot_image_from_deep_sleep(void);
+#endif
/**
* @brief Software reset the ESP32
}
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
}
+
+
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
+
+rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
+
+static bool check_rtc_retain_mem(void)
+{
+ return crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc)) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
+}
+
+static void update_rtc_retain_mem_crc(void)
+{
+ rtc_retain_mem->crc = crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc));
+}
+
+void bootloader_common_reset_rtc_retain_mem(void)
+{
+ memset(rtc_retain_mem, 0, sizeof(rtc_retain_mem_t));
+}
+
+uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void)
+{
+ if (check_rtc_retain_mem()) {
+ return rtc_retain_mem->reboot_counter;
+ }
+ return 0;
+}
+
+esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void)
+{
+ if (check_rtc_retain_mem()) {
+ return &rtc_retain_mem->partition;
+ }
+ return NULL;
+}
+
+void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter)
+{
+ if (reboot_counter) {
+ if (!check_rtc_retain_mem()) {
+ bootloader_common_reset_rtc_retain_mem();
+ }
+ if (++rtc_retain_mem->reboot_counter == 0) {
+ // do not allow to overflow. Stop it.
+ --rtc_retain_mem->reboot_counter;
+ }
+
+ }
+
+ if (partition != NULL) {
+ rtc_retain_mem->partition.offset = partition->offset;
+ rtc_retain_mem->partition.size = partition->size;
+ }
+
+ update_rtc_retain_mem_crc();
+}
+
+rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
+{
+ return rtc_retain_mem;
+}
+#endif
\ No newline at end of file
update_anti_rollback(&bs->ota[index]);
#endif
}
-#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP )
+#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
esp_partition_pos_t partition = index_to_partition(bs, index);
bootloader_common_update_rtc_retain_mem(&partition, true);
#endif
#define CONFIG_BT_RESERVE_DRAM 0
#endif
-#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
#else
#define ESP_BOOTLOADER_RESERVE_RTC 0