Skip to content

Commit

Permalink
Merge branch 'feature/bootloader_skip_validate_in_deep_sleep_for_c2' …
Browse files Browse the repository at this point in the history
…into 'master'

feat(bootloader): BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP for C2 (without RTC_MEM)

Closes IDF-9129

See merge request espressif/esp-idf!31241
  • Loading branch information
KonstantinKondrashov committed Jun 25, 2024
2 parents fce3df1 + ee605e3 commit e7070e7
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 16 deletions.
4 changes: 2 additions & 2 deletions components/bootloader/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,9 @@ menu "Bootloader config"
# options, allowing to turn on "allow insecure options" and have secure boot with
# "skip validation when existing deep sleep". Keeping this to avoid a breaking change,
# but - as noted in help - it invalidates the integrity of Secure Boot checks
depends on SOC_RTC_FAST_MEM_SUPPORTED && ((SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT)
depends on ((SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT)
default n
select BOOTLOADER_RESERVE_RTC_MEM
select BOOTLOADER_RESERVE_RTC_MEM if SOC_RTC_FAST_MEM_SUPPORTED
help
This option disables the normal validation of an image coming out of
deep sleep (checksums, SHA256, and signature). This is a trade-off
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ __attribute__((__noreturn__)) void bootloader_utility_load_boot_image(const boot
/**
* @brief Load that application which was worked before we go to the deep sleep.
*
* If chip supports the RTC memory:
* 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.
*
* If chip does not support the RTC memory:
* Checks the reboot reason if it is the deep sleep then the partition table is read
* to select and load an application which was worked before we go to the deep sleep.
*
*/
void bootloader_utility_load_boot_image_from_deep_sleep(void);
#endif
Expand Down
26 changes: 22 additions & 4 deletions components/bootloader_support/src/bootloader_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,15 +461,33 @@ static void set_actual_ota_seq(const bootloader_state_t *bs, int index)
void bootloader_utility_load_boot_image_from_deep_sleep(void)
{
if (esp_rom_get_reset_reason(0) == RESET_REASON_CORE_DEEP_SLEEP) {
#if SOC_RTC_FAST_MEM_SUPPORTED
esp_partition_pos_t *partition = bootloader_common_get_rtc_retain_mem_partition();
if (partition != NULL) {
esp_image_metadata_t image_data;
if (partition != NULL && bootloader_load_image_no_verify(partition, &image_data) == ESP_OK) {
ESP_LOGI(TAG, "Fast booting app from partition at offset 0x%"PRIx32, partition->offset);
bootloader_common_update_rtc_retain_mem(NULL, true);
load_image(&image_data);
}
#else // !SOC_RTC_FAST_MEM_SUPPORTED
bootloader_state_t bs = {0};
if (bootloader_utility_load_partition_table(&bs)) {
int index_of_last_loaded_app = FACTORY_INDEX;
esp_ota_select_entry_t otadata[2];
if (bs.ota_info.size && bootloader_common_read_otadata(&bs.ota_info, otadata) == ESP_OK) {
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1) {
index_of_last_loaded_app = (otadata[active_otadata].ota_seq - 1) % bs.app_count;
}
}
esp_partition_pos_t partition = index_to_partition(&bs, index_of_last_loaded_app);
esp_image_metadata_t image_data;
if (bootloader_load_image_no_verify(partition, &image_data) == ESP_OK) {
ESP_LOGI(TAG, "Fast booting app from partition at offset 0x%"PRIx32, partition->offset);
bootloader_common_update_rtc_retain_mem(NULL, true);
if (partition.size && bootloader_load_image_no_verify(&partition, &image_data) == ESP_OK) {
ESP_LOGI(TAG, "Fast booting app from partition at offset 0x%"PRIx32, partition.offset);
load_image(&image_data);
}
}
#endif // !SOC_RTC_FAST_MEM_SUPPORTED
ESP_LOGE(TAG, "Fast booting is not successful");
ESP_LOGI(TAG, "Try to load an app as usual with all validations");
}
Expand Down
12 changes: 9 additions & 3 deletions docs/en/api-guides/bootloader.rst
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,18 @@ Options to work around this are:

When Secure Boot V2 is enabled, there is also an absolute binary size limit of {IDF_TARGET_MAX_BOOTLOADER_SIZE} (excluding the 4 KB signature), because the bootloader is first loaded into a fixed size buffer for verification.

Fast Boot from Deep-Sleep
-------------------------

The bootloader has the :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` option which allows the wake-up time from Deep-sleep to be reduced (useful for reducing power consumption). This option is available when the :ref:`CONFIG_SECURE_BOOT` option is disabled or :ref:`CONFIG_SECURE_BOOT_INSECURE` is enabled along with Secure Boot. The reduction in time is achieved by ignoring image verification.

.. only:: SOC_RTC_FAST_MEM_SUPPORTED

Fast Boot from Deep-Sleep
-------------------------
During the first boot, the bootloader stores the address of the application being launched in the RTC FAST memory. After waking up from deep sleep, this address is used to boot the application again without any checks, resulting in a significantly faster load.

.. only:: not SOC_RTC_FAST_MEM_SUPPORTED

The bootloader has the :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` option which allows the wake-up time from Deep-sleep to be reduced (useful for reducing power consumption). This option is available when :ref:`CONFIG_SECURE_BOOT` option is disabled. Reduction of time is achieved due to the lack of image verification. During the first boot, the bootloader stores the address of the application being launched in the RTC FAST memory. And during the awakening, this address is used for booting without any checks, thus fast loading is achieved.
The {IDF_TARGET_NAME} does not have RTC memory, so a running partition cannot be saved there; instead, the entire partition table is read to select the correct application. During wake-up, the selected application is loaded without any checks, resulting in a significantly faster load.

Custom Bootloader
-----------------
Expand Down
2 changes: 1 addition & 1 deletion examples/system/deep_sleep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Note: Some wake up sources can be disabled via configuration (see section on [pr

Warning: On ESP32, touch wake up source cannot be used together with EXT0 wake up source. If they co-exist, IDF will give a runtime error and the program will crash. By default in this example, touch wake up is enabled, and the other two are disabled. You can switch to enable the other wake up sources via menuconfig.

In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in RTC memory the address of a running partition and uses it when it wakes up (ESP32-C2 does not have RTC memory, so a running partition cannot be saved there, instead the partition table is read to select an application). This example allows you to skip all image checks and speed up the boot.

## How to use example

Expand Down
7 changes: 7 additions & 0 deletions examples/system/deep_sleep/partitions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x4000,
otadata, data, ota, , 0x2000,
factory, app, factory, , 600K,
ota_0, app, ota_0, , 600K,
ota_1, app, ota_1, , 600K,
8 changes: 2 additions & 6 deletions examples/system/deep_sleep/pytest_deep_sleep.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import logging
import time
Expand Down Expand Up @@ -67,11 +67,7 @@ def expect_enable_deep_sleep_no_touch() -> None:
logging.info('Host measured sleep time at {:.2f}s'.format(sleep_time))
assert 18 < sleep_time < 22 # note: high tolerance as measuring time on the host may have some timing skew

# This line indicates that the CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP option set in sdkconfig.defaults
# has correctly allowed skipping verification on wakeup
# Note: this feature depends on rtc mem
if dut.app.sdkconfig.get('SOC_RTC_MEM_SUPPORTED') is True:
dut.expect_exact('boot: Fast booting app from partition', timeout=2)
dut.expect_exact('boot: Fast booting app from partition', timeout=2)

# Check that it measured 2xxxxms in deep sleep, i.e at least 20 seconds:
expect_enable_deep_sleep()
Expand Down
1 change: 1 addition & 0 deletions examples/system/deep_sleep/sdkconfig.ci.basic
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_PARTITION_TABLE_CUSTOM=y
1 change: 1 addition & 0 deletions examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_PARTITION_TABLE_CUSTOM=y
1 change: 1 addition & 0 deletions examples/system/deep_sleep/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
CONFIG_PARTITION_TABLE_CUSTOM=y

0 comments on commit e7070e7

Please sign in to comment.