add api get valid mmu table pages number

This commit is contained in:
Tian Zhong Xing 2018-03-15 19:58:02 +08:00
parent 7e268adaf5
commit 7555031553
4 changed files with 89 additions and 21 deletions

View file

@ -23,7 +23,7 @@
*/ */
static const char *TAG = "bootloader_mmap"; static const char *TAG = "bootloader_mmap";
static spi_flash_mmap_memory_t map; static spi_flash_mmap_handle_t map;
const void *bootloader_mmap(uint32_t src_addr, uint32_t size) const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{ {
@ -36,7 +36,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
size += (src_addr - src_page); size += (src_addr - src_page);
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map); esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
if (err != ESP_OK) { if (err != ESP_OK) {
result = NULL; ESP_LOGE(TAG, "spi_flash_mmap failed: 0x%x", err);
return NULL;
} }
return (void *)((intptr_t)result + (src_addr - src_page)); return (void *)((intptr_t)result + (src_addr - src_page));
} }

View file

@ -19,6 +19,7 @@
#include <esp_image_format.h> #include <esp_image_format.h>
#include <esp_secure_boot.h> #include <esp_secure_boot.h>
#include <esp_log.h> #include <esp_log.h>
#include <esp_spi_flash.h>
#include <bootloader_flash.h> #include <bootloader_flash.h>
#include <bootloader_random.h> #include <bootloader_random.h>
#include <bootloader_sha.h> #include <bootloader_sha.h>
@ -48,6 +49,9 @@ static bool should_map(uint32_t load_addr);
/* Load or verify a segment */ /* Load or verify a segment */
static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum); static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum);
/* split segment and verify if data_len is too long */
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);
/* Verify the main image header */ /* Verify the main image header */
static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent); static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent);
@ -291,7 +295,34 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
} }
} }
} }
#ifndef BOOTLOADER_BUILD
uint32_t page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGI(TAG, "free data page_count 0x%08x",page_count);
while (data_len >= page_count * SPI_FLASH_MMU_PAGE_SIZE) {
err = process_segment_data(load_addr, data_addr, page_count * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum);
if (err != ESP_OK) {
return err;
}
data_addr += page_count * SPI_FLASH_MMU_PAGE_SIZE;
data_len -= page_count * 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;
}
return ESP_OK;
err:
if (err == ESP_OK) {
err = ESP_ERR_IMAGE_INVALID;
}
return 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); const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len);
if(!data) { if(!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed",
@ -332,12 +363,6 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
bootloader_munmap(data); bootloader_munmap(data);
return ESP_OK; return ESP_OK;
err:
if (err == ESP_OK) {
err = ESP_ERR_IMAGE_INVALID;
}
return err;
} }
static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent) static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent)

View file

@ -100,6 +100,21 @@ static void IRAM_ATTR spi_flash_mmap_init()
DPORT_STALL_OTHER_CPU_END(); DPORT_STALL_OTHER_CPU_END();
} }
static void IRAM_ATTR get_mmu_region(spi_flash_mmap_memory_t memory, int* out_begin, int* out_size,uint32_t* region_addr)
{
if (memory == SPI_FLASH_MMAP_DATA) {
// Vaddr0
*out_begin = 0;
*out_size = 64;
*region_addr = VADDR0_START_ADDR;
} else {
// only part of VAddr1 is usable, so adjust for that
*out_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
*out_size = 3 * 64 - *out_begin;
*region_addr = VADDR1_FIRST_USABLE_ADDR;
}
}
esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory, esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle) const void** out_ptr, spi_flash_mmap_handle_t* out_handle)
{ {
@ -157,17 +172,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
int region_begin; // first page to check int region_begin; // first page to check
int region_size; // number of pages to check int region_size; // number of pages to check
uint32_t region_addr; // base address of memory region uint32_t region_addr; // base address of memory region
if (memory == SPI_FLASH_MMAP_DATA) { get_mmu_region(memory,&region_begin,&region_size,&region_addr);
// Vaddr0
region_begin = 0;
region_size = 64;
region_addr = VADDR0_START_ADDR;
} else {
// only part of VAddr1 is usable, so adjust for that
region_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
region_size = 3 * 64 - region_begin;
region_addr = VADDR1_FIRST_USABLE_ADDR;
}
if (region_size < page_count) { if (region_size < page_count) {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
@ -176,7 +181,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
// entries are treated as wildcards. // entries are treated as wildcards.
int start; int start;
int end = region_begin + region_size - page_count; int end = region_begin + region_size - page_count;
for (start = region_begin; start < end; ++start) { for (start = region_begin; start <= end; ++start) {
int pageno = 0; int pageno = 0;
int pos; int pos;
DPORT_STALL_OTHER_CPU_START(); DPORT_STALL_OTHER_CPU_START();
@ -194,7 +199,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas
} }
} }
// checked all the region(s) and haven't found anything? // checked all the region(s) and haven't found anything?
if (start == end) { if (start > end) {
*out_handle = 0; *out_handle = 0;
*out_ptr = NULL; *out_ptr = NULL;
ret = ESP_ERR_NO_MEM; ret = ESP_ERR_NO_MEM;
@ -292,6 +297,28 @@ void spi_flash_mmap_dump()
} }
} }
uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory)
{
spi_flash_mmap_init();
int count = 0;
int region_begin; // first page to check
int region_size; // number of pages to check
uint32_t region_addr; // base address of memory region
get_mmu_region(memory,&region_begin,&region_size,&region_addr);
DPORT_STALL_OTHER_CPU_START();
for (int i = region_begin; i < region_begin + region_size; ++i) {
if (s_mmap_page_refcnt[i] == 0 && DPORT_PRO_FLASH_MMU_TABLE[i] == INVALID_ENTRY_VAL) {
count++;
}
}
DPORT_STALL_OTHER_CPU_END();
if(count >= 1) {
return count - 1; //don't sure mmap src_addr,if src_addr not align 64K bytes,max need one more pages
} else {
return 0;
}
}
/* 256-bit (up to 16MB of 64KB pages) bitset of all flash pages /* 256-bit (up to 16MB of 64KB pages) bitset of all flash pages
that have been written to since last cache flush. that have been written to since last cache flush.

View file

@ -236,6 +236,21 @@ void spi_flash_munmap(spi_flash_mmap_handle_t handle);
*/ */
void spi_flash_mmap_dump(); void spi_flash_mmap_dump();
/**
* @brief get free pages number which can be mmap
*
* @note This function will return free page number of the mmu table which can mmap,
* when you want to call spi_flash_mmap to mmap an ranger of flash data to Dcache or Icache
* memmory region, maybe the size of MMU table will exceed,so if you are not sure the
* size need mmap is ok, can call the interface and watch how many MMU table page can be
* mmaped.
*
* @param memory memmory type of MMU table free page
*
* @return number of free pages which can be mmaped
*/
uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */ #define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */