• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description: SOC KEY VALUE STORAGE IMPLEMENTATION
15  */
16 
17 #include "nv.h"
18 #include "nv_storage.h"
19 #include "nv_store.h"
20 #include "nv_upg.h"
21 #include "securec.h"
22 #include "nv_porting.h"
23 #include "common_def.h"
24 #include "nv_reset.h"
25 #include "nv_async_store.h"
26 #include "osal_semaphore.h"
27 #include "nv_update.h"
28 #include "nv_notify.h"
29 #include "nv_task_adapt.h"
30 #include "nv_storage_handle.h"
31 
32 osal_semaphore nv_sem;
33 #define MAX_BINARY_VAL 1
34 
nv_helper_convert_key_attr(const nv_key_attr_t * attr)35 STATIC nv_attributes_t nv_helper_convert_key_attr(const nv_key_attr_t *attr)
36 {
37     nv_attributes_t attribute = NV_ATTRIBUTE_NORMAL;
38     bool is_support_crypt = false;
39 
40 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
41     is_support_crypt = attr->encrypted;
42 #endif
43 
44     if (attr->permanent && is_support_crypt) {
45         attribute = NV_ATTRIBUTE_ENCRYPTED | NV_ATTRIBUTE_PERMANENT | NV_ATTRIBUTE_NON_UPGRADE;
46     } else if (attr->permanent) {
47         attribute = NV_ATTRIBUTE_PERMANENT | NV_ATTRIBUTE_NON_UPGRADE;
48     } else if (is_support_crypt) {
49         attribute = NV_ATTRIBUTE_ENCRYPTED | NV_ATTRIBUTE_NON_UPGRADE;
50     } else if (attr->non_upgrade) {
51         attribute = NV_ATTRIBUTE_NON_UPGRADE;
52     }
53     return attribute;
54 }
55 
nv_storage_max_key_space(const nv_key_attr_t * attr)56 static uint16_t nv_storage_max_key_space(const nv_key_attr_t *attr)
57 {
58     if (attr == NULL) {
59         return NV_NORMAL_KVALUE_MAX_LEN;
60     }
61     return (attr->encrypted ? NV_ENCRYPTED_KVALUE_MAX_LEN : NV_NORMAL_KVALUE_MAX_LEN);
62 }
63 
64 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
65 nv_direct_ctrl_t g_nv_direct_ctrl = { 0 };
nv_direct_get_nv_ctrl(void)66 nv_direct_ctrl_t *nv_direct_get_nv_ctrl(void)
67 {
68     return &g_nv_direct_ctrl;
69 }
70 #endif
71 
nv_direct_get_key_attr(uint16_t key_id,uint16_t * len,nv_key_attr_t * attr)72 errcode_t nv_direct_get_key_attr(uint16_t key_id, uint16_t *len, nv_key_attr_t *attr)
73 {
74     kv_attributes_t get_attribute = 0;
75     errcode_t ret = ERRCODE_SUCC;
76 
77     if (len == NULL || attr == NULL) {
78         return ERRCODE_NV_INVALID_PARAMS;
79     }
80 
81     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
82         return ERRCODE_NV_SEM_WAIT_ERR;
83     }
84 
85     *len = 0;
86     memset_s(attr, sizeof(nv_key_attr_t), 0, sizeof(nv_key_attr_t));
87     ret = kv_store_get_key_attr(KV_STORE_APPLICATION, key_id, len, &get_attribute);
88     if (ret == ERRCODE_SUCC) {
89         if (((uint32_t)get_attribute & NV_ATTRIBUTE_PERMANENT) != 0) {
90             attr->permanent = true;
91             attr->non_upgrade = true;
92         }
93 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
94         if (((uint32_t)get_attribute & NV_ATTRIBUTE_ENCRYPTED) != 0) {
95             attr->encrypted = true;
96             attr->non_upgrade = true;
97         }
98 #endif
99         if (((uint32_t)get_attribute & NV_ATTRIBUTE_NON_UPGRADE) != 0) {
100             attr->non_upgrade = true;
101         }
102     }
103     osal_sem_up(&nv_sem);
104     return ret;
105 }
106 
nv_direct_write_with_attr(uint16_t key_id,const uint8_t * kvalue,uint16_t kvalue_length,nv_key_attr_t * attr,nv_storage_completed_callback func)107 errcode_t nv_direct_write_with_attr(uint16_t key_id, const uint8_t *kvalue, uint16_t kvalue_length,
108     nv_key_attr_t *attr, nv_storage_completed_callback func)
109 {
110     errcode_t ret;
111     flash_task_node task_node = {0};
112     uint16_t len;
113     kv_attributes_t attribute = (kv_attributes_t)0;
114     unused(func);
115 
116     if (kvalue_length > nv_storage_max_key_space(attr)) {
117         nv_log_err("[NV] nv_direct_write_with_attr: len exceeds the max size. key_id = 0x%x\r\n", key_id);
118         return ERRCODE_NV_NO_ENOUGH_SPACE;
119     }
120 
121     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
122         nv_log_err("[NV] nv_direct_write_with_attr: semaphore error!\r\n");
123         return ERRCODE_NV_SEM_WAIT_ERR;
124     }
125 
126     ret = kv_store_get_key_attr(KV_STORE_APPLICATION, key_id, &len, &attribute);
127     if (ret == ERRCODE_SUCC) {
128         bool check_encry = false;
129 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
130         check_encry = ((((uint32_t)attribute & NV_ATTRIBUTE_ENCRYPTED) != 0) &&
131                       (attr == NULL || (attr->encrypted == false)));
132 #endif
133         if ((((uint32_t)attribute & NV_ATTRIBUTE_PERMANENT) != 0) || check_encry) {
134             /* When old key is permanent, not permit to write */
135             /* When old key is encrypted, new key is non-encrypted, not permit to write */
136             /* When old key is non upgrade, new key is write by ordinary write, not permit to write */
137             nv_log_err("[NV] nv_direct_write_with_attr: operation not allowed! key_id = 0x%x\r\n", key_id);
138             osal_sem_up(&nv_sem);
139             return ERRCODE_NV_ILLEGAL_OPERATION;
140         }
141     }
142     if (attr != NULL) { attribute = (uint8_t)nv_helper_convert_key_attr(attr); }
143     task_node.state_code = FLASH_TASK_READY;
144     task_node.data.kv.key = key_id;
145     task_node.data.kv.kvalue = kvalue;
146     task_node.data.kv.kvalue_length = kvalue_length;
147     task_node.data.kv.force_write = false;
148     task_node.data.kv.attribute = attribute;
149     ret = kv_update_write_key(KV_STORE_APPLICATION, &task_node);
150     osal_sem_up(&nv_sem);
151     if (ret != ERRCODE_SUCC) {
152         nv_log_err("[NV] nv_direct_write_with_attr failed. key_id = 0x%x, ret = 0x%x\r\n", key_id, ret);
153         return ret;
154     }
155 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
156     nv_change_notify(key_id);
157 #endif
158     return ERRCODE_SUCC;
159 }
160 
161 #ifdef CONFIG_NV_SUPPORT_WRITE_FORCE
nv_direct_write_force(uint16_t key_id,const uint8_t * kvalue,uint16_t kvalue_length)162 errcode_t nv_direct_write_force(uint16_t key_id, const uint8_t *kvalue, uint16_t kvalue_length)
163 {
164     errcode_t ret;
165     flash_task_node task_node = {0};
166     uint16_t len;
167     kv_attributes_t attribute = 0;
168 
169     if (kvalue_length > NV_NORMAL_KVALUE_MAX_LEN) {
170         return ERRCODE_NV_NO_ENOUGH_SPACE;
171     }
172 
173     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
174         return ERRCODE_NV_SEM_WAIT_ERR;
175     }
176 
177     ret = kv_store_get_key_attr(KV_STORE_APPLICATION, key_id, &len, &attribute);
178     if (ret == ERRCODE_SUCC) {
179 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
180         if (((uint32_t)attribute & NV_ATTRIBUTE_ENCRYPTED) != 0) {
181             /* When old key is encrypted, not permit to write */
182             osal_sem_up(&nv_sem);
183             return ERRCODE_NV_ILLEGAL_OPERATION;
184         }
185 #endif
186     }
187 
188     task_node.state_code = FLASH_TASK_READY;
189     task_node.data.kv.key = key_id;
190     task_node.data.kv.kvalue = kvalue;
191     task_node.data.kv.kvalue_length = kvalue_length;
192     task_node.data.kv.force_write = true;
193     task_node.data.kv.attribute = (uint8_t)NV_ATTRIBUTE_NORMAL;
194     ret = kv_update_write_key(KV_STORE_APPLICATION, &task_node);
195     osal_sem_up(&nv_sem);
196     if (ret != ERRCODE_SUCC) {
197         return ret;
198     }
199 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
200     nv_change_notify(key_id);
201 #endif
202     return ERRCODE_SUCC;
203 }
204 #endif
205 
nv_direct_get_key_data(uint16_t key_id,uint16_t kvalue_max_length,uint16_t * kvalue_length,uint8_t * kvalue,nv_key_attr_t * attr)206 errcode_t nv_direct_get_key_data(uint16_t key_id, uint16_t kvalue_max_length, uint16_t *kvalue_length,
207     uint8_t *kvalue, nv_key_attr_t *attr)
208 {
209     kv_attributes_t data_attribute = 0;
210 
211     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
212         return ERRCODE_NV_SEM_WAIT_ERR;
213     }
214 
215     kv_store_key_data_t key_data = {kvalue_max_length, 0, kvalue};
216     errcode_t ret_val = kv_store_get_key(KV_STORE_APPLICATION, key_id, &key_data, &data_attribute);
217     /* 如果在工作区没有找到该数据,可能存在数据被破坏情况,去备份区去找该数据 */
218     if (ret_val != ERRCODE_SUCC) {
219         ret_val = kv_store_read_backup_key(key_id, &key_data, &data_attribute);
220     }
221 
222     if (ret_val == ERRCODE_SUCC) {
223         if (((uint32_t)data_attribute & NV_ATTRIBUTE_PERMANENT) != 0) {
224             attr->permanent = true;
225             attr->non_upgrade = true;
226         }
227 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
228         if (((uint32_t)data_attribute & NV_ATTRIBUTE_ENCRYPTED) != 0) {
229             attr->encrypted = true;
230             attr->non_upgrade = true;
231         }
232 #endif
233         if (((uint32_t)data_attribute & NV_ATTRIBUTE_NON_UPGRADE) != 0) {
234             attr->non_upgrade = true;
235         }
236     }
237 
238     *kvalue_length = key_data.kvalue_actual_length;
239     osal_sem_up(&nv_sem);
240     return ret_val;
241 }
242 
243 #ifdef CONFIG_NV_SUPPORT_UPDATE_ATTR
nv_direct_update_key_attr(uint16_t key_id,nv_key_attr_t * attr,nv_storage_completed_callback func)244 errcode_t nv_direct_update_key_attr(uint16_t key_id, nv_key_attr_t *attr, nv_storage_completed_callback func)
245 {
246     errcode_t ret_val;
247     flash_task_node task_node = {0};
248     uint16_t len;
249     kv_attributes_t attribute = 0;
250     nv_key_attr_t new_attr;
251     unused(func);
252 
253     memcpy_s(&new_attr, sizeof(nv_key_attr_t), attr, sizeof(nv_key_attr_t));
254     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
255         return ERRCODE_NV_SEM_WAIT_ERR;
256     }
257 
258     ret_val = kv_store_get_key_attr(KV_STORE_APPLICATION, key_id, &len, &attribute);
259     if (ret_val != ERRCODE_SUCC) {
260         osal_sem_up(&nv_sem);
261         return ret_val;
262     }
263 
264     if (((uint32_t)attribute & NV_ATTRIBUTE_PERMANENT) != 0) {
265         osal_sem_up(&nv_sem);
266         return ERRCODE_SUCC;
267     }
268 #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
269     if (((uint32_t)attribute & NV_ATTRIBUTE_ENCRYPTED) != 0) {
270         /* if old key is encrypted, the new key must be encrypted too */
271         new_attr.encrypted = true;
272     }
273 #endif
274     task_node.state_code = FLASH_TASK_READY;
275     task_node.data.kv_attribute.key = key_id;
276     task_node.data.kv_attribute.attribute = (uint8_t)nv_helper_convert_key_attr(&new_attr);
277     ret_val = kv_update_modify_attribute(KV_STORE_APPLICATION, &task_node);
278     osal_sem_up(&nv_sem);
279     return ret_val;
280 }
281 #endif
282 
283 #ifdef CONFIG_NV_SUPPORT_DELETE_KEY
nv_direct_erase(uint16_t key_id)284 errcode_t nv_direct_erase(uint16_t key_id)
285 {
286     errcode_t ret_val;
287     uint16_t len = 0;
288     kv_attributes_t attribute = 0;
289     flash_task_node task_node = {0};
290     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
291         return ERRCODE_NV_SEM_WAIT_ERR;
292     }
293 
294     ret_val = kv_store_get_key_attr(KV_STORE_APPLICATION, key_id, &len, &attribute);
295     if (ret_val != ERRCODE_SUCC) {
296         osal_sem_up(&nv_sem);
297         return ret_val;
298     }
299 
300     if (((uint32_t)attribute & KV_ATTRIBUTE_PERMANENT) != 0) {
301         osal_sem_up(&nv_sem);
302         return ERRCODE_NV_ILLEGAL_OPERATION;
303     }
304 
305     task_node.data.kv_erase.key = key_id;
306     ret_val = kv_update_erase_key(KV_STORE_APPLICATION, &task_node);
307     osal_sem_up(&nv_sem);
308     return ret_val;
309 }
310 #endif
311 
nv_direct_get_store_status(nv_store_status_t * status)312 errcode_t nv_direct_get_store_status(nv_store_status_t *status)
313 {
314     errcode_t ret_val = ERRCODE_FAIL;
315     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
316         return ERRCODE_NV_SEM_WAIT_ERR;
317     }
318 
319     memset_s(status, sizeof(nv_store_status_t), 0, sizeof(nv_store_status_t));
320     ret_val = kv_store_get_status(KV_STORE_APPLICATION, status);
321     osal_sem_up(&nv_sem);
322     return ret_val;
323 }
324 
nv_direct_stored(uint16_t key_id,uint16_t kvalue_length,const uint8_t * kvalue)325 errcode_t nv_direct_stored(uint16_t key_id, uint16_t kvalue_length, const uint8_t *kvalue)
326 {
327     errcode_t ret = ERRCODE_SUCC;
328     uint8_t *stored_kvalue = NULL;
329     kv_attributes_t attribute = 0;
330 
331     if (kvalue_length > NV_NORMAL_KVALUE_MAX_LEN) {
332         return ERRCODE_NV_NO_ENOUGH_SPACE;
333     }
334 
335     stored_kvalue = (uint8_t *)(uintptr_t)kv_malloc(kvalue_length);
336     if (stored_kvalue == NULL) {
337         return ERRCODE_MALLOC;
338     }
339 
340     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
341         kv_free(stored_kvalue);
342         return ERRCODE_NV_SEM_WAIT_ERR;
343     }
344 
345     kv_store_key_data_t key_data = {kvalue_length, 0, stored_kvalue};
346     if (kv_store_get_key(KV_STORE_APPLICATION, key_id, &key_data, &attribute) != ERRCODE_SUCC) {
347         ret = ERRCODE_FAIL;
348     } else if ((key_data.kvalue_actual_length != kvalue_length) ||
349                (memcmp((void *)stored_kvalue, (void *)kvalue, kvalue_length) != 0)) {
350         ret = ERRCODE_FAIL;
351     }
352     osal_sem_up(&nv_sem);
353     kv_free(stored_kvalue);
354     return ret;
355 }
356 
nv_direct_backup_keys(const nv_backup_mode_t * backup_mode)357 errcode_t nv_direct_backup_keys(const nv_backup_mode_t *backup_mode)
358 {
359 #if (CONFIG_NV_SUPPORT_BACKUP_RESTORE == NV_YES)
360     errcode_t ret;
361 
362 #if (CONFIG_NV_SUPPORT_ASYNCHRONOUS_STORE == NV_YES)
363     /* 保证备份前,NV消息队列中数据写入flash */
364     ret = uapi_nv_flush();
365     if (ret != ERRCODE_SUCC) {
366         return ret;
367     }
368 #endif
369 
370     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
371         return ERRCODE_NV_SEM_WAIT_ERR;
372     }
373 
374     ret = kv_restore_set_region_flag(backup_mode->region_mode);
375     if (ret != ERRCODE_SUCC) {
376         osal_sem_up(&nv_sem);
377         return ret;
378     }
379     ret = kv_backup_delete_repeat_key();
380     if (ret != ERRCODE_SUCC) {
381         osal_sem_up(&nv_sem);
382         return ret;
383     }
384     ret = kv_backup_write_key();
385     osal_sem_up(&nv_sem);
386     return ret;
387 #else
388     unused(backup_mode);
389     return ERRCODE_NOT_SUPPORT;
390 #endif
391 }
392 
nv_direct_set_restore_flag_all(void)393 errcode_t nv_direct_set_restore_flag_all(void)
394 {
395 #if (CONFIG_NV_SUPPORT_BACKUP_RESTORE == NV_YES)
396     nv_reset_mode_t nv_reset_mode = {0};
397     nv_reset_mode.mode = RESET_MODE_A;
398     return kv_enable_restore_flag(&nv_reset_mode);
399 #else
400     return ERRCODE_NOT_SUPPORT;
401 #endif
402 }
403 
nv_direct_set_restore_flag_partitial(const nv_restore_mode_t * nv_restore_mode)404 errcode_t nv_direct_set_restore_flag_partitial(const nv_restore_mode_t *nv_restore_mode)
405 {
406 #if (CONFIG_NV_SUPPORT_BACKUP_RESTORE == NV_YES)
407     if (nv_restore_mode == NULL) {
408         return ERRCODE_NV_INVALID_PARAMS;
409     }
410     nv_reset_mode_t nv_reset_mode = {0};
411     if (memcpy_s(nv_reset_mode.region_flag, KEY_ID_REGION_MAX_NUM, nv_restore_mode, KEY_ID_REGION_MAX_NUM) != EOK) {
412         return ERRCODE_MEMCPY;
413     }
414     nv_reset_mode.mode = RESET_MODE_B;
415     return kv_enable_restore_flag(&nv_reset_mode);
416 #else
417     unused(nv_restore_mode);
418     return ERRCODE_NOT_SUPPORT;
419 #endif
420 }
421 
422 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
nv_direct_add_func_to_notify_list(uint16_t min_key,uint16_t max_key,nv_changed_notify_func func)423 errcode_t nv_direct_add_func_to_notify_list(uint16_t min_key, uint16_t max_key, nv_changed_notify_func func)
424 {
425     nv_direct_ctrl_t *nv_ctrl = nv_direct_get_nv_ctrl();
426     if (osal_sem_down_timeout(&nv_sem, 0xFFFFFFFF) != ERRCODE_SUCC) {
427         return ERRCODE_NV_SEM_WAIT_ERR;
428     }
429 
430     nv_changed_proc_t *notify_list = nv_ctrl->nv_change_notify_list;
431     if (notify_list == NULL) {
432         osal_sem_up(&nv_sem);
433         return ERRCODE_NV_NOT_INITIALISED;
434     }
435 
436     if (nv_ctrl->notify_registered_nums >= nv_ctrl->notify_regitser_max_nums) {
437         osal_sem_up(&nv_sem);
438         return ERRCODE_NV_NOTIFY_LIST_FULL;
439     }
440 
441     if (!nv_change_notify_segment_is_valid(nv_ctrl, min_key, max_key)) {
442         osal_sem_up(&nv_sem);
443         return ERRCODE_NV_NOTIFY_SEGMENT_ERR;
444     }
445 
446     uint8_t new_index = nv_ctrl->notify_registered_nums;
447     notify_list[new_index].min_key = min_key;
448     notify_list[new_index].max_key = max_key;
449     notify_list[new_index].func = func;
450     nv_ctrl->notify_registered_nums++;
451     osal_sem_up(&nv_sem);
452     return ERRCODE_SUCC;
453 }
454 #endif
455 
nv_direct_ctrl_init(void)456 void nv_direct_ctrl_init(void)
457 {
458     (void)kv_update_init((cores_t)KV_STORE_APPLICATION);
459 
460 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
461     nv_direct_ctrl_t *nv_ctrl = nv_direct_get_nv_ctrl();
462     memset_s(nv_ctrl, sizeof(nv_direct_ctrl_t), 0, sizeof(nv_direct_ctrl_t));
463 #endif
464 
465     if (osal_sem_binary_sem_init(&nv_sem, MAX_BINARY_VAL) != ERRCODE_SUCC) {
466         return;
467     }
468 #if (CONFIG_NV_SUPPORT_CHANGE_NOTIFY == NV_YES)
469     (void)nv_direct_notify_list_init();
470 #endif
471 #if (CONFIG_NV_SUPPORT_BACKUP_RESTORE == NV_YES)
472     (void)kv_update_backup_init();
473 #endif
474 #if (CONFIG_NV_SUPPORT_BACKUP_RESTORE == NV_YES)
475     (void)kv_restore_all_keys();
476 #endif
477 #if (CONFIG_NV_SUPPORT_ASYNCHRONOUS_STORE == NV_YES)
478     (void)nv_async_init(KV_STORE_APPLICATION, kv_store_get_page_count(KV_STORE_APPLICATION));
479 #endif
480     nv_log_info("nv init success!\r\n");
481 }
482