Merge branch 'master' into feature/esp32s2beta_update

This commit is contained in:
Angus Gratton
2019-08-08 13:44:24 +10:00
committed by Angus Gratton
2414 changed files with 160787 additions and 45783 deletions

View File

@@ -28,6 +28,11 @@ static const char *TAG = "bootloader_mmap";
static spi_flash_mmap_handle_t map;
uint32_t bootloader_mmap_get_free_pages()
{
return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
}
const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{
if (map) {
@@ -104,6 +109,7 @@ static const char *TAG = "bootloader_flash";
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_SIZE (0x320000)
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
#elif CONFIG_IDF_TARGET_ESP32S2BETA
/* Use first 63 blocks in MMU for bootloader_mmap,
63th block for bootloader_flash_read
@@ -111,13 +117,25 @@ static const char *TAG = "bootloader_flash";
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_SIZE (0x3f0000)
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
#endif
#define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
static bool mapped;
// Current bootloader mapping (ab)used for bootloader_read()
static uint32_t current_read_mapping = UINT32_MAX;
uint32_t bootloader_mmap_get_free_pages()
{
/**
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
* Since, bootloader_mmap function below assumes it to be 0x320000 (50 pages), we can safely do this.
*/
return MMU_FREE_PAGES;
}
const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{
if (mapped) {
@@ -235,9 +253,9 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
#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);
int e = cache_flash_mmu_set(0, 0, FLASH_READ_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);
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, FLASH_READ_VADDR, map_at, 64, 1, 0);
#endif
if (e != 0) {
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
@@ -255,11 +273,7 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
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
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
dest_words[word] = *map_ptr;
}
return ESP_OK;

View File

@@ -70,6 +70,7 @@
#include "bootloader_common.h"
#include "bootloader_clock.h"
#include "bootloader_common.h"
#include "bootloader_flash_config.h"
#include "flash_qio_mode.h"
@@ -83,7 +84,7 @@ 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 bootloader_init_flash_configure(const esp_image_header_t* pfhdr);
static void uart_console_configure(void);
static void wdt_reset_check(void);
@@ -169,7 +170,7 @@ static esp_err_t bootloader_main()
ESP_LOGE(TAG, "failed to load bootloader header!");
return ESP_FAIL;
}
flash_gpio_configure(&fhdr);
bootloader_init_flash_configure(&fhdr);
#ifdef CONFIG_IDF_TARGET_ESP32
int rated_freq = bootloader_clock_get_rated_freq_mhz();
@@ -358,134 +359,11 @@ static void print_flash_info(const esp_image_header_t *phdr)
#endif
}
#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 bootloader_init_flash_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;
}
/* 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;
#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;
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
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
}
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
bootloader_configure_spi_pins(drv);
#endif
bootloader_flash_gpio_config(pfhdr);
bootloader_flash_dummy_config(pfhdr);
bootloader_flash_cs_timing_config();
}
static void uart_console_configure(void)

View File

@@ -0,0 +1,165 @@
// 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.
#include <stdbool.h>
#include <assert.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/efuse.h"
#include "soc/gpio_periph.h"
#include "soc/efuse_reg.h"
#include "soc/spi_reg.h"
#include "soc/spi_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
void bootloader_flash_update_id()
{
g_rom_flashchip.device_id = bootloader_read_flash_id();
}
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
{
uint32_t spi_clk_div = 0;
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
spi_clk_div = 1;
break;
case ESP_IMAGE_SPI_SPEED_40M:
spi_clk_div = 2;
break;
case ESP_IMAGE_SPI_SPEED_26M:
spi_clk_div = 3;
break;
case ESP_IMAGE_SPI_SPEED_20M:
spi_clk_div = 4;
break;
default:
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
}
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
{
uint32_t drv = 2;
if (pfhdr->spi_speed == ESP_IMAGE_SPI_SPEED_80M) {
drv = 3;
}
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(SPI_IOMUX_PIN_NUM_CS, SPICS0_OUT_IDX, 0, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_MISO, SPIQ_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_MISO, SPIQ_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_MOSI, SPID_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_MOSI, SPID_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_WP, SPIWP_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_WP, SPIWP_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_HD, SPIHD_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_HD, 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);
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);
}
}
}
}
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
{
int spi_cache_dummy = 0;
uint32_t modebit = READ_PERI_REG(SPI_CTRL_REG(0));
if (modebit & SPI_FASTRD_MODE) {
if (modebit & SPI_FREAD_QIO) { //SPI mode is QIO
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
} else if (modebit & SPI_FREAD_DIO) { //SPI mode is DIO
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
} else if(modebit & (SPI_FREAD_QUAD | SPI_FREAD_DUAL)) { //SPI mode is QOUT or DIO
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
}
}
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] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
break;
case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
break;
case ESP_IMAGE_SPI_SPEED_26M:
case ESP_IMAGE_SPI_SPEED_20M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
break;
default:
break;
}
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + g_rom_spiflash_dummy_len_plus[0],
SPI_USR_DUMMY_CYCLELEN_S);
}

View File

@@ -27,6 +27,12 @@
#include "esp32/rom/cache.h"
#include "esp32/rom/spi_flash.h" /* TODO: Remove this */
/* This file implements FLASH ENCRYPTION related APIs to perform
* various operations such as programming necessary flash encryption
* eFuses, detect whether flash encryption is enabled (by reading eFuse)
* and if required encrypt the partitions in flash memory
*/
static const char *TAG = "flash_encrypt";
/* Static functions for stages of flash encryption */
@@ -203,7 +209,13 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
/* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == EFUSE_RD_FLASH_CRYPT_CNT (0x7F) */
uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt);
REG_SET_FIELD(EFUSE_BLK0_WDATA0_REG, EFUSE_FLASH_CRYPT_CNT, new_flash_crypt_cnt);
uint32_t wdata0_reg = ((new_flash_crypt_cnt & EFUSE_FLASH_CRYPT_CNT) << EFUSE_FLASH_CRYPT_CNT_S);
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
ESP_LOGI(TAG, "Write protecting FLASH_CRYPT_CNT eFuse");
wdata0_reg |= EFUSE_WR_DIS_FLASH_CRYPT_CNT;
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, wdata0_reg);
esp_efuse_burn_new_values();
ESP_LOGI(TAG, "Flash encryption completed");
@@ -337,14 +349,4 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
flash_failed:
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
return err;
}
void esp_flash_write_protect_crypt_cnt()
{
uint32_t efuse_blk0 = REG_READ(EFUSE_BLK0_RDATA0_REG);
bool flash_crypt_wr_dis = efuse_blk0 & EFUSE_WR_DIS_FLASH_CRYPT_CNT;
if(!flash_crypt_wr_dis) {
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_FLASH_CRYPT_CNT);
esp_efuse_burn_new_values();
}
}
}

View File

@@ -21,7 +21,7 @@
#include "esp32/rom/sha.h"
#include "uECC.h"
typedef SHA_CTX sha_context;
#include <sys/param.h>
static const char *TAG = "secure_boot";
@@ -32,6 +32,9 @@ extern const uint8_t signature_verification_key_end[] asm("_binary_signature_ver
#define DIGEST_LEN 32
/* Mmap source address mask */
#define MMAP_ALIGNED_MASK 0x0000FFFF
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
@@ -40,21 +43,44 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
bootloader_sha256_handle_t handle = bootloader_sha256_start();
uint32_t free_page_count = bootloader_mmap_get_free_pages();
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
int32_t data_len_remain = length;
uint32_t data_addr = src_addr;
while (data_len_remain > 0) {
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
data = (const uint8_t *) bootloader_mmap(data_addr, data_len);
if(!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len);
bootloader_sha256_finish(handle, NULL);
return ESP_FAIL;
}
bootloader_sha256_data(handle, data, data_len);
bootloader_munmap(data);
data_addr += data_len;
data_len_remain -= data_len;
}
// Calculate digest of main image
bootloader_sha256_handle_t handle = bootloader_sha256_start();
bootloader_sha256_data(handle, data, length);
/* Done! Get the digest */
bootloader_sha256_finish(handle, digest);
// Map the signature block and verify the signature
sigblock = (const esp_secure_boot_sig_block_t *)(data + length);
// Map the signature block
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if(!sigblock) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
// Verify the signature
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
bootloader_munmap(data);
// Unmap
bootloader_munmap(sigblock);
return err;
}

View File

@@ -0,0 +1,109 @@
// Copyright 2019 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 <stdbool.h>
#include <assert.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/efuse.h"
#include "soc/gpio_periph.h"
#include "soc/efuse_reg.h"
#include "soc/spi_reg.h"
#include "soc/spi_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
void bootloader_flash_update_id()
{
g_rom_flashchip.device_id = bootloader_read_flash_id();
}
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
{
uint32_t spi_clk_div = 0;
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
spi_clk_div = 1;
break;
case ESP_IMAGE_SPI_SPEED_40M:
spi_clk_div = 2;
break;
case ESP_IMAGE_SPI_SPEED_26M:
spi_clk_div = 3;
break;
case ESP_IMAGE_SPI_SPEED_20M:
spi_clk_div = 4;
break;
default:
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
}
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
{
}
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
{
int spi_cache_dummy = 0;
uint32_t modebit = READ_PERI_REG(SPI_CTRL_REG(0));
if (modebit & SPI_FASTRD_MODE) {
if (modebit & SPI_FREAD_QIO) { //SPI mode is QIO
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
} else if (modebit & SPI_FREAD_DIO) { //SPI mode is DIO
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
} else if(modebit & (SPI_FREAD_QUAD | SPI_FREAD_DUAL)) { //SPI mode is QOUT or DIO
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
}
}
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] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
break;
case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
break;
case ESP_IMAGE_SPI_SPEED_26M:
case ESP_IMAGE_SPI_SPEED_20M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
break;
default:
break;
}
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
}

View File

@@ -380,24 +380,22 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
}
#endif // BOOTLOADER_BUILD
#ifndef BOOTLOADER_BUILD
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
uint32_t free_page_count = bootloader_mmap_get_free_pages();
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;
err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum);
int32_t data_len_remain = data_len;
while (data_len_remain > 0) {
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
if (err != ESP_OK) {
return err;
}
data_addr += (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
data_len -= (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
}
#endif
err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
if (err != ESP_OK) {
return err;
data_addr += data_len;
data_len_remain -= data_len;
}
return ESP_OK;
err:

View File

@@ -0,0 +1,52 @@
// Copyright 2015-2019 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 "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_flash_encrypt.h"
void esp_flash_write_protect_crypt_cnt()
{
uint8_t flash_crypt_cnt_wr_dis = 0;
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
if (!flash_crypt_cnt_wr_dis) {
esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, 1);
}
}
esp_flash_enc_mode_t esp_get_flash_encryption_mode()
{
uint8_t efuse_flash_crypt_cnt_wr_protected = 0;
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
if (esp_flash_encryption_enabled()) {
/* Check if FLASH CRYPT CNT is write protected */
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &efuse_flash_crypt_cnt_wr_protected, 1);
if (efuse_flash_crypt_cnt_wr_protected) {
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_CACHE, &dis_dl_cache, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_ENCRYPT, &dis_dl_enc, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_DECRYPT, &dis_dl_dec, 1);
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
mode = ESP_FLASH_ENC_MODE_RELEASE;
}
}
} else {
mode = ESP_FLASH_ENC_MODE_DISABLED;
}
return mode;
}