make bootloader_support support esp32s2beta

This commit is contained in:
suda-morris 2019-05-27 14:29:43 +08:00
parent b146104885
commit 61ce868396
62 changed files with 1914 additions and 336 deletions

View file

@ -1,18 +1,8 @@
set(COMPONENT_SRCS "bootloader_start.c") idf_component_register(SRCS "bootloader_start.c"
set(COMPONENT_ADD_INCLUDEDIRS "") REQUIRES bootloader bootloader_support)
set(COMPONENT_REQUIRES bootloader bootloader_support)
register_component()
idf_build_get_property(target IDF_TARGET) idf_build_get_property(target IDF_TARGET)
set(scripts "ld/${target}/bootloader.ld"
"ld/${target}/bootloader.rom.ld")
target_linker_script(${COMPONENT_LIB} target_linker_script(${COMPONENT_LIB} "${scripts}")
"ld/${target}/bootloader.ld"
"ld/${target}/bootloader.rom.ld"
)
set(scripts
"${IDF_PATH}/components/esp_rom/${target}/ld/${target}.rom.ld"
"${IDF_PATH}/components/esp_rom/${target}/ld/${target}.rom.newlib-funcs.ld"
"${IDF_PATH}/components/${target}/ld/${target}.peripherals.ld")
target_linker_script(${COMPONENT_LIB} ${scripts})

View file

@ -29,7 +29,7 @@
#include "esp32s2beta/rom/spi_flash.h" #include "esp32s2beta/rom/spi_flash.h"
#endif #endif
static const char* TAG = "boot"; static const char *TAG = "boot";
static int select_partition_number (bootloader_state_t *bs); static int select_partition_number (bootloader_state_t *bs);
static int selected_boot_partition(const bootloader_state_t *bs); static int selected_boot_partition(const bootloader_state_t *bs);

View file

@ -5,10 +5,10 @@
PROVIDE ( ets_update_cpu_frequency = 0x4000d954 ); PROVIDE ( ets_update_cpu_frequency = 0x4000d954 );
/* ToDo: Following address may need modification */ /* ToDo: Following address may need modification */
PROVIDE ( MD5Final = 0x4005db1c ); PROVIDE ( MD5Final = 0x400056e8 );
PROVIDE ( MD5Init = 0x4005da7c ); PROVIDE ( MD5Init = 0x40005648 );
PROVIDE ( MD5Update = 0x4005da9c ); PROVIDE ( MD5Update = 0x40005668 );
/* bootloader will use following functions from xtensa hal library */ /* bootloader will use following functions from xtensa hal library */
xthal_get_ccount = 0x4000c050; xthal_get_ccount = 0x40015cbc;
xthal_get_ccompare = 0x4000c078; xthal_get_ccompare = 0x40015ce8;
xthal_set_ccompare = 0x4000c058; xthal_set_ccompare = 0x40015cc4;

View file

@ -15,7 +15,9 @@ if(BOOTLOADER_BUILD)
"src/${IDF_TARGET}/bootloader_sha.c" "src/${IDF_TARGET}/bootloader_sha.c"
"src/${IDF_TARGET}/flash_encrypt.c" "src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/secure_boot_signatures.c" "src/${IDF_TARGET}/secure_boot_signatures.c"
"src/${IDF_TARGET}/secure_boot.c") "src/${IDF_TARGET}/secure_boot.c"
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
"src/${IDF_TARGET}/bootloader_clock_${IDF_TARGET}.c")
if(CONFIG_SECURE_SIGNED_APPS) if(CONFIG_SECURE_SIGNED_APPS)
get_filename_component(secure_boot_verification_key get_filename_component(secure_boot_verification_key

View file

@ -46,10 +46,10 @@ $(ORIG_SECURE_BOOT_VERIFICATION_KEY):
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE) $(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
$(summary) CP $< $@ $(summary) CP $< $@
cp $< $@ cp $< $@
endif endif #CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY) COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY) COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
endif endif #CONFIG_SECURE_SIGNED_APPS

View file

@ -19,3 +19,7 @@
* Called by bootloader, or by the app if the bootloader version is old (pre v2.1). * Called by bootloader, or by the app if the bootloader version is old (pre v2.1).
*/ */
void bootloader_clock_configure(void); void bootloader_clock_configure(void);
/** @brief Return the rated maximum frequency of this chip
*/
int bootloader_clock_get_rated_freq_mhz(void);

View file

@ -78,6 +78,13 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
*/ */
bool bootloader_common_label_search(const char *list, char *label); bool bootloader_common_label_search(const char *list, char *label);
/**
* @brief Configure default SPI pin modes and drive strengths
*
* @param drv GPIO drive level (determined by clock frequency)
*/
void bootloader_configure_spi_pins(int drv);
/** /**
* @brief Calculates a sha-256 for a given partition or returns a appended digest. * @brief Calculates a sha-256 for a given partition or returns a appended digest.
* *

View file

@ -21,6 +21,7 @@
#include "esp_spi_flash.h" #include "esp_spi_flash.h"
#endif #endif
#include "soc/efuse_periph.h" #include "soc/efuse_periph.h"
#include "sdkconfig.h"
/** /**
* @file esp_partition.h * @file esp_partition.h
@ -35,11 +36,17 @@
* *
* @return true if flash encryption is enabled. * @return true if flash encryption is enabled.
*/ */
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) { static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT); {
uint32_t flash_crypt_cnt;
#if CONFIG_IDF_TARGET_ESP32
flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
flash_crypt_cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
#endif
/* __builtin_parity is in flash, so we calculate parity inline */ /* __builtin_parity is in flash, so we calculate parity inline */
bool enabled = false; bool enabled = false;
while(flash_crypt_cnt) { while (flash_crypt_cnt) {
if (flash_crypt_cnt & 1) { if (flash_crypt_cnt & 1) {
enabled = !enabled; enabled = !enabled;
} }

View file

@ -18,6 +18,9 @@
#include "soc/efuse_periph.h" #include "soc/efuse_periph.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/efuse.h"
#endif
#ifdef CONFIG_SECURE_BOOT_ENABLED #ifdef CONFIG_SECURE_BOOT_ENABLED
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS) #if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
@ -36,14 +39,18 @@ extern "C" {
/** @brief Is secure boot currently enabled in hardware? /** @brief Is secure boot currently enabled in hardware?
* *
* Secure boot is enabled if the ABS_DONE_0 efuse is blown. This means * This means that the ROM bootloader code will only boot
* that the ROM bootloader code will only boot a verified secure * a verified secure bootloader from now on.
* bootloader digest from now on.
* *
* @return true if secure boot is enabled. * @return true if secure boot is enabled.
*/ */
static inline bool esp_secure_boot_enabled(void) { static inline bool esp_secure_boot_enabled(void)
{
#if CONFIG_IDF_TARGET_ESP32
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0; return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
return ets_efuse_secure_boot_enabled();
#endif
} }
/** @brief Generate secure digest from bootloader image /** @brief Generate secure digest from bootloader image

View file

@ -15,6 +15,7 @@
#include "bootloader_config.h" #include "bootloader_config.h"
#include "esp_image_format.h" #include "esp_image_format.h"
#include "bootloader_config.h"
/** /**
* @brief Load partition table. * @brief Load partition table.
@ -86,3 +87,14 @@ __attribute__((noreturn)) void bootloader_reset(void);
* ESP_ERR_INVALID_ARG: Error in the passed arguments * ESP_ERR_INVALID_ARG: Error in the passed arguments
*/ */
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len); esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
/**
* @brief Debug log contents of a buffer as hexadecimal
*
* @note Only works if component log level is DEBUG or higher.
*
* @param buffer Buffer to log
* @param length Length of buffer in bytes. Maximum length 128 bytes.
* @param label Label to print at beginning of log line.
*/
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label);

View file

@ -27,23 +27,30 @@ void bootloader_clock_configure()
// and will be done with the bootloader much earlier than UART FIFO is empty. // and will be done with the bootloader much earlier than UART FIFO is empty.
uart_tx_wait_idle(0); uart_tx_wait_idle(0);
/* Set CPU to 80MHz. Keep other clocks unmodified. */
int cpu_freq_mhz = 80;
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to /* 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 * 240 MHz may cause the chip to lock up (see section 3.5 of the errata
* document). For rev. 0, switch to 240 instead if it has been enabled * document). For rev. 0, switch to 240 instead if it has been enabled
* previously. * previously.
*/ */
#if CONFIG_IDF_TARGET_ESP32
/* Set CPU to 80MHz. Keep other clocks unmodified. */
int cpu_freq_mhz = 80;
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG); uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 && if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) { DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) {
cpu_freq_mhz = 240; cpu_freq_mhz = 240;
} }
#endif
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
#ifdef CONFIG_IDF_TARGET_ESP32
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
clk_cfg.cpu_freq_mhz = cpu_freq_mhz; clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
clk_cfg.cpu_freq = RTC_CPU_FREQ_80M;
#endif
clk_cfg.slow_freq = rtc_clk_slow_freq_get(); clk_cfg.slow_freq = rtc_clk_slow_freq_get();
clk_cfg.fast_freq = rtc_clk_fast_freq_get(); clk_cfg.fast_freq = rtc_clk_fast_freq_get();
rtc_clk_init(clk_cfg); rtc_clk_init(clk_cfg);

View file

@ -19,7 +19,6 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp32/rom/crc.h" #include "esp32/rom/crc.h"
#include "esp32/rom/gpio.h" #include "esp32/rom/gpio.h"
#include "esp_secure_boot.h"
#include "esp_flash_partitions.h" #include "esp_flash_partitions.h"
#include "bootloader_flash.h" #include "bootloader_flash.h"
#include "bootloader_common.h" #include "bootloader_common.h"

View file

@ -17,6 +17,9 @@
#include <esp_log.h> #include <esp_log.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */ #include <esp_spi_flash.h> /* including in bootloader for error values */
#include <esp_flash_encrypt.h> #include <esp_flash_encrypt.h>
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#endif
#ifndef BOOTLOADER_BUILD #ifndef BOOTLOADER_BUILD
/* Normal app version maps to esp_spi_flash.h operations... /* Normal app version maps to esp_spi_flash.h operations...
@ -32,7 +35,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
return NULL; /* existing mapping in use... */ return NULL; /* existing mapping in use... */
} }
const void *result = NULL; const void *result = NULL;
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1); uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
size += (src_addr - src_page); size += (src_addr - src_page);
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map); esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
if (err != ESP_OK) { if (err != ESP_OK) {
@ -44,7 +47,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
void bootloader_munmap(const void *mapping) void bootloader_munmap(const void *mapping)
{ {
if(mapping && map) { if (mapping && map) {
spi_flash_munmap(map); spi_flash_munmap(map);
} }
map = 0; map = 0;
@ -62,7 +65,11 @@ esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted) esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
{ {
if (write_encrypted) { if (write_encrypted) {
#if CONFIG_IDF_TARGET_ESP32
return spi_flash_write_encrypted(dest_addr, src, size); return spi_flash_write_encrypted(dest_addr, src, size);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
return SPI_Encrypt_Write(dest_addr, src, size);
#endif
} else { } else {
return spi_flash_write(dest_addr, src, size); return spi_flash_write(dest_addr, src, size);
} }
@ -81,16 +88,30 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
#else #else
/* Bootloader version, uses ROM functions only */ /* Bootloader version, uses ROM functions only */
#include <soc/dport_reg.h> #include <soc/dport_reg.h>
#if CONFIG_IDF_TARGET_ESP32
#include <esp32/rom/spi_flash.h> #include <esp32/rom/spi_flash.h>
#include <esp32/rom/cache.h> #include <esp32/rom/cache.h>
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include <esp32s2beta/rom/spi_flash.h>
#include <esp32s2beta/rom/cache.h>
#endif
static const char *TAG = "bootloader_flash"; static const char *TAG = "bootloader_flash";
#if CONFIG_IDF_TARGET_ESP32
/* Use first 50 blocks in MMU for bootloader_mmap, /* Use first 50 blocks in MMU for bootloader_mmap,
50th block for bootloader_flash_read 50th block for bootloader_flash_read
*/ */
#define MMU_BLOCK0_VADDR 0x3f400000 #define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_BLOCK50_VADDR 0x3f720000 #define MMU_SIZE (0x320000)
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#elif CONFIG_IDF_TARGET_ESP32S2BETA
/* Use first 63 blocks in MMU for bootloader_mmap,
63th block for bootloader_flash_read
*/
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_SIZE (0x3f0000)
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#endif
static bool mapped; static bool mapped;
@ -103,25 +124,41 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
ESP_LOGE(TAG, "tried to bootloader_mmap twice"); ESP_LOGE(TAG, "tried to bootloader_mmap twice");
return NULL; /* can't map twice */ return NULL; /* can't map twice */
} }
if (size > 0x320000) { if (size > MMU_SIZE) {
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size); ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
return NULL; return NULL;
} }
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK; uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
uint32_t count = bootloader_cache_pages_to_map(size, src_addr); uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0); Cache_Read_Disable(0);
Cache_Flush(0); Cache_Flush(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
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", 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 ); src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
#if CONFIG_IDF_TARGET_ESP32
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count); int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
#endif
if (e != 0) { if (e != 0) {
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e); ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
return NULL; return NULL;
} }
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
mapped = true; mapped = true;
@ -131,10 +168,17 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
void bootloader_munmap(const void *mapping) void bootloader_munmap(const void *mapping)
{ {
if (mapped) { if (mapped) {
#if CONFIG_IDF_TARGET_ESP32
/* Full MMU reset */ /* Full MMU reset */
Cache_Read_Disable(0); Cache_Read_Disable(0);
Cache_Flush(0); Cache_Flush(0);
mmu_init(0); mmu_init(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
//TODO, save the autoload value.
Cache_Suspend_ICache();
Cache_Invalidate_ICache_All();
Cache_MMU_Init();
#endif
mapped = false; mapped = false;
current_read_mapping = UINT32_MAX; current_read_mapping = UINT32_MAX;
} }
@ -142,7 +186,7 @@ void bootloader_munmap(const void *mapping)
static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r) static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
{ {
switch(r) { switch (r) {
case ESP_ROM_SPIFLASH_RESULT_OK: case ESP_ROM_SPIFLASH_RESULT_OK:
return ESP_OK; return ESP_OK;
case ESP_ROM_SPIFLASH_RESULT_ERR: case ESP_ROM_SPIFLASH_RESULT_ERR:
@ -156,10 +200,18 @@ static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size) static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
{ {
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0); Cache_Read_Disable(0);
Cache_Flush(0); Cache_Flush(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t autoload = Cache_Suspend_ICache();
#endif
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size); esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
return spi_to_esp_err(r); return spi_to_esp_err(r);
} }
@ -168,28 +220,46 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
{ {
uint32_t *dest_words = (uint32_t *)dest; uint32_t *dest_words = (uint32_t *)dest;
/* Use the 51st MMU mapping to read from flash in 64KB blocks.
(MMU will transparently decrypt if encryption is enabled.)
*/
for (int word = 0; word < size / 4; word++) { for (int word = 0; word < size / 4; word++) {
uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */ uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */ uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
uint32_t *map_ptr; uint32_t *map_ptr;
if (map_at != current_read_mapping) { if (map_at != current_read_mapping) {
/* Move the 64KB mmu mapping window to fit map_at */ /* Move the 64KB mmu mapping window to fit map_at */
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0); Cache_Read_Disable(0);
Cache_Flush(0); Cache_Flush(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
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); 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, MMU_BLOCK50_VADDR, map_at, 64, 1); int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
#endif
if (e != 0) { if (e != 0) {
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e); ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
return ESP_FAIL; return ESP_FAIL;
} }
current_read_mapping = map_at; current_read_mapping = map_at;
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
} }
#if CONFIG_IDF_TARGET_ESP32
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at)); map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
map_ptr = (uint32_t *)(MMU_BLOCK63_VADDR + (word_src - map_at));
#endif
dest_words[word] = *map_ptr; dest_words[word] = *map_ptr;
} }
return ESP_OK; return ESP_OK;
@ -240,7 +310,12 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
} }
if (write_encrypted) { if (write_encrypted) {
#if CONFIG_IDF_TARGET_ESP32
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size)); return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
// TODO: use the same ROM AP here
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
#endif
} else { } else {
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size)); return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
} }

View file

@ -19,6 +19,7 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_log.h" #include "esp_log.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/cache.h" #include "esp32/rom/cache.h"
#include "esp32/rom/efuse.h" #include "esp32/rom/efuse.h"
#include "esp32/rom/ets_sys.h" #include "esp32/rom/ets_sys.h"
@ -28,6 +29,19 @@
#include "esp32/rom/uart.h" #include "esp32/rom/uart.h"
#include "esp32/rom/gpio.h" #include "esp32/rom/gpio.h"
#include "esp32/rom/secure_boot.h" #include "esp32/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/rom/efuse.h"
#include "esp32s2beta/rom/ets_sys.h"
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/crc.h"
#include "esp32s2beta/rom/rtc.h"
#include "esp32s2beta/rom/uart.h"
#include "esp32s2beta/rom/gpio.h"
#include "esp32s2beta/rom/secure_boot.h"
#else
#error "Unsupported IDF_TARGET"
#endif
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/cpu.h" #include "soc/cpu.h"
@ -39,6 +53,11 @@
#include "soc/timer_periph.h" #include "soc/timer_periph.h"
#include "soc/rtc_wdt.h" #include "soc/rtc_wdt.h"
#include "soc/spi_periph.h" #include "soc/spi_periph.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "soc/spi_mem_reg.h"
#include "soc/extmem_reg.h"
#include "soc/assist_debug_reg.h"
#endif
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_image_format.h" #include "esp_image_format.h"
@ -48,6 +67,7 @@
#include "bootloader_flash.h" #include "bootloader_flash.h"
#include "bootloader_random.h" #include "bootloader_random.h"
#include "bootloader_config.h" #include "bootloader_config.h"
#include "bootloader_common.h"
#include "bootloader_clock.h" #include "bootloader_clock.h"
#include "bootloader_common.h" #include "bootloader_common.h"
@ -58,12 +78,13 @@ extern int _bss_end;
extern int _data_start; extern int _data_start;
extern int _data_end; extern int _data_end;
static const char* TAG = "boot"; static const char *TAG = "boot";
static esp_err_t bootloader_main(); static esp_err_t bootloader_main();
static void print_flash_info(const esp_image_header_t* pfhdr); static void print_flash_info(const esp_image_header_t *pfhdr);
static void update_flash_config(const esp_image_header_t* pfhdr); static void update_flash_config(const esp_image_header_t *pfhdr);
static void flash_gpio_configure(const esp_image_header_t* pfhdr); static void vddsdio_configure();
static void flash_gpio_configure(const esp_image_header_t *pfhdr);
static void uart_console_configure(void); static void uart_console_configure(void);
static void wdt_reset_check(void); static void wdt_reset_check(void);
@ -79,8 +100,10 @@ esp_err_t bootloader_init()
int *sp = get_sp(); int *sp = get_sp();
assert(&_bss_start <= &_bss_end); assert(&_bss_start <= &_bss_end);
assert(&_data_start <= &_data_end); assert(&_data_start <= &_data_end);
#if CONFIG_IDF_TARGET_ESP32
assert(sp < &_bss_start); assert(sp < &_bss_start);
assert(sp < &_data_start); assert(sp < &_data_start);
#endif
} }
#endif #endif
@ -89,14 +112,27 @@ esp_err_t bootloader_init()
/* completely reset MMU for both CPUs /* completely reset MMU for both CPUs
(in case serial bootloader was running) */ (in case serial bootloader was running) */
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0); Cache_Read_Disable(0);
#if !CONFIG_FREERTOS_UNICORE
Cache_Read_Disable(1); Cache_Read_Disable(1);
#endif
Cache_Flush(0); Cache_Flush(0);
#if !CONFIG_FREERTOS_UNICORE
Cache_Flush(1); Cache_Flush(1);
#endif
mmu_init(0); mmu_init(0);
#if !CONFIG_FREERTOS_UNICORE
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
mmu_init(1); mmu_init(1);
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
#endif
#elif CONFIG_IDF_TARGET_ESP32S2BETA
//TODO, save the autoload value
Cache_Suspend_ICache();
Cache_Invalidate_ICache_All();
Cache_MMU_Init();
#endif
/* (above steps probably unnecessary for most serial bootloader /* (above steps probably unnecessary for most serial bootloader
usage, all that's absolutely needed is that we unmask DROM0 usage, all that's absolutely needed is that we unmask DROM0
cache on the following two lines - normal ROM boot exits with cache on the following two lines - normal ROM boot exits with
@ -107,10 +143,18 @@ esp_err_t bootloader_init()
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
necessary to work around a hardware bug. necessary to work around a hardware bug.
*/ */
#if CONFIG_IDF_TARGET_ESP32
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
#if !CONFIG_FREERTOS_UNICORE
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
#endif
if(bootloader_main() != ESP_OK){ #elif CONFIG_IDF_TARGET_ESP32S2BETA
DPORT_REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_DROM0);
#if !CONFIG_FREERTOS_UNICORE
DPORT_REG_CLR_BIT(DPORT_APP_ICACHE_CTRL1_REG, DPORT_APP_ICACHE_MASK_DROM0);
#endif
#endif
if (bootloader_main() != ESP_OK) {
return ESP_FAIL; return ESP_FAIL;
} }
return ESP_OK; return ESP_OK;
@ -127,23 +171,25 @@ static esp_err_t bootloader_main()
return ESP_FAIL; return ESP_FAIL;
} }
flash_gpio_configure(&fhdr); flash_gpio_configure(&fhdr);
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
//Check if ESP32 is rated for a CPU frequency of 160MHz only int rated_freq = bootloader_clock_get_rated_freq_mhz();
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) && if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) { ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig"); rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
return ESP_FAIL; return ESP_FAIL;
} }
#endif
bootloader_clock_configure(); bootloader_clock_configure();
uart_console_configure(); uart_console_configure();
wdt_reset_check(); wdt_reset_check();
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
ESP_LOGI(TAG, "compile time " __TIME__ ); ESP_LOGI(TAG, "compile time " __TIME__ );
#if !CONFIG_FREERTOS_UNICORE
ets_set_appcpu_boot_addr(0); ets_set_appcpu_boot_addr(0);
#endif
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE #if CONFIG_BOOTLOADER_WDT_ENABLE && CONFIG_IDF_TARGET_ESP32
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS); ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
rtc_wdt_protect_off(); rtc_wdt_protect_off();
rtc_wdt_disable(); rtc_wdt_disable();
@ -153,7 +199,7 @@ static esp_err_t bootloader_main()
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS); rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
rtc_wdt_enable(); rtc_wdt_enable();
rtc_wdt_protect_on(); rtc_wdt_protect_on();
#else #elif CONFIG_IDF_TARGET_ESP32
/* disable watch dog here */ /* disable watch dog here */
rtc_wdt_disable(); rtc_wdt_disable();
#endif #endif
@ -162,7 +208,7 @@ static esp_err_t bootloader_main()
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH #ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = ets_efuse_get_spiconfig(); const uint32_t spiconfig = ets_efuse_get_spiconfig();
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig"); ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
return ESP_FAIL; return ESP_FAIL;
} }
@ -183,10 +229,10 @@ static esp_err_t bootloader_main()
return ESP_OK; return ESP_OK;
} }
static void update_flash_config(const esp_image_header_t* pfhdr) static void update_flash_config(const esp_image_header_t *pfhdr)
{ {
uint32_t size; uint32_t size;
switch(pfhdr->spi_size) { switch (pfhdr->spi_size) {
case ESP_IMAGE_FLASH_SIZE_1MB: case ESP_IMAGE_FLASH_SIZE_1MB:
size = 1; size = 1;
break; break;
@ -205,16 +251,24 @@ static void update_flash_config(const esp_image_header_t* pfhdr)
default: default:
size = 2; size = 2;
} }
Cache_Read_Disable( 0 ); #if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t autoload = Cache_Suspend_ICache();
#endif
// Set flash chip size // Set flash chip size
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
// TODO: set mode // TODO: set mode
// TODO: set frequency // TODO: set frequency
#if CONFIG_IDF_TARGET_ESP32
Cache_Flush(0); Cache_Flush(0);
Cache_Read_Enable( 0 ); Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
} }
static void print_flash_info(const esp_image_header_t* phdr) static void print_flash_info(const esp_image_header_t *phdr)
{ {
#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE) #if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
@ -224,7 +278,7 @@ static void print_flash_info(const esp_image_header_t* phdr)
ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed ); ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size ); ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
const char* str; const char *str;
switch ( phdr->spi_speed ) { switch ( phdr->spi_speed ) {
case ESP_IMAGE_SPI_SPEED_40M: case ESP_IMAGE_SPI_SPEED_40M:
str = "40MHz"; str = "40MHz";
@ -246,6 +300,7 @@ static void print_flash_info(const esp_image_header_t* phdr)
/* SPI mode could have been set to QIO during boot already, /* SPI mode could have been set to QIO during boot already,
so test the SPI registers not the flash header */ so test the SPI registers not the flash header */
#if CONFIG_IDF_TARGET_ESP32
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0)); uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
if (spi_ctrl & SPI_FREAD_QIO) { if (spi_ctrl & SPI_FREAD_QIO) {
str = "QIO"; str = "QIO";
@ -260,6 +315,22 @@ static void print_flash_info(const esp_image_header_t* phdr)
} else { } else {
str = "SLOW READ"; str = "SLOW READ";
} }
#elif CONFIG_IDF_TARGET_ESP32S2BETA
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";
}
#endif
ESP_LOGI(TAG, "SPI Mode : %s", str ); ESP_LOGI(TAG, "SPI Mode : %s", str );
switch ( phdr->spi_size ) { switch ( phdr->spi_size ) {
@ -286,21 +357,44 @@ static void print_flash_info(const esp_image_header_t* phdr)
#endif #endif
} }
static void vddsdio_configure()
{
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V
cfg.drefh = 3;
cfg.drefm = 3;
cfg.drefl = 3;
cfg.force = 1;
rtc_vddsdio_set_config(cfg);
ets_delay_us(10); // wait for regulator to become stable
}
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
}
#if CONFIG_IDF_TARGET_ESP32
#define FLASH_CLK_IO 6 #define FLASH_CLK_IO 6
#define FLASH_CS_IO 11 #define FLASH_CS_IO 11
#define FLASH_SPIQ_IO 7 #define FLASH_SPIQ_IO 7
#define FLASH_SPID_IO 8 #define FLASH_SPID_IO 8
#define FLASH_SPIWP_IO 10 #define FLASH_SPIWP_IO 10
#define FLASH_SPIHD_IO 9 #define FLASH_SPIHD_IO 9
#endif
#if CONFIG_IDF_TARGET_ESP32
#define FLASH_IO_MATRIX_DUMMY_40M 1 #define FLASH_IO_MATRIX_DUMMY_40M 1
#define FLASH_IO_MATRIX_DUMMY_80M 2 #define FLASH_IO_MATRIX_DUMMY_80M 2
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define FLASH_IO_MATRIX_DUMMY_40M 0
#define FLASH_IO_MATRIX_DUMMY_80M 0
#endif
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3 #define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
/* /*
* Bootloader reads SPI configuration from bin header, so that * Bootloader reads SPI configuration from bin header, so that
* the burning configuration can be different with compiling configuration. * the burning configuration can be different with compiling configuration.
*/ */
static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr) static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t *pfhdr)
{ {
int spi_cache_dummy = 0; int spi_cache_dummy = 0;
int drv = 2; int drv = 2;
@ -324,20 +418,30 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
case ESP_IMAGE_SPI_SPEED_80M: case ESP_IMAGE_SPI_SPEED_80M:
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
#endif
drv = 3; drv = 3;
break; break;
case ESP_IMAGE_SPI_SPEED_40M: case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
#endif
break; break;
default: default:
break; break;
} }
#if CONFIG_IDF_TARGET_ESP32
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7; uint32_t pkg_ver = chip_ver & 0x7;
@ -379,7 +483,7 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 #if CONFIG_SPIRAM_TYPE_ESPPSRAM32
uint32_t flash_id = g_rom_flashchip.device_id; uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) { if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz. // Set drive ability for 1.8v flash in 80Mhz.
@ -390,9 +494,12 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
} }
#endif #endif
} }
} }
#elif CONFIG_IDF_TARGET_ESP32S2BETA
bootloader_configure_spi_pins(drv);
#endif
} }
static void uart_console_configure(void) static void uart_console_configure(void)
@ -450,9 +557,16 @@ static void uart_console_configure(void)
static void wdt_reset_cpu0_info_enable(void) static void wdt_reset_cpu0_info_enable(void)
{ {
#if CONFIG_IDF_TARGET_ESP32
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1. //We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE); DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE); DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
REG_WRITE(ASSIST_DEBUG_PRO_PDEBUGENABLE, 1);
REG_WRITE(ASSIST_DEBUG_PRO_RCD_RECORDING, 1);
#endif
} }
static void wdt_reset_info_dump(int cpu) static void wdt_reset_info_dump(int cpu)
@ -461,6 +575,7 @@ static void wdt_reset_info_dump(int cpu)
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0; lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
const char *cpu_name = cpu ? "APP" : "PRO"; const char *cpu_name = cpu ? "APP" : "PRO";
#if CONFIG_IDF_TARGET_ESP32
if (cpu == 0) { if (cpu == 0) {
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG); stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG); pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
@ -473,6 +588,7 @@ static void wdt_reset_info_dump(int cpu)
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG); lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
} else { } else {
#if !CONFIG_FREERTOS_UNICORE
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG); stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG); pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG); inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
@ -482,7 +598,23 @@ static void wdt_reset_info_dump(int cpu)
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG); lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG); lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG); lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
#else
ESP_LOGE(TAG, "WDT reset info: &s CPU not support!\n", cpu_name);
return;
#endif
} }
#elif CONFIG_IDF_TARGET_ESP32S2BETA
stat = 0xdeadbeef;
pid = 0;
inst = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGINST);
dstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGSTATUS);
data = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGDATA);
pc = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGPC);
lsstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0STAT);
lsaddr = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0ADDR);
lsdata = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0DATA);
#endif
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 && if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) { DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc); ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
@ -506,6 +638,7 @@ static void wdt_reset_check(void)
RESET_REASON rst_reas[2]; RESET_REASON rst_reas[2];
rst_reas[0] = rtc_get_reset_reason(0); rst_reas[0] = rtc_get_reset_reason(0);
#if CONFIG_IDF_TARGET_ESP32
rst_reas[1] = rtc_get_reset_reason(1); rst_reas[1] = rtc_get_reset_reason(1);
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET || if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) { rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
@ -517,10 +650,19 @@ static void wdt_reset_check(void)
ESP_LOGW(TAG, "APP CPU has been reset by WDT."); ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
wdt_rst = 1; wdt_rst = 1;
} }
#elif CONFIG_IDF_TARGET_ESP32S2BETA
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;
}
#endif
if (wdt_rst) { if (wdt_rst) {
// if reset by WDT dump info from trace port // if reset by WDT dump info from trace port
wdt_reset_info_dump(0); wdt_reset_info_dump(0);
#if CONFIG_IDF_TARGET_ESP32
wdt_reset_info_dump(1); wdt_reset_info_dump(1);
#endif
} }
wdt_reset_cpu0_info_enable(); wdt_reset_cpu0_info_enable();
} }
@ -528,7 +670,7 @@ static void wdt_reset_check(void)
void __assert_func(const char *file, int line, const char *func, const char *expr) void __assert_func(const char *file, int line, const char *func, const char *expr)
{ {
ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr); ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
while(1) {} while (1) {}
} }
void abort() void abort()
@ -539,5 +681,5 @@ void abort()
if (esp_cpu_in_ocd_debug_mode()) { if (esp_cpu_in_ocd_debug_mode()) {
__asm__ ("break 0,0"); __asm__ ("break 0,0");
} }
while(1) {} while (1) {}
} }

View file

@ -47,14 +47,18 @@ void bootloader_fill_random(void *buffer, size_t length)
as-is, we repeatedly read the RNG register and XOR all as-is, we repeatedly read the RNG register and XOR all
values. values.
*/ */
#if CONFIG_IDF_TARGET_ESP32
random = REG_READ(WDEV_RND_REG); random = REG_READ(WDEV_RND_REG);
RSR(CCOUNT, start); RSR(CCOUNT, start);
do { do {
random ^= REG_READ(WDEV_RND_REG); random ^= REG_READ(WDEV_RND_REG);
RSR(CCOUNT, now); RSR(CCOUNT, now);
} while(now - start < 80*32*2); /* extra factor of 2 is precautionary */ } while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */
#elif CONFIG_IDF_TARGET_ESP32S2BETA
// ToDo: Get random from register
random = 12345678;
#endif
} }
buffer_bytes[i] = random >> ((i % 4) * 8); buffer_bytes[i] = random >> ((i % 4) * 8);
} }
} }
@ -92,18 +96,22 @@ 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_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_CTRL_REG, SENS_SAR1_DIG_FORCE);
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE); SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX); SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX);
#endif
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S); SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S);
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */ SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S); SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S);
#endif
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S); SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S);
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL); SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL);
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL); CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL);
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_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S);
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG,SYSCON_SARADC_DATA_TO_I2S); SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_TO_I2S);
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN); 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_LCD_EN);
@ -132,10 +140,16 @@ void bootloader_random_disable(void)
/* Restore SAR ADC mode */ /* Restore SAR ADC mode */
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST); CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
#if CONFIG_IDF_TARGET_ESP32
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S); | SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
#endif
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S); SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S); SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
#endif
/* Reset i2s peripheral */ /* Reset i2s peripheral */
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);

View file

@ -19,6 +19,7 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_log.h" #include "esp_log.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/cache.h" #include "esp32/rom/cache.h"
#include "esp32/rom/efuse.h" #include "esp32/rom/efuse.h"
#include "esp32/rom/ets_sys.h" #include "esp32/rom/ets_sys.h"
@ -28,6 +29,19 @@
#include "esp32/rom/uart.h" #include "esp32/rom/uart.h"
#include "esp32/rom/gpio.h" #include "esp32/rom/gpio.h"
#include "esp32/rom/secure_boot.h" #include "esp32/rom/secure_boot.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/rom/efuse.h"
#include "esp32s2beta/rom/ets_sys.h"
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/crc.h"
#include "esp32s2beta/rom/rtc.h"
#include "esp32s2beta/rom/uart.h"
#include "esp32s2beta/rom/gpio.h"
#include "esp32s2beta/rom/secure_boot.h"
#else
#error "Unsupported IDF_TARGET"
#endif
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/cpu.h" #include "soc/cpu.h"
@ -49,16 +63,19 @@
#include "bootloader_common.h" #include "bootloader_common.h"
#include "bootloader_utility.h" #include "bootloader_utility.h"
#include "bootloader_sha.h" #include "bootloader_sha.h"
#include "esp_efuse.h"
static const char* TAG = "boot"; #ifndef BOOTLOADER_BUILD // TODO: efuse component on esp32s2beta
#include "esp_efuse.h"
#endif
static const char *TAG = "boot";
/* Reduce literal size for some generic string literals */ /* Reduce literal size for some generic string literals */
#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped." #define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
static bool ota_has_initial_contents; static bool ota_has_initial_contents;
static void load_image(const esp_image_metadata_t* image_data); static void load_image(const esp_image_metadata_t *image_data);
static void unpack_load_app(const esp_image_metadata_t *data); static void unpack_load_app(const esp_image_metadata_t *data);
static void set_cache_and_start_app(uint32_t drom_addr, static void set_cache_and_start_app(uint32_t drom_addr,
uint32_t drom_load_addr, uint32_t drom_load_addr,
@ -96,7 +113,7 @@ static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_selec
return ESP_OK; return ESP_OK;
} }
bool bootloader_utility_load_partition_table(bootloader_state_t* bs) bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
{ {
const esp_partition_info_t *partitions; const esp_partition_info_t *partitions;
const char *partition_usage; const char *partition_usage;
@ -119,16 +136,16 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
ESP_LOGI(TAG, "Partition Table:"); ESP_LOGI(TAG, "Partition Table:");
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length"); ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
for(int i = 0; i < num_partitions; i++) { for (int i = 0; i < num_partitions; i++) {
const esp_partition_info_t *partition = &partitions[i]; const esp_partition_info_t *partition = &partitions[i];
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition); ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype); ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
partition_usage = "unknown"; partition_usage = "unknown";
/* valid partition table */ /* valid partition table */
switch(partition->type) { switch (partition->type) {
case PART_TYPE_APP: /* app partition */ case PART_TYPE_APP: /* app partition */
switch(partition->subtype) { switch (partition->subtype) {
case PART_SUBTYPE_FACTORY: /* factory binary */ case PART_SUBTYPE_FACTORY: /* factory binary */
bs->factory = partition->pos; bs->factory = partition->pos;
partition_usage = "factory app"; partition_usage = "factory app";
@ -143,15 +160,14 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos; bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
++bs->app_count; ++bs->app_count;
partition_usage = "OTA app"; partition_usage = "OTA app";
} } else {
else {
partition_usage = "Unknown app"; partition_usage = "Unknown app";
} }
break; break;
} }
break; /* PART_TYPE_APP */ break; /* PART_TYPE_APP */
case PART_TYPE_DATA: /* data partition */ case PART_TYPE_DATA: /* data partition */
switch(partition->subtype) { switch (partition->subtype) {
case PART_SUBTYPE_DATA_OTA: /* ota data */ case PART_SUBTYPE_DATA_OTA: /* ota data */
bs->ota_info = partition->pos; bs->ota_info = partition->pos;
partition_usage = "OTA data"; partition_usage = "OTA data";
@ -188,7 +204,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
bootloader_munmap(partitions); bootloader_munmap(partitions);
ESP_LOGI(TAG,"End of partition table"); ESP_LOGI(TAG, "End of partition table");
return true; return true;
} }
@ -214,7 +230,7 @@ static esp_partition_pos_t index_to_partition(const bootloader_state_t *bs, int
static void log_invalid_app_partition(int index) static void log_invalid_app_partition(int index)
{ {
const char *not_bootable = " is not bootable"; /* save a few string literal bytes */ const char *not_bootable = " is not bootable"; /* save a few string literal bytes */
switch(index) { switch (index) {
case FACTORY_INDEX: case FACTORY_INDEX:
ESP_LOGE(TAG, "Factory app partition%s", not_bootable); ESP_LOGE(TAG, "Factory app partition%s", not_bootable);
break; break;
@ -426,7 +442,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
esp_partition_pos_t part; esp_partition_pos_t part;
esp_image_metadata_t image_data; esp_image_metadata_t image_data;
if(start_index == TEST_APP_INDEX) { if (start_index == TEST_APP_INDEX) {
if (try_load_partition(&bs->test, &image_data)) { if (try_load_partition(&bs->test, &image_data)) {
load_image(&image_data); load_image(&image_data);
} else { } else {
@ -436,7 +452,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
} }
/* work backwards from start_index, down to the factory app */ /* work backwards from start_index, down to the factory app */
for(index = start_index; index >= FACTORY_INDEX; index--) { for (index = start_index; index >= FACTORY_INDEX; index--) {
part = index_to_partition(bs, index); part = index_to_partition(bs, index);
if (part.size == 0) { if (part.size == 0) {
continue; continue;
@ -450,7 +466,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
} }
/* failing that work forwards from start_index, try valid OTA slots */ /* failing that work forwards from start_index, try valid OTA slots */
for(index = start_index + 1; index < bs->app_count; index++) { for (index = start_index + 1; index < bs->app_count; index++) {
part = index_to_partition(bs, index); part = index_to_partition(bs, index);
if (part.size == 0) { if (part.size == 0) {
continue; continue;
@ -474,7 +490,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
} }
// Copy loaded segments to RAM, set up caches for mapped segments, and start application. // Copy loaded segments to RAM, set up caches for mapped segments, and start application.
static void load_image(const esp_image_metadata_t* image_data) static void load_image(const esp_image_metadata_t *image_data)
{ {
/** /**
* Rough steps for a first boot, when encryption and secure boot are both disabled: * Rough steps for a first boot, when encryption and secure boot are both disabled:
@ -571,6 +587,7 @@ static void load_image(const esp_image_metadata_t* image_data)
so issue a system reset to ensure flash encryption so issue a system reset to ensure flash encryption
cache resets properly */ cache resets properly */
ESP_LOGI(TAG, "Resetting with flash encryption enabled..."); ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
uart_tx_wait_idle(0);
bootloader_reset(); bootloader_reset();
} }
#endif #endif
@ -582,7 +599,7 @@ static void load_image(const esp_image_metadata_t* image_data)
unpack_load_app(image_data); unpack_load_app(image_data);
} }
static void unpack_load_app(const esp_image_metadata_t* data) static void unpack_load_app(const esp_image_metadata_t *data)
{ {
uint32_t drom_addr = 0; uint32_t drom_addr = 0;
uint32_t drom_load_addr = 0; uint32_t drom_load_addr = 0;
@ -637,8 +654,13 @@ static void set_cache_and_start_app(
{ {
int rc; int rc;
ESP_LOGD(TAG, "configure drom and irom and start"); ESP_LOGD(TAG, "configure drom and irom and start");
Cache_Read_Disable( 0 ); #if CONFIG_IDF_TARGET_ESP32
Cache_Flush( 0 ); Cache_Read_Disable(0);
Cache_Flush(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t autoload = Cache_Suspend_ICache();
Cache_Invalidate_ICache_All();
#endif
/* Clear the MMU entries that are already set up, /* Clear the MMU entries that are already set up,
so the new app only has the mappings it creates. so the new app only has the mappings it creates.
@ -651,32 +673,72 @@ static void set_cache_and_start_app(
uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr); uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr);
ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d",
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count); drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
#if CONFIG_IDF_TARGET_ESP32
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count); rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000,
64, drom_page_count, 0);
#endif
ESP_LOGV(TAG, "rc=%d", rc); ESP_LOGV(TAG, "rc=%d", rc);
#if !CONFIG_FREERTOS_UNICORE
rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count); rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
ESP_LOGV(TAG, "rc=%d", rc); ESP_LOGV(TAG, "rc=%d", rc);
#endif
uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK; uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK;
uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr); uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr);
ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d",
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count); irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
#if CONFIG_IDF_TARGET_ESP32
rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count); rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
ESP_LOGV(TAG, "rc=%d", rc); ESP_LOGV(TAG, "rc=%d", rc);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t iram1_used = 0, irom0_used = 0;
if (irom_load_addr + irom_size > IRAM1_ADDRESS_LOW) {
iram1_used = 1;
}
if (irom_load_addr + irom_size > IROM0_ADDRESS_LOW) {
irom0_used = 1;
}
if (iram1_used || irom0_used) {
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM0_ADDRESS_LOW, 0, 64, 64, 1);
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM1_ADDRESS_LOW, 0, 64, 64, 1);
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IRAM1);
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IRAM1);
if (irom0_used) {
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IROM0_ADDRESS_LOW, 0, 64, 64, 1);
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IROM0);
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IROM0);
}
}
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
#endif
ESP_LOGV(TAG, "rc=%d", rc);
#if !CONFIG_FREERTOS_UNICORE
rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count); rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
ESP_LOGV(TAG, "rc=%d", rc); ESP_LOGV(TAG, "rc=%d", rc);
#endif
#if CONFIG_IDF_TARGET_ESP32
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
DPORT_PRO_CACHE_MASK_DRAM1 ); DPORT_PRO_CACHE_MASK_DRAM1 );
#if !CONFIG_FREERTOS_UNICORE
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
DPORT_APP_CACHE_MASK_DRAM1 ); DPORT_APP_CACHE_MASK_DRAM1 );
#endif
Cache_Read_Enable( 0 ); #elif CONFIG_IDF_TARGET_ESP32S2BETA
DPORT_REG_CLR_BIT( DPORT_PRO_ICACHE_CTRL1_REG, (DPORT_PRO_ICACHE_MASK_IRAM0) | (DPORT_PRO_ICACHE_MASK_IRAM1 & 0) | (DPORT_PRO_ICACHE_MASK_IROM0 & 0) | DPORT_PRO_ICACHE_MASK_DROM0 );
#if !CONFIG_FREERTOS_UNICORE
DPORT_REG_CLR_BIT( DPORT_APP_ICACHE_CTRL1_REG, (DPORT_APP_ICACHE_MASK_IRAM0) | (DPORT_APP_ICACHE_MASK_IRAM1 & 0) | (DPORT_APP_ICACHE_MASK_IROM0 & 0) | DPORT_APP_ICACHE_MASK_DROM0 );
#endif
#endif
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Enable(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(autoload);
#endif
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
ESP_LOGD(TAG, "start: 0x%08x", entry_addr); ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
@ -688,7 +750,6 @@ static void set_cache_and_start_app(
(*entry)(); (*entry)();
} }
void bootloader_reset(void) void bootloader_reset(void)
{ {
#ifdef BOOTLOADER_BUILD #ifdef BOOTLOADER_BUILD
@ -719,3 +780,24 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
} }
return ESP_OK; return ESP_OK;
} }
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label)
{
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
assert(length <= 128); // Avoid unbounded VLA size
const uint8_t *bytes = (const uint8_t *)buffer;
char hexbuf[length * 2 + 1];
hexbuf[length * 2] = 0;
for (int i = 0; i < length; i++) {
for (int shift = 0; shift < 2; shift++) {
uint8_t nibble = (bytes[i] >> (shift ? 0 : 4)) & 0x0F;
if (nibble < 10) {
hexbuf[i * 2 + shift] = '0' + nibble;
} else {
hexbuf[i * 2 + shift] = 'a' + nibble - 10;
}
}
}
ESP_LOGD(TAG, "%s: %s", label, hexbuf);
#endif
}

View file

@ -0,0 +1,13 @@
#include "soc/efuse_reg.h"
#include "bootloader_clock.h"
int bootloader_clock_get_rated_freq_mhz()
{
//Check if ESP32 is rated for a CPU frequency of 160MHz only
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
return 160;
}
return 240;
}

View file

@ -0,0 +1,74 @@
#include "bootloader_common.h"
#include "sdkconfig.h"
#include "soc/efuse_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
#include "esp32/rom/efuse.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
#define FLASH_SPID_IO SPI_D_GPIO_NUM
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
void bootloader_configure_spi_pins(int drv)
{
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
// For ESP32D2WD the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
// For ESP32PICOD2 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
// For ESP32PICOD4 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz.
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
}
#endif
}
}
}

View file

@ -16,9 +16,10 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <sys/param.h> #include <sys/param.h>
#include "esp32/rom/sha.h" #include "esp32/rom/sha.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_periph.h" #include "soc/hwcrypto_periph.h"
#include "esp32/rom/ets_sys.h" // TO REMOVE
static uint32_t words_hashed; static uint32_t words_hashed;

View file

@ -162,7 +162,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
/* If the last flash_crypt_cnt bit is burned or write-disabled, the /* If the last flash_crypt_cnt bit is burned or write-disabled, the
device can't re-encrypt itself. */ device can't re-encrypt itself. */
if (flash_crypt_wr_dis) { if (flash_crypt_wr_dis || flash_crypt_cnt == 0xFF) {
ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis); ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
return ESP_FAIL; return ESP_FAIL;
} }

View file

@ -0,0 +1,12 @@
#include "sdkconfig.h"
#include "bootloader_clock.h"
int bootloader_clock_get_rated_freq_mhz()
{
#ifndef CONFIG_HARDWARE_IS_FPGA
#warning "FIXME this needs to be filled in for real hardware"
#endif
return 999;
}

View file

@ -0,0 +1,54 @@
#include "bootloader_common.h"
#include "sdkconfig.h"
#include "soc/efuse_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
#include "esp32s2beta/rom/efuse.h"
#include "esp32s2beta/rom/gpio.h"
#include "esp32s2beta/rom/spi_flash.h"
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
#define FLASH_SPID_IO SPI_D_GPIO_NUM
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
void bootloader_configure_spi_pins(int drv)
{
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz.
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S);
}
#endif
}
}

View file

@ -0,0 +1,53 @@
// Copyright 2017 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 <stdbool.h>
#include <string.h>
#include <assert.h>
#include <sys/param.h>
#include "esp32s2beta/rom/sha.h"
static SHA_CTX ctx;
// Words per SHA256 block
// static const size_t BLOCK_WORDS = (64/sizeof(uint32_t));
// Words in final SHA256 digest
// static const size_t DIGEST_WORDS = (32/sizeof(uint32_t));
bootloader_sha256_handle_t bootloader_sha256_start()
{
// 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);
}

View file

@ -0,0 +1,303 @@
// 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 <strings.h>
#include "bootloader_flash.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 "esp32s2beta/rom/secure_boot.h"
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/rom/efuse.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);
static esp_err_t encrypt_bootloader();
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)
{
// TODO: not clear why this is read from DATA1 and written to PGM_DATA2
uint32_t cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", cnt);
bool flash_crypt_wr_dis = false; // TODO: check if CRYPT_CNT is write disabled
_Static_assert(EFUSE_SPI_BOOT_CRYPT_CNT == 0x7, "assuming CRYPT_CNT is only 3 bits wide");
if (cnt == 1 || cnt == 3 || cnt == 7) {
/* Flash is already encrypted */
int left;
if (cnt == 7 /* || disabled */) {
left = 0;
} else if (cnt == 3) {
left = 1;
} else {
left = 2;
}
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
return ESP_OK;
}
else {
/* Flash is not encrypted, so encrypt it! */
return encrypt_flash_contents(cnt, flash_crypt_wr_dis);
}
}
static esp_err_t initialise_flash_encryption(void)
{
/* Before first flash encryption pass, need to initialise key & crypto config */
/* Find out if a key is already set */
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, NULL);
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, NULL);
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, NULL);
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_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) {
ESP_LOGI(TAG, "Using pre-existing key in efuse");
ESP_LOGE(TAG, "TODO: Check key is read & write protected"); // TODO
} else {
ESP_LOGI(TAG, "Generating new flash encryption key...");
#ifdef CONFIG_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];
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);
bootloader_debug_buffer(buf, sizeof(buf), "Key content");
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
bzero(buf, sizeof(buf));
if (r != 0) {
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.");
return ESP_FAIL;
}
}
ESP_LOGD(TAG, "Key generation complete");
}
ESP_LOGE(TAG, "TODO: burn remaining security protection bits"); // TODO
return ESP_OK;
}
/* 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 = 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);
ets_efuse_clear_program_registers();
REG_SET_FIELD(EFUSE_PGM_DATA2_REG, EFUSE_SPI_BOOT_CRYPT_CNT, new_spi_boot_crypt_cnt);
ets_efuse_program(ETS_EFUSE_BLOCK0);
ESP_LOGI(TAG, "Flash encryption completed");
return ESP_OK;
}
static esp_err_t encrypt_bootloader()
{
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...");
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;
}
if (esp_secure_boot_enabled()) {
// TODO: anything different for secure boot?
}
}
else {
ESP_LOGW(TAG, "no valid bootloader was found");
}
return ESP_OK;
}
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_basic_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 */
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_load(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;
}
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
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;
}

View file

@ -0,0 +1,45 @@
// 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 "esp_secure_boot.h"
#include "esp_log.h"
#include "esp32s2beta/rom/secure_boot.h"
#define TAG "secure_boot"
esp_err_t esp_secure_boot_permanently_enable(void)
{
uint8_t hash[32];
if (ets_efuse_secure_boot_enabled())
{
ESP_LOGI(TAG, "secure boot is already enabled, continuing..");
return ESP_OK;
}
ESP_LOGI(TAG, "Verifying bootloader signature...\n");
int r = ets_secure_boot_verify_bootloader(hash, false);
if (r != ESP_OK) {
ESP_LOGE(TAG, "Failed to verify bootloader signature");
return r;
}
ets_efuse_clear_program_registers();
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
ets_efuse_program(ETS_EFUSE_BLOCK0);
assert(ets_efuse_secure_boot_enabled());
ESP_LOGI(TAG, "Secure boot permanently enabled");
return ESP_OK;
}

View file

@ -0,0 +1,92 @@
// 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 "sdkconfig.h"
#include "bootloader_flash.h"
#include "bootloader_sha.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp32s2beta/rom/secure_boot.h"
static const char* TAG = "secure_boot";
#define DIGEST_LEN 32
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
ets_secure_boot_key_digests_t trusted_keys = { 0 };
uint8_t digest[DIGEST_LEN];
const uint8_t *data;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
if ((src_addr + length) % 4096 != 0) {
ESP_LOGE(TAG, "addr 0x%x length 0x%x doesn't end on a sector boundary", src_addr, length);
return ESP_ERR_INVALID_ARG;
}
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
#ifdef BOOTLOADER_BUILD
bootloader_sha256_handle_t handle = bootloader_sha256_start();
bootloader_sha256_data(handle, data, length);
bootloader_sha256_finish(handle, digest);
#else
/* Use thread-safe esp-idf SHA function */
esp_sha(SHA2_256, data, length, digest);
#endif
int r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r == ETS_OK) {
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
// TODO: calling this function in IDF app context is unsafe
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys);
}
bootloader_munmap(data);
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest)
{
ets_secure_boot_key_digests_t trusted_keys;
assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way
const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t));
if (sig == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs);
return ESP_FAIL;
}
int r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r != 0) {
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
} else {
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
// TODO: calling this function in IDF app context is unsafe
r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys);
}
bootloader_munmap(sig);
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}

View file

@ -13,8 +13,6 @@
// limitations under the License. // limitations under the License.
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#include <esp32/rom/rtc.h>
#include <soc/cpu.h> #include <soc/cpu.h>
#include <bootloader_utility.h> #include <bootloader_utility.h>
#include <esp_secure_boot.h> #include <esp_secure_boot.h>
@ -24,6 +22,14 @@
#include <bootloader_random.h> #include <bootloader_random.h>
#include <bootloader_sha.h> #include <bootloader_sha.h>
#include "bootloader_util.h" #include "bootloader_util.h"
#include "bootloader_utility.h"
#if CONFIG_IDF_TARGET_ESP32
#include <esp32/rom/rtc.h>
#include <esp32/rom/secure_boot.h>
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include <esp32s2beta/rom/rtc.h>
#include <esp32s2beta/rom/secure_boot.h>
#endif
/* Checking signatures as part of verifying images is necessary: /* Checking signatures as part of verifying images is necessary:
- Always if secure boot is enabled - Always if secure boot is enabled
@ -156,7 +162,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
} }
uint32_t next_addr = data->start_addr + sizeof(esp_image_header_t); uint32_t next_addr = data->start_addr + sizeof(esp_image_header_t);
for(int i = 0; i < data->image.segment_count; i++) { for (int i = 0; i < data->image.segment_count; i++) {
esp_image_segment_header_t *header = &data->segments[i]; esp_image_segment_header_t *header = &data->segments[i];
ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr); ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr);
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, &checksum_word); err = process_segment(i, next_addr, header, silent, do_load, sha_handle, &checksum_word);
@ -186,13 +192,19 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size); FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
} }
bool is_bootloader = (data->start_addr == ESP_BOOTLOADER_OFFSET);
/* For secure boot, we don't verify signature on bootloaders. /* For secure boot, we don't verify signature on bootloaders.
For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because esptool.py may have For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because esptool.py may have
rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead. rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.
*/ */
if (!is_bootloader) { bool should_verify;
#if defined(CONFIG_SECURE_BOOT_ENABLED) && defined(CONFIG_IDF_TARGET_ESP32S2BETA)
should_verify = true;
#else // ESP32, or ESP32S2 without secure boot enabled
should_verify = (data->start_addr != ESP_BOOTLOADER_OFFSET);
#endif
if (should_verify) {
#ifdef SECURE_BOOT_CHECK_SIGNATURE #ifdef SECURE_BOOT_CHECK_SIGNATURE
// secure boot images have a signature appended // secure boot images have a signature appended
err = verify_secure_boot_signature(sha_handle, data); err = verify_secure_boot_signature(sha_handle, data);
@ -202,7 +214,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
err = verify_simple_hash(sha_handle, data); err = verify_simple_hash(sha_handle, data);
} }
#endif // SECURE_BOOT_CHECK_SIGNATURE #endif // SECURE_BOOT_CHECK_SIGNATURE
} else { // is_bootloader } else {
// bootloader may still have a sha256 digest handle open // bootloader may still have a sha256 digest handle open
if (sha_handle != NULL) { if (sha_handle != NULL) {
bootloader_sha256_finish(sha_handle, NULL); bootloader_sha256_finish(sha_handle, NULL);
@ -230,7 +242,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
uint32_t load_addr = data->segments[i].load_addr; uint32_t load_addr = data->segments[i].load_addr;
if (should_load(load_addr)) { if (should_load(load_addr)) {
uint32_t *loaded = (uint32_t *)load_addr; uint32_t *loaded = (uint32_t *)load_addr;
for (int j = 0; j < data->segments[i].data_len/sizeof(uint32_t); j++) { for (int j = 0; j < data->segments[i].data_len / sizeof(uint32_t); j++) {
loaded[j] ^= (j & 1) ? ram_obfs_value[0] : ram_obfs_value[1]; loaded[j] ^= (j & 1) ? ram_obfs_value[0] : ram_obfs_value[1];
} }
} }
@ -241,7 +253,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
// Success! // Success!
return ESP_OK; return ESP_OK;
err: err:
if (err == ESP_OK) { if (err == ESP_OK) {
err = ESP_ERR_IMAGE_INVALID; err = ESP_ERR_IMAGE_INVALID;
} }
@ -330,7 +342,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
ESP_LOGI(TAG, "segment %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s", ESP_LOGI(TAG, "segment %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s",
index, data_addr, load_addr, index, data_addr, load_addr,
data_len, data_len, data_len, data_len,
(do_load)?"load":(is_mapping)?"map":""); (do_load) ? "load" : (is_mapping) ? "map" : "");
} }
@ -370,10 +382,10 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
#ifndef BOOTLOADER_BUILD #ifndef BOOTLOADER_BUILD
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count); ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
uint32_t offset_page = 0; uint32_t offset_page = 0;
while (data_len >= free_page_count * SPI_FLASH_MMU_PAGE_SIZE) { while (data_len >= free_page_count * SPI_FLASH_MMU_PAGE_SIZE) {
offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0)?1:0; offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum); err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
@ -399,7 +411,7 @@ err:
static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum) static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
{ {
const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len); const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len);
if(!data) { if (!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed",
data_addr, data_len); data_addr, data_len);
return ESP_FAIL; return ESP_FAIL;
@ -416,7 +428,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
const uint32_t *src = data; const uint32_t *src = data;
for (int i = 0; i < data_len; i += 4) { for (int i = 0; i < data_len; i += 4) {
int w_i = i/4; // Word index int w_i = i / 4; // Word index
uint32_t w = src[w_i]; uint32_t w = src[w_i];
*checksum ^= w; *checksum ^= w;
#ifdef BOOTLOADER_BUILD #ifdef BOOTLOADER_BUILD
@ -568,26 +580,36 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
return ESP_OK; return ESP_OK;
} }
static void debug_log_hash(const uint8_t *image_hash, const char *caption);
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data) static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
{ {
uint8_t image_hash[HASH_LEN] = { 0 }; uint8_t image_hash[HASH_LEN] = { 0 };
uint32_t end = data->start_addr + data->image_len;
ESP_LOGI(TAG, "Verifying image signature..."); ESP_LOGI(TAG, "Verifying image signature...");
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash // For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
// appended to the image for corruption detection // appended to the image for corruption detection
if (data->image.hash_appended) { if (data->image.hash_appended) {
const void *simple_hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN); const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN); bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
bootloader_munmap(simple_hash); bootloader_munmap(simple_hash);
} }
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
// Pad to 4096 byte sector boundary
if (end % FLASH_SECTOR_SIZE != 0) {
uint32_t pad_len = FLASH_SECTOR_SIZE - (end % FLASH_SECTOR_SIZE);
const void *padding = bootloader_mmap(end, pad_len);
bootloader_sha256_data(sha_handle, padding, pad_len);
bootloader_munmap(padding);
end += pad_len;
}
#endif
bootloader_sha256_finish(sha_handle, image_hash); bootloader_sha256_finish(sha_handle, image_hash);
// Log the hash for debugging // Log the hash for debugging
debug_log_hash(image_hash, "Calculated secure boot hash"); bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash");
// Use hash to verify signature block // Use hash to verify signature block
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t)); const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
@ -612,6 +634,11 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
return ESP_ERR_IMAGE_INVALID; return ESP_ERR_IMAGE_INVALID;
} }
#if CONFIG_IDF_TARGET_ESP32S2BETA
// Adjust image length result to include the appended signature
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
#endif
return ESP_OK; return ESP_OK;
} }
@ -621,13 +648,13 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
bootloader_sha256_finish(sha_handle, image_hash); bootloader_sha256_finish(sha_handle, image_hash);
// Log the hash for debugging // Log the hash for debugging
debug_log_hash(image_hash, "Calculated hash"); bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated hash");
// Simple hash for verification only // Simple hash for verification only
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN); const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
if (memcmp(hash, image_hash, HASH_LEN) != 0) { if (memcmp(hash, image_hash, HASH_LEN) != 0) {
ESP_LOGE(TAG, "Image hash failed - image is corrupt"); ESP_LOGE(TAG, "Image hash failed - image is corrupt");
debug_log_hash(hash, "Expected hash"); bootloader_debug_buffer(hash, HASH_LEN, "Expected hash");
bootloader_munmap(hash); bootloader_munmap(hash);
return ESP_ERR_IMAGE_INVALID; return ESP_ERR_IMAGE_INVALID;
} }
@ -635,14 +662,3 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
bootloader_munmap(hash); bootloader_munmap(hash);
return ESP_OK; return ESP_OK;
} }
// Log a hash as a hex string
static void debug_log_hash(const uint8_t *image_hash, const char *label)
{
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
char hash_print[HASH_LEN * 2 + 1];
hash_print[HASH_LEN * 2] = 0;
bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
ESP_LOGD(TAG, "%s: %s", label, hash_print);
#endif
}

View file

@ -16,14 +16,28 @@
#include "flash_qio_mode.h" #include "flash_qio_mode.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_err.h" #include "esp_err.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h" #include "esp32/rom/spi_flash.h"
#include "esp32/rom/efuse.h" #include "esp32/rom/efuse.h"
#include "soc/spi_periph.h" #elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/efuse.h"
#endif
#include "soc/spi_struct.h"
#include "soc/spi_reg.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "soc/spi_mem_struct.h"
#endif
#include "soc/efuse_periph.h" #include "soc/efuse_periph.h"
#include "soc/io_mux_reg.h"
#include "sdkconfig.h" #include "sdkconfig.h"
/* SPI flash controller */ /* SPI flash controller */
#if CONFIG_IDF_TARGET_ESP32
#define SPIFLASH SPI1 #define SPIFLASH SPI1
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define SPIFLASH SPIMEM1
#endif
/* SPI commands (actual on-wire commands not SPI controller bitmasks) /* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the execute_flash_command static function. Suitable for use with the execute_flash_command static function.
@ -42,7 +56,8 @@ static const char *TAG = "qio_mode";
typedef unsigned (*read_status_fn_t)(); typedef unsigned (*read_status_fn_t)();
typedef void (*write_status_fn_t)(unsigned); typedef void (*write_status_fn_t)(unsigned);
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed))
{
const char *manufacturer; const char *manufacturer;
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */ uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */ uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
@ -90,7 +105,7 @@ static void write_status_8b_xmc25qu64a(unsigned new_status);
Searching of this table stops when the first match is found. Searching of this table stops when the first match is found.
*/ */
const static qio_info_t chip_data[] = { const static qio_info_t chip_data[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */ /* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */ { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
@ -128,6 +143,46 @@ uint32_t bootloader_read_flash_id()
return id; return id;
} }
#if CONFIG_IDF_TARGET_ESP32S2BETA
#define FLASH_WRAP_CMD 0x77
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif
void bootloader_enable_qio_mode(void) void bootloader_enable_qio_mode(void)
{ {
uint32_t raw_flash_id; uint32_t raw_flash_id;
@ -145,7 +200,7 @@ void bootloader_enable_qio_mode(void)
flash_id = raw_flash_id & 0xFFFF; flash_id = raw_flash_id & 0xFFFF;
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id); ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
for (i = 0; i < NUM_CHIPS-1; i++) { for (i = 0; i < NUM_CHIPS - 1; i++) {
const qio_info_t *chip = &chip_data[i]; const qio_info_t *chip = &chip_data[i];
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) { if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer); ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
@ -156,7 +211,9 @@ void bootloader_enable_qio_mode(void)
if (i == NUM_CHIPS - 1) { if (i == NUM_CHIPS - 1) {
ESP_LOGI(TAG, "Enabling default flash chip QIO"); ESP_LOGI(TAG, "Enabling default flash chip QIO");
} }
#if CONFIG_IDF_TARGET_ESP32S2BETA
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
#endif
enable_qio_mode(chip_data[i].read_status_fn, enable_qio_mode(chip_data[i].read_status_fn,
chip_data[i].write_status_fn, chip_data[i].write_status_fn,
chip_data[i].status_qio_bit); chip_data[i].status_qio_bit);
@ -169,6 +226,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
uint32_t status; uint32_t status;
const uint32_t spiconfig = ets_efuse_get_spiconfig(); const uint32_t spiconfig = ets_efuse_get_spiconfig();
#if CONFIG_IDF_TARGET_ESP32
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP, // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
// which is compiled into the bootloader instead. // which is compiled into the bootloader instead.
@ -184,21 +242,22 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash"); ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash");
} }
} }
#endif
esp_rom_spiflash_wait_idle(&g_rom_flashchip); esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn(); status = read_status_fn();
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status); ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) { if ((status & (1 << status_qio_bit)) == 0) {
execute_flash_command(CMD_WREN, 0, 0, 0); execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1<<status_qio_bit)); write_status_fn(status | (1 << status_qio_bit));
esp_rom_spiflash_wait_idle(&g_rom_flashchip); esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn(); status = read_status_fn();
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status); ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) { if ((status & (1 << status_qio_bit)) == 0) {
ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode"); ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
return ESP_FAIL; return ESP_FAIL;
} }
@ -218,8 +277,15 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
esp_rom_spiflash_config_readmode(mode); esp_rom_spiflash_config_readmode(mode);
#if CONFIG_IDF_TARGET_ESP32
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig); esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (ets_efuse_get_wp_pad() <= MAX_PAD_GPIO_NUM) {
esp_rom_spiflash_select_qio_pins(ets_efuse_get_wp_pad(), spiconfig);
} else {
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
}
#endif
return ESP_OK; return ESP_OK;
} }
@ -274,7 +340,11 @@ static void write_status_8b_xmc25qu64a(unsigned new_status)
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{ {
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#endif
SPIFLASH.user.usr_dummy = 0; SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 0; SPIFLASH.user.usr_addr = 0;
SPIFLASH.user.usr_command = 1; SPIFLASH.user.usr_command = 1;
@ -282,9 +352,17 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
SPIFLASH.user2.usr_command_value = command; SPIFLASH.user2.usr_command_value = command;
SPIFLASH.user.usr_miso = miso_len > 0; SPIFLASH.user.usr_miso = miso_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
#endif
SPIFLASH.user.usr_mosi = mosi_len > 0; SPIFLASH.user.usr_mosi = mosi_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
#endif
SPIFLASH.data_buf[0] = mosi_data; SPIFLASH.data_buf[0] = mosi_data;
if (g_rom_spiflash_dummy_len_plus[1]) { if (g_rom_spiflash_dummy_len_plus[1]) {
@ -299,8 +377,8 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
} }
SPIFLASH.cmd.usr = 1; SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0) while (SPIFLASH.cmd.usr != 0) {
{ } }
SPIFLASH.ctrl.val = old_ctrl_reg; SPIFLASH.ctrl.val = old_ctrl_reg;
return SPIFLASH.data_buf[0]; return SPIFLASH.data_buf[0];

View file

@ -1,5 +1,10 @@
idf_build_get_property(soc_name IDF_TARGET) idf_build_get_property(soc_name IDF_TARGET)
# TODO: add esp32sbeta support for efuse component
if(NOT CONFIG_IDF_TARGET_ESP32)
return()
endif()
if(EXISTS "${COMPONENT_DIR}/${soc_name}") if(EXISTS "${COMPONENT_DIR}/${soc_name}")
include(${COMPONENT_DIR}/${soc_name}/sources.cmake) include(${COMPONENT_DIR}/${soc_name}/sources.cmake)
spaces2list(EFUSE_SOC_SRCS) spaces2list(EFUSE_SOC_SRCS)
@ -7,6 +12,7 @@ if(EXISTS "${COMPONENT_DIR}/${soc_name}")
set(COMPONENT_ADD_INCLUDEDIRS include ${soc_name}/include) set(COMPONENT_ADD_INCLUDEDIRS include ${soc_name}/include)
endif() endif()
list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
list(APPEND COMPONENT_SRCS "src/esp_efuse_api.c" list(APPEND COMPONENT_SRCS "src/esp_efuse_api.c"
"src/esp_efuse_fields.c" "src/esp_efuse_fields.c"
"src/esp_efuse_utility.c") "src/esp_efuse_utility.c")

View file

@ -1,11 +1,11 @@
require_idf_targets(esp32) # require_idf_targets(esp32)
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD AND CONFIG_IDF_TARGET_ESP32)
# For bootloader, all we need from esp32 is headers # For bootloader, all we need from esp32 is headers
set(COMPONENT_ADD_INCLUDEDIRS include) set(COMPONENT_ADD_INCLUDEDIRS include)
register_component() register_component()
target_linker_script(${COMPONENT_LIB} "ld/esp32.peripherals.ld") target_linker_script(${COMPONENT_LIB} "ld/esp32.peripherals.ld")
else() elseif(CONFIG_IDF_TARGET_ESP32)
# Regular app build # Regular app build
set(COMPONENT_SRCS "brownout.c" set(COMPONENT_SRCS "brownout.c"

View file

@ -4,6 +4,9 @@ if(BOOTLOADER_BUILD AND CONFIG_IDF_TARGET_ESP32S2BETA)
set(COMPONENT_REQUIRES ${IDF_COMPONENTS} soc) #unfortunately rom/uart uses SOC registers directly set(COMPONENT_REQUIRES ${IDF_COMPONENTS} soc) #unfortunately rom/uart uses SOC registers directly
set(COMPONENT_SRCS ) set(COMPONENT_SRCS )
register_component() register_component()
idf_build_get_property(target IDF_TARGET)
set(scripts "ld/esp32s2beta.peripherals.ld")
target_linker_script(${COMPONENT_LIB} "${scripts}")
elseif(CONFIG_IDF_TARGET_ESP32S2BETA) elseif(CONFIG_IDF_TARGET_ESP32S2BETA)
# Regular app build # Regular app build

View file

@ -116,7 +116,6 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
{ {
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
int cpu_id = xPortGetCoreID(); int cpu_id = xPortGetCoreID();
if (dport_core_state[0] == DPORT_CORE_STATE_IDLE if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
|| dport_core_state[1] == DPORT_CORE_STATE_IDLE) { || dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
return; return;

View file

@ -340,7 +340,6 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force
ALCHLOG("....Unusable: reserved at runtime."); ALCHLOG("....Unusable: reserved at runtime.");
return false; return false;
} }
//Ints can't be both shared and non-shared. //Ints can't be both shared and non-shared.
assert(!((vd->flags&VECDESC_FL_SHARED)&&(vd->flags&VECDESC_FL_NONSHARED))); assert(!((vd->flags&VECDESC_FL_SHARED)&&(vd->flags&VECDESC_FL_NONSHARED)));
//check if interrupt already is in use by a non-shared interrupt //check if interrupt already is in use by a non-shared interrupt
@ -368,7 +367,6 @@ static bool is_vect_desc_usable(vector_desc_t *vd, int flags, int cpu, int force
ALCHLOG("....Unusable: already allocated"); ALCHLOG("....Unusable: already allocated");
return false; return false;
} }
return true; return true;
} }
@ -385,7 +383,6 @@ static int get_available_int(int flags, int cpu, int force, int source)
vector_desc_t empty_vect_desc; vector_desc_t empty_vect_desc;
memset(&empty_vect_desc, 0, sizeof(vector_desc_t)); memset(&empty_vect_desc, 0, sizeof(vector_desc_t));
//Level defaults to any low/med interrupt //Level defaults to any low/med interrupt
if (!(flags&ESP_INTR_FLAG_LEVELMASK)) flags|=ESP_INTR_FLAG_LOWMED; if (!(flags&ESP_INTR_FLAG_LEVELMASK)) flags|=ESP_INTR_FLAG_LOWMED;
@ -433,12 +430,10 @@ static int get_available_int(int flags, int cpu, int force, int source)
ALCHLOG("Int %d reserved %d level %d %s hasIsr %d", ALCHLOG("Int %d reserved %d level %d %s hasIsr %d",
x, int_desc[x].cpuflags[cpu]==INTDESC_RESVD, int_desc[x].level, x, int_desc[x].cpuflags[cpu]==INTDESC_RESVD, int_desc[x].level,
int_desc[x].type==INTTP_LEVEL?"LEVEL":"EDGE", int_has_handler(x, cpu)); int_desc[x].type==INTTP_LEVEL?"LEVEL":"EDGE", int_has_handler(x, cpu));
if ( !is_vect_desc_usable(vd, flags, cpu, force) ) continue; if ( !is_vect_desc_usable(vd, flags, cpu, force) ) continue;
if (flags&ESP_INTR_FLAG_SHARED) { if (flags&ESP_INTR_FLAG_SHARED) {
//We're allocating a shared int. //We're allocating a shared int.
//See if int already is used as a shared interrupt. //See if int already is used as a shared interrupt.
if (vd->flags&VECDESC_FL_SHARED) { if (vd->flags&VECDESC_FL_SHARED) {
//We can use this already-marked-as-shared interrupt. Count the already attached isrs in order to see //We can use this already-marked-as-shared interrupt. Count the already attached isrs in order to see

View file

@ -0,0 +1,332 @@
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
/* RTC fast memory holds RTC wake stub code,
including from any source file named rtc_wake_stub*.c
*/
.rtc.text :
{
. = ALIGN(4);
mapping[rtc_text]
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
_rtc_text_end = ABSOLUTE(.);
} > rtc_iram_seg
/*
This section is required to skip rtc.text area because rtc_iram_seg and
rtc_data_seg are reflect the same address space on different buses.
*/
.rtc.dummy :
{
_rtc_dummy_start = ABSOLUTE(.);
_rtc_fast_start = ABSOLUTE(.);
. = SIZEOF(.rtc.text);
_rtc_dummy_end = ABSOLUTE(.);
} > rtc_data_seg
/* This section located in RTC FAST Memory area.
It holds data marked with RTC_FAST_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_fast :
{
. = ALIGN(4);
_rtc_force_fast_start = ABSOLUTE(.);
*(.rtc.force_fast .rtc.force_fast.*)
. = ALIGN(4) ;
_rtc_force_fast_end = ABSOLUTE(.);
} > rtc_data_seg
/* RTC data section holds RTC wake stub
data/rodata, including from any source file
named rtc_wake_stub*.c and the data marked with
RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
mapping[rtc_data]
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location
/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(COMMON)
mapping[rtc_bss]
_rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location
/* This section holds data that should not be initialized at power up
and will be retained during deep sleep.
User data marked with RTC_NOINIT_ATTR will be placed
into this section. See the file "esp_attr.h" for more information.
The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc_noinit (NOLOAD):
{
. = ALIGN(4);
_rtc_noinit_start = ABSOLUTE(.);
*(.rtc_noinit .rtc_noinit.*)
. = ALIGN(4) ;
_rtc_noinit_end = ABSOLUTE(.);
} > rtc_data_location
/* This section located in RTC SLOW Memory area.
It holds data marked with RTC_SLOW_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_slow :
{
. = ALIGN(4);
_rtc_force_slow_start = ABSOLUTE(.);
*(.rtc.force_slow .rtc.force_slow.*)
. = ALIGN(4) ;
_rtc_force_slow_end = ABSOLUTE(.);
} > rtc_slow_seg
/* Get size of rtc slow data based on rtc_data_location alias */
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_slow_end - _rtc_data_start)
: (_rtc_force_slow_end - _rtc_force_slow_start);
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_fast_end - _rtc_fast_start)
: (_rtc_noinit_end - _rtc_fast_start);
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
"RTC_SLOW segment data does not fit.")
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
"RTC_FAST segment data does not fit.")
/* Send .iram0 code to iram */
.iram0.vectors :
{
_iram_start = ABSOLUTE(.);
/* Vectors go to IRAM */
_init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
. = 0x0;
KEEP(*(.WindowVectors.text));
. = 0x180;
KEEP(*(.Level2InterruptVector.text));
. = 0x1c0;
KEEP(*(.Level3InterruptVector.text));
. = 0x200;
KEEP(*(.Level4InterruptVector.text));
. = 0x240;
KEEP(*(.Level5InterruptVector.text));
. = 0x280;
KEEP(*(.DebugExceptionVector.text));
. = 0x2c0;
KEEP(*(.NMIExceptionVector.text));
. = 0x300;
KEEP(*(.KernelExceptionVector.text));
. = 0x340;
KEEP(*(.UserExceptionVector.text));
. = 0x3C0;
KEEP(*(.DoubleExceptionVector.text));
. = 0x400;
*(.*Vector.literal)
*(.UserEnter.literal);
*(.UserEnter.text);
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
_init_end = ABSOLUTE(.);
} > iram0_0_seg
.iram0.text :
{
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
mapping[iram0_text]
_iram_text_end = ABSOLUTE(.);
_iram_end = ABSOLUTE(.);
} > iram0_0_seg
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
"IRAM0 segment data does not fit.")
.dram0.data :
{
_data_start = ABSOLUTE(.);
_bt_data_start = ABSOLUTE(.);
*libbt.a:(.data .data.*)
. = ALIGN (4);
_bt_data_end = ABSOLUTE(.);
_btdm_data_start = ABSOLUTE(.);
*libbtdm_app.a:(.data .data.*)
. = ALIGN (4);
_btdm_data_end = ABSOLUTE(.);
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
mapping[dram0_data]
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} > dram0_0_seg
/*This section holds data that should not be initialized at power up.
The section located in Internal SRAM memory region. The macro _NOINIT
can be used as attribute to place data into this section.
See the esp_attr.h file for more information.
*/
.noinit (NOLOAD):
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
*(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.ext_ram.bss*)
_bt_bss_start = ABSOLUTE(.);
*libbt.a:(.bss .bss.* COMMON)
. = ALIGN (4);
_bt_bss_end = ABSOLUTE(.);
_btdm_bss_start = ABSOLUTE(.);
*libbtdm_app.a:(.bss .bss.* COMMON)
. = ALIGN (4);
_btdm_bss_end = ABSOLUTE(.);
mapping[dram0_bss]
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.share.mem)
*(.gnu.linkonce.b.*)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
/* The heap starts right after end of this section */
_heap_start = ABSOLUTE(.);
} > dram0_0_seg
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
"DRAM segment data does not fit.")
.flash.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
mapping[flash_rodata]
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 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)
/* Addresses of memory regions reserved via
SOC_RESERVE_MEMORY_REGION() */
soc_reserved_memory_region_start = ABSOLUTE(.);
KEEP (*(.reserved_memory_address))
soc_reserved_memory_region_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
*(.tdata)
*(.tdata.*)
*(.tbss)
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(4);
} >drom0_0_seg
.flash.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
mapping[flash_text]
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is
resolved by addr2line in preference to the first symbol in
the flash.text segment.
*/
_flash_cache_start = ABSOLUTE(0);
} >iram0_2_seg
}

View file

@ -0,0 +1,89 @@
[sections:text]
entries:
.text+
.literal+
[sections:data]
entries:
.data+
[sections:bss]
entries:
.bss+
[sections:common]
entries:
COMMON
[sections:rodata]
entries:
.rodata+
[sections:rtc_text]
entries:
.rtc.text+
.rtc.literal
[sections:rtc_data]
entries:
.rtc.data+
[sections:rtc_rodata]
entries:
.rtc.rodata+
[sections:rtc_bss]
entries:
.rtc.bss
[sections:iram]
entries:
.iram1+
[sections:dram]
entries:
.dram1+
[sections:wifi_iram]
entries:
.wifi0iram+
[scheme:default]
entries:
text -> flash_text
rodata -> flash_rodata
data -> dram0_data
bss -> dram0_bss
common -> dram0_bss
iram -> iram0_text
dram -> dram0_data
rtc_text -> rtc_text
rtc_data -> rtc_data
rtc_rodata -> rtc_data
rtc_bss -> rtc_bss
wifi_iram -> flash_text
[scheme:rtc]
entries:
text -> rtc_text
data -> rtc_data
rodata -> rtc_data
bss -> rtc_bss
common -> rtc_bss
[scheme:noflash]
entries:
text -> iram0_text
rodata -> dram0_data
[scheme:noflash_data]
entries:
rodata -> dram0_data
[scheme:noflash_text]
entries:
text -> iram0_text
[scheme:wifi_iram]
entries:
wifi_iram -> iram0_text

View file

@ -200,7 +200,6 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
ESP_LOGW(TAG, "incorrect mac type"); ESP_LOGW(TAG, "incorrect mac type");
break; break;
} }
return ESP_OK; return ESP_OK;
} }
@ -366,4 +365,3 @@ void esp_chip_info(esp_chip_info_t* out_info)
out_info->features = CHIP_FEATURE_WIFI_BGN; out_info->features = CHIP_FEATURE_WIFI_BGN;
// FIXME: other features? // FIXME: other features?
}

View file

@ -8,8 +8,9 @@ set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_PRIV_INCLUDEDIRS "private_include") set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
set(COMPONENT_REQUIRES log tcpip_adapter) set(COMPONENT_REQUIRES log tcpip_adapter)
set(COMPONENT_PRIV_REQUIRES ethernet) if(CONFIG_IDF_TARGET_ESP32)
set(COMPONENT_REQUIRES log tcpip_adapter ethernet) set(COMPONENT_PRIV_REQUIRES ethernet)
endif()
set(COMPONENT_ADD_LDFRAGMENTS linker.lf) set(COMPONENT_ADD_LDFRAGMENTS linker.lf)

View file

@ -4,11 +4,17 @@ if(BOOTLOADER_BUILD)
set(COMPONENT_REQUIRES ${IDF_COMPONENTS}) set(COMPONENT_REQUIRES ${IDF_COMPONENTS})
set(COMPONENT_SRCS) set(COMPONENT_SRCS)
register_component() register_component()
set(scripts idf_build_get_property(target IDF_TARGET)
"esp32/ld/esp32.rom.ld" set(scripts "${target}/ld/${target}.rom.ld")
"esp32/ld/esp32.rom.newlib-funcs.ld" if(target STREQUAL "esp32")
"esp32/ld/esp32.rom.libgcc.ld" list(APPEND scripts
) "${target}/ld/${target}.rom.newlib-funcs.ld"
"${target}/ld/${target}.rom.libgcc.ld")
elseif(target STREQUAL "esp32s2beta")
list(APPEND scripts
"${target}/ld/${target}.rom.spiflash.ld"
"${target}/ld/${target}.rom.spiram_incompatible_fns.ld")
endif()
target_linker_script(${COMPONENT_LIB} "${scripts}") target_linker_script(${COMPONENT_LIB} "${scripts}")
else() else()
# Regular app build # Regular app build
@ -17,6 +23,7 @@ else()
register_component() register_component()
if (CONFIG_IDF_TARGET_ESP32)
set(scripts set(scripts
"esp32/ld/esp32.rom.ld" "esp32/ld/esp32.rom.ld"
"esp32/ld/esp32.rom.libgcc.ld" "esp32/ld/esp32.rom.libgcc.ld"
@ -40,4 +47,15 @@ else()
if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH) if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH)
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.spiflash.ld") target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.spiflash.ld")
endif() endif()
elseif(CONFIG_IDF_TARGET_ESP32S2BETA)
target_linker_script(${COMPONENT_LIB}
"esp32s2beta/ld/esp32s2beta.rom.ld"
"esp32s2beta/ld/esp32s2beta.rom.nanofmt.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiflash.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiram_incompatible_fns.ld"
"esp32s2beta/ld/esp32s2beta.spiram.rom-functions-dram.ld"
"esp32s2beta/ld/esp32s2beta.spiram.rom-functions-iram.ld")
endif()
endif() endif()

View file

@ -7,10 +7,14 @@ PROVIDE ( g_ticks_per_us_pro = g_ticks_per_us );
PROVIDE ( g_rom_flashchip = SPI_flashchip_data ); PROVIDE ( g_rom_flashchip = SPI_flashchip_data );
PROVIDE ( g_rom_spiflash_chip = SPI_flashchip_data ); PROVIDE ( g_rom_spiflash_chip = SPI_flashchip_data );
PROVIDE ( esp_rom_spiflash_config_param = SPIParamCfg ); PROVIDE ( esp_rom_spiflash_config_param = SPIParamCfg );
PROVIDE ( esp_rom_spiflash_read = SPIRead );
PROVIDE ( esp_rom_spiflash_read_status = SPI_read_status ); PROVIDE ( esp_rom_spiflash_read_status = SPI_read_status );
PROVIDE ( esp_rom_spiflash_read_statushigh = SPI_read_status_high ); PROVIDE ( esp_rom_spiflash_read_statushigh = SPI_read_status_high );
PROVIDE ( esp_rom_spiflash_read_user_cmd = SPI_user_command_read ); PROVIDE ( esp_rom_spiflash_read_user_cmd = SPI_user_command_read );
PROVIDE ( esp_rom_spiflash_write_encrypted_disable = SPI_Write_Encrypt_Disable); PROVIDE ( esp_rom_spiflash_write = SPIWrite );
PROVIDE ( esp_rom_spiflash_write_encrypted_disable = SPI_Write_Encrypt_Disable );
PROVIDE ( esp_rom_spiflash_write_encrypted_enable = SPI_Write_Encrypt_Enable ); PROVIDE ( esp_rom_spiflash_write_encrypted_enable = SPI_Write_Encrypt_Enable );
PROVIDE ( esp_rom_spiflash_config_clk = SPIClkConfig); PROVIDE ( esp_rom_spiflash_config_clk = SPIClkConfig );
PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO); PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO );
PROVIDE ( esp_rom_spiflash_unlock = SPIUnlock );
PROVIDE ( esp_rom_spiflash_erase_sector = SPIEraseSector );

View file

@ -15,6 +15,7 @@
#ifndef _ROM_CACHE_H_ #ifndef _ROM_CACHE_H_
#define _ROM_CACHE_H_ #define _ROM_CACHE_H_
#include "esp_bit_defs.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -17,7 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include "queue.h" #include "sys/queue.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -16,7 +16,6 @@
#define _ROM_RSA_PSS_H_ #define _ROM_RSA_PSS_H_
#include <stdint.h> #include <stdint.h>
#include "rom/rsa_pss.h"
#define ETS_SIG_LEN 384 /* Bytes */ #define ETS_SIG_LEN 384 /* Bytes */
#define ETS_DIGEST_LEN 32 /* SHA-256, bytes */ #define ETS_DIGEST_LEN 32 /* SHA-256, bytes */

View file

@ -16,7 +16,7 @@
#define _ROM_SECURE_BOOT_H_ #define _ROM_SECURE_BOOT_H_
#include <stdint.h> #include <stdint.h>
#include "rom/rsa_pss.h" #include "rsa_pss.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -24,7 +24,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "rom/ets_sys.h" #include "ets_sys.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -1,5 +1,3 @@
require_idf_targets(esp32)
set(COMPONENT_SRCS "emac_dev.c" set(COMPONENT_SRCS "emac_dev.c"
"emac_main.c" "emac_main.c"
"eth_phy/phy_common.c" "eth_phy/phy_common.c"

View file

@ -3,6 +3,7 @@ menu "FreeRTOS"
# This is actually also handled in the ESP32 startup code, not only in FreeRTOS. # This is actually also handled in the ESP32 startup code, not only in FreeRTOS.
config FREERTOS_UNICORE config FREERTOS_UNICORE
bool "Run FreeRTOS only on first core" bool "Run FreeRTOS only on first core"
default y if IDF_TARGET_ESP32S2BETA
default n default n
help help
This version of FreeRTOS normally takes control of all cores of This version of FreeRTOS normally takes control of all cores of
@ -13,6 +14,7 @@ menu "FreeRTOS"
# This invisible config value sets the value of tskNO_AFFINITY in task.h. # This invisible config value sets the value of tskNO_AFFINITY in task.h.
# Intended to be used as a constant from other Kconfig files. # Intended to be used as a constant from other Kconfig files.
# Value is (32-bit) INT_MAX. # Value is (32-bit) INT_MAX.
config FREERTOS_NO_AFFINITY config FREERTOS_NO_AFFINITY
hex hex
default 0x7FFFFFFF default 0x7FFFFFFF

View file

@ -126,8 +126,8 @@ if(CONFIG_LWIP_PPP_SUPPORT)
"lwip/src/netif/ppp/polarssl/sha1.c") "lwip/src/netif/ppp/polarssl/sha1.c")
endif() endif()
set(COMPONENT_REQUIRES vfs esp_wifi) set(COMPONENT_REQUIRES vfs esp_wifi ethernet)
set(COMPONENT_PRIV_REQUIRES ethernet tcpip_adapter nvs_flash) set(COMPONENT_PRIV_REQUIRES tcpip_adapter nvs_flash)
set(COMPONENT_ADD_LDFRAGMENTS linker.lf) set(COMPONENT_ADD_LDFRAGMENTS linker.lf)

View file

@ -9,16 +9,14 @@ if(EXISTS "${COMPONENT_DIR}/${soc_name}")
endif() endif()
list(APPEND COMPONENT_ADD_INCLUDEDIRS include) list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c" if(NOT BOOTLOADER_BUILD)
"src/lldesc.c" list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c"
"src/hal/spi_hal.c" "src/lldesc.c src/hal/spi_hal.c"
"src/hal/spi_hal_iram.c" "src/hal/spi_hal_iram.c"
"src/hal/spi_slave_hal.c" "src/soc_include_legacy_warn.c")
"src/hal/spi_slave_hal_iram.c"
"src/soc_include_legacy_warn.c"
)
set(COMPONENT_ADD_LDFRAGMENTS linker.lf) set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
endif()
set(COMPONENT_REQUIRES) set(COMPONENT_REQUIRES)

View file

@ -51,6 +51,13 @@ static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
asm volatile ("witlb %1, %0; isync\n" :: "r" (vpn), "r" (attr)); asm volatile ("witlb %1, %0; isync\n" :: "r" (vpn), "r" (attr));
} }
static inline void cpu_init_memctl()
{
#if XCHAL_ERRATUM_572
#error "Shouldn't have this errata or need this call on esp32s2beta"
#endif
}
/** /**
* @brief Configure memory region protection * @brief Configure memory region protection
* *

View file

@ -17,7 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_dport_access.h" #include "esp32s2beta/dport_access.h"
#include "soc.h" #include "soc.h"
#include "uart_reg.h" #include "uart_reg.h"
#include "xtensa/xtruntime.h" #include "xtensa/xtruntime.h"

View file

@ -0,0 +1,28 @@
// Copyright 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.
#ifndef _GPIO_PINS_H
#define _GPIO_PINS_H
#ifdef __cplusplus
extern "C"
{
#endif
#define GPIO_PIN_COUNT 48
#ifdef __cplusplus
}
#endif
#endif // _GPIO_PINS_H

View file

@ -279,6 +279,8 @@
#define SOC_IROM_HIGH 0x40c00000 #define SOC_IROM_HIGH 0x40c00000
#define SOC_IRAM_LOW 0x40020000 #define SOC_IRAM_LOW 0x40020000
#define SOC_IRAM_HIGH 0x40070000 #define SOC_IRAM_HIGH 0x40070000
#define SOC_DRAM_LOW 0x3FFD0000
#define SOC_DRAM_HIGH 0x3FF80000 // TODO: check RAM ranges
#define SOC_RTC_IRAM_LOW 0x40070000 #define SOC_RTC_IRAM_LOW 0x40070000
#define SOC_RTC_IRAM_HIGH 0x40072000 #define SOC_RTC_IRAM_HIGH 0x40072000
#define SOC_RTC_DRAM_LOW 0x3ff9e000 #define SOC_RTC_DRAM_LOW 0x3ff9e000

View file

@ -16,10 +16,10 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <assert.h> #include <assert.h>
#include "rom/ets_sys.h" #include "esp32s2beta/rom/ets_sys.h"
#include "rom/rtc.h" #include "esp32s2beta/rom/rtc.h"
#include "rom/uart.h" #include "esp32s2beta/rom/uart.h"
#include "rom/gpio.h" #include "esp32s2beta/rom/gpio.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h" #include "soc/rtc_io_reg.h"
@ -528,7 +528,6 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
/* may need equivalent function /* may need equivalent function
uint32_t apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); uint32_t apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD);
* if (apll_fpd) { * if (apll_fpd) {
* SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD); * SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
* } * }
@ -752,7 +751,6 @@ void rtc_clk_8m_divider_set(uint32_t div)
void rtc_clk_init(rtc_clk_config_t cfg) void rtc_clk_init(rtc_clk_config_t cfg)
{ {
rtc_cpu_freq_t cpu_source_before = rtc_clk_cpu_freq_get(); rtc_cpu_freq_t cpu_source_before = rtc_clk_cpu_freq_get();
/* If we get a TG WDT system reset while running at 240MHz, /* If we get a TG WDT system reset while running at 240MHz,
* DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz * DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz
* APB and CPU frequencies after reset. This will cause issues with XTAL * APB and CPU frequencies after reset. This will cause issues with XTAL

View file

@ -25,7 +25,7 @@
#include "soc/nrx_reg.h" #include "soc/nrx_reg.h"
#include "soc/fe_reg.h" #include "soc/fe_reg.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "rom/ets_sys.h" #include "esp32s2beta/rom/ets_sys.h"
#define MHZ (1000000) #define MHZ (1000000)

View file

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
#include <stdint.h> #include <stdint.h>
#include "rom/ets_sys.h" #include "esp32s2beta/rom/ets_sys.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h" #include "soc/timer_group_reg.h"
@ -68,7 +68,6 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
expected_freq = 150000; expected_freq = 150000;
} }
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
/* Start calibration */ /* Start calibration */
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);

View file

@ -1,4 +1,5 @@
set(SOC_SRCS "rtc_clk.c" set(SOC_SRCS "cpu_util.c"
"rtc_clk.c"
"rtc_init.c" "rtc_init.c"
"rtc_pm.c" "rtc_pm.c"
"rtc_sleep.c" "rtc_sleep.c"

View file

@ -164,7 +164,7 @@ inline static bool IRAM_ATTR esp_ptr_byte_accessible(const void *p)
bool r; bool r;
r = (ip >= SOC_BYTE_ACCESSIBLE_LOW && ip < SOC_BYTE_ACCESSIBLE_HIGH); r = (ip >= SOC_BYTE_ACCESSIBLE_LOW && ip < SOC_BYTE_ACCESSIBLE_HIGH);
#if CONFIG_ESP32_SPIRAM_SUPPORT && CONFIG_SPIRAM_SIZE #if CONFIG_ESP32_SPIRAM_SUPPORT && CONFIG_SPIRAM_SIZE
// ToDo: Use SOC_EXTRAM_DATA_HIGH if CONFIG_SPIRAM_SIZE is -1 (ie max possible SPIRAM size) // ToDo: Use SOC_EXTRAM_DATA_HIGH if CONFIG_SPIRAM_SIZE is -1 (ie max possible SPIRAM size)
r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE)); r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE));
#endif #endif
return r; return r;
@ -183,7 +183,7 @@ inline static bool IRAM_ATTR esp_ptr_external_ram(const void *p) {
} }
inline static bool IRAM_ATTR esp_ptr_in_iram(const void *p) { inline static bool IRAM_ATTR esp_ptr_in_iram(const void *p) {
#ifndef CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE || CONFIG_IDF_TARGET_ESP32S2BETA
return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH); return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH);
#else #else
return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH); return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH);

View file

@ -16,12 +16,14 @@
#include <stdint.h> #include <stdint.h>
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/periph_defs.h" #include "soc/periph_defs.h"
//include soc related (generated) definitions
#include "soc/spi_pins.h" #include "soc/spi_pins.h"
#include "soc/spi_reg.h" #include "soc/spi_reg.h"
#include "soc/spi_struct.h" #include "soc/spi_struct.h"
#include "soc/gpio_sig_map.h" #include "soc/gpio_sig_map.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "soc/spi_mem_struct.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"

View file

@ -1,9 +1,11 @@
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
# Bootloader needs SPIUnlock from this file, but doesn't if (CONFIG_IDF_TARGET_ESP32)
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
# need other parts of this component # need other parts of this component
set(COMPONENT_SRCS "spi_flash_rom_patch.c") set(COMPONENT_SRCS "spi_flash_rom_patch.c")
set(COMPONENT_PRIV_REQUIRES bootloader_support soc) set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
else() endif()
else() # not BOOTLOADER_BUILD
set(COMPONENT_SRCS "cache_utils.c" set(COMPONENT_SRCS "cache_utils.c"
"flash_mmap.c" "flash_mmap.c"
"flash_ops.c" "flash_ops.c"

View file

@ -1,4 +1,6 @@
set(COMPONENT_SRCS "eri.c" "trax.c") if(NOT BOOTLOADER_BUILD)
set(COMPONENT_SRCS "eri.c" "trax.c")
endif()
set(COMPONENT_ADD_INCLUDEDIRS "include" "${IDF_TARGET}/include") set(COMPONENT_ADD_INCLUDEDIRS "include" "${IDF_TARGET}/include")
@ -7,4 +9,6 @@ set(COMPONENT_PRIV_REQUIRES soc)
register_component() register_component()
target_link_libraries(${COMPONENT_LIB} "${CMAKE_CURRENT_SOURCE_DIR}/${IDF_TARGET}/libhal.a") if (NOT BOOTLOADER_BUILD)
target_link_libraries(${COMPONENT_LIB} "${CMAKE_CURRENT_SOURCE_DIR}/${IDF_TARGET}/libhal.a")
endif()

View file

@ -130,6 +130,9 @@ endfunction()
# Automatically adds a -L search path for the containing directory (if found), # Automatically adds a -L search path for the containing directory (if found),
# and then adds -T with the filename only. This allows INCLUDE directives to be # and then adds -T with the filename only. This allows INCLUDE directives to be
# used to include other linker scripts in the same directory. # used to include other linker scripts in the same directory.
#
# TODO: currently multiple linker scripts must be supplied as a single list for "scriptfiles"
# arg, cannot be supplied as list of args
function(target_linker_script target scriptfiles) function(target_linker_script target scriptfiles)
cmake_parse_arguments(_ "PROCESS" "" "" ${ARGN}) cmake_parse_arguments(_ "PROCESS" "" "" ${ARGN})
foreach(scriptfile ${scriptfiles}) foreach(scriptfile ${scriptfiles})