esp-idf: update to v5.5.4, take multisig bootloader component from https://github.com/Blockstream/esp-idf/tree/securebootv2_multisig_v5.5.4
What changed, and why it matters
This is a large update that pulls in Espressif's ESP-IDF v5.5.4 bootloader code, plus Blockstream's own multi-signature secure-boot patches. Most of the visible changes are routine: support for newer ESP32 chips, larger flash sizes, and a new Trusted Execution Environment (TEE) mode. There are also several security-hardening touches, such as preventing the TEE from writing or erasing its own active flash partition and adding anti-fault-injection checks. However, the commit is a broad vendor SDK refresh rather than a single focused security fix, and the diff provided is only a partial sample of the whole change.
Treat this as a high-risk SDK migration rather than a routine patch. Build and run the full Blockstream Jade test suite, with special attention to secure-boot verification, TEE partition protection, and OTA rollback behavior. Compare the imported Blockstream esp-idf branch against upstream ESP-IDF v5.5.4 to confirm that only intended multi-signature changes were introduced. Perform a targeted hardware-in-the-loop review of flash write/erase paths under TEE and verify that ESP_FAULT_ASSERT cannot be bypassed by glitching the comparison result.
Security signals we found
Anti-fault-injection assertion (ESP_FAULT_ASSERT) added around TEE flash address validation
TEE flash write/erase now rejects operations targeting the active TEE partition range
Secure Boot V2 extended to support ECDSA-P384 / SHA-384 digests
Multi-signature bootloader component imported from a dedicated Blockstream secureboot branch
Cache handling changed from disable/enable to suspend/resume in TEE builds, with explicit invalidation
Large SDK refresh (+3,879/-1,437 lines across 104 files) increases attack surface and review burden
Evidence from the diff
The commit imports the ESP-IDF v5.5.4 bootloader_support component into Blockstream Jade, alongside a Blockstream branch that adds Secure Boot V2 multi-signature support. Key technical changes visible in the partial diff include: (1) TEE build support with separate MMU mapping strategy, cache suspend/resume instead of disable/enable, and flash write/erase address validation against the active TEE partition plus ESP_FAULT_ASSERT anti-FI checks; (2) SHA-384/ECDSA-P384 secure boot support, including digest length changes and chunked SHA-384 over large flash ranges; (3) new chip support (ESP32-C61, H21, H4) and larger flash sizes up to 128 MB; (4) bootloader_flash_unlock converted from a weak symbol to a weak alias, with a new default implementation; (5) addition of TEE OTA partition types and helper APIs. The supplied diff is a small subset of the 104 changed files, so full security assessment of the entire SDK refresh is not possible from this sample alone.
Changed components
bootloader_components/bootloader_supportbootloader flash configuration for ESP32 variantsESP-IDF v5.5.4 SDK integrationSecure Boot V2 signature verificationTEE (Trusted Execution Environment) OTA and flash protectionmain/idf_component.yml and dependency lock filesInspect captured patch +3879 / −1437
diff --git a/bootloader_components/bootloader_support/CMakeLists.txt b/bootloader_components/bootloader_support/CMakeLists.txt
index c1f8eb6..bae865d 100644
--- a/bootloader_components/bootloader_support/CMakeLists.txt
+++ b/bootloader_components/bootloader_support/CMakeLists.txt
@@ -1,9 +1,37 @@
idf_build_get_property(target IDF_TARGET)
+idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
+if(esp_tee_build)
+ set(tee_inc_dirs "include"
+ "private_include"
+ "bootloader_flash/include")
+
+ set(tee_srcs "src/flash_partitions.c"
+ "src/bootloader_sha.c"
+ "src/bootloader_common_loader.c"
+ "src/esp_image_format.c"
+ "src/bootloader_utility.c"
+ "src/bootloader_utility_tee.c"
+ "bootloader_flash/src/bootloader_flash.c")
+
+ if(CONFIG_SECURE_BOOT_V2_ENABLED)
+ if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
+ list(APPEND tee_srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c"
+ "src/secure_boot_v2/secure_boot.c"
+ "src/${IDF_TARGET}/secure_boot_secure_features.c")
+ endif()
+ endif()
+
+ idf_component_register(SRCS ${tee_srcs}
+ INCLUDE_DIRS ${tee_inc_dirs}
+ PRIV_REQUIRES efuse esp_app_format)
+ return()
+endif()
+
set(srcs
"src/bootloader_common.c"
"src/bootloader_common_loader.c"
@@ -36,6 +64,11 @@ if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT)
)
endif()
+list(APPEND srcs "src/bootloader_sha.c")
+if(CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE)
+ list(APPEND srcs "src/${IDF_TARGET}/bootloader_ecdsa.c")
+endif()
+
if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM)
set(include_dirs "include" "bootloader_flash/include"
"private_include")
@@ -45,18 +78,14 @@ if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM)
"src/bootloader_clock_loader.c"
"src/bootloader_console.c"
"src/bootloader_console_loader.c"
- "src/${IDF_TARGET}/bootloader_sha.c"
"src/${IDF_TARGET}/bootloader_soc.c"
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
)
- list(APPEND priv_requires hal)
- if(CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE)
- list(APPEND srcs
- "src/${IDF_TARGET}/bootloader_ecdsa.c")
+ if(CONFIG_SECURE_ENABLE_TEE)
+ list(APPEND srcs "src/bootloader_utility_tee.c")
endif()
+ list(APPEND priv_requires hal)
else()
- list(APPEND srcs
- "src/idf/bootloader_sha.c")
set(include_dirs "include" "bootloader_flash/include")
set(priv_include_dirs "private_include")
# heap is required for `heap_memory_layout.h` header
diff --git a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash.h b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash.h
index c85dfbd..4cb3856 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash.h
+++ b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -28,7 +28,7 @@ uint32_t bootloader_read_flash_id(void);
/**
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
*
- * @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
+ * @return ESP_OK When startup successfully, otherwise ESP_FAIL (indicating you should reboot before erase/write).
*/
esp_err_t bootloader_flash_xmc_startup(void);
@@ -36,9 +36,16 @@ esp_err_t bootloader_flash_xmc_startup(void);
* @brief Unlock Flash write protect.
* Please do not call this function in SDK.
*
- * @note This can be overridden because it's attribute weak.
+ * @note This can be overridden because it's attribute weak, when there is a same name symbol.
*/
-esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
+esp_err_t bootloader_flash_unlock(void);
+
+/**
+ * @brief Unlock Flash write protect.
+ * This is alias to `bootloader_flash_unlock`.
+ * Please do not call this function in SDK.
+ */
+esp_err_t bootloader_flash_unlock_default(void);
/**
* @brief Reset the flash chip (66H + 99H).
diff --git a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_override.h b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_override.h
index 4950dde..b910a8d 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_override.h
+++ b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_override.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -99,15 +99,20 @@ void bootloader_write_status_8b_xmc25qu64a(unsigned new_status);
Searching of this table stops when the first match is found.
*/
-extern const bootloader_qio_info_t __attribute__((weak)) bootloader_flash_qe_support_list[];
+extern const bootloader_qio_info_t* bootloader_flash_qe_support_list;
+
+/**
+ * @brief The bootloader flash qe list count number.
+*/
+extern uint8_t bootloader_flash_qe_list_count;
/**
* @brief Unlock Flash write protect.
* Please do not call this function in SDK.
*
- * @note This can be overridden because it's attribute weak.
+ * @note This can be overridden because it's attribute weak, when there is a same name symbol.
*/
-esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
+esp_err_t bootloader_flash_unlock(void);
#if CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH || CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_OCTAL_FLASH
/**
@@ -115,7 +120,7 @@ esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
*
* @param flash_mode SPI flash working mode.
*
- * @note This can be overridden because it's attribute weak.
+ * @note This can be overridden because it's attribute weak, when there is a same name symbol.
*/
void __attribute__((weak)) bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t flash_mode);
#endif
diff --git a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_priv.h b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_priv.h
index 50f31ca..304ef07 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_priv.h
+++ b/bootloader_components/bootloader_support/bootloader_flash/include/bootloader_flash_priv.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -128,7 +128,10 @@ esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool a
*
* @note All of dest_addr, src and size have to be 4-byte aligned. If write_encrypted is set, dest_addr and size must be 32-byte aligned.
*
- * Note: In bootloader, when write_encrypted == true, the src buffer is encrypted in place.
+ * @note In bootloader, when write_encrypted == true, the src buffer is encrypted in place.
+ *
+ * @note [ESP-TEE] Using this API from the TEE will return an error if the dest_addr lies
+ * within the active TEE partition range.
*
* @param dest_addr Destination address to write in Flash.
* @param src Pointer to the data to write to flash
@@ -152,6 +155,9 @@ esp_err_t bootloader_flash_erase_sector(size_t sector);
/**
* @brief Erase the Flash range.
*
+ * @note [ESP-TEE] Using this API from the TEE will return an error if the start_addr lies
+ * within the active TEE partition range.
+ *
* @param start_addr start address of flash offset
* @param size sector aligned size to be erased
*
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash.c
index adff675..5315bc2 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,11 +13,12 @@
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
-#ifndef BOOTLOADER_BUILD
+#if !NON_OS_BUILD
#include "spi_flash_mmap.h"
#endif
#include "hal/spi_flash_ll.h"
#include "rom/spi_flash.h"
+#include "esp_private/cache_utils.h"
#if !CONFIG_IDF_TARGET_ESP32
#include "hal/spimem_flash_ll.h"
#endif
@@ -44,7 +45,7 @@
#define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
-#ifndef BOOTLOADER_BUILD
+#if !NON_OS_BUILD
/* Normal app version maps to spi_flash_mmap.h operations...
*/
static const char *TAG = "bootloader_mmap";
@@ -111,7 +112,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
return esp_flash_erase_region(NULL, start_addr, size);
}
-#else //BOOTLOADER_BUILD
+#else // NON_OS_BUILD
/* Bootloader version, uses ROM functions only */
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/cache.h"
@@ -127,16 +128,53 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
#include "esp32s3/rom/opi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/opi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32C5
+#include "esp32c5/rom/opi_flash.h"
#endif
+#include "spi_flash/spi_flash_defs.h"
+
+#if ESP_TEE_BUILD
+#include "esp_fault.h"
+#include "esp_flash_partitions.h"
+#include "rom/spi_flash.h"
+
+extern bool esp_tee_flash_check_prange_in_active_tee_part(const size_t paddr, const size_t len);
+#endif
+
static const char *TAG = "bootloader_flash";
+/*
+ * NOTE: Memory mapping strategy
+ *
+ * Bootloader:
+ * - Uses the first N-1 MMU entries for general memory mapping.
+ * - Reserves the Nth (last) MMU entry for flash read through the cache
+ * (auto-decryption).
+ * - This strategy is viable because the bootloader runs exclusively
+ * on the device from the internal SRAM.
+ *
+ * ESP-TEE (Trusted Execution Environment)
+ * - Cannot adopt the strategy used by the bootloader as the TEE app operates
+ * in parallel to the REE.
+ * - The few initial MMU entries have already been taken by the TEE and REE
+ * application flash IDROM segments.
+ * - The REE could have also mapped some custom flash partitions it requires.
+ * - Therefore, the TEE uses MMU entries from the end of the range, with the number
+ * of entries corresponding to the size of its IDROM segment sizes.
+ * - The final MMU entry in this range is reserved for flash reads through the
+ * cache (auto-decryption).
+ * - The pages used by TEE are protected by PMP (Physical Memory Protection).
+ * While REE attempts to mmap this protected area would trigger a load access
+ * fault, this is unlikely since the MMU can address up to 16MB at once.
+ */
+
#if CONFIG_IDF_TARGET_ESP32
/* Use first 50 blocks in MMU for bootloader_mmap,
50th block for bootloader_flash_read
*/
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
-#define MMAP_MMU_SIZE (0x320000)
-#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMAP_MMU_SIZE)
+#define MMU_TOTAL_SIZE (0x320000)
+#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_TOTAL_SIZE)
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
#else // !CONFIG_IDF_TARGET_ESP32
@@ -150,21 +188,129 @@ static const char *TAG = "bootloader_flash";
* On ESP32S2 we use `(SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW)`.
* As this code is in bootloader, we keep this on ESP32S2
*/
-#define MMAP_MMU_SIZE (SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
+#define MMU_TOTAL_SIZE (SOC_DRAM0_CACHE_ADDRESS_HIGH - SOC_DRAM0_CACHE_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
#else
-#define MMAP_MMU_SIZE (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_DRAM_FLASH_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
+#define MMU_TOTAL_SIZE (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_DRAM_FLASH_ADDRESS_LOW) // This mmu size means that the mmu size to be mapped
#endif
-#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMAP_MMU_SIZE - SPI_FLASH_MMU_PAGE_SIZE)
-#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
+#define MMU_END_VADDR (MMU_BLOCK0_VADDR + MMU_TOTAL_SIZE)
+#define MMU_BLOCKL_VADDR (MMU_END_VADDR - 1 * CONFIG_MMU_PAGE_SIZE)
+#define FLASH_READ_VADDR MMU_BLOCKL_VADDR
#endif
+#if !ESP_TEE_BUILD
+#define MMAP_MMU_SIZE (MMU_TOTAL_SIZE)
+// Represents the MMU pages available for mmapping by the bootloader
#define MMU_FREE_PAGES (MMAP_MMU_SIZE / CONFIG_MMU_PAGE_SIZE)
+#define FLASH_MMAP_VADDR (MMU_BLOCK0_VADDR)
+#else /* ESP_TEE_BUILD */
+#define MMAP_MMU_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
+// Represents the MMU pages available for mmapping by the TEE
+#define MMU_FREE_PAGES (MMAP_MMU_SIZE / CONFIG_MMU_PAGE_SIZE)
+#define FLASH_MMAP_VADDR (MMU_END_VADDR - (MMU_FREE_PAGES + 1) * CONFIG_MMU_PAGE_SIZE)
+#endif /* !ESP_TEE_BUILD */
static bool mapped;
+// Required for bootloader_flash_munmap() for ESP-TEE
+static uint32_t current_mapped_size;
+
// Current bootloader mapping (ab)used for bootloader_read()
static uint32_t current_read_mapping = UINT32_MAX;
+#if ESP_TEE_BUILD
+/* [ESP-TEE] Workarounds for the ROM SPI flash APIs */
+/*
+ * TODO: The esp_rom_spiflash_read API requires two workarounds on ESP32-C6 ECO0 -
+ *
+ * 1. [IDF-7199] Call esp_rom_spiflash_write API once before reading.
+ * Without this, reads return corrupted data.
+ *
+ * 2. Configure ROM flash parameters before each read using the function below.
+ * Without this, the first byte read is corrupted.
+ *
+ * NOTE: These workarounds are not needed for ESP32-C6 ECO1 and later versions.
+ */
+static void rom_read_api_workaround(void)
+{
+#if CONFIG_ESP32C6_REV_MIN_FULL == 0
+ if (efuse_hal_chip_revision() == 0) {
+ extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode);
+ extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
+
+ static bool is_first_call = true;
+ if (is_first_call) {
+ uint32_t dummy_val = UINT32_MAX;
+ uint32_t dest_addr = ESP_PARTITION_TABLE_OFFSET + ESP_PARTITION_TABLE_MAX_LEN;
+ esp_rom_spiflash_write(dest_addr, &dummy_val, sizeof(dummy_val));
+ is_first_call = false;
+ }
+
+ uint32_t freqdiv = 0;
+
+#if CONFIG_ESPTOOLPY_FLASHFREQ_80M
+ freqdiv = 1;
+#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
+ freqdiv = 2;
+#elif CONFIG_ESPTOOLPY_FLASHFREQ_20M
+ freqdiv = 4;
+#endif
+
+ esp_rom_spiflash_read_mode_t read_mode;
+#if CONFIG_ESPTOOLPY_FLASHMODE_QIO
+ read_mode = ESP_ROM_SPIFLASH_QIO_MODE;
+#elif CONFIG_ESPTOOLPY_FLASHMODE_QOUT
+ read_mode = ESP_ROM_SPIFLASH_QOUT_MODE;
+#elif CONFIG_ESPTOOLPY_FLASHMODE_DIO
+ read_mode = ESP_ROM_SPIFLASH_DIO_MODE;
+#elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT
+ read_mode = ESP_ROM_SPIFLASH_DOUT_MODE;
+#endif
+
+ esp_rom_spiflash_config_clk(freqdiv, 1);
+ spi_dummy_len_fix(1, freqdiv);
+ esp_rom_spiflash_config_readmode(read_mode);
+ spi_common_set_dummy_output(read_mode);
+ }
+#endif
+}
+
+/*
+ * TODO: [IDF-13582]
+ *
+ * When `esp_flash_read()` is invoked from REE, it enables SPI1 WB (write-back) mode
+ * via `spi_flash_ll_wb_mode_enable()`. The ROM flash APIs used by TEE do not support
+ * WB mode, causing failures when TEE later accesses flash.
+ *
+ * Workaround applied in TEE flash layer:
+ * 1. Save the current WB mode state.
+ * 2. Temporarily disable WB mode before calling ROM flash APIs.
+ * 3. Restore WB mode state after the ROM API call completes.
+ *
+ * NOTE: This workaround will become removed once IDF-13582 is implemented.
+ */
+static inline bool spi1_wb_mode_save_and_disable(void)
+{
+#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
+ if (REG_GET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN)) {
+ REG_CLR_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN);
+ return true;
+ }
+#endif
+ return false;
+}
+
+static inline void spi1_wb_mode_restore(bool saved_state)
+{
+#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
+ if (saved_state) {
+ REG_SET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN);
+ }
+#else
+ (void)saved_state;
+#endif
+}
+#endif
+
uint32_t bootloader_mmap_get_free_pages(void)
{
/**
@@ -188,13 +334,15 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size)
uint32_t src_paddr_aligned = src_paddr & MMU_FLASH_MASK;
//The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
uint32_t size_after_paddr_aligned = (src_paddr - src_paddr_aligned) + size;
+
+ uint32_t actual_mapped_len = 0;
/**
* @note 1
* Will add here a check to make sure the vaddr is on read-only and executable buses, since we use others for psram
* Now simply check if it's valid vaddr, didn't check if it's readable, writable or executable.
* TODO: IDF-4710
*/
- if (mmu_ll_check_valid_ext_vaddr_region(0, MMU_BLOCK0_VADDR, size_after_paddr_aligned, MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION) == 0) {
+ if (mmu_ll_check_valid_ext_vaddr_region(0, FLASH_MMAP_VADDR, size_after_paddr_aligned, MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION) == 0) {
ESP_EARLY_LOGE(TAG, "vaddr not valid");
return NULL;
}
@@ -204,15 +352,25 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size)
Cache_Read_Disable(0);
Cache_Flush(0);
#else
+ /* NOTE: [ESP-TEE] Cache suspension vs disabling
+ *
+ * For ESP-TEE , we use suspend the cache instead of disabling it to avoid flushing the entire cache.
+ * This prevents performance hits when returning to the REE app due to cache misses.
+ * This is not applicable to the bootloader as it runs exclusively on the device from the internal SRAM.
+ */
+#if !ESP_TEE_BUILD
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#endif
#endif
//---------------Do mapping------------------------
- ESP_EARLY_LOGD(TAG, "rodata starts from paddr=0x%08" PRIx32 ", size=0x%" PRIx32 ", will be mapped to vaddr=0x%08" PRIx32, src_paddr, size, (uint32_t)MMU_BLOCK0_VADDR);
+ ESP_EARLY_LOGD(TAG, "rodata starts from paddr=0x%08" PRIx32 ", size=0x%" PRIx32 ", will be mapped to vaddr=0x%08" PRIx32, src_paddr, size, (uint32_t)FLASH_MMAP_VADDR);
#if CONFIG_IDF_TARGET_ESP32
uint32_t count = GET_REQUIRED_MMU_PAGES(size, src_paddr);
- int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_paddr_aligned, 64, count);
- ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)MMU_BLOCK0_VADDR, count * SPI_FLASH_MMU_PAGE_SIZE);
+ int e = cache_flash_mmu_set(0, 0, FLASH_MMAP_VADDR, src_paddr_aligned, 64, count);
+ ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)FLASH_MMAP_VADDR, count * SPI_FLASH_MMU_PAGE_SIZE);
if (e != 0) {
ESP_EARLY_LOGE(TAG, "cache_flash_mmu_set failed: %d", e);
Cache_Read_Enable(0);
@@ -223,9 +381,8 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size)
* This hal won't return error, it assumes the inputs are valid. The related check should be done in `bootloader_mmap()`.
* See above comments (note 1) about IDF-4710
*/
- uint32_t actual_mapped_len = 0;
- mmu_hal_map_region(0, MMU_TARGET_FLASH0, MMU_BLOCK0_VADDR, src_paddr_aligned, size_after_paddr_aligned, &actual_mapped_len);
- ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)MMU_BLOCK0_VADDR, actual_mapped_len);
+ mmu_hal_map_region(0, MMU_TARGET_FLASH0, FLASH_MMAP_VADDR, src_paddr_aligned, size_after_paddr_aligned, &actual_mapped_len);
+ ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)FLASH_MMAP_VADDR, actual_mapped_len);
#endif
/**
@@ -238,14 +395,19 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size)
Cache_Read_Enable(0);
#else
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
- cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len);
+ cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, FLASH_MMAP_VADDR, actual_mapped_len);
#endif
+#if !ESP_TEE_BUILD
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#endif
#endif
mapped = true;
+ current_mapped_size = actual_mapped_len;
- return (void *)(MMU_BLOCK0_VADDR + (src_paddr - src_paddr_aligned));
+ return (void *)(FLASH_MMAP_VADDR + (src_paddr - src_paddr_aligned));
}
void bootloader_munmap(const void *mapping)
@@ -257,11 +419,18 @@ void bootloader_munmap(const void *mapping)
Cache_Flush(0);
mmu_init(0);
#else
+#if !ESP_TEE_BUILD
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
mmu_hal_unmap_all();
+#else
+ cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ mmu_hal_unmap_region(0, FLASH_MMAP_VADDR, current_mapped_size);
+ cache_hal_invalidate_addr(FLASH_MMAP_VADDR, current_mapped_size);
+ cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#endif
#endif
mapped = false;
- current_read_mapping = UINT32_MAX;
+ current_mapped_size = 0;
}
}
@@ -285,7 +454,12 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
Cache_Read_Disable(0);
Cache_Flush(0);
#else
+#if !ESP_TEE_BUILD
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ rom_read_api_workaround();
+ bool is_wb_saved = spi1_wb_mode_save_and_disable();
+#endif
#endif
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
@@ -293,7 +467,11 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0);
#else
+#if !ESP_TEE_BUILD
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ spi1_wb_mode_restore(is_wb_saved);
+#endif
#endif
return spi_to_esp_err(r);
@@ -316,7 +494,13 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
Cache_Read_Disable(0);
Cache_Flush(0);
#else
+#if !ESP_TEE_BUILD
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ //---------------Invalidating entries at to-be-mapped v_addr------------------------
+ cache_hal_invalidate_addr(FLASH_READ_VADDR, SPI_FLASH_MMU_PAGE_SIZE);
+#endif
#endif
//---------------Do mapping------------------------
@@ -337,29 +521,26 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
Cache_Read_Enable(0);
#else
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
- cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, MMU_BLOCK0_VADDR, actual_mapped_len);
+ cache_ll_invalidate_addr(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL, FLASH_READ_VADDR, actual_mapped_len);
#endif
+#if !ESP_TEE_BUILD
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#else
+ cache_hal_resume(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+#endif
#endif
}
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
dest_words[word] = *map_ptr;
+ current_read_mapping = UINT32_MAX;
}
return ESP_OK;
}
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt)
{
- if (src_addr & 3) {
- ESP_EARLY_LOGE(TAG, "bootloader_flash_read src_addr 0x%x not 4-byte aligned", src_addr);
- return ESP_FAIL;
- }
- if (size & 3) {
- ESP_EARLY_LOGE(TAG, "bootloader_flash_read size 0x%x not 4-byte aligned", size);
- return ESP_FAIL;
- }
- if ((intptr_t)dest & 3) {
- ESP_EARLY_LOGE(TAG, "bootloader_flash_read dest 0x%x not 4-byte aligned", (intptr_t)dest);
+ if ((src_addr & 3) || (size & 3) || ((intptr_t)dest & 3)) {
+ ESP_EARLY_LOGE(TAG, "bootloader_flash_read src_addr 0x%x, size 0x%x or dest 0x%x not 4-byte aligned", src_addr, size, (intptr_t)dest);
return ESP_FAIL;
}
@@ -372,7 +553,19 @@ esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool a
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
{
- esp_err_t err;
+ /* NOTE: [ESP-TEE] Flash operation address validation with anti-FI check
+ *
+ * Ensure that flash operations cannot be executed within forbidden memory ranges
+ * by validating the address before proceeding.
+ */
+#if ESP_TEE_BUILD
+ bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(dest_addr, size);
+ if (addr_chk) {
+ ESP_EARLY_LOGE(TAG, "bootloader_flash_write invalid dest_addr");
+ return ESP_FAIL;
+ }
+ ESP_FAULT_ASSERT(!addr_chk);
+#endif
size_t alignment = write_encrypted ? 32 : 4;
if ((dest_addr % alignment) != 0) {
ESP_EARLY_LOGE(TAG, "bootloader_flash_write dest_addr 0x%x not %d-byte aligned", dest_addr, alignment);
@@ -387,16 +580,34 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
return ESP_FAIL;
}
- err = bootloader_flash_unlock();
+ esp_err_t err = bootloader_flash_unlock();
if (err != ESP_OK) {
return err;
}
+#if ESP_TEE_BUILD
+ bool is_wb_saved = spi1_wb_mode_save_and_disable();
+#endif
+
+ esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
+
if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) {
- return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
+ rc = esp_rom_spiflash_write_encrypted(dest_addr, src, size);
} else {
- return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
+ rc = esp_rom_spiflash_write(dest_addr, src, size);
}
+ /* NOTE: [ESP-TEE] Cache flushing after flash writes/erases
+ *
+ * After writing or erasing the flash, we need to flush the cache at locations
+ * corresponding to the destination write/erase address. This prevents stale data
+ * from being read from already memory-mapped addresses that were modified.
+ */
+#if ESP_TEE_BUILD
+ spi1_wb_mode_restore(is_wb_saved);
+ spi_flash_check_and_flush_cache(dest_addr, size);
+#endif
+
+ return spi_to_esp_err(rc);
}
esp_err_t bootloader_flash_erase_sector(size_t sector)
@@ -406,6 +617,13 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
{
+#if ESP_TEE_BUILD
+ bool addr_chk = esp_tee_flash_check_prange_in_active_tee_part(start_addr, size);
+ if (addr_chk) {
+ return ESP_ERR_INVALID_ARG;
+ }
+ ESP_FAULT_ASSERT(!addr_chk);
+#endif
if (start_addr % FLASH_SECTOR_SIZE != 0) {
return ESP_ERR_INVALID_ARG;
}
@@ -413,7 +631,11 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
return ESP_ERR_INVALID_SIZE;
}
size_t start = start_addr / FLASH_SECTOR_SIZE;
- size_t end = start + size / FLASH_SECTOR_SIZE;
+ size_t num_sectors = size / FLASH_SECTOR_SIZE;
+ if (num_sectors > SIZE_MAX - start) {
+ return ESP_ERR_INVALID_SIZE;
+ }
+ size_t end = start + num_sectors;
const size_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE;
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
@@ -426,6 +648,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
++sector;
}
}
+#if ESP_TEE_BUILD
+ spi_flash_check_and_flush_cache(start_addr, size);
+#endif
+
return spi_to_esp_err(rc);
}
@@ -436,37 +662,37 @@ void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t fla
switch (flash_mode) {
case ESP_ROM_SPIFLASH_DOUT_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 8;
+ cache_rd.dummy_bit_len = SPI_FLASH_DOUT_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_DUAL_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_DIO_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 4;
+ cache_rd.dummy_bit_len = SPI_FLASH_DIO_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_DIO_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_QOUT_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 8;
+ cache_rd.dummy_bit_len = SPI_FLASH_QOUT_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_QUAD_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_QIO_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 6;
+ cache_rd.dummy_bit_len = SPI_FLASH_QIO_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_QIO_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_FASTRD_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 8;
+ cache_rd.dummy_bit_len = SPI_FLASH_FASTRD_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_SLOWRD_MODE:
cache_rd.addr_bit_len = 32;
- cache_rd.dummy_bit_len = 0;
+ cache_rd.dummy_bit_len = SPI_FLASH_SLOWRD_DUMMY_BITLEN;
cache_rd.cmd = CMD_SLOWRD_4B;
cache_rd.cmd_bit_len = 8;
break;
@@ -480,7 +706,7 @@ void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t fla
}
#endif
-#endif // BOOTLOADER_BUILD
+#endif // NON_OS_BUILD
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
@@ -499,7 +725,7 @@ FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
return BYTESHIFT(chip->device_id, 2) == MXIC_ID;
}
-esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
+esp_err_t IRAM_ATTR bootloader_flash_unlock_default(void)
{
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
@@ -568,6 +794,17 @@ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
return err;
}
+esp_err_t __attribute__((weak, alias("bootloader_flash_unlock_default"))) bootloader_flash_unlock(void);
+
+
+#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 && !NON_OS_BUILD
+extern uint32_t bootloader_flash_execute_command_common(
+ uint8_t command,
+ uint32_t addr_len, uint32_t address,
+ uint8_t dummy_len,
+ uint8_t mosi_len, uint32_t mosi_data,
+ uint8_t miso_len);
+#else
IRAM_ATTR uint32_t bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
@@ -620,6 +857,7 @@ IRAM_ATTR uint32_t bootloader_flash_execute_command_common(
}
return ret;
}
+#endif
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
@@ -671,7 +909,7 @@ void bootloader_spi_flash_reset(void)
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
#define XMC_VENDOR_ID_1 0x20
-#if BOOTLOADER_BUILD
+#if NON_OS_BUILD
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_EARLY_LOG##level(TAG, ##__VA_ARGS__)
#else
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
@@ -787,7 +1025,7 @@ esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
bool IRAM_ATTR bootloader_flash_is_octal_mode_enabled(void)
{
-#if SOC_SPI_MEM_SUPPORT_OPI_MODE
+#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
return efuse_ll_get_flash_type();
#else
return false;
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c
index e50dcff..f1f6b6c 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -93,7 +93,7 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
// flash clock signal should come from IO MUX.
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
+ gpio_ll_func_sel(&GPIO, FLASH_CLK_IO, MSPI_FUNC_NUM);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
@@ -108,14 +108,14 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
esp_rom_gpio_connect_out_signal(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIQ_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPID_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIHD_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIWP_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_CS_IO, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
+ gpio_ll_func_sel(&GPIO, FLASH_CLK_IO, MSPI_FUNC_NUM);
// set drive ability for clock
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
uint32_t flash_id = g_rom_flashchip.device_id;
@@ -190,7 +190,7 @@ int bootloader_flash_get_wp_pin(void)
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302:
return ESP32_PICO_V3_GPIO;
default:
- return MSPI_IOMUX_PIN_NUM_WP;
+ return FLASH_SPIWP_IO;
}
#endif
}
@@ -207,7 +207,7 @@ void bootloader_configure_spi_pins(int drv)
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
// flash clock signal should come from IO MUX.
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
+ gpio_ll_func_sel(&GPIO, FLASH_CLK_IO, MSPI_FUNC_NUM);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
@@ -222,14 +222,14 @@ void bootloader_configure_spi_pins(int drv)
esp_rom_gpio_connect_out_signal(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIQ_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPID_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIHD_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_SPIWP_IO, PIN_FUNC_GPIO);
+ gpio_ll_func_sel(&GPIO, FLASH_CS_IO, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
+ gpio_ll_func_sel(&GPIO, FLASH_CLK_IO, MSPI_FUNC_NUM);
// set drive ability for clock
- gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
@@ -267,6 +267,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -345,6 +354,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -371,6 +389,10 @@ esp_err_t bootloader_init_spi_flash(void)
}
#endif
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
+
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c
index fa4f3c5..f7479ec 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -128,6 +128,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -204,6 +213,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -238,6 +256,9 @@ esp_err_t bootloader_init_spi_flash(void)
bootloader_init_flash_configure();
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c
index f537240..10b6496 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -139,6 +139,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -215,6 +224,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -247,6 +265,9 @@ esp_err_t bootloader_init_spi_flash(void)
#endif
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c
index a876c04..42dc2da 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -28,7 +28,8 @@
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
-#include "hal/mspi_timing_tuning_ll.h"
+#include "hal/mspi_ll.h"
+#include "bootloader_flash_override.h"
void bootloader_flash_update_id()
{
@@ -53,8 +54,9 @@ void IRAM_ATTR bootloader_init_mspi_clock(void)
// Set source mspi pll clock as 80M in bootloader stage.
// SPLL clock on C5 is 480MHz , and mspi_pll needs 80MHz
// in this stage, set divider as 6
- mspi_ll_clock_src_sel(MSPI_CLK_SRC_SPLL);
- mspi_ll_fast_set_hs_divider(6);
+ _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_SPLL);
+ // MSPI0 and MSPI1 share this core clock register, but only setting to MSPI0 register is valid
+ mspi_timing_ll_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
@@ -117,6 +119,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -193,6 +204,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -217,13 +237,26 @@ esp_err_t bootloader_init_spi_flash(void)
bootloader_init_mspi_clock();
bootloader_init_flash_configure();
+
+#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
+ // Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.
+ bootloader_spi_flash_reset();
+#endif
+
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
#endif
+#if CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
+ bootloader_flash_32bits_address_map_enable(bootloader_flash_get_spi_mode());
+#endif
+
print_flash_info(&bootloader_image_hdr);
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
@@ -292,6 +325,10 @@ void bootloader_flash_hardware_init(void)
bootloader_spi_flash_resume();
bootloader_flash_unlock();
+#if CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
+ bootloader_flash_32bits_address_map_enable(bootloader_flash_get_spi_mode());
+#endif
+
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
update_flash_config(&hdr);
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c
index 62ec882..2b71ea0 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -102,6 +102,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -178,6 +187,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -201,6 +219,9 @@ esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c
index 5cb2c24..ca8999a 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -24,7 +24,7 @@
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
-#include "hal/mspi_timing_tuning_ll.h"
+#include "hal/mspi_ll.h"
static const char *TAG __attribute__((unused)) = "boot.esp32c61";
@@ -51,8 +51,9 @@ void IRAM_ATTR bootloader_init_mspi_clock(void)
// Set source mspi pll clock as 80M in bootloader stage.
// SPLL clock on C61 is 480MHz , and mspi_pll needs 80MHz
// in this stage, set divider as 6
- mspi_ll_clock_src_sel(MSPI_CLK_SRC_SPLL);
- mspi_ll_fast_set_hs_divider(6);
+ _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_DEFAULT);
+ // MSPI0 and MSPI1 share this core clock register, but only setting to MSPI0 register is valid
+ mspi_timing_ll_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
@@ -114,6 +115,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -188,6 +198,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -211,7 +230,16 @@ esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_mspi_clock();
bootloader_init_flash_configure();
+
+#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
+ // Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.
+ bootloader_spi_flash_reset();
+#endif
+
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c
index b0f1ff4..4c79bb0 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -24,6 +24,7 @@
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
+#include "hal/mspi_ll.h"
#include "soc/pcr_reg.h"
void bootloader_flash_update_id()
@@ -87,7 +88,7 @@ void IRAM_ATTR bootloader_configure_spi_pins(int drv)
static void IRAM_ATTR bootloader_flash_clock_init(void)
{
// At this moment, BBPLL should be enabled, safe to switch MSPI clock source to PLL_F64M (default clock src) to raise speed
- REG_SET_FIELD(PCR_MSPI_CONF_REG, PCR_MSPI_CLK_SEL, 2);
+ _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_PLL_F64M);
}
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
@@ -109,6 +110,15 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
default:
size = 2;
}
@@ -185,6 +195,15 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
default:
str = "2MB";
break;
@@ -209,6 +228,9 @@ esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c
new file mode 100644
index 0000000..9a434c0
--- /dev/null
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c
@@ -0,0 +1,305 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdbool.h>
+#include <assert.h>
+#include "string.h"
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_rom_gpio.h"
+#include "flash_qio_mode.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_flash_priv.h"
+#include "bootloader_init.h"
+#include "hal/mmu_hal.h"
+#include "hal/cache_hal.h"
+#include "hal/cache_ll.h"
+#include "hal/mspi_ll.h"
+#include "soc/pcr_reg.h"
+
+static const char *TAG = "boot.esp32h21";
+
+void bootloader_flash_update_id()
+{
+ esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
+ chip->device_id = bootloader_read_flash_id();
+}
+
+void bootloader_flash_update_size(uint32_t size)
+{
+ rom_spiflash_legacy_data->chip.chip_size = size;
+}
+
+void IRAM_ATTR bootloader_flash_cs_timing_config()
+{
+ SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
+ SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
+ SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
+}
+
+void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
+{
+ uint32_t spi_clk_div = 0;
+ switch (pfhdr->spi_speed) {
+ case ESP_IMAGE_SPI_SPEED_DIV_1:
+ spi_clk_div = 1;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_2:
+ spi_clk_div = 2;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_3:
+ spi_clk_div = 3;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_4:
+ spi_clk_div = 4;
+ break;
+ default:
+ break;
+ }
+ esp_rom_spiflash_config_clk(spi_clk_div, 0);
+}
+
+void IRAM_ATTR bootloader_configure_spi_pins(int drv)
+{
+ uint8_t clk_gpio_num = MSPI_IOMUX_PIN_NUM_CLK;
+ uint8_t q_gpio_num = MSPI_IOMUX_PIN_NUM_MISO;
+ uint8_t d_gpio_num = MSPI_IOMUX_PIN_NUM_MOSI;
+ uint8_t cs0_gpio_num = MSPI_IOMUX_PIN_NUM_CS0;
+ uint8_t hd_gpio_num = MSPI_IOMUX_PIN_NUM_HD;
+ uint8_t wp_gpio_num = MSPI_IOMUX_PIN_NUM_WP;
+ esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
+}
+
+static void IRAM_ATTR bootloader_flash_clock_init(void)
+{
+ // At this moment, BBPLL should be enabled, safe to switch MSPI clock source to PLL_F64M (default clock src) to raise speed
+ _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_PLL_F64M);
+}
+
+static void update_flash_config(const esp_image_header_t *bootloader_hdr)
+{
+ uint32_t size;
+ switch (bootloader_hdr->spi_size) {
+ case ESP_IMAGE_FLASH_SIZE_1MB:
+ size = 1;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_2MB:
+ size = 2;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_4MB:
+ size = 4;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_8MB:
+ size = 8;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_16MB:
+ size = 16;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
+ default:
+ size = 2;
+ }
+ // Set flash chip size
+ esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode
+}
+
+static void print_flash_info(const esp_image_header_t *bootloader_hdr)
+{
+ ESP_EARLY_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
+ ESP_EARLY_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
+ ESP_EARLY_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
+ ESP_EARLY_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
+ ESP_EARLY_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
+
+ const char *str;
+ switch (bootloader_hdr->spi_speed) {
+ case ESP_IMAGE_SPI_SPEED_DIV_2:
+ str = "32MHz";
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_3:
+ str = "21.3MHz";
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_4:
+ str = "16MHz";
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_1:
+ str = "64MHz";
+ break;
+ default:
+ str = "16MHz";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Speed : %s", str);
+
+ /* SPI mode could have been set to QIO during boot already,
+ so test the SPI registers not the flash header */
+ esp_rom_spiflash_read_mode_t spi_mode = bootloader_flash_get_spi_mode();
+ switch (spi_mode) {
+ case ESP_ROM_SPIFLASH_QIO_MODE:
+ str = "QIO";
+ break;
+ case ESP_ROM_SPIFLASH_QOUT_MODE:
+ str = "QOUT";
+ break;
+ case ESP_ROM_SPIFLASH_DIO_MODE:
+ str = "DIO";
+ break;
+ case ESP_ROM_SPIFLASH_DOUT_MODE:
+ str = "DOUT";
+ break;
+ case ESP_ROM_SPIFLASH_FASTRD_MODE:
+ str = "FAST READ";
+ break;
+ default:
+ str = "SLOW READ";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Mode : %s", str);
+
+ switch (bootloader_hdr->spi_size) {
+ case ESP_IMAGE_FLASH_SIZE_1MB:
+ str = "1MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_2MB:
+ str = "2MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_4MB:
+ str = "4MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_8MB:
+ str = "8MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_16MB:
+ str = "16MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
+ default:
+ str = "2MB";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Flash Size : %s", str);
+}
+
+static void IRAM_ATTR bootloader_init_flash_configure(void)
+{
+ bootloader_flash_clock_init();
+ bootloader_configure_spi_pins(1);
+ bootloader_flash_cs_timing_config();
+}
+
+static void bootloader_spi_flash_resume(void)
+{
+ bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
+ esp_rom_spiflash_wait_idle(&g_rom_flashchip);
+}
+
+esp_err_t bootloader_init_spi_flash(void)
+{
+ bootloader_init_flash_configure();
+ bootloader_spi_flash_resume();
+ bootloader_flash_unlock();
+
+#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
+ bootloader_enable_qio_mode();
+#endif
+
+ print_flash_info(&bootloader_image_hdr);
+
+ cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ update_flash_config(&bootloader_image_hdr);
+ cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+
+ //ensure the flash is write-protected
+ bootloader_enable_wp();
+ return ESP_OK;
+}
+
+#if CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
+static void bootloader_flash_set_spi_mode(const esp_image_header_t* pfhdr)
+{
+ esp_rom_spiflash_read_mode_t mode;
+ switch(pfhdr->spi_mode) {
+ case ESP_IMAGE_SPI_MODE_QIO:
+ mode = ESP_ROM_SPIFLASH_QIO_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_QOUT:
+ mode = ESP_ROM_SPIFLASH_QOUT_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_DIO:
+ mode = ESP_ROM_SPIFLASH_DIO_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_FAST_READ:
+ mode = ESP_ROM_SPIFLASH_FASTRD_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_SLOW_READ:
+ mode = ESP_ROM_SPIFLASH_SLOWRD_MODE;
+ break;
+ default:
+ mode = ESP_ROM_SPIFLASH_DIO_MODE;
+ }
+ esp_rom_spiflash_config_readmode(mode);
+}
+
+void bootloader_flash_hardware_init(void)
+{
+ esp_rom_spiflash_attach(0, false);
+
+ //init cache hal
+ cache_hal_init();
+ //init mmu
+ mmu_hal_init();
+ // update flash ID
+ bootloader_flash_update_id();
+ // Check and run XMC startup flow
+ esp_err_t ret = bootloader_flash_xmc_startup();
+ assert(ret == ESP_OK);
+
+ /* Alternative of bootloader_init_spi_flash */
+ // RAM app doesn't have headers in the flash. Make a default one for it.
+ esp_image_header_t WORD_ALIGNED_ATTR hdr = {
+ .spi_mode = ESP_IMAGE_SPI_MODE_DIO,
+ .spi_speed = ESP_IMAGE_SPI_SPEED_DIV_2,
+ .spi_size = ESP_IMAGE_FLASH_SIZE_2MB,
+ };
+
+ bootloader_configure_spi_pins(1);
+ bootloader_flash_set_spi_mode(&hdr);
+ bootloader_flash_clock_config(&hdr);
+ bootloader_flash_clock_init();
+ bootloader_flash_cs_timing_config();
+
+ bootloader_spi_flash_resume();
+ bootloader_flash_unlock();
+
+ cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ update_flash_config(&hdr);
+ cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+
+ //ensure the flash is write-protected
+ bootloader_enable_wp();
+}
+#endif //CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c
new file mode 100644
index 0000000..d7b26a7
--- /dev/null
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c
@@ -0,0 +1,300 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdbool.h>
+#include <assert.h>
+#include "string.h"
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_rom_gpio.h"
+#include "esp_rom_efuse.h"
+#include "rom/spi_flash.h"
+#include "rom/efuse.h"
+#include "soc/efuse_reg.h"
+#include "soc/spi_mem_reg.h"
+#include "soc/soc_caps.h"
+#include "flash_qio_mode.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_common.h"
+#include "bootloader_flash_priv.h"
+#include "bootloader_init.h"
+#include "hal/mmu_hal.h"
+#include "hal/mmu_ll.h"
+#include "hal/cache_hal.h"
+#include "hal/cache_ll.h"
+
+static const char *TAG = "boot.esp32h4";
+
+void bootloader_flash_update_id()
+{
+ esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
+ chip->device_id = bootloader_read_flash_id();
+}
+
+void bootloader_flash_update_size(uint32_t size)
+{
+ rom_spiflash_legacy_data->chip.chip_size = size;
+}
+
+void IRAM_ATTR bootloader_flash_cs_timing_config()
+{
+ SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
+ SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
+ SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
+}
+
+void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
+{
+ uint32_t spi_clk_div = 0;
+ switch (pfhdr->spi_speed) {
+ case ESP_IMAGE_SPI_SPEED_DIV_1:
+ spi_clk_div = 1;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_2:
+ spi_clk_div = 2;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_3:
+ spi_clk_div = 3;
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_4:
+ spi_clk_div = 4;
+ break;
+ default:
+ break;
+ }
+ esp_rom_spiflash_config_clk(spi_clk_div, 0);
+}
+
+void IRAM_ATTR bootloader_configure_spi_pins(int drv)
+{
+ uint8_t clk_gpio_num = MSPI_IOMUX_PIN_NUM_CLK;
+ uint8_t q_gpio_num = MSPI_IOMUX_PIN_NUM_MISO;
+ uint8_t d_gpio_num = MSPI_IOMUX_PIN_NUM_MOSI;
+ uint8_t cs0_gpio_num = MSPI_IOMUX_PIN_NUM_CS0;
+ uint8_t hd_gpio_num = MSPI_IOMUX_PIN_NUM_HD;
+ uint8_t wp_gpio_num = MSPI_IOMUX_PIN_NUM_WP;
+ esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
+ esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
+}
+
+static void update_flash_config(const esp_image_header_t *bootloader_hdr)
+{
+ uint32_t size;
+ switch (bootloader_hdr->spi_size) {
+ case ESP_IMAGE_FLASH_SIZE_1MB:
+ size = 1;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_2MB:
+ size = 2;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_4MB:
+ size = 4;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_8MB:
+ size = 8;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_16MB:
+ size = 16;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ size = 32;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ size = 64;
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ size = 128;
+ break;
+ default:
+ size = 2;
+ }
+ // Set flash chip size
+ esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: [ESP32H4] IDF-12290 set mode
+}
+
+static void print_flash_info(const esp_image_header_t *bootloader_hdr)
+{
+ ESP_EARLY_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
+ ESP_EARLY_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
+ ESP_EARLY_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
+ ESP_EARLY_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
+ ESP_EARLY_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
+
+ const char *str;
+ switch (bootloader_hdr->spi_speed) {
+ case ESP_IMAGE_SPI_SPEED_DIV_2:
+ str = "32MHz";
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_4:
+ str = "16MHz";
+ break;
+ case ESP_IMAGE_SPI_SPEED_DIV_1:
+ str = "64MHz";
+ break;
+ default:
+ str = "16MHz";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Speed : %s", str);
+
+ /* SPI mode could have been set to QIO during boot already,
+ so test the SPI registers not the flash header */
+ esp_rom_spiflash_read_mode_t spi_mode = bootloader_flash_get_spi_mode();
+ switch (spi_mode) {
+ case ESP_ROM_SPIFLASH_QIO_MODE:
+ str = "QIO";
+ break;
+ case ESP_ROM_SPIFLASH_QOUT_MODE:
+ str = "QOUT";
+ break;
+ case ESP_ROM_SPIFLASH_DIO_MODE:
+ str = "DIO";
+ break;
+ case ESP_ROM_SPIFLASH_DOUT_MODE:
+ str = "DOUT";
+ break;
+ case ESP_ROM_SPIFLASH_FASTRD_MODE:
+ str = "FAST READ";
+ break;
+ default:
+ str = "SLOW READ";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Mode : %s", str);
+
+ switch (bootloader_hdr->spi_size) {
+ case ESP_IMAGE_FLASH_SIZE_1MB:
+ str = "1MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_2MB:
+ str = "2MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_4MB:
+ str = "4MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_8MB:
+ str = "8MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_16MB:
+ str = "16MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_32MB:
+ str = "32MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_64MB:
+ str = "64MB";
+ break;
+ case ESP_IMAGE_FLASH_SIZE_128MB:
+ str = "128MB";
+ break;
+ default:
+ str = "2MB";
+ break;
+ }
+ ESP_EARLY_LOGI(TAG, "SPI Flash Size : %s", str);
+}
+
+static void IRAM_ATTR bootloader_init_flash_configure(void)
+{
+ bootloader_configure_spi_pins(1);
+ bootloader_flash_cs_timing_config();
+}
+
+static void bootloader_spi_flash_resume(void)
+{
+ bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
+ esp_rom_spiflash_wait_idle(&g_rom_flashchip);
+}
+
+esp_err_t bootloader_init_spi_flash(void)
+{
+ bootloader_init_flash_configure();
+ bootloader_spi_flash_resume();
+ bootloader_flash_unlock();
+
+#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
+ bootloader_enable_qio_mode();
+#endif
+
+ print_flash_info(&bootloader_image_hdr);
+
+ cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ update_flash_config(&bootloader_image_hdr);
+ cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+
+ //ensure the flash is write-protected
+ bootloader_enable_wp();
+ return ESP_OK;
+}
+
+#if CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
+static void bootloader_flash_set_spi_mode(const esp_image_header_t* pfhdr)
+{
+ esp_rom_spiflash_read_mode_t mode;
+ switch(pfhdr->spi_mode) {
+ case ESP_IMAGE_SPI_MODE_QIO:
+ mode = ESP_ROM_SPIFLASH_QIO_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_QOUT:
+ mode = ESP_ROM_SPIFLASH_QOUT_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_DIO:
+ mode = ESP_ROM_SPIFLASH_DIO_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_FAST_READ:
+ mode = ESP_ROM_SPIFLASH_FASTRD_MODE;
+ break;
+ case ESP_IMAGE_SPI_MODE_SLOW_READ:
+ mode = ESP_ROM_SPIFLASH_SLOWRD_MODE;
+ break;
+ default:
+ mode = ESP_ROM_SPIFLASH_DIO_MODE;
+ }
+ esp_rom_spiflash_config_readmode(mode);
+}
+
+void bootloader_flash_hardware_init(void)
+{
+ esp_rom_spiflash_attach(0, false);
+
+ //init cache hal
+ cache_hal_init();
+ //init mmu
+ mmu_hal_init();
+ // update flash ID
+ bootloader_flash_update_id();
+ // Check and run XMC startup flow
+ esp_err_t ret = bootloader_flash_xmc_startup();
+ assert(ret == ESP_OK);
+
+ /* Alternative of bootloader_init_spi_flash */
+ // RAM app doesn't have headers in the flash. Make a default one for it.
+ esp_image_header_t WORD_ALIGNED_ATTR hdr = {
+ .spi_mode = ESP_IMAGE_SPI_MODE_DIO,
+ .spi_speed = ESP_IMAGE_SPI_SPEED_DIV_2,
+ .spi_size = ESP_IMAGE_FLASH_SIZE_2MB,
+ };
+
+ bootloader_configure_spi_pins(1);
+ bootloader_flash_set_spi_mode(&hdr);
+ bootloader_flash_clock_config(&hdr);
+ bootloader_flash_cs_timing_config();
+
+ bootloader_spi_flash_resume();
+ bootloader_flash_unlock();
+
+ cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+ update_flash_config(&hdr);
+ cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
+
+ //ensure the flash is write-protected
+ bootloader_enable_wp();
+}
+#endif //CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c
index 78a53b4..5457ea2 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,7 +19,7 @@
#include "bootloader_init.h"
#include "hal/mmu_hal.h"
#include "hal/mmu_ll.h"
-#include "hal/spimem_flash_ll.h"
+#include "hal/mspi_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "esp_private/bootloader_flash_internal.h"
@@ -44,8 +44,8 @@ void IRAM_ATTR bootloader_flash_cs_timing_config(void)
void IRAM_ATTR bootloader_init_mspi_clock(void)
{
- _spimem_flash_ll_select_clk_source(0, FLASH_CLK_SRC_SPLL);
- _spimem_ctrlr_ll_set_core_clock(0, 6);
+ _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_SPLL);
+ _mspi_timing_ll_set_flash_core_clock(0, 80);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
@@ -76,18 +76,19 @@ static const char *TAG = "boot.esp32p4";
void IRAM_ATTR bootloader_configure_spi_pins(int drv)
{
- uint8_t clk_gpio_num = MSPI_IOMUX_PIN_NUM_CLK;
- uint8_t q_gpio_num = MSPI_IOMUX_PIN_NUM_MISO;
- uint8_t d_gpio_num = MSPI_IOMUX_PIN_NUM_MOSI;
- uint8_t cs0_gpio_num = MSPI_IOMUX_PIN_NUM_CS0;
- uint8_t hd_gpio_num = MSPI_IOMUX_PIN_NUM_HD;
- uint8_t wp_gpio_num = MSPI_IOMUX_PIN_NUM_WP;
- esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
- esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
- esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
- esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
- esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
- esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
+ // Configure all Flash pins: clear pull-up/pull-down, set drive strength
+ // SPI CS is external pull-uped so there no need to set internal pull-up
+ mspi_ll_flash_pin_cfg_t flash_cfg = {
+ .hys = 0,
+ .ie = 0,
+ .wpu = 0,
+ .wpd = 0,
+ .drv = drv,
+ .reserved = 0
+ };
+ for (mspi_ll_flash_pin_id_t pin_id = MSPI_LL_PIN_ID_FLASH_CS; pin_id <= MSPI_LL_PIN_ID_FLASH_D; pin_id++) {
+ mspi_ll_set_flash_pin_cfg(pin_id, &flash_cfg);
+ }
}
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
@@ -224,8 +225,18 @@ static void bootloader_spi_flash_resume(void)
esp_err_t bootloader_init_spi_flash(void)
{
+ bootloader_init_mspi_clock();
bootloader_init_flash_configure();
+
+#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
+ // Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.
+ bootloader_spi_flash_reset();
+#endif
+
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c
index 0597826..9539e90 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c
@@ -262,6 +262,10 @@ esp_err_t bootloader_init_spi_flash(void)
}
#endif
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
+
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c
index 83b02ba..489f2e7 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c
@@ -286,6 +286,9 @@ esp_err_t bootloader_init_spi_flash(void)
#endif
bootloader_spi_flash_resume();
+ if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");
+ }
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
diff --git a/bootloader_components/bootloader_support/bootloader_flash/src/flash_qio_mode.c b/bootloader_components/bootloader_support/bootloader_flash/src/flash_qio_mode.c
index 957c2c3..039b3fb 100644
--- a/bootloader_components/bootloader_support/bootloader_flash/src/flash_qio_mode.c
+++ b/bootloader_components/bootloader_support/bootloader_flash/src/flash_qio_mode.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,6 +18,7 @@
#include "soc/efuse_periph.h"
#include "soc/io_mux_reg.h"
#include "esp_private/spi_flash_os.h"
+#include "bootloader_flash_override.h"
static const char *TAG = "qio_mode";
@@ -34,7 +35,7 @@ static const char *TAG = "qio_mode";
Searching of this table stops when the first match is found.
*/
-const bootloader_qio_info_t __attribute__((weak)) bootloader_flash_qe_support_list[] = {
+const DRAM_ATTR bootloader_qio_info_t __attribute__((weak)) bootloader_flash_qe_support_list_default[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, bootloader_read_status_8b_rdsr, bootloader_write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, bootloader_read_status_8b_rdsr, bootloader_write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
@@ -53,7 +54,9 @@ const bootloader_qio_info_t __attribute__((weak)) bootloader_flash_qe_support_li
{ NULL, 0xFF, 0xFFFF, 0xFFFF, bootloader_read_status_8b_rdsr2, bootloader_write_status_8b_wrsr2, 1 },
};
-#define NUM_CHIPS (sizeof(bootloader_flash_qe_support_list) / sizeof(bootloader_qio_info_t))
+const DRAM_ATTR bootloader_qio_info_t* bootloader_flash_qe_support_list __attribute__((weak)) = bootloader_flash_qe_support_list_default;
+
+uint8_t DRAM_ATTR __attribute__((weak)) bootloader_flash_qe_list_count = (sizeof(bootloader_flash_qe_support_list_default) / sizeof(bootloader_qio_info_t));
static esp_err_t enable_qio_mode(bootloader_flash_read_status_fn_t read_status_fn,
bootloader_flash_write_status_fn_t write_status_fn,
@@ -82,7 +85,11 @@ void bootloader_enable_qio_mode(void)
flash_id = raw_flash_id & 0xFFFF;
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
- for (i = 0; i < NUM_CHIPS - 1; i++) {
+ if ((intptr_t)bootloader_flash_qe_support_list != (intptr_t)bootloader_flash_qe_support_list_default) {
+ ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_qio, the list number is %d", bootloader_flash_qe_list_count);
+ }
+
+ for (i = 0; i < bootloader_flash_qe_list_count - 1; i++) {
const bootloader_qio_info_t *chip = &bootloader_flash_qe_support_list[i];
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", bootloader_flash_qe_support_list[i].manufacturer);
@@ -90,7 +97,7 @@ void bootloader_enable_qio_mode(void)
}
}
- if (i == NUM_CHIPS - 1) {
+ if (i == bootloader_flash_qe_list_count - 1) {
ESP_LOGI(TAG, "Enabling default flash chip QIO");
}
enable_qio_mode(bootloader_flash_qe_support_list[i].read_status_fn,
diff --git a/bootloader_components/bootloader_support/include/bootloader_common.h b/bootloader_components/bootloader_support/include/bootloader_common.h
index 4f819a1..ce678d1 100644
--- a/bootloader_components/bootloader_support/include/bootloader_common.h
+++ b/bootloader_components/bootloader_support/include/bootloader_common.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -24,6 +24,19 @@ typedef enum {
ESP_IMAGE_APPLICATION
} esp_image_type;
+/**
+ * @brief Check if the chip revision meets the image requirements.
+ *
+ * This function verifies whether the actual chip revision satisfies the minimum
+ * and optionally the maximum chip revision requirements specified in the image.
+ *
+ * @param image_header Pointer to the image header containing revision details.
+ * @param check_max_revision If true, also checks the maximum chip revision requirements.
+ *
+ * @return true if the chip revision meets the requirements, false otherwise.
+ */
+bool bootloader_common_check_chip_revision_validity(const esp_image_header_t *image_header, bool check_max_revision);
+
/**
* @brief Read ota_info partition and fill array from two otadata structures.
*
diff --git a/bootloader_components/bootloader_support/include/bootloader_memory_utils.h b/bootloader_components/bootloader_support/include/bootloader_memory_utils.h
index adbf72a..0e0f048 100644
--- a/bootloader_components/bootloader_support/include/bootloader_memory_utils.h
+++ b/bootloader_components/bootloader_support/include/bootloader_memory_utils.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -28,7 +28,21 @@ extern "C" {
*/
__attribute__((always_inline))
inline static bool esp_dram_match_iram(void) {
- return (SOC_DRAM_LOW == SOC_IRAM_LOW && SOC_DRAM_HIGH == SOC_IRAM_HIGH);
+ return ((SOC_DRAM_LOW == SOC_IRAM_LOW) && (SOC_DRAM_HIGH == SOC_IRAM_HIGH));
+}
+
+/**
+ * @brief Check if the RTC IRAM and RTC DRAM are separate or using the same memory space
+ *
+ * @return true if the RTC DRAM and RTC IRAM are sharing the same memory space, false otherwise
+ */
+__attribute__((always_inline))
+inline static bool esp_rtc_dram_match_rtc_iram(void) {
+#if SOC_RTC_FAST_MEM_SUPPORTED
+ return ((SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW) && (SOC_RTC_IRAM_HIGH == SOC_RTC_DRAM_HIGH));
+#else
+ return false;
+#endif
}
/**
@@ -82,6 +96,7 @@ __attribute__((always_inline))
inline static bool esp_ptr_in_diram_iram(const void *p) {
// TODO: IDF-5980 esp32c6 D/I RAM share the same address
#if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW
+ (void)p;
return false;
#else
return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
@@ -100,6 +115,7 @@ inline static bool esp_ptr_in_rtc_iram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED
return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
#else
+ (void)p;
return false;
#endif
}
@@ -116,6 +132,7 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) {
#if SOC_RTC_FAST_MEM_SUPPORTED
return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
#else
+ (void)p;
return false;
#endif
}
@@ -151,6 +168,21 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
#endif
}
+/* Convert a RTC DRAM pointer to equivalent word address in RTC IRAM
+
+ - Address must be word aligned
+ - Address must pass esp_ptr_in_rtc_dram_fast() test, or result will be invalid pointer
+*/
+__attribute__((always_inline))
+inline static void * esp_ptr_rtc_dram_to_iram(const void *p) {
+ intptr_t ptr = (intptr_t)p;
+#if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
+ return (void *) ( SOC_RTC_IRAM_LOW + (ptr - SOC_RTC_DRAM_LOW) );
+#else
+ return (void *) ptr;
+#endif
+}
+
/* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
- Address must be word aligned
diff --git a/bootloader_components/bootloader_support/include/bootloader_utility_tee.h b/bootloader_components/bootloader_support/include/bootloader_utility_tee.h
new file mode 100644
index 0000000..893d673
--- /dev/null
+++ b/bootloader_components/bootloader_support/include/bootloader_utility_tee.h
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include "esp_flash_partitions.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Fetch the currently running TEE partition
+ *
+ * @param[in] tee_ota_info TEE OTA data partition
+ *
+ * @return Subtype of the running TEE partition, or -1 if an error occurred
+ */
+int bootloader_utility_tee_get_boot_partition(const esp_partition_pos_t *tee_ota_info);
+
+/**
+ * @brief Set a new TEE boot partition in the TEE OTA data
+ *
+ * @param[in] tee_ota_info TEE OTA data partition
+ * @param[in] tee_try_part Partition table entry for the new boot partition
+ *
+ * @return ESP_OK on success, or an error code otherwise
+ */
+esp_err_t bootloader_utility_tee_set_boot_partition(const esp_partition_pos_t *tee_ota_info, const esp_partition_info_t *tee_try_part);
+
+/**
+ * @brief Fetch the next TEE partition for update
+ *
+ * @param[in] tee_ota_info TEE OTA data partition
+ *
+ * @return Subtype of the next TEE partition for update, or -1 if an error occurred
+ */
+int bootloader_utility_tee_get_next_update_partition(const esp_partition_pos_t *tee_ota_info);
+
+/**
+ * @brief Mark the current TEE app as valid and cancel update rollback
+ *
+ * @param[in] tee_ota_info TEE OTA data partition
+ *
+ * @return ESP_OK on success, or an error code otherwise
+ */
+esp_err_t bootloader_utility_tee_mark_app_valid_and_cancel_rollback(const esp_partition_pos_t *tee_ota_info);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bootloader_components/bootloader_support/include/esp_app_format.h b/bootloader_components/bootloader_support/include/esp_app_format.h
index 18d5b13..7eeeeda 100644
--- a/bootloader_components/bootloader_support/include/esp_app_format.h
+++ b/bootloader_components/bootloader_support/include/esp_app_format.h
@@ -26,6 +26,9 @@ typedef enum {
ESP_CHIP_ID_ESP32H2 = 0x0010, /*!< chip ID: ESP32-H2 */
ESP_CHIP_ID_ESP32P4 = 0x0012, /*!< chip ID: ESP32-P4 */
ESP_CHIP_ID_ESP32C5 = 0x0017, /*!< chip ID: ESP32-C5 */
+ ESP_CHIP_ID_ESP32C61= 0x0014, /*!< chip ID: ESP32-C61 */
+ ESP_CHIP_ID_ESP32H21= 0x0019, /*!< chip ID: ESP32-H21 */
+ ESP_CHIP_ID_ESP32H4 = 0x001C, /*!< chip ID: ESP32-H4 */
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
} __attribute__((packed)) esp_chip_id_t;
diff --git a/bootloader_components/bootloader_support/include/esp_flash_encrypt.h b/bootloader_components/bootloader_support/include/esp_flash_encrypt.h
index efc061e..e814574 100644
--- a/bootloader_components/bootloader_support/include/esp_flash_encrypt.h
+++ b/bootloader_components/bootloader_support/include/esp_flash_encrypt.h
@@ -215,6 +215,10 @@ bool esp_flash_encryption_cfg_verify_release_mode(void);
* It burns:
* - "disable encrypt in dl mode"
* - set FLASH_CRYPT_CNT efuse to max
+ *
+ * In case of the targets that support the XTS-AES peripheral's pseudo rounds function,
+ * this API would configure the pseudo rounds level efuse bit to level low if the efuse bit
+ * is not set already.
*/
void esp_flash_encryption_set_release_mode(void);
diff --git a/bootloader_components/bootloader_support/include/esp_flash_partitions.h b/bootloader_components/bootloader_support/include/esp_flash_partitions.h
index d05ded6..d50fd48 100644
--- a/bootloader_components/bootloader_support/include/esp_flash_partitions.h
+++ b/bootloader_components/bootloader_support/include/esp_flash_partitions.h
@@ -21,6 +21,8 @@ extern "C" {
#define PART_SUBTYPE_OTA_FLAG 0x10
#define PART_SUBTYPE_OTA_MASK 0x0f
#define PART_SUBTYPE_TEST 0x20
+#define PART_SUBTYPE_TEE_0 0x30
+#define PART_SUBTYPE_TEE_1 0x31
#define PART_TYPE_DATA 0x01
#define PART_SUBTYPE_DATA_OTA 0x00
@@ -32,11 +34,14 @@ extern "C" {
#define PART_TYPE_BOOTLOADER 0x02
#define PART_SUBTYPE_BOOTLOADER_PRIMARY 0x00
#define PART_SUBTYPE_BOOTLOADER_OTA 0x01
+#define PART_SUBTYPE_BOOTLOADER_RECOVERY 0x02
#define PART_TYPE_PARTITION_TABLE 0x03
#define PART_SUBTYPE_PARTITION_TABLE_PRIMARY 0x00
#define PART_SUBTYPE_PARTITION_TABLE_OTA 0x01
+#define PART_SUBTYPE_DATA_TEE_OTA 0x90
+
#define PART_TYPE_END 0xff
#define PART_SUBTYPE_END 0xff
diff --git a/bootloader_components/bootloader_support/include/esp_image_format.h b/bootloader_components/bootloader_support/include/esp_image_format.h
index 4cc4ba0..77f0f23 100644
--- a/bootloader_components/bootloader_support/include/esp_image_format.h
+++ b/bootloader_components/bootloader_support/include/esp_image_format.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -87,12 +87,12 @@ ESP_STATIC_ASSERT(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reser
#endif // CONFIG_BOOTLOADER_RESERVE_RTC_MEM
/**
- * @brief Verify an app image.
+ * @brief Verify an app/bootloader image.
*
* If encryption is enabled, data will be transparently decrypted.
*
* @param mode Mode of operation (verify, silent verify, or load).
- * @param part Partition to load the app from.
+ * @param part Partition to load the app/bootloader from.
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function.
* 'start_addr' member should be set (to the start address of the image.)
* Other fields will all be initialised by this function.
@@ -114,11 +114,11 @@ ESP_STATIC_ASSERT(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reser
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data);
/**
- * @brief Get metadata of app
+ * @brief Get metadata of app/bootloader
*
* If encryption is enabled, data will be transparently decrypted.
*
- * @param part Partition to load the app from.
+ * @param part Partition to load the app/bootloader from.
* @param[out] metadata Pointer to the image metadata structure which is be filled in by this function.
* Fields will all be initialised by this function.
*
@@ -172,7 +172,7 @@ esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metad
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data);
/**
- * @brief Verify the bootloader image.
+ * @brief Verify the PRIMARY bootloader image.
*
* @param[out] If result is ESP_OK and this pointer is non-NULL, it
* will be set to the length of the bootloader image.
@@ -182,7 +182,7 @@ esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_i
esp_err_t esp_image_verify_bootloader(uint32_t *length);
/**
- * @brief Verify the bootloader image.
+ * @brief Verify the PRIMARY bootloader image.
*
* @param[out] Metadata for the image. Only valid if result is ESP_OK.
*
@@ -198,6 +198,25 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data);
*/
int esp_image_get_flash_size(esp_image_flash_size_t app_flash_size);
+/**
+ * @brief Get the ota bootloader offset
+ *
+ * The esp_image_verify functions use the offset to distinguish between application and bootloader verifications.
+ * The application must set the OTA bootloader offset before running any verification functions for the OTA bootloader partition.
+ *
+ * @return ota Bootloader offset. UINT32_MAX - not set.
+ */
+uint32_t esp_image_bootloader_offset_get(void);
+
+/**
+ * @brief Set the ota bootloader offset
+ *
+ * The esp_image_verify functions use the offset to distinguish between application and bootloader verifications.
+ * The application must set the OTA bootloader offset before running any verification functions for the OTA bootloader partition.
+ *
+ * @param offset ota Bootloader offset
+ */
+void esp_image_bootloader_offset_set(const uint32_t offset);
typedef struct {
uint32_t drom_addr;
diff --git a/bootloader_components/bootloader_support/include/esp_secure_boot.h b/bootloader_components/bootloader_support/include/esp_secure_boot.h
index 84cb241..4b7294d 100644
--- a/bootloader_components/bootloader_support/include/esp_secure_boot.h
+++ b/bootloader_components/bootloader_support/include/esp_secure_boot.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,29 +14,9 @@
#include "sdkconfig.h"
#include "esp_rom_crc.h"
#include "hal/efuse_ll.h"
-
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C2
-#include "esp32c2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C6
-#include "esp32c6/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32H2
-#include "esp32h2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32P4
-#include "esp32p4/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C5
-#include "esp32c5/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C61
-#include "esp32c61/rom/secure_boot.h"
+#if !CONFIG_IDF_TARGET_LINUX
+#include "rom/secure_boot.h"
#endif
-
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
#error "internal sdkconfig error, secure boot should always enable all signature options"
@@ -52,12 +32,20 @@ extern "C" {
Can be compiled as part of app or bootloader code.
*/
+#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
+#define ESP_SECURE_BOOT_DIGEST_LEN 48
+#else /* !CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
#define ESP_SECURE_BOOT_DIGEST_LEN 32
+#endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */
+/* SHA-256 length of the public key digest */
+#define ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN 32
+
+/* Length of the public key digest that is stored in efuses */
#if CONFIG_IDF_TARGET_ESP32C2
-#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 16
+#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN / 2
#else
-#define ESP_SECURE_BOOT_KEY_DIGEST_LEN 32
+#define ESP_SECURE_BOOT_KEY_DIGEST_LEN ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN
#endif
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@@ -212,7 +200,8 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
/** @brief Verify the secure boot signature appended to some binary data in flash.
*
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
- * For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
+ * For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image digest
+ * For ECDSA Scheme (Secure Boot V2) - ECDSA Verification of the SHA-256 / SHA-384 (in case of ECDSA-P384 secure boot key) image digest
*
* Public key is compiled into the calling program in the ECDSA Scheme.
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
@@ -236,6 +225,23 @@ typedef struct {
uint8_t signature[64];
} esp_secure_boot_sig_block_t;
+/** @brief Get the size of the secure boot signature block
+ *
+ * This is the size of the signature block appended to a signed image.
+ *
+ * @return Size of the secure boot signature block in bytes
+ */
+static inline uint32_t esp_secure_boot_sig_block_size(void)
+{
+#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
+ return sizeof(ets_secure_boot_signature_t);
+#elif defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
+ return sizeof(esp_secure_boot_sig_block_t);
+#else
+ return 0;
+#endif
+}
+
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
*
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
@@ -255,13 +261,13 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
/** @brief Verify the secure boot signature block for Secure Boot V2.
*
- * Performs RSA-PSS or ECDSA verification of the SHA-256 image based on the public key
+ * Performs RSA-PSS or ECDSA verification of the SHA-256 / SHA-384 image based on the public key
* in the signature block, compared against the public key digest stored in efuse.
*
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
* @param[in] sig_block Pointer to signature block data
- * @param[in] image_digest Pointer to 32 byte buffer holding SHA-256 hash.
- * @param[out] verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
+ * @param[in] image_digest Pointer to 32/48 byte buffer holding SHA-256/SHA-384 hash.
+ * @param[out] verified_digest Pointer to 32/48 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
*
*/
esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
@@ -274,7 +280,7 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
* Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key.
*/
typedef struct {
- uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */
+ uint8_t key_digests[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS][ESP_SECURE_BOOT_KEY_DIGEST_SHA_256_LEN]; /* SHA of the public key components in the signature block */
unsigned num_digests; /* Number of valid digests, starting at index 0 */
} esp_image_sig_public_key_digests_t;
diff --git a/bootloader_components/bootloader_support/include/esp_tee_ota_utils.h b/bootloader_components/bootloader_support/include/esp_tee_ota_utils.h
new file mode 100644
index 0000000..cb703a1
--- /dev/null
+++ b/bootloader_components/bootloader_support/include/esp_tee_ota_utils.h
@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdint.h>
+
+#include "esp_err.h"
+#include "esp_flash_partitions.h"
+#include "esp_image_format.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TEE otadata magic is derived from sha256 of "tee_ota" string
+#define TEE_OTADATA_MAGIC 0x4337e1e1
+
+/* TEE OTA selection structure (two copies in the TEE OTA data partition) */
+typedef struct {
+ uint32_t magic; // A magic byte for otadata structure
+ uint8_t version; // OTA image version
+ uint8_t boot_partition; // Default boot partition
+ uint8_t ota_state; // OTA_DATA states for checking operability of the app
+ uint8_t reserved_1; // Reserved field 1
+ uint32_t reserved_2[5]; // Reserved fields 2
+ uint32_t crc; // CRC32 of all fields in the structure
+} __attribute__((packed)) esp_tee_ota_select_entry_t;
+
+ESP_STATIC_ASSERT(offsetof(esp_tee_ota_select_entry_t, crc) == sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t));
+
+// OTA_DATA states for checking operability of the app.
+typedef enum {
+ ESP_TEE_OTA_IMG_NEW = 0x00U, /*!< Monitor the first boot - the bootloader changes the state to PENDING_VERIFY. */
+ ESP_TEE_OTA_IMG_PENDING_VERIFY = 0x33U, /*!< If encountered during the second boot, the bootloader changes the state to INVALID. */
+ ESP_TEE_OTA_IMG_INVALID = 0x55U, /*!< App was confirmed as workable - can boot and work without limits. */
+ ESP_TEE_OTA_IMG_VALID = 0xAAU, /*!< App was confirmed as non-workable - will not selected to boot at all. */
+ ESP_TEE_OTA_IMG_UNDEFINED = 0xFFU, /*!< Undefined. */
+} esp_tee_ota_img_states_t;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_config.h b/bootloader_components/bootloader_support/private_include/bootloader_config.h
index ef283b1..cce4ba2 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_config.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_config.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -21,11 +21,16 @@ extern "C"
#define SPI_ERROR_LOG "spi flash error"
#define MAX_OTA_SLOTS 16
+#define MAX_TEE_OTA_SLOTS 2
typedef struct {
esp_partition_pos_t ota_info;
esp_partition_pos_t factory;
esp_partition_pos_t test;
+#if CONFIG_SECURE_ENABLE_TEE
+ esp_partition_pos_t tee_ota_info;
+ esp_partition_pos_t tee[MAX_TEE_OTA_SLOTS];
+#endif
esp_partition_pos_t ota[MAX_OTA_SLOTS];
uint32_t app_count;
uint32_t selected_subtype;
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_init.h b/bootloader_components/bootloader_support/private_include/bootloader_init.h
index 7246437..4dfc2d5 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_init.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_init.h
@@ -51,6 +51,7 @@ void bootloader_print_banner(void);
* @return ESP_OK - If the setting is successful.
* ESP_FAIL - If the setting is not successful.
+ * ESP_ERR_NOT_SUPPORTED - If selected secure boot scheme is not supported.
*/
esp_err_t bootloader_init(void);
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_sha.h b/bootloader_components/bootloader_support/private_include/bootloader_sha.h
index 09b5694..b4eec76 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_sha.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_sha.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,15 +12,18 @@
Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps.
*/
+#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "esp_err.h"
+#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *bootloader_sha256_handle_t;
+typedef bootloader_sha256_handle_t bootloader_sha_handle_t;
bootloader_sha256_handle_t bootloader_sha256_start(void);
@@ -28,6 +31,14 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data,
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest);
+#if SOC_SHA_SUPPORT_SHA512
+bootloader_sha_handle_t bootloader_sha512_start(bool is384);
+
+void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len);
+
+void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest);
+#endif /* SOC_SHA_SUPPORT_SHA512 */
+
#ifdef __cplusplus
}
#endif
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_signature.h b/bootloader_components/bootloader_support/private_include/bootloader_signature.h
index f101b42..2ade78b 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_signature.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_signature.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,28 +8,7 @@
#include "sdkconfig.h"
#include <esp_err.h>
#include <stdint.h>
-
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C2
-#include "esp32c2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C6
-#include "esp32c6/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32H2
-#include "esp32h2/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32P4
-#include "esp32p4/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C5
-#include "esp32c5/rom/secure_boot.h"
-#elif CONFIG_IDF_TARGET_ESP32C61
-#include "esp32c61/rom/secure_boot.h"
-#endif
+#include "rom/secure_boot.h"
#ifdef __cplusplus
extern "C" {
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_soc.h b/bootloader_components/bootloader_support/private_include/bootloader_soc.h
index acce77c..d701f87 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_soc.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_soc.h
@@ -25,12 +25,11 @@ void bootloader_ana_super_wdt_reset_config(bool enable);
void bootloader_ana_clock_glitch_reset_config(bool enable);
/**
- * @brief Configure analog power glitch reset & glitch reset dref
+ * @brief Configure analog power glitch reset
*
* @param enable Boolean to enable or disable power glitch reset
- * @param dref voltage threshold
*/
-void bootloader_power_glitch_reset_config(bool enable, uint8_t dref);
+void bootloader_power_glitch_reset_config(bool enable);
#ifdef __cplusplus
}
diff --git a/bootloader_components/bootloader_support/private_include/bootloader_utility.h b/bootloader_components/bootloader_support/private_include/bootloader_utility.h
index 94040cf..d8ed646 100644
--- a/bootloader_components/bootloader_support/private_include/bootloader_utility.h
+++ b/bootloader_components/bootloader_support/private_include/bootloader_utility.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -38,6 +38,13 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs);
*/
int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs);
+/**
+ * @brief Load and verify the TEE image from the selected partition
+ *
+ * @param bs Bootloader state structure
+ */
+void bootloader_utility_load_tee_image(const bootloader_state_t *bs);
+
/**
* @brief Load the selected partition and start application.
*
@@ -131,6 +138,20 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
*/
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
+/** @brief Generates the digest of the data between offset & offset+length.
+ *
+ * This function should be used when the size of the data is larger than 3.2MB.
+ * The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-384
+ * of the data in chunks of 3.2MB, considering the MMU capacity.
+ *
+ * @param[in] flash_offset Offset of the data in flash.
+ * @param[in] len Length of data in bytes.
+ * @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
+ *
+ * @return ESP_OK if secure boot digest is generated successfully.
+ */
+esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
+
#ifdef __cplusplus
}
#endif
diff --git a/bootloader_components/bootloader_support/src/bootloader_clock_init.c b/bootloader_components/bootloader_support/src/bootloader_clock_init.c
index 8099aa4..ecabcec 100644
--- a/bootloader_components/bootloader_support/src/bootloader_clock_init.c
+++ b/bootloader_components/bootloader_support/src/bootloader_clock_init.c
@@ -9,7 +9,7 @@
#include "soc/chip_revision.h"
#include "hal/efuse_hal.h"
-#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 &&! CONFIG_IDF_TARGET_ESP32C61 // TODO: IDF-5645
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO: IDF-5645
#include "soc/rtc_cntl_reg.h"
#else
#include "soc/lp_wdt_reg.h"
@@ -34,7 +34,11 @@ __attribute__((weak)) void bootloader_clock_configure(void)
esp_rom_output_tx_wait_idle(0);
/* Set CPU to a higher certain frequency. Keep other clocks unmodified. */
+#if CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
+ int cpu_freq_mhz = 100;
+#else
int cpu_freq_mhz = CPU_CLK_FREQ_MHZ_BTLD;
+#endif
#if CONFIG_IDF_TARGET_ESP32
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
@@ -64,7 +68,7 @@ __attribute__((weak)) void bootloader_clock_configure(void)
// RTC_FAST clock source will be switched to RC_FAST at application startup
clk_cfg.fast_clk_src = rtc_clk_fast_src_get();
if (clk_cfg.fast_clk_src == SOC_RTC_FAST_CLK_SRC_INVALID) {
- clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_XTAL_DIV;
+ clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_DEFAULT;
}
#if CONFIG_IDF_TARGET_ESP32C6
@@ -100,14 +104,12 @@ __attribute__((weak)) void bootloader_clock_configure(void)
#endif
// CLR ENA
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
- CLEAR_PERI_REG_MASK(LP_TIMER_LP_INT_ENA_REG, LP_TIMER_MAIN_TIMER_LP_INT_ENA); /* MAIN_TIMER */
CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_ENA_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
// SET CLR
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
- SET_PERI_REG_MASK(LP_TIMER_LP_INT_CLR_REG, LP_TIMER_MAIN_TIMER_LP_INT_CLR); /* MAIN_TIMER */
SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
#elif CONFIG_IDF_TARGET_ESP32H2
@@ -123,17 +125,43 @@ __attribute__((weak)) void bootloader_clock_configure(void)
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */
+#elif CONFIG_IDF_TARGET_ESP32H21
+ // CLR ENA
+ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
+ CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
+ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
+ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
+ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
+ // SET CLR
+ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
+ SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */
+ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
+ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
+ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR);
+#elif CONFIG_IDF_TARGET_ESP32H4
+ // CLR ENA
+ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
+ // TODO [ESP32H4] IDF-12295
+ // CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
+ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
+ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
+ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
+ // SET CLR
+ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
+ // TODO [ESP32H4] IDF-12295
+ // SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */
+ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
+ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
+ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR);
#elif CONFIG_IDF_TARGET_ESP32P4
// CLR ENA
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
- CLEAR_PERI_REG_MASK(LP_TIMER_LP_INT_ENA_REG, LP_TIMER_MAIN_TIMER_LP_INT_ENA); /* MAIN_TIMER */
CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_INT_ENA_REG, LP_ANALOG_PERI_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
// SET CLR
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
- SET_PERI_REG_MASK(LP_TIMER_LP_INT_CLR_REG, LP_TIMER_MAIN_TIMER_LP_INT_CLR); /* MAIN_TIMER */
SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_INT_CLR_REG); /* BROWN_OUT */
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
#else
diff --git a/bootloader_components/bootloader_support/src/bootloader_common.c b/bootloader_components/bootloader_support/src/bootloader_common.c
index e37a5b4..759263e 100644
--- a/bootloader_components/bootloader_support/src/bootloader_common.c
+++ b/bootloader_components/bootloader_support/src/bootloader_common.c
@@ -140,13 +140,13 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
return ret;
}
-esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t size, int type, uint8_t *out_sha_256)
+esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256)
{
if (out_sha_256 == NULL || size == 0) {
return ESP_ERR_INVALID_ARG;
}
- if (type == PART_TYPE_APP) {
+ if (type == PART_TYPE_APP || type == PART_TYPE_BOOTLOADER) {
const esp_partition_pos_t partition_pos = {
.offset = address,
.size = size,
diff --git a/bootloader_components/bootloader_support/src/bootloader_common_loader.c b/bootloader_components/bootloader_support/src/bootloader_common_loader.c
index 2d29ac6..058037d 100644
--- a/bootloader_components/bootloader_support/src/bootloader_common_loader.c
+++ b/bootloader_components/bootloader_support/src/bootloader_common_loader.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,6 +12,9 @@
#include "esp_rom_crc.h"
#include "esp_rom_gpio.h"
#include "esp_flash_partitions.h"
+#if CONFIG_SECURE_BOOT
+#include "esp_secure_boot.h"
+#endif
#include "bootloader_flash.h"
#include "bootloader_common.h"
#include "soc/gpio_periph.h"
@@ -28,9 +31,41 @@
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
#define IS_FIELD_SET(rev_full) (((rev_full) != 65535) && ((rev_full) != 0))
+#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
static const char* TAG = "boot_comm";
+bool bootloader_common_check_chip_revision_validity(const esp_image_header_t *img_hdr, bool check_max_revision)
+{
+ if (!img_hdr) {
+ return false;
+ }
+
+ unsigned revision = efuse_hal_chip_revision();
+ unsigned min_rev = img_hdr->min_chip_rev_full;
+
+ bool is_min_rev_invalid = !ESP_CHIP_REV_ABOVE(revision, min_rev);
+ if (is_min_rev_invalid) {
+ ESP_LOGE(TAG, "chip revision check failed. Required >= v%d.%d, found v%d.%d.",
+ min_rev / 100, min_rev % 100,
+ revision / 100, revision % 100);
+ return false;
+ }
+
+ if (check_max_revision) {
+ unsigned int max_rev = img_hdr->max_chip_rev_full;
+ bool is_max_rev_invalid = IS_FIELD_SET(max_rev) && revision > max_rev && !efuse_hal_get_disable_wafer_version_major();
+ if (is_max_rev_invalid) {
+ ESP_LOGE(TAG, "chip revision check failed. Required <= v%d.%d, found v%d.%d.",
+ max_rev / 100, max_rev % 100,
+ revision / 100, revision % 100);
+ return false;
+ }
+ }
+
+ return true;
+}
+
uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s)
{
return esp_rom_crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4);
@@ -91,24 +126,15 @@ esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hd
err = ESP_FAIL;
} else {
#ifndef CONFIG_IDF_ENV_FPGA
- unsigned revision = efuse_hal_chip_revision();
- unsigned int major_rev = revision / 100;
- unsigned int minor_rev = revision % 100;
- unsigned min_rev = img_hdr->min_chip_rev_full;
- if (type == ESP_IMAGE_BOOTLOADER || type == ESP_IMAGE_APPLICATION) {
- if (!ESP_CHIP_REV_ABOVE(revision, min_rev)) {
- ESP_LOGE(TAG, "Image requires chip rev >= v%d.%d, but chip is v%d.%d",
- min_rev / 100, min_rev % 100,
- major_rev, minor_rev);
+ if (type == ESP_IMAGE_APPLICATION) {
+ if (!bootloader_common_check_chip_revision_validity(img_hdr, true)) {
err = ESP_FAIL;
}
}
- if (type == ESP_IMAGE_APPLICATION) {
- unsigned max_rev = img_hdr->max_chip_rev_full;
- if ((IS_FIELD_SET(max_rev) && (revision > max_rev) && !efuse_hal_get_disable_wafer_version_major())) {
- ESP_LOGE(TAG, "Image requires chip rev <= v%d.%d, but chip is v%d.%d",
- max_rev / 100, max_rev % 100,
- major_rev, minor_rev);
+
+ // Maximum revision check is skipped for bootloader images
+ if (type == ESP_IMAGE_BOOTLOADER) {
+ if (!bootloader_common_check_chip_revision_validity(img_hdr, false)) {
err = ESP_FAIL;
}
}
@@ -240,11 +266,23 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
#ifdef BOOTLOADER_BUILD
#if ESP_ROM_HAS_LP_ROM
+#if CONFIG_IDF_TARGET_ESP32P4
+ #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW + CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE)
+#else
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW)
+#endif
#else
- #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t))
+ /* Since the structure containing the retain_mem_t is aligned on 8 by the linker, make sure we align this
+ * structure size here too */
+ #define RETAIN_MEM_SIZE ALIGN_UP(sizeof(rtc_retain_mem_t), 8)
+ #define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - RETAIN_MEM_SIZE)
#endif //ESP_ROM_HAS_LP_ROM
+
+#if CONFIG_SECURE_BOOT && ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP
+ static rtc_retain_mem_t *const s_bootloader_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR - ESP_SECURE_BOOT_DIGEST_LEN;
+#else
static rtc_retain_mem_t *const s_bootloader_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;
+#endif
return s_bootloader_retain_mem;
#else
static __attribute__((section(".bootloader_data_rtc_mem"))) rtc_retain_mem_t s_bootloader_retain_mem;
diff --git a/bootloader_components/bootloader_support/src/bootloader_console.c b/bootloader_components/bootloader_support/src/bootloader_console.c
index eb83ae8..e5769d7 100644
--- a/bootloader_components/bootloader_support/src/bootloader_console.c
+++ b/bootloader_components/bootloader_support/src/bootloader_console.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,7 +10,6 @@
#include "soc/uart_periph.h"
#include "soc/uart_channel.h"
#include "soc/io_mux_reg.h"
-#include "soc/gpio_periph.h"
#include "soc/gpio_sig_map.h"
#include "soc/rtc.h"
#include "hal/gpio_ll.h"
@@ -26,9 +25,21 @@
#include "esp_rom_sys.h"
#include "esp_rom_caps.h"
+static void __attribute__((unused)) release_default_console_io(void)
+{
+ // Default console is UART0 with TX and RX on their IOMUX pins
+ gpio_ll_output_disable(&GPIO, UART_NUM_0_TXD_DIRECT_GPIO_NUM);
+ gpio_ll_func_sel(&GPIO, U0TXD_GPIO_NUM, PIN_FUNC_GPIO); // Set TX pin to GPIO function to truly disable output
+ esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(UART_NUM_0, SOC_UART_RX_PIN_IDX), 0);
+}
+
#ifdef CONFIG_ESP_CONSOLE_NONE
void bootloader_console_init(void)
{
+ // Wait for UART FIFO to be empty.
+ esp_rom_output_tx_wait_idle(0);
+ release_default_console_io();
+
esp_rom_install_channel_putc(1, NULL);
esp_rom_install_channel_putc(2, NULL);
}
@@ -59,9 +70,7 @@ void bootloader_console_init(void)
if (uart_num != 0 ||
uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM ||
uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) {
- // Change default UART pins back to GPIOs
- gpio_ll_func_sel(&GPIO, UART_NUM_0_RXD_DIRECT_GPIO_NUM, PIN_FUNC_GPIO);
- gpio_ll_func_sel(&GPIO, UART_NUM_0_TXD_DIRECT_GPIO_NUM, PIN_FUNC_GPIO);
+ release_default_console_io();
// Route GPIO signals to/from pins
const uint32_t tx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX);
const uint32_t rx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX);
@@ -101,6 +110,10 @@ static char s_usb_cdc_buf[ESP_ROM_CDC_ACM_WORK_BUF_MIN];
void bootloader_console_init(void)
{
+ // Wait for UART FIFO to be empty.
+ esp_rom_output_tx_wait_idle(0);
+ release_default_console_io();
+
#ifdef CONFIG_IDF_TARGET_ESP32S2
/* ESP32-S2 specific patch to set the correct serial number in the descriptor.
* Later chips don't need this.
@@ -120,6 +133,10 @@ void bootloader_console_init(void)
#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
void bootloader_console_init(void)
{
+ // Wait for UART FIFO to be empty.
+ esp_rom_output_tx_wait_idle(0);
+ release_default_console_io();
+
esp_rom_output_switch_buffer(ESP_ROM_USB_SERIAL_DEVICE_NUM);
/* Switch console channel to avoid output on UART and allow */
diff --git a/bootloader_components/bootloader_support/src/bootloader_efuse.c b/bootloader_components/bootloader_support/src/bootloader_efuse.c
index 8d5fade..af5ca63 100644
--- a/bootloader_components/bootloader_support/src/bootloader_efuse.c
+++ b/bootloader_components/bootloader_support/src/bootloader_efuse.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,6 +18,7 @@ IRAM_ATTR uint32_t bootloader_common_get_chip_ver_pkg(void)
int bootloader_clock_get_rated_freq_mhz(void)
{
+ //TODO: IDF-6570, need refactor
#ifdef CONFIG_IDF_TARGET_ESP32
return efuse_hal_get_rated_freq_mhz();
@@ -40,6 +41,14 @@ int bootloader_clock_get_rated_freq_mhz(void)
//IDF-6570
return 96;
+#elif CONFIG_IDF_TARGET_ESP32H21
+ //TODO: [ESP32H21] IDF-11556, please check
+ return 96;
+
+#elif CONFIG_IDF_TARGET_ESP32H4
+ //TODO: [ESP32H4] IDF-12322 inherited from verification branch, need check
+ return 96;
+
#elif CONFIG_IDF_TARGET_ESP32P4
return 400;
diff --git a/bootloader_components/bootloader_support/src/bootloader_init.c b/bootloader_components/bootloader_support/src/bootloader_init.c
index bff1b92..0e8dcd7 100644
--- a/bootloader_components/bootloader_support/src/bootloader_init.c
+++ b/bootloader_components/bootloader_support/src/bootloader_init.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,7 @@
#include "hal/wdt_hal.h"
#include "hal/efuse_hal.h"
#include "esp_bootloader_desc.h"
+#include "esp_rom_sys.h"
static const char *TAG = "boot";
@@ -34,7 +35,12 @@ void bootloader_clear_bss_section(void)
esp_err_t bootloader_read_bootloader_header(void)
{
/* load bootloader image header */
- if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
+#if SOC_RECOVERY_BOOTLOADER_SUPPORTED
+ const uint32_t bootloader_flash_offset = esp_rom_get_bootloader_offset();
+#else
+ const uint32_t bootloader_flash_offset = ESP_PRIMARY_BOOTLOADER_OFFSET;
+#endif
+ if (bootloader_flash_read(bootloader_flash_offset, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
ESP_EARLY_LOGE(TAG, "failed to load bootloader image header!");
return ESP_FAIL;
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_mem.c b/bootloader_components/bootloader_support/src/bootloader_mem.c
index 2a837fe..6ae07f7 100644
--- a/bootloader_components/bootloader_support/src/bootloader_mem.c
+++ b/bootloader_components/bootloader_support/src/bootloader_mem.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,14 +12,12 @@
#include "bootloader_mem.h"
#include "esp_cpu.h"
-#if SOC_APM_SUPPORTED
#include "hal/apm_hal.h"
-#endif
void bootloader_init_mem(void)
{
-#if !defined(BOOTLOADER_BUILD) && defined(SOC_APM_SUPPORTED)
+#if !defined(BOOTLOADER_BUILD)
/* By default, these access path filters are enable and allow the
* access to masters only if they are in TEE mode. Since all masters
* except HP CPU boots in REE mode, default setting of these filters
@@ -27,12 +25,19 @@ void bootloader_init_mem(void)
* So, at boot disabling these filters. They will enable as per the
* use case by TEE initialization code.
*/
-#ifdef SOC_APM_CTRL_FILTER_SUPPORTED
- apm_hal_apm_ctrl_filter_enable_all(false);
-#endif
+#if SOC_APM_CTRL_FILTER_SUPPORTED
+ apm_hal_enable_ctrl_filter_all(false);
+ /* [APM] On power-up, only the HP CPU starts in TEE mode; others
+ * default to REE2. APM blocks REE0–REE2 access by default.
+ * Thus, all masters are set to TEE mode.
+ */
+#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
+ apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE);
+#endif // SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
+#endif // SOC_APM_CTRL_FILTER_SUPPORTED
#endif
-#ifdef CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
+#if CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
// protect memory region
esp_cpu_configure_region_protection();
#endif
diff --git a/bootloader_components/bootloader_support/src/bootloader_random_esp32c5.c b/bootloader_components/bootloader_support/src/bootloader_random_esp32c5.c
index 6541b8d..826aa78 100644
--- a/bootloader_components/bootloader_support/src/bootloader_random_esp32c5.c
+++ b/bootloader_components/bootloader_support/src/bootloader_random_esp32c5.c
@@ -1,102 +1,75 @@
/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
-#include "soc/soc.h"
-#include "soc/pcr_reg.h"
-#include "soc/apb_saradc_reg.h"
-#include "soc/pmu_reg.h"
-#include "hal/regi2c_ctrl.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "hal/rng_ll.h"
+#include "esp_private/regi2c_ctrl.h"
#include "soc/lpperi_reg.h"
-#include "soc/regi2c_saradc.h"
-#include "esp_log.h"
-static const uint32_t SAR2_CHANNEL = 9;
-static const uint32_t SAR1_CHANNEL = 7;
-static const uint32_t PATTERN_BIT_WIDTH = 6;
-static const uint32_t SAR1_ATTEN = 3;
-static const uint32_t SAR2_ATTEN = 3;
+#define I2C_SAR_ADC_INIT_CODE_VAL 2150
void bootloader_random_enable(void)
{
- // pull SAR ADC out of reset
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
-
- // enable SAR ADC APB clock
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN);
-
- // pull APB register out of reset
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN);
-
- // enable ADC_CTRL_CLK (SAR ADC function clock)
- REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN);
-
- // select XTAL clock (40 MHz) source for ADC_CTRL_CLK
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0); // 0: XTAL; 1: 80M(from bbpll); 2. FOSC
-
- // set the clock divider for ADC_CTRL_CLK to default value (in case it has been changed)
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0);
-
- // some magic register poke from the digital team
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
-
- // Config ADC circuit (Analog part) with I2C (HOST ID 0X69) and choose internal voltage as sampling source
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_PERIF_ADDR, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_EN_TOUT_ADDR, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_EN_TOUT_ADDR, 1);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x66);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_MSB, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_LSB, 0x66);
-
- // create patterns and set them in pattern table
- uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN; // we want channel 9 with max attenuation
- uint32_t pattern_two = (SAR1_CHANNEL << 2) | SAR1_ATTEN; // we want channel 7 with max attenuation
- uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, pattern_table);
-
- // set pattern length (APB_SARADC_SARADC_SAR_PATT_LEN counts from 0)
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_PATT_LEN, 1);
-
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_CLK_DIV, 15);
-
- // set timer expiry (timer is ADC_CTRL_CLK)
- REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_TARGET, 200);
-
- // enable timer
- REG_SET_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
- CLEAR_PERI_REG_MASK(LPPERI_RNG_CFG_REG, LPPERI_RNG_TIMER_EN);
+ adc_ll_reset_register();
+ adc_ll_enable_bus_clock(true);
+ adc_ll_enable_func_clock(true);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_digi_controller_clk_div(0, 0, 0);
+
+ // some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_enable();
+#else
+ regi2c_ctrl_ll_i2c_sar_periph_enable();
+#endif
+
+ // enable analog i2c master clock for RNG runtime
+ ANALOG_CLOCK_ENABLE();
+
+ adc_ll_regi2c_init();
+ adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
+ adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
+
+ adc_digi_pattern_config_t pattern_config = {};
+ pattern_config.unit = ADC_UNIT_1;
+ pattern_config.atten = ADC_ATTEN_DB_12;
+ pattern_config.channel = ADC_CHANNEL_7; //Use reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
+ pattern_config.unit = ADC_UNIT_2;
+ pattern_config.atten = ADC_ATTEN_DB_12;
+ pattern_config.channel = ADC_CHANNEL_1; //Use reserved ADC2 and reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_2, 1, pattern_config);
+
+ adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 2);
+
+ adc_ll_digi_set_clk_div(15);
+ adc_ll_digi_set_trigger_interval(200);
+ adc_ll_digi_trigger_enable();
+
+ rng_ll_enable_sample(true);
+ rng_ll_enable_rtc_timer(true);
+ rng_ll_enable_rng_timer(true);
}
void bootloader_random_disable(void)
{
- // disable timer
- REG_CLR_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
-
- // Write reset value of this register
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF);
-
- // Revert ADC I2C configuration and initial voltage source setting
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_MSB, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_LSB, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_PERIF_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_EN_TOUT_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_EN_TOUT_ADDR, 0);
-
- // disable ADC_CTRL_CLK (SAR ADC function clock)
- REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
-
- // Set PCR_SARADC_CONF_REG to initial state
- REG_WRITE(PCR_SARADC_CONF_REG, 0x5);
+ adc_ll_digi_trigger_disable();
+ adc_ll_digi_reset_pattern_table();
+ adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
+ adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
+ adc_ll_regi2c_adc_deinit();
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_disable();
+#endif
+
+ // disable analog i2c master clock
+ ANALOG_CLOCK_DISABLE();
+ adc_ll_digi_controller_clk_div(4, 0, 0);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_random_esp32c6.c b/bootloader_components/bootloader_support/src/bootloader_random_esp32c6.c
index fec85a6..de45f07 100644
--- a/bootloader_components/bootloader_support/src/bootloader_random_esp32c6.c
+++ b/bootloader_components/bootloader_support/src/bootloader_random_esp32c6.c
@@ -1,96 +1,68 @@
/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
-#include "soc/soc.h"
-#include "soc/pcr_reg.h"
-#include "soc/apb_saradc_reg.h"
-#include "soc/pmu_reg.h"
-#include "hal/regi2c_ctrl.h"
-#include "soc/regi2c_saradc.h"
-#include "esp_log.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "esp_private/regi2c_ctrl.h"
-static const uint32_t SAR2_CHANNEL = 9;
-static const uint32_t PATTERN_BIT_WIDTH = 6;
-static const uint32_t SAR1_ATTEN = 1;
-static const uint32_t SAR2_ATTEN = 1;
+#define I2C_SAR_ADC_INIT_CODE_VAL 2150
void bootloader_random_enable(void)
{
- // pull SAR ADC out of reset
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
-
- // enable SAR ADC APB clock
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN);
-
- // enable ADC_CTRL_CLK (SAR ADC function clock)
- REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN);
-
- // select XTAL clock (40 MHz) source for ADC_CTRL_CLK
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0);
-
- // set the clock divider for ADC_CTRL_CLK to default value (in case it has been changed)
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0);
+ adc_ll_reset_register();
+ adc_ll_enable_bus_clock(true);
+ adc_ll_enable_func_clock(true);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_digi_controller_clk_div(0, 0, 0);
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
-
- // Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR , 2);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR , 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x66);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x66);
-
- // create patterns and set them in pattern table
- uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN; // we want channel 9 with max attenuation
- uint32_t pattern_two = (SAR2_CHANNEL << 2) | SAR1_ATTEN; // we want channel 9 with max attenuation
- uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, pattern_table);
-
- // set pattern length to 2 (APB_SARADC_SAR_PATT_LEN counts from 0)
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_PATT_LEN, 1);
-
- // Same as in C3
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_CLK_DIV, 15);
-
- // set timer expiry (timer is ADC_CTRL_CLK)
- REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_TARGET, 200);
-
- // enable timer
- REG_SET_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_enable();
+#else
+ regi2c_ctrl_ll_i2c_sar_periph_enable();
+#endif
+
+ // enable analog i2c master clock for RNG runtime
+ ANALOG_CLOCK_ENABLE();
+
+ adc_ll_regi2c_init();
+ adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
+ adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
+
+ adc_digi_pattern_config_t pattern_config = {};
+ pattern_config.unit = ADC_UNIT_2;
+ pattern_config.atten = ADC_ATTEN_DB_2_5;
+ pattern_config.channel = ADC_CHANNEL_1; //Use reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
+ pattern_config.unit = ADC_UNIT_2;
+ pattern_config.atten = ADC_ATTEN_DB_2_5;
+ pattern_config.channel = ADC_CHANNEL_1; //Use reserved ADC2 and reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_2, 1, pattern_config);
+ adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, 2);
+
+ adc_ll_digi_set_clk_div(15);
+ adc_ll_digi_set_trigger_interval(200);
+ adc_ll_digi_trigger_enable();
}
void bootloader_random_disable(void)
{
- // disable timer
- REG_CLR_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
-
- // Write reset value of this register
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF);
-
- // Revert ADC I2C configuration and initial voltage source setting
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
-
- // disable ADC_CTRL_CLK (SAR ADC function clock)
- REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
-
- // Set PCR_SARADC_CONF_REG to initial state
- REG_WRITE(PCR_SARADC_CONF_REG, 0x5);
+ adc_ll_digi_trigger_disable();
+ adc_ll_digi_reset_pattern_table();
+ adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
+ adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
+ adc_ll_regi2c_adc_deinit();
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_disable();
+#endif
+
+ // disable analog i2c master clock
+ ANALOG_CLOCK_DISABLE();
+ adc_ll_digi_controller_clk_div(4, 0, 0);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_random_esp32c61.c b/bootloader_components/bootloader_support/src/bootloader_random_esp32c61.c
index bcc7d57..1f1e2ad 100644
--- a/bootloader_components/bootloader_support/src/bootloader_random_esp32c61.c
+++ b/bootloader_components/bootloader_support/src/bootloader_random_esp32c61.c
@@ -1,101 +1,68 @@
/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
-#include "soc/soc.h"
-#include "soc/pcr_reg.h"
-#include "soc/apb_saradc_reg.h"
-#include "soc/pmu_reg.h"
-#include "hal/regi2c_ctrl.h"
-#include "soc/regi2c_saradc.h"
-#include "esp_log.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "esp_private/regi2c_ctrl.h"
-static const uint32_t SAR2_CHANNEL = 9;
-static const uint32_t SAR1_CHANNEL = 7;
-static const uint32_t PATTERN_BIT_WIDTH = 6;
-static const uint32_t SAR1_ATTEN = 3;
-static const uint32_t SAR2_ATTEN = 3;
+#define I2C_SAR_ADC_INIT_CODE_VAL 2150
void bootloader_random_enable(void)
{
- // pull SAR ADC out of reset
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
-
- // enable SAR ADC APB clock
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN);
-
- // pull APB register out of reset
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_RST_EN);
-
- // enable ADC_CTRL_CLK (SAR ADC function clock)
- REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN);
-
- // select XTAL clock (40 MHz) source for ADC_CTRL_CLK
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0);
-
- // set the clock divider for ADC_CTRL_CLK to default value (in case it has been changed)
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0);
+ adc_ll_reset_register();
+ adc_ll_enable_bus_clock(true);
+ adc_ll_enable_func_clock(true);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_digi_controller_clk_div(0, 0, 0);
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
-
- // Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR , 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR , 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x66);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x66);
-
- // create patterns and set them in pattern table
- uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN; // we want channel 9 with max attenuation
- uint32_t pattern_two = (SAR1_CHANNEL << 2) | SAR1_ATTEN; // we want channel 7 with max attenuation
- uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
- REG_WRITE(SARADC_SAR_PATT_TAB1_REG, pattern_table);
-
- // set pattern length to 2 (APB_SARADC_SAR_PATT_LEN counts from 0)
- REG_SET_FIELD(SARADC_CTRL_REG, SARADC_SAR_PATT_LEN, 1);
-
- // Same as in C3
- REG_SET_FIELD(SARADC_CTRL_REG, SARADC_SAR_CLK_DIV, 15);
-
- // set timer expiry (timer is ADC_CTRL_CLK)
- REG_SET_FIELD(SARADC_CTRL2_REG, SARADC_TIMER_TARGET, 200);
-
- // enable timer
- REG_SET_BIT(SARADC_CTRL2_REG, SARADC_TIMER_EN);
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_enable();
+#else
+ regi2c_ctrl_ll_i2c_sar_periph_enable();
+#endif
+
+ // enable analog i2c master clock for RNG runtime
+ ANALOG_CLOCK_ENABLE();
+
+ adc_ll_regi2c_init();
+ adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
+ adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
+
+ adc_digi_pattern_config_t pattern_config = {};
+ pattern_config.unit = ADC_UNIT_1;
+ pattern_config.atten = ADC_ATTEN_DB_12;
+ pattern_config.channel = ADC_CHANNEL_7; //Use reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
+ pattern_config.unit = ADC_UNIT_2;
+ pattern_config.atten = ADC_ATTEN_DB_12;
+ pattern_config.channel = ADC_CHANNEL_1; //Use reserved ADC2 and reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_2, 1, pattern_config);
+ adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 2);
+
+ adc_ll_digi_set_clk_div(15);
+ adc_ll_digi_set_trigger_interval(200);
+ adc_ll_digi_trigger_enable();
}
void bootloader_random_disable(void)
{
- // disable timer
- REG_CLR_BIT(SARADC_CTRL2_REG, SARADC_TIMER_EN);
-
- // Write reset value of this register
- REG_WRITE(SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF);
-
- // Revert ADC I2C configuration and initial voltage source setting
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
-
- // disable ADC_CTRL_CLK (SAR ADC function clock)
- REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
-
- // Set PCR_SARADC_CONF_REG to initial state
- REG_WRITE(PCR_SARADC_CONF_REG, 0x5);
+ adc_ll_digi_trigger_disable();
+ adc_ll_digi_reset_pattern_table();
+ adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
+ adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
+ adc_ll_regi2c_adc_deinit();
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_disable();
+#endif
+
+ // disable analog i2c master clock
+ ANALOG_CLOCK_DISABLE();
+ adc_ll_digi_controller_clk_div(4, 0, 0);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_random_esp32h2.c b/bootloader_components/bootloader_support/src/bootloader_random_esp32h2.c
index 0b4e382..4c4f515 100644
--- a/bootloader_components/bootloader_support/src/bootloader_random_esp32h2.c
+++ b/bootloader_components/bootloader_support/src/bootloader_random_esp32h2.c
@@ -1,88 +1,66 @@
/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "bootloader_random.h"
-#include "soc/soc.h"
-#include "soc/pcr_reg.h"
-#include "soc/apb_saradc_reg.h"
-#include "soc/pmu_reg.h"
-#include "hal/regi2c_ctrl.h"
-#include "soc/regi2c_saradc.h"
-#include "esp_log.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "esp_private/regi2c_ctrl.h"
-static const uint32_t SAR2_CHANNEL = 9;
-static const uint32_t PATTERN_BIT_WIDTH = 6;
-static const uint32_t SAR1_ATTEN = 1;
-static const uint32_t SAR2_ATTEN = 1;
+#define I2C_SAR_ADC_INIT_CODE_VAL 2150
void bootloader_random_enable(void)
{
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
- REG_CLR_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_RST_EN);
-
- REG_SET_BIT(PCR_SARADC_CONF_REG, PCR_SARADC_REG_CLK_EN);
-
- REG_SET_BIT(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_EN);
-
- // select XTAL clock (40 MHz) source for ADC_CTRL_CLK
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_SEL, 0);
-
- REG_SET_FIELD(PCR_SARADC_CLKM_CONF_REG, PCR_SARADC_CLKM_DIV_NUM, 0);
+ adc_ll_reset_register();
+ adc_ll_enable_bus_clock(true);
+ adc_ll_enable_func_clock(true);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_digi_controller_clk_div(0, 0, 0);
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_DTEST, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_ENT_SAR, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_EN_TOUT_SAR1_BUS, 1);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR2_INIT_CODE_MSB, 0X08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR2_INIT_CODE_LSB, 0X66);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR1_INIT_CODE_MSB, 0X08);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR1_INIT_CODE_LSB, 0X66);
-
- // create patterns and set them in pattern table
- uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN;
- uint32_t pattern_two = SAR1_ATTEN; // we want channel 0 with max attenuation, channel doesn't really matter here
- uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, pattern_table);
-
- // set pattern length to 2 (APB_SARADC_SAR_PATT_LEN counts from 0)
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_PATT_LEN, 0);
-
- // Same as in C3
- REG_SET_FIELD(APB_SARADC_CTRL_REG, APB_SARADC_SARADC_SAR_CLK_DIV, 15);
-
- // set timer expiry (timer is ADC_CTRL_CLK)
- REG_SET_FIELD(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_TARGET, 200);
-
- // ENABLE_TIMER
- REG_SET_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_enable();
+#else
+ regi2c_ctrl_ll_i2c_sar_periph_enable();
+#endif
+
+ // enable analog i2c master clock for RNG runtime
+ ANALOG_CLOCK_ENABLE();
+
+ adc_ll_regi2c_init();
+ adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
+ adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
+
+ adc_digi_pattern_config_t pattern_config = {};
+ pattern_config.atten = ADC_ATTEN_DB_2_5;
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
+ pattern_config.unit = ADC_UNIT_2;
+ pattern_config.atten = ADC_ATTEN_DB_2_5;
+ pattern_config.channel = ADC_CHANNEL_1; //Use reserved ADC2 and reserved channel to get internal voltage
+ adc_ll_digi_set_pattern_table(ADC_UNIT_2, 1, pattern_config);
+ adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 1);
+
+ adc_ll_digi_set_clk_div(15);
+ adc_ll_digi_set_trigger_interval(200);
+ adc_ll_digi_trigger_enable();
}
void bootloader_random_disable(void)
{
- // disable timer
- REG_CLR_BIT(APB_SARADC_CTRL2_REG, APB_SARADC_SARADC_TIMER_EN);
-
- // Write reset value of this register
- REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, 0xFFFFFF);
-
- // Revert ADC I2C configuration and initial voltage source setting
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR2_INIT_CODE_MSB, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR2_INIT_CODE_LSB, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR1_INIT_CODE_MSB, 0x60);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_SAR1_INIT_CODE_LSB, 0x0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_DTEST, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_ENT_SAR, 0);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_EN_TOUT_SAR1_BUS, 0);
-
- // disable ADC_CTRL_CLK (SAR ADC function clock)
- REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
-
- // Set PCR_SARADC_CONF_REG to initial state
- REG_WRITE(PCR_SARADC_CONF_REG, 0x5);
+ adc_ll_digi_trigger_disable();
+ adc_ll_digi_reset_pattern_table();
+ adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
+ adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
+ adc_ll_regi2c_adc_deinit();
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_disable();
+#endif
+
+ // disable analog i2c master clock
+ ANALOG_CLOCK_DISABLE();
+ adc_ll_digi_controller_clk_div(4, 0, 0);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_random_esp32p4.c b/bootloader_components/bootloader_support/src/bootloader_random_esp32p4.c
index df88e8d..0a9f90a 100644
--- a/bootloader_components/bootloader_support/src/bootloader_random_esp32p4.c
+++ b/bootloader_components/bootloader_support/src/bootloader_random_esp32p4.c
@@ -1,100 +1,88 @@
/*
- * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
+ * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
+*
+* SPDX-License-Identifier: Apache-2.0
+*/
+#include "sdkconfig.h"
#include "bootloader_random.h"
-#include "soc/soc.h"
-#include "soc/adc_reg.h"
-#include "soc/pmu_reg.h"
-#include "soc/regi2c_saradc.h"
-#include "soc/hp_sys_clkrst_reg.h"
-#include "soc/lp_adc_reg.h"
-#include "esp_private/regi2c_ctrl.h"
-#include "esp_rom_regi2c.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "hal/config.h"
-// TODO IDF-6497: once ADC API is supported, use the API instead of defining functions and constants here
+#include "esp_private/periph_ctrl.h"
+#include "esp_private/adc_share_hw_ctrl.h"
-#define I2C_SAR_ADC_INIT_CODE_VAL 2166
+#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
+#include "hal/trng_ll.h"
+#endif
-typedef struct {
- int atten;
- int channel;
-} pattern_item;
-
-typedef struct {
- pattern_item item[4];
-} pattern_table;
-
-static void adc1_fix_initcode_set(uint32_t initcode_value)
-{
- uint32_t msb = initcode_value >> 8;
- uint32_t lsb = initcode_value & 0xff;
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_MSB, msb);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_LSB, lsb);
-}
-
-//total 4 tables
-static void hpadc_sar1_pattern_table_cfg(unsigned int table_idx, pattern_table table)
-{
- uint32_t wdata = 0;
- wdata = (table.item[0].channel << 20 | table.item[0].atten << 18 |
- table.item[1].channel << 14|table.item[1].atten << 12 |
- table.item[2].channel << 8 |table.item[2].atten << 6 |
- table.item[3].channel << 2 |table.item[3].atten);
- WRITE_PERI_REG(ADC_SAR1_PATT_TAB1_REG + table_idx * 4, wdata);
-}
+#define I2C_SAR_ADC_INIT_CODE_VAL 2166
+#define ADC_RNG_CLKM_DIV_NUM 0
+#define ADC_RNG_CLKM_DIV_B 0
+#define ADC_RNG_CLKM_DIV_A 0
void bootloader_random_enable(void)
{
- pattern_table sar1_table[4] = {};
- uint32_t pattern_len = 0;
-
- SET_PERI_REG_MASK(HP_SYS_CLKRST_SOC_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_ADC_APB_CLK_EN);
- SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL23_REG, HP_SYS_CLKRST_REG_ADC_CLK_EN);
-
- SET_PERI_REG_MASK(RTCADC_MEAS1_MUX_REG, RTCADC_SAR1_DIG_FORCE);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG,PMU_XPD_PERIF_I2C);
-
- uint32_t sar1_clk_div_num = GET_PERI_REG_BITS2((HP_SYS_CLKRST_PERI_CLK_CTRL24_REG),
- (HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_M),
- (HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_S));
-
- SET_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE); //start force 1
-
- adc1_fix_initcode_set(I2C_SAR_ADC_INIT_CODE_VAL);
-
- // cfg pattern table
- sar1_table[0].item[0].channel = 10; //rand() % 6;
- sar1_table[0].item[0].atten = 3;
- sar1_table[0].item[1].channel = 10;
- sar1_table[0].item[1].atten = 3;
- sar1_table[0].item[2].channel = 10;
- sar1_table[0].item[2].atten = 3;
- sar1_table[0].item[3].channel = 10;
- sar1_table[0].item[3].atten = 3;
-
- hpadc_sar1_pattern_table_cfg(0, sar1_table[0]);
- SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_SAR1_PATT_LEN, pattern_len, ADC_SAR1_PATT_LEN_S);
-
- SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR1_FORCE, 3, ADC_XPD_SAR1_FORCE_S);
- SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR2_FORCE, 3, ADC_XPD_SAR2_FORCE_S);
-
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_ENT_VDD_GRP1, 1);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_DTEST_VDD_GRP1, 0);
-
- CLEAR_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE);
- SET_PERI_REG_MASK(ADC_CTRL2_REG, ADC_TIMER_EN);
- SET_PERI_REG_BITS(ADC_CTRL2_REG, ADC_TIMER_TARGET, sar1_clk_div_num * 25, ADC_TIMER_TARGET_S);
-
- while (GET_PERI_REG_MASK(ADC_INT_RAW_REG, ADC_SAR1_DONE_INT_RAW) == 0) { }
-
- SET_PERI_REG_MASK(ADC_INT_CLR_REG, ADC_APB_SARADC1_DONE_INT_CLR);
+ _adc_ll_reset_register();
+ _adc_ll_enable_bus_clock(true);
+
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_digi_controller_clk_div(0, 0, 0);
+
+ // some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_enable();
+#else
+ regi2c_ctrl_ll_i2c_sar_periph_enable();
+#endif
+
+ // enable analog i2c master clock for RNG runtime
+ ANALOG_CLOCK_ENABLE();
+
+ adc_ll_regi2c_init();
+ adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
+
+ adc_digi_pattern_config_t pattern_config = {};
+ pattern_config.unit = ADC_UNIT_1;
+ pattern_config.atten = ADC_ATTEN_DB_12;
+ pattern_config.channel = ADC_CHANNEL_10;
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 1, pattern_config);
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 2, pattern_config);
+ adc_ll_digi_set_pattern_table(ADC_UNIT_1, 3, pattern_config);
+ adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 1);
+
+ adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
+ adc_ll_digi_set_power_manage(ADC_UNIT_1, ADC_LL_POWER_SW_ON);
+
+ adc_ll_digi_set_clk_div(15);
+ adc_ll_digi_set_trigger_interval(100);
+ adc_ll_digi_trigger_enable();
+#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
+ trng_ll_enable();
+#endif
}
void bootloader_random_disable(void)
{
- // No-op for now TODO IDF-6497
- // ADC should be set to defaults here, once ADC API is implemented
- // OR just keep this empty and let application continue to use RNG initialized by the bootloader
+ adc_ll_digi_trigger_disable();
+ adc_ll_digi_reset_pattern_table();
+ adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
+ adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
+ adc_ll_regi2c_adc_deinit();
+
+#ifndef BOOTLOADER_BUILD
+ regi2c_saradc_disable();
+#endif
+
+ // disable analog i2c master clock
+ ANALOG_CLOCK_DISABLE();
+ adc_ll_digi_controller_clk_div(4, 0, 0);
+ adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
+ adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_ULP);
+
+#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
+ trng_ll_disable();
+#endif
}
diff --git a/bootloader_components/bootloader_support/src/bootloader_sha.c b/bootloader_components/bootloader_support/src/bootloader_sha.c
new file mode 100644
index 0000000..e4b553a
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/bootloader_sha.c
@@ -0,0 +1,260 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "bootloader_sha.h"
+#include "soc/soc_caps.h"
+#include "rom/sha.h"
+#include "sdkconfig.h"
+
+#if NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM
+#if !CONFIG_IDF_TARGET_ESP32
+static SHA_CTX ctx;
+
+bootloader_sha256_handle_t bootloader_sha256_start()
+{
+ // Enable SHA hardware
+ ets_sha_enable();
+ ets_sha_init(&ctx, SHA2_256);
+ return &ctx; // Meaningless non-NULL value
+}
+
+void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
+{
+ assert(handle != NULL);
+ ets_sha_update(&ctx, data, data_len, false);
+}
+
+void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
+{
+ assert(handle != NULL);
+
+ if (digest == NULL) {
+ bzero(&ctx, sizeof(ctx));
+ return;
+ }
+ ets_sha_finish(&ctx, digest);
+}
+
+#if SOC_SHA_SUPPORT_SHA512
+bootloader_sha_handle_t bootloader_sha512_start(bool is384)
+{
+ // Enable SHA hardware
+ ets_sha_enable();
+ ets_sha_init(&ctx, is384 ? SHA2_384 : SHA2_512);
+ return &ctx; // Meaningless non-NULL value
+}
+
+void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
+{
+ assert(handle != NULL);
+ ets_sha_update(&ctx, data, data_len, false);
+}
+
+void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
+{
+ assert(handle != NULL);
+
+ if (digest == NULL) {
+ bzero(&ctx, sizeof(ctx));
+ return;
+ }
+ ets_sha_finish(&ctx, digest);
+}
+#endif /* SOC_SHA_SUPPORT_SHA512 */
+#else /* !CONFIG_IDF_TARGET_ESP32 */
+
+#include "soc/dport_reg.h"
+#include "soc/hwcrypto_periph.h"
+
+static uint32_t words_hashed;
+
+// Words per SHA256 block
+static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t));
+// Words in final SHA256 digest
+static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
+
+bootloader_sha256_handle_t bootloader_sha256_start(void)
+{
+ // Enable SHA hardware
+ ets_sha_enable();
+ words_hashed = 0;
+ return (bootloader_sha256_handle_t)&words_hashed; // Meaningless non-NULL value
+}
+
+void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
+{
+ assert(handle != NULL);
+ assert(data_len % 4 == 0);
+
+ const uint32_t *w = (const uint32_t *)data;
+ size_t word_len = data_len / 4;
+ uint32_t *sha_text_reg = (uint32_t *)(SHA_TEXT_BASE);
+
+ while (word_len > 0) {
+ size_t block_count = words_hashed % BLOCK_WORDS;
+ size_t copy_words = (BLOCK_WORDS - block_count);
+
+ copy_words = MIN(word_len, copy_words);
+
+ // Wait for SHA engine idle
+ while (_DPORT_REG_READ(SHA_256_BUSY_REG) != 0) { }
+
+ // Copy to memory block
+ for (size_t i = 0; i < copy_words; i++) {
+ sha_text_reg[block_count + i] = __builtin_bswap32(w[i]);
+ }
+ asm volatile ("memw");
+
+ // Update counters
+ words_hashed += copy_words;
+ block_count += copy_words;
+ word_len -= copy_words;
+ w += copy_words;
+
+ // If we loaded a full block, run the SHA engine
+ if (block_count == BLOCK_WORDS) {
+ if (words_hashed == BLOCK_WORDS) {
+ _DPORT_REG_WRITE(SHA_256_START_REG, 1);
+ } else {
+ _DPORT_REG_WRITE(SHA_256_CONTINUE_REG, 1);
+ }
+ block_count = 0;
+ }
+ }
+}
+
+void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
+{
+ assert(handle != NULL);
+
+ if (digest == NULL) {
+ return; // We'd free resources here, but there are none to free
+ }
+
+ uint32_t data_words = words_hashed;
+
+ // Pad to a 55 byte long block loaded in the engine
+ // (leaving 1 byte 0x80 plus variable padding plus 8 bytes of length,
+ // to fill a 64 byte block.)
+ int block_bytes = (words_hashed % BLOCK_WORDS) * 4;
+ int pad_bytes = 55 - block_bytes;
+ if (pad_bytes < 0) {
+ pad_bytes += 64;
+ }
+ static const uint8_t padding[64] = { 0x80, 0, };
+
+ pad_bytes += 5; // 1 byte for 0x80 plus first 4 bytes of the 64-bit length
+ assert(pad_bytes % 4 == 0); // should be, as (block_bytes % 4 == 0)
+
+ bootloader_sha256_data(handle, padding, pad_bytes);
+
+ assert(words_hashed % BLOCK_WORDS == 60 / 4); // 32-bits left in block
+
+ // Calculate 32-bit length for final 32 bits of data
+ uint32_t bit_count = __builtin_bswap32( data_words * 32 );
+ bootloader_sha256_data(handle, &bit_count, sizeof(bit_count));
+
+ assert(words_hashed % BLOCK_WORDS == 0);
+
+ while (_DPORT_REG_READ(SHA_256_BUSY_REG) == 1) { }
+ _DPORT_REG_WRITE(SHA_256_LOAD_REG, 1);
+ while (_DPORT_REG_READ(SHA_256_BUSY_REG) == 1) { }
+
+ uint32_t *digest_words = (uint32_t *)digest;
+ uint32_t *sha_text_reg = (uint32_t *)(SHA_TEXT_BASE);
+ for (size_t i = 0; i < DIGEST_WORDS; i++) {
+ digest_words[i] = __builtin_bswap32(sha_text_reg[i]);
+ }
+ asm volatile ("memw");
+}
+#endif /* CONFIG_IDF_TARGET_ESP32 */
+#else /* NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM */
+
+#include "bootloader_flash_priv.h"
+#include <mbedtls/sha256.h>
+#include <mbedtls/sha512.h>
+
+bootloader_sha256_handle_t bootloader_sha256_start(void)
+{
+ mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context));
+ if (!ctx) {
+ return NULL;
+ }
+ mbedtls_sha256_init(ctx);
+ int ret = mbedtls_sha256_starts(ctx, false);
+ if (ret != 0) {
+ return NULL;
+ }
+ return ctx;
+}
+
+void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
+{
+ assert(handle != NULL);
+ mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle;
+ int ret = mbedtls_sha256_update(ctx, data, data_len);
+ assert(ret == 0);
+ (void)ret;
+}
+
+void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
+{
+ assert(handle != NULL);
+ mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle;
+ if (digest != NULL) {
+ int ret = mbedtls_sha256_finish(ctx, digest);
+ assert(ret == 0);
+ (void)ret;
+ }
+ mbedtls_sha256_free(ctx);
+ free(handle);
+ handle = NULL;
+}
+
+#if SOC_SHA_SUPPORT_SHA512
+bootloader_sha_handle_t bootloader_sha512_start(bool is384)
+{
+ mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
+ if (!ctx) {
+ return NULL;
+ }
+ mbedtls_sha512_init(ctx);
+ int ret = mbedtls_sha512_starts(ctx, is384);
+ if (ret != 0) {
+ return NULL;
+ }
+ return ctx;
+}
+
+void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len)
+{
+ assert(handle != NULL);
+ mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
+ int ret = mbedtls_sha512_update(ctx, data, data_len);
+ assert(ret == 0);
+ (void)ret;
+}
+
+void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest)
+{
+ assert(handle != NULL);
+ mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle;
+ if (digest != NULL) {
+ int ret = mbedtls_sha512_finish(ctx, digest);
+ assert(ret == 0);
+ (void)ret;
+ }
+ mbedtls_sha512_free(ctx);
+ free(handle);
+ handle = NULL;
+}
+#endif /* SOC_SHA_SUPPORT_SHA512 */
+#endif /* !(NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM) */
diff --git a/bootloader_components/bootloader_support/src/bootloader_utility.c b/bootloader_components/bootloader_support/src/bootloader_utility.c
index 3071db6..3ea2d79 100644
--- a/bootloader_components/bootloader_support/src/bootloader_utility.c
+++ b/bootloader_components/bootloader_support/src/bootloader_utility.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -30,6 +30,7 @@
#include "hal/cache_types.h"
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
+#include "hal/sha_types.h"
#include "esp_cpu.h"
#include "esp_image_format.h"
@@ -52,6 +53,10 @@
#include "esp_efuse.h"
#include "esp_fault.h"
+#if CONFIG_SECURE_ENABLE_TEE
+#include "bootloader_utility_tee.h"
+#endif
+
static const char *TAG = "boot";
/* Reduce literal size for some generic string literals */
@@ -69,6 +74,21 @@ static void set_cache_and_start_app(uint32_t drom_addr,
uint32_t irom_size,
const esp_image_metadata_t *data);
+#if CONFIG_SECURE_ENABLE_TEE
+/* NOTE: Required by other sources for secure boot routine */
+esp_image_metadata_t tee_data;
+static uint8_t tee_boot_part = UINT8_MAX;
+
+static void unpack_load_tee_app(const esp_image_metadata_t *data);
+static void set_cache_and_load_tee_app(uint32_t drom_addr,
+ uint32_t drom_load_addr,
+ uint32_t drom_size,
+ uint32_t irom_addr,
+ uint32_t irom_load_addr,
+ uint32_t irom_size,
+ const esp_image_metadata_t *data);
+#endif
+
esp_err_t bootloader_common_read_otadata(const esp_partition_pos_t *ota_info, esp_ota_select_entry_t *two_otadata)
{
const esp_ota_select_entry_t *ota_select_map;
@@ -162,6 +182,13 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
bs->test = partition->pos;
partition_usage = "test app";
break;
+#if CONFIG_SECURE_ENABLE_TEE
+ case PART_SUBTYPE_TEE_0: /* TEE binary */
+ case PART_SUBTYPE_TEE_1:
+ bs->tee[partition->subtype & 0x01] = partition->pos;
+ partition_usage = "TEE app";
+ break;
+#endif
default:
/* OTA binary */
if ((partition->subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
@@ -195,6 +222,12 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
esp_efuse_init_virtual_mode_in_flash(partition->pos.offset, partition->pos.size);
#endif
break;
+#if CONFIG_SECURE_ENABLE_TEE
+ case PART_SUBTYPE_DATA_TEE_OTA: /* TEE ota data */
+ bs->tee_ota_info = partition->pos;
+ partition_usage = "TEE OTA data";
+ break;
+#endif
default:
partition_usage = "Unknown data";
break;
@@ -208,6 +241,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
case PART_SUBTYPE_BOOTLOADER_OTA:
partition_usage = "ota bootloader";
break;
+ case PART_SUBTYPE_BOOTLOADER_RECOVERY:
+ partition_usage = "recovery bootloader";
+ break;
}
break; /* PART_TYPE_BOOTLOADER */
case PART_TYPE_PARTITION_TABLE: /* Partition table partition */
@@ -323,6 +359,10 @@ static int get_active_otadata_with_check_anti_rollback(const bootloader_state_t
valid_otadata[1] = bootloader_common_ota_select_valid(&two_otadata[1]);
bool sec_ver_valid_otadata[2] = { 0 };
+ if (bs->app_count == 0) {
+ return -1;
+ }
+
for (int i = 0; i < 2; ++i) {
if (valid_otadata[i] == true) {
ota_seq = two_otadata[i].ota_seq - 1; // Raw OTA sequence number. May be more than # of OTA slots
@@ -405,6 +445,9 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
if (active_otadata != -1) {
ESP_LOGD(TAG, "Active otadata[%d]", active_otadata);
uint32_t ota_seq = otadata[active_otadata].ota_seq - 1; // Raw OTA sequence number. May be more than # of OTA slots
+ if (bs->app_count == 0) {
+ return INVALID_INDEX;
+ }
boot_index = ota_seq % bs->app_count; // Actual OTA partition selection
ESP_LOGD(TAG, "Mapping seq %"PRIu32" -> OTA slot %d", ota_seq, boot_index);
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
@@ -497,7 +540,7 @@ void bootloader_utility_load_boot_image_from_deep_sleep(void)
esp_ota_select_entry_t otadata[2];
if (bs.ota_info.size && bootloader_common_read_otadata(&bs.ota_info, otadata) == ESP_OK) {
int active_otadata = bootloader_common_get_active_otadata(otadata);
- if (active_otadata != -1) {
+ if (active_otadata != -1 && bs.app_count > 0) {
index_of_last_loaded_app = (otadata[active_otadata].ota_seq - 1) % bs.app_count;
}
}
@@ -515,6 +558,29 @@ void bootloader_utility_load_boot_image_from_deep_sleep(void)
}
#endif
+#if CONFIG_SECURE_ENABLE_TEE
+void bootloader_utility_load_tee_image(const bootloader_state_t *bs)
+{
+ esp_err_t err = ESP_FAIL;
+ uint8_t tee_active_part = bootloader_utility_tee_get_boot_partition(&bs->tee_ota_info);
+ if (tee_active_part != PART_SUBTYPE_TEE_0 && tee_active_part != PART_SUBTYPE_TEE_1) {
+ ESP_LOGE(TAG, "Failed to find valid TEE app");
+ bootloader_reset();
+ }
+
+ uint8_t tee_part_idx = tee_active_part & 0x01;
+ const esp_partition_pos_t *tee_active_part_pos = &bs->tee[tee_part_idx];
+ err = bootloader_load_image(tee_active_part_pos, &tee_data);
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to load TEE app");
+ bootloader_reset();
+ }
+ tee_boot_part = tee_active_part;
+
+ ESP_LOGI(TAG, "Loaded TEE app from partition at offset 0x%"PRIx32, tee_active_part_pos->offset);
+}
+#endif
+
#define TRY_LOG_FORMAT "Trying partition index %d offs 0x%"PRIx32" size 0x%"PRIx32
void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index)
@@ -853,6 +919,127 @@ static bool s_flash_seg_needs_map(uint32_t vaddr)
#endif
}
+/* TODO: [IDF-11689] Unify the TEE-specific app loading implementation with
+ * the existing app loading implementation.
+ */
+#if CONFIG_SECURE_ENABLE_TEE
+static void unpack_load_tee_app(const esp_image_metadata_t *data)
+{
+ /**
+ * note:
+ * On chips with shared D/I external vaddr, we don't divide them into either D or I,
+ * as essentially they are the same.
+ * We integrate all the hardware difference into this `unpack_load_app` function.
+ */
+ uint32_t rom_addr[2] = {};
+ uint32_t rom_load_addr[2] = {};
+ uint32_t rom_size[2] = {};
+ int rom_index = 0; //shall not exceed 2
+
+ // Find DROM & IROM addresses, to configure MMU mappings
+ for (int i = 0; i < data->image.segment_count; i++) {
+ const esp_image_segment_header_t *header = &data->segments[i];
+ const uint32_t addr = header->load_addr;
+
+ //`SOC_DROM_LOW` and `SOC_DROM_HIGH` are the same as `SOC_IROM_LOW` and `SOC_IROM_HIGH`, reasons are in above `note`
+ if ((addr >= SOC_DROM_LOW && addr < SOC_DROM_HIGH)
+#if SOC_MMU_PER_EXT_MEM_TARGET
+ || (addr >= SOC_EXTRAM_LOW && addr < SOC_EXTRAM_HIGH)
+#endif
+ ) {
+ /**
+ * D/I are shared, but there should not be a third segment on flash/psram
+ */
+ assert(rom_index < 2);
+ rom_addr[rom_index] = data->segment_data[i];
+ rom_load_addr[rom_index] = header->load_addr;
+ rom_size[rom_index] = header->data_len;
+ rom_index++;
+ }
+ }
+ assert(rom_index == 2);
+
+ ESP_EARLY_LOGD(TAG, "calling set_cache_and_start_tee_app");
+ set_cache_and_load_tee_app(rom_addr[0],
+ rom_load_addr[0],
+ rom_size[0],
+ rom_addr[1],
+ rom_load_addr[1],
+ rom_size[1],
+ data);
+}
+
+static void set_cache_and_load_tee_app(
+ uint32_t drom_addr,
+ uint32_t drom_load_addr,
+ uint32_t drom_size,
+ uint32_t irom_addr,
+ uint32_t irom_load_addr,
+ uint32_t irom_size,
+ const esp_image_metadata_t *data)
+{
+ uint32_t drom_load_addr_aligned = 0, drom_addr_aligned = 0;
+ uint32_t irom_load_addr_aligned = 0, irom_addr_aligned = 0;
+ uint32_t actual_mapped_len = 0;
+
+ const uint32_t mmu_page_size = data->mmu_page_size;
+#if SOC_MMU_PAGE_SIZE_CONFIGURABLE
+ // re-configure MMU page size
+ mmu_ll_set_page_size(0, mmu_page_size);
+#endif //SOC_MMU_PAGE_SIZE_CONFIGURABLE
+
+ if (drom_addr != 0) {
+ drom_load_addr_aligned = drom_load_addr & MMU_FLASH_MASK_FROM_VAL(mmu_page_size);
+ drom_addr_aligned = drom_addr & MMU_FLASH_MASK_FROM_VAL(mmu_page_size);
+ ESP_EARLY_LOGV(TAG, "TEE rodata starts from paddr=0x%08x, vaddr=0x%08x, size=0x%x", drom_addr, drom_load_addr, drom_size);
+
+ //The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
+ if (s_flash_seg_needs_map(drom_load_addr_aligned)) {
+ mmu_hal_map_region(0, MMU_TARGET_FLASH0, drom_load_addr_aligned, drom_addr_aligned, drom_size, &actual_mapped_len);
+ ESP_EARLY_LOGV(TAG, "after mapping rodata, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, actual_mapped_len);
+ }
+ //we use the MMU_LL_END_DROM_ENTRY_ID mmu entry as a map page for app to find the boot partition
+ mmu_hal_map_region(0, MMU_TARGET_FLASH0, MMU_DROM_END_ENTRY_VADDR_FROM_VAL(mmu_page_size), drom_addr_aligned, mmu_page_size, &actual_mapped_len);
+ ESP_EARLY_LOGV(TAG, "mapped one page of the rodata, from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, actual_mapped_len);
+ }
+
+ if (irom_addr != 0) {
+ irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK_FROM_VAL(mmu_page_size);
+ irom_addr_aligned = irom_addr & MMU_FLASH_MASK_FROM_VAL(mmu_page_size);
+ ESP_EARLY_LOGV(TAG, "TEE text starts from paddr=0x%08x, vaddr=0x%08x, size=0x%x", irom_addr, irom_load_addr, irom_size);
+ //The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
+ irom_size = (irom_load_addr - irom_load_addr_aligned) + irom_size;
+
+ if (s_flash_seg_needs_map(irom_load_addr_aligned)) {
+ mmu_hal_map_region(0, MMU_TARGET_FLASH0, irom_load_addr_aligned, irom_addr_aligned, irom_size, &actual_mapped_len);
+ ESP_EARLY_LOGV(TAG, "after mapping text, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", irom_addr_aligned, irom_load_addr_aligned, actual_mapped_len);
+ }
+ }
+
+ if (drom_load_addr_aligned != 0) {
+ cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, drom_load_addr_aligned, drom_size);
+ cache_ll_l1_enable_bus(0, bus_mask);
+ }
+
+ if (irom_load_addr_aligned != 0) {
+ cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, irom_load_addr_aligned, irom_size);
+ cache_ll_l1_enable_bus(0, bus_mask);
+ }
+
+#if !CONFIG_FREERTOS_UNICORE
+ if (drom_load_addr_aligned != 0) {
+ cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(1, drom_load_addr_aligned, drom_size);
+ cache_ll_l1_enable_bus(1, bus_mask);
+ }
+
+ if (irom_load_addr_aligned != 0) {
+ cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(1, irom_load_addr_aligned, irom_size);
+ cache_ll_l1_enable_bus(1, bus_mask);
+ }
+#endif
+}
+#endif // CONFIG_SECURE_ENABLE_TEE
+
static void set_cache_and_start_app(
uint32_t drom_addr,
uint32_t drom_load_addr,
@@ -940,6 +1127,11 @@ static void set_cache_and_start_app(
cache_ll_l1_enable_bus(1, bus_mask);
#endif
+#if CONFIG_SECURE_ENABLE_TEE
+ //----------------------Unpacking and loading the TEE app----------------
+ unpack_load_tee_app(&tee_data);
+#endif
+
//----------------------Enable Cache----------------
#if CONFIG_IDF_TARGET_ESP32
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
@@ -950,12 +1142,26 @@ static void set_cache_and_start_app(
ESP_LOGD(TAG, "start: 0x%08"PRIx32, entry_addr);
bootloader_atexit();
+
+#if CONFIG_SECURE_ENABLE_TEE
+ ESP_LOGI(TAG, "Current privilege level - %d", esp_cpu_get_curr_privilege_level());
+ /* NOTE: TEE Initialization and REE Switch
+ * This call will not return back. After TEE initialization,
+ * it will switch to the REE and execute the user application.
+ */
+ typedef void (*esp_tee_init_t)(uint32_t, uint32_t, uint8_t) __attribute__((noreturn));
+ esp_tee_init_t esp_tee_init = ((esp_tee_init_t) tee_data.image.entry_addr);
+
+ ESP_LOGI(TAG, "Starting TEE: Entry point - 0x%"PRIx32, (uint32_t)esp_tee_init);
+ (*esp_tee_init)(entry_addr, drom_addr, tee_boot_part);
+#else
typedef void (*entry_t)(void) __attribute__((noreturn));
entry_t entry = ((entry_t) entry_addr);
// TODO: we have used quite a bit of stack at this point.
// use "movsp" instruction to reset stack back to where ROM stack starts.
(*entry)();
+#endif
}
void bootloader_reset(void)
@@ -1015,37 +1221,101 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
#endif
}
-esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
+static esp_err_t bootloader_sha_flash_contents(esp_sha_type type, uint32_t flash_offset, uint32_t len, uint8_t *digest)
{
-
if (digest == NULL) {
return ESP_ERR_INVALID_ARG;
}
/* Handling firmware images larger than MMU capacity */
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
- bootloader_sha256_handle_t sha_handle = NULL;
+ bootloader_sha_handle_t sha_handle = NULL;
+
+ if (type == SHA2_256) {
+ sha_handle = bootloader_sha256_start();
+ } else
+ // Using SOC_ECDSA_SUPPORT_CURVE_P384 here so that there is no flash size impact in the case of existing targets like ESP32.
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+ if (type == SHA2_384) {
+ sha_handle = bootloader_sha512_start(true);
+ } else
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
+ {
+ return ESP_ERR_INVALID_ARG;
+ }
- sha_handle = bootloader_sha256_start();
if (sha_handle == NULL) {
return ESP_ERR_NO_MEM;
}
while (len > 0) {
uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */
- uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */
+ uint32_t max_pages = (mmu_free_pages_count > mmu_page_offset) ? (mmu_free_pages_count - mmu_page_offset) : 0;
+ if (max_pages == 0) {
+ ESP_LOGE(TAG, "No free MMU pages are available");
+ if (type == SHA2_256) {
+ bootloader_sha256_finish(sha_handle, NULL);
+ }
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+ else if (type == SHA2_384) {
+ bootloader_sha512_finish(sha_handle, NULL);
+ }
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
+ return ESP_ERR_NO_MEM;
+ }
+ uint32_t max_image_len;
+ if (__builtin_mul_overflow(max_pages, SPI_FLASH_MMU_PAGE_SIZE, &max_image_len)) {
+ max_image_len = UINT32_MAX;
+ }
+ uint32_t partial_image_len = MIN(len, max_image_len); /* Read the image that fits in the free MMU pages */
const void * image = bootloader_mmap(flash_offset, partial_image_len);
if (image == NULL) {
- bootloader_sha256_finish(sha_handle, NULL);
+ if (type == SHA2_256) {
+ bootloader_sha256_finish(sha_handle, NULL);
+ }
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+ else if (type == SHA2_384) {
+ bootloader_sha512_finish(sha_handle, NULL);
+ }
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
return ESP_FAIL;
}
- bootloader_sha256_data(sha_handle, image, partial_image_len);
+
+ if (type == SHA2_256) {
+ bootloader_sha256_data(sha_handle, image, partial_image_len);
+ }
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+ else if (type == SHA2_384) {
+ bootloader_sha512_data(sha_handle, image, partial_image_len);
+ }
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
+
bootloader_munmap(image);
flash_offset += partial_image_len;
len -= partial_image_len;
}
- bootloader_sha256_finish(sha_handle, digest);
+
+ if (type == SHA2_256) {
+ bootloader_sha256_finish(sha_handle, digest);
+ }
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+ else if (type == SHA2_384) {
+ bootloader_sha512_finish(sha_handle, digest);
+ }
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
return ESP_OK;
}
+
+esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
+{
+ return bootloader_sha_flash_contents(SHA2_256, flash_offset, len, digest);
+}
+
+#if SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384
+esp_err_t bootloader_sha384_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
+{
+ return bootloader_sha_flash_contents(SHA2_384, flash_offset, len, digest);
+}
+#endif /* SOC_SHA_SUPPORT_SHA384 && SOC_ECDSA_SUPPORT_CURVE_P384 */
diff --git a/bootloader_components/bootloader_support/src/bootloader_utility_tee.c b/bootloader_components/bootloader_support/src/bootloader_utility_tee.c
new file mode 100644
index 0000000..c6efd2e
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/bootloader_utility_tee.c
@@ -0,0 +1,260 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+#include <stdint.h>
+
+#include "esp_attr.h"
+#include "esp_log.h"
+
+#include "esp_rom_sys.h"
+#include "esp_rom_crc.h"
+
+#include "hal/efuse_hal.h"
+
+#include "esp_image_format.h"
+#include "bootloader_config.h"
+#include "bootloader_flash_priv.h"
+
+#include "bootloader_utility.h"
+#include "bootloader_utility_tee.h"
+#include "esp_tee_ota_utils.h"
+
+#include "sdkconfig.h"
+
+static const char *TAG = "boot_tee";
+
+static esp_err_t write_tee_otadata_sector(esp_tee_ota_select_entry_t *tee_otadata, uint32_t offset)
+{
+ if (tee_otadata == NULL) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ esp_err_t err = bootloader_flash_erase_sector(offset / FLASH_SECTOR_SIZE);
+ if (err == ESP_OK) {
+ bool write_encrypted = false;
+#if !CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
+ write_encrypted = efuse_hal_flash_encryption_enabled();
+#endif
+ err = bootloader_flash_write(offset, tee_otadata, sizeof(esp_tee_ota_select_entry_t), write_encrypted);
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to write otadata sector, 0x%x", err);
+ }
+ }
+
+ return err;
+}
+
+static esp_err_t read_tee_otadata(const esp_partition_pos_t *tee_ota_info, esp_tee_ota_select_entry_t *two_otadata)
+{
+ if (tee_ota_info == NULL || two_otadata == NULL || tee_ota_info->offset == 0) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ if (tee_ota_info->size < 2 * FLASH_SECTOR_SIZE) {
+ return ESP_ERR_INVALID_SIZE;
+ }
+
+ ESP_LOGV(TAG, "TEE OTA data offset 0x%"PRIx32, tee_ota_info->offset);
+
+ const esp_tee_ota_select_entry_t *ota_select_map = bootloader_mmap(tee_ota_info->offset, tee_ota_info->size);
+ if (!ota_select_map) {
+ ESP_LOGE(TAG, "bootloader_mmap(0x%"PRIx32", 0x%"PRIx32") failed", tee_ota_info->offset, tee_ota_info->size);
+ return ESP_FAIL;
+ }
+
+ memcpy(&two_otadata[0], (uint8_t *)ota_select_map, sizeof(esp_tee_ota_select_entry_t));
+ memcpy(&two_otadata[1], (uint8_t *)ota_select_map + FLASH_SECTOR_SIZE, sizeof(esp_tee_ota_select_entry_t));
+
+ bootloader_munmap(ota_select_map);
+
+ return ESP_OK;
+}
+
+static esp_err_t write_tee_otadata(esp_tee_ota_select_entry_t *tee_otadata, const esp_partition_pos_t *tee_ota_info)
+{
+ esp_err_t err = write_tee_otadata_sector(tee_otadata, tee_ota_info->offset);
+ if (err == ESP_OK) {
+ err = write_tee_otadata_sector(tee_otadata, tee_ota_info->offset + FLASH_SECTOR_SIZE);
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to update otadata sector, 0x%x", err);
+ }
+ }
+
+ return err;
+}
+
+static esp_err_t get_valid_tee_otadata(const esp_partition_pos_t *tee_ota_info, esp_tee_ota_select_entry_t *tee_otadata)
+{
+ esp_tee_ota_select_entry_t two_otadata[2] = {0};
+ if (read_tee_otadata(tee_ota_info, two_otadata) != ESP_OK) {
+ return ESP_ERR_NOT_FOUND;
+ }
+
+ esp_tee_ota_select_entry_t blank_otadata;
+ memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
+
+ // Check if the contents of both the otadata sectors match
+ bool sectors_match = (memcmp(&two_otadata[0], &two_otadata[1], sizeof(esp_tee_ota_select_entry_t)) == 0);
+ if (sectors_match) {
+ if (memcmp(&two_otadata[0], &blank_otadata, sizeof(esp_tee_ota_select_entry_t)) != 0) {
+ uint32_t crc = esp_rom_crc32_le(0, (uint8_t const *)two_otadata, (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
+ if (two_otadata[0].magic != TEE_OTADATA_MAGIC || crc != two_otadata[0].crc) {
+ ESP_LOGE(TAG, "TEE otadata[0] magic or CRC verification failed");
+ return ESP_FAIL;
+ }
+ }
+ memcpy(tee_otadata, &two_otadata[0], sizeof(esp_tee_ota_select_entry_t));
+ ESP_LOGV(TAG, "Both tee_otadata sectors are the same");
+ } else {
+ uint32_t crc_otadata0 = esp_rom_crc32_le(0, (uint8_t const *)&two_otadata[0], (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
+ uint32_t crc_otadata1 = esp_rom_crc32_le(0, (uint8_t const *)&two_otadata[1], (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
+
+ if (crc_otadata0 == two_otadata[0].crc) {
+ ESP_LOGV(TAG, "Second tee_otadata sector is invalid - copying contents from first sector");
+ // Copy contents of first tee_otadata sector into second
+ write_tee_otadata_sector(&two_otadata[0], tee_ota_info->offset + FLASH_SECTOR_SIZE);
+ memcpy(tee_otadata, &two_otadata[0], sizeof(esp_tee_ota_select_entry_t));
+ } else if (crc_otadata1 == two_otadata[1].crc) {
+ ESP_LOGV(TAG, "First tee_otadata sector is invalid - copying contents from second sector");
+ // Copy contents of second tee_otadata sector into first
+ write_tee_otadata_sector(&two_otadata[1], tee_ota_info->offset);
+ memcpy(tee_otadata, &two_otadata[1], sizeof(esp_tee_ota_select_entry_t));
+ } else {
+ ESP_LOGE(TAG, "Both tee_otadata sectors are invalid!");
+ abort();
+ }
+ }
+
+ return ESP_OK;
+}
+
+static esp_err_t update_tee_otadata(const esp_partition_pos_t *tee_ota_info, uint8_t boot_partition, uint8_t ota_state)
+{
+ esp_tee_ota_select_entry_t otadata = {
+ .magic = TEE_OTADATA_MAGIC,
+ .boot_partition = boot_partition,
+ .ota_state = ota_state,
+ };
+ otadata.crc = esp_rom_crc32_le(0, (uint8_t const *)&otadata, (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
+ return write_tee_otadata(&otadata, tee_ota_info);
+}
+
+int bootloader_utility_tee_get_boot_partition(const esp_partition_pos_t *tee_ota_info)
+{
+ esp_tee_ota_select_entry_t otadata = {}, blank_otadata;
+ const int default_tee_app_slot = PART_SUBTYPE_TEE_0;
+
+ esp_err_t err = get_valid_tee_otadata(tee_ota_info, &otadata);
+ if (err == ESP_ERR_NOT_FOUND) {
+ ESP_LOGV(TAG, "otadata partition not found, booting from first partition");
+ return default_tee_app_slot;
+ }
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to get valid otadata, 0x%x", err);
+ return -1;
+ }
+ memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
+ if (!memcmp(&blank_otadata, &otadata, sizeof(esp_tee_ota_select_entry_t))) {
+ ESP_LOGV(TAG, "otadata partition empty, booting from first partition");
+ /* NOTE: The first TEE partition will always be valid as it is flashed manually */
+ if (update_tee_otadata(tee_ota_info, default_tee_app_slot, ESP_TEE_OTA_IMG_VALID) != ESP_OK) {
+ ESP_LOGW(TAG, "Failed to setup TEE otadata as per the first partition!");
+ }
+ return default_tee_app_slot;
+ }
+
+ int boot_partition = 0;
+
+#if BOOTLOADER_BUILD
+ switch(otadata.ota_state) {
+ case ESP_TEE_OTA_IMG_NEW:
+ ESP_LOGD(TAG, "TEE otadata - Current image state: NEW");
+ boot_partition = otadata.boot_partition;
+ if (update_tee_otadata(tee_ota_info, otadata.boot_partition, ESP_TEE_OTA_IMG_PENDING_VERIFY) != ESP_OK) {
+ return -1;
+ }
+ break;
+ case ESP_TEE_OTA_IMG_UNDEFINED:
+ case ESP_TEE_OTA_IMG_PENDING_VERIFY:
+ ESP_LOGD(TAG, "TEE otadata - Current image state: PENDING_VERIFY/UNDEFINED");
+ boot_partition = (otadata.boot_partition == PART_SUBTYPE_TEE_0) ? PART_SUBTYPE_TEE_1 : PART_SUBTYPE_TEE_0;
+ if (update_tee_otadata(tee_ota_info, boot_partition, ESP_TEE_OTA_IMG_INVALID) != ESP_OK) {
+ return -1;
+ }
+ break;
+ case ESP_TEE_OTA_IMG_INVALID:
+ ESP_LOGD(TAG, "TEE otadata - Current image state: INVALID");
+ bootloader_reset();
+ break;
+ case ESP_TEE_OTA_IMG_VALID:
+ ESP_LOGD(TAG, "TEE otadata - Current image state: VALID");
+ boot_partition = otadata.boot_partition;
+ break;
+ break;
+ default:
+ break;
+ }
+#else
+ boot_partition = otadata.boot_partition;
+#endif
+
+ return boot_partition;
+}
+
+esp_err_t bootloader_utility_tee_set_boot_partition(const esp_partition_pos_t *tee_ota_info, const esp_partition_info_t *tee_try_part)
+{
+ if (tee_ota_info == NULL || tee_try_part == NULL) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ if (tee_try_part->subtype != PART_SUBTYPE_TEE_0 && tee_try_part->subtype != PART_SUBTYPE_TEE_1) {
+ return ESP_ERR_INVALID_ARG;
+ }
+
+ esp_image_metadata_t data = {};
+ if (esp_image_verify(ESP_IMAGE_VERIFY, &tee_try_part->pos, &data) != ESP_OK) {
+ return ESP_ERR_IMAGE_INVALID;
+ }
+
+ return update_tee_otadata(tee_ota_info, tee_try_part->subtype, ESP_TEE_OTA_IMG_NEW);
+}
+
+int bootloader_utility_tee_get_next_update_partition(const esp_partition_pos_t *tee_ota_info)
+{
+ esp_tee_ota_select_entry_t otadata = {}, blank_otadata;
+ const int default_tee_next_app_slot = PART_SUBTYPE_TEE_1;
+
+ esp_err_t err = get_valid_tee_otadata(tee_ota_info, &otadata);
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to get valid otadata, 0x%x", err);
+ return -1;
+ }
+ memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
+ if (!memcmp(&blank_otadata, &otadata, sizeof(esp_tee_ota_select_entry_t))) {
+ return default_tee_next_app_slot;
+ }
+
+ return (otadata.boot_partition == PART_SUBTYPE_TEE_0) ? PART_SUBTYPE_TEE_1 : PART_SUBTYPE_TEE_0;
+}
+
+esp_err_t bootloader_utility_tee_mark_app_valid_and_cancel_rollback(const esp_partition_pos_t *tee_ota_info)
+{
+ esp_tee_ota_select_entry_t two_otadata[2];
+
+ esp_err_t err = read_tee_otadata(tee_ota_info, two_otadata);
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Failed to fetch TEE otadata!");
+ return err;
+ }
+
+ if (two_otadata[0].ota_state == ESP_TEE_OTA_IMG_VALID) {
+ ESP_LOGD(TAG, "TEE otadata - Current image already has been marked VALID");
+ return ESP_ERR_INVALID_STATE;
+ }
+
+ int tee_app_slot = bootloader_utility_tee_get_boot_partition(tee_ota_info);
+ return update_tee_otadata(tee_ota_info, (uint8_t)tee_app_slot, ESP_TEE_OTA_IMG_VALID);
+}
diff --git a/bootloader_components/bootloader_support/src/esp32/bootloader_esp32.c b/bootloader_components/bootloader_support/src/esp32/bootloader_esp32.c
index 5ce6d3e..f57816a 100644
--- a/bootloader_components/bootloader_support/src/esp32/bootloader_esp32.c
+++ b/bootloader_components/bootloader_support/src/esp32/bootloader_esp32.c
@@ -190,7 +190,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32/bootloader_sha.c
deleted file mode 100644
index d69ad06..0000000
--- a/bootloader_components/bootloader_support/src/esp32/bootloader_sha.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32/rom/sha.h"
-#include "soc/dport_reg.h"
-#include "soc/hwcrypto_periph.h"
-
-static uint32_t words_hashed;
-
-// Words per SHA256 block
-static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t));
-// Words in final SHA256 digest
-static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
-
-bootloader_sha256_handle_t bootloader_sha256_start(void)
-{
- // Enable SHA hardware
- ets_sha_enable();
- words_hashed = 0;
- return (bootloader_sha256_handle_t)&words_hashed; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- assert(data_len % 4 == 0);
-
- const uint32_t *w = (const uint32_t *)data;
- size_t word_len = data_len / 4;
- uint32_t *sha_text_reg = (uint32_t *)(SHA_TEXT_BASE);
-
- while (word_len > 0) {
- size_t block_count = words_hashed % BLOCK_WORDS;
- size_t copy_words = (BLOCK_WORDS - block_count);
-
- copy_words = MIN(word_len, copy_words);
-
- // Wait for SHA engine idle
- while (_DPORT_REG_READ(SHA_256_BUSY_REG) != 0) { }
-
- // Copy to memory block
- for (size_t i = 0; i < copy_words; i++) {
- sha_text_reg[block_count + i] = __builtin_bswap32(w[i]);
- }
- asm volatile ("memw");
-
- // Update counters
- words_hashed += copy_words;
- block_count += copy_words;
- word_len -= copy_words;
- w += copy_words;
-
- // If we loaded a full block, run the SHA engine
- if (block_count == BLOCK_WORDS) {
- if (words_hashed == BLOCK_WORDS) {
- _DPORT_REG_WRITE(SHA_256_START_REG, 1);
- } else {
- _DPORT_REG_WRITE(SHA_256_CONTINUE_REG, 1);
- }
- block_count = 0;
- }
- }
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- return; // We'd free resources here, but there are none to free
- }
-
- uint32_t data_words = words_hashed;
-
- // Pad to a 55 byte long block loaded in the engine
- // (leaving 1 byte 0x80 plus variable padding plus 8 bytes of length,
- // to fill a 64 byte block.)
- int block_bytes = (words_hashed % BLOCK_WORDS) * 4;
- int pad_bytes = 55 - block_bytes;
- if (pad_bytes < 0) {
- pad_bytes += 64;
- }
- static const uint8_t padding[64] = { 0x80, 0, };
-
- pad_bytes += 5; // 1 byte for 0x80 plus first 4 bytes of the 64-bit length
- assert(pad_bytes % 4 == 0); // should be, as (block_bytes % 4 == 0)
-
- bootloader_sha256_data(handle, padding, pad_bytes);
-
- assert(words_hashed % BLOCK_WORDS == 60 / 4); // 32-bits left in block
-
- // Calculate 32-bit length for final 32 bits of data
- uint32_t bit_count = __builtin_bswap32( data_words * 32 );
- bootloader_sha256_data(handle, &bit_count, sizeof(bit_count));
-
- assert(words_hashed % BLOCK_WORDS == 0);
-
- while (_DPORT_REG_READ(SHA_256_BUSY_REG) == 1) { }
- _DPORT_REG_WRITE(SHA_256_LOAD_REG, 1);
- while (_DPORT_REG_READ(SHA_256_BUSY_REG) == 1) { }
-
- uint32_t *digest_words = (uint32_t *)digest;
- uint32_t *sha_text_reg = (uint32_t *)(SHA_TEXT_BASE);
- for (size_t i = 0; i < DIGEST_WORDS; i++) {
- digest_words[i] = __builtin_bswap32(sha_text_reg[i]);
- }
- asm volatile ("memw");
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c2/bootloader_esp32c2.c b/bootloader_components/bootloader_support/src/esp32c2/bootloader_esp32c2.c
index 665ccca..c867d13 100644
--- a/bootloader_components/bootloader_support/src/esp32c2/bootloader_esp32c2.c
+++ b/bootloader_components/bootloader_support/src/esp32c2/bootloader_esp32c2.c
@@ -106,7 +106,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32c2/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32c2/bootloader_sha.c
deleted file mode 100644
index 77fdb00..0000000
--- a/bootloader_components/bootloader_support/src/esp32c2/bootloader_sha.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32c2/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- /* C2 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
- * While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
- * ets_sha_update handles it cleanly so we can safely remove the check:
- * assert(data_len % 4) == 0
- */
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c3/bootloader_esp32c3.c b/bootloader_components/bootloader_support/src/esp32c3/bootloader_esp32c3.c
index b693db3..6e5dd0b 100644
--- a/bootloader_components/bootloader_support/src/esp32c3/bootloader_esp32c3.c
+++ b/bootloader_components/bootloader_support/src/esp32c3/bootloader_esp32c3.c
@@ -145,7 +145,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32c3/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32c3/bootloader_sha.c
deleted file mode 100644
index 2dc321b..0000000
--- a/bootloader_components/bootloader_support/src/esp32c3/bootloader_sha.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32c3/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- assert(data_len % 4 == 0);
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c5/bootloader_esp32c5.c b/bootloader_components/bootloader_support/src/esp32c5/bootloader_esp32c5.c
index d7258e5..bd7511f 100644
--- a/bootloader_components/bootloader_support/src/esp32c5/bootloader_esp32c5.c
+++ b/bootloader_components/bootloader_support/src/esp32c5/bootloader_esp32c5.c
@@ -43,6 +43,7 @@
#include "hal/lpwdt_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "hal/brownout_ll.h"
+#include "hal/axi_icm_ll.h"
static const char *TAG = "boot.esp32c5";
@@ -85,7 +86,10 @@ static void bootloader_super_wdt_auto_feed(void)
static inline void bootloader_hardware_init(void)
{
- regi2c_ctrl_ll_master_enable_clock(true);
+ // Clear bit reset_event_bypass to ensure that the system bus is also reset during a core reset (WDT),
+ // preventing bus freezing caused by an incorrect MSPI core reset in ROM.
+ axi_icm_ll_reset_with_core_reset(true);
+ _regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-8667 Remove this?
regi2c_ctrl_ll_master_configure_clock();
}
@@ -94,15 +98,20 @@ static inline void bootloader_ana_reset_config(void)
{
//Enable BOD reset (mode1)
brownout_ll_ana_reset_enable(true);
- if (efuse_hal_chip_revision() == 0) {
- // decrease power glitch reset voltage to avoid start the glitch reset
- uint8_t power_glitch_dref = 0;
- bootloader_power_glitch_reset_config(true, power_glitch_dref);
- }
+ bootloader_power_glitch_reset_config(true);
}
esp_err_t bootloader_init(void)
{
+#if CONFIG_SECURE_BOOT
+#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
+ if (efuse_hal_chip_revision() == 0) {
+ ESP_LOGE(TAG, "Chip version 0.0 is not supported with RSA secure boot scheme. Please select the ECDSA scheme.");
+ return ESP_ERR_NOT_SUPPORTED;
+ }
+#endif /* CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME */
+#endif /* CONFIG_SECURE_BOOT */
+
esp_err_t ret = ESP_OK;
bootloader_hardware_init();
@@ -122,7 +131,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32c5/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32c5/bootloader_sha.c
deleted file mode 100644
index 57c77e8..0000000
--- a/bootloader_components/bootloader_support/src/esp32c5/bootloader_sha.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32c5/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- /* C5 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
- * While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
- * ets_sha_update handles it cleanly so we can safely remove the check:
- * assert(data_len % 4) == 0
- */
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c5/bootloader_soc.c b/bootloader_components/bootloader_support/src/esp32c5/bootloader_soc.c
index 1e43354..74c4b20 100644
--- a/bootloader_components/bootloader_support/src/esp32c5/bootloader_soc.c
+++ b/bootloader_components/bootloader_support/src/esp32c5/bootloader_soc.c
@@ -17,19 +17,19 @@ void bootloader_ana_clock_glitch_reset_config(bool enable)
(void)enable;
}
-void bootloader_power_glitch_reset_config(bool enable, uint8_t dref)
+void bootloader_power_glitch_reset_config(bool enable)
{
- assert(dref < 8);
- REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0);
+ //only detect VDDPST POWER GLITCH
+ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
+ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_PERIF, 0);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_XTAL, 0);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_PLL, 0);
+
+ REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0);//default val for chip from ECO1
if (enable) {
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PERIF, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_VDDPST, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_XTAL, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLL, dref);
- REG_SET_FIELD(LP_ANA_CK_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0xf);
+ REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0xf);//default val for chip from ECO1
} else {
- REG_SET_FIELD(LP_ANA_CK_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0);
+ REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_PWR_GLITCH_RESET_ENA, 0);
}
}
diff --git a/bootloader_components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c b/bootloader_components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c
index ad90f30..683b9f7 100644
--- a/bootloader_components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c
+++ b/bootloader_components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c
@@ -1,18 +1,20 @@
/*
- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+#include <stdint.h>
#include <strings.h>
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"
-#include "sdkconfig.h"
#include "hal/key_mgr_ll.h"
-#include "hal/mspi_timing_tuning_ll.h"
+#include "hal/mspi_ll.h"
+#include "soc/soc_caps.h"
+#include "sdkconfig.h"
static __attribute__((unused)) const char *TAG = "flash_encrypt";
@@ -42,6 +44,12 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
+#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
+ ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
+ uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
+ esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
+#endif
+
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
// otherwise the Flash Encryption key cannot be read protected
@@ -63,12 +71,9 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
esp_err_t esp_flash_encryption_enable_key_mgr(void)
{
- // Enable and reset key manager
- // To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV
- int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
- key_mgr_ll_enable_bus_clock(true);
- key_mgr_ll_enable_peripheral_clock(true);
- key_mgr_ll_reset_register();
+ _key_mgr_ll_enable_bus_clock(true);
+ _key_mgr_ll_enable_peripheral_clock(true);
+ _key_mgr_ll_reset_register();
while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) {
};
diff --git a/bootloader_components/bootloader_support/src/esp32c5/secure_boot_secure_features.c b/bootloader_components/bootloader_support/src/esp32c5/secure_boot_secure_features.c
index 272f252..b38fab5 100644
--- a/bootloader_components/bootloader_support/src/esp32c5/secure_boot_secure_features.c
+++ b/bootloader_components/bootloader_support/src/esp32c5/secure_boot_secure_features.c
@@ -49,6 +49,10 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
#endif
+#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
+ esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_SHA384_EN);
+#endif
+
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
diff --git a/bootloader_components/bootloader_support/src/esp32c6/bootloader_esp32c6.c b/bootloader_components/bootloader_support/src/esp32c6/bootloader_esp32c6.c
index 2930188..54fa88a 100644
--- a/bootloader_components/bootloader_support/src/esp32c6/bootloader_esp32c6.c
+++ b/bootloader_components/bootloader_support/src/esp32c6/bootloader_esp32c6.c
@@ -96,7 +96,7 @@ static inline void bootloader_hardware_init(void)
esp_rom_spiflash_fix_dummylen(1, 1);
#endif
- regi2c_ctrl_ll_master_enable_clock(true);
+ _regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_configure_clock();
}
@@ -129,7 +129,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32c6/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32c6/bootloader_sha.c
deleted file mode 100644
index 861b927..0000000
--- a/bootloader_components/bootloader_support/src/esp32c6/bootloader_sha.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32c6/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- /* C6 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
- * While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
- * ets_sha_update handles it cleanly so we can safely remove the check:
- * assert(data_len % 4) == 0
- */
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c61/bootloader_esp32c61.c b/bootloader_components/bootloader_support/src/esp32c61/bootloader_esp32c61.c
index d9b65d3..55137ac 100644
--- a/bootloader_components/bootloader_support/src/esp32c61/bootloader_esp32c61.c
+++ b/bootloader_components/bootloader_support/src/esp32c61/bootloader_esp32c61.c
@@ -44,6 +44,7 @@
#include "hal/lpwdt_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "hal/brownout_ll.h"
+#include "hal/axi_icm_ll.h"
static const char *TAG = "boot.esp32c61";
@@ -86,7 +87,10 @@ static void bootloader_super_wdt_auto_feed(void)
static inline void bootloader_hardware_init(void)
{
- regi2c_ctrl_ll_master_enable_clock(true);
+ // Clear bit reset_event_bypass to ensure that the system bus is also reset during a core reset (WDT),
+ // preventing bus freezing caused by an incorrect MSPI core reset in ROM.
+ axi_icm_ll_reset_with_core_reset(true);
+ _regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-9274 Remove this?
regi2c_ctrl_ll_master_configure_clock();
}
@@ -95,8 +99,7 @@ static inline void bootloader_ana_reset_config(void)
{
//Enable BOD reset (mode1)
brownout_ll_ana_reset_enable(true);
- uint8_t power_glitch_dref = 0;
- bootloader_power_glitch_reset_config(true, power_glitch_dref);
+ bootloader_power_glitch_reset_config(true);
}
esp_err_t bootloader_init(void)
@@ -119,7 +122,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32c61/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32c61/bootloader_sha.c
deleted file mode 100644
index 4722094..0000000
--- a/bootloader_components/bootloader_support/src/esp32c61/bootloader_sha.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32c61/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- /* C61 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
- * While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
- * ets_sha_update handles it cleanly so we can safely remove the check:
- * assert(data_len % 4) == 0
- */
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32c61/bootloader_soc.c b/bootloader_components/bootloader_support/src/esp32c61/bootloader_soc.c
index 055fe37..52e2d9d 100644
--- a/bootloader_components/bootloader_support/src/esp32c61/bootloader_soc.c
+++ b/bootloader_components/bootloader_support/src/esp32c61/bootloader_soc.c
@@ -11,24 +11,24 @@
#include "hal/regi2c_ctrl.h"
#include "soc/regi2c_saradc.h"
-//Not supported but common bootloader calls the function. Do nothing
void bootloader_ana_clock_glitch_reset_config(bool enable)
{
+ // TODO: IDF-9274
(void)enable;
}
-void bootloader_power_glitch_reset_config(bool enable, uint8_t dref)
+void bootloader_power_glitch_reset_config(bool enable)
{
- assert(dref < 8);
- REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0);
+ //only detect VDDPST POWER GLITCH
+ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
+ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_PERIF, 0);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_PLLBB, 0);
+ REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_XPD_VDET_PLL, 0);
+
+ REG_SET_FIELD(LP_ANA_FIB_ENABLE_REG, LP_ANA_ANA_FIB_PWR_GLITCH_ENA, 0);//default val for chip from ECO2
if (enable) {
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
- SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PERIF, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_VDDPST, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLLBB, dref);
- REGI2C_WRITE_MASK(I2C_SAR_ADC, POWER_GLITCH_DREF_VDET_PLL, dref);
- REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_POWER_GLITCH_RESET_ENA, 0xf);
+ REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_POWER_GLITCH_RESET_ENA, 0xf);//default val for chip from ECO2
} else {
REG_SET_FIELD(LP_ANA_POWER_GLITCH_CNTL_REG, LP_ANA_POWER_GLITCH_RESET_ENA, 0);
}
diff --git a/bootloader_components/bootloader_support/src/esp32c61/flash_encryption_secure_features.c b/bootloader_components/bootloader_support/src/esp32c61/flash_encryption_secure_features.c
index c1a12fd..c865373 100644
--- a/bootloader_components/bootloader_support/src/esp32c61/flash_encryption_secure_features.c
+++ b/bootloader_components/bootloader_support/src/esp32c61/flash_encryption_secure_features.c
@@ -40,6 +40,12 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
+#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
+ ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
+ uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
+ esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
+#endif
+
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
// otherwise the Flash Encryption key cannot be read protected
diff --git a/bootloader_components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/bootloader_components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
index 7d79902..f7379fe 100644
--- a/bootloader_components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
+++ b/bootloader_components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
@@ -90,8 +90,9 @@ static inline void bootloader_hardware_init(void)
CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_RFPLL);
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_FORCE_RFPLL);
- regi2c_ctrl_ll_master_enable_clock(true);
+ _regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_configure_clock();
+
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_0P8, 8); // fix low temp issue, need to increase this internal voltage
}
@@ -125,7 +126,7 @@ esp_err_t bootloader_init(void)
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
- ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32h2/bootloader_sha.c b/bootloader_components/bootloader_support/src/esp32h2/bootloader_sha.c
deleted file mode 100644
index 212345c..0000000
--- a/bootloader_components/bootloader_support/src/esp32h2/bootloader_sha.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "bootloader_sha.h"
-#include <stdbool.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/param.h>
-
-#include "esp32h2/rom/sha.h"
-
-static SHA_CTX ctx;
-
-bootloader_sha256_handle_t bootloader_sha256_start()
-{
- // Enable SHA hardware
- ets_sha_enable();
- ets_sha_init(&ctx, SHA2_256);
- return &ctx; // Meaningless non-NULL value
-}
-
-void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
-{
- assert(handle != NULL);
- /* H2 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
- * While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
- * ets_sha_update handles it cleanly so we can safely remove the check:
- * assert(data_len % 4) == 0
- */
- ets_sha_update(&ctx, data, data_len, false);
-}
-
-void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
-{
- assert(handle != NULL);
-
- if (digest == NULL) {
- bzero(&ctx, sizeof(ctx));
- return;
- }
- ets_sha_finish(&ctx, digest);
-}
diff --git a/bootloader_components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c b/bootloader_components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c
index f1a6d2a..db92b41 100644
--- a/bootloader_components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c
+++ b/bootloader_components/bootloader_support/src/esp32h2/flash_encryption_secure_features.c
@@ -1,15 +1,18 @@
/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
+#include <stdint.h>
#include <strings.h>
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"
+#include "hal/spi_flash_encrypted_ll.h"
+#include "soc/soc_caps.h"
#include "sdkconfig.h"
static __attribute__((unused)) const char *TAG = "flash_encrypt";
@@ -33,6 +36,14 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
+#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
+ if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
+ ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
+ uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
+ esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
+ }
+#endif
+
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
// otherwise the Flash Encryption key cannot be read protected
@@ -44,7 +55,7 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
// esp32h2 has DIS_ICACHE. Write-protection bit = 2.
// List of eFuses with the same write protection bit:
// DIS_ICACHE, DIS_USB_JTAG, POWERGLITCH_EN, DIS_FORCE_DOWNLOAD, SPI_DOWNLOAD_MSPI_DIS,
- // DIS_TWAI, JTAG_SEL_ENABLE, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT
+ // DIS_TWAI, JTAG_SEL_ENABLE, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_SERIAL_JTAG
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_ICACHE);
#endif
diff --git a/bootloader_components/bootloader_support/src/esp32h2/secure_boot_secure_features.c b/bootloader_components/bootloader_support/src/esp32h2/secure_boot_secure_features.c
index 9ea0f69..18f4e07 100644
--- a/bootloader_components/bootloader_support/src/esp32h2/secure_boot_secure_features.c
+++ b/bootloader_components/bootloader_support/src/esp32h2/secure_boot_secure_features.c
@@ -1,10 +1,11 @@
/*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <strings.h>
+#include "hal/ecdsa_ll.h"
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
diff --git a/bootloader_components/bootloader_support/src/esp32h21/bootloader_esp32h21.c b/bootloader_components/bootloader_support/src/esp32h21/bootloader_esp32h21.c
new file mode 100644
index 0000000..65e49e1
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/esp32h21/bootloader_esp32h21.c
@@ -0,0 +1,173 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_image_format.h"
+#include "flash_qio_mode.h"
+#include "esp_rom_gpio.h"
+#include "esp_rom_uart.h"
+#include "esp_rom_sys.h"
+#include "esp_rom_spiflash.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/io_mux_reg.h"
+#include "soc/assist_debug_reg.h"
+#include "esp_cpu.h"
+#include "soc/rtc.h"
+#include "soc/spi_periph.h"
+#include "soc/cache_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/pcr_reg.h"
+#include "rom/ets_sys.h"
+#include "bootloader_common.h"
+#include "bootloader_init.h"
+#include "bootloader_clock.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
+#include "esp_private/regi2c_ctrl.h"
+#include "soc/regi2c_lp_bias.h"
+#include "soc/regi2c_bias.h"
+#include "bootloader_console.h"
+#include "bootloader_flash_priv.h"
+#include "bootloader_soc.h"
+#include "esp_private/bootloader_flash_internal.h"
+#include "esp_efuse.h"
+#include "hal/mmu_hal.h"
+#include "hal/cache_hal.h"
+#include "hal/lpwdt_ll.h"
+#include "soc/lp_wdt_reg.h"
+#include "soc/pmu_reg.h"
+#include "hal/efuse_hal.h"
+#include "hal/regi2c_ctrl_ll.h"
+
+static const char *TAG = "boot.esp32h21";
+
+static void wdt_reset_cpu0_info_enable(void)
+{
+ REG_SET_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_CLK_EN);
+ REG_CLR_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_RST_EN);
+ REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_0_RCD_RECORDEN);
+}
+
+static void wdt_reset_info_dump(int cpu)
+{
+ (void) cpu;
+ // saved PC was already printed by the ROM bootloader.
+ // nothing to do here.
+}
+
+static void bootloader_check_wdt_reset(void)
+{
+ int wdt_rst = 0;
+ soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
+ if (rst_reason == RESET_REASON_CORE_RTC_WDT || rst_reason == RESET_REASON_CORE_MWDT0 || rst_reason == RESET_REASON_CORE_MWDT1 ||
+ rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_MWDT1 || rst_reason == RESET_REASON_CPU0_RTC_WDT) {
+ ESP_EARLY_LOGW(TAG, "PRO CPU has been reset by WDT.");
+ wdt_rst = 1;
+ }
+ if (wdt_rst) {
+ // if reset by WDT dump info from trace port
+ wdt_reset_info_dump(0);
+ }
+ wdt_reset_cpu0_info_enable();
+}
+
+static void bootloader_super_wdt_auto_feed(void)
+{
+ REG_WRITE(LP_WDT_SWD_WPROTECT_REG, LP_WDT_SWD_WKEY_VALUE);
+ REG_SET_BIT(LP_WDT_SWD_CONFIG_REG, LP_WDT_SWD_AUTO_FEED_EN);
+ REG_WRITE(LP_WDT_SWD_WPROTECT_REG, 0);
+}
+
+static inline void bootloader_hardware_init(void)
+{
+ /* Disable RF pll by default */
+ CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_RFPLL);
+ SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_FORCE_RFPLL);
+
+ //TODO: [ESP32H21] IDF-11550, regi2c atomic clock
+ regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
+ regi2c_ctrl_ll_master_configure_clock();
+}
+
+static inline void bootloader_ana_reset_config(void)
+{
+ //Enable super WDT reset.
+ bootloader_ana_super_wdt_reset_config(true);
+ //Enable BOD reset (mode1)
+ //TODO: [ESP32H21] IDF-11530
+ // brownout_ll_ana_reset_enable(true);
+}
+
+esp_err_t bootloader_init(void)
+{
+ esp_err_t ret = ESP_OK;
+
+ bootloader_hardware_init();
+ bootloader_ana_reset_config();
+ bootloader_super_wdt_auto_feed();
+
+// In RAM_APP, memory will be initialized in `call_start_cpu0`
+#if !CONFIG_APP_BUILD_TYPE_RAM
+ // protect memory region
+ bootloader_init_mem();
+ /* check that static RAM is after the stack */
+ assert(&_bss_start <= &_bss_end);
+ assert(&_data_start <= &_data_end);
+ // clear bss section
+ bootloader_clear_bss_section();
+#endif // !CONFIG_APP_BUILD_TYPE_RAM
+
+ // init eFuse virtual mode (read eFuses to RAM)
+#ifdef CONFIG_EFUSE_VIRTUAL
+ ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
+#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
+ esp_efuse_init_virtual_mode_in_ram();
+#endif
+#endif
+ // config clock
+ bootloader_clock_configure();
+ // initialize console, from now on, we can use esp_log
+ bootloader_console_init();
+ /* print 2nd bootloader banner */
+ bootloader_print_banner();
+
+#if !CONFIG_APP_BUILD_TYPE_RAM
+ //init cache hal
+ cache_hal_init();
+ //init mmu
+ mmu_hal_init();
+ // update flash ID
+ bootloader_flash_update_id();
+ // Check and run XMC startup flow
+ if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
+ ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
+ return ret;
+ }
+ // read bootloader header
+ if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
+ return ret;
+ }
+ // read chip revision and check if it's compatible to bootloader
+ if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
+ return ret;
+ }
+ // initialize spi flash
+ if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
+ return ret;
+ }
+#endif // !CONFIG_APP_BUILD_TYPE_RAM
+
+ // check whether a WDT reset happened
+ bootloader_check_wdt_reset();
+ // config WDT
+ bootloader_config_wdt();
+ // enable RNG early entropy source
+ bootloader_enable_random();
+
+ return ret;
+}
diff --git a/bootloader_components/bootloader_support/src/esp32h21/bootloader_soc.c b/bootloader_components/bootloader_support/src/esp32h21/bootloader_soc.c
new file mode 100644
index 0000000..094e25d
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/esp32h21/bootloader_soc.c
@@ -0,0 +1,32 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdbool.h>
+#include "soc/lp_analog_peri_reg.h"
+
+void bootloader_ana_super_wdt_reset_config(bool enable)
+{
+ //H21 doesn't support bypass super WDT reset
+ assert(enable);
+ REG_CLR_BIT(LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_SUPER_WDT_RST);
+}
+
+//TODO: [ESP32H21] IDF-11534, there is a `bootloader_ana_bod_reset_config` in verify code, please check
+void bootloader_ana_bod_reset_config(bool enable)
+{
+ REG_CLR_BIT(LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_BOD_RST);
+
+ if (enable) {
+ REG_SET_BIT(LP_ANA_BOD_MODE1_CNTL_REG, LP_ANA_BOD_MODE1_RESET_ENA);
+ } else {
+ REG_CLR_BIT(LP_ANA_BOD_MODE1_CNTL_REG, LP_ANA_BOD_MODE1_RESET_ENA);
+ }
+}
+
+//Not supported but common bootloader calls the function. Do nothing
+void bootloader_ana_clock_glitch_reset_config(bool enable)
+{
+ (void)enable;
+}
diff --git a/bootloader_components/bootloader_support/src/esp32h21/flash_encryption_secure_features.c b/bootloader_components/bootloader_support/src/esp32h21/flash_encryption_secure_features.c
new file mode 100644
index 0000000..e09c249
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/esp32h21/flash_encryption_secure_features.c
@@ -0,0 +1,52 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <strings.h>
+#include "esp_flash_encrypt.h"
+#include "esp_secure_boot.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "esp_log.h"
+#include "sdkconfig.h"
+
+static __attribute__((unused)) const char *TAG = "flash_encrypt";
+
+esp_err_t esp_flash_encryption_enable_secure_features(void)
+{
+#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
+ ESP_LOGI(TAG, "Disable UART bootloader encryption...");
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
+#else
+ ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
+#endif
+
+#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
+ ESP_LOGI(TAG, "Disable JTAG...");
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
+#else
+ ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
+#endif
+
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
+
+#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
+ // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
+ // otherwise the Flash Encryption key cannot be read protected
+ esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS);
+#endif
+
+#ifndef CONFIG_SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE
+ // Set write-protection for DIS_ICACHE to prevent bricking chip in case it will be set accidentally.
+ // esp32h21 has DIS_ICACHE. Write-protection bit = 2.
+ // List of eFuses with the same write protection bit:
+ // DIS_ICACHE, DIS_USB_JTAG, POWERGLITCH_EN, DIS_FORCE_DOWNLOAD, SPI_DOWNLOAD_MSPI_DIS,
+ // DIS_TWAI, JTAG_SEL_ENABLE, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_SERIAL_JTAG
+ esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_ICACHE);
+#endif
+
+ return ESP_OK;
+}
diff --git a/bootloader_components/bootloader_support/src/esp32h21/secure_boot_secure_features.c b/bootloader_components/bootloader_support/src/esp32h21/secure_boot_secure_features.c
new file mode 100644
index 0000000..61ba217
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/esp32h21/secure_boot_secure_features.c
@@ -0,0 +1,70 @@
+/*
+ * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <strings.h>
+#include "esp_flash_encrypt.h"
+#include "esp_secure_boot.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "esp_log.h"
+#include "sdkconfig.h"
+
+static __attribute__((unused)) const char *TAG = "secure_boot";
+
+esp_err_t esp_secure_boot_enable_secure_features(void)
+{
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
+
+#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
+ ESP_LOGI(TAG, "Enabling Security download mode...");
+ esp_err_t err = esp_efuse_enable_rom_secure_download_mode();
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Could not enable Security download mode...");
+ return err;
+ }
+#elif CONFIG_SECURE_DISABLE_ROM_DL_MODE
+ ESP_LOGI(TAG, "Disable ROM Download mode...");
+ esp_err_t err = esp_efuse_disable_rom_download_mode();
+ if (err != ESP_OK) {
+ ESP_LOGE(TAG, "Could not disable ROM Download mode...");
+ return err;
+ }
+#else
+ ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
+#endif
+
+#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
+ ESP_LOGI(TAG, "Disable hardware & software JTAG...");
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
+ esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
+ esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count);
+#else
+ ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
+#endif
+
+#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
+ esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
+#endif
+
+ esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
+
+#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
+ bool rd_dis_now = true;
+#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
+ /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
+ when Flash Encryption is being enabled */
+ rd_dis_now = esp_flash_encryption_enabled();
+#endif
+ if (rd_dis_now) {
+ ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
+ esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS);
+ }
+#else
+ ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
+#endif
+
+ return ESP_OK;
+}
diff --git a/bootloader_components/bootloader_support/src/esp32h4/bootloader_esp32h4.c b/bootloader_components/bootloader_support/src/esp32h4/bootloader_esp32h4.c
new file mode 100644
index 0000000..2dc5c6b
--- /dev/null
+++ b/bootloader_components/bootloader_support/src/esp32h4/bootloader_esp32h4.c
@@ -0,0 +1,212 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_image_format.h"
+#include "flash_qio_mode.h"
+#include "esp_rom_gpio.h"
+#include "esp_rom_efuse.h"
+#include "esp_rom_uart.h"
+#include "esp_rom_sys.h"
+#include "esp_rom_spiflash.h"
+#include "soc/gpio_sig_map.h"
+#include "esp_cpu.h"
+#include "soc/rtc.h"
+#include "soc/spi_periph.h"
+#include "soc/cache_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/pcr_reg.h"
+#include "soc/bus_monitor_reg.h"
+#include "bootloader_common.h"
+#include "bootloader_init.h"
+#include "bootloader_clock.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
+#include "esp_private/regi2c_ctrl.h"
+#include "soc/regi2c_lp_bias.h"
+#include "soc/regi2c_bias.h"
+#include "soc/hp_system_reg.h"
+#include "bootloader_console.h"
+#include "bootloader_flash_priv.h"
+#include "bootloader_soc.h"
+#include "esp_private/bootloader_flash_internal.h"
+#include "esp_efuse.h"
+#include "hal/mmu_hal.h"
+#include "hal/cache_hal.h"
+#include "hal/clk_tree_ll.h"
+#include "soc/lp_wdt_reg.h"
+#include "hal/efuse_hal.h"
+#include "hal/lpwdt_ll.h"
+
+static const char *TAG = "boot.esp32h4";
+
+// TODO: [ESP32H4] support core1 bus monitor IDF-12592
+static void wdt_reset_cpu0_info_enable(void)
+{
+ REG_SET_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_CLK_EN);
+ REG_CLR_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_RST_EN);
+ REG_WRITE(BUS_MONITOR_CORE_0_RCD_EN_REG, BUS_MONITOR_CORE_0_RCD_PDEBUGEN | BUS_MONITOR_CORE_0_RCD_RECORDEN);
+}
+
+static void wdt_reset_info_dump(int cpu)
+{
+ (void) cpu;
+ // saved PC was already printed by the ROWhy this scored 57/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.