efuse.c 10 KB

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