hal_efuse.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright 2018 AllWinnertech Co., Ltd
  3. * wangwei@allwinnertech.com
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sunxi_hal_efuse.h>
  8. #include <sunxi_hal_common.h>
  9. #include "platform_efuse.h"
  10. #include "efuse.h"
  11. #if (EFUSE_DBG_EN & (CONFIG_LOG_DEFAULT_LEVEL != 0))
  12. #define EFUSE_DBG(fmt,args...) printf(fmt ,##args)
  13. #define EFUSE_DUMP_LEN 16
  14. #define EFUSE_DBG_DUMP(key_name, key_data, key_len) efuse_dump(key_name, key_data, key_len, EFUSE_DUMP_LEN)
  15. #else
  16. #define EFUSE_DBG(fmt,args...)
  17. #define EFUSE_DBG_DUMP(...) do{} while(0);
  18. #endif
  19. #if EFUSE_DBG_EN
  20. static void efuse_dump(char *str,unsigned char *data,\
  21. int len, int align)
  22. {
  23. int i = 0;
  24. if(str)
  25. printf("\n%s: ",str);
  26. for(i = 0; i<len; i++)
  27. {
  28. if((i%align) == 0)
  29. {
  30. printf("\n");
  31. }
  32. printf("%02x ",*(data++));
  33. }
  34. printf("\n");
  35. }
  36. #endif
  37. int hal_efuse_write(char *key_name, unsigned char *key_data, size_t key_bit_len)
  38. {
  39. unsigned long k_src = 0;
  40. unsigned int niddle = 0,tmp_data = 0,k_d_lft = 0 ;
  41. size_t key_len = key_bit_len>>3;
  42. efuse_key_map_new_t *key_map;
  43. int ret;
  44. if ((strlen(key_name) == 0)|| (key_len == 0) || ((unsigned long)key_data%4 != 0))
  45. return EFUSE_ERR_ARG;
  46. key_map = efuse_search_key_by_name(key_name);
  47. if (((unsigned int)key_map->size >> 3) < key_len) {
  48. EFUSE_DBG("key name = %s\n", key_map->name);
  49. return EFUSE_ERR_KEY_SIZE_TOO_BIG;
  50. }
  51. if (key_map->size == 0) {
  52. EFUSE_DBG("%s: error: unknow key\n", __func__);
  53. return EFUSE_ERR_KEY_NAME_WRONG;
  54. }
  55. ret = efuse_acl_ck(key_map, 1);
  56. if(ret) {
  57. EFUSE_DBG("%s: __efuse_acl_ck check failed\n", __func__);
  58. return ret;
  59. }
  60. EFUSE_DBG_DUMP(key_name, key_data, key_len);
  61. /*rotpk need double check before burn*/
  62. if (strcmp(key_name, "rotpk") == 0) {
  63. }
  64. niddle = key_map->offset;
  65. k_d_lft = key_len;
  66. k_src = (unsigned long)key_data;
  67. while(k_d_lft >= 4) {
  68. tmp_data = *(unsigned int*)k_src;
  69. EFUSE_DBG("offset:0x%x val:0x%x\n",niddle,tmp_data);
  70. if(tmp_data)
  71. {
  72. if(efuse_uni_burn_key(niddle, tmp_data))
  73. {
  74. return EFUSE_ERR_BURN_TIMING;
  75. }
  76. }
  77. k_d_lft-=4;
  78. niddle += 4;
  79. k_src +=4;
  80. }
  81. if(k_d_lft) {
  82. uint mask = (1UL << (k_d_lft << 3)) - 1;
  83. tmp_data = *(unsigned int*)k_src;
  84. mask &= tmp_data;
  85. EFUSE_DBG("offset:0x%x val:0x%x\n",niddle,mask);
  86. if(mask)
  87. {
  88. if(efuse_uni_burn_key(niddle,mask))
  89. {
  90. return EFUSE_ERR_BURN_TIMING;
  91. }
  92. }
  93. }
  94. /*Already burned bit: Set this bit to indicate it is already burned.*/
  95. if ((key_map->burned_flg_offset >= 0) &&
  96. (key_map->burned_flg_offset <= EFUSE_BRUN_RD_OFFSET_MASK)) {
  97. efuse_set_cfg_flg(EFUSE_WRITE_PROTECT,key_map->burned_flg_offset);
  98. }
  99. /*Read forbidden bit: Set to indicate cpu can not access this key again.*/
  100. if ((key_map->rd_fbd_offset >= 0) &&
  101. (key_map->rd_fbd_offset <= EFUSE_BRUN_RD_OFFSET_MASK)) {
  102. efuse_set_cfg_flg(EFUSE_READ_PROTECT,key_map->rd_fbd_offset);
  103. }
  104. return 0;
  105. }
  106. /*This API assume the caller already
  107. *prepared enough buffer to receive data.
  108. *Because the lenth of key is exported as MACRO*/
  109. #define EFUSE_ROUND_UP(x,y) ((((x) + ((y) - 1)) / (y)) * (y))
  110. int hal_efuse_read(char *key_name, unsigned char *key_data, size_t key_bit_len)
  111. {
  112. efuse_key_map_new_t *key_map;
  113. uint tmp=0,i=0,k_u32_l=0,bit_lft = 0;
  114. int offset =0,tmp_sz = 0;
  115. int ret;
  116. /*if key_data not aligned ,u32_p will not be accessed*/
  117. unsigned int *u32_p = (unsigned int *)key_data;
  118. unsigned char *u8_p = (unsigned char *)key_data;
  119. if(!(key_name && key_data)) {
  120. EFUSE_DBG("[efuse] error arg: key_name is %p, key_data is %p\n",key_name, key_data);
  121. return EFUSE_ERR_ARG;
  122. }
  123. key_map = efuse_search_key_by_name(key_name);
  124. if (key_map->size == 0 || key_map->size > key_bit_len) {
  125. EFUSE_DBG("[efuse] error: unknow key name\n");
  126. return EFUSE_ERR_KEY_NAME_WRONG;
  127. }
  128. ret = efuse_acl_ck(key_map, 0);
  129. if(ret) {
  130. EFUSE_DBG("[sunxi_efuse_write] error: acl check fail\n");
  131. return ret;
  132. }
  133. EFUSE_DBG("key name:%s key size:%d key offset:%d\n",\
  134. key_map->name,key_map->size,key_map->offset);
  135. if (key_map->size > key_bit_len) {
  136. EFUSE_DBG("[efuse] error: key size\n");
  137. return EFUSE_ERR_ARG;
  138. }
  139. k_u32_l = key_map->size / 32;
  140. bit_lft = key_map->size % 32;
  141. offset = key_map->offset;
  142. for(i = 0;i<k_u32_l;i++)
  143. {
  144. tmp = efuse_sram_read_key(offset);
  145. if(((unsigned long)key_data & 0x3) == 0)
  146. {
  147. u32_p[i] = tmp;
  148. }
  149. else
  150. {
  151. memcpy((void*)(u8_p + i * 4),(void*)(&tmp),4);
  152. }
  153. offset += 4;
  154. tmp_sz += 4;
  155. }
  156. if(bit_lft)
  157. {
  158. EFUSE_DBG("bit lft is %d\n",bit_lft);
  159. tmp = efuse_sram_read_key(offset);
  160. memcpy((void*)(u8_p + k_u32_l * 4),(void*)(&tmp),
  161. EFUSE_ROUND_UP(bit_lft,8) / 8);
  162. tmp_sz += (EFUSE_ROUND_UP(bit_lft,8) / 8);
  163. }
  164. EFUSE_DBG_DUMP(key_name, key_data, key_bit_len/8);
  165. return tmp_sz;
  166. }
  167. int hal_efuse_set_security_mode(void)
  168. {
  169. #ifdef EFUSE_LCJS
  170. return efuse_uni_burn_key(EFUSE_LCJS, 0x1 << SECURE_BIT_OFFSET);
  171. #else
  172. return 0;
  173. #endif
  174. }
  175. int hal_efuse_get_security_mode(void)
  176. {
  177. #ifdef EFUSE_SECURE_MODE
  178. return hal_readl(EFUSE_SECURE_MODE) & 0x1;
  179. #else
  180. return 0;
  181. #endif
  182. }
  183. int hal_efuse_get_chipid(unsigned char *buffer)
  184. {
  185. return hal_efuse_read("chipid", buffer, 128);
  186. }
  187. int hal_efuse_get_thermal_cdata(unsigned char *buffer)
  188. {
  189. return hal_efuse_read("thermal_sensor", buffer, 64);
  190. }