1 /*
2 * =====================================================================================
3 *
4 * Filename: hal_efuse.c
5 *
6 * Description: efuse
7 *
8 * Version: 1.0
9 * Created: 2019-07-19
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: wangwei
14 * Organization:
15 *
16 * =====================================================================================
17 */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <sunxi_hal_efuse.h>
22 #include <sunxi_hal_common.h>
23 #include <hal_osal.h>
24
25 #include "platform_efuse.h"
26 #include "efuse.h"
27
28 #define EFUSE_CHIPID_NAME "chipid"
29 #define EFUSE_BROM_CONF_NAME "brom_conf"
30 #define EFUSE_BROM_TRY_NAME "brom_try"
31 #define EFUSE_THM_SENSOR_NAME "thermal_sensor"
32
33 #define EFUSE_FT_ZONE_NAME "ft_zone"
34 #define EFUSE_TV_OUT_NAME "tvout"
35 #define EFUSE_OEM_NAME "oem"
36 #define EFUSE_OEM_SEC_NAME "oem_secure"
37 #define EFUSE_EMAC_NAME "emac"
38
39 #define EFUSE_WR_PROTECT_NAME "write_protect"
40 #define EFUSE_RD_PROTECT_NAME "read_protect"
41 #define EFUSE_IN_NAME "in"
42 #define EFUSE_ID_NAME "id"
43 #define EFUSE_ROTPK_NAME "rotpk"
44 #define EFUSE_SSK_NAME "ssk"
45 #define EFUSE_RSSK_NAME "rssk"
46 #define EFUSE_HDCP_HASH_NAME "hdcp_hash"
47 #define EFUSE_HDCP_PKF_NAME "hdcp_pkf"
48 #define EFUSE_HDCP_DUK_NAME "hdcp_duk"
49 #define EFUSE_EK_HASH_NAME "ek_hash"
50 #define EFUSE_SN_NAME "sn"
51 #define EFUSE_NV1_NAME "nv1"
52 #define EFUSE_NV2_NAME "nv2"
53 #define EFUSE_BACKUP_KEY_NAME "backup_key"
54 #define EFUSE_RSAKEY_HASH_NAME "rsakey_hash"
55 #define EFUSE_RENEW_NAME "renewability"
56 #define EFUSE_IPTV_MAC "efusemac"
57 #define EFUSE_OPT_ID_NAME "operator_id"
58 #define EFUSE_LIFE_CYCLE_NAME "life_cycle"
59 #define EFUSE_JTAG_SECU_NAME "jtag_security"
60 #define EFUSE_JTAG_ATTR_NAME "jtag_attr"
61 #define EFUSE_CHIP_CONF_NAME "chip_config"
62 #define EFUSE_RESERVED_NAME "reserved"
63 #define EFUSE_RESERVED2_NAME "reserved2"
64 #define EFUSE_HUK_NAME "huk"
65 #define EFUSE_ANTI_BLUSH_NAME "anti_blushing"
66 #define EFUSE_TVE_NAME "tve"
67
68 /* For KeyLadder */
69 #define EFUSE_KL_SCK0_NAME "keyladder_sck0"
70 #define EFUSE_KL_KEY0_NAME "keyladder_master_key0"
71 #define EFUSE_KL_SCK1_NAME "keyladder_sck1"
72 #define EFUSE_KL_KEY1_NAME "keyladder_master_key1"
73
74 #define SUNXI_KEY_NAME_LEN 64
75
76
77 #if EFUSE_DBG_EN
78 #define EFUSE_DBG(fmt,args...) hal_log_debug(fmt ,##args)
79 #define EFUSE_DBG_E 1
80 static unsigned int g_err_flg = 0;
81 #else
82 #define EFUSE_DBG_DUMP(...) do{} while(0);
83 #define EFUSE_DBG(...) do{} while(0);
84 #define EFUSE_DBG_E 0
85 #endif
86
87 static hal_spinlock_t efuse_lock;
88
89 int __efuse_acl_ck(efuse_key_map_new_t *key_map,int burn);
90
91
92 static efuse_key_map_new_t g_key_info[] = {
93 EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME, 0x0, 128, -1, 0, EFUSE_RO),
94 EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME, EFUSE_THERMAL_SENSOR, 64, -1, 0, EFUSE_RO),
95 EFUSE_DEF_ITEM(EFUSE_FT_ZONE_NAME, EFUSE_TF_ZONE, 128, -1, 0, EFUSE_RO),
96 #ifdef EFUSE_ROTPK
97 EFUSE_DEF_ITEM(EFUSE_ROTPK_NAME, EFUSE_ROTPK, 256, -1, 12, EFUSE_RO),
98 #endif
99 #ifdef EFUSE_NV1
100 EFUSE_DEF_ITEM(EFUSE_NV1_NAME, EFUSE_NV1, 32, -1, 15, EFUSE_RO),
101 #endif
102 #ifdef EFUSE_PSENSOR
103 EFUSE_DEF_ITEM("psensor", EFUSE_PSENSOR, 32, -1, 15, EFUSE_RO),
104 #endif
105 #ifdef EFUSE_TVOUT
106 EFUSE_DEF_ITEM(EFUSE_TV_OUT_NAME, EFUSE_TVOUT, SID_TVOUT_SIZE, -1, -1, EFUSE_RO),
107 #endif
108 //EFUSE_DEF_ITEM("anti_blushing", EFUSE_ANTI_BLUSHING, 32, -1, 15, EFUSE_RO),
109 //EFUSE_DEF_ITEM(EFUSE_RESERVED_NAME, EFUSE_CLIENT_RESERVE, 256, -1, 12, EFUSE_RO),
110 EFUSE_DEF_ITEM("", 0, 0, 0, 0, EFUSE_PRIVATE),
111 };
112
113
_efuse_reg_read_key(uint key_index)114 static uint _efuse_reg_read_key(uint key_index)
115 {
116 uint reg_val;
117 uint32_t cpu_sr;
118
119 // taskENTER_CRITICAL(cpu_sr);
120 //rt_enter_critical();
121 cpu_sr = hal_spin_lock_irqsave(&efuse_lock);
122
123 reg_val = hal_readl((unsigned long)SID_PRCTL);
124 reg_val &= ~((0x1ff<<16)|0x3);
125 reg_val |= key_index<<16;
126 hal_writel(reg_val, (unsigned long)SID_PRCTL);
127 reg_val &= ~((0xff<<8)|0x3);
128 reg_val |= (SID_OP_LOCK<<8) | 0x2;
129 hal_writel(reg_val, (unsigned long)SID_PRCTL);
130 while(hal_readl(SID_PRCTL)&0x2){};
131 reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
132 hal_writel(reg_val, (unsigned long)SID_PRCTL);
133 reg_val = hal_readl((unsigned long)SID_RDKEY);
134
135 hal_spin_unlock_irqrestore(&efuse_lock, cpu_sr);
136 //rt_exit_critical();
137 // taskEXIT_CRITICAL(cpu_sr);
138 return reg_val;
139 }
140
141
_efuse_program_key(uint key_index,uint key_value)142 static void _efuse_program_key(uint key_index, uint key_value)
143 {
144 uint reg_val;
145 uint32_t cpu_sr;
146
147 // taskENTER_CRITICAL(cpu_sr);
148 cpu_sr = hal_spin_lock_irqsave(&efuse_lock);
149
150 #ifdef EFUSE_HV_SWITCH
151 hal_writel(0x1, (unsigned long)EFUSE_HV_SWITCH);
152 #endif
153 hal_writel(key_value, SID_PRKEY);
154 reg_val = hal_readl((unsigned long)SID_PRCTL);
155 reg_val &= ~((0x1ff<<16)|0x3);
156 reg_val |= key_index<<16;
157 hal_writel(reg_val, (unsigned long)SID_PRCTL);
158 reg_val &= ~((0xff<<8)|0x3);
159 reg_val |= (SID_OP_LOCK<<8) | 0x1;
160 hal_writel(reg_val, (unsigned long)SID_PRCTL);
161 while(hal_readl((unsigned long)SID_PRCTL)&0x1){};
162 reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
163 hal_writel(reg_val, (unsigned long)SID_PRCTL);
164
165 #ifdef EFUSE_HV_SWITCH
166 hal_writel(0x0, (unsigned long)EFUSE_HV_SWITCH);
167 #endif
168 hal_spin_unlock_irqrestore(&efuse_lock, cpu_sr);
169 // taskEXIT_CRITICAL(cpu_sr);
170 return ;
171 }
172
_get_burned_flag(efuse_key_map_new_t * key_map)173 static int _get_burned_flag(efuse_key_map_new_t *key_map)
174 {
175 if(key_map->burned_flg_offset < 0)
176 {
177 EFUSE_DBG("_get_burned_flag offset:%d\n", key_map->burned_flg_offset);
178 return 0;
179 }
180 else
181 {
182 EFUSE_DBG("_get_burned_flag val:%d\n", _efuse_reg_read_key(EFUSE_WRITE_PROTECT));
183 return (_efuse_reg_read_key(EFUSE_WRITE_PROTECT)
184 >> (key_map->burned_flg_offset & EFUSE_BRUN_RD_OFFSET_MASK)) & 1;
185 }
186 }
187
_sw_acl_ck(efuse_key_map_new_t * key_map,int burn)188 static int _sw_acl_ck(efuse_key_map_new_t *key_map,int burn)
189 {
190 if(key_map->sw_rule == EFUSE_PRIVATE)
191 {
192 EFUSE_DBG("\n[efuse]%s: PRIVATE\n",key_map->name);
193 return EFUSE_ERR_PRIVATE;
194 }
195 if(burn==0)
196 {
197 if(key_map->sw_rule == EFUSE_NACCESS)
198 {
199 EFUSE_DBG("\n[efuse]%s:NACCESS\n",key_map->name);
200 return EFUSE_ERR_NO_ACCESS;
201 }
202 }
203 else
204 {
205 /*If already burned:*/
206 if(_get_burned_flag(key_map))
207 {
208 EFUSE_DBG("\n[efuse]%s: already burned\n",key_map->name);
209 EFUSE_DBG("config reg:0x%x\n",efuse_sram_read_key(EFUSE_WRITE_PROTECT));
210 if(key_map->sw_rule == EFUSE_NACCESS)
211 return EFUSE_ERR_NO_ACCESS;
212 return EFUSE_ERR_ALREADY_BURNED;
213 }
214 if(key_map->sw_rule == EFUSE_RW)
215 {
216 /*modify burned_flg_offset&&rd_fbd_offset in case of the config bits been burned*/
217 key_map->burned_flg_offset |= EFUSE_ACL_SET_BRUN_BIT;
218 key_map->rd_fbd_offset |= EFUSE_ACL_SET_RD_FORBID_BIT;
219 }
220 else if(key_map->sw_rule == EFUSE_RO)
221 {
222 /*modify rd_fbd_offset in case of the config bit been burned*/
223 key_map->rd_fbd_offset |= EFUSE_ACL_SET_RD_FORBID_BIT;
224 }
225 }
226 return 0;
227 }
228
229
efuse_sram_read_key(uint key_index)230 uint efuse_sram_read_key(uint key_index)
231 {
232 return hal_readl((unsigned long)EFUSE_SRAM + key_index);
233 }
234
235
236 /*Please reference 1728 spec page11 to know why to call _efuse_reg_read_key
237 * but efuse_sram_read_key
238 *burn efuse :efuse sram can not get the latest value
239 *unless via sid read or reboot.
240 */
efuse_uni_burn_key(uint key_index,uint key_value)241 int efuse_uni_burn_key(uint key_index, uint key_value)
242 {
243 #define EFUSE_BURN_MAX_TRY_CNT 3
244 uint key_burn_bitmask = ~(efuse_sram_read_key(key_index)) & key_value;
245 int fail = 0;
246
247 while(key_burn_bitmask)
248 {
249 _efuse_program_key(key_index,key_burn_bitmask);
250
251 if(fail > EFUSE_BURN_MAX_TRY_CNT)
252 {
253 EFUSE_DBG("%s: **failed **",
254 __func__);
255 #if EFUSE_DBG_E
256 g_err_flg++;
257 #endif
258 return -1;
259 }
260 key_burn_bitmask &= (~(_efuse_reg_read_key(key_index)));
261 fail++;
262 }
263 return 0;
264 }
265
266
efuse_set_cfg_flg(int efuse_cfg_base,int bit_offset)267 void efuse_set_cfg_flg(int efuse_cfg_base,int bit_offset)
268 {
269 if(efuse_uni_burn_key(efuse_cfg_base,(1<<bit_offset)))
270 {
271 EFUSE_DBG("[efuse] %s %d fatal err: **_set_cfg_flg [base:%d][offset:%d] **",
272 __FILE__,__LINE__,efuse_cfg_base,bit_offset);
273 }
274 return;
275 }
276
277
278
279 /*Efuse access control rule check.*/
efuse_acl_ck(efuse_key_map_new_t * key_map,int burn)280 int efuse_acl_ck(efuse_key_map_new_t *key_map,int burn)
281 {
282 /*For normal solution only check EFUSE_PRIVATE,other will be seemed as EFUSE_RW */
283 if(hal_efuse_get_security_mode() == 0)
284 {
285 if(key_map->sw_rule == EFUSE_PRIVATE)
286 {
287 return EFUSE_ERR_PRIVATE;
288 }
289 return 0;
290 }
291
292 int ret = _sw_acl_ck(key_map,burn);
293 if(ret)
294 {
295 EFUSE_DBG("[efuse]%s sw check failed\n",key_map->name);
296 return ret;
297 }
298 if(burn)
299 {
300 EFUSE_DBG("[efuse]burn %s burned bit check begin\n",key_map->name);
301 if(_get_burned_flag(key_map))
302 {
303 /*already burned*/
304 EFUSE_DBG("[efuse]%s:already burned\n",key_map->name);
305 EFUSE_DBG("config reg:0x%x\n",efuse_sram_read_key(EFUSE_WRITE_PROTECT));
306 return EFUSE_ERR_ALREADY_BURNED;
307 }
308 EFUSE_DBG("[efuse]burn %s burned bit check end\n",key_map->name);
309 }
310 else
311 {
312 if((key_map->rd_fbd_offset>=0)&&
313 ((efuse_sram_read_key(EFUSE_READ_PROTECT) >>
314 (key_map->rd_fbd_offset & EFUSE_BRUN_RD_OFFSET_MASK)) & 1))
315 {
316 /*Read is not allowed because of the read forbidden bit was set*/
317 EFUSE_DBG("[efuse]%s forbid bit set\n",key_map->name);
318 EFUSE_DBG("config reg:0x%x\n",efuse_sram_read_key(EFUSE_READ_PROTECT));
319 return EFUSE_ERR_READ_FORBID;
320 }
321
322 }
323 return 0;
324 }
325
efuse_search_key_by_name(const char * key_name)326 efuse_key_map_new_t *efuse_search_key_by_name(const char *key_name)
327 {
328 efuse_key_map_new_t *key_map = g_key_info;
329
330 for (; key_map->size != 0; key_map++) {
331 if (strlen(key_map->name) != strlen(key_name)) {
332 continue;
333 }
334 if (!memcmp(key_name, key_map->name, strlen(key_map->name))) {
335 break;
336 }
337 }
338 return key_map;
339 }
340
341