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