Просмотр исходного кода

NVS Flash: prevent erasing initialized partition

Closes https://github.com/espressif/esp-idf/issues/4755
Closes https://github.com/espressif/esp-idf/issues/2777

* nvs_flash_erase_partition() checks whether
  the parition in question is initialized
  already and will return an error if so
* reflect changes in the documentation
Jakob Hasse 6 лет назад
Родитель
Сommit
c6deffb8a2

+ 5 - 3
components/nvs_flash/include/nvs_flash.h

@@ -87,26 +87,28 @@ esp_err_t nvs_flash_deinit_partition(const char* partition_label);
 /**
  * @brief Erase the default NVS partition
  *
- * This function erases all contents of the default NVS partition (one with label "nvs")
+ * Erases all contents of the default NVS partition (one with label "nvs"), which must be uninitialized.
  *
  * @return
  *      - ESP_OK on success
  *      - ESP_ERR_NOT_FOUND if there is no NVS partition labeled "nvs" in the
  *        partition table
+ *      - ESP_ERR_NVS_INVALID_STATE if the default partition is initialized already
  */
 esp_err_t nvs_flash_erase(void);
 
 /**
  * @brief Erase specified NVS partition
  *
- * This function erases all contents of specified NVS partition
+ * Erase all content of a specified uninitialized NVS partition
  *
- * @param[in]  part_name    Name (label) of the partition to be erased
+ * @param[in]  part_name    Name (label) of an uninitialized partition which should be erased
  *
  * @return
  *      - ESP_OK on success
  *      - ESP_ERR_NOT_FOUND if there is no NVS partition with the specified name
  *        in the partition table
+ *      - ESP_ERR_NVS_INVALID_STATE if the partition with part_name is initialized already
  */
 esp_err_t nvs_flash_erase_partition(const char *part_name);
 

+ 8 - 4
components/nvs_flash/src/nvs_api.cpp

@@ -95,7 +95,7 @@ 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);
 
-    return nvs::NVSPartitionManager::get_instance()->init_custom(partName, baseSector, sectorCount);
+    return NVSPartitionManager::get_instance()->init_custom(partName, baseSector, sectorCount);
 }
 
 #ifdef CONFIG_NVS_ENCRYPTION
@@ -125,7 +125,7 @@ extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
     Lock::init();
     Lock lock;
 
-    return nvs::NVSPartitionManager::get_instance()->init_partition(part_name);
+    return NVSPartitionManager::get_instance()->init_partition(part_name);
 }
 
 extern "C" esp_err_t nvs_flash_init(void)
@@ -163,6 +163,10 @@ extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
 
 extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
 {
+    if (NVSPartitionManager::get_instance()->lookup_storage_from_name(part_name)) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+
     const esp_partition_t* partition = esp_partition_find_first(
             ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
     if (partition == NULL) {
@@ -187,7 +191,7 @@ extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
     s_nvs_handles.clearAndFreeNodes();
 
     // Deinit partition
-    return nvs::NVSPartitionManager::get_instance()->deinit_partition(partition_name);
+    return NVSPartitionManager::get_instance()->deinit_partition(partition_name);
 }
 
 extern "C" esp_err_t nvs_flash_deinit(void)
@@ -213,7 +217,7 @@ extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char*
     ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode);
 
     NVSHandleSimple *handle;
-    esp_err_t result = nvs::NVSPartitionManager::get_instance()->open_handle(part_name, name, open_mode, &handle);
+    esp_err_t result = NVSPartitionManager::get_instance()->open_handle(part_name, name, open_mode, &handle);
     if (result == ESP_OK) {
         NVSHandleEntry *entry = new (std::nothrow) NVSHandleEntry(handle, part_name);
         if (entry) {

+ 20 - 2
components/nvs_flash/test/test_nvs.c

@@ -18,6 +18,24 @@
 
 static const char* TAG = "test_nvs";
 
+TEST_CASE("flash erase fails on initialized partition", "[nvs]")
+{
+    esp_err_t err = nvs_flash_init();
+    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+        ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err);
+        const esp_partition_t* nvs_partition = esp_partition_find_first(
+                ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL);
+        assert(nvs_partition && "partition table must have an NVS partition");
+        ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) );
+        err = nvs_flash_init();
+    }
+    ESP_ERROR_CHECK( err );
+
+    TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, nvs_flash_erase());
+
+    nvs_flash_deinit();
+}
+
 // test could have different output on host tests
 TEST_CASE("nvs deinit with open handle", "[nvs]")
 {
@@ -121,8 +139,8 @@ TEST_CASE("calculate used and free space", "[nvs]")
     // erase if have any namespace
     TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
     if(stat1.namespace_count != 0) {
-        TEST_ESP_OK(nvs_flash_erase());
         TEST_ESP_OK(nvs_flash_deinit());
+        TEST_ESP_OK(nvs_flash_erase());
         TEST_ESP_OK(nvs_flash_init());
     }
 
@@ -235,8 +253,8 @@ TEST_CASE("calculate used and free space", "[nvs]")
 
     nvs_close(handle_3);
 
-    TEST_ESP_OK(nvs_flash_erase());
     TEST_ESP_OK(nvs_flash_deinit());
+    TEST_ESP_OK(nvs_flash_erase());
 }
 
 TEST_CASE("check for memory leaks in nvs_set_blob", "[nvs]")

+ 1 - 1
tools/ci/config/target-test.yml

@@ -336,7 +336,7 @@ example_test_012:
 
 UT_001:
   extends: .unit_test_template
-  parallel: 33
+  parallel: 34
   tags:
     - ESP32_IDF
     - UT_T1_1