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

This commit is contained in:
Konstantin Kondrashov 2024-06-14 15:39:42 +03:00 committed by BOT
parent e9a2f3b098
commit ee605e35b4
10 changed files with 51 additions and 16 deletions

View File

@ -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

View File

@ -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

View File

@ -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");
}

View File

@ -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.
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.
.. only:: not SOC_RTC_FAST_MEM_SUPPORTED
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
-----------------

View File

@ -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

View File

@ -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,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, , 0x4000,
4 otadata, data, ota, , 0x2000,
5 factory, app, factory, , 600K,
6 ota_0, app, ota_0, , 600K,
7 ota_1, app, ota_1, , 600K,

View File

@ -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
@ -67,11 +67,7 @@ def test_deep_sleep(dut: Dut) -> 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()

View File

@ -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

View File

@ -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

View File

@ -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