mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
NVS: using esp_partition API
* partition api changed from spi_flash* API to esp_partition* API and is abstracted as a C++ interface. * The old nvs encryption is still possible * changed default unit test app partition table * Partitions coming from esp_partition API are checked for generic flash encryption. If yes, an error is returned since generic flash encryption isn't compatible with nvs encryption * esp32, esp32s2 tests don't require nvs_flash but mbedtls now Closes IDF-1340 Closes IDF-858
This commit is contained in:
parent
153c2e7406
commit
aca9ec28b3
@ -1,7 +1,7 @@
|
|||||||
if(IDF_TARGET STREQUAL "esp32")
|
if(IDF_TARGET STREQUAL "esp32")
|
||||||
idf_component_register(SRC_DIRS .
|
idf_component_register(SRC_DIRS .
|
||||||
PRIV_INCLUDE_DIRS .
|
PRIV_INCLUDE_DIRS .
|
||||||
PRIV_REQUIRES cmock test_utils nvs_flash ulp esp_common
|
PRIV_REQUIRES cmock test_utils mbedtls ulp esp_common
|
||||||
)
|
)
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
if(IDF_TARGET STREQUAL "esp32s2")
|
if(IDF_TARGET STREQUAL "esp32s2")
|
||||||
idf_component_register(SRC_DIRS .
|
idf_component_register(SRC_DIRS .
|
||||||
PRIV_INCLUDE_DIRS .
|
PRIV_INCLUDE_DIRS .
|
||||||
PRIV_REQUIRES cmock test_utils nvs_flash ulp esp_common
|
PRIV_REQUIRES cmock test_utils nvs_flash mbedtls ulp esp_common
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -212,6 +212,12 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
|||||||
ERR_TBL_IT(ESP_ERR_NVS_CONTENT_DIFFERS), /* 4376 0x1118 Internal error; never returned by nvs
|
ERR_TBL_IT(ESP_ERR_NVS_CONTENT_DIFFERS), /* 4376 0x1118 Internal error; never returned by nvs
|
||||||
API functions. NVS key is different in
|
API functions. NVS key is different in
|
||||||
comparison */
|
comparison */
|
||||||
|
# endif
|
||||||
|
# ifdef ESP_ERR_NVS_WRONG_ENCRYPTION
|
||||||
|
ERR_TBL_IT(ESP_ERR_NVS_WRONG_ENCRYPTION), /* 4377 0x1119 NVS partition is marked as encrypted
|
||||||
|
with generic flash encryption. This is
|
||||||
|
forbidden since the NVS encryption works
|
||||||
|
differently. */
|
||||||
# endif
|
# endif
|
||||||
// components/ulp/include/ulp_common.h
|
// components/ulp/include/ulp_common.h
|
||||||
# ifdef ESP_ERR_ULP_BASE
|
# ifdef ESP_ERR_ULP_BASE
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
set(srcs "src/nvs_api.cpp"
|
set(srcs "src/nvs_api.cpp"
|
||||||
"src/nvs_cxx_api.cpp"
|
"src/nvs_cxx_api.cpp"
|
||||||
"src/nvs_item_hash_list.cpp"
|
"src/nvs_item_hash_list.cpp"
|
||||||
"src/nvs_ops.cpp"
|
|
||||||
"src/nvs_page.cpp"
|
"src/nvs_page.cpp"
|
||||||
"src/nvs_pagemanager.cpp"
|
"src/nvs_pagemanager.cpp"
|
||||||
"src/nvs_storage.cpp"
|
"src/nvs_storage.cpp"
|
||||||
"src/nvs_handle_simple.cpp"
|
"src/nvs_handle_simple.cpp"
|
||||||
"src/nvs_handle_locked.cpp"
|
"src/nvs_handle_locked.cpp"
|
||||||
|
"src/nvs_partition.cpp"
|
||||||
|
"src/nvs_partition_lookup.cpp"
|
||||||
"src/nvs_partition_manager.cpp"
|
"src/nvs_partition_manager.cpp"
|
||||||
"src/nvs_types.cpp")
|
"src/nvs_types.cpp")
|
||||||
|
|
||||||
if(CONFIG_NVS_ENCRYPTION)
|
if(CONFIG_NVS_ENCRYPTION)
|
||||||
list(APPEND srcs "src/nvs_encr.cpp")
|
list(APPEND srcs "src/nvs_encrypted_partition.cpp")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
|
@ -59,6 +59,7 @@ typedef nvs_handle_t nvs_handle IDF_DEPRECATED("Replace with nvs_handle_t");
|
|||||||
#define ESP_ERR_NVS_ENCR_NOT_SUPPORTED (ESP_ERR_NVS_BASE + 0x15) /*!< NVS encryption is not supported in this version */
|
#define ESP_ERR_NVS_ENCR_NOT_SUPPORTED (ESP_ERR_NVS_BASE + 0x15) /*!< NVS encryption is not supported in this version */
|
||||||
#define ESP_ERR_NVS_KEYS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x16) /*!< NVS key partition is uninitialized */
|
#define ESP_ERR_NVS_KEYS_NOT_INITIALIZED (ESP_ERR_NVS_BASE + 0x16) /*!< NVS key partition is uninitialized */
|
||||||
#define ESP_ERR_NVS_CORRUPT_KEY_PART (ESP_ERR_NVS_BASE + 0x17) /*!< NVS key partition is corrupt */
|
#define ESP_ERR_NVS_CORRUPT_KEY_PART (ESP_ERR_NVS_BASE + 0x17) /*!< NVS key partition is corrupt */
|
||||||
|
#define ESP_ERR_NVS_WRONG_ENCRYPTION (ESP_ERR_NVS_BASE + 0x19) /*!< NVS partition is marked as encrypted with generic flash encryption. This is forbidden since the NVS encryption works differently. */
|
||||||
|
|
||||||
#define ESP_ERR_NVS_CONTENT_DIFFERS (ESP_ERR_NVS_BASE + 0x18) /*!< Internal error; never returned by nvs API functions. NVS key is different in comparison */
|
#define ESP_ERR_NVS_CONTENT_DIFFERS (ESP_ERR_NVS_BASE + 0x18) /*!< Internal error; never returned by nvs API functions. NVS key is different in comparison */
|
||||||
|
|
||||||
|
@ -20,9 +20,6 @@
|
|||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "nvs_handle_simple.hpp"
|
#include "nvs_handle_simple.hpp"
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
#include "nvs_encr.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include <esp32/rom/crc.h>
|
#include <esp32/rom/crc.h>
|
||||||
@ -57,14 +54,9 @@ private:
|
|||||||
uint32_t NVSHandleEntry::s_nvs_next_handle;
|
uint32_t NVSHandleEntry::s_nvs_next_handle;
|
||||||
|
|
||||||
extern "C" void nvs_dump(const char *partName);
|
extern "C" void nvs_dump(const char *partName);
|
||||||
extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
|
|
||||||
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
SemaphoreHandle_t nvs::Lock::mSemaphore = NULL;
|
SemaphoreHandle_t nvs::Lock::mSemaphore = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -83,41 +75,13 @@ extern "C" void nvs_dump(const char *partName)
|
|||||||
nvs::Storage* pStorage;
|
nvs::Storage* pStorage;
|
||||||
|
|
||||||
pStorage = lookup_storage_from_name(partName);
|
pStorage = lookup_storage_from_name(partName);
|
||||||
if (pStorage == NULL) {
|
if (pStorage == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pStorage->debugDump();
|
pStorage->debugDump();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
|
|
||||||
|
|
||||||
return NVSPartitionManager::get_instance()->init_custom(partName, baseSector, sectorCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "nvs_flash_secure_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
|
|
||||||
|
|
||||||
if(cfg) {
|
|
||||||
auto encrMgr = EncrMgr::getInstance();
|
|
||||||
|
|
||||||
if (!encrMgr) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg);
|
|
||||||
if(err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nvs_flash_init_custom(partName, baseSector, sectorCount);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static esp_err_t close_handles_and_deinit(const char* part_name)
|
static esp_err_t close_handles_and_deinit(const char* part_name)
|
||||||
{
|
{
|
||||||
// Delete all corresponding open handles
|
// Delete all corresponding open handles
|
||||||
@ -132,13 +96,24 @@ extern "C" esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partiti
|
|||||||
Lock::init();
|
Lock::init();
|
||||||
Lock lock;
|
Lock lock;
|
||||||
|
|
||||||
if (!partition) {
|
if (partition == nullptr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nvs_flash_init_custom(partition->label,
|
NVSPartition *part = new (std::nothrow) NVSPartition(partition);
|
||||||
partition->address / SPI_FLASH_SEC_SIZE,
|
if (part == nullptr) {
|
||||||
partition->size / SPI_FLASH_SEC_SIZE);
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t init_res = NVSPartitionManager::get_instance()->init_custom(part,
|
||||||
|
partition->address / SPI_FLASH_SEC_SIZE,
|
||||||
|
partition->size / SPI_FLASH_SEC_SIZE);
|
||||||
|
|
||||||
|
if (init_res != ESP_OK) {
|
||||||
|
delete part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return init_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
@ -160,21 +135,8 @@ extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_
|
|||||||
{
|
{
|
||||||
Lock::init();
|
Lock::init();
|
||||||
Lock lock;
|
Lock lock;
|
||||||
nvs::Storage* mStorage;
|
|
||||||
|
|
||||||
mStorage = lookup_storage_from_name(part_name);
|
return NVSPartitionManager::get_instance()->secure_init_partition(part_name, cfg);
|
||||||
if (mStorage) {
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_partition_t* partition = esp_partition_find_first(
|
|
||||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
|
|
||||||
if (partition == NULL) {
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nvs_flash_secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
|
|
||||||
partition->size / SPI_FLASH_SEC_SIZE, cfg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
|
extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
|
||||||
@ -200,7 +162,7 @@ extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
|
|||||||
|
|
||||||
const esp_partition_t* partition = esp_partition_find_first(
|
const esp_partition_t* partition = esp_partition_find_first(
|
||||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
|
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
|
||||||
if (partition == NULL) {
|
if (partition == nullptr) {
|
||||||
return ESP_ERR_NOT_FOUND;
|
return ESP_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +174,7 @@ extern "C" esp_err_t nvs_flash_erase_partition_ptr(const esp_partition_t *partit
|
|||||||
Lock::init();
|
Lock::init();
|
||||||
Lock lock;
|
Lock lock;
|
||||||
|
|
||||||
if (!partition) {
|
if (partition == nullptr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +477,7 @@ extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats
|
|||||||
Lock lock;
|
Lock lock;
|
||||||
nvs::Storage* pStorage;
|
nvs::Storage* pStorage;
|
||||||
|
|
||||||
if (nvs_stats == NULL) {
|
if (nvs_stats == nullptr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
nvs_stats->used_entries = 0;
|
nvs_stats->used_entries = 0;
|
||||||
@ -523,8 +485,8 @@ extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats
|
|||||||
nvs_stats->total_entries = 0;
|
nvs_stats->total_entries = 0;
|
||||||
nvs_stats->namespace_count = 0;
|
nvs_stats->namespace_count = 0;
|
||||||
|
|
||||||
pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
|
pStorage = lookup_storage_from_name((part_name == nullptr) ? NVS_DEFAULT_PART_NAME : part_name);
|
||||||
if (pStorage == NULL) {
|
if (pStorage == nullptr) {
|
||||||
return ESP_ERR_NVS_NOT_INITIALIZED;
|
return ESP_ERR_NVS_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +500,7 @@ extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats
|
|||||||
extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* used_entries)
|
extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* used_entries)
|
||||||
{
|
{
|
||||||
Lock lock;
|
Lock lock;
|
||||||
if(used_entries == NULL){
|
if(used_entries == nullptr){
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
*used_entries = 0;
|
*used_entries = 0;
|
||||||
@ -571,12 +533,12 @@ extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, n
|
|||||||
cfg->tky[cnt] = 0xee;
|
cfg->tky[cnt] = 0xee;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spi_flash_write(partition->address, cfg->eky, NVS_KEY_SIZE);
|
err = esp_partition_write(partition, 0, cfg->eky, NVS_KEY_SIZE);
|
||||||
if(err != ESP_OK) {
|
if(err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spi_flash_write(partition->address + NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
|
err = esp_partition_write(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
|
||||||
if(err != ESP_OK) {
|
if(err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -622,17 +584,17 @@ extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partitio
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto err = spi_flash_read(partition->address, eky_raw, NVS_KEY_SIZE);
|
auto err = esp_partition_read_raw(partition, 0, eky_raw, NVS_KEY_SIZE);
|
||||||
if(err != ESP_OK) {
|
if(err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spi_flash_read(partition->address + NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE);
|
err = esp_partition_read_raw(partition, NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE);
|
||||||
if(err != ESP_OK) {
|
if(err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spi_flash_read(partition->address + 2 * NVS_KEY_SIZE, &crc_raw, 4);
|
err = esp_partition_read_raw(partition, 2 * NVS_KEY_SIZE, &crc_raw, 4);
|
||||||
if(err != ESP_OK) {
|
if(err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -679,8 +641,8 @@ extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partitio
|
|||||||
static nvs_iterator_t create_iterator(nvs::Storage *storage, nvs_type_t type)
|
static nvs_iterator_t create_iterator(nvs::Storage *storage, nvs_type_t type)
|
||||||
{
|
{
|
||||||
nvs_iterator_t it = (nvs_iterator_t)calloc(1, sizeof(nvs_opaque_iterator_t));
|
nvs_iterator_t it = (nvs_iterator_t)calloc(1, sizeof(nvs_opaque_iterator_t));
|
||||||
if (it == NULL) {
|
if (it == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->storage = storage;
|
it->storage = storage;
|
||||||
@ -695,19 +657,19 @@ extern "C" nvs_iterator_t nvs_entry_find(const char *part_name, const char *name
|
|||||||
nvs::Storage *pStorage;
|
nvs::Storage *pStorage;
|
||||||
|
|
||||||
pStorage = lookup_storage_from_name(part_name);
|
pStorage = lookup_storage_from_name(part_name);
|
||||||
if (pStorage == NULL) {
|
if (pStorage == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvs_iterator_t it = create_iterator(pStorage, type);
|
nvs_iterator_t it = create_iterator(pStorage, type);
|
||||||
if (it == NULL) {
|
if (it == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entryFound = pStorage->findEntry(it, namespace_name);
|
bool entryFound = pStorage->findEntry(it, namespace_name);
|
||||||
if (!entryFound) {
|
if (!entryFound) {
|
||||||
free(it);
|
free(it);
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
@ -721,7 +683,7 @@ extern "C" nvs_iterator_t nvs_entry_next(nvs_iterator_t it)
|
|||||||
bool entryFound = it->storage->nextEntry(it);
|
bool entryFound = it->storage->nextEntry(it);
|
||||||
if (!entryFound) {
|
if (!entryFound) {
|
||||||
free(it);
|
free(it);
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
// 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 "nvs_encr.hpp"
|
|
||||||
#include "nvs_types.hpp"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace nvs
|
|
||||||
{
|
|
||||||
|
|
||||||
bool EncrMgr::isActive = false;
|
|
||||||
EncrMgr* EncrMgr::instance = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
EncrMgr* EncrMgr::getInstance()
|
|
||||||
{
|
|
||||||
if(!isActive)
|
|
||||||
{
|
|
||||||
instance = new (std::nothrow) EncrMgr();
|
|
||||||
if (instance) {
|
|
||||||
isActive = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncrMgr::resetInstance()
|
|
||||||
{
|
|
||||||
if(isActive) {
|
|
||||||
delete instance;
|
|
||||||
instance = nullptr;
|
|
||||||
isActive = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EncrMgr::isEncrActive() {
|
|
||||||
return isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
XtsCtxt* EncrMgr::findXtsCtxtFromAddr(uint32_t addr) {
|
|
||||||
|
|
||||||
auto it = find_if(std::begin(xtsCtxtList), std::end(xtsCtxtList), [=](XtsCtxt& ctx) -> bool
|
|
||||||
{ return (ctx.baseSector * SPI_FLASH_SEC_SIZE <= addr)
|
|
||||||
&& (addr < (ctx.baseSector + ctx.sectorCount) * SPI_FLASH_SEC_SIZE); });
|
|
||||||
|
|
||||||
if (it == std::end(xtsCtxtList)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t EncrMgr::setSecurityContext(uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg) {
|
|
||||||
|
|
||||||
uint8_t* eky = reinterpret_cast<uint8_t*>(cfg);
|
|
||||||
|
|
||||||
auto ctxt = new (std::nothrow) XtsCtxt();
|
|
||||||
|
|
||||||
if (!ctxt) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
ctxt->baseSector = baseSector;
|
|
||||||
ctxt->sectorCount = sectorCount;
|
|
||||||
|
|
||||||
mbedtls_aes_xts_init(ctxt->ectxt);
|
|
||||||
mbedtls_aes_xts_init(ctxt->dctxt);
|
|
||||||
|
|
||||||
if(mbedtls_aes_xts_setkey_enc(ctxt->ectxt, eky, 2 * NVS_KEY_SIZE * 8)) {
|
|
||||||
return ESP_ERR_NVS_XTS_CFG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mbedtls_aes_xts_setkey_dec(ctxt->dctxt, eky, 2 * NVS_KEY_SIZE * 8)) {
|
|
||||||
return ESP_ERR_NVS_XTS_CFG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
xtsCtxtList.push_back(ctxt);
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t EncrMgr::removeSecurityContext(uint32_t baseSector) {
|
|
||||||
auto xtsCtxt = findXtsCtxtFromAddr(baseSector * SPI_FLASH_SEC_SIZE);
|
|
||||||
if(!xtsCtxt) {
|
|
||||||
return ESP_ERR_NVS_XTS_CFG_NOT_FOUND;
|
|
||||||
}
|
|
||||||
xtsCtxtList.erase(xtsCtxt);
|
|
||||||
delete xtsCtxt;
|
|
||||||
|
|
||||||
if(!xtsCtxtList.size()) {
|
|
||||||
resetInstance();
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t EncrMgr::encryptNvsData(uint8_t* ptxt, uint32_t addr, uint32_t ptxtLen, XtsCtxt* xtsCtxt) {
|
|
||||||
|
|
||||||
uint8_t entrySize = sizeof(Item);
|
|
||||||
|
|
||||||
//sector num required as an arr by mbedtls. Should have been just uint64/32.
|
|
||||||
uint8_t data_unit[16];
|
|
||||||
|
|
||||||
assert(ptxtLen % entrySize == 0);
|
|
||||||
|
|
||||||
/* Use relative address instead of absolute address (relocatable), so that host-generated
|
|
||||||
* encrypted nvs images can be used*/
|
|
||||||
uint32_t relAddr = addr - (xtsCtxt->baseSector * SPI_FLASH_SEC_SIZE);
|
|
||||||
|
|
||||||
memset(data_unit, 0, sizeof(data_unit));
|
|
||||||
|
|
||||||
for(uint8_t entry = 0; entry < (ptxtLen/entrySize); entry++)
|
|
||||||
{
|
|
||||||
uint32_t offset = entry * entrySize;
|
|
||||||
uint32_t *addr_loc = (uint32_t*) &data_unit[0];
|
|
||||||
|
|
||||||
*addr_loc = relAddr + offset;
|
|
||||||
if(mbedtls_aes_crypt_xts(xtsCtxt->ectxt, MBEDTLS_AES_ENCRYPT, entrySize, data_unit, ptxt + offset, ptxt + offset)) {
|
|
||||||
return ESP_ERR_NVS_XTS_ENCR_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t EncrMgr::decryptNvsData(uint8_t* ctxt, uint32_t addr, uint32_t ctxtLen, XtsCtxt* xtsCtxt) {
|
|
||||||
|
|
||||||
//sector num required as an arr by mbedtls. Should have been just uint64/32.
|
|
||||||
uint8_t data_unit[16];
|
|
||||||
|
|
||||||
|
|
||||||
/** Currently upper layer of NVS reads entries one by one even for variable size
|
|
||||||
* multi-entry data types. So length should always be equal to size of an entry.*/
|
|
||||||
assert(ctxtLen == sizeof(Item));
|
|
||||||
|
|
||||||
uint32_t relAddr = addr - (xtsCtxt->baseSector * SPI_FLASH_SEC_SIZE);
|
|
||||||
|
|
||||||
memset(data_unit, 0, sizeof(data_unit));
|
|
||||||
|
|
||||||
memcpy(data_unit, &relAddr, sizeof(relAddr));
|
|
||||||
|
|
||||||
if(mbedtls_aes_crypt_xts(xtsCtxt->dctxt, MBEDTLS_AES_DECRYPT, ctxtLen, data_unit, ctxt, ctxt)) {
|
|
||||||
return ESP_ERR_NVS_XTS_DECR_FAILED;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace nvs
|
|
@ -1,63 +0,0 @@
|
|||||||
// 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.
|
|
||||||
#ifndef nvs_encr_hpp
|
|
||||||
#define nvs_encr_hpp
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "mbedtls/aes.h"
|
|
||||||
#include "intrusive_list.h"
|
|
||||||
#include "nvs_flash.h"
|
|
||||||
|
|
||||||
namespace nvs
|
|
||||||
{
|
|
||||||
|
|
||||||
struct XtsCtxt : public intrusive_list_node<XtsCtxt> {
|
|
||||||
public:
|
|
||||||
mbedtls_aes_xts_context ectxt[1];
|
|
||||||
mbedtls_aes_xts_context dctxt[1];
|
|
||||||
uint32_t baseSector;
|
|
||||||
uint32_t sectorCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* A singleton class for managing nvs encryption*/
|
|
||||||
class EncrMgr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static EncrMgr* getInstance();
|
|
||||||
static void resetInstance();
|
|
||||||
static bool isEncrActive();
|
|
||||||
esp_err_t setSecurityContext(uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg);
|
|
||||||
esp_err_t removeSecurityContext(uint32_t baseSector);
|
|
||||||
esp_err_t encryptNvsData(uint8_t* ptxt, uint32_t addr, uint32_t ptxtLen, XtsCtxt* xtsCtxt);
|
|
||||||
esp_err_t decryptNvsData(uint8_t* ctxt, uint32_t addr, uint32_t ctxtLen, XtsCtxt* xtsCtxt);
|
|
||||||
XtsCtxt* findXtsCtxtFromAddr(uint32_t addr);
|
|
||||||
~EncrMgr() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static bool isActive;
|
|
||||||
static EncrMgr* instance;
|
|
||||||
intrusive_list<XtsCtxt> xtsCtxtList;
|
|
||||||
EncrMgr() {}
|
|
||||||
|
|
||||||
}; // class EncrMgr
|
|
||||||
|
|
||||||
esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size);
|
|
||||||
esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size);
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace nvs
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* nvs_encr_hpp */
|
|
122
components/nvs_flash/src/nvs_encrypted_partition.cpp
Normal file
122
components/nvs_flash/src/nvs_encrypted_partition.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// 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 <cstring>
|
||||||
|
#include "nvs_encrypted_partition.hpp"
|
||||||
|
#include "nvs_types.hpp"
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
NVSEncryptedPartition::NVSEncryptedPartition(const esp_partition_t *partition)
|
||||||
|
: NVSPartition(partition) { }
|
||||||
|
|
||||||
|
esp_err_t NVSEncryptedPartition::init(nvs_sec_cfg_t* cfg)
|
||||||
|
{
|
||||||
|
uint8_t* eky = reinterpret_cast<uint8_t*>(cfg);
|
||||||
|
|
||||||
|
mbedtls_aes_xts_init(&mEctxt);
|
||||||
|
mbedtls_aes_xts_init(&mDctxt);
|
||||||
|
|
||||||
|
if (mbedtls_aes_xts_setkey_enc(&mEctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) {
|
||||||
|
return ESP_ERR_NVS_XTS_CFG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mbedtls_aes_xts_setkey_dec(&mDctxt, eky, 2 * NVS_KEY_SIZE * 8) != 0) {
|
||||||
|
return ESP_ERR_NVS_XTS_CFG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSEncryptedPartition::read(size_t src_offset, void* dst, size_t size)
|
||||||
|
{
|
||||||
|
/** Currently upper layer of NVS reads entries one by one even for variable size
|
||||||
|
* multi-entry data types. So length should always be equal to size of an entry.*/
|
||||||
|
if (size != sizeof(Item)) return ESP_ERR_INVALID_SIZE;
|
||||||
|
|
||||||
|
// read data
|
||||||
|
esp_err_t read_result = esp_partition_read(mESPPartition, src_offset, dst, size);
|
||||||
|
if (read_result != ESP_OK) {
|
||||||
|
return read_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt data
|
||||||
|
//sector num required as an arr by mbedtls. Should have been just uint64/32.
|
||||||
|
uint8_t data_unit[16];
|
||||||
|
|
||||||
|
uint32_t relAddr = src_offset;
|
||||||
|
|
||||||
|
memset(data_unit, 0, sizeof(data_unit));
|
||||||
|
|
||||||
|
memcpy(data_unit, &relAddr, sizeof(relAddr));
|
||||||
|
|
||||||
|
uint8_t *destination = reinterpret_cast<uint8_t*>(dst);
|
||||||
|
|
||||||
|
if (mbedtls_aes_crypt_xts(&mDctxt, MBEDTLS_AES_DECRYPT, size, data_unit, destination, destination) != 0) {
|
||||||
|
return ESP_ERR_NVS_XTS_DECR_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSEncryptedPartition::write(size_t addr, const void* src, size_t size)
|
||||||
|
{
|
||||||
|
if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) return ESP_ERR_INVALID_SIZE;
|
||||||
|
|
||||||
|
// copy data to buffer for encryption
|
||||||
|
uint8_t* buf = new (std::nothrow) uint8_t [size];
|
||||||
|
|
||||||
|
if (!buf) return ESP_ERR_NO_MEM;
|
||||||
|
|
||||||
|
memcpy(buf, src, size);
|
||||||
|
|
||||||
|
// encrypt data
|
||||||
|
uint8_t entrySize = sizeof(Item);
|
||||||
|
|
||||||
|
//sector num required as an arr by mbedtls. Should have been just uint64/32.
|
||||||
|
uint8_t data_unit[16];
|
||||||
|
|
||||||
|
/* Use relative address instead of absolute address (relocatable), so that host-generated
|
||||||
|
* encrypted nvs images can be used*/
|
||||||
|
uint32_t relAddr = addr;
|
||||||
|
|
||||||
|
memset(data_unit, 0, sizeof(data_unit));
|
||||||
|
|
||||||
|
for(uint8_t entry = 0; entry < (size/entrySize); entry++)
|
||||||
|
{
|
||||||
|
uint32_t offset = entry * entrySize;
|
||||||
|
uint32_t *addr_loc = (uint32_t*) &data_unit[0];
|
||||||
|
|
||||||
|
*addr_loc = relAddr + offset;
|
||||||
|
if (mbedtls_aes_crypt_xts(&mEctxt,
|
||||||
|
MBEDTLS_AES_ENCRYPT,
|
||||||
|
entrySize,
|
||||||
|
data_unit,
|
||||||
|
buf + offset,
|
||||||
|
buf + offset) != 0) {
|
||||||
|
delete buf;
|
||||||
|
return ESP_ERR_NVS_XTS_ENCR_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data
|
||||||
|
esp_err_t result = esp_partition_write(mESPPartition, addr, buf, size);
|
||||||
|
|
||||||
|
delete buf;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
44
components/nvs_flash/src/nvs_encrypted_partition.hpp
Normal file
44
components/nvs_flash/src/nvs_encrypted_partition.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef NVS_ENCRYPTED_PARTITION_HPP_
|
||||||
|
#define NVS_ENCRYPTED_PARTITION_HPP_
|
||||||
|
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "nvs_partition.hpp"
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
class NVSEncryptedPartition : public NVSPartition {
|
||||||
|
public:
|
||||||
|
NVSEncryptedPartition(const esp_partition_t *partition);
|
||||||
|
|
||||||
|
virtual ~NVSEncryptedPartition() { }
|
||||||
|
|
||||||
|
esp_err_t init(nvs_sec_cfg_t* cfg);
|
||||||
|
|
||||||
|
esp_err_t read(size_t src_offset, void* dst, size_t size) override;
|
||||||
|
|
||||||
|
esp_err_t write(size_t dst_offset, const void* src, size_t size) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mbedtls_aes_xts_context mEctxt;
|
||||||
|
mbedtls_aes_xts_context mDctxt;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
||||||
|
#endif // NVS_ENCRYPTED_PARTITION_HPP_
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
// 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_spi_flash.h"
|
|
||||||
#include "nvs_ops.hpp"
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
#include "nvs_encr.hpp"
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nvs
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size) {
|
|
||||||
|
|
||||||
if(EncrMgr::isEncrActive()) {
|
|
||||||
auto encrMgr = EncrMgr::getInstance();
|
|
||||||
|
|
||||||
if (!encrMgr) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
auto xtsCtxt = encrMgr->findXtsCtxtFromAddr(destAddr);
|
|
||||||
|
|
||||||
if(xtsCtxt) {
|
|
||||||
uint8_t* buf = static_cast<uint8_t*>(malloc(size));
|
|
||||||
memcpy(buf, srcAddr, size);
|
|
||||||
auto err = encrMgr->encryptNvsData(buf, destAddr, size, xtsCtxt);
|
|
||||||
if( err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = spi_flash_write(destAddr, buf, size);
|
|
||||||
delete buf;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return spi_flash_write(destAddr, srcAddr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size) {
|
|
||||||
|
|
||||||
auto err = spi_flash_read(srcAddr, destAddr, size);
|
|
||||||
|
|
||||||
if(err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(EncrMgr::isEncrActive()) {
|
|
||||||
auto encrMgr = EncrMgr::getInstance();
|
|
||||||
|
|
||||||
if (!encrMgr) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
auto xtsCtxt = encrMgr->findXtsCtxtFromAddr(srcAddr);
|
|
||||||
if(xtsCtxt) {
|
|
||||||
return encrMgr->decryptNvsData(static_cast<uint8_t*>(destAddr),
|
|
||||||
srcAddr, size, xtsCtxt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size) {
|
|
||||||
return spi_flash_write(destAddr, srcAddr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size) {
|
|
||||||
return spi_flash_read(srcAddr, destAddr, size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
// 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.
|
|
||||||
#ifndef nvs_ops_hpp
|
|
||||||
#define nvs_ops_hpp
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
namespace nvs
|
|
||||||
{
|
|
||||||
esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size);
|
|
||||||
esp_err_t nvs_flash_read(size_t srcAddr, void *destAddr, size_t size);
|
|
||||||
|
|
||||||
} // namespace nvs
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* nvs_ops_hpp */
|
|
@ -20,11 +20,11 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "nvs_ops.hpp"
|
|
||||||
|
|
||||||
namespace nvs
|
namespace nvs
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Page::Page() : mPartition(nullptr) { }
|
||||||
|
|
||||||
uint32_t Page::Header::calculateCrc32()
|
uint32_t Page::Header::calculateCrc32()
|
||||||
{
|
{
|
||||||
return crc32_le(0xffffffff,
|
return crc32_le(0xffffffff,
|
||||||
@ -32,14 +32,19 @@ uint32_t Page::Header::calculateCrc32()
|
|||||||
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t Page::load(uint32_t sectorNumber)
|
esp_err_t Page::load(Partition *partition, uint32_t sectorNumber)
|
||||||
{
|
{
|
||||||
|
if (partition == nullptr) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPartition = partition;
|
||||||
mBaseAddress = sectorNumber * SEC_SIZE;
|
mBaseAddress = sectorNumber * SEC_SIZE;
|
||||||
mUsedEntryCount = 0;
|
mUsedEntryCount = 0;
|
||||||
mErasedEntryCount = 0;
|
mErasedEntryCount = 0;
|
||||||
|
|
||||||
Header header;
|
Header header;
|
||||||
auto rc = spi_flash_read(mBaseAddress, &header, sizeof(header));
|
auto rc = mPartition->read_raw(mBaseAddress, &header, sizeof(header));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return rc;
|
return rc;
|
||||||
@ -54,7 +59,7 @@ esp_err_t Page::load(uint32_t sectorNumber)
|
|||||||
if (!block) return ESP_ERR_NO_MEM;
|
if (!block) return ESP_ERR_NO_MEM;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += 4 * BLOCK_SIZE) {
|
for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += 4 * BLOCK_SIZE) {
|
||||||
rc = spi_flash_read(mBaseAddress + i, block, 4 * BLOCK_SIZE);
|
rc = mPartition->read_raw(mBaseAddress + i, block, 4 * BLOCK_SIZE);
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
delete[] block;
|
delete[] block;
|
||||||
@ -101,7 +106,7 @@ esp_err_t Page::writeEntry(const Item& item)
|
|||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
|
|
||||||
err = nvs_flash_write(getEntryAddress(mNextFreeEntry), &item, sizeof(item));
|
err = mPartition->write(getEntryAddress(mNextFreeEntry), &item, sizeof(item));
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
@ -133,6 +138,7 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
|||||||
const uint8_t* buf = data;
|
const uint8_t* buf = data;
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
// TODO: check whether still necessary with esp_partition* API
|
||||||
/* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write
|
/* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write
|
||||||
* function. To work around this, we copy the data to heap if it came from DROM.
|
* function. To work around this, we copy the data to heap if it came from DROM.
|
||||||
* Hopefully this won't happen very often in practice. For data from DRAM, we should
|
* Hopefully this won't happen very often in practice. For data from DRAM, we should
|
||||||
@ -149,7 +155,7 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
|||||||
}
|
}
|
||||||
#endif //ESP_PLATFORM
|
#endif //ESP_PLATFORM
|
||||||
|
|
||||||
auto rc = nvs_flash_write(getEntryAddress(mNextFreeEntry), buf, size);
|
auto rc = mPartition->write(getEntryAddress(mNextFreeEntry), buf, size);
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
if (buf != data) {
|
if (buf != data) {
|
||||||
@ -518,7 +524,7 @@ esp_err_t Page::mLoadEntryTable()
|
|||||||
if (mState == PageState::ACTIVE ||
|
if (mState == PageState::ACTIVE ||
|
||||||
mState == PageState::FULL ||
|
mState == PageState::FULL ||
|
||||||
mState == PageState::FREEING) {
|
mState == PageState::FREEING) {
|
||||||
auto rc = spi_flash_read(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(),
|
auto rc = mPartition->read_raw(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(),
|
||||||
mEntryTable.byteSize());
|
mEntryTable.byteSize());
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
@ -557,7 +563,7 @@ esp_err_t Page::mLoadEntryTable()
|
|||||||
while (mNextFreeEntry < ENTRY_COUNT) {
|
while (mNextFreeEntry < ENTRY_COUNT) {
|
||||||
uint32_t entryAddress = getEntryAddress(mNextFreeEntry);
|
uint32_t entryAddress = getEntryAddress(mNextFreeEntry);
|
||||||
uint32_t header;
|
uint32_t header;
|
||||||
auto rc = spi_flash_read(entryAddress, &header, sizeof(header));
|
auto rc = mPartition->read_raw(entryAddress, &header, sizeof(header));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return rc;
|
return rc;
|
||||||
@ -722,7 +728,7 @@ esp_err_t Page::initialize()
|
|||||||
header.mVersion = mVersion;
|
header.mVersion = mVersion;
|
||||||
header.mCrc32 = header.calculateCrc32();
|
header.mCrc32 = header.calculateCrc32();
|
||||||
|
|
||||||
auto rc = spi_flash_write(mBaseAddress, &header, sizeof(header));
|
auto rc = mPartition->write_raw(mBaseAddress, &header, sizeof(header));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return rc;
|
return rc;
|
||||||
@ -739,7 +745,7 @@ esp_err_t Page::alterEntryState(size_t index, EntryState state)
|
|||||||
mEntryTable.set(index, state);
|
mEntryTable.set(index, state);
|
||||||
size_t wordToWrite = mEntryTable.getWordIndex(index);
|
size_t wordToWrite = mEntryTable.getWordIndex(index);
|
||||||
uint32_t word = mEntryTable.data()[wordToWrite];
|
uint32_t word = mEntryTable.data()[wordToWrite];
|
||||||
auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordToWrite) * 4,
|
auto rc = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordToWrite) * 4,
|
||||||
&word, sizeof(word));
|
&word, sizeof(word));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
@ -763,7 +769,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state)
|
|||||||
}
|
}
|
||||||
if (nextWordIndex != wordIndex) {
|
if (nextWordIndex != wordIndex) {
|
||||||
uint32_t word = mEntryTable.data()[wordIndex];
|
uint32_t word = mEntryTable.data()[wordIndex];
|
||||||
auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordIndex) * 4,
|
auto rc = mPartition->write_raw(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordIndex) * 4,
|
||||||
&word, 4);
|
&word, 4);
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
@ -777,7 +783,7 @@ esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state)
|
|||||||
esp_err_t Page::alterPageState(PageState state)
|
esp_err_t Page::alterPageState(PageState state)
|
||||||
{
|
{
|
||||||
uint32_t state_val = static_cast<uint32_t>(state);
|
uint32_t state_val = static_cast<uint32_t>(state);
|
||||||
auto rc = spi_flash_write(mBaseAddress, &state_val, sizeof(state));
|
auto rc = mPartition->write_raw(mBaseAddress, &state_val, sizeof(state));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return rc;
|
return rc;
|
||||||
@ -788,7 +794,7 @@ esp_err_t Page::alterPageState(PageState state)
|
|||||||
|
|
||||||
esp_err_t Page::readEntry(size_t index, Item& dst) const
|
esp_err_t Page::readEntry(size_t index, Item& dst) const
|
||||||
{
|
{
|
||||||
auto rc = nvs_flash_read(getEntryAddress(index), &dst, sizeof(dst));
|
auto rc = mPartition->read(getEntryAddress(index), &dst, sizeof(dst));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -925,8 +931,7 @@ esp_err_t Page::setVersion(uint8_t ver)
|
|||||||
|
|
||||||
esp_err_t Page::erase()
|
esp_err_t Page::erase()
|
||||||
{
|
{
|
||||||
auto sector = mBaseAddress / SPI_FLASH_SEC_SIZE;
|
auto rc = mPartition->erase_range(mBaseAddress, SPI_FLASH_SEC_SIZE);
|
||||||
auto rc = spi_flash_erase_sector(sector);
|
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "compressed_enum_table.hpp"
|
#include "compressed_enum_table.hpp"
|
||||||
#include "intrusive_list.h"
|
#include "intrusive_list.h"
|
||||||
#include "nvs_item_hash_list.hpp"
|
#include "nvs_item_hash_list.hpp"
|
||||||
|
#include "partition.hpp"
|
||||||
|
|
||||||
namespace nvs
|
namespace nvs
|
||||||
{
|
{
|
||||||
@ -77,12 +78,14 @@ public:
|
|||||||
INVALID = 0
|
INVALID = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Page();
|
||||||
|
|
||||||
PageState state() const
|
PageState state() const
|
||||||
{
|
{
|
||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t load(uint32_t sectorNumber);
|
esp_err_t load(Partition *partition, uint32_t sectorNumber);
|
||||||
|
|
||||||
esp_err_t getSeqNumber(uint32_t& seqNumber) const;
|
esp_err_t getSeqNumber(uint32_t& seqNumber) const;
|
||||||
|
|
||||||
@ -223,6 +226,8 @@ protected:
|
|||||||
|
|
||||||
HashList mHashList;
|
HashList mHashList;
|
||||||
|
|
||||||
|
Partition *mPartition;
|
||||||
|
|
||||||
static const uint32_t HEADER_OFFSET = 0;
|
static const uint32_t HEADER_OFFSET = 0;
|
||||||
static const uint32_t ENTRY_TABLE_OFFSET = HEADER_OFFSET + 32;
|
static const uint32_t ENTRY_TABLE_OFFSET = HEADER_OFFSET + 32;
|
||||||
static const uint32_t ENTRY_DATA_OFFSET = ENTRY_TABLE_OFFSET + 32;
|
static const uint32_t ENTRY_DATA_OFFSET = ENTRY_TABLE_OFFSET + 32;
|
||||||
|
@ -15,8 +15,12 @@
|
|||||||
|
|
||||||
namespace nvs
|
namespace nvs
|
||||||
{
|
{
|
||||||
esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
esp_err_t PageManager::load(Partition *partition, uint32_t baseSector, uint32_t sectorCount)
|
||||||
{
|
{
|
||||||
|
if (partition == nullptr) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
mBaseSector = baseSector;
|
mBaseSector = baseSector;
|
||||||
mPageCount = sectorCount;
|
mPageCount = sectorCount;
|
||||||
mPageList.clear();
|
mPageList.clear();
|
||||||
@ -26,7 +30,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
|||||||
if (!mPages) return ESP_ERR_NO_MEM;
|
if (!mPages) return ESP_ERR_NO_MEM;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sectorCount; ++i) {
|
for (uint32_t i = 0; i < sectorCount; ++i) {
|
||||||
auto err = mPages[i].load(baseSector + i);
|
auto err = mPages[i].load(partition, baseSector + i);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -126,7 +130,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// partition should have at least one free page
|
// partition should have at least one free page
|
||||||
if (mFreePageList.size() == 0) {
|
if (mFreePageList.empty()) {
|
||||||
return ESP_ERR_NVS_NO_FREE_PAGES;
|
return ESP_ERR_NVS_NO_FREE_PAGES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include "nvs_types.hpp"
|
#include "nvs_types.hpp"
|
||||||
#include "nvs_page.hpp"
|
#include "nvs_page.hpp"
|
||||||
#include "nvs_pagemanager.hpp"
|
#include "partition.hpp"
|
||||||
#include "intrusive_list.h"
|
#include "intrusive_list.h"
|
||||||
|
|
||||||
namespace nvs
|
namespace nvs
|
||||||
@ -31,7 +31,7 @@ public:
|
|||||||
|
|
||||||
PageManager() {}
|
PageManager() {}
|
||||||
|
|
||||||
esp_err_t load(uint32_t baseSector, uint32_t sectorCount);
|
esp_err_t load(Partition *partition, uint32_t baseSector, uint32_t sectorCount);
|
||||||
|
|
||||||
TPageListIterator begin()
|
TPageListIterator begin()
|
||||||
{
|
{
|
||||||
|
78
components/nvs_flash/src/nvs_partition.cpp
Normal file
78
components/nvs_flash/src/nvs_partition.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// 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 "string.h"
|
||||||
|
#include "nvs_partition.hpp"
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
NVSPartition::NVSPartition(const esp_partition_t* partition)
|
||||||
|
: mESPPartition(partition)
|
||||||
|
{
|
||||||
|
// ensure the class is in a valid state
|
||||||
|
if (partition == nullptr) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *NVSPartition::get_partition_name()
|
||||||
|
{
|
||||||
|
return mESPPartition->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSPartition::read_raw(size_t src_offset, void* dst, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_read_raw(mESPPartition, src_offset, dst, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSPartition::read(size_t src_offset, void* dst, size_t size)
|
||||||
|
{
|
||||||
|
if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return esp_partition_read(mESPPartition, src_offset, dst, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSPartition::write_raw(size_t dst_offset, const void* src, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_write_raw(mESPPartition, dst_offset, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSPartition::write(size_t dst_offset, const void* src, size_t size)
|
||||||
|
{
|
||||||
|
if (size % ESP_ENCRYPT_BLOCK_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return esp_partition_write(mESPPartition, dst_offset, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t NVSPartition::erase_range(size_t dst_offset, size_t size)
|
||||||
|
{
|
||||||
|
return esp_partition_erase_range(mESPPartition, dst_offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NVSPartition::get_address()
|
||||||
|
{
|
||||||
|
return mESPPartition->address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NVSPartition::get_size()
|
||||||
|
{
|
||||||
|
return mESPPartition->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
116
components/nvs_flash/src/nvs_partition.hpp
Normal file
116
components/nvs_flash/src/nvs_partition.hpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef ESP_PARTITION_HPP_
|
||||||
|
#define ESP_PARTITION_HPP_
|
||||||
|
|
||||||
|
#include "esp_partition.h"
|
||||||
|
#include "intrusive_list.h"
|
||||||
|
#include "partition.hpp"
|
||||||
|
|
||||||
|
#define ESP_ENCRYPT_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
#define PART_NAME_MAX_SIZE 16 /*!< maximum length of partition name (excluding null terminator) */
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of Partition for NVS.
|
||||||
|
*
|
||||||
|
* It is implemented as an intrusive_list_node to easily store instances of it. NVSStorage and NVSPage take pointer
|
||||||
|
* references of this class to abstract their partition operations.
|
||||||
|
*/
|
||||||
|
class NVSPartition : public Partition, public intrusive_list_node<NVSPartition> {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Copy partition_name to mPartitionName and initialize mESPPartition.
|
||||||
|
*
|
||||||
|
* @param partition_name the name of the partition as in the partition table, must be non-NULL!
|
||||||
|
* @param partition an already initialized partition structure
|
||||||
|
*/
|
||||||
|
NVSPartition(const esp_partition_t* partition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No need to de-initialize mESPPartition here, if you used esp_partition_find_first.
|
||||||
|
* Otherwise, the user is responsible for de-initializing it.
|
||||||
|
*/
|
||||||
|
virtual ~NVSPartition() { }
|
||||||
|
|
||||||
|
const char *get_partition_name() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look into \c esp_partition_read_raw for more details.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - other error codes from the esp_partition API
|
||||||
|
*/
|
||||||
|
esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look into \c esp_partition_read for more details.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG if size isn't a multiple of ESP_ENCRYPT_BLOCK_SIZE
|
||||||
|
* - other error codes from the esp_partition API
|
||||||
|
*/
|
||||||
|
esp_err_t read(size_t src_offset, void* dst, size_t size) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look into \c esp_partition_write_raw for more details.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - error codes from the esp_partition API
|
||||||
|
*/
|
||||||
|
esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look into \c esp_partition_write for more details.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - ESP_ERR_INVALID_ARG if size isn't a multiple of ESP_ENCRYPT_BLOCK_SIZE
|
||||||
|
* - other error codes from the esp_partition API
|
||||||
|
*/
|
||||||
|
esp_err_t write(size_t dst_offset, const void* src, size_t size) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look into \c esp_partition_erase_range for more details.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK on success
|
||||||
|
* - error codes from the esp_partition API
|
||||||
|
*/
|
||||||
|
esp_err_t erase_range(size_t dst_offset, size_t size) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the base address of the partition.
|
||||||
|
*/
|
||||||
|
uint32_t get_address() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the size of the partition in bytes.
|
||||||
|
*/
|
||||||
|
uint32_t get_size() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const esp_partition_t* mESPPartition;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
||||||
|
#endif // ESP_PARTITION_HPP_
|
||||||
|
|
65
components/nvs_flash/src/nvs_partition_lookup.cpp
Normal file
65
components/nvs_flash/src/nvs_partition_lookup.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "esp_partition.h"
|
||||||
|
#include "nvs_partition_lookup.hpp"
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
|
#include "nvs_encrypted_partition.hpp"
|
||||||
|
#endif // CONFIG_NVS_ENCRYPTION
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
esp_err_t lookup_nvs_partition(const char* label, NVSPartition **p)
|
||||||
|
{
|
||||||
|
const esp_partition_t* esp_partition = esp_partition_find_first(
|
||||||
|
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, label);
|
||||||
|
|
||||||
|
if (esp_partition == nullptr) {
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_partition->encrypted) {
|
||||||
|
return ESP_ERR_NVS_WRONG_ENCRYPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
NVSPartition *partition = new (std::nothrow) NVSPartition(esp_partition);
|
||||||
|
if (partition == nullptr) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = partition;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
|
esp_err_t lookup_nvs_encrypted_partition(const char* label, nvs_sec_cfg_t* cfg, NVSPartition **p)
|
||||||
|
{
|
||||||
|
const esp_partition_t* esp_partition = esp_partition_find_first(
|
||||||
|
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, label);
|
||||||
|
|
||||||
|
if (esp_partition == nullptr) {
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_partition->encrypted) {
|
||||||
|
return ESP_ERR_NVS_WRONG_ENCRYPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
NVSEncryptedPartition *enc_p = new (std::nothrow) NVSEncryptedPartition(esp_partition);
|
||||||
|
if (enc_p == nullptr) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t result = enc_p->init(cfg);
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
delete enc_p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = enc_p;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_NVS_ENCRYPTION
|
||||||
|
|
||||||
|
} // nvs
|
18
components/nvs_flash/src/nvs_partition_lookup.hpp
Normal file
18
components/nvs_flash/src/nvs_partition_lookup.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include "esp_err.h"
|
||||||
|
#include "nvs_partition.hpp"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
#ifndef NVS_PARTITION_LOOKUP_HPP_
|
||||||
|
#define NVS_PARTITION_LOOKUP_HPP_
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
esp_err_t lookup_nvs_partition(const char* label, NVSPartition **p);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
|
esp_err_t lookup_nvs_encrypted_partition(const char* label, nvs_sec_cfg_t* cfg, NVSPartition **p);
|
||||||
|
#endif // CONFIG_NVS_ENCRYPTION
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
||||||
|
#endif // NVS_PARTITION_LOOKUP_HPP_
|
@ -13,6 +13,11 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
#include "nvs_partition_manager.hpp"
|
#include "nvs_partition_manager.hpp"
|
||||||
|
#include "nvs_partition_lookup.hpp"
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
|
#include "nvs_encrypted_partition.hpp"
|
||||||
|
#endif // CONFIG_NVS_ENCRYPTION
|
||||||
|
|
||||||
namespace nvs {
|
namespace nvs {
|
||||||
|
|
||||||
@ -30,6 +35,11 @@ NVSPartitionManager* NVSPartitionManager::get_instance()
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
esp_err_t NVSPartitionManager::init_partition(const char *partition_label)
|
esp_err_t NVSPartitionManager::init_partition(const char *partition_label)
|
||||||
{
|
{
|
||||||
|
if (strlen(partition_label) > NVS_PART_NAME_MAX_SIZE) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
Storage* mStorage;
|
Storage* mStorage;
|
||||||
|
|
||||||
mStorage = lookup_storage_from_name(partition_label);
|
mStorage = lookup_storage_from_name(partition_label);
|
||||||
@ -39,33 +49,55 @@ esp_err_t NVSPartitionManager::init_partition(const char *partition_label)
|
|||||||
|
|
||||||
assert(SPI_FLASH_SEC_SIZE != 0);
|
assert(SPI_FLASH_SEC_SIZE != 0);
|
||||||
|
|
||||||
const esp_partition_t* partition = esp_partition_find_first(
|
NVSPartition *p = nullptr;
|
||||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, partition_label);
|
esp_err_t result = lookup_nvs_partition(partition_label, &p);
|
||||||
if (partition == nullptr) {
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
if (result != ESP_OK) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return init_custom(partition_label, partition->address / SPI_FLASH_SEC_SIZE,
|
size = p->get_size();
|
||||||
partition->size / SPI_FLASH_SEC_SIZE);
|
|
||||||
|
result = init_custom(p, 0, size / SPI_FLASH_SEC_SIZE);
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_partition_list.push_back(p);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
delete p;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
#endif // ESP_PLATFORM
|
#endif // ESP_PLATFORM
|
||||||
|
|
||||||
esp_err_t NVSPartitionManager::init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount)
|
esp_err_t NVSPartitionManager::init_custom(Partition *partition, uint32_t baseSector, uint32_t sectorCount)
|
||||||
{
|
{
|
||||||
if (strlen(partName) > NVS_PART_NAME_MAX_SIZE) return ESP_ERR_INVALID_ARG;
|
Storage* new_storage = nullptr;
|
||||||
|
Storage* storage = lookup_storage_from_name(partition->get_partition_name());
|
||||||
|
if (storage == nullptr) {
|
||||||
|
new_storage = new (std::nothrow) Storage(partition);
|
||||||
|
|
||||||
Storage* new_storage = NULL;
|
if (new_storage == nullptr) {
|
||||||
Storage* storage = lookup_storage_from_name(partName);
|
return ESP_ERR_NO_MEM;
|
||||||
if (storage == NULL) {
|
}
|
||||||
new_storage = new (std::nothrow) Storage((const char *)partName);
|
|
||||||
|
|
||||||
if (!new_storage) return ESP_ERR_NO_MEM;
|
|
||||||
|
|
||||||
storage = new_storage;
|
storage = new_storage;
|
||||||
|
} else {
|
||||||
|
// if storage was initialized already, we don't need partition and hence delete it
|
||||||
|
for (auto it = nvs_partition_list.begin(); it != nvs_partition_list.end(); ++it) {
|
||||||
|
if (partition == it) {
|
||||||
|
nvs_partition_list.erase(it);
|
||||||
|
delete partition;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t err = storage->init(baseSector, sectorCount);
|
esp_err_t err = storage->init(baseSector, sectorCount);
|
||||||
if (new_storage != NULL) {
|
if (new_storage != nullptr) {
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
nvs_storage_list.push_back(new_storage);
|
nvs_storage_list.push_back(new_storage);
|
||||||
} else {
|
} else {
|
||||||
@ -75,41 +107,47 @@ esp_err_t NVSPartitionManager::init_custom(const char *partName, uint32_t baseSe
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
esp_err_t NVSPartitionManager::secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg)
|
esp_err_t NVSPartitionManager::secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg)
|
||||||
{
|
{
|
||||||
|
if (strlen(part_name) > NVS_PART_NAME_MAX_SIZE) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
Storage* mStorage;
|
Storage* mStorage;
|
||||||
|
|
||||||
mStorage = lookup_storage_from_name(part_name);
|
mStorage = lookup_storage_from_name(part_name);
|
||||||
if (mStorage) {
|
if (mStorage != nullptr) {
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
const esp_partition_t* partition = esp_partition_find_first(
|
NVSPartition *p;
|
||||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
|
esp_err_t result;
|
||||||
if (partition == NULL) {
|
if (cfg != nullptr) {
|
||||||
return ESP_ERR_NOT_FOUND;
|
result = lookup_nvs_encrypted_partition(part_name, cfg, &p);
|
||||||
|
} else {
|
||||||
|
result = lookup_nvs_partition(part_name, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
|
if (result != ESP_OK) {
|
||||||
partition->size / SPI_FLASH_SEC_SIZE, cfg);
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t NVSPartitionManager::secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg)
|
|
||||||
{
|
|
||||||
if(cfg) {
|
|
||||||
auto encrMgr = EncrMgr::getInstance();
|
|
||||||
auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg);
|
|
||||||
if(err != ESP_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return init_custom(partName, baseSector, sectorCount);
|
uint32_t size = p->get_size();
|
||||||
|
|
||||||
|
result = init_custom(p, 0, size / SPI_FLASH_SEC_SIZE);
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
delete p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_partition_list.push_back(p);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
#endif // CONFIG_NVS_ENCRYPTION
|
|
||||||
#endif // ESP_PLATFORM
|
#endif // ESP_PLATFORM
|
||||||
|
#endif // CONFIG_NVS_ENCRYPTION
|
||||||
|
|
||||||
esp_err_t NVSPartitionManager::deinit_partition(const char *partition_label)
|
esp_err_t NVSPartitionManager::deinit_partition(const char *partition_label)
|
||||||
{
|
{
|
||||||
@ -118,13 +156,6 @@ esp_err_t NVSPartitionManager::deinit_partition(const char *partition_label)
|
|||||||
return ESP_ERR_NVS_NOT_INITIALIZED;
|
return ESP_ERR_NVS_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
|
||||||
if(EncrMgr::isEncrActive()) {
|
|
||||||
auto encrMgr = EncrMgr::getInstance();
|
|
||||||
encrMgr->removeSecurityContext(storage->getBaseSector());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Clean up handles related to the storage being deinitialized */
|
/* Clean up handles related to the storage being deinitialized */
|
||||||
for (auto it = nvs_handles.begin(); it != nvs_handles.end(); ++it) {
|
for (auto it = nvs_handles.begin(); it != nvs_handles.end(); ++it) {
|
||||||
if (it->mStoragePtr == storage) {
|
if (it->mStoragePtr == storage) {
|
||||||
@ -133,10 +164,19 @@ esp_err_t NVSPartitionManager::deinit_partition(const char *partition_label)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally delete the storage itself */
|
/* Finally delete the storage and its partition */
|
||||||
nvs_storage_list.erase(storage);
|
nvs_storage_list.erase(storage);
|
||||||
delete storage;
|
delete storage;
|
||||||
|
|
||||||
|
for (auto it = nvs_partition_list.begin(); it != nvs_partition_list.end(); ++it) {
|
||||||
|
if (strcmp(it->get_partition_name(), partition_label) == 0) {
|
||||||
|
NVSPartition *p = it;
|
||||||
|
nvs_partition_list.erase(it);
|
||||||
|
delete p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,12 +188,12 @@ esp_err_t NVSPartitionManager::open_handle(const char *part_name,
|
|||||||
uint8_t nsIndex;
|
uint8_t nsIndex;
|
||||||
Storage* sHandle;
|
Storage* sHandle;
|
||||||
|
|
||||||
if (nvs_storage_list.size() == 0) {
|
if (nvs_storage_list.empty()) {
|
||||||
return ESP_ERR_NVS_NOT_INITIALIZED;
|
return ESP_ERR_NVS_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sHandle = lookup_storage_from_name(part_name);
|
sHandle = lookup_storage_from_name(part_name);
|
||||||
if (sHandle == NULL) {
|
if (sHandle == nullptr) {
|
||||||
return ESP_ERR_NVS_PART_NOT_FOUND;
|
return ESP_ERR_NVS_PART_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +204,9 @@ esp_err_t NVSPartitionManager::open_handle(const char *part_name,
|
|||||||
|
|
||||||
*handle = new (std::nothrow) NVSHandleSimple(open_mode==NVS_READONLY, nsIndex, sHandle);
|
*handle = new (std::nothrow) NVSHandleSimple(open_mode==NVS_READONLY, nsIndex, sHandle);
|
||||||
|
|
||||||
if (!handle) return ESP_ERR_NO_MEM;
|
if (handle == nullptr) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
nvs_handles.push_back(*handle);
|
nvs_handles.push_back(*handle);
|
||||||
|
|
||||||
@ -194,7 +236,7 @@ Storage* NVSPartitionManager::lookup_storage_from_name(const char* name)
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (it == end(nvs_storage_list)) {
|
if (it == end(nvs_storage_list)) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
#include "nvs_handle_simple.hpp"
|
#include "nvs_handle_simple.hpp"
|
||||||
#include "nvs_storage.hpp"
|
#include "nvs_storage.hpp"
|
||||||
|
#include "nvs_partition.hpp"
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
#include "nvs_flash.h"
|
||||||
#include "nvs_encr.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nvs {
|
namespace nvs {
|
||||||
|
|
||||||
@ -31,12 +29,10 @@ public:
|
|||||||
|
|
||||||
esp_err_t init_partition(const char *partition_label);
|
esp_err_t init_partition(const char *partition_label);
|
||||||
|
|
||||||
esp_err_t init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
|
esp_err_t init_custom(Partition *partition, uint32_t baseSector, uint32_t sectorCount);
|
||||||
|
|
||||||
#ifdef CONFIG_NVS_ENCRYPTION
|
#ifdef CONFIG_NVS_ENCRYPTION
|
||||||
esp_err_t secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg);
|
esp_err_t secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg);
|
||||||
|
|
||||||
esp_err_t secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
esp_err_t deinit_partition(const char *partition_label);
|
esp_err_t deinit_partition(const char *partition_label);
|
||||||
@ -57,6 +53,8 @@ protected:
|
|||||||
intrusive_list<NVSHandleSimple> nvs_handles;
|
intrusive_list<NVSHandleSimple> nvs_handles;
|
||||||
|
|
||||||
intrusive_list<nvs::Storage> nvs_storage_list;
|
intrusive_list<nvs::Storage> nvs_storage_list;
|
||||||
|
|
||||||
|
intrusive_list<nvs::NVSPartition> nvs_partition_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // nvs
|
} // nvs
|
||||||
|
@ -90,7 +90,7 @@ void Storage::eraseOrphanDataBlobs(TBlobIndexList& blobIdxList)
|
|||||||
|
|
||||||
esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
|
esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
|
||||||
{
|
{
|
||||||
auto err = mPageManager.load(baseSector, sectorCount);
|
auto err = mPageManager.load(mPartition, baseSector, sectorCount);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
mState = StorageState::INVALID;
|
mState = StorageState::INVALID;
|
||||||
return err;
|
return err;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "nvs_types.hpp"
|
#include "nvs_types.hpp"
|
||||||
#include "nvs_page.hpp"
|
#include "nvs_page.hpp"
|
||||||
#include "nvs_pagemanager.hpp"
|
#include "nvs_pagemanager.hpp"
|
||||||
|
#include "partition.hpp"
|
||||||
|
|
||||||
//extern void dumpBytes(const uint8_t* data, size_t count);
|
//extern void dumpBytes(const uint8_t* data, size_t count);
|
||||||
|
|
||||||
@ -60,9 +61,10 @@ class Storage : public intrusive_list_node<Storage>
|
|||||||
public:
|
public:
|
||||||
~Storage();
|
~Storage();
|
||||||
|
|
||||||
Storage(const char *pName = NVS_DEFAULT_PART_NAME)
|
Storage(Partition *partition) : mPartition(partition) {
|
||||||
{
|
if (partition == nullptr) {
|
||||||
strncpy(mPartitionName, pName, NVS_PART_NAME_MAX_SIZE);
|
abort();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t init(uint32_t baseSector, uint32_t sectorCount);
|
esp_err_t init(uint32_t baseSector, uint32_t sectorCount);
|
||||||
@ -98,10 +100,16 @@ public:
|
|||||||
|
|
||||||
esp_err_t eraseNamespace(uint8_t nsIndex);
|
esp_err_t eraseNamespace(uint8_t nsIndex);
|
||||||
|
|
||||||
|
const Partition *getPart() const
|
||||||
|
{
|
||||||
|
return mPartition;
|
||||||
|
}
|
||||||
|
|
||||||
const char *getPartName() const
|
const char *getPartName() const
|
||||||
{
|
{
|
||||||
return mPartitionName;
|
return mPartition->get_partition_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getBaseSector()
|
uint32_t getBaseSector()
|
||||||
{
|
{
|
||||||
return mPageManager.getBaseSector();
|
return mPageManager.getBaseSector();
|
||||||
@ -145,7 +153,7 @@ protected:
|
|||||||
esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item, uint8_t chunkIdx = Page::CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY);
|
esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item, uint8_t chunkIdx = Page::CHUNK_ANY, VerOffset chunkStart = VerOffset::VER_ANY);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char mPartitionName [NVS_PART_NAME_MAX_SIZE + 1];
|
Partition *mPartition;
|
||||||
size_t mPageCount;
|
size_t mPageCount;
|
||||||
PageManager mPageManager;
|
PageManager mPageManager;
|
||||||
TNamespaces mNamespaces;
|
TNamespaces mNamespaces;
|
||||||
|
60
components/nvs_flash/src/partition.hpp
Normal file
60
components/nvs_flash/src/partition.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef PARTITION_HPP_
|
||||||
|
#define PARTITION_HPP_
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
namespace nvs {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Abstract interface for partition related operations, currently in NVS.
|
||||||
|
*
|
||||||
|
* It resembles the main operations according to esp_partition.h.
|
||||||
|
*/
|
||||||
|
class Partition {
|
||||||
|
public:
|
||||||
|
virtual ~Partition() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the partition name as in the partition table.
|
||||||
|
*/
|
||||||
|
virtual const char *get_partition_name() = 0;
|
||||||
|
|
||||||
|
virtual esp_err_t read_raw(size_t src_offset, void* dst, size_t size) = 0;
|
||||||
|
|
||||||
|
virtual esp_err_t read(size_t src_offset, void* dst, size_t size) = 0;
|
||||||
|
|
||||||
|
virtual esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) = 0;
|
||||||
|
|
||||||
|
virtual esp_err_t write(size_t dst_offset, const void* src, size_t size) = 0;
|
||||||
|
|
||||||
|
virtual esp_err_t erase_range(size_t dst_offset, size_t size) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address of the beginning of the partition.
|
||||||
|
*/
|
||||||
|
virtual uint32_t get_address() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the partition size in bytes.
|
||||||
|
*/
|
||||||
|
virtual uint32_t get_size() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // nvs
|
||||||
|
|
||||||
|
#endif // PARTITION_HPP_
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
idf_component_register(SRC_DIRS "."
|
idf_component_register(SRC_DIRS "."
|
||||||
PRIV_INCLUDE_DIRS "."
|
PRIV_INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES cmock test_utils nvs_flash bootloader_support)
|
PRIV_REQUIRES cmock test_utils nvs_flash bootloader_support
|
||||||
|
EMBED_TXTFILES encryption_keys.bin partition_encrypted.bin sample.bin)
|
||||||
|
@ -18,6 +18,15 @@
|
|||||||
|
|
||||||
static const char* TAG = "test_nvs";
|
static const char* TAG = "test_nvs";
|
||||||
|
|
||||||
|
TEST_CASE("Partition name no longer than 16 characters", "[nvs]")
|
||||||
|
{
|
||||||
|
const char *TOO_LONG_NAME = "0123456789abcdefg";
|
||||||
|
|
||||||
|
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, nvs_flash_init_partition(TOO_LONG_NAME));
|
||||||
|
|
||||||
|
nvs_flash_deinit_partition(TOO_LONG_NAME); // just in case
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("flash erase deinitializes initialized partition", "[nvs]")
|
TEST_CASE("flash erase deinitializes initialized partition", "[nvs]")
|
||||||
{
|
{
|
||||||
nvs_handle_t handle;
|
nvs_handle_t handle;
|
||||||
@ -26,7 +35,7 @@ TEST_CASE("flash erase deinitializes initialized partition", "[nvs]")
|
|||||||
nvs_flash_erase();
|
nvs_flash_erase();
|
||||||
err = nvs_flash_init();
|
err = nvs_flash_init();
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK( err );
|
TEST_ESP_OK( err );
|
||||||
|
|
||||||
TEST_ESP_OK(nvs_flash_init());
|
TEST_ESP_OK(nvs_flash_init());
|
||||||
TEST_ESP_OK(nvs_open("uninit_ns", NVS_READWRITE, &handle));
|
TEST_ESP_OK(nvs_open("uninit_ns", NVS_READWRITE, &handle));
|
||||||
@ -468,7 +477,7 @@ TEST_CASE("test nvs apis for nvs partition generator utility with encryption ena
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nvs_part->size; i+= SPI_FLASH_SEC_SIZE) {
|
for (int i = 0; i < nvs_part->size; i+= SPI_FLASH_SEC_SIZE) {
|
||||||
ESP_ERROR_CHECK( spi_flash_write(nvs_part->address + i, nvs_data_start + i, SPI_FLASH_SEC_SIZE) );
|
ESP_ERROR_CHECK( esp_partition_write(nvs_part, i, nvs_data_start + i, SPI_FLASH_SEC_SIZE) );
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t err = nvs_flash_read_security_cfg(key_part, &xts_cfg);
|
esp_err_t err = nvs_flash_read_security_cfg(key_part, &xts_cfg);
|
||||||
|
@ -10,11 +10,11 @@ SOURCE_FILES = \
|
|||||||
nvs_pagemanager.cpp \
|
nvs_pagemanager.cpp \
|
||||||
nvs_storage.cpp \
|
nvs_storage.cpp \
|
||||||
nvs_item_hash_list.cpp \
|
nvs_item_hash_list.cpp \
|
||||||
nvs_encr.cpp \
|
|
||||||
nvs_ops.cpp \
|
|
||||||
nvs_handle_simple.cpp \
|
nvs_handle_simple.cpp \
|
||||||
nvs_handle_locked.cpp \
|
nvs_handle_locked.cpp \
|
||||||
nvs_partition_manager.cpp \
|
nvs_partition_manager.cpp \
|
||||||
|
nvs_partition.cpp \
|
||||||
|
nvs_encrypted_partition.cpp \
|
||||||
nvs_cxx_api.cpp \
|
nvs_cxx_api.cpp \
|
||||||
) \
|
) \
|
||||||
spi_flash_emulation.cpp \
|
spi_flash_emulation.cpp \
|
||||||
@ -25,6 +25,7 @@ SOURCE_FILES = \
|
|||||||
test_partition_manager.cpp \
|
test_partition_manager.cpp \
|
||||||
test_nvs_handle.cpp \
|
test_nvs_handle.cpp \
|
||||||
test_nvs_storage.cpp \
|
test_nvs_storage.cpp \
|
||||||
|
test_nvs_partition.cpp \
|
||||||
test_nvs_cxx_api.cpp \
|
test_nvs_cxx_api.cpp \
|
||||||
test_nvs_initialization.cpp \
|
test_nvs_initialization.cpp \
|
||||||
crc.cpp \
|
crc.cpp \
|
||||||
@ -36,7 +37,7 @@ else
|
|||||||
COMPILER := gcc
|
COMPILER := gcc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPFLAGS += -I../include -I../src -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage
|
CPPFLAGS += -I../include -I../src -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb
|
||||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||||
CXXFLAGS += -std=c++11 -Wall -Werror
|
CXXFLAGS += -std=c++11 -Wall -Werror
|
||||||
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
||||||
@ -89,6 +90,8 @@ clean: clean-coverage
|
|||||||
rm -f ../nvs_partition_generator/partition_encrypted.bin
|
rm -f ../nvs_partition_generator/partition_encrypted.bin
|
||||||
rm -f ../nvs_partition_generator/partition_encrypted_using_keygen.bin
|
rm -f ../nvs_partition_generator/partition_encrypted_using_keygen.bin
|
||||||
rm -f ../nvs_partition_generator/partition_encrypted_using_keyfile.bin
|
rm -f ../nvs_partition_generator/partition_encrypted_using_keyfile.bin
|
||||||
|
rm -f ../nvs_partition_generator/partition_decrypted.bin
|
||||||
|
rm -f ../nvs_partition_generator/partition_encoded.bin
|
||||||
rm -f ../nvs_partition_generator/Test-1-partition-encrypted.bin
|
rm -f ../nvs_partition_generator/Test-1-partition-encrypted.bin
|
||||||
rm -f ../nvs_partition_generator/Test-1-partition.bin
|
rm -f ../nvs_partition_generator/Test-1-partition.bin
|
||||||
rm -f ../../../tools/mass_mfg/samples/sample_values_multipage_blob_created.csv
|
rm -f ../../../tools/mass_mfg/samples/sample_values_multipage_blob_created.csv
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
#include "esp_spi_flash.h"
|
#include "esp_partition.h"
|
||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
|
|
||||||
|
|
||||||
@ -22,39 +22,82 @@ void spi_flash_emulator_set(SpiFlashEmulator* e)
|
|||||||
s_emulator = e;
|
s_emulator = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_erase_sector(size_t sec)
|
esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
|
||||||
|
size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
if (!s_emulator) {
|
if (!s_emulator) {
|
||||||
return ESP_ERR_FLASH_OP_TIMEOUT;
|
return ESP_ERR_FLASH_OP_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_emulator->erase(sec)) {
|
if (size % SPI_FLASH_SEC_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset % SPI_FLASH_SEC_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start_sector = offset / SPI_FLASH_SEC_SIZE;
|
||||||
|
size_t num_sectors = size / SPI_FLASH_SEC_SIZE;
|
||||||
|
for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) {
|
||||||
|
if (!s_emulator->erase(sector)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_partition_read(const esp_partition_t* partition,
|
||||||
|
size_t src_offset, void* dst, size_t size)
|
||||||
|
{
|
||||||
|
if (!s_emulator) {
|
||||||
|
return ESP_ERR_FLASH_OP_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_emulator->read(reinterpret_cast<uint32_t*>(dst), src_offset, size)) {
|
||||||
return ESP_ERR_FLASH_OP_FAIL;
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_write(size_t des_addr, const void *src_addr, size_t size)
|
esp_err_t esp_partition_read_raw(const esp_partition_t* partition,
|
||||||
|
size_t src_offset, void* dst, size_t size)
|
||||||
{
|
{
|
||||||
if (!s_emulator) {
|
if (!s_emulator) {
|
||||||
return ESP_ERR_FLASH_OP_TIMEOUT;
|
return ESP_ERR_FLASH_OP_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_emulator->write(des_addr, reinterpret_cast<const uint32_t*>(src_addr), size)) {
|
if (!s_emulator->read(reinterpret_cast<uint32_t*>(dst), src_offset, size)) {
|
||||||
return ESP_ERR_FLASH_OP_FAIL;
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_read(size_t src_addr, void *des_addr, size_t size)
|
esp_err_t esp_partition_write(const esp_partition_t* partition,
|
||||||
|
size_t dst_offset, const void* src, size_t size)
|
||||||
{
|
{
|
||||||
if (!s_emulator) {
|
if (!s_emulator) {
|
||||||
return ESP_ERR_FLASH_OP_TIMEOUT;
|
return ESP_ERR_FLASH_OP_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_emulator->read(reinterpret_cast<uint32_t*>(des_addr), src_addr, size)) {
|
if (!s_emulator->write(dst_offset, reinterpret_cast<const uint32_t*>(src), size)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
|
||||||
|
size_t dst_offset, const void* src, size_t size)
|
||||||
|
{
|
||||||
|
if (!s_emulator) {
|
||||||
|
return ESP_ERR_FLASH_OP_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_emulator->write(dst_offset, reinterpret_cast<const uint32_t*>(src), size)) {
|
||||||
return ESP_ERR_FLASH_OP_FAIL;
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
149
components/nvs_flash/test_nvs_host/test_fixtures.hpp
Normal file
149
components/nvs_flash/test_nvs_host/test_fixtures.hpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// 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 "nvs_partition.hpp"
|
||||||
|
#include "nvs_encrypted_partition.hpp"
|
||||||
|
#include "spi_flash_emulation.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
|
||||||
|
class PartitionEmulation : public nvs::Partition {
|
||||||
|
public:
|
||||||
|
PartitionEmulation(SpiFlashEmulator *spi_flash_emulator,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t size,
|
||||||
|
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||||
|
: partition_name(partition_name), flash_emu(spi_flash_emulator), address(address), size(size)
|
||||||
|
{
|
||||||
|
assert(partition_name);
|
||||||
|
assert(flash_emu);
|
||||||
|
assert(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_partition_name() override
|
||||||
|
{
|
||||||
|
return partition_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override
|
||||||
|
{
|
||||||
|
if (!flash_emu->read(reinterpret_cast<uint32_t*>(dst), src_offset, size)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t read(size_t src_offset, void* dst, size_t size) override
|
||||||
|
{
|
||||||
|
if (!flash_emu->read(reinterpret_cast<uint32_t*>(dst), src_offset, size)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override
|
||||||
|
{
|
||||||
|
if (!flash_emu->write(dst_offset, reinterpret_cast<const uint32_t*>(src), size)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t write(size_t dst_offset, const void* src, size_t size) override
|
||||||
|
{
|
||||||
|
if (!flash_emu->write(dst_offset, reinterpret_cast<const uint32_t*>(src), size)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t erase_range(size_t dst_offset, size_t size) override
|
||||||
|
{
|
||||||
|
if (size % SPI_FLASH_SEC_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst_offset % SPI_FLASH_SEC_SIZE != 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start_sector = dst_offset / SPI_FLASH_SEC_SIZE;
|
||||||
|
size_t num_sectors = size / SPI_FLASH_SEC_SIZE;
|
||||||
|
for (size_t sector = start_sector; sector < (start_sector + num_sectors); sector++) {
|
||||||
|
if (!flash_emu->erase(sector)) {
|
||||||
|
return ESP_ERR_FLASH_OP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_address() override
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_size() override
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *partition_name;
|
||||||
|
|
||||||
|
SpiFlashEmulator *flash_emu;
|
||||||
|
|
||||||
|
uint32_t address;
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PartitionEmulationFixture {
|
||||||
|
PartitionEmulationFixture(uint32_t start_sector = 0,
|
||||||
|
uint32_t sector_size = 1,
|
||||||
|
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||||
|
: emu(start_sector + sector_size),
|
||||||
|
part(&emu, start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE, partition_name) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~PartitionEmulationFixture() { }
|
||||||
|
|
||||||
|
SpiFlashEmulator emu;
|
||||||
|
|
||||||
|
PartitionEmulation part;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EncryptedPartitionFixture {
|
||||||
|
EncryptedPartitionFixture(nvs_sec_cfg_t *cfg,
|
||||||
|
uint32_t start_sector = 0,
|
||||||
|
uint32_t sector_size = 1,
|
||||||
|
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||||
|
: esp_partition(), emu(start_sector + sector_size),
|
||||||
|
part(&esp_partition) {
|
||||||
|
esp_partition.address = start_sector * SPI_FLASH_SEC_SIZE;
|
||||||
|
esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE;
|
||||||
|
strncpy(esp_partition.label, partition_name, PART_NAME_MAX_SIZE);
|
||||||
|
assert(part.init(cfg) == ESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
~EncryptedPartitionFixture() { }
|
||||||
|
|
||||||
|
esp_partition_t esp_partition;
|
||||||
|
|
||||||
|
SpiFlashEmulator emu;
|
||||||
|
|
||||||
|
nvs::NVSEncryptedPartition part;
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,8 @@
|
|||||||
#include "nvs_partition_manager.hpp"
|
#include "nvs_partition_manager.hpp"
|
||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
|
|
||||||
|
#include "test_fixtures.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -27,12 +29,12 @@ TEST_CASE("NVSHandleSimple CXX api open invalid arguments", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->
|
||||||
init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
||||||
|
|
||||||
handle = nvs::open_nvs_handle_from_partition(nullptr, "ns_1", NVS_READWRITE, &result);
|
handle = nvs::open_nvs_handle_from_partition(nullptr, "ns_1", NVS_READWRITE, &result);
|
||||||
CHECK(result == ESP_ERR_INVALID_ARG);
|
CHECK(result == ESP_ERR_INVALID_ARG);
|
||||||
@ -61,11 +63,11 @@ TEST_CASE("NVSHandleSimple CXX api open successful", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -87,11 +89,11 @@ TEST_CASE("NVSHandleSimple CXX api open default part successful", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom("nvs", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -113,11 +115,11 @@ TEST_CASE("NVSHandleSimple CXX api open default part ns NULL", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom("nvs", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -135,12 +137,12 @@ TEST_CASE("NVSHandleSimple CXX api read/write string", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
char read_buffer [256];
|
char read_buffer [256];
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom("nvs", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -164,13 +166,13 @@ TEST_CASE("NVSHandleSimple CXX api read/write blob", "[nvs cxx]")
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
const char blob [6] = {15, 16, 17, 18, 19};
|
const char blob [6] = {15, 16, 17, 18, 19};
|
||||||
char read_blob[6] = {0};
|
char read_blob[6] = {0};
|
||||||
esp_err_t result;
|
esp_err_t result;
|
||||||
shared_ptr<nvs::NVSHandle> handle;
|
shared_ptr<nvs::NVSHandle> handle;
|
||||||
|
|
||||||
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom("nvs", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(nvs::NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(nvs::NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include "nvs_partition_manager.hpp"
|
#include "nvs_partition_manager.hpp"
|
||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
|
|
||||||
|
#include "test_fixtures.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -29,9 +31,9 @@ TEST_CASE("NVSHandleSimple closes its reference in PartitionManager", "[partitio
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -53,9 +55,9 @@ TEST_CASE("NVSHandleSimple multiple open and closes with PartitionManager", "[pa
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
@ -83,18 +85,18 @@ TEST_CASE("NVSHandleSimple multiple open and closes with PartitionManager", "[pa
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("nvshandle readonly fails", "[partition_mgr]")
|
TEST_CASE("NVSHandleSimple readonly fails", "[partition_mgr]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME);
|
NVSPartitionManager::get_instance()->deinit_partition(NVS_DEFAULT_PART_NAME);
|
||||||
NVSHandleSimple *handle_1;
|
NVSHandleSimple *handle_1;
|
||||||
NVSHandleSimple *handle_2;
|
NVSHandleSimple *handle_2;
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
CHECK(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
CHECK(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
||||||
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
CHECK(NVSPartitionManager::get_instance()->open_handles_size() == 0);
|
||||||
|
|
||||||
// first, creating namespace...
|
// first, creating namespace...
|
||||||
@ -123,13 +125,13 @@ TEST_CASE("NVSHandleSimple set/get char", "[partition_mgr]")
|
|||||||
BAR
|
BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
@ -155,13 +157,13 @@ TEST_CASE("NVSHandleSimple correctly sets/gets int enum", "[partition_mgr]")
|
|||||||
BAR
|
BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
@ -188,13 +190,13 @@ TEST_CASE("NVSHandleSimple correctly sets/gets int enum with negative values", "
|
|||||||
BAR
|
BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
@ -220,13 +222,13 @@ TEST_CASE("NVSHandleSimple correctly sets/gets uint8_t enum", "[partition_mgr]")
|
|||||||
BAR
|
BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
@ -253,13 +255,13 @@ TEST_CASE("NVSHandleSimple correctly sets/gets char enum", "[partition_mgr]")
|
|||||||
BAR
|
BAR
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10);
|
||||||
|
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
f.emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
|
55
components/nvs_flash/test_nvs_host/test_nvs_partition.cpp
Normal file
55
components/nvs_flash/test_nvs_host/test_nvs_partition.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// 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 "catch.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include "nvs_test_api.h"
|
||||||
|
#include "nvs_handle_simple.hpp"
|
||||||
|
#include "nvs_partition.hpp"
|
||||||
|
#include "spi_flash_emulation.h"
|
||||||
|
|
||||||
|
#include "test_fixtures.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace nvs;
|
||||||
|
|
||||||
|
TEST_CASE("encrypted partition read size must be item size", "[nvs]")
|
||||||
|
{
|
||||||
|
char foo [32] = { };
|
||||||
|
nvs_sec_cfg_t xts_cfg;
|
||||||
|
for(int count = 0; count < NVS_KEY_SIZE; count++) {
|
||||||
|
xts_cfg.eky[count] = 0x11;
|
||||||
|
xts_cfg.tky[count] = 0x22;
|
||||||
|
}
|
||||||
|
EncryptedPartitionFixture fix(&xts_cfg);
|
||||||
|
|
||||||
|
CHECK(fix.part.read(0, foo, sizeof (foo) -1) == ESP_ERR_INVALID_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("encrypted partition write size must be mod item size", "[nvs]")
|
||||||
|
{
|
||||||
|
char foo [64] = { };
|
||||||
|
nvs_sec_cfg_t xts_cfg;
|
||||||
|
for(int count = 0; count < NVS_KEY_SIZE; count++) {
|
||||||
|
xts_cfg.eky[count] = 0x11;
|
||||||
|
xts_cfg.tky[count] = 0x22;
|
||||||
|
}
|
||||||
|
EncryptedPartitionFixture fix(&xts_cfg);
|
||||||
|
|
||||||
|
CHECK(fix.part.write(0, foo, sizeof (foo) -1) == ESP_ERR_INVALID_SIZE);
|
||||||
|
CHECK(fix.part.write(0, foo, sizeof (foo)) == ESP_OK);
|
||||||
|
CHECK(fix.part.write(0, foo, sizeof (foo) * 2) == ESP_OK);
|
||||||
|
}
|
@ -18,6 +18,8 @@
|
|||||||
#include "nvs_partition_manager.hpp"
|
#include "nvs_partition_manager.hpp"
|
||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
|
|
||||||
|
#include "test_fixtures.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -27,9 +29,9 @@ TEST_CASE("Storage iterator recognizes blob with VerOffset::VER_1_OFFSET", "[nvs
|
|||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
uint8_t blob [] = {0x0, 0x1, 0x2, 0x3};
|
uint8_t blob [] = {0x0, 0x1, 0x2, 0x3};
|
||||||
|
@ -20,25 +20,28 @@
|
|||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
#include "nvs_test_api.h"
|
#include "nvs_test_api.h"
|
||||||
|
|
||||||
|
#include "test_fixtures.hpp"
|
||||||
|
|
||||||
using namespace nvs;
|
using namespace nvs;
|
||||||
|
|
||||||
TEST_CASE("Partition manager initializes storage", "[partition_mgr]")
|
TEST_CASE("Partition manager initializes storage", "[partition_mgr]")
|
||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
||||||
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr);
|
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr);
|
||||||
|
REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(f.part.get_partition_name()) == ESP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Partition manager de-initializes storage", "[partition_mgr]")
|
TEST_CASE("Partition manager de-initializes storage", "[partition_mgr]")
|
||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN) == ESP_OK);
|
||||||
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr);
|
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") != nullptr);
|
||||||
CHECK(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK);
|
CHECK(NVSPartitionManager::get_instance()->deinit_partition("test") == ESP_OK);
|
||||||
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") == nullptr);
|
CHECK(NVSPartitionManager::get_instance()->lookup_storage_from_name("test") == nullptr);
|
||||||
@ -49,11 +52,13 @@ TEST_CASE("Partition manager initializes multiple partitions", "[partition_mgr]"
|
|||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
SpiFlashEmulator emu(10);
|
||||||
|
PartitionEmulation part_0(&emu, NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE, "test1");
|
||||||
|
PartitionEmulation part_1(&emu, NVS_FLASH_SECTOR * SPI_FLASH_SEC_SIZE, NVS_FLASH_SECTOR_COUNT_MIN * SPI_FLASH_SEC_SIZE, "test2");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test1", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&part_0, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
// TODO: why does this work, actually? same sectors used as above
|
// TODO: why does this work, actually? same sectors used as above
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test2", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&part_1, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
Storage *storage1 = NVSPartitionManager::get_instance()->lookup_storage_from_name("test1");
|
Storage *storage1 = NVSPartitionManager::get_instance()->lookup_storage_from_name("test1");
|
||||||
REQUIRE(storage1 != nullptr);
|
REQUIRE(storage1 != nullptr);
|
||||||
@ -61,15 +66,17 @@ TEST_CASE("Partition manager initializes multiple partitions", "[partition_mgr]"
|
|||||||
REQUIRE(storage2 != nullptr);
|
REQUIRE(storage2 != nullptr);
|
||||||
|
|
||||||
CHECK(storage1 != storage2);
|
CHECK(storage1 != storage2);
|
||||||
|
REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(part_0.get_partition_name()) == ESP_OK);
|
||||||
|
REQUIRE(NVSPartitionManager::get_instance()->deinit_partition(part_1.get_partition_name()) == ESP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Partition manager invalidates handle on partition de-init", "[partition_mgr]")
|
TEST_CASE("Partition manager invalidates handle on partition de-init", "[partition_mgr]")
|
||||||
{
|
{
|
||||||
const uint32_t NVS_FLASH_SECTOR = 6;
|
const uint32_t NVS_FLASH_SECTOR = 6;
|
||||||
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
|
||||||
SpiFlashEmulator emu(10);
|
PartitionEmulationFixture f(0, 10, "test");
|
||||||
|
|
||||||
REQUIRE(NVSPartitionManager::get_instance()->init_custom("test", NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
REQUIRE(NVSPartitionManager::get_instance()->init_custom(&f.part, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
|
||||||
== ESP_OK);
|
== ESP_OK);
|
||||||
|
|
||||||
NVSHandleSimple *handle;
|
NVSHandleSimple *handle;
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
#include <functional>
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include "esp_spi_flash.h"
|
#include "esp_spi_flash.h"
|
||||||
|
#include "esp_partition.h"
|
||||||
#include "spi_flash_emulation.h"
|
#include "spi_flash_emulation.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@ -25,14 +25,21 @@ bool range_empty_n(Tit it_begin, size_t n)
|
|||||||
return all_of(it_begin, it_begin + n, bind(equal_to<uint32_t>(), placeholders::_1, 0xffffffff));
|
return all_of(it_begin, it_begin + n, bind(equal_to<uint32_t>(), placeholders::_1, 0xffffffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FlashEmuFixture {
|
||||||
|
FlashEmuFixture(size_t sectors) : esp_part(), emu(sectors) { }
|
||||||
|
|
||||||
|
esp_partition_t esp_part;
|
||||||
|
SpiFlashEmulator emu;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]")
|
TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(4);
|
FlashEmuFixture f(4);
|
||||||
|
|
||||||
uint8_t sector[SPI_FLASH_SEC_SIZE];
|
uint8_t sector[SPI_FLASH_SEC_SIZE];
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
CHECK(spi_flash_read(0, sector, sizeof(sector)) == ESP_OK);
|
CHECK(esp_partition_read(&f.esp_part, 0, sector, sizeof(sector)) == ESP_OK);
|
||||||
for (auto v: sector) {
|
for (auto v: sector) {
|
||||||
CHECK(v == 0xff);
|
CHECK(v == 0xff);
|
||||||
}
|
}
|
||||||
@ -41,106 +48,129 @@ TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]")
|
|||||||
|
|
||||||
TEST_CASE("invalid writes are checked", "[spi_flash_emu]")
|
TEST_CASE("invalid writes are checked", "[spi_flash_emu]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(1);
|
FlashEmuFixture f(1);
|
||||||
|
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
CHECK(spi_flash_write(0, &val, 4) == ESP_OK);
|
CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_OK);
|
||||||
val = 1;
|
val = 1;
|
||||||
CHECK(spi_flash_write(0, &val, 4) == ESP_ERR_FLASH_OP_FAIL);
|
CHECK(esp_partition_write(&f.esp_part, 0, &val, 4) == ESP_ERR_FLASH_OP_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("out of bounds writes fail", "[spi_flash_emu]")
|
TEST_CASE("out of bounds writes fail", "[spi_flash_emu]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(4);
|
FlashEmuFixture f(4);
|
||||||
uint32_t vals[8];
|
uint32_t vals[8];
|
||||||
std::fill_n(vals, 8, 0);
|
std::fill_n(vals, 8, 0);
|
||||||
CHECK(spi_flash_write(0, vals, sizeof(vals)) == ESP_OK);
|
CHECK(esp_partition_write(&f.esp_part, 0, &vals, sizeof(vals)) == ESP_OK);
|
||||||
|
|
||||||
CHECK(spi_flash_write(4*4096 - sizeof(vals), vals, sizeof(vals)) == ESP_OK);
|
CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals), &vals, sizeof(vals)) == ESP_OK);
|
||||||
|
|
||||||
CHECK(spi_flash_write(4*4096 - sizeof(vals) + 4, vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL);
|
CHECK(esp_partition_write(&f.esp_part, 4*4096 - sizeof(vals) + 4, &vals, sizeof(vals)) == ESP_ERR_FLASH_OP_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]")
|
TEST_CASE("after erase the sector is set to 0xff", "[spi_flash_emu]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(4);
|
FlashEmuFixture f(4);
|
||||||
uint32_t val1 = 0xab00cd12;
|
uint32_t val1 = 0xab00cd12;
|
||||||
CHECK(spi_flash_write(0, &val1, sizeof(val1)) == ESP_OK);
|
CHECK(esp_partition_write(&f.esp_part, 0, &val1, sizeof(val1)) == ESP_OK);
|
||||||
uint32_t val2 = 0x5678efab;
|
uint32_t val2 = 0x5678efab;
|
||||||
CHECK(spi_flash_write(4096 - 4, &val2, sizeof(val2)) == ESP_OK);
|
CHECK(esp_partition_write(&f.esp_part, 4096 - 4, &val2, sizeof(val2)) == ESP_OK);
|
||||||
|
|
||||||
CHECK(emu.words()[0] == val1);
|
CHECK(f.emu.words()[0] == val1);
|
||||||
CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2));
|
CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2));
|
||||||
CHECK(emu.words()[4096 / 4 - 1] == val2);
|
CHECK(f.emu.words()[4096 / 4 - 1] == val2);
|
||||||
|
|
||||||
CHECK(spi_flash_erase_sector(0) == ESP_OK);
|
CHECK(esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE) == ESP_OK);
|
||||||
|
|
||||||
CHECK(emu.words()[0] == 0xffffffff);
|
CHECK(f.emu.words()[0] == 0xffffffff);
|
||||||
CHECK(range_empty_n(emu.words() + 1, 4096 / 4 - 2));
|
CHECK(range_empty_n(f.emu.words() + 1, 4096 / 4 - 2));
|
||||||
CHECK(emu.words()[4096 / 4 - 1] == 0xffffffff);
|
CHECK(f.emu.words()[4096 / 4 - 1] == 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("EMU raw read function works", "[spi_flash_emu]")
|
||||||
|
{
|
||||||
|
FlashEmuFixture f(4);
|
||||||
|
uint32_t value = 0xdeadbeef;
|
||||||
|
uint32_t read_value = 0;
|
||||||
|
CHECK(esp_partition_write(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK);
|
||||||
|
|
||||||
|
CHECK(esp_partition_read_raw(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK);
|
||||||
|
|
||||||
|
CHECK(read_value == 0xdeadbeef);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("EMU raw write function works", "[spi_flash_emu]")
|
||||||
|
{
|
||||||
|
FlashEmuFixture f(4);
|
||||||
|
uint32_t value = 0xdeadbeef;
|
||||||
|
uint32_t read_value = 0;
|
||||||
|
CHECK(esp_partition_write_raw(&f.esp_part, 0, &value, sizeof(value)) == ESP_OK);
|
||||||
|
|
||||||
|
CHECK(esp_partition_read(&f.esp_part, 0, &read_value, sizeof(&read_value)) == ESP_OK);
|
||||||
|
|
||||||
|
CHECK(read_value == 0xdeadbeef);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]")
|
TEST_CASE("read/write/erase operation times are calculated correctly", "[spi_flash_emu]")
|
||||||
{
|
{
|
||||||
SpiFlashEmulator emu(1);
|
FlashEmuFixture f(1);
|
||||||
uint8_t data[512];
|
uint8_t data[512];
|
||||||
spi_flash_read(0, data, 4);
|
esp_partition_read(&f.esp_part, 0, data, 4);
|
||||||
CHECK(emu.getTotalTime() == 7);
|
CHECK(f.emu.getTotalTime() == 7);
|
||||||
CHECK(emu.getReadOps() == 1);
|
CHECK(f.emu.getReadOps() == 1);
|
||||||
CHECK(emu.getReadBytes() == 4);
|
CHECK(f.emu.getReadBytes() == 4);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_read(0, data, 8);
|
esp_partition_read(&f.esp_part, 0, data, 8);
|
||||||
CHECK(emu.getTotalTime() == 5);
|
CHECK(f.emu.getTotalTime() == 5);
|
||||||
CHECK(emu.getReadOps() == 1);
|
CHECK(f.emu.getReadOps() == 1);
|
||||||
CHECK(emu.getReadBytes() == 8);
|
CHECK(f.emu.getReadBytes() == 8);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_read(0, data, 16);
|
esp_partition_read(&f.esp_part, 0, data, 16);
|
||||||
CHECK(emu.getTotalTime() == 6);
|
CHECK(f.emu.getTotalTime() == 6);
|
||||||
CHECK(emu.getReadOps() == 1);
|
CHECK(f.emu.getReadOps() == 1);
|
||||||
CHECK(emu.getReadBytes() == 16);
|
CHECK(f.emu.getReadBytes() == 16);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_read(0, data, 128);
|
esp_partition_read(&f.esp_part, 0, data, 128);
|
||||||
CHECK(emu.getTotalTime() == 18);
|
CHECK(f.emu.getTotalTime() == 18);
|
||||||
CHECK(emu.getReadOps() == 1);
|
CHECK(f.emu.getReadOps() == 1);
|
||||||
CHECK(emu.getReadBytes() == 128);
|
CHECK(f.emu.getReadBytes() == 128);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_read(0, data, 256);
|
esp_partition_read(&f.esp_part, 0, data, 256);
|
||||||
CHECK(emu.getTotalTime() == 32);
|
CHECK(f.emu.getTotalTime() == 32);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_read(0, data, (128+256)/2);
|
esp_partition_read(&f.esp_part, 0, data, (128+256)/2);
|
||||||
CHECK(emu.getTotalTime() == (18+32)/2);
|
CHECK(f.emu.getTotalTime() == (18+32)/2);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
|
|
||||||
spi_flash_write(0, data, 4);
|
esp_partition_write(&f.esp_part, 0, data, 4);
|
||||||
CHECK(emu.getTotalTime() == 19);
|
CHECK(f.emu.getTotalTime() == 19);
|
||||||
CHECK(emu.getWriteOps() == 1);
|
CHECK(f.emu.getWriteOps() == 1);
|
||||||
CHECK(emu.getWriteBytes() == 4);
|
CHECK(f.emu.getWriteBytes() == 4);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
CHECK(emu.getWriteOps() == 0);
|
CHECK(f.emu.getWriteOps() == 0);
|
||||||
CHECK(emu.getWriteBytes() == 0);
|
CHECK(f.emu.getWriteBytes() == 0);
|
||||||
spi_flash_write(0, data, 8);
|
esp_partition_write(&f.esp_part, 0, data, 8);
|
||||||
CHECK(emu.getTotalTime() == 23);
|
CHECK(f.emu.getTotalTime() == 23);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_write(0, data, 16);
|
esp_partition_write(&f.esp_part, 0, data, 16);
|
||||||
CHECK(emu.getTotalTime() == 35);
|
CHECK(f.emu.getTotalTime() == 35);
|
||||||
CHECK(emu.getWriteOps() == 1);
|
CHECK(f.emu.getWriteOps() == 1);
|
||||||
CHECK(emu.getWriteBytes() == 16);
|
CHECK(f.emu.getWriteBytes() == 16);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_write(0, data, 128);
|
esp_partition_write(&f.esp_part, 0, data, 128);
|
||||||
CHECK(emu.getTotalTime() == 205);
|
CHECK(f.emu.getTotalTime() == 205);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_write(0, data, 256);
|
esp_partition_write(&f.esp_part, 0, data, 256);
|
||||||
CHECK(emu.getTotalTime() == 417);
|
CHECK(f.emu.getTotalTime() == 417);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
spi_flash_write(0, data, (128+256)/2);
|
esp_partition_write(&f.esp_part, 0, data, (128+256)/2);
|
||||||
CHECK(emu.getTotalTime() == (205+417)/2);
|
CHECK(f.emu.getTotalTime() == (205+417)/2);
|
||||||
emu.clearStats();
|
f.emu.clearStats();
|
||||||
|
|
||||||
spi_flash_erase_sector(0);
|
esp_partition_erase_range(&f.esp_part, 0, SPI_FLASH_SEC_SIZE);
|
||||||
CHECK(emu.getEraseOps() == 1);
|
CHECK(f.emu.getEraseOps() == 1);
|
||||||
CHECK(emu.getTotalTime() == 37142);
|
CHECK(f.emu.getTotalTime() == 37142);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("data is randomized predictably", "[spi_flash_emu]")
|
TEST_CASE("data is randomized predictably", "[spi_flash_emu]")
|
||||||
|
@ -10,7 +10,7 @@ TEST_CASE("Can read partition table", "[partition]")
|
|||||||
|
|
||||||
const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||||
TEST_ASSERT_NOT_NULL(p);
|
TEST_ASSERT_NOT_NULL(p);
|
||||||
TEST_ASSERT_EQUAL(0x10000, p->address);
|
TEST_ASSERT_EQUAL(0x20000, p->address);
|
||||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, p->subtype);
|
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, p->subtype);
|
||||||
|
|
||||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||||
|
@ -202,6 +202,9 @@ const esp_partition_t *esp_partition_verify(const esp_partition_t *partition);
|
|||||||
/**
|
/**
|
||||||
* @brief Read data from the partition
|
* @brief Read data from the partition
|
||||||
*
|
*
|
||||||
|
* Partitions marked with an encryption flag will automatically be
|
||||||
|
* be read and decrypted via a cache mapping.
|
||||||
|
*
|
||||||
* @param partition Pointer to partition structure obtained using
|
* @param partition Pointer to partition structure obtained using
|
||||||
* esp_partition_find_first or esp_partition_get.
|
* esp_partition_find_first or esp_partition_get.
|
||||||
* Must be non-NULL.
|
* Must be non-NULL.
|
||||||
@ -250,7 +253,59 @@ esp_err_t esp_partition_read(const esp_partition_t* partition,
|
|||||||
* or one of error codes from lower-level flash driver.
|
* or one of error codes from lower-level flash driver.
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_partition_write(const esp_partition_t* partition,
|
esp_err_t esp_partition_write(const esp_partition_t* partition,
|
||||||
size_t dst_offset, const void* src, size_t size);
|
size_t dst_offset, const void* src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from the partition
|
||||||
|
*
|
||||||
|
* @note This function is essentially the same as \c esp_partition_write() above.
|
||||||
|
* It just never decrypts data but returns it as is.
|
||||||
|
*
|
||||||
|
* @param partition Pointer to partition structure obtained using
|
||||||
|
* esp_partition_find_first or esp_partition_get.
|
||||||
|
* Must be non-NULL.
|
||||||
|
* @param dst Pointer to the buffer where data should be stored.
|
||||||
|
* Pointer must be non-NULL and buffer must be at least 'size' bytes long.
|
||||||
|
* @param src_offset Address of the data to be read, relative to the
|
||||||
|
* beginning of the partition.
|
||||||
|
* @param size Size of data to be read, in bytes.
|
||||||
|
*
|
||||||
|
* @return ESP_OK, if data was read successfully;
|
||||||
|
* ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
|
||||||
|
* ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
|
||||||
|
* or one of error codes from lower-level flash driver.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_partition_read_raw(const esp_partition_t* partition,
|
||||||
|
size_t src_offset, void* dst, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to the partition without any transformation/encryption.
|
||||||
|
*
|
||||||
|
* @note This function is essentially the same as \c esp_partition_write() above.
|
||||||
|
* It just never encrypts data but writes it as is.
|
||||||
|
*
|
||||||
|
* Before writing data to flash, corresponding region of flash needs to be erased.
|
||||||
|
* This can be done using esp_partition_erase_range function.
|
||||||
|
*
|
||||||
|
* @param partition Pointer to partition structure obtained using
|
||||||
|
* esp_partition_find_first or esp_partition_get.
|
||||||
|
* Must be non-NULL.
|
||||||
|
* @param dst_offset Address where the data should be written, relative to the
|
||||||
|
* beginning of the partition.
|
||||||
|
* @param src Pointer to the source buffer. Pointer must be non-NULL and
|
||||||
|
* buffer must be at least 'size' bytes long.
|
||||||
|
* @param size Size of data to be written, in bytes.
|
||||||
|
*
|
||||||
|
* @note Prior to writing to flash memory, make sure it has been erased with
|
||||||
|
* esp_partition_erase_range call.
|
||||||
|
*
|
||||||
|
* @return ESP_OK, if data was written successfully;
|
||||||
|
* ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
|
||||||
|
* ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
|
||||||
|
* or one of the error codes from lower-level flash driver.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
|
||||||
|
size_t dst_offset, const void* src, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Erase part of the partition
|
* @brief Erase part of the partition
|
||||||
|
@ -402,6 +402,43 @@ esp_err_t esp_partition_write(const esp_partition_t* partition,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_partition_read_raw(const esp_partition_t* partition,
|
||||||
|
size_t src_offset, void* dst, size_t size)
|
||||||
|
{
|
||||||
|
assert(partition != NULL);
|
||||||
|
if (src_offset > partition->size) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (src_offset + size > partition->size) {
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
|
return esp_flash_read(partition->flash_chip, dst, partition->address + src_offset, size);
|
||||||
|
#else
|
||||||
|
return spi_flash_read(partition->address + src_offset, dst, size);
|
||||||
|
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
|
||||||
|
size_t dst_offset, const void* src, size_t size)
|
||||||
|
{
|
||||||
|
assert(partition != NULL);
|
||||||
|
if (dst_offset > partition->size) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (dst_offset + size > partition->size) {
|
||||||
|
return ESP_ERR_INVALID_SIZE;
|
||||||
|
}
|
||||||
|
dst_offset = partition->address + dst_offset;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
|
return esp_flash_write(partition->flash_chip, src, dst_offset, size);
|
||||||
|
#else
|
||||||
|
return spi_flash_write(dst_offset, src, size);
|
||||||
|
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
|
esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
|
||||||
size_t offset, size_t size)
|
size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
#
|
#
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
||||||
nvs, data, nvs, 0x9000, 0x4000
|
nvs, data, nvs, 0xb000, 0x5000
|
||||||
otadata, data, ota, 0xd000, 0x2000
|
otadata, data, ota, 0x10000, 0x2000
|
||||||
phy_init, data, phy, 0xf000, 0x1000
|
phy_init, data, phy, 0x12000, 0x1000
|
||||||
factory, 0, 0, 0x10000, 0x260000
|
factory, 0, 0, 0x20000, 0x260000
|
||||||
# these OTA partitions are used for tests, but can't fit real OTA apps in them
|
# these OTA partitions are used for tests, but can't fit real OTA apps in them
|
||||||
# (done this way to reduce total flash usage.)
|
# (done this way to reduce total flash usage.)
|
||||||
ota_0, 0, ota_0, , 64K
|
ota_0, 0, ota_0, , 64K
|
||||||
|
|
Loading…
Reference in New Issue
Block a user