mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
make bootloader_support support esp32s2beta
This commit is contained in:
parent
b146104885
commit
61ce868396
@ -1,18 +1,8 @@
|
||||
set(COMPONENT_SRCS "bootloader_start.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS "")
|
||||
set(COMPONENT_REQUIRES bootloader bootloader_support)
|
||||
register_component()
|
||||
idf_component_register(SRCS "bootloader_start.c"
|
||||
REQUIRES bootloader bootloader_support)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "ld/${target}/bootloader.ld"
|
||||
"ld/${target}/bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB}
|
||||
"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})
|
||||
target_linker_script(${COMPONENT_LIB} "${scripts}")
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
static const char* TAG = "boot";
|
||||
static const char *TAG = "boot";
|
||||
|
||||
static int select_partition_number (bootloader_state_t *bs);
|
||||
static int selected_boot_partition(const bootloader_state_t *bs);
|
||||
@ -95,7 +95,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
return bootloader_utility_get_selected_boot_partition(bs);
|
||||
}
|
||||
#endif
|
||||
// TEST firmware.
|
||||
// TEST firmware.
|
||||
#ifdef CONFIG_BOOTLOADER_APP_TEST
|
||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
||||
ESP_LOGI(TAG, "Detect a boot condition of the test firmware");
|
||||
|
@ -5,10 +5,10 @@
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x4000d954 );
|
||||
|
||||
/* ToDo: Following address may need modification */
|
||||
PROVIDE ( MD5Final = 0x4005db1c );
|
||||
PROVIDE ( MD5Init = 0x4005da7c );
|
||||
PROVIDE ( MD5Update = 0x4005da9c );
|
||||
PROVIDE ( MD5Final = 0x400056e8 );
|
||||
PROVIDE ( MD5Init = 0x40005648 );
|
||||
PROVIDE ( MD5Update = 0x40005668 );
|
||||
/* bootloader will use following functions from xtensa hal library */
|
||||
xthal_get_ccount = 0x4000c050;
|
||||
xthal_get_ccompare = 0x4000c078;
|
||||
xthal_set_ccompare = 0x4000c058;
|
||||
xthal_get_ccount = 0x40015cbc;
|
||||
xthal_get_ccompare = 0x40015ce8;
|
||||
xthal_set_ccompare = 0x40015cc4;
|
||||
|
@ -15,7 +15,9 @@ if(BOOTLOADER_BUILD)
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.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)
|
||||
get_filename_component(secure_boot_verification_key
|
||||
|
@ -46,10 +46,10 @@ $(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(summary) CP $< $@
|
||||
cp $< $@
|
||||
endif
|
||||
endif #CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
|
||||
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
endif
|
||||
endif #CONFIG_SECURE_SIGNED_APPS
|
||||
|
@ -19,3 +19,7 @@
|
||||
* Called by bootloader, or by the app if the bootloader version is old (pre v2.1).
|
||||
*/
|
||||
void bootloader_clock_configure(void);
|
||||
|
||||
/** @brief Return the rated maximum frequency of this chip
|
||||
*/
|
||||
int bootloader_clock_get_rated_freq_mhz(void);
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
@ -125,7 +132,7 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition App partition description.
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/**
|
||||
* @file esp_partition.h
|
||||
@ -35,11 +36,17 @@
|
||||
*
|
||||
* @return true if flash encryption is enabled.
|
||||
*/
|
||||
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);
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
|
||||
{
|
||||
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 */
|
||||
bool enabled = false;
|
||||
while(flash_crypt_cnt) {
|
||||
while (flash_crypt_cnt) {
|
||||
if (flash_crypt_cnt & 1) {
|
||||
enabled = !enabled;
|
||||
}
|
||||
@ -110,7 +117,7 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
|
||||
* is enabled but secure boot is not used. This should protect against
|
||||
* serial re-flashing of an unauthorised code in absence of secure boot.
|
||||
*
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
void esp_flash_write_protect_crypt_cnt();
|
||||
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#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?
|
||||
*
|
||||
* Secure boot is enabled if the ABS_DONE_0 efuse is blown. This means
|
||||
* that the ROM bootloader code will only boot a verified secure
|
||||
* bootloader digest from now on.
|
||||
* This means that the ROM bootloader code will only boot
|
||||
* a verified secure bootloader from now on.
|
||||
*
|
||||
* @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;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return ets_efuse_secure_boot_enabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "bootloader_config.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_config.h"
|
||||
|
||||
/**
|
||||
* @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_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);
|
||||
|
@ -27,23 +27,30 @@ void bootloader_clock_configure()
|
||||
// and will be done with the bootloader much earlier than UART FIFO is empty.
|
||||
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
|
||||
* 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
|
||||
* 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);
|
||||
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) {
|
||||
cpu_freq_mhz = 240;
|
||||
}
|
||||
#endif
|
||||
|
||||
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.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.fast_freq = rtc_clk_fast_freq_get();
|
||||
rtc_clk_init(clk_cfg);
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* 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... */
|
||||
}
|
||||
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);
|
||||
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
|
||||
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)
|
||||
{
|
||||
if(mapping && map) {
|
||||
if (mapping && map) {
|
||||
spi_flash_munmap(map);
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_flash_write_encrypted(dest_addr, src, size);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return SPI_Encrypt_Write(dest_addr, src, size);
|
||||
#endif
|
||||
} else {
|
||||
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
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include <soc/dport_reg.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/spi_flash.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";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Use first 50 blocks in MMU for bootloader_mmap,
|
||||
50th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR 0x3f400000
|
||||
#define MMU_BLOCK50_VADDR 0x3f720000
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#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;
|
||||
|
||||
@ -103,25 +124,41 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
ESP_LOGE(TAG, "tried to bootloader_mmap twice");
|
||||
return NULL; /* can't map twice */
|
||||
}
|
||||
if (size > 0x320000) {
|
||||
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
|
||||
if (size > MMU_SIZE) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
|
||||
uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(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",
|
||||
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);
|
||||
#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) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
mapped = true;
|
||||
|
||||
@ -131,10 +168,17 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapped) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Full MMU reset */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(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;
|
||||
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)
|
||||
{
|
||||
switch(r) {
|
||||
switch (r) {
|
||||
case ESP_ROM_SPIFLASH_RESULT_OK:
|
||||
return ESP_OK;
|
||||
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)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(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);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
/* 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++) {
|
||||
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_ptr;
|
||||
if (map_at != current_read_mapping) {
|
||||
/* Move the 64KB mmu mapping window to fit map_at */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(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);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return ESP_FAIL;
|
||||
}
|
||||
current_read_mapping = map_at;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
map_ptr = (uint32_t *)(MMU_BLOCK63_VADDR + (word_src - map_at));
|
||||
#endif
|
||||
dest_words[word] = *map_ptr;
|
||||
}
|
||||
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 CONFIG_IDF_TARGET_ESP32
|
||||
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 {
|
||||
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@ -28,6 +29,19 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.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/cpu.h"
|
||||
@ -39,6 +53,11 @@
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/rtc_wdt.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 "esp_image_format.h"
|
||||
@ -48,6 +67,7 @@
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
@ -58,12 +78,13 @@ extern int _bss_end;
|
||||
extern int _data_start;
|
||||
extern int _data_end;
|
||||
|
||||
static const char* TAG = "boot";
|
||||
static const char *TAG = "boot";
|
||||
|
||||
static esp_err_t bootloader_main();
|
||||
static void print_flash_info(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 print_flash_info(const esp_image_header_t *pfhdr);
|
||||
static void update_flash_config(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 wdt_reset_check(void);
|
||||
|
||||
@ -79,8 +100,10 @@ esp_err_t bootloader_init()
|
||||
int *sp = get_sp();
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -89,14 +112,27 @@ esp_err_t bootloader_init()
|
||||
|
||||
/* completely reset MMU for both CPUs
|
||||
(in case serial bootloader was running) */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Read_Disable(1);
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
mmu_init(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
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
|
||||
usage, all that's absolutely needed is that we unmask DROM0
|
||||
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
|
||||
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);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
|
||||
if(bootloader_main() != ESP_OK){
|
||||
#endif
|
||||
#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_OK;
|
||||
@ -127,23 +171,25 @@ static esp_err_t bootloader_main()
|
||||
return ESP_FAIL;
|
||||
}
|
||||
flash_gpio_configure(&fhdr);
|
||||
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
||||
//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)) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
|
||||
|
||||
int rated_freq = bootloader_clock_get_rated_freq_mhz();
|
||||
if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
|
||||
rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_clock_configure();
|
||||
uart_console_configure();
|
||||
wdt_reset_check();
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
|
||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
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);
|
||||
rtc_wdt_protect_off();
|
||||
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_enable();
|
||||
rtc_wdt_protect_on();
|
||||
#else
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
/* disable watch dog here */
|
||||
rtc_wdt_disable();
|
||||
#endif
|
||||
@ -162,7 +208,7 @@ static esp_err_t bootloader_main()
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
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");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -183,38 +229,46 @@ static esp_err_t bootloader_main()
|
||||
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;
|
||||
switch(pfhdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
switch (pfhdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
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
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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)
|
||||
|
||||
@ -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_size %02x", phdr->spi_size );
|
||||
|
||||
const char* str;
|
||||
const char *str;
|
||||
switch ( phdr->spi_speed ) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
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,
|
||||
so test the SPI registers not the flash header */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
@ -260,6 +315,22 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
} else {
|
||||
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 );
|
||||
|
||||
switch ( phdr->spi_size ) {
|
||||
@ -286,58 +357,91 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
#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_CS_IO 11
|
||||
#define FLASH_SPIQ_IO 7
|
||||
#define FLASH_SPID_IO 8
|
||||
#define FLASH_SPIWP_IO 10
|
||||
#define FLASH_SPIHD_IO 9
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 1
|
||||
#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
|
||||
|
||||
/*
|
||||
* Bootloader reads SPI configuration from bin header, so that
|
||||
* 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 drv = 2;
|
||||
switch (pfhdr->spi_mode) {
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
default:
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
default:
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_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;
|
||||
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
|
||||
drv = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_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;
|
||||
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
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_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;
|
||||
#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,
|
||||
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;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_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;
|
||||
#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,
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
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);
|
||||
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;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// 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_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)
|
||||
@ -450,9 +557,16 @@ static void uart_console_configure(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.
|
||||
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);
|
||||
#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)
|
||||
@ -461,6 +575,7 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_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);
|
||||
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
@ -482,9 +598,25 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_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 &&
|
||||
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);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
@ -506,21 +638,31 @@ static void wdt_reset_check(void)
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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 ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
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 reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
wdt_reset_info_dump(1);
|
||||
#endif
|
||||
}
|
||||
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)
|
||||
{
|
||||
ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
|
||||
while(1) {}
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
void abort()
|
||||
@ -539,5 +681,5 @@ void abort()
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__ ("break 0,0");
|
||||
}
|
||||
while(1) {}
|
||||
while (1) {}
|
||||
}
|
||||
|
@ -47,14 +47,18 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
as-is, we repeatedly read the RNG register and XOR all
|
||||
values.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
random = REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, start);
|
||||
do {
|
||||
random ^= REG_READ(WDEV_RND_REG);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_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);
|
||||
#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_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);
|
||||
#endif
|
||||
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);
|
||||
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_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);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
@ -132,10 +140,16 @@ void bootloader_random_disable(void)
|
||||
|
||||
/* Restore SAR ADC mode */
|
||||
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
|
||||
| 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);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@ -28,6 +29,19 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.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/cpu.h"
|
||||
@ -49,24 +63,27 @@
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_utility.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 */
|
||||
#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
|
||||
|
||||
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 set_cache_and_start_app(uint32_t drom_addr,
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
|
||||
// Read ota_info partition and fill array from two otadata structures.
|
||||
static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_select_entry_t *two_otadata)
|
||||
@ -96,7 +113,7 @@ static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_selec
|
||||
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 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, "## 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];
|
||||
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
|
||||
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
|
||||
partition_usage = "unknown";
|
||||
|
||||
/* valid partition table */
|
||||
switch(partition->type) {
|
||||
switch (partition->type) {
|
||||
case PART_TYPE_APP: /* app partition */
|
||||
switch(partition->subtype) {
|
||||
switch (partition->subtype) {
|
||||
case PART_SUBTYPE_FACTORY: /* factory binary */
|
||||
bs->factory = partition->pos;
|
||||
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->app_count;
|
||||
partition_usage = "OTA app";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
partition_usage = "Unknown app";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break; /* PART_TYPE_APP */
|
||||
case PART_TYPE_DATA: /* data partition */
|
||||
switch(partition->subtype) {
|
||||
switch (partition->subtype) {
|
||||
case PART_SUBTYPE_DATA_OTA: /* ota data */
|
||||
bs->ota_info = partition->pos;
|
||||
partition_usage = "OTA data";
|
||||
@ -188,7 +204,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
|
||||
|
||||
bootloader_munmap(partitions);
|
||||
|
||||
ESP_LOGI(TAG,"End of partition table");
|
||||
ESP_LOGI(TAG, "End of partition table");
|
||||
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)
|
||||
{
|
||||
const char *not_bootable = " is not bootable"; /* save a few string literal bytes */
|
||||
switch(index) {
|
||||
switch (index) {
|
||||
case FACTORY_INDEX:
|
||||
ESP_LOGE(TAG, "Factory app partition%s", not_bootable);
|
||||
break;
|
||||
@ -317,8 +333,8 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=%d)", bs->app_count);
|
||||
if (bs->factory.offset != 0) {
|
||||
ESP_LOGI(TAG, "Defaulting to factory image");
|
||||
@ -328,7 +344,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
boot_index = 0;
|
||||
// Try to boot from ota_0.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
// Factory is not found and both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
ota_has_initial_contents = true;
|
||||
@ -341,7 +357,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
ESP_LOGI(TAG, "Secure version (from eFuse) = %d", esp_efuse_read_secure_version());
|
||||
// When CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK is enabled factory partition should not be in partition table, only two ota_app are there.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
ESP_LOGI(TAG, "otadata[0..1] in initial state");
|
||||
// both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
@ -426,7 +442,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
esp_partition_pos_t part;
|
||||
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)) {
|
||||
load_image(&image_data);
|
||||
} 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 */
|
||||
for(index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
for (index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
part = index_to_partition(bs, index);
|
||||
if (part.size == 0) {
|
||||
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 */
|
||||
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);
|
||||
if (part.size == 0) {
|
||||
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.
|
||||
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:
|
||||
@ -571,6 +587,7 @@ static void load_image(const esp_image_metadata_t* image_data)
|
||||
so issue a system reset to ensure flash encryption
|
||||
cache resets properly */
|
||||
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
|
||||
uart_tx_wait_idle(0);
|
||||
bootloader_reset();
|
||||
}
|
||||
#endif
|
||||
@ -582,7 +599,7 @@ static void load_image(const esp_image_metadata_t* 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_load_addr = 0;
|
||||
@ -618,12 +635,12 @@ static void unpack_load_app(const esp_image_metadata_t* data)
|
||||
|
||||
ESP_LOGD(TAG, "calling set_cache_and_start_app");
|
||||
set_cache_and_start_app(drom_addr,
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
}
|
||||
|
||||
static void set_cache_and_start_app(
|
||||
@ -637,8 +654,13 @@ static void set_cache_and_start_app(
|
||||
{
|
||||
int rc;
|
||||
ESP_LOGD(TAG, "configure drom and irom and start");
|
||||
Cache_Read_Disable( 0 );
|
||||
Cache_Flush( 0 );
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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,
|
||||
so the new app only has the mappings it creates.
|
||||
@ -650,33 +672,73 @@ static void set_cache_and_start_app(
|
||||
uint32_t drom_load_addr_aligned = drom_load_addr & MMU_FLASH_MASK;
|
||||
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",
|
||||
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);
|
||||
#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);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
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);
|
||||
|
||||
#endif
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
|
||||
(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_DRAM1 );
|
||||
|
||||
(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_DRAM1 );
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
|
||||
(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_DRAM1 );
|
||||
|
||||
Cache_Read_Enable( 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_DRAM1 );
|
||||
#endif
|
||||
#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)
|
||||
|
||||
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
|
||||
@ -688,7 +750,6 @@ static void set_cache_and_start_app(
|
||||
(*entry)();
|
||||
}
|
||||
|
||||
|
||||
void bootloader_reset(void)
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
74
components/bootloader_support/src/esp32/bootloader_esp32.c
Normal file
74
components/bootloader_support/src/esp32/bootloader_esp32.c
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -16,9 +16,10 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_periph.h"
|
||||
#include "esp32/rom/ets_sys.h" // TO REMOVE
|
||||
|
||||
static uint32_t words_hashed;
|
||||
|
||||
|
@ -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
|
||||
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);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
303
components/bootloader_support/src/esp32s2beta/flash_encrypt.c
Normal file
303
components/bootloader_support/src/esp32s2beta/flash_encrypt.c
Normal 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;
|
||||
}
|
45
components/bootloader_support/src/esp32s2beta/secure_boot.c
Normal file
45
components/bootloader_support/src/esp32s2beta/secure_boot.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -13,8 +13,6 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <bootloader_utility.h>
|
||||
#include <esp_secure_boot.h>
|
||||
@ -24,6 +22,14 @@
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.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:
|
||||
- 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);
|
||||
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_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);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
bool is_bootloader = (data->start_addr == ESP_BOOTLOADER_OFFSET);
|
||||
/* 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
|
||||
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
|
||||
// secure boot images have a signature appended
|
||||
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);
|
||||
}
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // is_bootloader
|
||||
} else {
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (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;
|
||||
if (should_load(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];
|
||||
}
|
||||
}
|
||||
@ -241,9 +253,9 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
// Success!
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
err:
|
||||
if (err == ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (sha_handle != NULL) {
|
||||
// Need to finish the hash process to free the handle
|
||||
@ -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",
|
||||
index, data_addr, load_addr,
|
||||
data_len, data_len,
|
||||
(do_load)?"load":(is_mapping)?"map":"");
|
||||
(do_load) ? "load" : (is_mapping) ? "map" : "");
|
||||
}
|
||||
|
||||
|
||||
@ -359,7 +371,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
|
||||
|
||||
if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
|
||||
load_addr, load_end)) {
|
||||
load_addr, load_end)) {
|
||||
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
|
||||
index, load_addr, load_end, loader_iram_start, loader_iram_end);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
@ -370,10 +382,10 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
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;
|
||||
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);
|
||||
if (err != ESP_OK) {
|
||||
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)
|
||||
{
|
||||
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",
|
||||
data_addr, data_len);
|
||||
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;
|
||||
|
||||
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];
|
||||
*checksum ^= w;
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@ -443,7 +455,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent)
|
||||
{
|
||||
if ((segment->data_len & 3) != 0
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "invalid segment length 0x%x", segment->data_len);
|
||||
}
|
||||
@ -459,7 +471,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
ESP_LOGV(TAG, "segment %d map_segment %d segment_data_offs 0x%x load_addr 0x%x",
|
||||
index, map_segment, segment_data_offs, load_addr);
|
||||
if (map_segment
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "Segment %d load address 0x%08x, doesn't match data 0x%08x",
|
||||
index, load_addr, segment_data_offs);
|
||||
@ -473,7 +485,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
static bool should_map(uint32_t load_addr)
|
||||
{
|
||||
return (load_addr >= SOC_IROM_LOW && load_addr < SOC_IROM_HIGH)
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
}
|
||||
|
||||
static bool should_load(uint32_t load_addr)
|
||||
@ -532,8 +544,8 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
|
||||
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
|
||||
};
|
||||
return esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&bootloader_part,
|
||||
data);
|
||||
&bootloader_part,
|
||||
data);
|
||||
}
|
||||
|
||||
|
||||
@ -548,9 +560,9 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
esp_err_t err = bootloader_flash_read(data->start_addr + unpadded_length, buf, length - unpadded_length, true);
|
||||
uint8_t calc = buf[length - unpadded_length - 1];
|
||||
uint8_t checksum = (checksum_word >> 24)
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
if (err != ESP_OK || checksum != calc) {
|
||||
ESP_LOGE(TAG, "Checksum failed. Calculated 0x%x read 0x%x", checksum, calc);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
@ -568,26 +580,36 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
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)
|
||||
{
|
||||
uint8_t image_hash[HASH_LEN] = { 0 };
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
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_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);
|
||||
|
||||
// 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
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
// 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
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (memcmp(hash, image_hash, HASH_LEN) != 0) {
|
||||
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);
|
||||
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);
|
||||
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
|
||||
}
|
||||
|
@ -16,14 +16,28 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.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/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* SPI flash controller */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SPIFLASH SPI1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
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 void (*write_status_fn_t)(unsigned);
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
const char *manufacturer;
|
||||
uint8_t mfg_id; /* 8-bit JEDEC manufacturer 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.
|
||||
*/
|
||||
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 },
|
||||
{ "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 },
|
||||
@ -109,8 +124,8 @@ const static qio_info_t chip_data[] = {
|
||||
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
|
||||
/* Generic function to use the "user command" SPI controller functionality
|
||||
to send commands to the SPI flash and read the respopnse.
|
||||
@ -128,6 +143,46 @@ uint32_t bootloader_read_flash_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)
|
||||
{
|
||||
uint32_t raw_flash_id;
|
||||
@ -145,7 +200,7 @@ void bootloader_enable_qio_mode(void)
|
||||
flash_id = raw_flash_id & 0xFFFF;
|
||||
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
|
||||
|
||||
for (i = 0; i < NUM_CHIPS-1; i++) {
|
||||
for (i = 0; i < NUM_CHIPS - 1; 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)) {
|
||||
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
|
||||
@ -156,19 +211,22 @@ void bootloader_enable_qio_mode(void)
|
||||
if (i == NUM_CHIPS - 1) {
|
||||
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,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
}
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
{
|
||||
uint32_t status;
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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,
|
||||
// which is compiled into the bootloader instead.
|
||||
@ -178,27 +236,28 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
//assignment from that chip's WP pin.
|
||||
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
if (CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO &&
|
||||
(pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
|
||||
(pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
|
||||
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);
|
||||
|
||||
status = read_status_fn();
|
||||
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);
|
||||
write_status_fn(status | (1<<status_qio_bit));
|
||||
write_status_fn(status | (1 << status_qio_bit));
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
|
||||
status = read_status_fn();
|
||||
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");
|
||||
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);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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
|
||||
#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_addr = 0;
|
||||
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.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
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;
|
||||
|
||||
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;
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
|
@ -1,5 +1,10 @@
|
||||
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}")
|
||||
include(${COMPONENT_DIR}/${soc_name}/sources.cmake)
|
||||
spaces2list(EFUSE_SOC_SRCS)
|
||||
@ -7,6 +12,7 @@ if(EXISTS "${COMPONENT_DIR}/${soc_name}")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS include ${soc_name}/include)
|
||||
endif()
|
||||
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
|
||||
list(APPEND COMPONENT_SRCS "src/esp_efuse_api.c"
|
||||
"src/esp_efuse_fields.c"
|
||||
"src/esp_efuse_utility.c")
|
||||
|
@ -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
|
||||
set(COMPONENT_ADD_INCLUDEDIRS include)
|
||||
register_component()
|
||||
target_linker_script(${COMPONENT_LIB} "ld/esp32.peripherals.ld")
|
||||
else()
|
||||
elseif(CONFIG_IDF_TARGET_ESP32)
|
||||
# Regular app build
|
||||
|
||||
set(COMPONENT_SRCS "brownout.c"
|
||||
|
@ -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_SRCS )
|
||||
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)
|
||||
# Regular app build
|
||||
|
||||
|
@ -116,7 +116,6 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
int cpu_id = xPortGetCoreID();
|
||||
|
||||
if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
|
||||
|| dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
|
||||
return;
|
||||
|
@ -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.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Ints can't be both shared and non-shared.
|
||||
assert(!((vd->flags&VECDESC_FL_SHARED)&&(vd->flags&VECDESC_FL_NONSHARED)));
|
||||
//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");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
memset(&empty_vect_desc, 0, sizeof(vector_desc_t));
|
||||
|
||||
|
||||
//Level defaults to any low/med interrupt
|
||||
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",
|
||||
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));
|
||||
|
||||
if ( !is_vect_desc_usable(vd, flags, cpu, force) ) continue;
|
||||
|
||||
if (flags&ESP_INTR_FLAG_SHARED) {
|
||||
//We're allocating a shared int.
|
||||
|
||||
//See if int already is used as a shared interrupt.
|
||||
if (vd->flags&VECDESC_FL_SHARED) {
|
||||
//We can use this already-marked-as-shared interrupt. Count the already attached isrs in order to see
|
||||
|
332
components/esp32s2beta/ld/esp32s2beta.project.ld.in
Normal file
332
components/esp32s2beta/ld/esp32s2beta.project.ld.in
Normal 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
|
||||
}
|
89
components/esp32s2beta/ld/esp32s2beta_fragments.lf
Normal file
89
components/esp32s2beta/ld/esp32s2beta_fragments.lf
Normal 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
|
@ -200,7 +200,6 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
|
||||
ESP_LOGW(TAG, "incorrect mac type");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -366,4 +365,3 @@ void esp_chip_info(esp_chip_info_t* out_info)
|
||||
out_info->features = CHIP_FEATURE_WIFI_BGN;
|
||||
|
||||
// FIXME: other features?
|
||||
}
|
||||
|
@ -8,8 +8,9 @@ set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||
set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
|
||||
|
||||
set(COMPONENT_REQUIRES log tcpip_adapter)
|
||||
set(COMPONENT_PRIV_REQUIRES ethernet)
|
||||
set(COMPONENT_REQUIRES log tcpip_adapter ethernet)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
set(COMPONENT_PRIV_REQUIRES ethernet)
|
||||
endif()
|
||||
|
||||
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
||||
|
||||
|
@ -4,11 +4,17 @@ if(BOOTLOADER_BUILD)
|
||||
set(COMPONENT_REQUIRES ${IDF_COMPONENTS})
|
||||
set(COMPONENT_SRCS)
|
||||
register_component()
|
||||
set(scripts
|
||||
"esp32/ld/esp32.rom.ld"
|
||||
"esp32/ld/esp32.rom.newlib-funcs.ld"
|
||||
"esp32/ld/esp32.rom.libgcc.ld"
|
||||
)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "${target}/ld/${target}.rom.ld")
|
||||
if(target STREQUAL "esp32")
|
||||
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}")
|
||||
else()
|
||||
# Regular app build
|
||||
@ -17,27 +23,39 @@ else()
|
||||
|
||||
register_component()
|
||||
|
||||
set(scripts
|
||||
"esp32/ld/esp32.rom.ld"
|
||||
"esp32/ld/esp32.rom.libgcc.ld"
|
||||
"esp32/ld/esp32.rom.syscalls.ld"
|
||||
"esp32/ld/esp32.rom.newlib-data.ld"
|
||||
)
|
||||
target_linker_script(${COMPONENT_LIB} "${scripts}")
|
||||
if (CONFIG_IDF_TARGET_ESP32)
|
||||
set(scripts
|
||||
"esp32/ld/esp32.rom.ld"
|
||||
"esp32/ld/esp32.rom.libgcc.ld"
|
||||
"esp32/ld/esp32.rom.syscalls.ld"
|
||||
"esp32/ld/esp32.rom.newlib-data.ld"
|
||||
)
|
||||
target_linker_script(${COMPONENT_LIB} "${scripts}")
|
||||
|
||||
if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-funcs.ld")
|
||||
if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-funcs.ld")
|
||||
endif()
|
||||
|
||||
if(CONFIG_NEWLIB_NANO_FORMAT)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-nano.ld")
|
||||
endif()
|
||||
|
||||
if(NOT GCC_NOT_5_2_0)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-locale.ld")
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.spiflash.ld")
|
||||
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()
|
||||
|
||||
if(CONFIG_NEWLIB_NANO_FORMAT)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-nano.ld")
|
||||
endif()
|
||||
|
||||
if(NOT GCC_NOT_5_2_0)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-locale.ld")
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH)
|
||||
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.spiflash.ld")
|
||||
endif()
|
||||
endif()
|
||||
|
@ -7,10 +7,14 @@ PROVIDE ( g_ticks_per_us_pro = g_ticks_per_us );
|
||||
PROVIDE ( g_rom_flashchip = SPI_flashchip_data );
|
||||
PROVIDE ( g_rom_spiflash_chip = SPI_flashchip_data );
|
||||
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_statushigh = SPI_read_status_high );
|
||||
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_config_clk = SPIClkConfig);
|
||||
PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO);
|
||||
PROVIDE ( esp_rom_spiflash_config_clk = SPIClkConfig );
|
||||
PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO );
|
||||
PROVIDE ( esp_rom_spiflash_unlock = SPIUnlock );
|
||||
PROVIDE ( esp_rom_spiflash_erase_sector = SPIEraseSector );
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef _ROM_CACHE_H_
|
||||
#define _ROM_CACHE_H_
|
||||
|
||||
#include "esp_bit_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "sys/queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -53,8 +53,8 @@ extern "C" {
|
||||
#endif /* !ESP_MAC_5 */
|
||||
/*
|
||||
* SLC2 DMA Desc struct, aka lldesc_t
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* | own | EoF | sub_sof | 5'b0 | length [11:0] | size [11:0] |
|
||||
* --------------------------------------------------------------
|
||||
* | buf_ptr [31:0] |
|
||||
@ -139,12 +139,12 @@ static inline uint32_t lldesc_get_chain_length(lldesc_t *head)
|
||||
{
|
||||
lldesc_t *ds = head;
|
||||
uint32_t len = 0;
|
||||
|
||||
|
||||
while (ds) {
|
||||
len += ds->length;
|
||||
ds = STAILQ_NEXT(ds, qe);
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#define _ROM_RSA_PSS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rom/rsa_pss.h"
|
||||
|
||||
#define ETS_SIG_LEN 384 /* Bytes */
|
||||
#define ETS_DIGEST_LEN 32 /* SHA-256, bytes */
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define _ROM_SECURE_BOOT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rom/rsa_pss.h"
|
||||
#include "rsa_pss.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "rom/ets_sys.h"
|
||||
#include "ets_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -1,5 +1,3 @@
|
||||
require_idf_targets(esp32)
|
||||
|
||||
set(COMPONENT_SRCS "emac_dev.c"
|
||||
"emac_main.c"
|
||||
"eth_phy/phy_common.c"
|
||||
|
@ -3,6 +3,7 @@ menu "FreeRTOS"
|
||||
# This is actually also handled in the ESP32 startup code, not only in FreeRTOS.
|
||||
config FREERTOS_UNICORE
|
||||
bool "Run FreeRTOS only on first core"
|
||||
default y if IDF_TARGET_ESP32S2BETA
|
||||
default n
|
||||
help
|
||||
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.
|
||||
# Intended to be used as a constant from other Kconfig files.
|
||||
# Value is (32-bit) INT_MAX.
|
||||
|
||||
config FREERTOS_NO_AFFINITY
|
||||
hex
|
||||
default 0x7FFFFFFF
|
||||
|
@ -126,8 +126,8 @@ if(CONFIG_LWIP_PPP_SUPPORT)
|
||||
"lwip/src/netif/ppp/polarssl/sha1.c")
|
||||
endif()
|
||||
|
||||
set(COMPONENT_REQUIRES vfs esp_wifi)
|
||||
set(COMPONENT_PRIV_REQUIRES ethernet tcpip_adapter nvs_flash)
|
||||
set(COMPONENT_REQUIRES vfs esp_wifi ethernet)
|
||||
set(COMPONENT_PRIV_REQUIRES tcpip_adapter nvs_flash)
|
||||
|
||||
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
||||
|
||||
|
@ -9,16 +9,14 @@ if(EXISTS "${COMPONENT_DIR}/${soc_name}")
|
||||
endif()
|
||||
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
|
||||
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c"
|
||||
"src/lldesc.c"
|
||||
"src/hal/spi_hal.c"
|
||||
"src/hal/spi_hal_iram.c"
|
||||
"src/hal/spi_slave_hal.c"
|
||||
"src/hal/spi_slave_hal_iram.c"
|
||||
"src/soc_include_legacy_warn.c"
|
||||
)
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c"
|
||||
"src/lldesc.c src/hal/spi_hal.c"
|
||||
"src/hal/spi_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)
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_dport_access.h"
|
||||
#include "esp32s2beta/dport_access.h"
|
||||
#include "soc.h"
|
||||
#include "uart_reg.h"
|
||||
#include "xtensa/xtruntime.h"
|
||||
|
28
components/soc/esp32s2beta/include/soc/gpio_pins.h
Normal file
28
components/soc/esp32s2beta/include/soc/gpio_pins.h
Normal 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
|
@ -279,6 +279,8 @@
|
||||
#define SOC_IROM_HIGH 0x40c00000
|
||||
#define SOC_IRAM_LOW 0x40020000
|
||||
#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_HIGH 0x40072000
|
||||
#define SOC_RTC_DRAM_LOW 0x3ff9e000
|
||||
|
@ -16,10 +16,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
@ -201,8 +201,8 @@ void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT);
|
||||
}
|
||||
/* d256 should be independent configured with 8M
|
||||
* Maybe we can split this function into 8m and dmd256
|
||||
/* d256 should be independent configured with 8M
|
||||
* Maybe we can split this function into 8m and dmd256
|
||||
*/
|
||||
if (d256_en) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
|
||||
@ -226,7 +226,7 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1);
|
||||
REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0);
|
||||
|
||||
/* BIAS I2C not exist any more, but not sure how to get the same effect yet...
|
||||
/* BIAS I2C not exist any more, but not sure how to get the same effect yet...
|
||||
* if (!enable &&
|
||||
* REG_GET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_SOC_CLK_SEL) != SYSCON_SOC_CLK_SEL_PLL) {
|
||||
* REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
|
||||
@ -236,7 +236,7 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm
|
||||
*/
|
||||
|
||||
if (enable) {
|
||||
/* no need to differentiate ECO chip any more
|
||||
/* no need to differentiate ECO chip any more
|
||||
uint8_t sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV1;
|
||||
uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
|
||||
if (is_rev0) {
|
||||
@ -427,7 +427,7 @@ void rtc_clk_bbpll_set(rtc_xtal_freq_t xtal_freq, rtc_pll_t pll_freq)
|
||||
ets_delay_us(1);
|
||||
}
|
||||
*/
|
||||
ets_delay_us(50000);
|
||||
ets_delay_us(50000);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -458,9 +458,9 @@ static void rtc_clk_cpu_freq_to_pll(rtc_cpu_freq_t cpu_freq)
|
||||
{
|
||||
int freq = 0;
|
||||
if ((s_cur_pll == RTC_PLL_NONE) || ((s_cur_pll == RTC_PLL_320M) && (cpu_freq == RTC_CPU_FREQ_240M))) {
|
||||
/*
|
||||
/*
|
||||
* if switch from non-pll or switch from PLL 320M to 480M
|
||||
* need to switch PLLs, fall back to full implementation
|
||||
* need to switch PLLs, fall back to full implementation
|
||||
*/
|
||||
rtc_clk_cpu_freq_set(cpu_freq);
|
||||
return;
|
||||
@ -528,7 +528,6 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
|
||||
/* may need equivalent function
|
||||
uint32_t apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD);
|
||||
|
||||
|
||||
* if (apll_fpd) {
|
||||
* SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
|
||||
* }
|
||||
@ -556,16 +555,16 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
|
||||
rtc_clk_bbpll_set(xtal_freq, RTC_PLL_480M);
|
||||
s_cur_pll = RTC_PLL_480M;
|
||||
}
|
||||
|
||||
|
||||
if ((cpu_freq == RTC_CPU_FREQ_80M) || (cpu_freq == RTC_CPU_320M_80M)) {
|
||||
DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
|
||||
ets_update_cpu_frequency(80);
|
||||
ets_update_cpu_frequency(80);
|
||||
} else if ((cpu_freq == RTC_CPU_FREQ_160M) || (cpu_freq == RTC_CPU_320M_160M)) {
|
||||
DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 1);
|
||||
ets_update_cpu_frequency(160);
|
||||
} else if (cpu_freq == RTC_CPU_FREQ_240M) {
|
||||
DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 2);
|
||||
ets_update_cpu_frequency(240);
|
||||
ets_update_cpu_frequency(240);
|
||||
}
|
||||
REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_SOC_CLK_SEL, SYSCON_SOC_CLK_SEL_PLL);
|
||||
//rtc_clk_wait_for_slow_cycle();
|
||||
@ -752,7 +751,6 @@ void rtc_clk_8m_divider_set(uint32_t div)
|
||||
void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
{
|
||||
rtc_cpu_freq_t cpu_source_before = rtc_clk_cpu_freq_get();
|
||||
|
||||
/* If we get a TG WDT system reset while running at 240MHz,
|
||||
* DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz
|
||||
* APB and CPU frequencies after reset. This will cause issues with XTAL
|
||||
@ -816,8 +814,8 @@ void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
rtc_clk_apb_freq_update(xtal_freq * MHZ);
|
||||
/* Set CPU frequency */
|
||||
rtc_clk_cpu_freq_set(cfg.cpu_freq);
|
||||
|
||||
/* Re-calculate the ccount to make time calculation correct. */
|
||||
|
||||
/* Re-calculate the ccount to make time calculation correct. */
|
||||
uint32_t freq_before = rtc_clk_cpu_freq_value(cpu_source_before) / MHZ;
|
||||
uint32_t freq_after = rtc_clk_cpu_freq_value(cfg.cpu_freq) / MHZ;
|
||||
XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * freq_after / freq_before );
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "soc/nrx_reg.h"
|
||||
#include "soc/fe_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
@ -55,7 +55,7 @@ void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
{
|
||||
/* Already defined in rtc init
|
||||
/* Already defined in rtc init
|
||||
// set 5 PWC state machine times to fit in main state machine time
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_SLP);
|
||||
@ -68,7 +68,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
rtc_sleep_pd(pd_cfg);
|
||||
}
|
||||
|
||||
/* This option seems to be unneccessary
|
||||
/* This option seems to be unneccessary
|
||||
if (cfg.rtc_mem_inf_fpu) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
|
||||
} else {
|
||||
@ -120,10 +120,10 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
/* redundant ? People may not want to touch such registers after init
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG,
|
||||
RTC_CNTL_DG_PAD_FORCE_ISO | RTC_CNTL_DG_PAD_FORCE_NOISO);
|
||||
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG,
|
||||
RTC_CNTL_DG_WRAP_FORCE_PU | RTC_CNTL_DG_WRAP_FORCE_PD);
|
||||
|
||||
|
||||
#ifdef CONFIG_CHIP_IS_ESP32
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP);
|
||||
#endif
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_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;
|
||||
}
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
|
||||
/* Start calibration */
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
@ -1,4 +1,5 @@
|
||||
set(SOC_SRCS "rtc_clk.c"
|
||||
set(SOC_SRCS "cpu_util.c"
|
||||
"rtc_clk.c"
|
||||
"rtc_init.c"
|
||||
"rtc_pm.c"
|
||||
"rtc_sleep.c"
|
||||
|
@ -164,7 +164,7 @@ inline static bool IRAM_ATTR esp_ptr_byte_accessible(const void *p)
|
||||
bool r;
|
||||
r = (ip >= SOC_BYTE_ACCESSIBLE_LOW && ip < SOC_BYTE_ACCESSIBLE_HIGH);
|
||||
#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));
|
||||
#endif
|
||||
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) {
|
||||
#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);
|
||||
#else
|
||||
return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH);
|
||||
|
@ -16,12 +16,14 @@
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
//include soc related (generated) definitions
|
||||
#include "soc/spi_pins.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -1,9 +1,11 @@
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Bootloader needs SPIUnlock from this file, but doesn't
|
||||
# need other parts of this component
|
||||
set(COMPONENT_SRCS "spi_flash_rom_patch.c")
|
||||
set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
|
||||
else()
|
||||
if (CONFIG_IDF_TARGET_ESP32)
|
||||
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
|
||||
# need other parts of this component
|
||||
set(COMPONENT_SRCS "spi_flash_rom_patch.c")
|
||||
set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
|
||||
endif()
|
||||
else() # not BOOTLOADER_BUILD
|
||||
set(COMPONENT_SRCS "cache_utils.c"
|
||||
"flash_mmap.c"
|
||||
"flash_ops.c"
|
||||
|
@ -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")
|
||||
|
||||
@ -7,4 +9,6 @@ set(COMPONENT_PRIV_REQUIRES soc)
|
||||
|
||||
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()
|
||||
|
@ -130,6 +130,9 @@ endfunction()
|
||||
# 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
|
||||
# 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)
|
||||
cmake_parse_arguments(_ "PROCESS" "" "" ${ARGN})
|
||||
foreach(scriptfile ${scriptfiles})
|
||||
|
Loading…
x
Reference in New Issue
Block a user