nvs_api.cpp 20 KB

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