Parcourir la source

esp32h2: add bootloader support

Shu Chen il y a 4 ans
Parent
commit
c0056813f2

+ 1 - 1
components/bootloader/subproject/main/CMakeLists.txt

@@ -4,7 +4,7 @@ idf_component_register(SRCS "bootloader_start.c"
 idf_build_get_property(target IDF_TARGET)
 set(scripts "ld/${target}/bootloader.ld")
 
-if(NOT CONFIG_IDF_TARGET_ESP32C3)
+if(NOT CONFIG_IDF_TARGET_ESP32C3 AND NOT CONFIG_IDF_TARGET_ESP32H2)
     list(APPEND scripts "ld/${target}/bootloader.rom.ld")
 endif()
 

+ 190 - 0
components/bootloader/subproject/main/ld/esp32h2/bootloader.ld

@@ -0,0 +1,190 @@
+/** Simplified memory map for the bootloader.
+ *  Make sure the bootloader can load into main memory without overwriting itself.
+ *  We put 2nd bootloader in the high address space (before ROM stack/data/bss).
+ *  See memory usage for ROM bootloader at the end of this file.
+ */
+
+MEMORY
+{
+  iram_seg (RWX) :                  org = 0x403CE000, len = 0x2000
+  iram_loader_seg (RWX) :           org = 0x403D0000, len = 0x6000
+  dram_seg (RW) :                   org = 0x3FCD6000, len = 0x4000
+}
+
+/* Default entry point: */
+ENTRY(call_start_cpu0);
+
+SECTIONS
+{
+
+  .iram_loader.text :
+  {
+    . = ALIGN (16);
+    _loader_text_start = ABSOLUTE(.);
+    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+     *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
+    *liblog.a:(.literal .text .literal.* .text.*)
+    *libgcc.a:(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
+    *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
+    *libbootloader_support.a:bootloader_efuse_esp32h2.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
+    *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
+    *libspi_flash.a:*.*(.literal .text .literal.* .text.*)
+    *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
+    *libefuse.a:*.*(.literal .text .literal.* .text.*)
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+    _loader_text_end = ABSOLUTE(.);
+  } > iram_loader_seg
+
+  .iram.text :
+  {
+    . = ALIGN (16);
+    *(.entry.text)
+    *(.init.literal)
+    *(.init)
+  } > iram_seg
+
+
+  /* Shared RAM */
+  .dram0.bss (NOLOAD) :
+  {
+    . = ALIGN (8);
+    _dram_start = ABSOLUTE(.);
+    _bss_start = ABSOLUTE(.);
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.sbss2)
+    *(.sbss2.*)
+    *(.gnu.linkonce.sb2.*)
+    *(.dynbss)
+    *(.bss)
+    *(.bss.*)
+    *(.gnu.linkonce.b.*)
+    *(COMMON)
+    . = ALIGN (8);
+    _bss_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .dram0.data :
+  {
+    _data_start = ABSOLUTE(.);
+    *(.data)
+    *(.data.*)
+    *(.gnu.linkonce.d.*)
+    *(.data1)
+    *(.sdata)
+    *(.sdata.*)
+    *(.gnu.linkonce.s.*)
+    *(.sdata2)
+    *(.sdata2.*)
+    *(.gnu.linkonce.s2.*)
+    *(.jcr)
+    _data_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .dram0.rodata :
+  {
+    _rodata_start = ABSOLUTE(.);
+    *(.rodata)
+    *(.rodata.*)
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    *(.eh_frame)
+    . = (. + 3) & ~ 3;
+    /* C++ constructor and destructor tables, properly ordered: */
+    __init_array_start = ABSOLUTE(.);
+    KEEP (*crtbegin.*(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    __init_array_end = ABSOLUTE(.);
+    KEEP (*crtbegin.*(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+    /*  C++ exception handlers table:  */
+    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+    *(.xt_except_desc)
+    *(.gnu.linkonce.h.*)
+    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+    *(.xt_except_desc_end)
+    *(.dynamic)
+    *(.gnu.version_d)
+    _rodata_end = ABSOLUTE(.);
+    /* Literals are also RO data. */
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    . = ALIGN(4);
+    _dram_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .iram.text :
+  {
+    _stext = .;
+    _text_start = ABSOLUTE(.);
+    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.iram .iram.*) /* catch stray IRAM_ATTR */
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+
+    /** CPU will try to prefetch up to 16 bytes of
+      * of instructions. This means that any configuration (e.g. MMU, PMS) must allow
+      * safe access to up to 16 bytes after the last real instruction, add
+      * dummy bytes to ensure this
+      */
+    . += 16;
+
+    _text_end = ABSOLUTE(.);
+    _etext = .;
+  } > iram_seg
+
+}
+
+
+/**
+ *  Appendix: Memory Usage of ROM bootloader
+ *
+ *  +--------+--------------+------+ 0x3FCC_B000
+ *  |        ^              |
+ *  |        |              |
+ *  |        | data/bss     |
+ *  |        |              |
+ *  |        v              |
+ *  +------------------------------+ 0x3FCD_C910
+ *  |        ^              |
+ *  |        |              |
+ *  |        | stack        |
+ *  |        |              |
+ *  |        v              |
+ *  +------------------------------+ 0x3FCD_E910
+ */

+ 2 - 0
components/bootloader_support/include/bootloader_common.h

@@ -17,6 +17,8 @@
 #include "esp32s3/rom/rtc.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
 #endif
 
 #ifdef __cplusplus

+ 1 - 0
components/bootloader_support/include/esp_app_format.h

@@ -16,6 +16,7 @@ typedef enum {
     ESP_CHIP_ID_ESP32S2 = 0x0002,  /*!< chip ID: ESP32-S2 */
     ESP_CHIP_ID_ESP32C3 = 0x0005, /*!< chip ID: ESP32-C3 */
     ESP_CHIP_ID_ESP32S3 = 0x0009, /*!< chip ID: ESP32-S3 */
+    ESP_CHIP_ID_ESP32H2 = 0x000A, /*!< chip ID: ESP32-H2 */
     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;
 

+ 3 - 0
components/bootloader_support/include/esp_secure_boot.h

@@ -25,6 +25,9 @@
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/efuse.h"
 #include "esp32s3/rom/secure_boot.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/secure_boot.h"
 #endif
 
 #ifdef CONFIG_SECURE_BOOT_V1_ENABLED

+ 2 - 0
components/bootloader_support/src/bootloader_clock_init.c

@@ -22,6 +22,8 @@
 #include "esp32s3/rom/rtc.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
 #endif
 #include "esp_rom_uart.h"
 

+ 2 - 0
components/bootloader_support/src/bootloader_common.c

@@ -17,6 +17,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 #include "esp_rom_crc.h"
 #include "esp_rom_gpio.h"

+ 3 - 0
components/bootloader_support/src/bootloader_console.c

@@ -22,6 +22,9 @@
 #include "esp32c3/rom/uart.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/uart.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/uart.h"
 #endif
 #include "esp_rom_gpio.h"
 #include "esp_rom_uart.h"

+ 20 - 0
components/bootloader_support/src/bootloader_efuse_esp32h2.c

@@ -0,0 +1,20 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "soc/efuse_reg.h"
+
+uint8_t bootloader_common_get_chip_revision(void)
+{
+    // should return the same value as esp_efuse_get_chip_ver()
+    return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_WAFER_VERSION);
+}
+
+uint32_t bootloader_common_get_chip_ver_pkg(void)
+{
+    // should return the same value as esp_efuse_get_pkg_ver()
+    return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
+}

+ 31 - 1
components/bootloader_support/src/bootloader_flash.c

@@ -29,6 +29,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 
 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@@ -124,6 +126,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
 #include "esp32c3/rom/spi_flash.h"
 #include "esp32c3/rom/cache.h"
 #include "soc/cache_memory.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/cache.h"
+#include "soc/cache_memory.h"
 #endif
 static const char *TAG = "bootloader_flash";
 
@@ -188,6 +194,9 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
     Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
 #endif
     ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
              src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
@@ -195,7 +204,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
 #elif CONFIG_IDF_TARGET_ESP32S2
     int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
-#else // S3, C3
+#else // S3, C3, H2
     int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
 #endif
     if (e != 0) {
@@ -208,6 +217,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
         Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
         Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+        Cache_Resume_ICache(autoload);
 #endif
         return NULL;
     }
@@ -219,6 +230,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
 
     mapped = true;
@@ -248,6 +261,10 @@ void bootloader_munmap(const void *mapping)
         Cache_Suspend_ICache();
         Cache_Invalidate_ICache_All();
         Cache_MMU_Init();
+#elif CONFIG_IDF_TARGET_ESP32H2
+        Cache_Suspend_ICache();
+        Cache_Invalidate_ICache_All();
+        Cache_MMU_Init();
 #endif
         mapped = false;
         current_read_mapping = UINT32_MAX;
@@ -279,6 +296,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
     uint32_t autoload = Cache_Suspend_DCache();
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
 #endif
     esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
 #if CONFIG_IDF_TARGET_ESP32
@@ -289,6 +308,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
 
     return spi_to_esp_err(r);
@@ -316,6 +337,9 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
 #elif CONFIG_IDF_TARGET_ESP32C3
             uint32_t autoload = Cache_Suspend_ICache();
             Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+            uint32_t autoload = Cache_Suspend_ICache();
+            Cache_Invalidate_ICache_All();
 #endif
             ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
 #if CONFIG_IDF_TARGET_ESP32
@@ -326,6 +350,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
             int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
             int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+            int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
 #endif
             if (e != 0) {
                 ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
@@ -337,6 +363,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
                 Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
                 Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+                Cache_Resume_ICache(autoload);
 #endif
                 return ESP_FAIL;
             }
@@ -349,6 +377,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
             Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
             Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+            Cache_Resume_ICache(autoload);
 #endif
         }
         map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));

+ 75 - 0
components/bootloader_support/src/bootloader_flash_config_esp32h2.c

@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 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 "esp32h2/rom/gpio.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/efuse.h"
+#include "soc/gpio_periph.h"
+#include "soc/efuse_reg.h"
+#include "soc/spi_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"
+
+#define FLASH_IO_MATRIX_DUMMY_40M   0
+#define FLASH_IO_MATRIX_DUMMY_80M   0
+
+void bootloader_flash_update_id()
+{
+    esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
+    chip->device_id = bootloader_read_flash_id();
+}
+
+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);
+    SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), 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_80M:
+        spi_clk_div = 1;
+        break;
+    case ESP_IMAGE_SPI_SPEED_40M:
+        spi_clk_div = 2;
+        break;
+    case ESP_IMAGE_SPI_SPEED_26M:
+        spi_clk_div = 3;
+        break;
+    case ESP_IMAGE_SPI_SPEED_20M:
+        spi_clk_div = 4;
+        break;
+    default:
+        break;
+    }
+    esp_rom_spiflash_config_clk(spi_clk_div, 0);
+}
+
+void IRAM_ATTR bootloader_flash_set_dummy_out(void)
+{
+    REG_SET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
+    REG_SET_BIT(SPI_MEM_CTRL_REG(1), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
+}
+
+void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t *pfhdr)
+{
+    bootloader_configure_spi_pins(1);
+    bootloader_flash_set_dummy_out();
+}

+ 24 - 0
components/bootloader_support/src/bootloader_random_esp32h2.c

@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "sdkconfig.h"
+#include "bootloader_random.h"
+#include "esp_log.h"
+#include "soc/syscon_reg.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/apb_saradc_reg.h"
+#include "soc/system_reg.h"
+#include "regi2c_ctrl.h"
+
+// ESP32H2-TODO: IDF-3381
+void bootloader_random_enable(void)
+{
+
+}
+
+void bootloader_random_disable(void)
+{
+
+}

+ 24 - 0
components/bootloader_support/src/bootloader_utility.c

@@ -45,6 +45,18 @@
 #include "esp32c3/rom/secure_boot.h"
 #include "soc/extmem_reg.h"
 #include "soc/cache_memory.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/cache.h"
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/crc.h"
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/uart.h"
+#include "esp32h2/rom/gpio.h"
+#include "esp32h2/rom/secure_boot.h"
+#include "soc/extmem_reg.h"
+#include "soc/cache_memory.h"
 #else // CONFIG_IDF_TARGET_*
 #error "Unsupported IDF_TARGET"
 #endif
@@ -700,6 +712,9 @@ static void set_cache_and_start_app(
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
     Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
 #endif
 
     /* Clear the MMU entries that are already set up,
@@ -726,6 +741,8 @@ static void set_cache_and_start_app(
     rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
     rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
 #endif
     ESP_LOGV(TAG, "rc=%d", rc);
 #if CONFIG_IDF_TARGET_ESP32
@@ -753,6 +770,8 @@ static void set_cache_and_start_app(
     rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
     rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
 #endif
     ESP_LOGV(TAG, "rc=%d", rc);
 #if CONFIG_IDF_TARGET_ESP32
@@ -776,6 +795,9 @@ static void set_cache_and_start_app(
 #elif CONFIG_IDF_TARGET_ESP32C3
     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
 #endif
 #if CONFIG_IDF_TARGET_ESP32
     Cache_Read_Enable(0);
@@ -785,6 +807,8 @@ static void set_cache_and_start_app(
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
     // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
 

+ 327 - 0
components/bootloader_support/src/esp32h2/bootloader_esp32h2.c

@@ -0,0 +1,327 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 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 "soc/efuse_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/io_mux_reg.h"
+#include "soc/assist_debug_reg.h"
+#include "soc/cpu.h"
+#include "soc/rtc.h"
+#include "soc/spi_periph.h"
+#include "soc/extmem_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/system_reg.h"
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/cache.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/rtc.h"
+#include "bootloader_common.h"
+#include "bootloader_init.h"
+#include "bootloader_clock.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
+#include "regi2c_ctrl.h"
+#include "bootloader_console.h"
+#include "bootloader_flash_priv.h"
+
+static const char *TAG = "boot.esp32h2";
+
+void IRAM_ATTR bootloader_configure_spi_pins(int drv)
+{
+    const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
+    uint8_t wp_pin = esp_rom_efuse_get_flash_wp_gpio();
+    uint8_t clk_gpio_num = SPI_CLK_GPIO_NUM;
+    uint8_t q_gpio_num   = SPI_Q_GPIO_NUM;
+    uint8_t d_gpio_num   = SPI_D_GPIO_NUM;
+    uint8_t cs0_gpio_num = SPI_CS0_GPIO_NUM;
+    uint8_t hd_gpio_num  = SPI_HD_GPIO_NUM;
+    uint8_t wp_gpio_num  = SPI_WP_GPIO_NUM;
+    if (spiconfig == 0) {
+
+    } else {
+        clk_gpio_num = spiconfig         & 0x3f;
+        q_gpio_num = (spiconfig >> 6)    & 0x3f;
+        d_gpio_num = (spiconfig >> 12)   & 0x3f;
+        cs0_gpio_num = (spiconfig >> 18) & 0x3f;
+        hd_gpio_num = (spiconfig >> 24)  & 0x3f;
+        wp_gpio_num = wp_pin;
+    }
+    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);
+    if (hd_gpio_num <= MAX_PAD_GPIO_NUM) {
+        esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
+    }
+    if (wp_gpio_num <= MAX_PAD_GPIO_NUM) {
+        esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
+    }
+}
+
+static void bootloader_reset_mmu(void)
+{
+    Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
+    Cache_MMU_Init();
+
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
+}
+
+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;
+    default:
+        size = 2;
+    }
+    uint32_t autoload = Cache_Suspend_ICache();
+    // 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
+    Cache_Resume_ICache(autoload);
+}
+
+static void print_flash_info(const esp_image_header_t *bootloader_hdr)
+{
+    ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
+    ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
+    ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
+    ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
+    ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
+
+    const char *str;
+    switch (bootloader_hdr->spi_speed) {
+    case ESP_IMAGE_SPI_SPEED_40M:
+        str = "40MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_26M:
+        str = "26.7MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_20M:
+        str = "20MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_80M:
+        str = "80MHz";
+        break;
+    default:
+        str = "20MHz";
+        break;
+    }
+    ESP_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 */
+    uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
+    if (spi_ctrl & SPI_MEM_FREAD_QIO) {
+        str = "QIO";
+    } else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
+        str = "QOUT";
+    } else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
+        str = "DIO";
+    } else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
+        str = "DOUT";
+    } else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
+        str = "FAST READ";
+    } else {
+        str = "SLOW READ";
+    }
+    ESP_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;
+    default:
+        str = "2MB";
+        break;
+    }
+    ESP_LOGI(TAG, "SPI Flash Size : %s", str);
+}
+
+static void IRAM_ATTR bootloader_init_flash_configure(void)
+{
+    bootloader_flash_dummy_config(&bootloader_image_hdr);
+    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);
+}
+
+static esp_err_t bootloader_init_spi_flash(void)
+{
+    bootloader_init_flash_configure();
+#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
+    const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
+    if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
+        ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
+        return ESP_FAIL;
+    }
+#endif
+
+    bootloader_spi_flash_resume();
+    esp_rom_spiflash_unlock();
+
+#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
+    bootloader_enable_qio_mode();
+#endif
+
+    print_flash_info(&bootloader_image_hdr);
+    update_flash_config(&bootloader_image_hdr);
+    //ensure the flash is write-protected
+    bootloader_enable_wp();
+    return ESP_OK;
+}
+
+static void wdt_reset_cpu0_info_enable(void)
+{
+    REG_SET_BIT(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
+    REG_CLR_BIT(SYSTEM_CPU_PERI_RST_EN_REG, SYSTEM_RST_EN_ASSIST_DEBUG);
+    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;
+    RESET_REASON rst_reas[2];
+
+    rst_reas[0] = rtc_get_reset_reason(0);
+    if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
+            rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
+        ESP_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(RTC_CNTL_SWD_WPROTECT_REG, RTC_CNTL_SWD_WKEY_VALUE);
+    REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
+    REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
+}
+
+static inline void bootloader_hardware_init(void)
+{
+    // This check is always included in the bootloader so it can
+    // print the minimum revision error message later in the boot
+    if (bootloader_common_get_chip_revision() < 3) {
+        REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
+        REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
+    }
+}
+
+static inline void bootloader_glitch_reset_disable(void)
+{
+    /*
+      For origin chip & ECO1: only support swt reset;
+      For ECO2: fix brownout reset bug, support swt & brownout reset;
+      For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
+    */
+    uint8_t chip_version = bootloader_common_get_chip_revision();
+    if (chip_version < 2) {
+        REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
+    } else if (chip_version == 2) {
+        REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
+    }
+}
+
+esp_err_t bootloader_init(void)
+{
+    esp_err_t ret = ESP_OK;
+
+    bootloader_hardware_init();
+    bootloader_glitch_reset_disable();
+    bootloader_super_wdt_auto_feed();
+    // 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();
+    // reset MMU
+    bootloader_reset_mmu();
+    // 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();
+    // update flash ID
+    bootloader_flash_update_id();
+    // read bootloader header
+    if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
+        goto err;
+    }
+    // read chip revision and check if it's compatible to bootloader
+    if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
+        goto err;
+    }
+    // initialize spi flash
+    if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
+        goto err;
+    }
+    // check whether a WDT reset happend
+    bootloader_check_wdt_reset();
+    // config WDT
+    bootloader_config_wdt();
+    // enable RNG early entropy source
+    bootloader_enable_random();
+err:
+    return ret;
+}

+ 40 - 0
components/bootloader_support/src/esp32h2/bootloader_sha.c

@@ -0,0 +1,40 @@
+/*
+ * 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 "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);
+    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);
+}

+ 346 - 0
components/bootloader_support/src/esp32h2/flash_encrypt.c

@@ -0,0 +1,346 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <strings.h>
+#include "bootloader_flash_priv.h"
+#include "bootloader_random.h"
+#include "bootloader_utility.h"
+#include "esp_image_format.h"
+#include "esp_flash_encrypt.h"
+#include "esp_flash_partitions.h"
+#include "esp_secure_boot.h"
+#include "esp_log.h"
+#include "esp32h2/rom/secure_boot.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "hal/wdt_hal.h"
+
+static const char *TAG = "flash_encrypt";
+
+/* Static functions for stages of flash encryption */
+static esp_err_t initialise_flash_encryption(void);
+static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
+static esp_err_t encrypt_bootloader(void);
+static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
+static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
+
+esp_err_t esp_flash_encrypt_check_and_update(void)
+{
+    uint8_t flash_crypt_wr_dis = 0;
+    uint32_t flash_crypt_cnt = 0;
+
+    esp_efuse_read_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &flash_crypt_cnt, 3);
+    esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &flash_crypt_wr_dis, 1);
+
+    ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_cnt);
+    ESP_LOGV(TAG, "EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_wr_dis);
+
+    if (__builtin_parity(flash_crypt_cnt) == 1) {
+        /* Flash is already encrypted */
+        int left = (flash_crypt_cnt == 1) ? 1 : 0;
+        if (flash_crypt_wr_dis) {
+            left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */
+        }
+        ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
+        return ESP_OK;
+    } else {
+#ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
+        /* Flash is not encrypted, so encrypt it! */
+        return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
+#else
+        ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED "
+                      "is set, refusing to boot.");
+        return ESP_ERR_INVALID_STATE;
+#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
+    }
+}
+
+static esp_err_t check_and_generate_encryption_keys(void)
+{
+    esp_efuse_block_t aes_128_key_block;
+
+    bool has_key = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,   &aes_128_key_block);
+    bool dis_write = false;
+    bool dis_read = false;
+
+    // If there are keys set, they must be write and read protected!
+    if(has_key) {
+        dis_write = esp_efuse_get_key_dis_write(aes_128_key_block);
+        dis_read  = esp_efuse_get_key_dis_read(aes_128_key_block);
+    }
+
+
+    if(has_key && (!dis_read || !dis_write)) {
+        ESP_LOGE(TAG, "Invalid key state, a key was set but not read and write protected.");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if(!has_key && !dis_write && !dis_read) {
+        ESP_LOGI(TAG, "Generating new flash encryption key...");
+
+        enum { BLOCKS_NEEDED = 1 };
+        esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = {
+            ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,
+        };
+
+        uint8_t keys[BLOCKS_NEEDED][32] = { 0 };
+        for (int i = 0; i < BLOCKS_NEEDED; ++i) {
+            bootloader_fill_random(keys[i], 32);
+        }
+
+        esp_err_t err = esp_efuse_write_keys(purposes, keys, BLOCKS_NEEDED);
+        if (err != ESP_OK) {
+            if (err == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
+                ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
+            } else {
+                ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", err);
+            }
+            return err;
+        }
+        ESP_LOGD(TAG, "Key generation complete");
+        return ESP_OK;
+
+    } else {
+        ESP_LOGI(TAG, "Using pre-existing key in efuse");
+        return ESP_OK;
+    }
+}
+
+
+static esp_err_t initialise_flash_encryption(void)
+{
+    esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
+
+    esp_err_t key_state = check_and_generate_encryption_keys();
+    if(key_state != ESP_OK) {
+        esp_efuse_batch_write_cancel();
+        return key_state;
+    }
+
+#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_FLASH_UART_BOOTLOADER_ALLOW_CACHE
+    ESP_LOGI(TAG, "Disable UART bootloader cache...");
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
+#else
+    ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
+#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_LEGACY_SPI_BOOT);
+
+    esp_err_t err = esp_efuse_batch_write_commit();
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
+    }
+
+    return err;
+}
+
+/* Encrypt all flash data that should be encrypted */
+static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
+{
+    esp_err_t err;
+    esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
+    int num_partitions;
+
+    /* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
+       device can't re-encrypt itself. */
+    if (flash_crypt_wr_dis || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
+        ESP_LOGE(TAG, "Cannot re-encrypt data SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
+        return ESP_FAIL;
+    }
+
+    if (spi_boot_crypt_cnt == 0) {
+        /* Very first flash of encrypted data: generate keys, etc. */
+        err = initialise_flash_encryption();
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    err = encrypt_bootloader();
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    err = encrypt_and_load_partition_table(partition_table, &num_partitions);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    /* Now iterate the just-loaded partition table, looking for entries to encrypt
+     */
+
+    /* Go through each partition and encrypt if necessary */
+    for (int i = 0; i < num_partitions; i++) {
+        err = encrypt_partition(i, &partition_table[i]);
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    ESP_LOGD(TAG, "All flash regions checked for encryption pass");
+
+    /* Set least significant 0-bit in spi_boot_crypt_cnt */
+    int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
+    /* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
+    uint32_t new_spi_boot_crypt_cnt = (1 << (ffs_inv - 1));
+    ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt + spi_boot_crypt_cnt);
+
+    esp_efuse_write_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &new_spi_boot_crypt_cnt, 3);
+
+#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
+    //Secure SPI boot cnt after its update if needed.
+    const uint32_t spi_boot_cnt_wr_dis = 1;
+    ESP_LOGI(TAG, "Write protecting SPI_CRYPT_CNT eFuse");
+    esp_efuse_write_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &spi_boot_cnt_wr_dis, 1);
+#endif
+    ESP_LOGI(TAG, "Flash encryption completed");
+
+    return ESP_OK;
+}
+
+static esp_err_t encrypt_bootloader(void)
+{
+    esp_err_t err;
+    uint32_t image_length;
+    /* Check for plaintext bootloader (verification will fail if it's already encrypted) */
+    if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
+        ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
+
+#if CONFIG_SECURE_BOOT_V2_ENABLED
+        /* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
+        if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
+            ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
+            return ESP_ERR_INVALID_SIZE;
+        }
+#endif // CONFIG_SECURE_BOOT_V2_ENABLED
+
+        err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
+            return err;
+        }
+
+        ESP_LOGI(TAG, "bootloader encrypted successfully");
+        return err;
+    }
+    else {
+        ESP_LOGW(TAG, "no valid bootloader was found");
+        return ESP_ERR_NOT_FOUND;
+    }
+}
+
+static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
+{
+    esp_err_t err;
+    /* Check for plaintext partition table */
+    err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to read partition table data");
+        return err;
+    }
+    if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
+        ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
+        esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
+                        FLASH_SECTOR_SIZE);
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
+            return err;
+        }
+    } else {
+        ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    /* Valid partition table loaded */
+    ESP_LOGI(TAG, "partition table encrypted and loaded successfully");
+    return ESP_OK;
+}
+
+
+static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
+{
+    esp_err_t err;
+    bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
+
+    if (partition->type == PART_TYPE_APP) {
+        /* check if the partition holds a valid unencrypted app */
+        esp_image_metadata_t data_ignored;
+        err = esp_image_verify(ESP_IMAGE_VERIFY,
+                               &partition->pos,
+                               &data_ignored);
+        should_encrypt = (err == ESP_OK);
+    } else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
+        /* check if we have ota data partition and the partition should be encrypted unconditionally */
+        should_encrypt = true;
+    }
+
+    if (!should_encrypt) {
+        return ESP_OK;
+    } else {
+        /* should_encrypt */
+        ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
+
+        err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
+        ESP_LOGI(TAG, "Done encrypting");
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
+        }
+        return err;
+    }
+}
+
+
+esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
+{
+    esp_err_t err;
+    uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
+
+    if (src_addr % FLASH_SECTOR_SIZE != 0) {
+        ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x", src_addr);
+        return ESP_FAIL;
+    }
+
+    wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
+    for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
+        wdt_hal_write_protect_disable(&rtc_wdt_ctx);
+        wdt_hal_feed(&rtc_wdt_ctx);
+        wdt_hal_write_protect_enable(&rtc_wdt_ctx);
+
+        uint32_t sec_start = i + src_addr;
+        err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+        err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+        err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+    }
+    return ESP_OK;
+
+flash_failed:
+    ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
+    return err;
+}

+ 289 - 0
components/bootloader_support/src/esp32h2/secure_boot.c

@@ -0,0 +1,289 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+
+#include "esp_log.h"
+#include "esp_secure_boot.h"
+#include "soc/efuse_reg.h"
+
+#include "bootloader_flash_priv.h"
+#include "bootloader_sha.h"
+#include "bootloader_utility.h"
+
+#include "esp_rom_crc.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/secure_boot.h"
+
+static const char *TAG = "secure_boot_v2";
+#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
+
+/* A signature block is valid when it has correct magic byte, crc and image digest. */
+static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
+{
+    uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
+    if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
+        // All signature blocks have been parsed, no new signature block present.
+        ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
+        return ESP_FAIL;
+    }
+    if (block->block_crc != crc) {
+        ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
+        return ESP_FAIL;
+    }
+    if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
+        ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
+        return ESP_FAIL;
+    } else {
+        ESP_LOGD(TAG, "valid signature block(%d) found", block_num);
+        return ESP_OK;
+    }
+
+    return ESP_FAIL;
+}
+
+/* Generates the public key digests of the valid public keys in an image's
+   signature block, verifies each signature, and stores the key digests in the
+   public_key_digests structure.
+
+   @param flash_offset Image offset in flash
+   @param flash_size Image size in flash (not including signature block)
+   @param[out] public_key_digests Pointer to structure to hold the key digests for valid sig blocks
+
+
+   Note that this function doesn't read any eFuses, so it doesn't know if the
+   keys are ultimately trusted by the hardware or not
+
+   @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
+           - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
+*/
+static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
+{
+    esp_err_t ret;
+    uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
+    uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
+    size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
+
+    ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
+
+    bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
+
+    ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "error generating image digest, %d", ret);
+        return ret;
+    }
+
+    ESP_LOGD(TAG, "reading signatures");
+    const ets_secure_boot_signature_t *signatures = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
+    if (signatures == NULL) {
+        ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
+        return ESP_FAIL;
+    }
+
+    for (int i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
+        const ets_secure_boot_sig_block_t *block = &signatures->block[i];
+
+        ret = validate_signature_block(block, i, image_digest);
+        if (ret != ESP_OK) {
+            ret = ESP_OK;  // past the last valid signature block
+            break;
+        }
+
+        /* Generating the SHA of the public key components in the signature block */
+        bootloader_sha256_handle_t sig_block_sha;
+        sig_block_sha = bootloader_sha256_start();
+        bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
+        bootloader_sha256_finish(sig_block_sha, key_digest);
+
+        // Check we can verify the image using this signature and this key
+        uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
+        bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
+
+        if (!verified) {
+            /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
+               so this is a fatal error
+            */
+            ret = ESP_FAIL;
+            ESP_LOGE(TAG, "Secure boot key (%d) verification failed.", i);
+            break;
+        }
+        ESP_LOGD(TAG, "Signature block (%d) is verified", i);
+        /* Copy the key digest to the buffer provided by the caller */
+        memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
+        public_key_digests->num_digests++;
+    }
+
+    if (ret == ESP_OK && public_key_digests->num_digests > 0) {
+        ESP_LOGI(TAG, "Digests successfully calculated, %d valid signatures (image offset 0x%x)",
+                 public_key_digests->num_digests, flash_offset);
+    }
+
+    bootloader_munmap(signatures);
+    return ret;
+}
+
+static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t *image_data)
+{
+    esp_err_t ret;
+    /* Verify the bootloader */
+    esp_image_metadata_t bootloader_data = { 0 };
+    ret = esp_image_verify_bootloader_data(&bootloader_data);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
+        return ret;
+    }
+
+    /* Check if secure boot digests are present */
+    bool has_secure_boot_digest = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL);
+    has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL);
+    has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL);
+    ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
+
+    if (!has_secure_boot_digest) {
+        esp_image_sig_public_key_digests_t boot_key_digests = {0};
+        esp_image_sig_public_key_digests_t app_key_digests = {0};
+
+        /* Generate the bootloader public key digests */
+        ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
+        if (ret != ESP_OK) {
+            ESP_LOGE(TAG, "Bootloader signature block is invalid");
+            return ret;
+        }
+
+        if (boot_key_digests.num_digests == 0) {
+            ESP_LOGE(TAG, "No valid bootloader signature blocks found.");
+            return ESP_FAIL;
+        }
+        ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests);
+
+        esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = {
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1,
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2,
+        };
+
+        ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests);
+        if (ret) {
+            if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
+                ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests);
+            } else {
+                ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret);
+            }
+            return ret;
+        }
+
+        /* Generate the application public key digests */
+        ret = s_calculate_image_public_key_digests(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, &app_key_digests);
+        if (ret != ESP_OK) {
+            ESP_LOGE(TAG, "App signature block is invalid.");
+            return ret;
+        }
+
+        if (app_key_digests.num_digests == 0) {
+            ESP_LOGE(TAG, "No valid applications signature blocks found.");
+            return ESP_FAIL;
+        }
+
+        ESP_LOGI(TAG, "%d signature block(s) found appended to the app.", app_key_digests.num_digests);
+        if (app_key_digests.num_digests > boot_key_digests.num_digests) {
+            ESP_LOGW(TAG, "App has %d signature blocks but bootloader only has %d. Some keys missing from bootloader?");
+        }
+
+        /* Confirm if at least one public key from the application matches a public key in the bootloader
+           (Also, ensure if that public revoke bit is not set for the matched key) */
+        bool match = false;
+
+        for (int i = 0; i < boot_key_digests.num_digests; i++) {
+
+            if (esp_efuse_get_digest_revoke(i)) {
+                ESP_LOGI(TAG, "Key block(%d) has been revoked.", i);
+                continue; // skip if the key block is revoked
+            }
+
+            for (int j = 0; j < app_key_digests.num_digests; j++) {
+                if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
+                    ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
+                    match = true;
+                }
+            }
+        }
+
+        if (match == false) {
+            ESP_LOGE(TAG, "No application key digest matches the bootloader key digest.");
+            return ESP_FAIL;
+        }
+
+        /* Revoke the empty signature blocks */
+        if (boot_key_digests.num_digests < SECURE_BOOT_NUM_BLOCKS) {
+            /* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */
+            for (uint8_t i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) {
+                ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i);
+                esp_efuse_set_digest_revoke(i);
+            }
+        }
+    }
+    return ESP_OK;
+}
+
+esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
+{
+    ESP_LOGI(TAG, "enabling secure boot v2...");
+
+    if (esp_secure_boot_enabled()) {
+        ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing..");
+        return ESP_OK;
+    }
+
+    esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
+
+    esp_err_t key_state = check_and_generate_secure_boot_keys(image_data);
+    if (key_state != ESP_OK) {
+        esp_efuse_batch_write_cancel();
+        return key_state;
+    }
+
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
+
+#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
+    ESP_LOGI(TAG, "Enabling Security download mode...");
+    esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
+#else
+    ESP_LOGW(TAG, "Not enabling Security download mode - 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_bit(ESP_EFUSE_SOFT_DIS_JTAG);
+#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);
+
+    esp_err_t err = esp_efuse_batch_write_commit();
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
+        return err;
+    }
+
+#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
+    assert(ets_efuse_secure_boot_aggressive_revoke_enabled());
+#endif
+
+    assert(esp_rom_efuse_is_secure_boot_enabled());
+    ESP_LOGI(TAG, "Secure boot permanently enabled");
+
+    return ESP_OK;
+}

+ 3 - 0
components/bootloader_support/src/esp_image_format.c

@@ -30,6 +30,9 @@
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/rtc.h"
 #include "esp32c3/rom/secure_boot.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/secure_boot.h"
 #endif
 
 /* Checking signatures as part of verifying images is necessary:

+ 10 - 0
components/bootloader_support/src/flash_encrypt.c

@@ -89,6 +89,9 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint8_t dis_dl_enc = 0;
     uint8_t dis_dl_icache = 0;
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint8_t dis_dl_enc = 0;
+    uint8_t dis_dl_icache = 0;
 #endif
 
     esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
@@ -127,6 +130,13 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
             dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
             dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
 
+            if (dis_dl_enc && dis_dl_icache) {
+                mode = ESP_FLASH_ENC_MODE_RELEASE;
+            }
+#elif CONFIG_IDF_TARGET_ESP32H2
+            dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
+            dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
+
             if (dis_dl_enc && dis_dl_icache) {
                 mode = ESP_FLASH_ENC_MODE_RELEASE;
             }

+ 2 - 0
components/bootloader_support/src/flash_partitions.c

@@ -13,6 +13,8 @@
 #include "esp32s2/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #else
 #include "esp32/rom/spi_flash.h"
 #endif

+ 2 - 0
components/bootloader_support/src/flash_qio_mode.c

@@ -21,6 +21,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 #include "soc/efuse_periph.h"
 #include "soc/io_mux_reg.h"