瀏覽代碼

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
Angus Gratton 6 年之前
父節點
當前提交
dba3c241a9

+ 3 - 1
components/nvs_flash/include/nvs.h

@@ -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 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

+ 11 - 12
components/nvs_flash/include/nvs_flash.h

@@ -50,8 +50,7 @@ esp_err_t nvs_flash_init(void);
 /**
  * @brief Initialize NVS flash storage for the specified partition.
  *
- * @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
+ * @param[in]  partition_label   Label of the partition. Must be no longer than 16 characters.
  *
  * @return
  *      - 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
  * is the one that is labeled "nvs" in the partition table.
  *
- * @param[in]  cfg Security configuration (keys) to be used for NVS encryption/decryption. 
- *                              If cfg is NULL, no encryption is used. 
+ * @param[in]  cfg Security configuration (keys) to be used for NVS encryption/decryption.
+ *                              If cfg is NULL, no encryption is used.
  *
  * @return
  *      - 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
  *                               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. 
- *                              If cfg is null, no encryption/decryption is used. 
+ * @param[in]  cfg Security configuration (keys) to be used for NVS encryption/decryption.
+ *                              If cfg is null, no encryption/decryption is used.
  * @return
  *      - ESP_OK if storage was successfully initialized.
  *      - 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
- * 
+ *
  * @param[in]  partition Pointer to partition structure obtained using
  *                       esp_partition_find_first or esp_partition_get.
  *                       Must be non-NULL.
  * @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.
  *
  *
- * @return 
+ * @return
  *      -ESP_OK, if cfg was read successfully;
  *      -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
  *                       esp_partition_find_first or esp_partition_get.
  *                       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'.
  *
- * @return 
+ * @return
  *      -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_CORRUPT_KEY_PART, if the partition containing keys is found to be corrupt

+ 2 - 0
components/nvs_flash/src/nvs_api.cpp

@@ -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);
 
+    if (strlen(partName) > NVS_PART_NAME_MAX_SIZE) return ESP_ERR_INVALID_ARG;
+
     nvs::Storage* new_storage = NULL;
     nvs::Storage* storage = lookup_storage_from_name(partName);
     if (storage == NULL) {

+ 9 - 7
components/nvs_flash/src/nvs_storage.hpp

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

+ 66 - 0
components/nvs_flash/test_nvs_host/test_nvs.cpp

@@ -549,6 +549,72 @@ TEST_CASE("can erase items", "[nvs]")
     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]")
 {
     SpiFlashEmulator emu(10);