320 lines
8.3 KiB
C
Executable File
320 lines
8.3 KiB
C
Executable File
/*
|
||
**********************************************************************************************************************
|
||
*
|
||
* the Embedded Secure Bootloader System
|
||
*
|
||
*
|
||
* Copyright(C), 2006-2014, Allwinnertech Co., Ltd.
|
||
* All Rights Reserved
|
||
*
|
||
* File :
|
||
*
|
||
* By :
|
||
*
|
||
* Version : V2.00
|
||
*
|
||
* Date :
|
||
*
|
||
* Descript:
|
||
**********************************************************************************************************************
|
||
*/
|
||
#include <debug.h>
|
||
#include <efuse.h>
|
||
#include <efuse_map.h>
|
||
#include <string.h>
|
||
|
||
extern void flush_dcache_range(unsigned long addr, unsigned long len);
|
||
|
||
static efuse_key_map_t key_imformatiom[] =
|
||
{
|
||
{"rotpk", EFUSE_ROTPK, SID_ROTPK_SIZE, SCC_ROTPK_DONTSHOW_FLAG, SCC_ROTPK_BURNED_FLAG, {0}},
|
||
{"rssk", EFUSE_RSSK, SID_RSSK_SIZE, SCC_RSSK_DONTSHOW_FLAG, SCC_RSSK_BURNED_FLAG, {0}},
|
||
{"ssk", EFUSE_SSK, SID_SSK_SIZE, SCC_SSK_DONTSHOW_FLAG, SCC_SSK_BURNED_FLAG, {0}},
|
||
{"rotpk", EFUSE_ROTPK, SID_ROTPK_SIZE, SCC_ROTPK_DONTSHOW_FLAG, SCC_ROTPK_BURNED_FLAG, {0}},
|
||
{"hdcphash", EFUSE_HDCP_HASH, SID_HDCP_HASH_SIZE, -1, SCC_HDCP_HASH_BURNED_FLAG, {0}},
|
||
{{0} , 0, 0, 0, 0,{0}}
|
||
};
|
||
|
||
static void sunxi_dump(void *addr, unsigned int size)
|
||
{
|
||
int i,j;
|
||
char *buf = (char *)addr;
|
||
|
||
for(j=0;j<size;j+=16)
|
||
{
|
||
for(i=0;i<16;i++)
|
||
{
|
||
tf_printf("%x ", buf[j+i] & 0xff);
|
||
}
|
||
tf_printf("\n");
|
||
}
|
||
tf_printf("\n");
|
||
|
||
return ;
|
||
}
|
||
//*****************************************************************************
|
||
// uint32_t sid_read_key(uint32_t key_index)
|
||
// Description:
|
||
// Read key from Efuse by software
|
||
// Arguments: None
|
||
//
|
||
//
|
||
// Return Value: Key value
|
||
//*****************************************************************************
|
||
unsigned int sid_set_burned_flag(int bit_offset)
|
||
{
|
||
unsigned int reg_val;
|
||
|
||
reg_val = sid_read_key(EFUSE_CHIP_CONFIG);
|
||
reg_val |= (0x1<<bit_offset); //ʹÄÜsecurebit
|
||
sid_program_key(EFUSE_CHIP_CONFIG, reg_val);
|
||
reg_val = (sid_read_key(EFUSE_CHIP_CONFIG) >> bit_offset) & 1;
|
||
|
||
return reg_val;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_efuse_write(void *key_buf)
|
||
{
|
||
sunxi_efuse_key_info_t *key_list = NULL;
|
||
unsigned long key_data_addr;
|
||
int i;
|
||
unsigned int key_start_addr; // ÿһ±ÊÊý¾ÝµÄ¿ªÊ¼µØÖ·
|
||
unsigned int *key_once_data = 0;
|
||
unsigned int key_data_remain_size; //Ê£ÏÂ×Ö½ÚÊý
|
||
|
||
unsigned int verify_buf[128];
|
||
|
||
int burned_status;
|
||
|
||
efuse_key_map_t *key_map = key_imformatiom;
|
||
|
||
if (key_buf == NULL)
|
||
{
|
||
tf_printf("[efuse] error: buf is null\n");
|
||
return -1;
|
||
}
|
||
key_list = (sunxi_efuse_key_info_t *)key_buf;
|
||
key_data_addr = ((unsigned long)key_list->key_data) & 0xffffffff ;
|
||
#ifdef EFUSE_DEBUG
|
||
tf_printf("^^^^^^^tf_printf key_buf^^^^^^^^^^^^\n");
|
||
tf_printf("key name=%s\n", key_list->name);
|
||
tf_printf("key len=%d\n", key_list->len);
|
||
tf_printf("key data:%p\n", (void*)key_data_addr);
|
||
sunxi_dump((void *)key_data_addr, key_list->len);
|
||
tf_printf("###################\n");
|
||
#endif
|
||
// ²é×ֵ䣬±»ÔÊÐíµÄkey²ÅÄÜÉÕд
|
||
for (; key_map != NULL; key_map++)
|
||
{
|
||
if (!memcmp(key_list->name, key_map->name, strlen(key_map->name)))
|
||
{
|
||
tf_printf(" burn key start\n");
|
||
tf_printf("burn key start\n");
|
||
tf_printf("key name = %s\n", key_map->name);
|
||
tf_printf("key index = 0x%x\n", key_map->key_index);
|
||
|
||
// ÅжÏÊÇ·ñ×ã¹»¿Õ¼äÀ´´æ·Åkey
|
||
if ((key_map->store_max_bit / 8) < key_list->len)
|
||
{
|
||
tf_printf("[efuse] error: not enough space to store the key, efuse size(%d), data size(%d)\n", key_map->store_max_bit/8, key_list->len);
|
||
|
||
return -1;
|
||
}
|
||
// Åжϴæ·ÅkeyµÄÇøÓòÊÇ·ñÒѾÉÕ¼
|
||
tf_printf("===== key_map->burned_bit_offset ====%d \n",key_map->burned_bit_offset);
|
||
burned_status = (sid_read_key(EFUSE_CHIP_CONFIG) >> key_map->burned_bit_offset) & 1;
|
||
if(burned_status)
|
||
{
|
||
tf_printf("key %s has been burned already\n", key_map->name);
|
||
|
||
return -1;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (key_map == NULL)
|
||
{
|
||
tf_printf("[efuse] error: can't burn the key (unknow)\n");
|
||
|
||
return -1;
|
||
}
|
||
//ÉÕдkey
|
||
key_start_addr = key_map->key_index;
|
||
key_data_remain_size = key_list->len;
|
||
memset(verify_buf, 0, 512);
|
||
memcpy(verify_buf,(void *)key_data_addr,key_data_remain_size); /*align key_once_data to 4 bytes*/
|
||
key_once_data = verify_buf;
|
||
tf_printf("key_data_remain_size=%d\n", key_data_remain_size);
|
||
//flush_cache((uint)pbuf, byte_cnt);
|
||
for(;key_data_remain_size >= 4; key_data_remain_size-=4, key_start_addr += 4, key_once_data ++)
|
||
{
|
||
tf_printf("key_data_remain_size=%d\n", key_data_remain_size);
|
||
tf_printf("key data=0x%x, addr=0x%p\n", *key_once_data, key_once_data);
|
||
sid_program_key(key_start_addr, *key_once_data);
|
||
|
||
tf_printf("[efuse] addr = 0x%x, data = 0x%x\n", key_start_addr, *key_once_data);
|
||
}
|
||
|
||
if(key_data_remain_size)
|
||
{
|
||
if(key_data_remain_size == 1)
|
||
{
|
||
*key_once_data &= 0x000000ff;
|
||
}
|
||
else if(key_data_remain_size == 2)
|
||
{
|
||
*key_once_data &= 0x0000ffff;
|
||
}
|
||
else if(key_data_remain_size == 3)
|
||
{
|
||
*key_once_data &= 0x00ffffff;
|
||
}
|
||
sid_program_key(key_start_addr, *key_once_data);
|
||
|
||
tf_printf("[efuse] addr = 0x%x, data = 0x%x\n", key_start_addr, *key_once_data);
|
||
}
|
||
//¶Á³öÉÕ¼µÄkeyÐÅÏ¢
|
||
key_start_addr = key_map->key_index;
|
||
key_data_remain_size = key_list->len;
|
||
|
||
memset(verify_buf, 0, 512);
|
||
if(key_data_remain_size & 3)
|
||
key_data_remain_size = (key_data_remain_size + 3) & (~3);
|
||
for(i=0;i<key_data_remain_size/4; i++)
|
||
{
|
||
verify_buf[i] = sid_read_key(key_start_addr);
|
||
key_start_addr += 4;
|
||
}
|
||
//±È½Ï
|
||
if(memcmp(verify_buf, (const void *)key_data_addr, key_list->len))
|
||
{
|
||
tf_printf("compare burned key with memory data failed\n");
|
||
tf_printf("memory data:\n");
|
||
sunxi_dump((void *)key_data_addr, key_list->len);
|
||
tf_printf("burned key:\n");
|
||
sunxi_dump(verify_buf, key_list->len);
|
||
|
||
return -1;
|
||
}
|
||
//Ëø¶¨
|
||
sid_set_burned_flag(key_map->burned_bit_offset);
|
||
|
||
tf_printf(" burn key end\n");
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/*
|
||
************************************************************************************************************
|
||
*
|
||
* function
|
||
*
|
||
* name :
|
||
*
|
||
* parmeters :
|
||
*
|
||
* return :
|
||
*
|
||
* note :
|
||
*
|
||
*
|
||
************************************************************************************************************
|
||
*/
|
||
int sunxi_efuse_read(void *key_name, void *read_buf)
|
||
{
|
||
efuse_key_map_t *key_map = key_imformatiom;
|
||
unsigned int key_start_addr; // ÿһ±ÊÊý¾ÝµÄ¿ªÊ¼µØÖ·
|
||
int show_status;
|
||
int check_buf[128];
|
||
unsigned int key_data_remain_size; //Ê£ÏÂ×Ö½ÚÊý
|
||
int i;
|
||
|
||
// ²é×ֵ䣬±»ÔÊÐíµÄkey²ÅÄܱ»²é¿´
|
||
for (; key_map != NULL; key_map++)
|
||
{
|
||
if (!memcmp(key_name, key_map->name, strlen(key_map->name)))
|
||
{
|
||
tf_printf("read key start\n");
|
||
tf_printf("key name = %s\n", key_map->name);
|
||
tf_printf("key index = 0x%x\n", key_map->key_index);
|
||
|
||
//ÅжÏkeyÓÐûÓÐÉÕ¼¹ý
|
||
show_status = (sid_read_key(EFUSE_CHIP_CONFIG) >> key_map->burned_bit_offset) & 1;
|
||
if(!show_status)
|
||
{
|
||
tf_printf("key %s have not been burned yet\n", key_map->name);
|
||
|
||
return -1;
|
||
}
|
||
// Åжϴæ·ÅkeyµÄÇøÓòÊÇ·ñÔÊÐí±»²é¿´
|
||
//Èç¹ûûÓд˱ê־룬±íʾһ¶¨¿ÉÒԲ鿴
|
||
if(key_map->show_bit_offset < 0)
|
||
{
|
||
break;
|
||
}
|
||
//Èç¹û´æÔÚ±ê־룬²¢ÇÒ²»ÔÊÐí²é¿´£¬Ôò²»¶Á³ö£¬²¢ÇÒ·µ»Ø±¨´í
|
||
show_status = (sid_read_key(EFUSE_CHIP_CONFIG) >> key_map->show_bit_offset) & 1;
|
||
if(show_status)
|
||
{
|
||
tf_printf("key %s don't show \n", key_map->name);
|
||
|
||
return -1;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (key_map == NULL)
|
||
{
|
||
tf_printf("[efuse] error: can't read the key (unknow)\n");
|
||
|
||
return -1;
|
||
}
|
||
|
||
//ÉÕдkey
|
||
key_start_addr = key_map->key_index;
|
||
key_data_remain_size = key_map->store_max_bit / 8;
|
||
|
||
memset(check_buf, 0, 512);
|
||
if(key_data_remain_size & 3)
|
||
key_data_remain_size = (key_data_remain_size + 3) & (~3);
|
||
for(i=0;i<key_data_remain_size/4; i++)
|
||
{
|
||
check_buf[i] = sid_read_key(key_start_addr);
|
||
key_start_addr += 4;
|
||
}
|
||
sunxi_dump(check_buf, key_map->store_max_bit / 8);
|
||
memcpy((void *)read_buf, check_buf, key_map->store_max_bit / 8);
|
||
flush_dcache_range((unsigned long)read_buf, key_map->store_max_bit / 8);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int sunxi_efuse_probe_security_mode(void)
|
||
{
|
||
return sid_probe_security_mode();
|
||
}
|
||
|
||
|