Merge branch 'feature/nvs_storage_copy_part_name' into 'master'

NVS: partition name is copied now

Closes IDF-1231

See merge request espressif/esp-idf!6933
This commit is contained in:
Angus Gratton
2020-01-09 10:42:25 +08:00
5 changed files with 91 additions and 20 deletions

View File

@ -62,7 +62,9 @@ typedef nvs_handle_t nvs_handle IDF_DEPRECATED("Replace with nvs_handle_t");
#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 */
#define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ #define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */
#define NVS_PART_NAME_MAX_SIZE 16 /*!< maximum length of partition name (excluding null terminator) */
/** /**
* @brief Mode of opening the non-volatile storage * @brief Mode of opening the non-volatile storage

View File

@ -50,8 +50,7 @@ esp_err_t nvs_flash_init(void);
/** /**
* @brief Initialize NVS flash storage for the specified partition. * @brief Initialize NVS flash storage for the specified partition.
* *
* @param[in] partition_label Label of the partition. Note that internally a reference to * @param[in] partition_label Label of the partition. Must be no longer than 16 characters.
* passed value is kept and it should be accessible for future operations
* *
* @return * @return
* - ESP_OK if storage was successfully initialized. * - ESP_OK if storage was successfully initialized.
@ -118,8 +117,8 @@ esp_err_t nvs_flash_erase_partition(const char *part_name);
* This API initialises the default NVS partition. The default NVS partition * This API initialises the default NVS partition. The default NVS partition
* is the one that is labeled "nvs" in the partition table. * is the one that is labeled "nvs" in the partition table.
* *
* @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption.
* If cfg is NULL, no encryption is used. * If cfg is NULL, no encryption is used.
* *
* @return * @return
* - ESP_OK if storage was successfully initialized. * - ESP_OK if storage was successfully initialized.
@ -136,8 +135,8 @@ esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg);
* @param[in] partition_label Label of the partition. Note that internally a reference to * @param[in] partition_label Label of the partition. Note that internally a reference to
* passed value is kept and it should be accessible for future operations * passed value is kept and it should be accessible for future operations
* *
* @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption. * @param[in] cfg Security configuration (keys) to be used for NVS encryption/decryption.
* If cfg is null, no encryption/decryption is used. * If cfg is null, no encryption/decryption is used.
* @return * @return
* - ESP_OK if storage was successfully initialized. * - ESP_OK if storage was successfully initialized.
* - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages * - ESP_ERR_NVS_NO_FREE_PAGES if the NVS storage contains no empty pages
@ -149,16 +148,16 @@ esp_err_t nvs_flash_secure_init_partition(const char *partition_label, nvs_sec_c
/** /**
* @brief Generate and store NVS keys in the provided esp partition * @brief Generate and store NVS keys in the provided esp partition
* *
* @param[in] partition Pointer to partition structure obtained using * @param[in] 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.
* @param[out] cfg Pointer to nvs security configuration structure. * @param[out] cfg Pointer to nvs security configuration structure.
* Pointer must be non-NULL. * Pointer must be non-NULL.
* Generated keys will be populated in this structure. * Generated keys will be populated in this structure.
* *
* *
* @return * @return
* -ESP_OK, if cfg was read successfully; * -ESP_OK, if cfg was read successfully;
* -or error codes from esp_partition_write/erase APIs. * -or error codes from esp_partition_write/erase APIs.
*/ */
@ -167,8 +166,8 @@ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_
/** /**
* @brief Read NVS security configuration from a partition. * @brief Read NVS security configuration from a partition.
* *
* @param[in] partition Pointer to partition structure obtained using * @param[in] 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.
@ -177,7 +176,7 @@ esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_
* *
* @note Provided parition is assumed to be marked 'encrypted'. * @note Provided parition is assumed to be marked 'encrypted'.
* *
* @return * @return
* -ESP_OK, if cfg was read successfully; * -ESP_OK, if cfg was read successfully;
* -ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys. * -ESP_ERR_NVS_KEYS_NOT_INITIALIZED, if the partition is not yet written with keys.
* -ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt * -ESP_ERR_NVS_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt

View File

@ -102,6 +102,8 @@ extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSe
{ {
ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount); ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
if (strlen(partName) > NVS_PART_NAME_MAX_SIZE) return ESP_ERR_INVALID_ARG;
nvs::Storage* new_storage = NULL; nvs::Storage* new_storage = NULL;
nvs::Storage* storage = lookup_storage_from_name(partName); nvs::Storage* storage = lookup_storage_from_name(partName);
if (storage == NULL) { if (storage == NULL) {

View File

@ -15,7 +15,6 @@
#define nvs_storage_hpp #define nvs_storage_hpp
#include <memory> #include <memory>
#include <string>
#include <unordered_map> #include <unordered_map>
#include "nvs.hpp" #include "nvs.hpp"
#include "nvs_types.hpp" #include "nvs_types.hpp"
@ -52,8 +51,8 @@ class Storage : public intrusive_list_node<Storage>
public: public:
char key[Item::MAX_KEY_LENGTH + 1]; char key[Item::MAX_KEY_LENGTH + 1];
uint8_t nsIndex; uint8_t nsIndex;
uint8_t chunkCount; uint8_t chunkCount;
VerOffset chunkStart; VerOffset chunkStart;
}; };
typedef intrusive_list<BlobIndexNode> TBlobIndexList; typedef intrusive_list<BlobIndexNode> TBlobIndexList;
@ -61,7 +60,10 @@ class Storage : public intrusive_list_node<Storage>
public: public:
~Storage(); ~Storage();
Storage(const char *pName = NVS_DEFAULT_PART_NAME) : mPartitionName(pName) { }; Storage(const char *pName = NVS_DEFAULT_PART_NAME)
{
strncpy(mPartitionName, pName, NVS_PART_NAME_MAX_SIZE);
};
esp_err_t init(uint32_t baseSector, uint32_t sectorCount); esp_err_t init(uint32_t baseSector, uint32_t sectorCount);
@ -93,7 +95,7 @@ public:
{ {
return eraseItem(nsIndex, ItemType::ANY, key); return eraseItem(nsIndex, ItemType::ANY, key);
} }
esp_err_t eraseNamespace(uint8_t nsIndex); esp_err_t eraseNamespace(uint8_t nsIndex);
const char *getPartName() const const char *getPartName() const
@ -114,7 +116,7 @@ public:
esp_err_t eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart = VerOffset::VER_ANY); esp_err_t eraseMultiPageBlob(uint8_t nsIndex, const char* key, VerOffset chunkStart = VerOffset::VER_ANY);
void debugDump(); void debugDump();
void debugCheck(); void debugCheck();
esp_err_t fillStats(nvs_stats_t& nvsStats); esp_err_t fillStats(nvs_stats_t& nvsStats);
@ -143,7 +145,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:
const char *mPartitionName; char mPartitionName [NVS_PART_NAME_MAX_SIZE + 1];
size_t mPageCount; size_t mPageCount;
PageManager mPageManager; PageManager mPageManager;
TNamespaces mNamespaces; TNamespaces mNamespaces;

View File

@ -549,6 +549,72 @@ TEST_CASE("can erase items", "[nvs]")
CHECK(storage.readItem(3, "key00222", val) == ESP_ERR_NVS_NOT_FOUND); CHECK(storage.readItem(3, "key00222", val) == ESP_ERR_NVS_NOT_FOUND);
} }
TEST_CASE("partition name is deep copy", "[nvs]")
{
SpiFlashEmulator emu(10);
char partition_name[16];
strcpy(partition_name, "const_name");
nvs_handle_t handle_1;
nvs_handle_t handle_2;
const uint32_t NVS_FLASH_SECTOR = 6;
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
TEST_ESP_OK(nvs_flash_init_custom(partition_name, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN));
strcpy(partition_name, "just_kidding");
TEST_ESP_OK(nvs_open_from_partition("const_name", "test", NVS_READWRITE, &handle_1));
CHECK(nvs_open_from_partition("just_kidding", "test", NVS_READWRITE, &handle_2) == ESP_ERR_NVS_PART_NOT_FOUND);
nvs_close(handle_1);
nvs_close(handle_2);
nvs_flash_deinit_partition("const_name");
nvs_flash_deinit_partition("just_kidding"); // just in case, try not to affect other tests
}
TEST_CASE("namespace name is deep copy", "[nvs]")
{
SpiFlashEmulator emu(10);
char ns_name[16];
strcpy(ns_name, "const_name");
nvs_handle_t handle_1;
nvs_handle_t handle_2;
const uint32_t NVS_FLASH_SECTOR = 6;
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN));
TEST_ESP_OK(nvs_open("const_name", NVS_READWRITE, &handle_1));
strcpy(ns_name, "just_kidding");
CHECK(nvs_open("just_kidding", NVS_READONLY, &handle_2) == ESP_ERR_NVS_NOT_FOUND);
nvs_close(handle_1);
nvs_close(handle_2);
nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME);
}
TEST_CASE("Partition name no longer than 16 characters", "[nvs]")
{
SpiFlashEmulator emu(10);
const char *TOO_LONG_NAME = "0123456789abcdefg";
const uint32_t NVS_FLASH_SECTOR = 6;
const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 3;
emu.setBounds(NVS_FLASH_SECTOR, NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN);
CHECK(nvs_flash_init_custom(TOO_LONG_NAME, NVS_FLASH_SECTOR, NVS_FLASH_SECTOR_COUNT_MIN)
== ESP_ERR_INVALID_ARG);
nvs_flash_deinit_partition(TOO_LONG_NAME); // just in case
}
TEST_CASE("readonly handle fails on writing", "[nvs]") TEST_CASE("readonly handle fails on writing", "[nvs]")
{ {
SpiFlashEmulator emu(10); SpiFlashEmulator emu(10);