Merge branch 'bugfix/sec_boot_ota_fail_v33' into 'release/v3.3'

Bugfix: ota fails with secure boot on for image size greater than 3.2MB (backport v3.3)

See merge request espressif/esp-idf!5581
This commit is contained in:
Angus Gratton 2019-08-06 14:51:06 +08:00
commit a6fb161309
5 changed files with 72 additions and 36 deletions

View file

@ -30,6 +30,13 @@
bootloader_support components only.
*/
/**
* @brief Get number of free pages
*
* @return Number of free pages
*/
uint32_t bootloader_mmap_get_free_pages();
/**
* @brief Map a region of flash to data memory
*

View file

@ -25,6 +25,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) {
@ -91,12 +96,22 @@ static const char *TAG = "bootloader_flash";
*/
#define MMU_BLOCK0_VADDR 0x3f400000
#define MMU_BLOCK50_VADDR 0x3f720000
#define MMU_FREE_PAGES ((MMU_BLOCK50_VADDR - MMU_BLOCK0_VADDR) / 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) {

View file

@ -368,24 +368,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);
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);
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 = 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

@ -21,12 +21,7 @@
#include "uECC.h"
#ifdef BOOTLOADER_BUILD
#include "rom/sha.h"
typedef SHA_CTX sha_context;
#else
#include "mbedtls/sha256.h"
#endif
#include <sys/param.h>
static const char* TAG = "secure_boot";
@ -37,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];
@ -45,26 +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
#ifdef BOOTLOADER_BUILD
bootloader_sha256_handle_t handle = bootloader_sha256_start();
bootloader_sha256_data(handle, data, length);
/* Done! Get the digest */
bootloader_sha256_finish(handle, digest);
#else
/* Use thread-safe mbedTLS version */
mbedtls_sha256_ret(data, length, digest, 0);
#endif
// 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

@ -1174,7 +1174,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
}
if (send_ptr && isdma && !esp_ptr_dma_capable( send_ptr )) {
//if txbuf in the desc not DMA-capable, malloc a new one
ESP_LOGI( SPI_TAG, "Allocate TX buffer for DMA" );
ESP_LOGD( SPI_TAG, "Allocate TX buffer for DMA" );
uint32_t *temp = heap_caps_malloc((trans_desc->length + 7) / 8, MALLOC_CAP_DMA);
if (temp == NULL) goto clean_up;