nvs_api.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include "nvs.hpp"
  14. #include "nvs_flash.h"
  15. #include "nvs_storage.hpp"
  16. #include "intrusive_list.h"
  17. #include "nvs_platform.hpp"
  18. #include "nvs_partition_manager.hpp"
  19. #include "esp_partition.h"
  20. #include "sdkconfig.h"
  21. #include "nvs_handle_simple.hpp"
  22. #ifdef CONFIG_NVS_ENCRYPTION
  23. #include "nvs_encr.hpp"
  24. #endif
  25. #ifdef ESP_PLATFORM
  26. #include <esp32/rom/crc.h>
  27. // Uncomment this line to force output from this module
  28. // #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  29. #include "esp_log.h"
  30. static const char* TAG = "nvs";
  31. #else
  32. #include "crc.h"
  33. #define ESP_LOGD(...)
  34. #endif
  35. class NVSHandleEntry : public intrusive_list_node<NVSHandleEntry> {
  36. public:
  37. NVSHandleEntry(nvs::NVSHandleSimple *handle, const char* part_name)
  38. : nvs_handle(handle),
  39. mHandle(++s_nvs_next_handle),
  40. handle_part_name(part_name) { }
  41. ~NVSHandleEntry() {
  42. delete nvs_handle;
  43. }
  44. nvs::NVSHandleSimple *nvs_handle;
  45. nvs_handle_t mHandle;
  46. const char* handle_part_name;
  47. private:
  48. static uint32_t s_nvs_next_handle;
  49. };
  50. uint32_t NVSHandleEntry::s_nvs_next_handle;
  51. extern "C" void nvs_dump(const char *partName);
  52. extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
  53. #ifdef CONFIG_NVS_ENCRYPTION
  54. extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg);
  55. #endif
  56. #ifdef ESP_PLATFORM
  57. SemaphoreHandle_t nvs::Lock::mSemaphore = NULL;
  58. #endif
  59. using namespace std;
  60. using namespace nvs;
  61. static intrusive_list<NVSHandleEntry> s_nvs_handles;
  62. static nvs::Storage* lookup_storage_from_name(const char *name)
  63. {
  64. return NVSPartitionManager::get_instance()->lookup_storage_from_name(name);
  65. }
  66. extern "C" void nvs_dump(const char *partName)
  67. {
  68. Lock lock;
  69. nvs::Storage* pStorage;
  70. pStorage = lookup_storage_from_name(partName);
  71. if (pStorage == NULL) {
  72. return;
  73. }
  74. pStorage->debugDump();
  75. return;
  76. }
  77. extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount)
  78. {
  79. ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
  80. return NVSPartitionManager::get_instance()->init_custom(partName, baseSector, sectorCount);
  81. }
  82. #ifdef CONFIG_NVS_ENCRYPTION
  83. extern "C" esp_err_t nvs_flash_secure_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount, nvs_sec_cfg_t* cfg)
  84. {
  85. ESP_LOGD(TAG, "nvs_flash_secure_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
  86. if(cfg) {
  87. auto encrMgr = EncrMgr::getInstance();
  88. if (!encrMgr) return ESP_ERR_NO_MEM;
  89. auto err = encrMgr->setSecurityContext(baseSector, sectorCount, cfg);
  90. if(err != ESP_OK) {
  91. return err;
  92. }
  93. }
  94. return nvs_flash_init_custom(partName, baseSector, sectorCount);
  95. }
  96. #endif
  97. #ifdef ESP_PLATFORM
  98. extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
  99. {
  100. Lock::init();
  101. Lock lock;
  102. return NVSPartitionManager::get_instance()->init_partition(part_name);
  103. }
  104. extern "C" esp_err_t nvs_flash_init(void)
  105. {
  106. return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
  107. }
  108. #ifdef CONFIG_NVS_ENCRYPTION
  109. extern "C" esp_err_t nvs_flash_secure_init_partition(const char *part_name, nvs_sec_cfg_t* cfg)
  110. {
  111. Lock::init();
  112. Lock lock;
  113. nvs::Storage* mStorage;
  114. mStorage = lookup_storage_from_name(part_name);
  115. if (mStorage) {
  116. return ESP_OK;
  117. }
  118. const esp_partition_t* partition = esp_partition_find_first(
  119. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  120. if (partition == NULL) {
  121. return ESP_ERR_NOT_FOUND;
  122. }
  123. return nvs_flash_secure_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
  124. partition->size / SPI_FLASH_SEC_SIZE, cfg);
  125. }
  126. extern "C" esp_err_t nvs_flash_secure_init(nvs_sec_cfg_t* cfg)
  127. {
  128. return nvs_flash_secure_init_partition(NVS_DEFAULT_PART_NAME, cfg);
  129. }
  130. #endif
  131. extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
  132. {
  133. if (NVSPartitionManager::get_instance()->lookup_storage_from_name(part_name)) {
  134. return ESP_ERR_NVS_INVALID_STATE;
  135. }
  136. const esp_partition_t* partition = esp_partition_find_first(
  137. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
  138. if (partition == NULL) {
  139. return ESP_ERR_NOT_FOUND;
  140. }
  141. return esp_partition_erase_range(partition, 0, partition->size);
  142. }
  143. extern "C" esp_err_t nvs_flash_erase(void)
  144. {
  145. return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
  146. }
  147. #endif // ESP_PLATFORM
  148. extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
  149. {
  150. Lock::init();
  151. Lock lock;
  152. // Delete all corresponding open handles // TODO: why all handles, not just the ones with partition_name?
  153. s_nvs_handles.clearAndFreeNodes();
  154. // Deinit partition
  155. return NVSPartitionManager::get_instance()->deinit_partition(partition_name);
  156. }
  157. extern "C" esp_err_t nvs_flash_deinit(void)
  158. {
  159. return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME);
  160. }
  161. static esp_err_t nvs_find_ns_handle(nvs_handle_t c_handle, NVSHandleSimple** handle)
  162. {
  163. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](NVSHandleEntry& e) -> bool {
  164. return e.mHandle == c_handle;
  165. });
  166. if (it == end(s_nvs_handles)) {
  167. return ESP_ERR_NVS_INVALID_HANDLE;
  168. }
  169. *handle = it->nvs_handle;
  170. return ESP_OK;
  171. }
  172. extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle)
  173. {
  174. Lock lock;
  175. ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode);
  176. NVSHandleSimple *handle;
  177. esp_err_t result = NVSPartitionManager::get_instance()->open_handle(part_name, name, open_mode, &handle);
  178. if (result == ESP_OK) {
  179. NVSHandleEntry *entry = new (std::nothrow) NVSHandleEntry(handle, part_name);
  180. if (entry) {
  181. s_nvs_handles.push_back(entry);
  182. *out_handle = entry->mHandle;
  183. } else {
  184. delete handle;
  185. return ESP_ERR_NO_MEM;
  186. }
  187. }
  188. return result;
  189. }
  190. extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle)
  191. {
  192. return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle);
  193. }
  194. extern "C" void nvs_close(nvs_handle_t handle)
  195. {
  196. Lock lock;
  197. ESP_LOGD(TAG, "%s %d", __func__, handle);
  198. auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](NVSHandleEntry& e) -> bool {
  199. return e.mHandle == handle;
  200. });
  201. if (it == end(s_nvs_handles)) {
  202. return;
  203. }
  204. s_nvs_handles.erase(it);
  205. delete static_cast<NVSHandleEntry*>(it);
  206. }
  207. extern "C" esp_err_t nvs_erase_key(nvs_handle_t c_handle, const char* key)
  208. {
  209. Lock lock;
  210. ESP_LOGD(TAG, "%s %s\r\n", __func__, key);
  211. NVSHandleSimple *handle;
  212. auto err = nvs_find_ns_handle(c_handle, &handle);
  213. if (err != ESP_OK) {
  214. return err;
  215. }
  216. return handle->erase_item(key);
  217. }
  218. extern "C" esp_err_t nvs_erase_all(nvs_handle_t c_handle)
  219. {
  220. Lock lock;
  221. ESP_LOGD(TAG, "%s\r\n", __func__);
  222. NVSHandleSimple *handle;
  223. auto err = nvs_find_ns_handle(c_handle, &handle);
  224. if (err != ESP_OK) {
  225. return err;
  226. }
  227. return handle->erase_all();
  228. }
  229. template<typename T>
  230. static esp_err_t nvs_set(nvs_handle_t c_handle, const char* key, T value)
  231. {
  232. Lock lock;
  233. ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value);
  234. NVSHandleSimple *handle;
  235. auto err = nvs_find_ns_handle(c_handle, &handle);
  236. if (err != ESP_OK) {
  237. return err;
  238. }
  239. return handle->set_item(key, value);
  240. }
  241. extern "C" esp_err_t nvs_set_i8 (nvs_handle_t handle, const char* key, int8_t value)
  242. {
  243. return nvs_set(handle, key, value);
  244. }
  245. extern "C" esp_err_t nvs_set_u8 (nvs_handle_t handle, const char* key, uint8_t value)
  246. {
  247. return nvs_set(handle, key, value);
  248. }
  249. extern "C" esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int16_t value)
  250. {
  251. return nvs_set(handle, key, value);
  252. }
  253. extern "C" esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, uint16_t value)
  254. {
  255. return nvs_set(handle, key, value);
  256. }
  257. extern "C" esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int32_t value)
  258. {
  259. return nvs_set(handle, key, value);
  260. }
  261. extern "C" esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value)
  262. {
  263. return nvs_set(handle, key, value);
  264. }
  265. extern "C" esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value)
  266. {
  267. return nvs_set(handle, key, value);
  268. }
  269. extern "C" esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value)
  270. {
  271. return nvs_set(handle, key, value);
  272. }
  273. extern "C" esp_err_t nvs_commit(nvs_handle_t c_handle)
  274. {
  275. Lock lock;
  276. // no-op for now, to be used when intermediate cache is added
  277. NVSHandleSimple *handle;
  278. auto err = nvs_find_ns_handle(c_handle, &handle);
  279. if (err != ESP_OK) {
  280. return err;
  281. }
  282. return handle->commit();
  283. }
  284. extern "C" esp_err_t nvs_set_str(nvs_handle_t c_handle, const char* key, const char* value)
  285. {
  286. Lock lock;
  287. ESP_LOGD(TAG, "%s %s %s", __func__, key, value);
  288. NVSHandleSimple *handle;
  289. auto err = nvs_find_ns_handle(c_handle, &handle);
  290. if (err != ESP_OK) {
  291. return err;
  292. }
  293. return handle->set_string(key, value);
  294. }
  295. extern "C" esp_err_t nvs_set_blob(nvs_handle_t c_handle, const char* key, const void* value, size_t length)
  296. {
  297. Lock lock;
  298. ESP_LOGD(TAG, "%s %s %d", __func__, key, length);
  299. NVSHandleSimple *handle;
  300. auto err = nvs_find_ns_handle(c_handle, &handle);
  301. if (err != ESP_OK) {
  302. return err;
  303. }
  304. return handle->set_blob(key, value, length);
  305. }
  306. template<typename T>
  307. static esp_err_t nvs_get(nvs_handle_t c_handle, const char* key, T* out_value)
  308. {
  309. Lock lock;
  310. ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T));
  311. NVSHandleSimple *handle;
  312. auto err = nvs_find_ns_handle(c_handle, &handle);
  313. if (err != ESP_OK) {
  314. return err;
  315. }
  316. return handle->get_item(key, *out_value);
  317. }
  318. extern "C" esp_err_t nvs_get_i8 (nvs_handle_t c_handle, const char* key, int8_t* out_value)
  319. {
  320. return nvs_get(c_handle, key, out_value);
  321. }
  322. extern "C" esp_err_t nvs_get_u8 (nvs_handle_t c_handle, const char* key, uint8_t* out_value)
  323. {
  324. return nvs_get(c_handle, key, out_value);
  325. }
  326. extern "C" esp_err_t nvs_get_i16 (nvs_handle_t c_handle, const char* key, int16_t* out_value)
  327. {
  328. return nvs_get(c_handle, key, out_value);
  329. }
  330. extern "C" esp_err_t nvs_get_u16 (nvs_handle_t c_handle, const char* key, uint16_t* out_value)
  331. {
  332. return nvs_get(c_handle, key, out_value);
  333. }
  334. extern "C" esp_err_t nvs_get_i32 (nvs_handle_t c_handle, const char* key, int32_t* out_value)
  335. {
  336. return nvs_get(c_handle, key, out_value);
  337. }
  338. extern "C" esp_err_t nvs_get_u32 (nvs_handle_t c_handle, const char* key, uint32_t* out_value)
  339. {
  340. return nvs_get(c_handle, key, out_value);
  341. }
  342. extern "C" esp_err_t nvs_get_i64 (nvs_handle_t c_handle, const char* key, int64_t* out_value)
  343. {
  344. return nvs_get(c_handle, key, out_value);
  345. }
  346. extern "C" esp_err_t nvs_get_u64 (nvs_handle_t c_handle, const char* key, uint64_t* out_value)
  347. {
  348. return nvs_get(c_handle, key, out_value);
  349. }
  350. static esp_err_t nvs_get_str_or_blob(nvs_handle_t c_handle, nvs::ItemType type, const char* key, void* out_value, size_t* length)
  351. {
  352. Lock lock;
  353. ESP_LOGD(TAG, "%s %s", __func__, key);
  354. NVSHandleSimple *handle;
  355. auto err = nvs_find_ns_handle(c_handle, &handle);
  356. if (err != ESP_OK) {
  357. return err;
  358. }
  359. size_t dataSize;
  360. err = handle->get_item_size(type, key, dataSize);
  361. if (err != ESP_OK) {
  362. return err;
  363. }
  364. if (length == nullptr) {
  365. return ESP_ERR_NVS_INVALID_LENGTH;
  366. } else if (out_value == nullptr) {
  367. *length = dataSize;
  368. return ESP_OK;
  369. } else if (*length < dataSize) {
  370. *length = dataSize;
  371. return ESP_ERR_NVS_INVALID_LENGTH;
  372. }
  373. *length = dataSize;
  374. return handle->get_typed_item(type, key, out_value, dataSize);
  375. }
  376. extern "C" esp_err_t nvs_get_str(nvs_handle_t c_handle, const char* key, char* out_value, size_t* length)
  377. {
  378. return nvs_get_str_or_blob(c_handle, nvs::ItemType::SZ, key, out_value, length);
  379. }
  380. extern "C" esp_err_t nvs_get_blob(nvs_handle_t c_handle, const char* key, void* out_value, size_t* length)
  381. {
  382. return nvs_get_str_or_blob(c_handle, nvs::ItemType::BLOB, key, out_value, length);
  383. }
  384. extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats)
  385. {
  386. Lock lock;
  387. nvs::Storage* pStorage;
  388. if (nvs_stats == NULL) {
  389. return ESP_ERR_INVALID_ARG;
  390. }
  391. nvs_stats->used_entries = 0;
  392. nvs_stats->free_entries = 0;
  393. nvs_stats->total_entries = 0;
  394. nvs_stats->namespace_count = 0;
  395. pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
  396. if (pStorage == NULL) {
  397. return ESP_ERR_NVS_NOT_INITIALIZED;
  398. }
  399. if(!pStorage->isValid()){
  400. return ESP_ERR_NVS_INVALID_STATE;
  401. }
  402. return pStorage->fillStats(*nvs_stats);
  403. }
  404. extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* used_entries)
  405. {
  406. Lock lock;
  407. if(used_entries == NULL){
  408. return ESP_ERR_INVALID_ARG;
  409. }
  410. *used_entries = 0;
  411. NVSHandleSimple *handle;
  412. auto err = nvs_find_ns_handle(c_handle, &handle);
  413. if (err != ESP_OK) {
  414. return err;
  415. }
  416. size_t used_entry_count;
  417. err = handle->get_used_entry_count(used_entry_count);
  418. if(err == ESP_OK){
  419. *used_entries = used_entry_count;
  420. }
  421. return err;
  422. }
  423. #if (defined CONFIG_NVS_ENCRYPTION) && (defined ESP_PLATFORM)
  424. extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  425. {
  426. auto err = esp_partition_erase_range(partition, 0, partition->size);
  427. if(err != ESP_OK) {
  428. return err;
  429. }
  430. for(uint8_t cnt = 0; cnt < NVS_KEY_SIZE; cnt++) {
  431. cfg->eky[cnt] = 0xff;
  432. cfg->tky[cnt] = 0xee;
  433. }
  434. err = spi_flash_write(partition->address, cfg->eky, NVS_KEY_SIZE);
  435. if(err != ESP_OK) {
  436. return err;
  437. }
  438. err = spi_flash_write(partition->address + NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  439. if(err != ESP_OK) {
  440. return err;
  441. }
  442. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  443. if(err != ESP_OK) {
  444. return err;
  445. }
  446. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  447. if(err != ESP_OK) {
  448. return err;
  449. }
  450. uint32_t crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  451. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  452. uint8_t crc_wr[16];
  453. memset(crc_wr, 0xff, sizeof(crc_wr));
  454. memcpy(crc_wr, &crc_calc, 4);
  455. err = esp_partition_write(partition, 2 * NVS_KEY_SIZE, crc_wr, sizeof(crc_wr));
  456. if(err != ESP_OK) {
  457. return err;
  458. }
  459. return ESP_OK;
  460. }
  461. extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
  462. {
  463. uint8_t eky_raw[NVS_KEY_SIZE], tky_raw[NVS_KEY_SIZE];
  464. uint32_t crc_raw, crc_read, crc_calc;
  465. auto check_if_initialized = [](uint8_t* eky, uint8_t* tky, uint32_t crc) {
  466. uint8_t cnt = 0;
  467. while(cnt < NVS_KEY_SIZE && eky[cnt] == 0xff && tky[cnt] == 0xff) cnt++;
  468. if(cnt == NVS_KEY_SIZE && crc == 0xffffffff) {
  469. return false;
  470. }
  471. return true;
  472. };
  473. auto err = spi_flash_read(partition->address, eky_raw, NVS_KEY_SIZE);
  474. if(err != ESP_OK) {
  475. return err;
  476. }
  477. err = spi_flash_read(partition->address + NVS_KEY_SIZE, tky_raw, NVS_KEY_SIZE);
  478. if(err != ESP_OK) {
  479. return err;
  480. }
  481. err = spi_flash_read(partition->address + 2 * NVS_KEY_SIZE, &crc_raw, 4);
  482. if(err != ESP_OK) {
  483. return err;
  484. }
  485. if(!check_if_initialized(eky_raw, tky_raw, crc_raw)) {
  486. /* This is an uninitialized key partition*/
  487. return ESP_ERR_NVS_KEYS_NOT_INITIALIZED;
  488. }
  489. err = esp_partition_read(partition, 0, cfg->eky, NVS_KEY_SIZE);
  490. if(err != ESP_OK) {
  491. return err;
  492. }
  493. err = esp_partition_read(partition, NVS_KEY_SIZE, cfg->tky, NVS_KEY_SIZE);
  494. if(err != ESP_OK) {
  495. return err;
  496. }
  497. err = esp_partition_read(partition, 2 * NVS_KEY_SIZE, &crc_read, 4);
  498. if(err != ESP_OK) {
  499. return err;
  500. }
  501. crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE);
  502. crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE);
  503. if(crc_calc != crc_read) {
  504. if(!check_if_initialized(cfg->eky, cfg->tky, crc_read)) {
  505. /* This is an uninitialized key partition*/
  506. return ESP_ERR_NVS_KEYS_NOT_INITIALIZED;
  507. }
  508. return ESP_ERR_NVS_CORRUPT_KEY_PART;
  509. }
  510. return ESP_OK;
  511. }
  512. #endif
  513. static nvs_iterator_t create_iterator(nvs::Storage *storage, nvs_type_t type)
  514. {
  515. nvs_iterator_t it = (nvs_iterator_t)calloc(1, sizeof(nvs_opaque_iterator_t));
  516. if (it == NULL) {
  517. return NULL;
  518. }
  519. it->storage = storage;
  520. it->type = type;
  521. return it;
  522. }
  523. extern "C" nvs_iterator_t nvs_entry_find(const char *part_name, const char *namespace_name, nvs_type_t type)
  524. {
  525. Lock lock;
  526. nvs::Storage *pStorage;
  527. pStorage = lookup_storage_from_name(part_name);
  528. if (pStorage == NULL) {
  529. return NULL;
  530. }
  531. nvs_iterator_t it = create_iterator(pStorage, type);
  532. if (it == NULL) {
  533. return NULL;
  534. }
  535. bool entryFound = pStorage->findEntry(it, namespace_name);
  536. if (!entryFound) {
  537. free(it);
  538. return NULL;
  539. }
  540. return it;
  541. }
  542. extern "C" nvs_iterator_t nvs_entry_next(nvs_iterator_t it)
  543. {
  544. Lock lock;
  545. assert(it);
  546. bool entryFound = it->storage->nextEntry(it);
  547. if (!entryFound) {
  548. free(it);
  549. return NULL;
  550. }
  551. return it;
  552. }
  553. extern "C" void nvs_entry_info(nvs_iterator_t it, nvs_entry_info_t *out_info)
  554. {
  555. *out_info = it->entry_info;
  556. }
  557. extern "C" void nvs_release_iterator(nvs_iterator_t it)
  558. {
  559. free(it);
  560. }