From 622593220102e88860a722a25c1180c3e5e54793 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 29 Jul 2020 22:03:46 +0800 Subject: [PATCH] bootloader_support: add esp32-s3 initial support --- components/bootloader_support/component.mk | 4 +- .../include/bootloader_common.h | 2 + .../include/esp_flash_encrypt.h | 2 +- .../src/bootloader_clock_init.c | 22 +- .../src/bootloader_common.c | 2 + .../src/bootloader_console.c | 6 +- .../src/bootloader_efuse_esp32s3.c | 21 + .../bootloader_support/src/bootloader_flash.c | 43 +- .../src/bootloader_flash_config_esp32s3.c | 80 ++++ .../src/bootloader_random.c | 41 +- .../src/bootloader_utility.c | 25 +- .../src/esp32s2/bootloader_esp32s2.c | 5 +- .../src/esp32s3/bootloader_esp32s3.c | 341 +++++++++++++++ .../src/esp32s3/bootloader_sha.c | 48 ++ .../src/esp32s3/flash_encrypt.c | 414 ++++++++++++++++++ .../src/esp32s3/secure_boot.c | 325 ++++++++++++++ .../src/esp32s3/secure_boot_signatures.c | 93 ++++ .../bootloader_support/src/esp_image_format.c | 5 +- .../bootloader_support/src/flash_encrypt.c | 3 + .../bootloader_support/src/flash_qio_mode.c | 5 +- components/esp32s3/CMakeLists.txt | 1 - components/esp32s3/clk.c | 6 - components/esp_common/CMakeLists.txt | 15 +- components/esp_common/Kconfig | 5 +- components/esp_common/component.mk | 4 + components/esp_common/include/esp_pm.h | 2 + components/esp_common/src/fpga_overrides.c | 57 +++ components/esp_common/src/int_wdt.c | 2 +- components/esp_common/src/mac_addr.c | 8 +- components/esp_rom/include/esp32s3/rom/aes.h | 2 - components/esp_rom/include/esp32s3/rom/rtc.h | 3 +- components/esp_system/port/esp32/clk.c | 4 +- components/esp_system/port/esp32s2/clk.c | 4 +- .../esp_system/port/esp32s3/CMakeLists.txt | 2 + components/esp_system/port/esp32s3/clk.c | 12 +- .../esp_system/port/esp32s3/reset_reason.c | 13 +- 36 files changed, 1550 insertions(+), 77 deletions(-) create mode 100644 components/bootloader_support/src/bootloader_efuse_esp32s3.c create mode 100644 components/bootloader_support/src/bootloader_flash_config_esp32s3.c create mode 100644 components/bootloader_support/src/esp32s3/bootloader_esp32s3.c create mode 100644 components/bootloader_support/src/esp32s3/bootloader_sha.c create mode 100644 components/bootloader_support/src/esp32s3/flash_encrypt.c create mode 100644 components/bootloader_support/src/esp32s3/secure_boot.c create mode 100644 components/bootloader_support/src/esp32s3/secure_boot_signatures.c create mode 100644 components/esp_common/src/fpga_overrides.c diff --git a/components/bootloader_support/component.mk b/components/bootloader_support/component.mk index dd1c16ceb0..1d678b7a0a 100644 --- a/components/bootloader_support/component.mk +++ b/components/bootloader_support/component.mk @@ -24,7 +24,9 @@ COMPONENT_OBJEXCLUDE := src/bootloader_init.o \ endif COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \ - src/bootloader_efuse_esp32s2.o + src/bootloader_flash_config_esp32s3.o \ + src/bootloader_efuse_esp32s2.o \ + src/bootloader_efuse_esp32s3.o \ ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index eaab4c2625..baf36702c1 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -21,6 +21,8 @@ #include "esp32/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/rtc.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/rtc.h" #endif #ifdef __cplusplus diff --git a/components/bootloader_support/include/esp_flash_encrypt.h b/components/bootloader_support/include/esp_flash_encrypt.h index fc1b3729d1..ef3b802715 100644 --- a/components/bootloader_support/include/esp_flash_encrypt.h +++ b/components/bootloader_support/include/esp_flash_encrypt.h @@ -49,7 +49,7 @@ typedef enum { */ static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) { - uint32_t flash_crypt_cnt; + uint32_t flash_crypt_cnt = 0; #if CONFIG_IDF_TARGET_ESP32 flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT); #elif CONFIG_IDF_TARGET_ESP32S2 diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index 9d641ddd63..283e207f83 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -24,10 +24,13 @@ #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/rtc.h" #define CPU_RESET_REASON RTC_SW_CPU_RESET +#elif CONFIG_IDF_TARGET_ESP32S3 +#define CPU_RESET_REASON RTC_SW_CPU_RESET +#include "esp32s3/rom/rtc.h" #endif #include "esp_rom_uart.h" -void bootloader_clock_configure(void) +__attribute__((weak)) void bootloader_clock_configure(void) { // ROM bootloader may have put a lot of text into UART0 FIFO. // Wait for it to be printed. @@ -38,7 +41,7 @@ void bootloader_clock_configure(void) /* Set CPU to 80MHz. Keep other clocks unmodified. */ int cpu_freq_mhz = 80; - + #if CONFIG_IDF_TARGET_ESP32 /* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to * 240 MHz may cause the chip to lock up (see section 3.5 of the errata @@ -51,23 +54,24 @@ void bootloader_clock_configure(void) cpu_freq_mhz = 240; } #endif + if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || rtc_get_reset_reason(0) != CPU_RESET_REASON) { rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); - #if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; - #endif +#endif /* ESP32-S2 doesn't have XTAL_FREQ choice, always 40MHz */ clk_cfg.cpu_freq_mhz = cpu_freq_mhz; clk_cfg.slow_freq = rtc_clk_slow_freq_get(); clk_cfg.fast_freq = rtc_clk_fast_freq_get(); rtc_clk_init(clk_cfg); - /* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable - * it here. Usually it needs some time to start up, so we amortize at least - * part of the start up time by enabling 32k XTAL early. - * App startup code will wait until the oscillator has started up. - */ } + /* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable + * it here. Usually it needs some time to start up, so we amortize at least + * part of the start up time by enabling 32k XTAL early. + * App startup code will wait until the oscillator has started up. + */ #if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL if (!rtc_clk_32k_enabled()) { rtc_clk_32k_bootstrap(CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES); diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index cc57d13273..729da47b2b 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -21,6 +21,8 @@ #include "esp32/rom/spi_flash.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" #endif #include "esp_rom_crc.h" #include "esp_rom_gpio.h" diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index 1609994a6b..b6730cebdc 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -74,7 +74,11 @@ void bootloader_console_init(void) #endif // CONFIG_ESP_CONSOLE_UART_CUSTOM // Set configured UART console baud rate - esp_rom_uart_set_clock_baudrate(uart_num, rtc_clk_apb_freq_get(), CONFIG_ESP_CONSOLE_UART_BAUDRATE); + uint32_t clock_hz = rtc_clk_apb_freq_get(); +#if CONFIG_IDF_TARGET_ESP32S3 + clock_hz = UART_CLK_FREQ_ROM; // From esp32-s3 on, UART clock source is selected to XTAL in ROM +#endif + esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); } #endif // CONFIG_ESP_CONSOLE_UART diff --git a/components/bootloader_support/src/bootloader_efuse_esp32s3.c b/components/bootloader_support/src/bootloader_efuse_esp32s3.c new file mode 100644 index 0000000000..0096c64315 --- /dev/null +++ b/components/bootloader_support/src/bootloader_efuse_esp32s3.c @@ -0,0 +1,21 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +uint8_t bootloader_common_get_chip_revision(void) +{ + /* No other revisions for ESP32-S3 */ + return 0; +} diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index d91c1cb4f3..45f6f5645b 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -32,7 +32,9 @@ #endif #if CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/spi_flash.h" //For SPI_Encrypt_Write +#include "esp32s2/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" #endif @@ -87,7 +89,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool if (write_encrypted) { #if CONFIG_IDF_TARGET_ESP32 return spi_flash_write_encrypted(dest_addr, src, size); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 return SPI_Encrypt_Write(dest_addr, src, size); #endif } else { @@ -115,6 +117,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) #include "esp32s2/rom/spi_flash.h" #include "esp32s2/rom/cache.h" #include "soc/cache_memory.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/cache.h" +#include "soc/cache_memory.h" #endif static const char *TAG = "bootloader_flash"; @@ -126,7 +132,7 @@ static const char *TAG = "bootloader_flash"; #define MMU_SIZE (0x320000) #define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE) #define FLASH_READ_VADDR MMU_BLOCK50_VADDR -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 /* Use first 63 blocks in MMU for bootloader_mmap, 63th block for bootloader_flash_read */ @@ -171,6 +177,9 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size) #elif CONFIG_IDF_TARGET_ESP32S2 uint32_t autoload = Cache_Suspend_ICache(); Cache_Invalidate_ICache_All(); +#elif CONFIG_IDF_TARGET_ESP32S3 + uint32_t autoload = Cache_Suspend_DCache(); + Cache_Invalidate_DCache_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 ); @@ -178,6 +187,8 @@ 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); +#elif CONFIG_IDF_TARGET_ESP32S3 + int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0); #endif if (e != 0) { ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e); @@ -185,6 +196,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size) Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif return NULL; } @@ -192,6 +205,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size) Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif mapped = true; @@ -212,6 +227,11 @@ void bootloader_munmap(const void *mapping) Cache_Suspend_ICache(); Cache_Invalidate_ICache_All(); Cache_MMU_Init(); +#elif CONFIG_IDF_TARGET_ESP32S3 + //TODO, save the autoload value. + Cache_Suspend_DCache(); + Cache_Invalidate_DCache_All(); + Cache_MMU_Init(); #endif mapped = false; current_read_mapping = UINT32_MAX; @@ -239,12 +259,16 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s Cache_Flush(0); #elif CONFIG_IDF_TARGET_ESP32S2 uint32_t autoload = Cache_Suspend_ICache(); +#elif CONFIG_IDF_TARGET_ESP32S3 + uint32_t autoload = Cache_Suspend_DCache(); #endif esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size); #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif return spi_to_esp_err(r); @@ -266,12 +290,17 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest #elif CONFIG_IDF_TARGET_ESP32S2 uint32_t autoload = Cache_Suspend_ICache(); Cache_Invalidate_ICache_All(); +#elif CONFIG_IDF_TARGET_ESP32S3 + uint32_t autoload = Cache_Suspend_DCache(); + Cache_Invalidate_DCache_All(); #endif ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping); #if CONFIG_IDF_TARGET_ESP32 int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1); #elif CONFIG_IDF_TARGET_ESP32S2 int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0); +#elif CONFIG_IDF_TARGET_ESP32S3 + 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); @@ -279,6 +308,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif return ESP_FAIL; } @@ -287,6 +318,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif } map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at)); @@ -342,8 +375,8 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool if (write_encrypted) { #if CONFIG_IDF_TARGET_ESP32 return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size)); -#elif CONFIG_IDF_TARGET_ESP32S2 - // TODO: use the same ROM AP here +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + // TODO: use the same ROM API here return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size)); #endif } else { diff --git a/components/bootloader_support/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c new file mode 100644 index 0000000000..0dc0e3f5f1 --- /dev/null +++ b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c @@ -0,0 +1,80 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "string.h" +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp32s3/rom/spi_flash.h" +#include "soc/efuse_reg.h" +#include "soc/spi_reg.h" +#include "soc/spi_mem_reg.h" +#include "soc/spi_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 +#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3 + +void bootloader_flash_update_id() +{ + g_rom_flashchip.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(); +} diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index 2a1d242d4b..a5a55d0c37 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -22,7 +22,7 @@ #include "soc/i2s_periph.h" #include "esp_log.h" #include "soc/io_mux_reg.h" -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "soc/apb_saradc_reg.h" #endif @@ -30,13 +30,13 @@ #include "esp_system.h" #include "driver/periph_ctrl.h" -void bootloader_fill_random(void *buffer, size_t length) + __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length) { return esp_fill_random(buffer, length); } #else -void bootloader_fill_random(void *buffer, size_t length) + __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length) { uint8_t *buffer_bytes = (uint8_t *)buffer; uint32_t random; @@ -71,7 +71,11 @@ void bootloader_random_enable(void) never disabled while the CPU is running), this is a "belts and braces" type check. */ #ifdef BOOTLOADER_BUILD +#if CONFIG_IDF_TARGET_ESP32S3 + SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_RNG_EN); +#else DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN); +#endif #else periph_module_enable(PERIPH_RNG_MODULE); #endif // BOOTLOADER_BUILD @@ -105,6 +109,17 @@ void bootloader_random_enable(void) DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP); CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP); +#elif CONFIG_IDF_TARGET_ESP32S3 + /* Disable IO1 digital function for random function. */ + PIN_INPUT_DISABLE(PERIPHS_IO_MUX_GPIO1_U); + PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO1_U); + PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO1_U); + WRITE_PERI_REG(APB_SARADC_SAR1_PATT_TAB1_REG, 0xFFFFFFFF); + + SET_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST); + SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_I2S0_CLK_EN); + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP); + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP); #endif // Test pattern configuration byte 0xAD: @@ -119,7 +134,7 @@ void bootloader_random_enable(void) SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE); SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB1_REG, 0xADADADAD); WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD); WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD); @@ -147,15 +162,18 @@ void bootloader_random_enable(void) SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S); SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_DATA_TO_I2S); #endif +#if !CONFIG_IDF_TARGET_ESP32S3 CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN); SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN); SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE); SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN); SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START); +#endif } void bootloader_random_disable(void) { +#if !CONFIG_IDF_TARGET_ESP32S3 /* Reset some i2s configuration (possibly redundant as we reset entire I2S peripheral further down). */ CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START); @@ -165,10 +183,14 @@ void bootloader_random_disable(void) CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN); CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN); CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE); - +#endif /* Disable i2s clock */ #ifdef BOOTLOADER_BUILD +#if CONFIG_IDF_TARGET_ESP32S3 + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_I2S0_CLK_EN); +#else DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); +#endif #else periph_module_disable(PERIPH_I2S0_MODULE); #endif // BOOTLOADER_BUILD @@ -177,7 +199,7 @@ void bootloader_random_disable(void) #if CONFIG_IDF_TARGET_ESP32 CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE); CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE); #endif @@ -187,7 +209,7 @@ void bootloader_random_disable(void) CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX | SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S); SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST); CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_SEL | APB_SARADC_DATA_TO_I2S); SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); @@ -199,8 +221,13 @@ void bootloader_random_disable(void) /* Reset i2s peripheral */ #ifdef BOOTLOADER_BUILD +#if CONFIG_IDF_TARGET_ESP32S3 + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_I2S0_RST); + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_I2S0_RST); +#else DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); +#endif #else periph_module_reset(PERIPH_I2S0_MODULE); #endif diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 6c4662695e..badbc8d3d6 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -20,6 +20,7 @@ #include "esp_log.h" #include "esp_rom_sys.h" +#include "esp_rom_uart.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" #include "esp32/rom/spi_flash.h" @@ -32,10 +33,16 @@ #include "esp32s2/rom/secure_boot.h" #include "soc/extmem_reg.h" #include "soc/cache_memory.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/rtc.h" +#include "esp32s3/rom/secure_boot.h" +#include "soc/extmem_reg.h" +#include "soc/cache_memory.h" #else #error "Unsupported IDF_TARGET" #endif -#include "esp_rom_uart.h" #include "soc/soc.h" #include "soc/cpu.h" @@ -683,6 +690,9 @@ static void set_cache_and_start_app( #elif CONFIG_IDF_TARGET_ESP32S2 uint32_t autoload = Cache_Suspend_ICache(); Cache_Invalidate_ICache_All(); +#elif CONFIG_IDF_TARGET_ESP32S3 + uint32_t autoload = Cache_Suspend_DCache(); + Cache_Invalidate_DCache_All(); #endif /* Clear the MMU entries that are already set up, @@ -692,7 +702,7 @@ static void set_cache_and_start_app( for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) { DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL; } -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) for (int i = 0; i < FLASH_MMU_TABLE_SIZE; i++) { FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL; } @@ -705,6 +715,8 @@ static void set_cache_and_start_app( rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count); #elif CONFIG_IDF_TARGET_ESP32S2 rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0); +#elif CONFIG_IDF_TARGET_ESP32S3 + 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 @@ -728,6 +740,8 @@ static void set_cache_and_start_app( REG_CLR_BIT(EXTMEM_PRO_ICACHE_CTRL1_REG, EXTMEM_PRO_ICACHE_MASK_IRAM1); } rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0); +#elif CONFIG_IDF_TARGET_ESP32S3 + 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 @@ -743,11 +757,18 @@ static void set_cache_and_start_app( DPORT_APP_CACHE_MASK_DRAM1 ); #elif CONFIG_IDF_TARGET_ESP32S2 REG_CLR_BIT( EXTMEM_PRO_ICACHE_CTRL1_REG, (EXTMEM_PRO_ICACHE_MASK_IRAM0) | (EXTMEM_PRO_ICACHE_MASK_IRAM1 & 0) | EXTMEM_PRO_ICACHE_MASK_DROM0 ); +#elif CONFIG_IDF_TARGET_ESP32S3 + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); +#endif #endif #if CONFIG_IDF_TARGET_ESP32 Cache_Read_Enable(0); #elif CONFIG_IDF_TARGET_ESP32S2 Cache_Resume_ICache(autoload); +#elif CONFIG_IDF_TARGET_ESP32S3 + Cache_Resume_DCache(autoload); #endif // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) diff --git a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c index 47c1a18020..aa089531c3 100644 --- a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c +++ b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c @@ -18,9 +18,6 @@ #include "soc/gpio_periph.h" #include "soc/gpio_sig_map.h" #include "soc/io_mux_reg.h" -#include "esp_rom_gpio.h" -#include "esp_rom_efuse.h" -#include "esp32s2/rom/spi_flash.h" #include "bootloader_init.h" #include "bootloader_clock.h" @@ -29,6 +26,8 @@ #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "esp_rom_gpio.h" +#include "esp_rom_efuse.h" #include "esp_rom_sys.h" #include "esp32s2/rom/cache.h" #include "esp32s2/rom/spi_flash.h" diff --git a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c new file mode 100644 index 0000000000..f6e0c2e853 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c @@ -0,0 +1,341 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_image_format.h" +#include "flash_qio_mode.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/dport_reg.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/spi_periph.h" +#include "soc/extmem_reg.h" + +#include "esp_rom_gpio.h" +#include "esp_rom_efuse.h" +#include "esp_rom_sys.h" +#include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/cache.h" +#include "esp32s3/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 "bootloader_console.h" +#include "bootloader_flash_priv.h" + + +static const char *TAG = "boot.esp32s3"; + +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_DCache(); + Cache_Invalidate_DCache_All(); + Cache_MMU_Init(); + + REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_CORE1_BUS); +#endif +} + +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_DCache(); + // Set flash chip size + esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); + // TODO: set mode + // TODO: set frequency + Cache_Resume_DCache(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 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 + + 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_PDEBUGENABLE_REG, 1); + REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_RECORDING_REG, 1); +} + +static void wdt_reset_info_dump(int cpu) +{ + uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0, + lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0; + const char *cpu_name = cpu ? "APP" : "PRO"; + + stat = 0xdeadbeef; + pid = 0; + if (cpu == 0) { + inst = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGINST_REG); + dstat = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGSTATUS_REG); + data = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGDATA_REG); + pc = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG); + lsstat = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0STAT_REG); + lsaddr = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0ADDR_REG); + lsdata = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0DATA_REG); + } else { +#if !CONFIG_FREERTOS_UNICORE + inst = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGINST_REG); + dstat = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGSTATUS_REG); + data = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGDATA_REG); + pc = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC_REG); + lsstat = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0STAT_REG); + lsaddr = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0ADDR_REG); + lsdata = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0DATA_REG); +#else + ESP_LOGE(TAG, "WDT reset info: %s CPU not support!\n", cpu_name); + return; +#endif + } + + ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr); + ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata); +} + +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_info_dump(1); + } + wdt_reset_cpu0_info_enable(); +} + +static void bootloader_super_wdt_auto_feed(void) +{ + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN); +} + +esp_err_t bootloader_init(void) +{ + esp_err_t ret = ESP_OK; + bootloader_super_wdt_auto_feed(); + // protect memory region + bootloader_init_mem(); + /* check that static RAM is after the stack */ +#ifndef NDEBUG + { + assert(&_bss_start <= &_bss_end); + assert(&_data_start <= &_data_end); + } +#endif + // 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; +} diff --git a/components/bootloader_support/src/esp32s3/bootloader_sha.c b/components/bootloader_support/src/esp32s3/bootloader_sha.c new file mode 100644 index 0000000000..b0d5b9b124 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/bootloader_sha.c @@ -0,0 +1,48 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "bootloader_sha.h" +#include +#include +#include +#include + +#include "esp32s3/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/components/bootloader_support/src/esp32s3/flash_encrypt.c b/components/bootloader_support/src/esp32s3/flash_encrypt.c new file mode 100644 index 0000000000..52e08293e0 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/flash_encrypt.c @@ -0,0 +1,414 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#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 "esp32s3/rom/secure_boot.h" +#include "esp32s3/rom/cache.h" +#include "esp32s3/rom/efuse.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 bool s_key_dis_read(ets_efuse_block_t block) +{ + // TODO: eFuse support on ESP32-S3 + // unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; + // return REG_GET_FIELD(EFUSE_RD_REPEAT_DATA0_REG, EFUSE_RD_DIS) & (EFUSE_RD_DIS_KEY0 << key_num); + return true; +} + +static bool s_key_dis_write(ets_efuse_block_t block) +{ + // TODO: eFuse support on ESP32-S3 + // unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; + // return REG_GET_FIELD(EFUSE_RD_WR_DIS_REG, EFUSE_WR_DIS) & (EFUSE_WR_DIS_KEY0 << key_num); + return true; +} + +static esp_err_t check_and_generate_encryption_keys(void) +{ + esp_err_t err = ESP_ERR_INVALID_STATE; + ets_efuse_block_t aes_128_key_block; + ets_efuse_block_t aes_256_key_block_1; + ets_efuse_block_t aes_256_key_block_2; + + bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block); + bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1); + bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2); + bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2); + bool dis_write = false; + bool dis_read = false; + + // If there are keys set, they must be write and read protected! + if(has_key && has_aes128) { + dis_write = s_key_dis_write(aes_128_key_block); + dis_read = s_key_dis_read(aes_128_key_block); + } else if (has_key && has_aes256_1 && has_aes256_2) { + dis_write = s_key_dis_write(aes_256_key_block_1) && s_key_dis_write(aes_256_key_block_2); + dis_read = s_key_dis_read(aes_256_key_block_1) && s_key_dis_read(aes_256_key_block_2); + } + + if (!has_key && (has_aes256_1 || has_aes256_2)) { + ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set."); + return ESP_ERR_INVALID_STATE; + } + + 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..."); +#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256 + const unsigned BLOCKS_NEEDED = 2; + const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1; + const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2; +#else + const unsigned BLOCKS_NEEDED = 1; + const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; + const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; +#endif + + if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) { + ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED); + return ESP_ERR_INVALID_STATE; + } + + for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) { + uint32_t buf[8] = {0}; + bootloader_fill_random(buf, sizeof(buf)); + ets_efuse_block_t block = ets_efuse_find_unused_key_block(); + ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d", + block - ETS_EFUSE_BLOCK_KEY0, purpose); + + /* Note: everything else in this function is deferred as a batch write, but we write the + key (and write protect it) immediately as it's too fiddly to manage unused key blocks, etc. + in bootloader size footprint otherwise. */ + int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf)); + if (r != 0) { + ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", + block, purpose); + return ESP_FAIL; + } + + /* assuming numbering of esp_efuse_block_t matches ets_efuse_block_t */ + _Static_assert((int)EFUSE_BLK_KEY0 == (int)ETS_EFUSE_BLOCK_KEY0, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + _Static_assert((int)EFUSE_BLK_KEY1 == (int)ETS_EFUSE_BLOCK_KEY1, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + _Static_assert((int)EFUSE_BLK_KEY2 == (int)ETS_EFUSE_BLOCK_KEY2, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + _Static_assert((int)EFUSE_BLK_KEY3 == (int)ETS_EFUSE_BLOCK_KEY3, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + _Static_assert((int)EFUSE_BLK_KEY4 == (int)ETS_EFUSE_BLOCK_KEY4, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + _Static_assert((int)EFUSE_BLK_KEY5 == (int)ETS_EFUSE_BLOCK_KEY5, "esp_efuse_block_t doesn't match ets_efuse_block_t"); + + // protect this block against reading after key is set (writing is done by ets_efuse_write_key) + err = esp_efuse_set_read_protect(block); + if(err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set read protect to efuse block %d. Can't continue.", block); + 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_DCACHE); + 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_HARD_DIS_JTAG); +#else + ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED"); +#endif + + esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); + + esp_err_t err = esp_efuse_batch_write_commit(); + + 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) { + 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 */ + 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 + // Account for the signature sector after the bootloader + image_length = (image_length + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE - 1); + image_length += FLASH_SECTOR_SIZE; + 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 loded */ + 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; +} diff --git a/components/bootloader_support/src/esp32s3/secure_boot.c b/components/bootloader_support/src/esp32s3/secure_boot.c new file mode 100644 index 0000000000..0406c48381 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/secure_boot.c @@ -0,0 +1,325 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#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 "esp32s3/rom/efuse.h" +#include "esp32s3/rom/secure_boot.h" + +static const char *TAG = "secure_boot_v2"; +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + +#define SIG_BLOCK_MAGIC_BYTE 0xe7 +#define CRC_SIGN_BLOCK_LEN 1196 +#define SIG_BLOCK_PADDING 4096 + +#define DIGEST_LEN 32 + +/* 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 != SIG_BLOCK_MAGIC_BYTE) { + // 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, 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; +} + +/* Structure to hold public key digests calculated from the signature blocks of a single image. + + Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block + includes a public key. + + Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests, + in this data structure the digest data is included. +*/ +typedef struct { + uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN]; + unsigned num_digests; /* Number of valid digests, starting at index 0 */ +} image_sig_public_key_digests_t; + +/* 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, image_sig_public_key_digests_t *public_key_digests) +{ + esp_err_t ret; + uint8_t image_digest[DIGEST_LEN] = {0}; + uint8_t __attribute__((aligned(4))) key_digest[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(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[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, 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; +} + +esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +{ + ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2..."); + + if (esp_secure_boot_enabled()) { + ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing.."); + return ESP_OK; + } + + 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 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL); + has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL); + has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL); + ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); + + ets_efuse_clear_program_registers(); + if (!has_secure_boot_digest) { + image_sig_public_key_digests_t boot_key_digests = {0}; + 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); + + int unused_key_slots = ets_efuse_count_unused_key_blocks(); + if (boot_key_digests.num_digests > unused_key_slots) { + ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots(%d).", boot_key_digests.num_digests, unused_key_slots); + return ESP_FAIL; + } + + for (int i = 0; i < boot_key_digests.num_digests; i++) { + ets_efuse_block_t block; + const uint32_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 }; + + block = ets_efuse_find_unused_key_block(); + if (block == ETS_EFUSE_BLOCK_MAX) { + ESP_LOGE(TAG, "No more unused key blocks available."); + return ESP_FAIL; + } + + int r = ets_efuse_write_key(block, secure_boot_key_purpose[i], boot_key_digests.key_digests[i], DIGEST_LEN); + if (r != 0) { + ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", block, secure_boot_key_purpose[i]); + return ESP_FAIL; + } + + // Note: write key will write protect both the block and the purpose eFuse, always + } + + /* 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; + const uint32_t revoke_bits[SECURE_BOOT_NUM_BLOCKS] = { EFUSE_SECURE_BOOT_KEY_REVOKE0, + EFUSE_SECURE_BOOT_KEY_REVOKE1, EFUSE_SECURE_BOOT_KEY_REVOKE2 }; + + for (int i = 0; i < boot_key_digests.num_digests; i++) { + + if (REG_GET_BIT(EFUSE_RD_REPEAT_DATA1_REG, revoke_bits[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], 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); + ets_secure_boot_revoke_public_key_digest(i); + } + } + } + + esp_err_t err = esp_efuse_batch_write_begin(); + if (err != ESP_OK) { + ESP_LOGI(TAG, "Error batch programming security eFuses."); + return err; + } + + __attribute__((unused)) static const uint8_t enable = 1; + + esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP); + 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_HARD_DIS_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); + + err = esp_efuse_batch_write_commit(); + if (err != ESP_OK) { + ESP_LOGI(TAG, "Error programming security eFuses."); + 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; +} diff --git a/components/bootloader_support/src/esp32s3/secure_boot_signatures.c b/components/bootloader_support/src/esp32s3/secure_boot_signatures.c new file mode 100644 index 0000000000..7bd377d480 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/secure_boot_signatures.c @@ -0,0 +1,93 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "sdkconfig.h" +#include "esp_fault.h" +#include "bootloader_flash_priv.h" +#include "bootloader_sha.h" +#include "bootloader_utility.h" +#include "esp_log.h" +#include "esp_image_format.h" +#include "esp_secure_boot.h" +#include "esp32s3/rom/secure_boot.h" + +static const char* TAG = "secure_boot"; + +#define DIGEST_LEN 32 +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[DIGEST_LEN]; + uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */ + const uint8_t *data; + + ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); + + /* Padding to round off the input to the nearest 4k boundary */ + int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE); + ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length); + + data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block)); + if (data == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t)); + return ESP_FAIL; + } + + /* Calculate digest of main image */ + esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length); + bootloader_munmap(data); + return err; + } + + const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length); + int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest); + bootloader_munmap(data); + + return (r == ETS_OK) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest) +{ + ets_secure_boot_key_digests_t trusted_keys; + ets_secure_boot_key_digests_t trusted_key_copies[2]; + ETS_STATUS r; + ets_secure_boot_status_t sb_result; + + memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t)); + memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t)); + + if (!esp_secure_boot_enabled()) { + return ESP_OK; + } + + r = ets_secure_boot_read_key_digests(&trusted_keys); + if (r != ETS_OK) { + ESP_LOGI(TAG, "Could not read secure boot digests!"); + return ESP_FAIL; + } + + // Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow) + ets_secure_boot_read_key_digests(&trusted_key_copies[0]); + ets_secure_boot_read_key_digests(&trusted_key_copies[1]); + ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0); + ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0); + + ESP_LOGI(TAG, "Verifying with RSA-PSS boot..."); + sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest); + return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL; +} diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index eb03a2e581..e76b3cee29 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -32,6 +32,9 @@ #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/rtc.h" #include "esp32s2/rom/secure_boot.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/rtc.h" +#include "esp32s3/rom/secure_boot.h" #endif /* Checking signatures as part of verifying images is necessary: @@ -209,7 +212,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_ bool verify_sha; #if CONFIG_SECURE_BOOT_V2_ENABLED verify_sha = true; -#else // ESP32, or ESP32S2 without secure boot enabled +#else // Secure boot not enabled verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET); #endif diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index a41fe8ee2d..465fb8483d 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -26,6 +26,9 @@ #elif CONFIG_IDF_TARGET_ESP32S2 #define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT #define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT +#elif CONFIG_IDF_TARGET_ESP32S3 +#define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT +#define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT #endif #ifndef BOOTLOADER_BUILD diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index f142f7c284..140e64da61 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -15,10 +15,12 @@ #include #include "bootloader_flash_config.h" #include "flash_qio_mode.h" +#include "sdkconfig.h" #include "bootloader_flash_priv.h" #include "esp_log.h" #include "esp_err.h" #include "esp_rom_efuse.h" +#include "flash_qio_mode.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/spi_flash.h" #elif CONFIG_IDF_TARGET_ESP32S2 @@ -28,7 +30,6 @@ #endif #include "soc/efuse_periph.h" #include "soc/io_mux_reg.h" -#include "sdkconfig.h" static const char *TAG = "qio_mode"; @@ -194,7 +195,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, #if CONFIG_IDF_TARGET_ESP32 int wp_pin = bootloader_flash_get_wp_pin(); esp_rom_spiflash_select_qio_pins(wp_pin, spiconfig); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 esp_rom_spiflash_select_qio_pins(esp_rom_efuse_get_flash_wp_gpio(), spiconfig); #endif return ESP_OK; diff --git a/components/esp32s3/CMakeLists.txt b/components/esp32s3/CMakeLists.txt index 34c91b07a5..65a277a7cf 100644 --- a/components/esp32s3/CMakeLists.txt +++ b/components/esp32s3/CMakeLists.txt @@ -16,7 +16,6 @@ else() "clk.c" "crosscore_int.c" "dport_access.c" - "esp_crypto_lock.c" "hw_random.c" "intr_alloc.c" "memprot.c" diff --git a/components/esp32s3/clk.c b/components/esp32s3/clk.c index e3a4c8a7fc..65dacbe58b 100644 --- a/components/esp32s3/clk.c +++ b/components/esp32s3/clk.c @@ -23,9 +23,6 @@ // g_ticks_us defined in ROMs for PRO and APP CPU extern uint32_t g_ticks_per_us_pro; -#ifndef CONFIG_FREERTOS_UNICORE -extern uint32_t g_ticks_per_us_app; -#endif int IRAM_ATTR esp_clk_cpu_freq(void) { @@ -46,7 +43,4 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us) { /* Update scale factors used by esp_rom_delay_us */ g_ticks_per_us_pro = ticks_per_us; -#ifndef CONFIG_FREERTOS_UNICORE - g_ticks_per_us_app = ticks_per_us; -#endif } \ No newline at end of file diff --git a/components/esp_common/CMakeLists.txt b/components/esp_common/CMakeLists.txt index 8e16313dd7..3382345769 100644 --- a/components/esp_common/CMakeLists.txt +++ b/components/esp_common/CMakeLists.txt @@ -1,12 +1,18 @@ idf_build_get_property(target IDF_TARGET) +if(CONFIG_IDF_ENV_FPGA) + list(APPEND srcs "src/fpga_overrides.c") +endif() + if(BOOTLOADER_BUILD) # For bootloader, all we need from esp_common is headers - idf_component_register(INCLUDE_DIRS include) + idf_component_register(SRCS ${srcs} + INCLUDE_DIRS include + PRIV_REQUIRES soc) set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-Wl,--gc-sections") else() # Regular app build - set(srcs "src/brownout.c" + list(APPEND srcs "src/brownout.c" "src/esp_err.c" "src/dbg_stubs.c" "src/esp_err_to_name.c" @@ -61,3 +67,8 @@ else() endforeach() endif() + +if(CONFIG_IDF_ENV_FPGA) + # Forces the linker to include fpga stubs from this component + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_common_include_fpga_overrides") +endif() diff --git a/components/esp_common/Kconfig b/components/esp_common/Kconfig index 31b2742c67..a05bd2cad8 100644 --- a/components/esp_common/Kconfig +++ b/components/esp_common/Kconfig @@ -125,7 +125,7 @@ menu "Common ESP-related" depends on ESP_CONSOLE_UART_CUSTOM range 0 46 default 1 if IDF_TARGET_ESP32 - default 43 if IDF_TARGET_ESP32S2 + default 43 help This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including boot log output and default standard output and standard error of the app). @@ -138,7 +138,7 @@ menu "Common ESP-related" depends on ESP_CONSOLE_UART_CUSTOM range 0 46 default 3 if IDF_TARGET_ESP32 - default 44 if IDF_TARGET_ESP32S2 + default 44 help This GPIO is used for UART RX input in the ESP-IDF Bootloader and the app (including default default standard input of the app). @@ -292,6 +292,7 @@ menu "Common ESP-related" int default 2 if ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR default 1 if ESP32_UNIVERSAL_MAC_ADDRESSES_TWO + default 1 config ESP_MAC_ADDR_UNIVERSE_ETH bool diff --git a/components/esp_common/component.mk b/components/esp_common/component.mk index 64c67abcc5..da494c4b94 100644 --- a/components/esp_common/component.mk +++ b/components/esp_common/component.mk @@ -5,5 +5,9 @@ COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_SRCDIRS := src +ifndef CONFIG_IDF_ENV_FPGA +COMPONENT_OBJEXCLUDE += src/fpga_overrides.o +endif + # disable stack protection in files which are involved in initialization of that feature src/stack_check.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS)) diff --git a/components/esp_common/include/esp_pm.h b/components/esp_common/include/esp_pm.h index 15af6a4aca..5c85188107 100644 --- a/components/esp_common/include/esp_pm.h +++ b/components/esp_common/include/esp_pm.h @@ -21,6 +21,8 @@ #include "esp32/pm.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/pm.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/pm.h" #endif #ifdef __cplusplus diff --git a/components/esp_common/src/fpga_overrides.c b/components/esp_common/src/fpga_overrides.c new file mode 100644 index 0000000000..e35ed52158 --- /dev/null +++ b/components/esp_common/src/fpga_overrides.c @@ -0,0 +1,57 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/system_reg.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_rom_sys.h" +#include "esp_rom_uart.h" + +extern void ets_update_cpu_frequency(uint32_t ticks_per_us); + +void bootloader_clock_configure(void) +{ + esp_rom_uart_tx_wait_idle(0); + + uint32_t clock = 40000000; + ets_update_cpu_frequency(clock / 1000000); + REG_WRITE(RTC_CNTL_STORE5_REG, (clock >> 12) | ((clock >> 12) << 16)); +} + +void bootloader_fill_random(void *buffer, size_t length) +{ + uint8_t *buffer_bytes = (uint8_t *)buffer; + for (int i = 0; i < length; i++) { + buffer_bytes[i] = 0x5A; + } +} + +void esp_clk_init(void) +{ + +} + +void esp_perip_clk_init(void) +{ + +} + +/** + * @brief No-op function, used to force linking this file + * + */ +void esp_common_include_fpga_overrides(void) +{ +} \ No newline at end of file diff --git a/components/esp_common/src/int_wdt.c b/components/esp_common/src/int_wdt.c index 77b2e09389..c6d3cc8e5d 100644 --- a/components/esp_common/src/int_wdt.c +++ b/components/esp_common/src/int_wdt.c @@ -82,7 +82,7 @@ static void IRAM_ATTR tick_hook(void) { } #else static void IRAM_ATTR tick_hook(void) { -#if CONFIG_IDF_TARGET_ESP32 +#if !CONFIG_FREERTOS_UNICORE if (xPortGetCoreID()!=0) { return; } diff --git a/components/esp_common/src/mac_addr.c b/components/esp_common/src/mac_addr.c index f54c955843..f441245de8 100644 --- a/components/esp_common/src/mac_addr.c +++ b/components/esp_common/src/mac_addr.c @@ -56,8 +56,8 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac) esp_err_t esp_efuse_mac_get_custom(uint8_t *mac) { -#ifdef CONFIG_IDF_TARGET_ESP32S2 - return ESP_ERR_NOT_SUPPORTED; // TODO: support custom MAC in efuse +#if !CONFIG_IDF_TARGET_ESP32 + return ESP_ERR_NOT_SUPPORTED; #else uint8_t version; esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM_VER, &version, 8); @@ -76,7 +76,7 @@ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac) return ESP_ERR_INVALID_CRC; } return ESP_OK; -#endif // IDF_TARGET_ESP32S2 +#endif } esp_err_t esp_efuse_mac_get_default(uint8_t* mac) @@ -86,7 +86,7 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac) return err; } #ifdef CONFIG_IDF_TARGET_ESP32 -// Only ESP32 has MAC CRC in efuse, ESP32-S2 has internal efuse consistency checks +// Only ESP32 has MAC CRC in efuse uint8_t efuse_crc; esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY_CRC, &efuse_crc, 8); uint8_t calc_crc = esp_rom_efuse_mac_address_crc8(mac, 6); diff --git a/components/esp_rom/include/esp32s3/rom/aes.h b/components/esp_rom/include/esp32s3/rom/aes.h index 432c65efa2..1df00a1d6d 100644 --- a/components/esp_rom/include/esp32s3/rom/aes.h +++ b/components/esp_rom/include/esp32s3/rom/aes.h @@ -21,8 +21,6 @@ extern "C" { #endif -#define AES_BLOCK_SIZE (16) - enum AES_TYPE { AES_ENC, AES_DEC, diff --git a/components/esp_rom/include/esp32s3/rom/rtc.h b/components/esp_rom/include/esp32s3/rom/rtc.h index 15adc528dc..a5a1ecb6a1 100644 --- a/components/esp_rom/include/esp32s3/rom/rtc.h +++ b/components/esp_rom/include/esp32s3/rom/rtc.h @@ -16,8 +16,7 @@ #include #include -#include "ets_sys.h" -#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/esp_system/port/esp32/clk.c b/components/esp_system/port/esp32/clk.c index a75ecf7a48..7f1c769266 100644 --- a/components/esp_system/port/esp32/clk.c +++ b/components/esp_system/port/esp32/clk.c @@ -121,7 +121,7 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk) esp_clk_slowclk_cal_set(cal_val); } -void esp_clk_init(void) + __attribute__((weak)) void esp_clk_init(void) { rtc_config_t cfg = RTC_CONFIG_DEFAULT(); rtc_init(cfg); @@ -203,7 +203,7 @@ void esp_clk_init(void) * These peripheral clocks are enabled when the peripherals are initialized * and disabled when they are de-initialized. */ -void esp_perip_clk_init(void) +__attribute__((weak)) void esp_perip_clk_init(void) { uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; diff --git a/components/esp_system/port/esp32s2/clk.c b/components/esp_system/port/esp32s2/clk.c index 0306d5d029..8ce2e4dd9e 100644 --- a/components/esp_system/port/esp32s2/clk.c +++ b/components/esp_system/port/esp32s2/clk.c @@ -73,7 +73,7 @@ typedef enum { static void select_rtc_slow_clk(slow_clk_sel_t slow_clk); -void esp_clk_init(void) + __attribute__((weak)) void esp_clk_init(void) { rtc_config_t cfg = RTC_CONFIG_DEFAULT(); RESET_REASON rst_reas; @@ -206,7 +206,7 @@ void rtc_clk_select_rtc_slow_clk(void) * These peripheral clocks are enabled when the peripherals are initialized * and disabled when they are de-initialized. */ -void esp_perip_clk_init(void) +__attribute__((weak)) void esp_perip_clk_init(void) { uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; uint32_t common_perip_clk1 = 0; diff --git a/components/esp_system/port/esp32s3/CMakeLists.txt b/components/esp_system/port/esp32s3/CMakeLists.txt index 039081b6f4..3726d76e29 100644 --- a/components/esp_system/port/esp32s3/CMakeLists.txt +++ b/components/esp_system/port/esp32s3/CMakeLists.txt @@ -1,6 +1,8 @@ set(srcs "../async_memcpy_impl_gdma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c") add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) +target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) + #ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the #linker will ignore panic_highint_hdl.S as it has no other files depending on any #symbols in it. diff --git a/components/esp_system/port/esp32s3/clk.c b/components/esp_system/port/esp32s3/clk.c index d449399fbf..9bf1d1e5f5 100644 --- a/components/esp_system/port/esp32s3/clk.c +++ b/components/esp_system/port/esp32s3/clk.c @@ -74,7 +74,7 @@ typedef enum { static void select_rtc_slow_clk(slow_clk_sel_t slow_clk); -void esp_clk_init(void) + __attribute__((weak)) void esp_clk_init(void) { rtc_config_t cfg = RTC_CONFIG_DEFAULT(); rtc_init(cfg); @@ -202,7 +202,7 @@ void rtc_clk_select_rtc_slow_clk(void) * These peripheral clocks are enabled when the peripherals are initialized * and disabled when they are de-initialized. */ -void esp_perip_clk_init(void) +__attribute__((weak)) void esp_perip_clk_init(void) { uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; uint32_t common_perip_clk1 = 0; @@ -252,7 +252,7 @@ void esp_perip_clk_init(void) SYSTEM_SPI3_CLK_EN | SYSTEM_SPI4_CLK_EN | SYSTEM_PWM0_CLK_EN | - SYSTEM_CAN_CLK_EN | + SYSTEM_TWAI_CLK_EN | SYSTEM_PWM1_CLK_EN | SYSTEM_I2S1_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | @@ -295,12 +295,6 @@ void esp_perip_clk_init(void) SYSTEM_SPI3_DMA_CLK_EN; common_perip_clk1 = 0; - /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, - * the current is not reduced when disable I2S clock. - */ - REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - /* Disable some peripheral clocks. */ CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk); SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk); diff --git a/components/esp_system/port/esp32s3/reset_reason.c b/components/esp_system/port/esp32s3/reset_reason.c index 25f8f0a90d..b53641ca7b 100644 --- a/components/esp_system/port/esp32s3/reset_reason.c +++ b/components/esp_system/port/esp32s3/reset_reason.c @@ -97,24 +97,13 @@ esp_reset_reason_t esp_reset_reason(void) /* in IRAM, can be called from panic handler */ void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint) { - assert((hint & (~RST_REASON_MASK)) == 0); - uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT; - REG_WRITE(RTC_RESET_CAUSE_REG, val); } /* in IRAM, can be called from panic handler */ esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void) { - uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG); - uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK; - uint32_t low = reset_reason_hint & RST_REASON_MASK; - if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) { - return ESP_RST_UNKNOWN; - } - return (esp_reset_reason_t) low; + return ESP_RST_UNKNOWN; } static void esp_reset_reason_clear_hint(void) { - REG_WRITE(RTC_RESET_CAUSE_REG, 0); } -