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 */
15
16 #include <efuse_opt.h>
17 #include <efuse.h>
18 #include <hi_cipher.h>
19
efuse_read(hi_u16 start_bit,hi_u16 size)20 hi_u32 efuse_read(hi_u16 start_bit, hi_u16 size)
21 {
22 hi_u8 count;
23 hi_u32 print_val;
24 hi_u8 line_cnt = U32_PER_LINE;
25 hi_u8 data[EFUSE_MAX_INDEX_SIZE] = { 0 };
26 hi_void *tmp_data = HI_NULL;
27 hi_u32 ret = efuse_bits_read(start_bit, size, data, EFUSE_MAX_INDEX_SIZE);
28 if (ret != HI_ERR_SUCCESS) {
29 return ret;
30 }
31
32 if (size < SIZE_32_BITS) {
33 *(volatile hi_u32 *)data &= ((1 << size) - 1);
34 size = SIZE_32_BITS;
35 } else if (size > SIZE_32_BITS && size < SIZE_64_BITS) {
36 *(volatile hi_u32 *)(data + WORD_WIDTH) &= ((1 << (size - SIZE_32_BITS)) - 1);
37 size = SIZE_64_BITS;
38 }
39
40 count = size >> SHIFT_5_BITS;
41 if (count < U32_PER_LINE) {
42 line_cnt = count;
43 }
44
45 tmp_data = (hi_void *)data;
46 while (count) {
47 boot_puthex(start_bit, 1);
48 serial_putc(':');
49 if (count < line_cnt) {
50 line_cnt = count;
51 }
52 /* Copy from memory into linebuf and print hex values */
53 for (hi_u8 i = 0; i < line_cnt; i++) {
54 print_val = *(volatile unsigned int *)tmp_data;
55 boot_puthex(print_val, 1);
56 tmp_data = (unsigned char *)tmp_data + WORD_WIDTH;
57 }
58 serial_putc('\n');
59
60 /* update references */
61 start_bit += line_cnt * WORD_WIDTH * BITS_PER_BYTE;
62 count -= line_cnt;
63 }
64 return HI_ERR_SUCCESS;
65 }
66
efuse_cfg_verify(uintptr_t file_addr,hi_u32 file_len)67 hi_u32 efuse_cfg_verify(uintptr_t file_addr, hi_u32 file_len)
68 {
69 hi_u32 ret;
70 hi_u8 hash[SHA_256_LENGTH] = {0};
71 efuse_config_header *header = (efuse_config_header *)file_addr;
72
73 if (header->file_size != file_len) {
74 return HI_ERR_FAILURE;
75 }
76
77 ret = hi_cipher_init();
78 if (ret != HI_ERR_SUCCESS) {
79 return ret;
80 }
81
82 ret = hi_cipher_hash_sha256((uintptr_t)&(header->stru_ver), header->file_size - SHA_256_LENGTH, hash,
83 SHA_256_LENGTH);
84 if (ret != HI_ERR_SUCCESS) {
85 return ret;
86 }
87
88 ret = hi_cipher_deinit();
89 if (ret != HI_ERR_SUCCESS) {
90 return ret;
91 }
92
93 if (memcmp(header->hash, hash, SHA_256_LENGTH) != EOK) {
94 return HI_ERR_FAILURE;
95 }
96
97 if (header->number > (HI_EFUSE_IDX_MAX + HI_EFUSE_LOCK_MAX)) {
98 return HI_ERR_FAILURE;
99 }
100
101 return HI_ERR_SUCCESS;
102 }
103
efuse_burn(uintptr_t file_addr,hi_u32 file_len)104 hi_u32 efuse_burn(uintptr_t file_addr, hi_u32 file_len)
105 {
106 hi_u32 ret = efuse_cfg_verify(file_addr, file_len);
107 if (ret != HI_ERR_SUCCESS) {
108 boot_msg0("Efuse config file invalid");
109 return HI_ERR_FAILURE;
110 }
111
112 efuse_config_header *header = (efuse_config_header *)file_addr;
113 efuse_config_item *item = (efuse_config_item *)(file_addr + header->stru_size);
114 for (hi_u8 i = 0; i < header->number; i++) {
115 if (item == HI_NULL) {
116 return HI_ERR_FAILURE;
117 }
118 ret = efuse_bits_write(item->start_bit, item->bit_width, item->value);
119 if (ret != HI_ERR_SUCCESS) {
120 boot_msg1("efuse write error, index:", i);
121 serial_puts("Start bit: ");
122 serial_puthex(item->start_bit, 1);
123 serial_puts(" len(bits)=");
124 serial_puthex(item->bit_width, 1);
125 serial_puts("\n");
126 }
127
128 item = (efuse_config_item *)((uintptr_t)item + item->stru_size + item->value_len);
129 }
130 return HI_ERR_SUCCESS;
131 }
132
133