From 6cbbd90223774465f75cfe786abe309880a7a335 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Sat, 24 May 2025 14:27:59 -0300 Subject: [PATCH 1/7] espressif: bump supported IDF code to v5.1.6 Also fix build if hal_espressif is used as IDF code layer (hal) for Espressif Port Signed-off-by: Almir Okato --- boot/espressif/CMakeLists.txt | 3 ++- boot/espressif/hal/include/esp32c2/esp32c2.cmake | 1 + boot/espressif/hal/include/esp32c3/esp32c3.cmake | 1 + boot/espressif/hal/include/esp32c6/esp32c6.cmake | 2 ++ boot/espressif/hal/include/esp32h2/esp32h2.cmake | 2 ++ boot/espressif/hal/include/esp32s3/esp32s3.cmake | 1 + boot/espressif/hal/include/stubs.h | 0 boot/espressif/hal/include/zephyr_compat.h | 0 boot/espressif/port/esp32h2/bootloader.conf | 2 ++ 9 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 boot/espressif/hal/include/stubs.h create mode 100644 boot/espressif/hal/include/zephyr_compat.h diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt index 0fa2759eab..264cf8fdff 100644 --- a/boot/espressif/CMakeLists.txt +++ b/boot/espressif/CMakeLists.txt @@ -13,8 +13,9 @@ endif() add_definitions(-DMCUBOOT_TARGET=${MCUBOOT_TARGET}) add_definitions(-D__ESPRESSIF__=1) +add_definitions(-DCONFIG_MCUBOOT_ESPRESSIF=1) -set(EXPECTED_IDF_HAL_VERSION "5.1.4") +set(EXPECTED_IDF_HAL_VERSION "5.1.6") if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR diff --git a/boot/espressif/hal/include/esp32c2/esp32c2.cmake b/boot/espressif/hal/include/esp32c2/esp32c2.cmake index b859f9f9d6..8362cad092 100644 --- a/boot/espressif/hal/include/esp32c2/esp32c2.cmake +++ b/boot/espressif/hal/include/esp32c2/esp32c2.cmake @@ -17,6 +17,7 @@ endif() list(APPEND LINKER_SCRIPTS -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld ) set_source_files_properties( diff --git a/boot/espressif/hal/include/esp32c3/esp32c3.cmake b/boot/espressif/hal/include/esp32c3/esp32c3.cmake index 3d4525a3c9..d4aba781f9 100644 --- a/boot/espressif/hal/include/esp32c3/esp32c3.cmake +++ b/boot/espressif/hal/include/esp32c3/esp32c3.cmake @@ -17,4 +17,5 @@ endif() list(APPEND LINKER_SCRIPTS -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.eco3.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld ) diff --git a/boot/espressif/hal/include/esp32c6/esp32c6.cmake b/boot/espressif/hal/include/esp32c6/esp32c6.cmake index f1b0a49f9e..b7af0392c9 100644 --- a/boot/espressif/hal/include/esp32c6/esp32c6.cmake +++ b/boot/espressif/hal/include/esp32c6/esp32c6.cmake @@ -7,6 +7,7 @@ list(APPEND include_dirs ) list(APPEND hal_srcs + ${esp_hal_dir}/components/bootloader_support/src/${MCUBOOT_TARGET}/bootloader_ecdsa.c ${esp_hal_dir}/components/hal/cache_hal.c ${esp_hal_dir}/components/hal/lp_timer_hal.c ${esp_hal_dir}/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c @@ -22,6 +23,7 @@ endif() list(APPEND LINKER_SCRIPTS -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld ) set_source_files_properties( diff --git a/boot/espressif/hal/include/esp32h2/esp32h2.cmake b/boot/espressif/hal/include/esp32h2/esp32h2.cmake index 2507e65125..f61e8a8a5c 100644 --- a/boot/espressif/hal/include/esp32h2/esp32h2.cmake +++ b/boot/espressif/hal/include/esp32h2/esp32h2.cmake @@ -9,6 +9,7 @@ list(APPEND include_dirs list(APPEND hal_srcs ${esp_hal_dir}/components/hal/cache_hal.c ${esp_hal_dir}/components/hal/lp_timer_hal.c + ${esp_hal_dir}/components/efuse/${MCUBOOT_TARGET}/esp_efuse_table_v0.0_v1.1.c ${esp_hal_dir}/components/efuse/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c ${esp_hal_dir}/components/esp_rom/patches/esp_rom_regi2c_${MCUBOOT_TARGET}.c ${esp_hal_dir}/components/esp_hw_support/port/${MCUBOOT_TARGET}/pmu_param.c @@ -22,6 +23,7 @@ endif() list(APPEND LINKER_SCRIPTS -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld ) set_source_files_properties( diff --git a/boot/espressif/hal/include/esp32s3/esp32s3.cmake b/boot/espressif/hal/include/esp32s3/esp32s3.cmake index b894c07eb4..b29f937c64 100644 --- a/boot/espressif/hal/include/esp32s3/esp32s3.cmake +++ b/boot/espressif/hal/include/esp32s3/esp32s3.cmake @@ -17,6 +17,7 @@ endif() list(APPEND LINKER_SCRIPTS -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib.ld + -T${esp_hal_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.version.ld ) set_source_files_properties( diff --git a/boot/espressif/hal/include/stubs.h b/boot/espressif/hal/include/stubs.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boot/espressif/hal/include/zephyr_compat.h b/boot/espressif/hal/include/zephyr_compat.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/boot/espressif/port/esp32h2/bootloader.conf b/boot/espressif/port/esp32h2/bootloader.conf index 214937867f..0fd5670196 100644 --- a/boot/espressif/port/esp32h2/bootloader.conf +++ b/boot/espressif/port/esp32h2/bootloader.conf @@ -87,6 +87,8 @@ CONFIG_ESP_CONSOLE_UART_NUM=0 # CONFIG_SECURE_BOOT_ALLOW_JTAG=1 # CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=1 +# CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH=1 + # Options for enabling eFuse emulation in Flash (adjust # CONFIG_EFUSE_VIRTUAL_OFFSET accordingly in order # to not overlap with other flash regions) From 7b2a04d1e0d92e20f4b9aefd7c84c13f25c227f2 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 21 Aug 2025 16:51:06 -0300 Subject: [PATCH 2/7] espressif: reorganize iram_loader.text section to reduce its size Signed-off-by: Almir Okato --- boot/espressif/port/esp32/ld/bootloader.ld | 51 +++++++++++++++++++- boot/espressif/port/esp32c2/ld/bootloader.ld | 36 +++++++++++++- boot/espressif/port/esp32c3/ld/bootloader.ld | 35 +++++++++++++- boot/espressif/port/esp32c6/ld/bootloader.ld | 40 ++++++++++++++- boot/espressif/port/esp32h2/ld/bootloader.ld | 42 +++++++++++++++- boot/espressif/port/esp32s2/ld/bootloader.ld | 38 ++++++++++++++- boot/espressif/port/esp32s3/ld/bootloader.ld | 46 +++++++++++++++++- 7 files changed, 281 insertions(+), 7 deletions(-) diff --git a/boot/espressif/port/esp32/ld/bootloader.ld b/boot/espressif/port/esp32/ld/bootloader.ld index 5ceac18e02..ee23823117 100644 --- a/boot/espressif/port/esp32/ld/bootloader.ld +++ b/boot/espressif/port/esp32/ld/bootloader.ld @@ -33,10 +33,59 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies + */ + *libhal.a:app_cpu_start.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_clock_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_efuse.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_esp32.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_mem.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cpu.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_spiflash.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_sys.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_uart.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:gpio_periph.*(.literal .text .literal.* .text.*) + *libhal.a:log_noos.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_time.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32c2/ld/bootloader.ld b/boot/espressif/port/esp32c2/ld/bootloader.ld index b24fabbeba..c949d09c9e 100644 --- a/boot/espressif/port/esp32c2/ld/bootloader.ld +++ b/boot/espressif/port/esp32c2/ld/bootloader.ld @@ -62,10 +62,44 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32c2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32c2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32c3/ld/bootloader.ld b/boot/espressif/port/esp32c3/ld/bootloader.ld index 747b549141..285009bd30 100644 --- a/boot/espressif/port/esp32c3/ld/bootloader.ld +++ b/boot/espressif/port/esp32c3/ld/bootloader.ld @@ -28,10 +28,43 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies + */ + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32c3.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32c3.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32c6/ld/bootloader.ld b/boot/espressif/port/esp32c6/ld/bootloader.ld index 06b6e91b4c..3ec5ca0ee4 100644 --- a/boot/espressif/port/esp32c6/ld/bootloader.ld +++ b/boot/espressif/port/esp32c6/ld/bootloader.ld @@ -59,10 +59,48 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32c6.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32c6.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_hp_regi2c_esp32c6.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_uart.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:lp_timer_hal.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:pmu_param.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32h2/ld/bootloader.ld b/boot/espressif/port/esp32h2/ld/bootloader.ld index b4330bf325..39a6d6cbfe 100644 --- a/boot/espressif/port/esp32h2/ld/bootloader.ld +++ b/boot/espressif/port/esp32h2/ld/bootloader.ld @@ -60,10 +60,50 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32h2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32h2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table_v0.0_v1.1.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_regi2c_esp32h2.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_uart.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:lp_timer_hal.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:pmu_param.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32s2/ld/bootloader.ld b/boot/espressif/port/esp32s2/ld/bootloader.ld index b615b73c5d..202402bed3 100644 --- a/boot/espressif/port/esp32s2/ld/bootloader.ld +++ b/boot/espressif/port/esp32s2/ld/bootloader.ld @@ -28,10 +28,46 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32s2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32s2.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_regi2c_esp32s2.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/boot/espressif/port/esp32s3/ld/bootloader.ld b/boot/espressif/port/esp32s3/ld/bootloader.ld index 082081ef43..cd56ec9114 100644 --- a/boot/espressif/port/esp32s3/ld/bootloader.ld +++ b/boot/espressif/port/esp32s3/ld/bootloader.ld @@ -28,10 +28,54 @@ SECTIONS _loader_text_start = ABSOLUTE(.); *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *libhal.a:*.*(.literal .text .literal.* .text.*) *esp_mcuboot.*(.literal .text .literal.* .text.*) *esp_loader.*(.literal .text .literal.* .text.*) *main.*(.literal .text .literal.* .text.*) + + /* iram_loader section must not be overlapped by application IRAM/DRAM + * mapping, therefore the following were added based on the dependencies + * from esp_loader as its from where the application RAM parts will be + * loaded into memory and ultimately boot. The cross reference table + * were used to map the reachable dependencies */ + *libhal.a:app_cpu_start.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_banner.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_clock_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_esp32s3.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_flash_config_esp32s3.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_mem.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_random_esp32s3.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libhal.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.*(.literal .text .literal.* .text.*) + *libhal.a:cpu.*(.literal .text .literal.* .text.*) + *libhal.a:efuse_hal.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_api_key.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libhal.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libhal.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_sys.*(.literal .text .literal.* .text.*) + *libhal.a:esp_rom_uart.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libhal.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libhal.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_clk_init.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_init.*(.literal .text .literal.* .text.*) + *libhal.a:rtc_time.*(.literal .text .literal.* .text.*) + *libhal.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libgcc.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) *(.fini) *(.gnu.version) From 1985040e9d5d7b504f27b8b60b72b130e33a1f0c Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 21 Aug 2025 16:54:03 -0300 Subject: [PATCH 3/7] espressif: ci: add C2, C6 and H2 builds and adjust for hal v5.1.6 Signed-off-by: Almir Okato --- .github/workflows/espressif.yaml | 2 +- boot/espressif/ci_configs/esp32-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/esp32c2-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/esp32c3-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/esp32c6-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/esp32h2-secureboot.conf | 12 ++++++++++++ boot/espressif/ci_configs/esp32s2-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/esp32s3-secureboot.conf | 11 +++++++++++ boot/espressif/ci_configs/secureboot-sign-ec256.conf | 1 - .../ci_configs/secureboot-sign-ed25519.conf | 1 - .../ci_configs/secureboot-sign-rsa2048.conf | 1 - .../ci_configs/secureboot-sign-rsa3072.conf | 1 - ci/espressif_install.sh | 2 +- ci/espressif_run.sh | 8 ++++++++ 14 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 boot/espressif/ci_configs/esp32-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32c2-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32c3-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32c6-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32h2-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32s2-secureboot.conf create mode 100644 boot/espressif/ci_configs/esp32s3-secureboot.conf diff --git a/.github/workflows/espressif.yaml b/.github/workflows/espressif.yaml index a5c3a75c7e..2a7fa11cec 100644 --- a/.github/workflows/espressif.yaml +++ b/.github/workflows/espressif.yaml @@ -18,7 +18,7 @@ jobs: environment: strategy: matrix: - targets: [esp32, esp32s2, esp32s3, esp32c3] + targets: [esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2] features: - "secureboot-sign-rsa2048,secureboot-sign-rsa3072,secureboot-sign-ec256,secureboot-sign-ed25519" - "serialrecovery" diff --git a/boot/espressif/ci_configs/esp32-secureboot.conf b/boot/espressif/ci_configs/esp32-secureboot.conf new file mode 100644 index 0000000000..372fbddcaf --- /dev/null +++ b/boot/espressif/ci_configs/esp32-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32c2-secureboot.conf b/boot/espressif/ci_configs/esp32c2-secureboot.conf new file mode 100644 index 0000000000..f76306fb74 --- /dev/null +++ b/boot/espressif/ci_configs/esp32c2-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32c3-secureboot.conf b/boot/espressif/ci_configs/esp32c3-secureboot.conf new file mode 100644 index 0000000000..372fbddcaf --- /dev/null +++ b/boot/espressif/ci_configs/esp32c3-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32c6-secureboot.conf b/boot/espressif/ci_configs/esp32c6-secureboot.conf new file mode 100644 index 0000000000..372fbddcaf --- /dev/null +++ b/boot/espressif/ci_configs/esp32c6-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32h2-secureboot.conf b/boot/espressif/ci_configs/esp32h2-secureboot.conf new file mode 100644 index 0000000000..96c51aca4b --- /dev/null +++ b/boot/espressif/ci_configs/esp32h2-secureboot.conf @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH=1 +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32s2-secureboot.conf b/boot/espressif/ci_configs/esp32s2-secureboot.conf new file mode 100644 index 0000000000..372fbddcaf --- /dev/null +++ b/boot/espressif/ci_configs/esp32s2-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/esp32s3-secureboot.conf b/boot/espressif/ci_configs/esp32s3-secureboot.conf new file mode 100644 index 0000000000..372fbddcaf --- /dev/null +++ b/boot/espressif/ci_configs/esp32s3-secureboot.conf @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: Apache-2.0 + +# ATTENTION: +# This configuration file targets the building for CI environment and contains +# a set of definitions to resemble a bootloader image for RELEASE environment. +# Running the generated firmware image may result in irreversible operations +# to the chip! + +CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 diff --git a/boot/espressif/ci_configs/secureboot-sign-ec256.conf b/boot/espressif/ci_configs/secureboot-sign-ec256.conf index 17b032b234..7866a7f702 100644 --- a/boot/espressif/ci_configs/secureboot-sign-ec256.conf +++ b/boot/espressif/ci_configs/secureboot-sign-ec256.conf @@ -9,7 +9,6 @@ # to the chip! CONFIG_SECURE_SIGNED_ON_BOOT=1 -CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 CONFIG_SECURE_BOOT=1 CONFIG_SECURE_BOOT_V2_ENABLED=1 CONFIG_SECURE_BOOT_SUPPORTS_RSA=1 diff --git a/boot/espressif/ci_configs/secureboot-sign-ed25519.conf b/boot/espressif/ci_configs/secureboot-sign-ed25519.conf index 9cbdcd67ee..ed09570249 100644 --- a/boot/espressif/ci_configs/secureboot-sign-ed25519.conf +++ b/boot/espressif/ci_configs/secureboot-sign-ed25519.conf @@ -9,7 +9,6 @@ # to the chip! CONFIG_SECURE_SIGNED_ON_BOOT=1 -CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 CONFIG_SECURE_BOOT=1 CONFIG_SECURE_BOOT_V2_ENABLED=1 CONFIG_SECURE_BOOT_SUPPORTS_RSA=1 diff --git a/boot/espressif/ci_configs/secureboot-sign-rsa2048.conf b/boot/espressif/ci_configs/secureboot-sign-rsa2048.conf index 2b2215017a..5843778fb8 100644 --- a/boot/espressif/ci_configs/secureboot-sign-rsa2048.conf +++ b/boot/espressif/ci_configs/secureboot-sign-rsa2048.conf @@ -9,7 +9,6 @@ # to the chip! CONFIG_SECURE_SIGNED_ON_BOOT=1 -CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 CONFIG_SECURE_BOOT=1 CONFIG_SECURE_BOOT_V2_ENABLED=1 CONFIG_SECURE_BOOT_SUPPORTS_RSA=1 diff --git a/boot/espressif/ci_configs/secureboot-sign-rsa3072.conf b/boot/espressif/ci_configs/secureboot-sign-rsa3072.conf index 9f1378505f..f125a0b40c 100644 --- a/boot/espressif/ci_configs/secureboot-sign-rsa3072.conf +++ b/boot/espressif/ci_configs/secureboot-sign-rsa3072.conf @@ -9,7 +9,6 @@ # to the chip! CONFIG_SECURE_SIGNED_ON_BOOT=1 -CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME=1 CONFIG_SECURE_BOOT=1 CONFIG_SECURE_BOOT_V2_ENABLED=1 CONFIG_SECURE_BOOT_SUPPORTS_RSA=1 diff --git a/ci/espressif_install.sh b/ci/espressif_install.sh index 4ac52c9ab3..f3659cf410 100755 --- a/ci/espressif_install.sh +++ b/ci/espressif_install.sh @@ -10,7 +10,7 @@ install_imgtool() { install_idf() { pushd $HOME - git clone --depth=1 https://github.com/espressif/esp-idf.git --branch v5.1.4 + git clone --depth=1 https://github.com/espressif/esp-idf.git --branch v5.1.6 [[ $? -ne 0 ]] && exit 1 $HOME/esp-idf/install.sh diff --git a/ci/espressif_run.sh b/ci/espressif_run.sh index 74b77cbbc6..e697ccb173 100755 --- a/ci/espressif_run.sh +++ b/ci/espressif_run.sh @@ -32,6 +32,14 @@ build_mcuboot() { build_dir=".build-${target}-${feature}" fi + IFS='-' + read -a feat_prefix <<< "${feature}" + + # Add chip-specific conf if any + if [ -e "${ESPRESSIF_ROOT}/ci_configs/${target}-${feat_prefix}.conf" ]; then + mcuboot_config="${mcuboot_config};${ESPRESSIF_ROOT}/ci_configs/${target}-${feat_prefix}.conf" + fi + # Build MCUboot for selected target cd "${MCUBOOT_ROOTDIR}" &>/dev/null From acd01443cd36ed065a6673f4d0069ec7bfa4e972 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Sat, 24 May 2025 13:04:39 -0300 Subject: [PATCH 4/7] espressif: add forced aligned flash erase Signed-off-by: Almir Okato --- boot/espressif/port/esp_mcuboot.c | 94 +++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index 9bbd5a9f20..cae3a6edb4 100644 --- a/boot/espressif/port/esp_mcuboot.c +++ b/boot/espressif/port/esp_mcuboot.c @@ -277,6 +277,73 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) return true; } +static bool aligned_flash_erase(size_t addr, size_t size) +{ + if (IS_ALIGNED(addr, FLASH_SECTOR_SIZE) && IS_ALIGNED(size, FLASH_SECTOR_SIZE)) { + /* A single write operation is enough when all parameters are aligned */ + + return bootloader_flash_erase_range(addr, size) == ESP_OK; + } + + const uint32_t aligned_addr = ALIGN_DOWN(addr, FLASH_SECTOR_SIZE); + const uint32_t addr_offset = ALIGN_OFFSET(addr, FLASH_SECTOR_SIZE); + uint32_t bytes_remaining = size; + uint8_t write_data[FLASH_SECTOR_SIZE] = {0}; + + /* Perform a read operation considering an offset not aligned to 4-byte boundary */ + + uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data)); + + if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) { + return false; + } + + + if (bootloader_flash_erase_range(aligned_addr, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed", __func__); + return -1; + } + + uint32_t bytes_written = bytes - addr_offset; + + /* Write first part of non-erased data */ + if(addr_offset > 0) { + aligned_flash_write(aligned_addr, write_data, addr_offset); + } + + if(bytes < sizeof(write_data)) { + aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes); + } + + bytes_remaining -= bytes_written; + + /* Write remaining data to Flash if any */ + + uint32_t offset = bytes; + + while (bytes_remaining != 0) { + bytes = MIN(bytes_remaining, sizeof(write_data)); + if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) { + return false; + } + + if (bootloader_flash_erase_range(aligned_addr + offset, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed", __func__); + return -1; + } + + if(bytes < sizeof(write_data)) { + aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes); + } + + offset += bytes; + bytes_written += bytes; + bytes_remaining -= bytes; + } + + return true; +} + int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, uint32_t len) { @@ -293,8 +360,8 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, const uint32_t start_addr = fa->fa_off + off; BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - bool success = aligned_flash_write(start_addr, src, len); - if (!success) { + + if (!aligned_flash_write(start_addr, src, len)) { BOOT_LOG_ERR("%s: Flash write failed", __func__); return -1; } @@ -308,19 +375,24 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) return -1; } + const uint32_t start_addr = fa->fa_off + off; + if ((len % FLASH_SECTOR_SIZE) != 0 || (off % FLASH_SECTOR_SIZE) != 0) { - BOOT_LOG_ERR("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", - __func__, (int)off, (int)len); - return -1; - } + BOOT_LOG_DBG("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", + __func__, (int)start_addr, (int)len); - const uint32_t start_addr = fa->fa_off + off; - BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); + if(!aligned_flash_erase(start_addr, len)) { + return -1; + } + } else { + BOOT_LOG_DBG("%s: Aligned Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - if (bootloader_flash_erase_range(start_addr, len) != ESP_OK) { - BOOT_LOG_ERR("%s: Flash erase failed", __func__); - return -1; + if (bootloader_flash_erase_range(start_addr, len) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed", __func__); + return -1; + } } + #if VALIDATE_PROGRAM_OP for (size_t i = 0; i < len; i++) { uint8_t *val = (void *)(start_addr + i); From fe7f5955559f63b9c7af9314b2713a2e22aa5df0 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Tue, 29 Jul 2025 15:48:14 -0300 Subject: [PATCH 5/7] espressif: fix flash write/erase operation when encryption is enabled Add cache flush after write/erase operations to avoid getting invalid data when these are followed by read operation. Signed-off-by: Almir Okato --- boot/espressif/port/esp_mcuboot.c | 85 +++++++++++++++++++------------ 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index cae3a6edb4..64710f99fb 100644 --- a/boot/espressif/port/esp_mcuboot.c +++ b/boot/espressif/port/esp_mcuboot.c @@ -13,6 +13,9 @@ #include "sdkconfig.h" #include "esp_err.h" +#include "rom/cache.h" +#include "hal/cache_hal.h" +#include "hal/mmu_hal.h" #include "bootloader_flash_priv.h" #include "esp_flash_encrypt.h" #include "mcuboot_config/mcuboot_config.h" @@ -148,6 +151,22 @@ void flash_area_close(const struct flash_area *area) } +static void flush_cache(size_t start_addr, size_t length) +{ +#if CONFIG_IDF_TARGET_ESP32 + Cache_Read_Disable(0); + Cache_Flush(0); + Cache_Read_Enable(0); +#else + uint32_t vaddr = 0; + + mmu_hal_paddr_to_vaddr(0, start_addr, MMU_TARGET_FLASH0, MMU_VADDR_DATA, &vaddr); + if ((void *)vaddr != NULL) { + cache_hal_invalidate_addr(vaddr, length); + } +#endif +} + static bool aligned_flash_read(uintptr_t addr, void *dest, size_t size) { if (IS_ALIGNED(addr, 4) && IS_ALIGNED((uintptr_t)dest, 4) && IS_ALIGNED(size, 4)) { @@ -225,29 +244,31 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) #else bool flash_encryption_enabled = false; #endif + size_t alignment = flash_encryption_enabled ? 32 : 4; - if (IS_ALIGNED(dest_addr, 4) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, 4)) { + if (IS_ALIGNED(dest_addr, alignment) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, alignment)) { /* A single write operation is enough when all parameters are aligned */ return bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK; } + BOOT_LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x", __func__, (uint32_t)dest_addr, (uint32_t)src, size); - const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, 4); - const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, 4); + const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, alignment); + const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, alignment); uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_BUFFER_SIZE] = {0}; + uint8_t write_data[FLASH_BUFFER_SIZE] __attribute__((aligned(32))) = {0}; /* Perform a read operation considering an offset not aligned to 4-byte boundary */ uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data)); - if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, 4), true) != ESP_OK) { + if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) { return false; } uint32_t bytes_written = bytes - addr_offset; memcpy(&write_data[addr_offset], src, bytes_written); - if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) { + if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) { return false; } @@ -259,13 +280,13 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) while (bytes_remaining != 0) { bytes = MIN(bytes_remaining, sizeof(write_data)); - if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), true) != ESP_OK) { + if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) { return false; } memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes); - if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) { + if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) { return false; } @@ -284,13 +305,15 @@ static bool aligned_flash_erase(size_t addr, size_t size) return bootloader_flash_erase_range(addr, size) == ESP_OK; } + BOOT_LOG_DBG("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x", + __func__, (int)addr, (int)size); const uint32_t aligned_addr = ALIGN_DOWN(addr, FLASH_SECTOR_SIZE); const uint32_t addr_offset = ALIGN_OFFSET(addr, FLASH_SECTOR_SIZE); uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_SECTOR_SIZE] = {0}; + uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; - /* Perform a read operation considering an offset not aligned to 4-byte boundary */ + /* Perform a read operation considering an offset not aligned */ uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data)); @@ -298,21 +321,23 @@ static bool aligned_flash_erase(size_t addr, size_t size) return false; } - if (bootloader_flash_erase_range(aligned_addr, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { - BOOT_LOG_ERR("%s: Flash erase failed", __func__); - return -1; + return false; } uint32_t bytes_written = bytes - addr_offset; /* Write first part of non-erased data */ if(addr_offset > 0) { - aligned_flash_write(aligned_addr, write_data, addr_offset); + if (!aligned_flash_write(aligned_addr, write_data, addr_offset)) { + return false; + } } if(bytes < sizeof(write_data)) { - aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes); + if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes)) { + return false; + } } bytes_remaining -= bytes_written; @@ -328,12 +353,13 @@ static bool aligned_flash_erase(size_t addr, size_t size) } if (bootloader_flash_erase_range(aligned_addr + offset, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { - BOOT_LOG_ERR("%s: Flash erase failed", __func__); - return -1; + return false; } if(bytes < sizeof(write_data)) { - aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes); + if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes)) { + return false; + } } offset += bytes; @@ -360,12 +386,13 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, const uint32_t start_addr = fa->fa_off + off; BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - if (!aligned_flash_write(start_addr, src, len)) { BOOT_LOG_ERR("%s: Flash write failed", __func__); return -1; } + flush_cache(start_addr, len); + return 0; } @@ -376,23 +403,15 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) } const uint32_t start_addr = fa->fa_off + off; + BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - if ((len % FLASH_SECTOR_SIZE) != 0 || (off % FLASH_SECTOR_SIZE) != 0) { - BOOT_LOG_DBG("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", - __func__, (int)start_addr, (int)len); - - if(!aligned_flash_erase(start_addr, len)) { - return -1; - } - } else { - BOOT_LOG_DBG("%s: Aligned Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - - if (bootloader_flash_erase_range(start_addr, len) != ESP_OK) { - BOOT_LOG_ERR("%s: Flash erase failed", __func__); - return -1; - } + if(!aligned_flash_erase(start_addr, len)) { + BOOT_LOG_ERR("%s: Flash erase failed", __func__); + return -1; } + flush_cache(start_addr, len); + #if VALIDATE_PROGRAM_OP for (size_t i = 0; i < len; i++) { uint8_t *val = (void *)(start_addr + i); From e1f0215fb2d74fc5b82de9eb0d7cf951e764c907 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Sat, 24 May 2025 15:25:57 -0300 Subject: [PATCH 6/7] espressif: flash: fix image wrong state after swap-scratch when flash encryption is enabled When hardware flash encryption is enabled, force expected erased value (0xFF) into flash when erasing a region, and also always do a real erase before writing data into flash. This is handled on this implementation because MCUboot's state machine relies on erased valued data (0xFF) readed from a previously erased region that was not written yet, however when hardware flash encryption is enabled, the flash read always decrypts whats being read from flash, thus a region that was erased would not be read as what MCUboot expected (0xFF). Signed-off-by: Almir Okato --- boot/espressif/hal/src/flash_encrypt.c | 4 +- boot/espressif/port/esp_mcuboot.c | 88 ++++++++++++++++--- docs/readme-espressif.md | 40 ++++++++- ...fw-update-with-hw-flash-encryption-enabled | 6 ++ 4 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 docs/release-notes.d/espressif-fix-fw-update-with-hw-flash-encryption-enabled diff --git a/boot/espressif/hal/src/flash_encrypt.c b/boot/espressif/hal/src/flash_encrypt.c index 3996d0e7a5..b977236479 100644 --- a/boot/espressif/hal/src/flash_encrypt.c +++ b/boot/espressif/hal/src/flash_encrypt.c @@ -423,7 +423,7 @@ static esp_err_t encrypt_primary_slot(void) * MCUboot header */ err = bootloader_flash_read(CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS + 0x20, - &img_header, sizeof(esp_image_load_header_t), true); + &img_header, sizeof(esp_image_load_header_t), false); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read slot img header"); return err; @@ -464,7 +464,7 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length) wdt_hal_feed(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx); uint32_t sec_start = i + src_addr; - err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, true); + err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false); if (err != ESP_OK) { goto flash_failed; } diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index 64710f99fb..c061e85bd9 100644 --- a/boot/espressif/port/esp_mcuboot.c +++ b/boot/espressif/port/esp_mcuboot.c @@ -237,26 +237,38 @@ int flash_area_read(const struct flash_area *fa, uint32_t off, void *dst, return 0; } -static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) +static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size, bool erase) { #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED bool flash_encryption_enabled = esp_flash_encryption_enabled(); #else bool flash_encryption_enabled = false; #endif - size_t alignment = flash_encryption_enabled ? 32 : 4; + + /* When flash encryption is enabled, write alignment is 32 bytes, however to avoid + * inconsistences the region may be erased right before writting, thus the alignment + * is set to the erase required alignment (FLASH_SECTOR_SIZE). + * When flash encryption is not enabled, regular write alignment is 4 bytes. + */ + size_t alignment = flash_encryption_enabled ? (erase ? FLASH_SECTOR_SIZE : 32) : 4; if (IS_ALIGNED(dest_addr, alignment) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, alignment)) { /* A single write operation is enough when all parameters are aligned */ + if (flash_encryption_enabled && erase) { + if (bootloader_flash_erase_range(dest_addr, size) != ESP_OK) { + return false; + } + } return bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK; } - BOOT_LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x", __func__, (uint32_t)dest_addr, (uint32_t)src, size); + BOOT_LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x erase: %c", + __func__, (uint32_t)dest_addr, (uint32_t)src, size, erase ? 't' : 'f'); const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, alignment); const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, alignment); uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_BUFFER_SIZE] __attribute__((aligned(32))) = {0}; + uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; /* Perform a read operation considering an offset not aligned to 4-byte boundary */ @@ -265,6 +277,11 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) return false; } + if (flash_encryption_enabled && erase) { + if (bootloader_flash_erase_range(aligned_addr, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + return false; + } + } uint32_t bytes_written = bytes - addr_offset; memcpy(&write_data[addr_offset], src, bytes_written); @@ -284,6 +301,12 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) return false; } + if (flash_encryption_enabled && erase) { + if (bootloader_flash_erase_range(aligned_addr + offset, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + return false; + } + } + memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes); if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) { @@ -301,7 +324,7 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) static bool aligned_flash_erase(size_t addr, size_t size) { if (IS_ALIGNED(addr, FLASH_SECTOR_SIZE) && IS_ALIGNED(size, FLASH_SECTOR_SIZE)) { - /* A single write operation is enough when all parameters are aligned */ + /* A single erase operation is enough when all parameters are aligned */ return bootloader_flash_erase_range(addr, size) == ESP_OK; } @@ -329,13 +352,13 @@ static bool aligned_flash_erase(size_t addr, size_t size) /* Write first part of non-erased data */ if(addr_offset > 0) { - if (!aligned_flash_write(aligned_addr, write_data, addr_offset)) { + if (!aligned_flash_write(aligned_addr, write_data, addr_offset, false)) { return false; } } if(bytes < sizeof(write_data)) { - if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes)) { + if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes, false)) { return false; } } @@ -357,7 +380,7 @@ static bool aligned_flash_erase(size_t addr, size_t size) } if(bytes < sizeof(write_data)) { - if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes)) { + if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes, false)) { return false; } } @@ -384,9 +407,19 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, } const uint32_t start_addr = fa->fa_off + off; - BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); + bool erase = false; + BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d (0x%x)", __func__, (int)start_addr, (int)len, (int)len); - if (!aligned_flash_write(start_addr, src, len)) { +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + if (esp_flash_encryption_enabled()) { + /* Ensuring flash region has been erased before writing in order to + * avoid inconsistences when hardware flash encryption is enabled. + */ + erase = true; + } +#endif + + if (!aligned_flash_write(start_addr, src, len, erase)) { BOOT_LOG_ERR("%s: Flash write failed", __func__); return -1; } @@ -403,7 +436,7 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) } const uint32_t start_addr = fa->fa_off + off; - BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); + BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d (0x%x)", __func__, (int)start_addr, (int)len, (int)len); if(!aligned_flash_erase(start_addr, len)) { BOOT_LOG_ERR("%s: Flash erase failed", __func__); @@ -412,7 +445,38 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) flush_cache(start_addr, len); -#if VALIDATE_PROGRAM_OP +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + uint8_t write_data[FLASH_BUFFER_SIZE]; + memset(write_data, flash_area_erased_val(fa), sizeof(write_data)); + uint32_t bytes_remaining = len; + uint32_t offset = start_addr; + + uint32_t bytes_written = MIN(sizeof(write_data), len); + if (esp_flash_encryption_enabled()) { + /* When hardware flash encryption is enabled, force expected erased + * value (0xFF) into flash when erasing a region. + * + * This is handled on this implementation because MCUboot's state + * machine relies on erased valued data (0xFF) read from a + * previously erased region that was not written yet, however when + * hardware flash encryption is enabled, the flash read always + * decrypts what's being read from flash, thus a region that was + * erased would not be read as what MCUboot expected (0xFF). + */ + while (bytes_remaining != 0) { + if (!aligned_flash_write(offset, write_data, bytes_written, false)) { + BOOT_LOG_ERR("%s: Flash erase failed", __func__); + return -1; + } + offset += bytes_written; + bytes_remaining -= bytes_written; + } + } + + flush_cache(start_addr, len); +#endif + +#if VALIDATE_PROGRAM_OP && !defined(CONFIG_SECURE_FLASH_ENC_ENABLED) for (size_t i = 0; i < len; i++) { uint8_t *val = (void *)(start_addr + i); if (*val != 0xff) { diff --git a/docs/readme-espressif.md b/docs/readme-espressif.md index 6c8f6b326b..1fe6c6e88f 100644 --- a/docs/readme-espressif.md +++ b/docs/readme-espressif.md @@ -120,6 +120,22 @@ Additional configuration related to MCUboot features and slot partitioning may b 2. Flash MCUboot in your device: + --- + ***Note*** + + *Prior to flashing the bootloader and/or application and booting for the first time, ensure + that the secondary slot and scratch area are erased. This is important because flash erased + value (`0xFF` in case of this port) read from the trailer registers are part of MCUboot's + update-state checking mechanism, thus unknown data or garbage could be potentially + interpreted as a valid state and lead to an unexpected behavior. Flash can be erased + entirely using:* + + ```bash + esptool.py -p erase_flash + ``` + + --- + ```bash ninja -C build/ flash ``` @@ -532,10 +548,26 @@ CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE=1 --- +--- +***Note*** + +As recommended, ensure that the secondary slot and scratch area are **erased** prior to +the first time boot. Hardware flash encryption is transparent to MCUboot and the first boot +encryption process will encrypt the whole slots and scratch including their trailer regions, +and as said before, erased value read from trailer registers is also an expected state of +MCUboot update checking process. Erase flash command: + +```bash +esptool.py -p erase_flash +``` + +--- + ### [Signing the image when working with Flash Encryption](#signing-the-image-when-working-with-flash-encryption) -When enabling flash encryption, it is required to signed the image using 32-byte alignment: -`--align 32 --max-align 32`. +When enabling flash encryption, it is required to sign the image using 32-byte alignment and also +add the padding to fill the image up to the slot size: +`--pad --align 32 --max-align 32`. Command example: @@ -546,7 +578,9 @@ imgtool.py sign -k --pad --pad-sig --align 32 --max-align ### [Device generated key](#device-generated-key) First ensure that the application image is able to perform encrypted read and write operations to -the SPI Flash. Flash the bootloader and application normally: +the SPI Flash. + +Flash the bootloader and application normally: ```bash esptool.py -p -b 2000000 --after no_reset --chip write_flash --flash_mode dio --flash_size --flash_freq 40m diff --git a/docs/release-notes.d/espressif-fix-fw-update-with-hw-flash-encryption-enabled b/docs/release-notes.d/espressif-fix-fw-update-with-hw-flash-encryption-enabled new file mode 100644 index 0000000000..91c96074d2 --- /dev/null +++ b/docs/release-notes.d/espressif-fix-fw-update-with-hw-flash-encryption-enabled @@ -0,0 +1,6 @@ +- Add cache flush after write/erase operations to avoid getting invalid + data when these are followed by read operation. +- Fix image wrong state after swap-scratch when hardware flash encryption + is enabled. When hardware flash encryption is enabled, force expected + erased value (0xFF) into flash when erasing a region, and also always + do a real erase before writing data into flash. From 068676490bd3e4d659092fd24d3acb7990a3ef1b Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Wed, 10 Sep 2025 16:23:18 -0300 Subject: [PATCH 7/7] espressif: flash: refactor force aligned write and erase algorithms Refactor force aligned write and erase algorithms to improve readability. Signed-off-by: Almir Okato --- boot/espressif/port/esp_mcuboot.c | 197 ++++++++++++++++-------------- 1 file changed, 103 insertions(+), 94 deletions(-) diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index c061e85bd9..a28731011f 100644 --- a/boot/espressif/port/esp_mcuboot.c +++ b/boot/espressif/port/esp_mcuboot.c @@ -257,65 +257,66 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size, if (flash_encryption_enabled && erase) { if (bootloader_flash_erase_range(dest_addr, size) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed at 0x%08x", __func__, (uint32_t)dest_addr); return false; } + flush_cache(dest_addr, size); } - return bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK; - } - BOOT_LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x erase: %c", - __func__, (uint32_t)dest_addr, (uint32_t)src, size, erase ? 't' : 'f'); - - const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, alignment); - const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, alignment); - uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; - - /* Perform a read operation considering an offset not aligned to 4-byte boundary */ - uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data)); - if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) { - return false; - } - - if (flash_encryption_enabled && erase) { - if (bootloader_flash_erase_range(aligned_addr, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + if (bootloader_flash_write(dest_addr, (void *)src, size, flash_encryption_enabled) == ESP_OK) { + flush_cache(dest_addr, size); + return true; + } else { + BOOT_LOG_ERR("%s: Flash write failed at 0x%08x", __func__, (uint32_t)dest_addr); return false; } } - uint32_t bytes_written = bytes - addr_offset; - memcpy(&write_data[addr_offset], src, bytes_written); - - if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) { - return false; - } + BOOT_LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08x src: 0x%08x size: 0x%x erase: %c", + __func__, (uint32_t)dest_addr, (uint32_t)src, size, erase ? 't' : 'f'); - bytes_remaining -= bytes_written; + uint8_t write_aux_buf[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; - /* Write remaining data to Flash if any */ + size_t write_addr = dest_addr; + size_t bytes_remaining = size; + size_t src_offset = 0; - uint32_t offset = bytes; + while (bytes_remaining > 0) { + size_t aligned_curr_addr = ALIGN_DOWN(write_addr, alignment); + size_t curr_buf_off = write_addr - aligned_curr_addr; + size_t chunk_len = MIN(bytes_remaining, FLASH_SECTOR_SIZE - curr_buf_off); - while (bytes_remaining != 0) { - bytes = MIN(bytes_remaining, sizeof(write_data)); - if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), true) != ESP_OK) { + /* Read data before modifying */ + if (bootloader_flash_read(aligned_curr_addr, write_aux_buf, + ALIGN_UP(chunk_len, alignment), true) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash read failed at 0x%08x", __func__, (uint32_t)aligned_curr_addr); return false; } + /* Erase if needed */ if (flash_encryption_enabled && erase) { - if (bootloader_flash_erase_range(aligned_addr + offset, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { + if (bootloader_flash_erase_range(aligned_curr_addr, + ALIGN_UP(chunk_len, FLASH_SECTOR_SIZE)) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed at 0x%08x", __func__, (uint32_t)aligned_curr_addr); return false; } + flush_cache(aligned_curr_addr, ALIGN_UP(chunk_len, FLASH_SECTOR_SIZE)); } - memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes); + /* Merge data into buffer */ + memcpy(&write_aux_buf[curr_buf_off], &((uint8_t *)src)[src_offset], chunk_len); - if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, alignment), flash_encryption_enabled) != ESP_OK) { + /* Write back aligned chunk */ + if (bootloader_flash_write(aligned_curr_addr, write_aux_buf, + ALIGN_UP(chunk_len, alignment), + flash_encryption_enabled) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash write failed at 0x%08x", __func__, (uint32_t)aligned_curr_addr); return false; } + flush_cache(aligned_curr_addr, ALIGN_UP(chunk_len, alignment)); - offset += bytes; - bytes_written += bytes; - bytes_remaining -= bytes; + write_addr += chunk_len; + src_offset += chunk_len; + bytes_remaining -= chunk_len; } return true; @@ -326,68 +327,82 @@ static bool aligned_flash_erase(size_t addr, size_t size) if (IS_ALIGNED(addr, FLASH_SECTOR_SIZE) && IS_ALIGNED(size, FLASH_SECTOR_SIZE)) { /* A single erase operation is enough when all parameters are aligned */ - return bootloader_flash_erase_range(addr, size) == ESP_OK; - } - BOOT_LOG_DBG("%s: forcing unaligned erase on sector Offset: 0x%x Length: 0x%x", - __func__, (int)addr, (int)size); - - const uint32_t aligned_addr = ALIGN_DOWN(addr, FLASH_SECTOR_SIZE); - const uint32_t addr_offset = ALIGN_OFFSET(addr, FLASH_SECTOR_SIZE); - uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; - - /* Perform a read operation considering an offset not aligned */ - - uint32_t bytes = MIN(bytes_remaining + addr_offset, sizeof(write_data)); - - if (bootloader_flash_read(aligned_addr, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) { - return false; - } - - if (bootloader_flash_erase_range(aligned_addr, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { - return false; - } - - uint32_t bytes_written = bytes - addr_offset; - - /* Write first part of non-erased data */ - if(addr_offset > 0) { - if (!aligned_flash_write(aligned_addr, write_data, addr_offset, false)) { - return false; - } - } - - if(bytes < sizeof(write_data)) { - if (!aligned_flash_write(aligned_addr + bytes, write_data + bytes, sizeof(write_data) - bytes, false)) { + if (bootloader_flash_erase_range(addr, size) == ESP_OK) { + flush_cache(addr, size); + return true; + } else { + BOOT_LOG_ERR("%s: Flash erase failed at 0x%08x", __func__, (uint32_t)addr); return false; } } - bytes_remaining -= bytes_written; - - /* Write remaining data to Flash if any */ + const size_t sector_size = FLASH_SECTOR_SIZE; + const size_t start_addr = ALIGN_DOWN(addr, sector_size); + const size_t end_addr = ALIGN_UP(addr + size, sector_size); + const size_t total_len = end_addr - start_addr; + + BOOT_LOG_DBG("%s: forcing unaligned erase on sector Offset: 0x%08x Length: 0x%x total_len: 0x%x", + __func__, (uint32_t)addr, (int)size, total_len); + + uint8_t erase_aux_buf[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; + size_t current_addr = start_addr; + while (current_addr < end_addr) { + bool preserve_head = (addr > current_addr); + bool preserve_tail = ((addr + size) < (current_addr + sector_size)); + + if (preserve_head || preserve_tail) { + /* Read full sector before erasing */ + if (bootloader_flash_read(current_addr, erase_aux_buf, sector_size, true) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash read failed at 0x%08x", __func__, (uint32_t)current_addr); + return false; + } - uint32_t offset = bytes; + /* Calculate the range of the erase: data between erase_start and erase_end + * will not be written back + */ + size_t erase_start = (addr > current_addr) ? (addr - current_addr) : 0; + size_t erase_end = MIN(current_addr + sector_size, addr + size) - current_addr; - while (bytes_remaining != 0) { - bytes = MIN(bytes_remaining, sizeof(write_data)); - if (bootloader_flash_read(aligned_addr + offset, write_data, ALIGN_UP(bytes, FLASH_SECTOR_SIZE), true) != ESP_OK) { - return false; - } + BOOT_LOG_INF("%s: partial sector erase from: 0x%08x to: 0x%08x Length: 0x%x", + __func__, (uint32_t)(current_addr + erase_start), + (uint32_t)(current_addr + erase_end), erase_end - erase_start); - if (bootloader_flash_erase_range(aligned_addr + offset, ALIGN_UP(bytes, FLASH_SECTOR_SIZE)) != ESP_OK) { - return false; - } + /* Erase full sector */ + if (bootloader_flash_erase_range(current_addr, sector_size) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed at 0x%08x", __func__, (uint32_t)current_addr); + return false; + } + flush_cache(current_addr, sector_size); + + if (preserve_head) { + /* Write back preserved head data up to erase_start */ + if (!aligned_flash_write(current_addr, erase_aux_buf, erase_start, false)) { + BOOT_LOG_ERR("%s: Flash write failed at 0x%08x", __func__, (uint32_t)current_addr); + return false; + } + } - if(bytes < sizeof(write_data)) { - if (!aligned_flash_write(aligned_addr + offset + bytes, write_data + bytes, sizeof(write_data) - bytes, false)) { + if (preserve_tail) { + /* Write back preserved tail data from erase_end up to sector end */ + if (!aligned_flash_write(current_addr + erase_end, &erase_aux_buf[erase_end], sector_size - erase_end, false)) { + BOOT_LOG_ERR("%s: Flash write failed at 0x%08x", __func__, (uint32_t)current_addr + erase_end); + return false; + } + } + current_addr += sector_size; + } else { + /* Full sector erase is safe, erase the next consecutive full sectors */ + size_t contiguous_size = ALIGN_DOWN(addr + size, sector_size) - current_addr; + BOOT_LOG_DBG("%s: sectors erased from: 0x%08x length: 0x%x", + __func__, (uint32_t)current_addr, contiguous_size); + if (bootloader_flash_erase_range(current_addr, contiguous_size) != ESP_OK) { + BOOT_LOG_ERR("%s: Flash erase failed at 0x%08x", __func__, (uint32_t)current_addr); return false; } - } + flush_cache(current_addr, contiguous_size); - offset += bytes; - bytes_written += bytes; - bytes_remaining -= bytes; + current_addr += contiguous_size; + } } return true; @@ -424,8 +439,6 @@ int flash_area_write(const struct flash_area *fa, uint32_t off, const void *src, return -1; } - flush_cache(start_addr, len); - return 0; } @@ -438,13 +451,11 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) const uint32_t start_addr = fa->fa_off + off; BOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d (0x%x)", __func__, (int)start_addr, (int)len, (int)len); - if(!aligned_flash_erase(start_addr, len)) { + if (!aligned_flash_erase(start_addr, len)) { BOOT_LOG_ERR("%s: Flash erase failed", __func__); return -1; } - flush_cache(start_addr, len); - #ifdef CONFIG_SECURE_FLASH_ENC_ENABLED uint8_t write_data[FLASH_BUFFER_SIZE]; memset(write_data, flash_area_erased_val(fa), sizeof(write_data)); @@ -472,8 +483,6 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) bytes_remaining -= bytes_written; } } - - flush_cache(start_addr, len); #endif #if VALIDATE_PROGRAM_OP && !defined(CONFIG_SECURE_FLASH_ENC_ENABLED)