• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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