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/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/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/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/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/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/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) 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) diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index 9bbd5a9f20..a28731011f 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)) { @@ -218,7 +237,7 @@ 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(); @@ -226,52 +245,164 @@ static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size) bool flash_encryption_enabled = false; #endif - if (IS_ALIGNED(dest_addr, 4) && IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED(size, 4)) { - /* 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; - } + /* 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; - const uint32_t aligned_addr = ALIGN_DOWN(dest_addr, 4); - const uint32_t addr_offset = ALIGN_OFFSET(dest_addr, 4); - uint32_t bytes_remaining = size; - uint8_t write_data[FLASH_BUFFER_SIZE] = {0}; + 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 */ - /* Perform a read operation considering an offset not aligned to 4-byte boundary */ + 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); + } - 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) { - return false; + 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; + } } + 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'); - uint32_t bytes_written = bytes - addr_offset; - memcpy(&write_data[addr_offset], src, bytes_written); + uint8_t write_aux_buf[FLASH_SECTOR_SIZE] __attribute__((aligned(32))) = {0}; - if (bootloader_flash_write(aligned_addr, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) { - return false; - } + size_t write_addr = dest_addr; + size_t bytes_remaining = size; + size_t src_offset = 0; - bytes_remaining -= bytes_written; + 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); - /* Write remaining data to Flash if any */ + /* 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; + } - uint32_t offset = bytes; + /* Erase if needed */ + if (flash_encryption_enabled && erase) { + 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)); + } - 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) { + /* Merge data into buffer */ + memcpy(&write_aux_buf[curr_buf_off], &((uint8_t *)src)[src_offset], chunk_len); + + /* 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)); + + write_addr += chunk_len; + src_offset += chunk_len; + bytes_remaining -= chunk_len; + } - memcpy(write_data, &((uint8_t *)src)[bytes_written], bytes); + return true; +} - if (bootloader_flash_write(aligned_addr + offset, write_data, ALIGN_UP(bytes, 4), flash_encryption_enabled) != ESP_OK) { +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 */ + + 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; } + } - offset += bytes; - bytes_written += bytes; - bytes_remaining -= bytes; + 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; + } + + /* 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; + + 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); + + /* 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 (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); + + current_addr += contiguous_size; + } } return true; @@ -291,10 +422,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); - bool success = aligned_flash_write(start_addr, src, len); - if (!success) { +#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; } @@ -308,20 +448,44 @@ int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len) return -1; } - 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; - } - 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 (bootloader_flash_erase_range(start_addr, len) != ESP_OK) { + if (!aligned_flash_erase(start_addr, len)) { BOOT_LOG_ERR("%s: Flash erase failed", __func__); return -1; } -#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; + } + } +#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/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 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.