1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-01 16:52:14 +02:00
Files
u-boot-megous/drivers/sunxi_crypto/sunxi_efuse.c
Ondrej Jirman ba8c26ce40 initial
2019-03-04 15:37:41 +01:00

606 lines
16 KiB
C
Executable File

/*
* (C) Copyright 2000-2999
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Author: qinjian <qinjian@allwinnertech.com>
* SPDX-License-Identifier: GPL-2.0+
*/
#include "common.h"
#include <efuse_map.h>
#include <sunxi_board.h>
#ifdef CONFIG_ARCH_SUN8IW12P1
#define SECURE_BIT_OFFSET 31
#else
#define SECURE_BIT_OFFSET 11
#endif
/*Globel config area begin*/
#define EFUSE_DBG_E 0
#define NORMAL_IC_FOLLOW_SEC_RULE 0
/*Globel config area end*/
#if EFUSE_DBG_E
static void efuse_dump(char *str,unsigned char *data,\
int len,int align)
{
int i = 0;
if(str)
printf("\n%s: ",str);
for(i = 0;i<len;i++)
{
if((i%align) == 0)
{
printf("\n");
}
printf("%x",*(data++));
}
printf("\n");
}
#define EFUSE_DBG printf
#define EFUSE_DBG_DUMP efuse_dump
#define EFUSE_DUMP_LEN 16
static unsigned int g_err_flg = 0;
#else
#define EFUSE_DBG_DUMP(...) do{} while(0);
#define EFUSE_DBG(...) do{} while(0);
#endif
#ifndef EFUSE_READ_PROTECT
#define EFUSE_READ_PROTECT EFUSE_CHIPCONFIG
#define EFUSE_WRITE_PROTECT EFUSE_CHIPCONFIG
#endif
/* internal struct */
typedef struct efuse_key_map_new{
char name[SUNXI_KEY_NAME_LEN];
int offset;
int size; /* unit: bit */
int rd_fbd_offset;
int burned_flg_offset;
int sw_rule;
}efuse_key_map_new_t;
/*It can not be seen.*/
#define EFUSE_PRIVATE (0)
/*After burned ,cpu can not access.*/
#define EFUSE_NACCESS (1)
#define EFUSE_RO (2)
#define EFUSE_RW (3)
#define EFUSE_ACL_SET_BRUN_BIT (1<<29)
#define EFUSE_ACL_SET_RD_FORBID_BIT (1<<30)
#define EFUSE_BRUN_RD_OFFSET_MASK (0xFFFFFF)
#define EFUSE_DEF_ITEM(name,offset,size_bits,rd_offset,burn_offset,acl) \
{name,offset,size_bits,rd_offset,burn_offset,acl}
#if defined(CONFIG_ARCH_SUN50IW2P1) || defined(CONFIG_ARCH_SUN50IW1P1)
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,0x0,128,-1,2,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_EMAC_NAME,0x10,32,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_NV1_NAME,0x14,32,-1,-1,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_NV2_NAME,0x18,64,-1,-1,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_RSAKEY_HASH_NAME,0x20,160,-1,8,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME,0x34,64,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_RENEW_NAME,0x3C,64,-1,-1,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_IPTV_MAC,0x3C,64,-1,-1,EFUSE_RW),/*share with EFUSE_RENEW_NAME*/
EFUSE_DEF_ITEM(EFUSE_HUK_NAME,0x44,192,17,9,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_OPT_ID_NAME,0x5C,32,18,10,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_ID_NAME,0x60,32,19,11,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_ROTPK_NAME,0x64,256,14,3,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_SSK_NAME,0x84,128,15,4,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_RSSK_NAME,0x94,256,16,5,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_HDCP_HASH_NAME,0xB4,128,-1,6,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_EK_HASH_NAME,0xC4,128,-1,7,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_SN_NAME,0xD4,192,20,12,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_BACKUP_KEY_NAME,0xEC,64,21,22,EFUSE_RW),
EFUSE_DEF_ITEM("sensor",0x34,64,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#elif defined(CONFIG_ARCH_SUN50IW3P1) || defined(CONFIG_ARCH_SUN50IW6P1)
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,EFUSE_CHIPD,128,0,0,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_BROM_CONF_NAME,EFUSE_BROM_CONFIG,32,1,1,EFUSE_PRIVATE),
EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME,EFUSE_THERMAL_SENSOR,64,2,2,EFUSE_RO),
EFUSE_DEF_ITEM("sensor",EFUSE_THERMAL_SENSOR,64,2,2,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_FT_ZONE_NAME,EFUSE_TF_ZONE,128,3,3,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_EMAC_NAME,EFUSE_OEM_PROGRAM,160,4,4,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_JTAG_SECU_NAME,0x48,32,7,7,EFUSE_PRIVATE),
EFUSE_DEF_ITEM(EFUSE_JTAG_ATTR_NAME,0x4C,32,8,8,EFUSE_PRIVATE),
EFUSE_DEF_ITEM(EFUSE_HUK_NAME,EFUSE_HUK,192,9,9,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_IN_NAME,0x50,192,9,9,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_OPT_ID_NAME,0x68,32,10,10,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_ID_NAME,0x6C,32,11,11,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_ROTPK_NAME,EFUSE_ROTPK,256,12,12,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_SSK_NAME,EFUSE_SSK,128,13,13,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_RSSK_NAME,EFUSE_RSSK,256,14,14,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_HDCP_HASH_NAME,EFUSE_HDCP_HASH,128,15,15,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_EK_HASH_NAME,EFUSE_EK_HASH,128,16,16,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_SN_NAME,EFUSE_SN,192,17,17,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_NV1_NAME,EFUSE_NV1,32,18,18,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_NV2_NAME,EFUSE_NV2,224,19,19,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_IPTV_MAC,EFUSE_MAC,64,-1,-1,EFUSE_RW),
#if defined(CONFIG_ARCH_SUN50IW6P1)
EFUSE_DEF_ITEM(EFUSE_HDCP_PKF_NAME,0x118,128,20,20,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_HDCP_DUK_NAME,0x128,128,21,21,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_BACKUP_KEY_NAME,0x138,576,22,22,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_KL_SCK0_NAME,EFUSE_SCK0,512,23,23,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_KL_SCK1_NAME,EFUSE_SCK1,512,24,24,EFUSE_NACCESS),
#else
EFUSE_DEF_ITEM(EFUSE_BACKUP_KEY_NAME,0x118,320,20,20,EFUSE_RW),
#endif
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#elif defined(CONFIG_ARCH_SUN8IW11P1)
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,0x0,128,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_HUK_NAME,0x10,256,23,11,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_SSK_NAME,0x30,128,22,10,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME,0x40,32,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM("sensor",0x40,32,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_FT_ZONE_NAME,0x44,64,-1,-1,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_TV_OUT_NAME,0x4C,128,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_RSSK_NAME,0x5C,256,20,8,EFUSE_NACCESS),
EFUSE_DEF_ITEM(EFUSE_HDCP_HASH_NAME,0x7C,128,-1,9,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_RESERVED_NAME,0x90,896,-1,-1,EFUSE_RW),
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#elif defined(CONFIG_ARCH_SUN8IW10P1)
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,0x0,128,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME,EFUSE_THERMAL_SENSOR,32,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM("sensor",EFUSE_THERMAL_SENSOR,32,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#elif defined(CONFIG_ARCH_SUN8IW12P1)
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,0,128,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_BROM_CONF_NAME,0x10,32,17,1,EFUSE_PRIVATE),
EFUSE_DEF_ITEM(EFUSE_THM_SENSOR_NAME,0x14,96,18,2,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_FT_ZONE_NAME,0x20,128,19,3,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_ROTPK_NAME,0x30,256,20,4,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_NV1_NAME,0x50,32,21,5,EFUSE_RW),
EFUSE_DEF_ITEM(EFUSE_TVE_NAME,0x54,32,22,6,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_ANTI_BLUSH_NAME,0x58,32,23,7,EFUSE_RO),
EFUSE_DEF_ITEM(EFUSE_RESERVED_NAME,0x5C,32,24,8,EFUSE_RW),
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#else
/*Please extend key_maps for new arch here*/
static efuse_key_map_new_t g_key_info[] = {
EFUSE_DEF_ITEM(EFUSE_CHIPID_NAME,0,128,-1,-1,EFUSE_RO),
EFUSE_DEF_ITEM("",0,0,0,0,EFUSE_PRIVATE),
};
#endif
extern u32 smc_readl(ulong addr);
extern void smc_writel(u32 val,ulong addr);
static uint __sid_reg_read_key(uint key_index)
{
uint reg_val;
reg_val = smc_readl(SID_PRCTL);
reg_val &= ~((0x1ff<<16)|0x3);
reg_val |= key_index<<16;
smc_writel(reg_val, SID_PRCTL);
reg_val &= ~((0xff<<8)|0x3);
reg_val |= (SID_OP_LOCK<<8) | 0x2;
smc_writel(reg_val, SID_PRCTL);
while(smc_readl(SID_PRCTL)&0x2){};
reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
smc_writel(reg_val, SID_PRCTL);
reg_val = smc_readl(SID_RDKEY);
return reg_val;
}
#ifdef SID_EFUSE
uint sid_read_key(uint key_index)
{
return smc_readl(SID_EFUSE + key_index);
}
#else
uint sid_read_key(uint key_index)
{
return __sid_reg_read_key(key_index);
}
#endif
void sid_program_key(uint key_index, uint key_value)
{
uint reg_val;
smc_writel(key_value, SID_PRKEY);
reg_val = smc_readl(SID_PRCTL);
reg_val &= ~((0x1ff<<16)|0x3);
reg_val |= key_index<<16;
smc_writel(reg_val, SID_PRCTL);
reg_val &= ~((0xff<<8)|0x3);
reg_val |= (SID_OP_LOCK<<8) | 0x1;
smc_writel(reg_val, SID_PRCTL);
while(smc_readl(SID_PRCTL)&0x1){};
reg_val &= ~((0x1ff<<16)|(0xff<<8)|0x3);
smc_writel(reg_val, SID_PRCTL);
return ;
}
#define EFUSE_BURN_MAX_TRY_CNT 3
/*Please reference 1728 spec page11 to know why to call __sid_reg_read_key
* but sid_read_key
*burn efuse :efuse sram can not get the latest value
*unless via sid read or reboot.
*/
static int uni_burn_key(uint key_index, uint key_value)
{
uint key_burn_bitmask = ~(sid_read_key(key_index)) & key_value;
int fail = 0;
while(key_burn_bitmask)
{
sid_program_key(key_index,key_burn_bitmask);
if(fail > EFUSE_BURN_MAX_TRY_CNT)
{
EFUSE_DBG("[efuse] %s %d fatal err: **uni_burn_key failed **",
__FILE__,__LINE__);
#if EFUSE_DBG_E
g_err_flg++;
#endif
return -1;
}
key_burn_bitmask &= (~(__sid_reg_read_key(key_index)));
fail++;
}
return 0;
}
void sid_set_security_mode(void)
{
#ifdef EFUSE_LCJS
if(uni_burn_key(EFUSE_LCJS, (0x1 << SECURE_BIT_OFFSET)))
{
EFUSE_DBG("[efuse] %s %d fatal err: **sid_set_security_mode failed **",
__FILE__,__LINE__);
}
#endif
return;
}
/*This is an obseleted api*/
int sid_probe_security_mode(void)
{
#ifdef EFUSE_LCJS
return (sid_read_key(EFUSE_LCJS) >> SECURE_BIT_OFFSET) & 1;
#else
return 0;
#endif
}
#ifdef SID_SECURE_MODE
int sid_get_security_status(void)
{
return readl(SID_SECURE_MODE) & 0x1;
}
#else
int sid_get_security_status(void)
{
return sid_probe_security_mode();
}
#endif
static void _set_cfg_flg(int efuse_cfg_base,int bit_offset)
{
if(uni_burn_key(efuse_cfg_base,(1<<bit_offset)))
{
EFUSE_DBG("[efuse] %s %d fatal err: **_set_cfg_flg [base:%d][offset:%d] **",
__FILE__,__LINE__,efuse_cfg_base,bit_offset);
}
return;
}
static int _get_burned_flag(efuse_key_map_new_t *key_map)
{
if(key_map->burned_flg_offset<0)
{
return 0;
}
else
{
return (sid_read_key(EFUSE_WRITE_PROTECT)
>> (key_map->burned_flg_offset & EFUSE_BRUN_RD_OFFSET_MASK)) & 1;
}
}
static int __sw_acl_ck(efuse_key_map_new_t *key_map,int burn)
{
if(key_map->sw_rule == EFUSE_PRIVATE)
{
EFUSE_DBG("\n[efuse]%s: PRIVATE\n",key_map->name);
return EFUSE_ERR_PRIVATE;
}
if(burn==0)
{
if(key_map->sw_rule == EFUSE_NACCESS)
{
EFUSE_DBG("\n[efuse]%s:NACCESS\n",key_map->name);
return EFUSE_ERR_NO_ACCESS;
}
}
else
{
/*If already burned:*/
if(_get_burned_flag(key_map))
{
EFUSE_DBG("\n[efuse]%s: already burned\n",key_map->name);
EFUSE_DBG("config reg:0x%x\n",sid_read_key(EFUSE_WRITE_PROTECT));
if(key_map->sw_rule == EFUSE_NACCESS)
return EFUSE_ERR_NO_ACCESS;
return EFUSE_ERR_ALREADY_BURNED;
}
if(key_map->sw_rule == EFUSE_RW)
{
/*modify burned_flg_offset&&rd_fbd_offset in case of the config bits been burned*/
key_map->burned_flg_offset |= EFUSE_ACL_SET_BRUN_BIT;
key_map->rd_fbd_offset |= EFUSE_ACL_SET_RD_FORBID_BIT;
}
else if(key_map->sw_rule == EFUSE_RO)
{
/*modify rd_fbd_offset in case of the config bit been burned*/
key_map->rd_fbd_offset |= EFUSE_ACL_SET_RD_FORBID_BIT;
}
}
return 0;
}
/*Efuse access control rule check.*/
static int __efuse_acl_ck(efuse_key_map_new_t *key_map,int burn)
{
/*For normal solution only check EFUSE_PRIVATE,other will be seemed as EFUSE_RW */
#ifdef NORMAL_IC_FOLLOW_SEC_RULE
#else
if(sid_get_security_status() == 0)
{
if(key_map->sw_rule == EFUSE_PRIVATE)
{
return EFUSE_ERR_PRIVATE;
}
return 0;
}
#endif
int ret = __sw_acl_ck(key_map,burn);
if(ret)
{
return ret;
}
if(burn)
{
if(_get_burned_flag(key_map))
{
/*already burned*/
EFUSE_DBG("[efuse]%s:already burned\n",key_map->name);
EFUSE_DBG("config reg:0x%x\n",sid_read_key(EFUSE_WRITE_PROTECT));
return EFUSE_ERR_ALREADY_BURNED;
}
}
else
{
if((key_map->rd_fbd_offset>=0)&&
((sid_read_key(EFUSE_READ_PROTECT) >> key_map->rd_fbd_offset) & 1))
{
/*Read is not allowed because of the read forbidden bit was set*/
EFUSE_DBG("[efuse]%s forbid bit set\n",key_map->name);
EFUSE_DBG("config reg:0x%x\n",sid_read_key(EFUSE_READ_PROTECT));
return EFUSE_ERR_READ_FORBID;
}
}
return 0;
}
/*get a uint value from unsigned char *k_src*/
static unsigned int _get_uint_val(unsigned char *k_src)
{
unsigned int test = 0x12345678;
if((unsigned int)k_src & 0x3)
{
/*big endian*/
if(*(unsigned char*)(&test) == 0x12)
{
memcpy((void*)&test,(void *)k_src,4);
return test;
}
else
{
test = ((*(k_src+3)) << 24) | ((*(k_src+2)) << 16)\
| ((*(k_src+1)) << 8) | (*k_src);
return test;
}
}
else
{
return *(unsigned int *)k_src;
}
}
int sunxi_efuse_write(void *key_inf)
{
efuse_key_info_t *list = (efuse_key_info_t *)key_inf;
unsigned char *k_src = NULL;
unsigned int niddle = 0,tmp_data = 0,k_d_lft = 0 ;
efuse_key_map_new_t *key_map = g_key_info;
if ((list == NULL)||(list->len == 0))
{
EFUSE_DBG("[efuse] error: key_inf is null or len is 0\n");
return EFUSE_ERR_ARG;
}
/* search key via name*/
for (; key_map->size != 0; key_map++)
{
if (!memcmp(list->name,key_map->name,strlen(key_map->name)))
{
/* check if there is enough space to store the key*/
if ((key_map->size >> 3) < list->len)
{
EFUSE_DBG("key name = %s\n", key_map->name);
EFUSE_DBG("[efuse] error: no enough space\
, dst size(%d), src size(%d)\n",
key_map->size >> 3, list->len);
return EFUSE_ERR_KEY_SIZE_TOO_BIG;
}
break;
}
}
if (key_map->size == 0)
{
EFUSE_DBG("[sunxi_efuse_write] error: unknow key\n");
return EFUSE_ERR_KEY_NAME_WRONG;
}
int ret = __efuse_acl_ck(key_map,1);
if(ret)
{
EFUSE_DBG("[sunxi_efuse_write] __efuse_acl_ck check failed\n");
return ret;
}
EFUSE_DBG_DUMP(list->name,list->key_data,\
list->len,EFUSE_DUMP_LEN);
niddle = key_map->offset;
k_d_lft = list->len;
k_src = list->key_data;
while(k_d_lft >= 4)
{
tmp_data = _get_uint_val(k_src);
EFUSE_DBG("offset:0x%x val:0x%x\n",niddle,tmp_data);
if(tmp_data)
{
if(uni_burn_key(niddle, tmp_data))
{
return EFUSE_ERR_BURN_TIMING;
}
}
k_d_lft-=4;
niddle += 4;
k_src +=4;
}
if(k_d_lft)
{
uint mask = (1UL << (k_d_lft << 3)) - 1;
tmp_data = _get_uint_val(k_src);
mask &= tmp_data;
EFUSE_DBG("offset:0x%x val:0x%x\n",niddle,mask);
if(mask)
{
if(uni_burn_key(niddle,mask))
{
return EFUSE_ERR_BURN_TIMING;
}
}
}
/*Already burned bit: Set this bit to indicate it is already burned.*/
if((key_map->burned_flg_offset >= 0) &&
(key_map->burned_flg_offset <= EFUSE_BRUN_RD_OFFSET_MASK)
#ifndef NORMAL_IC_FOLLOW_SEC_RULE
&&sid_get_security_status()
#endif
)
{
_set_cfg_flg(EFUSE_WRITE_PROTECT,key_map->burned_flg_offset);
}
/*Read forbidden bit: Set to indicate cpu can not access this key again.*/
if((key_map->rd_fbd_offset >= 0) &&
(key_map->rd_fbd_offset <= EFUSE_BRUN_RD_OFFSET_MASK)
#ifndef NORMAL_IC_FOLLOW_SEC_RULE
&&sid_get_security_status()
#endif
)
{
_set_cfg_flg(EFUSE_READ_PROTECT,key_map->rd_fbd_offset);
}
return 0;
}
/*This API assume the caller already
*prepared enough buffer to receive data.
*Because the lenth of key is exported as MACRO*/
#define EFUSE_ROUND_UP(x,y) ((((x) + ((y) - 1)) / (y)) * (y))
int sunxi_efuse_read(void *key_name, void *rd_buf)
{
efuse_key_map_new_t *key_map = g_key_info;
uint tmp=0,i=0,k_u32_l=0,bit_lft = 0;
int offset =0,tmp_sz = 0;
/*if rd_buf not aligned ,u32_p will not be accessed*/
unsigned int *u32_p = (unsigned int *)rd_buf;
unsigned char *u8_p = (unsigned char *)rd_buf;
if(!(key_name && rd_buf))
{
EFUSE_DBG("[efuse] error arg check fail\n");
return EFUSE_ERR_ARG;
}
/* search key via name*/
for(; key_map->size != 0; key_map++)
{
if (!memcmp(key_name, key_map->name, strlen(key_map->name)))
{
break;
}
}
if (key_map->size == 0)
{
EFUSE_DBG("[efuse] error: unknow key name\n");
return EFUSE_ERR_KEY_NAME_WRONG;
}
int ret = __efuse_acl_ck(key_map,0);
if(ret)
{
EFUSE_DBG("[sunxi_efuse_write] error: acl check fail\n");
return ret;
}
EFUSE_DBG("key name:%s key size:%d key offset:%d\n",\
key_map->name,key_map->size,key_map->offset);
k_u32_l = key_map->size / 32;
bit_lft = key_map->size % 32;
offset = key_map->offset;
for(i = 0;i<k_u32_l;i++)
{
tmp = sid_read_key(offset);
if(((unsigned int)rd_buf & 0x3) == 0)
{
u32_p[i] = tmp;
}
else
{
memcpy((void*)(u8_p + i * 4),(void*)(&tmp),4);
}
offset += 4;
tmp_sz += 4;
}
if(bit_lft)
{
EFUSE_DBG("bit lft is %d\n",bit_lft);
tmp = sid_read_key(offset);
memcpy((void*)(u8_p + k_u32_l * 4),(void*)(&tmp),
EFUSE_ROUND_UP(bit_lft,8));
tmp_sz +=EFUSE_ROUND_UP(bit_lft,8);
}
flush_dcache_range((unsigned long)rd_buf,tmp_sz);
return tmp_sz;
}
/*dbg only*/
void sunxi_efuse_dump(void)
{
efuse_key_map_new_t *key_map = g_key_info;
printf("\nsunxi_efuse_dump::\n");
/* search key via name*/
for(; key_map->size != 0; key_map++)
{
printf("%s : [size:%d Byte][sw_rule:%d]\n",
key_map->name,key_map->size/8,key_map->sw_rule);
}
}