1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include "drv_otp.h"
20 #include "drv_osal_lib.h"
21 #include "hal_otp.h"
22 #include "drv_osal_chip.h"
23
24 #define hal_otp_read_sta0(sta) hal_otp_read_word(OTP_USER_LOCK_STA0, sta)
25 #define hal_otp_read_rev_data(data) hal_otp_read_word(OTP_USER_REV_RDATA, data)
26
27 #define hal_otp_set_rev_addr(offset) hal_otp_write_word(OTP_USER_REV_ADDR, offset)
28 #define hal_otp_set_rev_data(data) hal_otp_write_word(OTP_USER_REV_WDATA, data)
29 #define hal_otp_set_work_mode(mode) hal_otp_write_word(OTP_USER_WORK_MODE, mode)
30 #define hal_otp_set_key_index(idx) hal_otp_write_word(OTP_USER_KEY_INDEX, idx);
31 #define hal_otp_set_flag_index(idx) hal_otp_write_word(OTP_USER_FLAG_INDEX, idx);
32 #define hal_otp_set_flag_value(value) hal_otp_write_word(OTP_USER_FLAG_VALUE, value);
33 #define hal_otp_op_start() hal_otp_write_word(OTP_USER_OP_START, OTP_OP_START_VAL)
34
hal_otp_wait_op_free(hi_void)35 static hi_s32 hal_otp_wait_op_free(hi_void)
36 {
37 hi_s32 ret;
38 hi_u32 time_out_cnt = OTP_WAIT_TIME_OUT;
39 hi_u32 sta;
40
41 while (time_out_cnt--) {
42 ret = hal_otp_read_word(OTP_USER_CTRL_STA, &sta);
43 hi_otp_func_fail_return(hal_otp_read_word, ret != HI_SUCCESS, ret);
44
45 if (((sta >> OTP_CTRL_STA_OP_BUSY) & 0x01) == 0) {
46 return HI_SUCCESS;
47 }
48 }
49 hi_otp_err("otp wait op timeout!\n");
50 return HI_ERR_OTP_BUSY;
51 }
52
53 /*
54 * if you want flag, please ensure that (offset != OTP_CTRL_STA_INVALID && flag != HI_NULL)
55 */
hal_otp_wait_cmd_finish(otp_user_ctrl_sta offset,hi_bool * flag)56 static hi_s32 hal_otp_wait_cmd_finish(otp_user_ctrl_sta offset, hi_bool *flag)
57 {
58 hi_s32 ret;
59 hi_u32 time_out_cnt = OTP_WAIT_TIME_OUT;
60 hi_u32 sta;
61
62 while (time_out_cnt--) {
63 ret = hal_otp_read_word(OTP_USER_CTRL_STA, &sta);
64 hi_otp_func_fail_return(hal_otp_read_word, ret != HI_SUCCESS, ret);
65
66 if (((sta >> OTP_CTRL_STA_USER_CMD_FINISH) & 0x01) == 1) {
67 break;
68 }
69 }
70
71 if (time_out_cnt == 0) {
72 hi_otp_err("otp wait op timeout!\n");
73 return HI_ERR_OTP_WAIT_TIMEOUT;
74 }
75
76 if (offset != OTP_CTRL_STA_INVALID && flag != HI_NULL) {
77 *flag = ((sta >> (hi_u32)offset) & 0x01);
78 }
79
80 return HI_SUCCESS;
81 }
82
hal_otp_get_user_lock_sta0(hi_u32 * sta0)83 hi_s32 hal_otp_get_user_lock_sta0(hi_u32 *sta0)
84 {
85 hi_s32 ret;
86
87 hi_otp_enter();
88
89 /* 1. wait otp ctrl free */
90 ret = hal_otp_wait_op_free();
91 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
92
93 /* 2. set work mode to read lock sta */
94 hal_otp_set_work_mode(OTP_WORK_MODE_READ_LOCK_STA);
95
96 /* 3. start otp ctrl */
97 hal_otp_op_start();
98
99 /* 4. wait user cmd finish */
100 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_INVALID, HI_NULL);
101 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
102
103 /* 5. read lock sta */
104 hal_otp_read_sta0(sta0);
105
106 hi_otp_exit();
107
108 return ret;
109 }
110
111 /*
112 * Note:
113 * write key: Writes key from a high address to a low address by word
114 * calculate crc: calculate crc according to the key write sequence by byte
115 */
hal_otp_write_key_data(const hi_u8 * u8_key,hi_u32 u8_klen)116 hi_s32 hal_otp_write_key_data(const hi_u8 *u8_key, hi_u32 u8_klen)
117 {
118 hi_s32 ret;
119 hi_u32 u32_key[OTP_USER_KEY_MAX_WORDS];
120 hi_u8 u8_tmp[OTP_USER_KEY_MAX_BYTES];
121 hi_u32 crc, i, u32_klen;
122
123 hi_otp_check_formula_fail(!align_word(u8_klen), HI_ERR_OTP_INVALID_PARAM);
124
125 (hi_void)otp_memset(u32_key, sizeof(u32_key), 0, sizeof(u32_key));
126 (hi_void)otp_memset(u8_tmp, sizeof(u8_tmp), 0, sizeof(u8_tmp));
127
128 hi_otp_print_arr_u8("u8_key", u8_key, u8_klen);
129
130 u32_klen = u8_klen / WORD_BYTE_WIDTH;
131
132 ret = otp_memcpy((hi_u8 *)u32_key, sizeof(u32_key), u8_key, u8_klen);
133 hi_otp_func_fail_return(otp_memcpy, ret != EOK, HI_ERR_OTP_FAILED_SEC_FUNC);
134
135 for (i = 0; i < u32_klen; i++) {
136 hal_otp_write_word(OTP_USER_KEY_DATA0 + i * WORD_BYTE_WIDTH, u32_key[i]);
137
138 ret = hi_otp_word_big_endian(u32_key[i], &u8_tmp[i * WORD_BYTE_WIDTH], WORD_BYTE_WIDTH);
139 hi_otp_func_fail_return(hi_otp_word_big_endian, ret != HI_SUCCESS, ret);
140 }
141 hi_otp_print_arr_u8("u8_tmp", u8_tmp, u8_klen);
142
143 crc = (0x0000ffff & hi_otp_crc16_modbus(u8_tmp, u8_klen));
144 hal_otp_write_word(OTP_USER_KEY_DATA0 + i * WORD_BYTE_WIDTH, crc);
145
146 hi_otp_info("crc value %x\n", crc);
147
148 return HI_SUCCESS;
149 }
150
hal_otp_check_key_sta(otp_user_key_index key_index,hi_u32 key_len)151 static hi_s32 hal_otp_check_key_sta(otp_user_key_index key_index, hi_u32 key_len)
152 {
153 hi_s32 ret;
154 otp_user_lock_sta0 sta0;
155
156 ret = hal_otp_get_user_lock_sta0(&sta0.u32);
157 hi_otp_func_fail_return(hal_otp_get_user_lock_sta0, ret != HI_SUCCESS, ret);
158
159 if ((key_index == OTP_USER_KEY0 && sta0.bits.key0_lock == 1) ||
160 (key_index == OTP_USER_KEY1 && sta0.bits.key1_lock == 1) ||
161 (key_index == OTP_USER_KEY2 && sta0.bits.key2_lock == 1) ||
162 (key_index == OTP_USER_KEY3 && sta0.bits.key3_lock == 1) ||
163 (key_index == OTP_USER_KEY_JTAG_PW_ID && sta0.bits.jtag_pw_id_lock == 1) ||
164 (key_index == OTP_USER_KEY_JTAG_PW && sta0.bits.jtag_pw_lock == 1) ||
165 (key_index == OTP_USER_KEY_ROOTKEY && sta0.bits.root_key_lock == 1) ||
166 (key_index == OTP_USER_KEY_HMACKEY && sta0.bits.hmac_key_lock == 1)) {
167 hi_otp_err("key slot %u had locked, sta0 %08x\n", key_index, sta0.u32);
168 return HI_ERR_OTP_ZONE_ALREADY_SET;
169 }
170 return HI_SUCCESS;
171 }
172
hal_otp_burn_key(const hi_otp_burn_pv_item * pv_item,const otp_data_item * data_item)173 hi_s32 hal_otp_burn_key(const hi_otp_burn_pv_item *pv_item, const otp_data_item *data_item)
174 {
175 hi_s32 ret;
176
177 hi_otp_enter();
178
179 /* 1. check user key status */
180 ret = hal_otp_check_key_sta(data_item->index, pv_item->value_len);
181 hi_otp_func_fail_return(hal_otp_check_key_sta, ret != HI_SUCCESS, ret);
182
183 /* 2. wait otp ctrl free */
184 ret = hal_otp_wait_op_free();
185 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
186
187 /* 3. set user key index */
188 hal_otp_set_key_index(data_item->index);
189
190 /* 4. write key data */
191 ret = hal_otp_write_key_data(pv_item->value, pv_item->value_len);
192 hi_otp_func_fail_return(hal_otp_write_key_data, ret != HI_SUCCESS, ret);
193
194 /* 5. set work mode */
195 hal_otp_set_work_mode(OTP_WORK_MODE_BURN_KEY);
196
197 /* 6. start otp ctrl */
198 hal_otp_op_start();
199
200 /* 7. wait user cmd finish */
201 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_INVALID, HI_NULL);
202 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
203
204 hi_otp_exit();
205
206 return ret;
207 }
208
hal_otp_verify_key(otp_user_key_index key_index,hi_bool * flag)209 hi_s32 hal_otp_verify_key(otp_user_key_index key_index, hi_bool *flag)
210 {
211 hi_s32 ret;
212
213 hi_otp_enter();
214
215 /* 1. wait otp ctrl free */
216 ret = hal_otp_wait_op_free();
217 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
218
219 /* 2. set key index */
220 hal_otp_set_key_index(key_index);
221
222 /* 3. set work mode to verify key crc */
223 hal_otp_set_work_mode(OTP_WORK_MODE_VERIFY_KEY_CRC);
224
225 /* 4. start otp ctrl */
226 hal_otp_op_start();
227
228 /* 5. wait user cmd finish & check key crc flag */
229 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_KEY_CRC_CHECK_OK_FLAG, flag);
230 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
231
232 if (*flag == 1) {
233 hi_otp_info("verify key crc %d ok\n", key_index);
234 } else {
235 hi_otp_info("verify key crc %d failed\n", key_index);
236 }
237
238 hi_otp_exit();
239
240 return ret;
241 }
242
hal_otp_load_key_to_klad(otp_user_key_index key_index)243 hi_s32 hal_otp_load_key_to_klad(otp_user_key_index key_index)
244 {
245 hi_s32 ret;
246
247 hi_otp_enter();
248
249 /* 1. wait otp ctrl free */
250 ret = hal_otp_wait_op_free();
251 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
252
253 /* 2. set key index */
254 hal_otp_set_key_index(key_index);
255
256 /* 3. set work mode to load key */
257 hal_otp_set_work_mode(OTP_WORK_MODE_LOAD_CIPHER_KEY);
258
259 /* 4. start otp ctrl */
260 hal_otp_op_start();
261
262 /* 5. wait user cmd finish */
263 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_INVALID, HI_NULL);
264 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
265
266 hi_otp_exit();
267
268 return ret;
269 }
270
hal_otp_check_flag_sta(otp_user_flag_index flag_index)271 static hi_s32 hal_otp_check_flag_sta(otp_user_flag_index flag_index)
272 {
273 hi_s32 ret;
274 otp_user_lock_sta0 sta0;
275
276 ret = hal_otp_get_user_lock_sta0(&sta0.u32);
277 hi_otp_func_fail_return(hal_otp_get_user_lock_sta0, ret != HI_SUCCESS, ret);
278
279 if ((flag_index == OTP_USER_FLAG_SECURE_BOOT_EN && sta0.bits.secure_boot_en_lock == 1) ||
280 (flag_index == OTP_USER_FLAG_DDR_CA_EN && sta0.bits.ddr_ca_en_lock == 1) ||
281 (flag_index == OTP_USER_FLAG_JTAG_CA_EN && sta0.bits.jtag_ca_en_lock == 1) ||
282 (flag_index == OTP_USER_FLAG_JTAG_PRT_MODE && sta0.bits.jtag_prt_mode_lock == 1) ||
283 (flag_index == OTP_USER_FLAG_UBOOT_REDUNDANCE && sta0.bits.uboot_redundance_lock == 1)) {
284 hi_otp_err("flag %u had locked!!!\n", flag_index);
285 return HI_ERR_OTP_ZONE_ALREADY_SET;
286 }
287
288 return HI_SUCCESS;
289 }
290
hal_otp_write_flag_value(otp_user_flag_index flag_index,hi_u32 value,hi_u32 lock)291 hi_s32 hal_otp_write_flag_value(otp_user_flag_index flag_index, hi_u32 value, hi_u32 lock)
292 {
293 otp_user_flag_value flag_value;
294
295 flag_value.u32 = 0;
296
297 if (flag_index == OTP_USER_FLAG_JTAG_PRT_MODE) {
298 hi_otp_check_formula_fail(value > 0x03, HI_ERR_OTP_INVALID_PARAM);
299
300 flag_value.bits.jtag_prt_mode = value;
301 if (lock == HI_TRUE) {
302 flag_value.bits.jtag_prt_mode_lock_en = 1;
303 }
304 } else {
305 hi_otp_check_formula_fail(value > 0x01, HI_ERR_OTP_INVALID_PARAM);
306 switch (flag_index) {
307 case OTP_USER_FLAG_SECURE_BOOT_EN:
308 flag_value.bits.secure_boot_en = value;
309 break;
310 case OTP_USER_FLAG_DDR_CA_EN:
311 flag_value.bits.ddr_ca_en = value;
312 break;
313 case OTP_USER_FLAG_JTAG_CA_EN:
314 flag_value.bits.jtag_ca_en = value;
315 break;
316 case OTP_USER_FLAG_UBOOT_REDUNDANCE:
317 flag_value.bits.uboot_redundance = value;
318 break;
319 default:
320 hi_otp_err("flag index %d is invalid\n", flag_index);
321 return HI_ERR_OTP_INVALID_PARAM;
322 }
323 }
324 hal_otp_set_flag_value(flag_value.u32);
325
326 return HI_SUCCESS;
327 }
328
hal_otp_enable_flag(const hi_otp_burn_pv_item * pv_item,const otp_data_item * data_item)329 hi_s32 hal_otp_enable_flag(const hi_otp_burn_pv_item *pv_item, const otp_data_item *data_item)
330 {
331 hi_s32 ret;
332
333 hi_otp_enter();
334
335 /* 1. check flag status */
336 ret = hal_otp_check_flag_sta(data_item->index);
337 hi_otp_func_fail_return(hal_otp_check_flag_sta, ret != HI_SUCCESS, ret);
338
339 /* 2. wait otp ctrl free */
340 ret = hal_otp_wait_op_free();
341 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
342
343 /* 3. set flag index */
344 hal_otp_set_flag_index(data_item->index);
345
346 /* 4. set flag value */
347 ret = hal_otp_write_flag_value(data_item->index, pv_item->value[0], pv_item->lock);
348 hi_otp_func_fail_return(hal_otp_write_flag_value, ret != HI_SUCCESS, ret);
349
350 /* 5. set work mode to enable flag config */
351 hal_otp_set_work_mode(OTP_WORK_MODE_ENABLE_FLAG_CFG);
352
353 /* 6. start otp ctrl */
354 hal_otp_op_start();
355
356 /* 7. wait user cmd finish */
357 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_INVALID, HI_NULL);
358 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
359
360 hi_otp_exit();
361
362 return ret;
363 }
364
hal_otp_set_user_data_word(hi_u32 index,hi_u32 value)365 hi_s32 hal_otp_set_user_data_word(hi_u32 index, hi_u32 value)
366 {
367 hi_s32 ret;
368 hi_bool lock;
369
370 /* 1. wait otp ctrl free */
371 ret = hal_otp_wait_op_free();
372 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
373
374 /* 2. set rev addr */
375 hal_otp_set_rev_addr(index);
376
377 /* 3. write rev data */
378 hal_otp_set_rev_data(value);
379
380 /* 4. set work mode to write user room */
381 hal_otp_set_work_mode(OTP_WORK_MODE_WRITE_USER_ROOM);
382
383 /* 5. start otp ctrl */
384 hal_otp_op_start();
385
386 /* 6. wait user cmd finish */
387 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_USER_LOCK_ERR, &lock);
388 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
389
390 if (lock == 1) {
391 hi_otp_err("index %u has locked\n", index);
392 return HI_ERR_OTP_ZONE_LOCKED;
393 }
394 return ret;
395 }
396
hal_otp_get_user_data_word(hi_u32 index,hi_u32 * value)397 hi_s32 hal_otp_get_user_data_word(hi_u32 index, hi_u32 *value)
398 {
399 hi_s32 ret;
400
401 /* 1. wait otp ctrl free */
402 ret = hal_otp_wait_op_free();
403 hi_otp_func_fail_return(hal_otp_wait_op_free, ret != HI_SUCCESS, ret);
404
405 /* 2. set rev addr */
406 hal_otp_set_rev_addr(index);
407
408 /* 3. set work mode to read user room */
409 hal_otp_set_work_mode(OTP_WORK_MODE_READ_USER_ROOM);
410
411 /* 4. start otp ctrl */
412 hal_otp_op_start();
413
414 /* 5. wait user cmd finish */
415 ret = hal_otp_wait_cmd_finish(OTP_CTRL_STA_INVALID, HI_NULL);
416 hi_otp_func_fail_return(hal_otp_wait_cmd_finish, ret != HI_SUCCESS, ret);
417
418 /* 6. read rev data */
419 hal_otp_read_rev_data(value);
420
421 return ret;
422 }
423
drv_otp_match_field_name(const hi_char * field_name)424 otp_data_item *drv_otp_match_field_name(const hi_char *field_name)
425 {
426 hi_u32 i;
427
428 for (i = 0; i < array_size(g_otp_data_item); i++) {
429 if ((strlen(field_name) != strlen(g_otp_data_item[i].field_name)) ||
430 (memcmp(g_otp_data_item[i].field_name, field_name, strlen(field_name)) != 0)) {
431 continue;
432 }
433
434 hi_otp_log("match %d field name %s\n", i, field_name);
435 return &g_otp_data_item[i];
436 }
437 hi_otp_err("field name %s don't match\n", field_name);
438 return HI_NULL;
439 }
440
drv_otp_set_user_data(const hi_char * field_name,hi_u32 offset,const hi_u8 * value,hi_u32 value_len)441 hi_s32 drv_otp_set_user_data(const hi_char *field_name,
442 hi_u32 offset, const hi_u8 *value, hi_u32 value_len)
443 {
444 hi_s32 ret;
445 hi_u32 *word = HI_NULL;
446 hi_u32 i, word_len, byte_len;
447 const otp_data_item *item = HI_NULL;
448
449 hi_otp_enter();
450
451 hi_otp_check_formula_fail(field_name == HI_NULL, HI_ERR_OTP_NULL_PTR);
452 hi_otp_check_formula_fail(value == HI_NULL, HI_ERR_OTP_NULL_PTR);
453 hi_otp_check_formula_fail(value_len == 0, HI_ERR_OTP_INVALID_PARAM);
454 hi_otp_check_formula_fail(!align_word(offset), HI_ERR_OTP_INVALID_PARAM);
455
456 /* match field name */
457 item = drv_otp_match_field_name(field_name);
458 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
459
460 /* avoid a + b overflow */
461 hi_otp_check_formula_fail(offset + value_len < value_len, HI_ERR_OTP_INVALID_PARAM);
462
463 /* check user name real max size: offset + value_len can't longer than max size */
464 hi_otp_check_formula_fail(offset + value_len > item->value_len, HI_ERR_OTP_INVALID_PARAM);
465
466 word_len = word_number(value_len);
467 byte_len = word_len * WORD_BYTE_WIDTH;
468
469 word = otp_malloc(byte_len);
470 hi_otp_func_fail_return(otp_malloc, word == HI_NULL, HI_ERR_OTP_FAILED_MEM);
471
472 (hi_void)otp_memset(word, byte_len, 0, byte_len);
473 ret = otp_memcpy(word, byte_len, value, value_len);
474 hi_otp_func_fail_goto(otp_memcpy, ret != EOK, HI_ERR_OTP_FAILED_SEC_FUNC);
475
476 hi_otp_print_arr_u32("set user data", word, word_len);
477
478 if (item->attr & OTP_ATTR_RESERVED_DATA) {
479 for (i = 0; i < word_len; i++) {
480 ret = hal_otp_set_user_data_word(offset / WORD_BYTE_WIDTH + i, word[i]);
481 hi_otp_func_fail_goto(hal_otp_get_user_data_word, ret != HI_SUCCESS, ret);
482 }
483 } else {
484 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
485 ret = HI_ERR_OTP_INVALID_FIELD_NAME;
486 goto otp_exit;
487 }
488
489 otp_exit:
490 if (word != HI_NULL) {
491 otp_free(word);
492 word = HI_NULL;
493 }
494 hi_otp_exit();
495 return ret;
496 }
497
drv_otp_get_user_data(const hi_char * field_name,hi_u32 offset,hi_u8 * value,hi_u32 value_len)498 hi_s32 drv_otp_get_user_data(const hi_char *field_name,
499 hi_u32 offset, hi_u8 *value, hi_u32 value_len)
500 {
501 hi_s32 ret;
502 hi_u32 *word = HI_NULL;
503 hi_u32 i, word_len, byte_len;
504 const otp_data_item *item = HI_NULL;
505
506 hi_otp_enter();
507
508 hi_otp_check_formula_fail(!align_word(offset), HI_ERR_OTP_INVALID_PARAM);
509 hi_otp_check_formula_fail(field_name == HI_NULL, HI_ERR_OTP_NULL_PTR);
510 hi_otp_check_formula_fail(value == HI_NULL, HI_ERR_OTP_NULL_PTR);
511 hi_otp_check_formula_fail(value_len == 0, HI_ERR_OTP_INVALID_PARAM);
512
513 /* match field name */
514 item = drv_otp_match_field_name(field_name);
515 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
516
517 /* avoid a + b overflow */
518 hi_otp_check_formula_fail(offset + value_len < value_len, HI_ERR_OTP_INVALID_PARAM);
519
520 /* check user name real max size: offset + value_len can't longer than max size */
521 hi_otp_check_formula_fail(offset + value_len > item->value_len, HI_ERR_OTP_INVALID_PARAM);
522
523 word_len = word_number(value_len);
524 byte_len = word_len * WORD_BYTE_WIDTH;
525
526 word = otp_malloc(byte_len);
527 hi_otp_func_fail_return(otp_malloc, word == HI_NULL, HI_ERR_OTP_FAILED_MEM);
528
529 (hi_void)otp_memset(word, byte_len, 0, byte_len);
530
531 if (item->attr & OTP_ATTR_RESERVED_DATA) {
532 for (i = 0; i < word_len; i++) {
533 ret = hal_otp_get_user_data_word(offset / WORD_BYTE_WIDTH + i, &word[i]);
534 hi_otp_func_fail_goto(hal_otp_get_user_data_word, ret != HI_SUCCESS, ret);
535 }
536 } else {
537 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
538 ret = HI_ERR_OTP_INVALID_FIELD_NAME;
539 goto otp_exit;
540 }
541
542 ret = otp_memcpy(value, value_len, (hi_u8 *)word, value_len);
543 hi_otp_func_fail_goto(otp_memcpy, ret != EOK, HI_ERR_OTP_FAILED_SEC_FUNC);
544
545 otp_exit:
546 if (word != HI_NULL) {
547 otp_free(word);
548 word = HI_NULL;
549 }
550 hi_otp_exit();
551 return ret;
552 }
553
drv_otp_burn_product_pv(const hi_otp_burn_pv_item * pv,hi_u32 num)554 hi_s32 drv_otp_burn_product_pv(const hi_otp_burn_pv_item *pv, hi_u32 num)
555 {
556 hi_s32 ret;
557 hi_u32 i;
558 const otp_data_item *item = HI_NULL;
559
560 hi_otp_check_formula_fail(pv == HI_NULL, HI_ERR_OTP_NULL_PTR);
561 hi_otp_check_formula_fail(num == 0, HI_ERR_OTP_INVALID_PARAM);
562
563 for (i = 0; i < num; i++) {
564 item = drv_otp_match_field_name(pv[i].field_name);
565 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
566
567 /* check pv param */
568 hi_otp_check_formula_fail(pv[i].burn != HI_TRUE, HI_ERR_OTP_INVALID_PARAM);
569 hi_otp_check_formula_fail(pv[i].value_len != item->value_len, HI_ERR_OTP_INVALID_PARAM);
570 hi_otp_check_formula_fail(pv[i].lock != HI_TRUE && pv[i].lock != HI_FALSE, HI_ERR_OTP_INVALID_PARAM);
571
572 if (item->attr & OTP_ATTR_BURN_KEY) {
573 ret = hal_otp_burn_key(pv, item);
574 hi_otp_func_fail_return(hal_otp_burn_key, ret != HI_SUCCESS, ret);
575 } else if (item->attr & OTP_ATTR_ENABLE_FLAG) {
576 ret = hal_otp_enable_flag(pv, item);
577 hi_otp_func_fail_return(hal_otp_enable_flag, ret != HI_SUCCESS, ret);
578 } else {
579 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
580 return HI_ERR_OTP_INVALID_FIELD_NAME;
581 }
582 }
583 return ret;
584 }
585
drv_otp_read_product_pv(hi_otp_burn_pv_item * pv,hi_u32 num)586 hi_s32 drv_otp_read_product_pv(hi_otp_burn_pv_item *pv, hi_u32 num)
587 {
588 hi_u32 i;
589 const otp_data_item *item = HI_NULL;
590
591 hi_otp_check_formula_fail(pv == HI_NULL, HI_ERR_OTP_NULL_PTR);
592 hi_otp_check_formula_fail(num == 0, HI_ERR_OTP_INVALID_PARAM);
593
594 for (i = 0; i < num; i++) {
595 item = drv_otp_match_field_name(pv[i].field_name);
596 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
597
598 hi_otp_check_formula_fail(pv[i].burn != HI_FALSE, HI_ERR_OTP_INVALID_PARAM);
599 hi_otp_check_formula_fail(pv[i].value_len != item->value_len, HI_ERR_OTP_INVALID_PARAM);
600
601 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
602 return HI_ERR_OTP_INVALID_FIELD_NAME;
603 }
604 return HI_SUCCESS;
605 }
606
drv_otp_get_key_verify_status(const hi_char * key_name,hi_bool * status)607 hi_s32 drv_otp_get_key_verify_status(const hi_char *key_name, hi_bool *status)
608 {
609 hi_s32 ret;
610 const otp_data_item *item = HI_NULL;
611
612 hi_otp_check_formula_fail(key_name == HI_NULL, HI_ERR_OTP_NULL_PTR);
613 hi_otp_check_formula_fail(status == HI_NULL, HI_ERR_OTP_NULL_PTR);
614
615 item = drv_otp_match_field_name(key_name);
616 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
617
618 if (item->attr & OTP_ATTR_VERIFY_KEY) {
619 ret = hal_otp_verify_key(item->index, status);
620 hi_otp_func_fail_return(hal_otp_verify_key, ret != HI_SUCCESS, ret);
621 } else {
622 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
623 return HI_ERR_OTP_INVALID_FIELD_NAME;
624 }
625
626 return HI_SUCCESS;
627 }
628
drv_otp_load_key_to_klad(const hi_char * key_name)629 hi_s32 drv_otp_load_key_to_klad(const hi_char *key_name)
630 {
631 hi_s32 ret;
632 const otp_data_item *item = HI_NULL;
633
634 hi_otp_check_formula_fail(key_name == HI_NULL, HI_ERR_OTP_NULL_PTR);
635
636 item = drv_otp_match_field_name(key_name);
637 hi_otp_func_fail_return(drv_otp_match_field_name, item == HI_NULL, HI_ERR_OTP_INVALID_FIELD_NAME);
638
639 if (item->attr & OTP_ATTR_LOAD_KEY) {
640 ret = hal_otp_load_key_to_klad(item->index);
641 hi_otp_func_fail_return(drv_otp_match_field_name, ret != HI_SUCCESS, ret);
642 } else {
643 hi_otp_err("%s don't match attribution %x\n", item->field_name, item->attr);
644 return HI_ERR_OTP_INVALID_FIELD_NAME;
645 }
646
647 return ret;
648 }
649
650