增加所有文件
This commit is contained in:
806
middleware/fuse/fuse_bin.c
Normal file
806
middleware/fuse/fuse_bin.c
Normal file
@@ -0,0 +1,806 @@
|
||||
#include <armv7-r/cache.h>
|
||||
#include <board.h>
|
||||
#include <common.h>
|
||||
#include <debug.h>
|
||||
#include <fuse_bin.h>
|
||||
#include <mailbox/sdrv_crypto_mailbox_common.h>
|
||||
#include <mailbox/sdrv_crypto_mailbox_ske_basic.h>
|
||||
#include <param.h>
|
||||
#include <reg.h>
|
||||
#include <regs_base.h>
|
||||
#include <sd_boot_img/sd_boot_img.h>
|
||||
#include <sdrv_crypto_init.h>
|
||||
#include <sdrv_fuse.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum {
|
||||
E_ACTION_FUSE_DIRECT_PROGRAM = 1,
|
||||
E_ACTION_FUSE_GEN_AND_PROGRAM = 2,
|
||||
E_ACTION_FUSE_OR_OPR_PROGRAM = 3,
|
||||
E_ACTION_FUSE_LOCK = 4,
|
||||
E_ACTION_FUSE_SSRK_PROGRAM = 9,
|
||||
E_ACTION_FUSE_TSRK_PROGRAM = 10,
|
||||
E_ACTION_FUSE_KCRC_PROGRAM = 11,
|
||||
} ACTION_TYPE;
|
||||
|
||||
#define ACTION_SEQ_TAG (0xE101)
|
||||
#define ACTION_ITEM_TAG (0xF001)
|
||||
#define ACTION_SEQ_VER (0x0001)
|
||||
#define ACTION_ITEM_VER (0x0001)
|
||||
|
||||
#define EFUSE_FSRK_INDEX (48)
|
||||
#define EFUSE_EHSM_CFG_INDEX (192)
|
||||
#define EFUSE_NVM_ALG_MASK (0xC00)
|
||||
#define EFUSE_NVM_ALG_OFFSET (10)
|
||||
#define EFUSE_NVM_ALG_AES_128_ECB (0x1)
|
||||
|
||||
#define EFUSE_FSRK_KEY_ID (1)
|
||||
#define EFUSE_SSRK_KEY_ID (3)
|
||||
|
||||
#define IS_NEED_TRANS(ADDR) \
|
||||
(((uint32_t)(ADDR) >= IRAM1_BASE - 0x20000 && \
|
||||
(uint32_t)(ADDR) < IRAM1_BASE) \
|
||||
? 1 \
|
||||
: 0)
|
||||
|
||||
#define OFFSET_BASE(ADDR) ((uint32_t)(ADDR) + 0x20000 - IRAM1_BASE)
|
||||
|
||||
#define TRANS_ADDR(ADDR) \
|
||||
((OFFSET_BASE(ADDR) > 0x10000) \
|
||||
? (R5_SF_TCM_R5_SF_TCMB_BASE - 0x10000 + OFFSET_BASE(ADDR)) \
|
||||
: (R5_SF_TCM_R5_SF_TCMB_BASE + 0x10000 + OFFSET_BASE(ADDR)))
|
||||
|
||||
#define TRANS_TO_SEIP_ACCESS_ADDR(ADDR) \
|
||||
((IS_NEED_TRANS(ADDR)) ? TRANS_ADDR(ADDR) : (uint32_t)(ADDR))
|
||||
|
||||
#define REAL_FUSE_NOT_SHADOW_REGISTER 1
|
||||
#define NVM_ALG_AES_128_ECB_TEST 0
|
||||
|
||||
typedef struct {
|
||||
uint16_t nTag;
|
||||
uint16_t nVer;
|
||||
uint16_t nCount; // action count
|
||||
uint8_t bReserved[18];
|
||||
uint32_t nSize; // total fuse bin size
|
||||
uint32_t nCrc32;
|
||||
} ACTION_SEQ_T;
|
||||
|
||||
typedef struct {
|
||||
uint16_t nTag;
|
||||
uint16_t nVer;
|
||||
uint16_t nActionType;
|
||||
uint16_t nLen; // 1 action and 1 item
|
||||
uint8_t bReserved[8];
|
||||
} ACTION_ITEM_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t nFuseType;
|
||||
uint16_t nFuseIndex;
|
||||
uint16_t nFuseLen; // fuse data len
|
||||
uint8_t *lpData;
|
||||
} FUSE_BURN_ITEM_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t nFuseType;
|
||||
uint16_t nFuseIndex;
|
||||
uint16_t nFuseLen;
|
||||
uint16_t nKeyIndex;
|
||||
uint16_t nKeyLen;
|
||||
} FUSE_KCRC_ITEM_T;
|
||||
|
||||
typedef struct {
|
||||
uint16_t nBankID;
|
||||
uint16_t nLockType;
|
||||
uint32_t nDomainType;
|
||||
} FUSE_LOCK_ITEM_T;
|
||||
|
||||
#define htonl(A) \
|
||||
((((uint32_t)(A)&0xFF000000) >> 24) | (((uint32_t)(A)&0x00FF0000) >> 8) | \
|
||||
(((uint32_t)(A)&0x0000FF00) << 8) | (((uint32_t)(A)&0x000000FF) << 24))
|
||||
|
||||
#define ONE_KEY_INDEX_LENGTH (4)
|
||||
#define ONE_FUSE_INDEX_BYTE_LENGTH (4)
|
||||
|
||||
static FUSE_ERR_CODE_E fuse_program_with_readback_verify(uint32_t index,
|
||||
uint32_t value)
|
||||
{
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
uint32_t read_value = 0;
|
||||
if (0 != sdrv_fuse_sense(index, &read_value)) {
|
||||
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
|
||||
err = ERR_FUSE_BIN_READ_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((read_value & value) != value) {
|
||||
read_value |= value;
|
||||
ssdk_printf(SSDK_ERR, "write fuse %d val 0x%08x\n", index, read_value);
|
||||
|
||||
if (0 != sdrv_fuse_program(index, read_value)) {
|
||||
ssdk_printf(SSDK_ERR, "Failed to write fuse %d val 0x%08x\n", index,
|
||||
read_value);
|
||||
err = ERR_FUSE_BIN_WRITE_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
read_value = 0;
|
||||
|
||||
if (0 != sdrv_fuse_sense(index, &read_value)) {
|
||||
ssdk_printf(SSDK_ERR, "Failed to read fuse %d\n", index);
|
||||
err = ERR_FUSE_BIN_READ_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "read back fuse %d val 0x%08x\n", index,
|
||||
read_value);
|
||||
|
||||
if ((read_value & value) != value) {
|
||||
ssdk_printf(SSDK_ERR, "read back error, fuse %d val 0x%08x\n",
|
||||
index, read_value);
|
||||
err = ERR_FUSE_BIN_READBACK_VERIFY_FAIL;
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
ssdk_printf(SSDK_DEBUG, "no need to fuse\n");
|
||||
}
|
||||
|
||||
end:
|
||||
return err;
|
||||
}
|
||||
|
||||
static FUSE_ERR_CODE_E fuse_seip(uint32_t index, uint32_t length,
|
||||
uint32_t *value)
|
||||
{
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
for (uint32_t i = 0; i < length / ONE_KEY_INDEX_LENGTH; i++) {
|
||||
index += ONE_KEY_INDEX_LENGTH * i;
|
||||
value = (value + ONE_KEY_INDEX_LENGTH * i);
|
||||
for (uint32_t j = 0; j < ONE_KEY_INDEX_LENGTH; j++) {
|
||||
ssdk_printf(SSDK_CRIT, "write cipher index:0x%08x val:0x%08x\r\n",
|
||||
index + j,
|
||||
htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)));
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
err = fuse_program_with_readback_verify(
|
||||
index + j, htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)));
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
writel(htonl(*(value + ONE_KEY_INDEX_LENGTH - 1 - j)),
|
||||
APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * (index + j));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
}
|
||||
|
||||
uint32_t get_fuse_bin_size(ACTION_SEQ_T *p_action_seq)
|
||||
{
|
||||
uint32_t offset = 3 * sizeof(uint16_t) + 18 * sizeof(uint8_t);
|
||||
return *(uint32_t *)((uint8_t *)p_action_seq + offset);
|
||||
}
|
||||
|
||||
uint32_t get_fuse_bin_crc(ACTION_SEQ_T *p_action_seq)
|
||||
{
|
||||
uint32_t offset =
|
||||
3 * sizeof(uint16_t) + 18 * sizeof(uint8_t) + sizeof(uint32_t);
|
||||
return *(uint32_t *)((uint8_t *)p_action_seq + offset);
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E verify_fuse_bin_crc(void *data)
|
||||
{
|
||||
uint32_t crc_calc =
|
||||
sfs_crc32(0, (uint8_t *)data, sizeof(ACTION_SEQ_T) - sizeof(uint32_t));
|
||||
uint32_t size = get_fuse_bin_size((ACTION_SEQ_T *)data);
|
||||
crc_calc = sfs_crc32(crc_calc, (uint8_t *)data + sizeof(ACTION_SEQ_T),
|
||||
size - sizeof(ACTION_SEQ_T));
|
||||
uint32_t crc_recieved = get_fuse_bin_crc((ACTION_SEQ_T *)data);
|
||||
if (crc_calc == crc_recieved) {
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
} else {
|
||||
return ERR_FUSE_BIN_CRC_CHECK_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t get_action_count(ACTION_SEQ_T *p_action_seq)
|
||||
{
|
||||
uint32_t offset = 2 * sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_action_seq + offset);
|
||||
}
|
||||
|
||||
uint16_t get_action_type(ACTION_ITEM_T *p_action_item)
|
||||
{
|
||||
uint32_t offset = 2 * sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_action_item + offset);
|
||||
}
|
||||
|
||||
uint16_t get_action_length(ACTION_ITEM_T *p_action_item)
|
||||
{
|
||||
uint32_t offset = 3 * sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_action_item + offset);
|
||||
}
|
||||
|
||||
uint32_t get_fuse_type(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
return *(uint32_t *)(p_fuse_item);
|
||||
}
|
||||
|
||||
uint16_t get_fuse_index(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t);
|
||||
return *(uint16_t *)((uint8_t *)p_fuse_item + offset);
|
||||
}
|
||||
|
||||
uint16_t get_fuse_length(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t) + sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_fuse_item + offset);
|
||||
}
|
||||
|
||||
uint32_t *get_fuse_value(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t) + 2 * sizeof(uint16_t);
|
||||
return (uint32_t *)((uint8_t *)p_fuse_item + offset);
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_gen_and_program(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_gen_and_program\r\n");
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
int32_t ret;
|
||||
uint16_t index, length;
|
||||
uint8_t *value, *value_align, *value_align_seip;
|
||||
length = get_fuse_length(p_fuse_item);
|
||||
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
index = get_fuse_index(p_fuse_item);
|
||||
|
||||
value = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
if (!value) {
|
||||
err = ERR_FUSE_BIN_MALLOC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
value_align = (uint8_t *)ROUNDUP((uint32_t)value, CONFIG_ARCH_CACHE_LINE);
|
||||
|
||||
board_mpu_init();
|
||||
if (sdrv_crypto_init()) {
|
||||
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
arch_invalidate_cache_range((addr_t)value_align,
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
value_align_seip = (uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR(value_align);
|
||||
ssdk_printf(SSDK_CRIT, "value_align:0x%08x value_align_seip:0x%08x\r\n",
|
||||
value_align, value_align_seip);
|
||||
ret = cmd_trng_get_rand((uint8_t *)value_align_seip, length);
|
||||
if (ret != 0) {
|
||||
err = ERR_FUSE_BIN_GEN_DATA_FAIL;
|
||||
goto end;
|
||||
}
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(
|
||||
SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(uint32_t *)(value_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
err = fuse_program_with_readback_verify(index + i, *(value_align + i));
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
goto end;
|
||||
}
|
||||
#else
|
||||
writel(*(value_align + i),
|
||||
APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
|
||||
#endif
|
||||
}
|
||||
end:
|
||||
if (value)
|
||||
free(value);
|
||||
return err;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_oropr_program(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_oropr_program\r\n");
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
int32_t ret;
|
||||
uint16_t index, length;
|
||||
uint32_t *p_value;
|
||||
length = get_fuse_length(p_fuse_item);
|
||||
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
index = get_fuse_index(p_fuse_item);
|
||||
p_value = get_fuse_value(p_fuse_item);
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
uint32_t read_value = 0;
|
||||
ret = sdrv_fuse_sense(index + i, &read_value);
|
||||
if (ret != 0)
|
||||
return ERR_FUSE_BIN_READ_FAIL;
|
||||
ssdk_printf(SSDK_CRIT, "read index:0x%08x val:0x%08x\r\n", index + i,
|
||||
read_value);
|
||||
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
|
||||
((*(p_value + i)) | read_value));
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
err = fuse_program_with_readback_verify(
|
||||
index + i, ((*(p_value + i)) | read_value));
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
writel(((*(p_value + i)) | read_value),
|
||||
APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
|
||||
#endif
|
||||
}
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_direct_program(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_direct_program\r\n");
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
uint16_t index, length;
|
||||
uint32_t *p_value;
|
||||
length = get_fuse_length(p_fuse_item);
|
||||
if (length % ONE_FUSE_INDEX_BYTE_LENGTH != 0)
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
index = get_fuse_index(p_fuse_item);
|
||||
p_value = get_fuse_value(p_fuse_item);
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(p_value + i));
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
err = fuse_program_with_readback_verify(index + i, *(p_value + i));
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
writel(*(p_value + i), APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * (index + i));
|
||||
#endif
|
||||
}
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_ssrk_program(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_ssrk_program\r\n");
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
int32_t ret;
|
||||
uint16_t index, length;
|
||||
uint32_t *p_value;
|
||||
uint32_t ehsm_cfg;
|
||||
uint8_t *ssrk_plain, *ssrk_cipher;
|
||||
uint8_t *ssrk_plain_align, *ssrk_cipher_align;
|
||||
uint8_t *ssrk_plain_align_seip, *ssrk_cipher_align_seip;
|
||||
|
||||
length = get_fuse_length(p_fuse_item);
|
||||
if (length != 16 && length != 32)
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
index = get_fuse_index(p_fuse_item);
|
||||
p_value = get_fuse_value(p_fuse_item);
|
||||
|
||||
ssrk_plain = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
if (!ssrk_plain) {
|
||||
err = ERR_FUSE_BIN_MALLOC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
ssrk_cipher = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
if (!ssrk_cipher) {
|
||||
err = ERR_FUSE_BIN_MALLOC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ssrk_plain_align =
|
||||
(uint8_t *)ROUNDUP((uint32_t)ssrk_plain, CONFIG_ARCH_CACHE_LINE);
|
||||
ssrk_cipher_align =
|
||||
(uint8_t *)ROUNDUP((uint32_t)ssrk_cipher, CONFIG_ARCH_CACHE_LINE);
|
||||
|
||||
memcpy((uint8_t *)ssrk_plain_align, (uint8_t *)p_value, length);
|
||||
|
||||
#if NVM_ALG_AES_128_ECB_TEST && !REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
writel(EFUSE_NVM_ALG_AES_128_ECB << EFUSE_NVM_ALG_OFFSET,
|
||||
APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
|
||||
#endif
|
||||
|
||||
// get ehsm cfg
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
ret = sdrv_fuse_sense(EFUSE_EHSM_CFG_INDEX, &ehsm_cfg);
|
||||
if (ret != 0) {
|
||||
err = ERR_FUSE_BIN_READ_FAIL;
|
||||
goto end;
|
||||
}
|
||||
#else
|
||||
ehsm_cfg = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
|
||||
#endif
|
||||
|
||||
// enc ssrk
|
||||
board_mpu_init();
|
||||
if (sdrv_crypto_init()) {
|
||||
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
|
||||
goto end;
|
||||
}
|
||||
arch_clean_cache_range((addr_t)ssrk_plain_align,
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
arch_invalidate_cache_range((addr_t)ssrk_cipher_align,
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
|
||||
ssrk_plain_align_seip =
|
||||
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)ssrk_plain_align);
|
||||
ssrk_cipher_align_seip =
|
||||
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)ssrk_cipher_align);
|
||||
ssdk_printf(SSDK_CRIT,
|
||||
"ssrk_plain_align:0x%08x ssrk_plain_align_seip:0x%08x\r\n",
|
||||
ssrk_plain_align, ssrk_plain_align_seip);
|
||||
ssdk_printf(SSDK_CRIT,
|
||||
"ssrk_cipher_align:0x%08x ssrk_cipher_align_seip:0x%08x\r\n",
|
||||
ssrk_cipher_align, ssrk_cipher_align_seip);
|
||||
|
||||
if ((ehsm_cfg & EFUSE_NVM_ALG_MASK) >> EFUSE_NVM_ALG_OFFSET !=
|
||||
EFUSE_NVM_ALG_AES_128_ECB) {
|
||||
ssdk_printf(SSDK_CRIT, "ssrk enc by sm4 ecb\r\n");
|
||||
ret =
|
||||
cmd_ske_basic_enc(SKE_ALG_SM4_ECB, (uint8_t *)ssrk_plain_align_seip,
|
||||
length, CMD_KEY_INTERNAL, NULL, EFUSE_FSRK_KEY_ID,
|
||||
NULL, (uint8_t *)ssrk_cipher_align_seip, NULL);
|
||||
} else {
|
||||
ssdk_printf(SSDK_CRIT, "ssrk enc by aes 128 ecb\r\n");
|
||||
ret = cmd_ske_basic_enc(
|
||||
SKE_ALG_AES_128_ECB, (uint8_t *)ssrk_plain_align_seip, length,
|
||||
CMD_KEY_INTERNAL, NULL, EFUSE_FSRK_KEY_ID, (uint8_t *)NULL,
|
||||
(uint8_t *)ssrk_cipher_align_seip, NULL);
|
||||
}
|
||||
if (ret != 0) {
|
||||
err = ERR_FUSE_BIN_ENC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(
|
||||
SSDK_CRIT, "plain index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(uint32_t *)(ssrk_plain_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
|
||||
}
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(
|
||||
SSDK_CRIT, "cipher index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(uint32_t *)(ssrk_cipher_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
|
||||
}
|
||||
|
||||
// program
|
||||
err = fuse_seip(index, length / ONE_FUSE_INDEX_BYTE_LENGTH,
|
||||
(uint32_t *)ssrk_cipher_align);
|
||||
|
||||
end:
|
||||
if (ssrk_plain)
|
||||
free(ssrk_plain);
|
||||
if (ssrk_cipher)
|
||||
free(ssrk_cipher);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_tsrk_program(FUSE_BURN_ITEM_T *p_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_tsrk_program\r\n");
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
int32_t ret;
|
||||
uint16_t index, length;
|
||||
uint32_t *p_value;
|
||||
uint32_t ehsm_cfg;
|
||||
uint8_t *tsrk_plain, *tsrk_cipher;
|
||||
uint8_t *tsrk_plain_align, *tsrk_cipher_align;
|
||||
uint8_t *tsrk_plain_align_seip, *tsrk_cipher_align_seip;
|
||||
|
||||
length = get_fuse_length(p_fuse_item);
|
||||
if (length != 16 && length != 32)
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
index = get_fuse_index(p_fuse_item);
|
||||
p_value = get_fuse_value(p_fuse_item);
|
||||
|
||||
tsrk_plain = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
if (!tsrk_plain) {
|
||||
err = ERR_FUSE_BIN_MALLOC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
tsrk_cipher = (uint8_t *)malloc(CONFIG_ARCH_CACHE_LINE +
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
if (!tsrk_cipher) {
|
||||
err = ERR_FUSE_BIN_MALLOC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
tsrk_plain_align =
|
||||
(uint8_t *)ROUNDUP((uint32_t)tsrk_plain, CONFIG_ARCH_CACHE_LINE);
|
||||
tsrk_cipher_align =
|
||||
(uint8_t *)ROUNDUP((uint32_t)tsrk_cipher, CONFIG_ARCH_CACHE_LINE);
|
||||
|
||||
memcpy((uint8_t *)tsrk_plain_align, (uint8_t *)p_value, length);
|
||||
|
||||
// get enc type
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
ret = sdrv_fuse_sense(EFUSE_EHSM_CFG_INDEX, &ehsm_cfg);
|
||||
if (ret != 0) {
|
||||
err = ERR_FUSE_BIN_READ_FAIL;
|
||||
goto end;
|
||||
}
|
||||
#else
|
||||
ehsm_cfg = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * EFUSE_EHSM_CFG_INDEX);
|
||||
#endif
|
||||
|
||||
// enc tsrk
|
||||
board_mpu_init();
|
||||
if (sdrv_crypto_init()) {
|
||||
err = ERR_FUSE_BIN_ENC_INIT_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
arch_clean_cache_range((addr_t)tsrk_plain_align,
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
arch_invalidate_cache_range((addr_t)tsrk_cipher_align,
|
||||
ROUNDUP(length, CONFIG_ARCH_CACHE_LINE));
|
||||
|
||||
tsrk_plain_align_seip =
|
||||
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)tsrk_plain_align);
|
||||
tsrk_cipher_align_seip =
|
||||
(uint8_t *)TRANS_TO_SEIP_ACCESS_ADDR((uint32_t)tsrk_cipher_align);
|
||||
ssdk_printf(SSDK_CRIT,
|
||||
"tsrk_plain_align:0x%08x tsrk_plain_align_seip:0x%08x\r\n",
|
||||
tsrk_plain_align, tsrk_plain_align_seip);
|
||||
ssdk_printf(SSDK_CRIT,
|
||||
"tsrk_cipher_align:0x%08x tsrk_cipher_align_seip:0x%08x\r\n",
|
||||
tsrk_cipher_align, tsrk_cipher_align_seip);
|
||||
|
||||
if ((ehsm_cfg & EFUSE_NVM_ALG_MASK) >> EFUSE_NVM_ALG_OFFSET !=
|
||||
EFUSE_NVM_ALG_AES_128_ECB) {
|
||||
ssdk_printf(SSDK_CRIT, "tsrk enc by sm4 ecb\r\n");
|
||||
ret =
|
||||
cmd_ske_basic_enc(SKE_ALG_SM4_ECB, (uint8_t *)tsrk_plain_align_seip,
|
||||
length, CMD_KEY_INTERNAL, NULL, EFUSE_SSRK_KEY_ID,
|
||||
NULL, (uint8_t *)tsrk_cipher_align_seip, NULL);
|
||||
} else {
|
||||
ssdk_printf(SSDK_CRIT, "tsrk enc by aes 128 ecb\r\n");
|
||||
ret = cmd_ske_basic_enc(
|
||||
SKE_ALG_AES_128_ECB, (uint8_t *)tsrk_plain_align_seip, length,
|
||||
CMD_KEY_INTERNAL, NULL, EFUSE_SSRK_KEY_ID, (uint8_t *)NULL,
|
||||
(uint8_t *)tsrk_cipher_align_seip, NULL);
|
||||
}
|
||||
if (ret != 0) {
|
||||
err = ERR_FUSE_BIN_ENC_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(
|
||||
SSDK_CRIT, "plain index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(uint32_t *)(tsrk_plain_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
|
||||
}
|
||||
for (uint32_t i = 0; i < length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
ssdk_printf(
|
||||
SSDK_CRIT, "cipher index:0x%08x val:0x%08x\r\n", index + i,
|
||||
*(uint32_t *)(tsrk_cipher_align + ONE_FUSE_INDEX_BYTE_LENGTH * i));
|
||||
}
|
||||
|
||||
// program
|
||||
err = fuse_seip(index, length / ONE_FUSE_INDEX_BYTE_LENGTH,
|
||||
(uint32_t *)tsrk_cipher_align);
|
||||
|
||||
end:
|
||||
if (tsrk_plain)
|
||||
free(tsrk_plain);
|
||||
if (tsrk_cipher)
|
||||
free(tsrk_cipher);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t get_crc_fuse_type(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
return *(uint32_t *)(p_crc_fuse_item);
|
||||
}
|
||||
|
||||
uint16_t get_crc_fuse_index(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t);
|
||||
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
|
||||
}
|
||||
|
||||
uint16_t get_crc_fuse_length(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t) + sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
|
||||
}
|
||||
|
||||
uint16_t get_crc_key_index(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t) + 2 * sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
|
||||
}
|
||||
|
||||
uint16_t get_crc_key_length(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint32_t) + 3 * sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_crc_fuse_item + offset);
|
||||
}
|
||||
|
||||
static uint32_t reverse(uint32_t x)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for (int32_t i = 0; i < 32; i++) {
|
||||
result <<= 1;
|
||||
result |= (x & 1);
|
||||
x >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_kcrc_program(FUSE_KCRC_ITEM_T *p_crc_fuse_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_kcrc_program\r\n");
|
||||
uint16_t key_index, key_length, fuse_index, fuse_length;
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
int32_t ret;
|
||||
uint32_t key_value;
|
||||
uint32_t crc_calc = 0;
|
||||
key_length = get_crc_key_length(p_crc_fuse_item);
|
||||
fuse_length = get_crc_fuse_length(p_crc_fuse_item);
|
||||
if ((key_length != 16 && key_length != 32) || fuse_length != 4) {
|
||||
return ERR_FUSE_BIN_LENGTH_CHECK_FAIL;
|
||||
}
|
||||
key_index = get_crc_key_index(p_crc_fuse_item);
|
||||
for (uint32_t i = 0; i < key_length / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
// read
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
ret = sdrv_fuse_sense(key_index + i, &key_value);
|
||||
if (ret != 0) {
|
||||
return ERR_FUSE_BIN_READ_FAIL;
|
||||
}
|
||||
#else
|
||||
key_value = readl(APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * (key_index + i));
|
||||
#endif
|
||||
ssdk_printf(SSDK_CRIT, "read index:0x%08x val:0x%08x\r\n",
|
||||
key_index + i, key_value);
|
||||
// calc crc
|
||||
crc_calc = sfs_crc32(crc_calc, (uint8_t *)&key_value,
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH);
|
||||
}
|
||||
|
||||
// ssrk tsrk need add 16 bytes 0 to calc;
|
||||
if (key_length == 16) {
|
||||
for (uint32_t i = 0; i < 16 / ONE_FUSE_INDEX_BYTE_LENGTH; i++) {
|
||||
key_value = 0;
|
||||
crc_calc = sfs_crc32(crc_calc, (uint8_t *)&key_value,
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH);
|
||||
}
|
||||
}
|
||||
crc_calc = reverse(crc_calc);
|
||||
|
||||
// program
|
||||
fuse_index = get_crc_fuse_index(p_crc_fuse_item);
|
||||
ssdk_printf(SSDK_CRIT, "write index:0x%08x val:0x%08x\r\n", fuse_index,
|
||||
crc_calc);
|
||||
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
err = fuse_program_with_readback_verify(fuse_index, crc_calc);
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
writel(crc_calc, APB_EFUSEC_BASE + FUSE0_OFFSET +
|
||||
ONE_FUSE_INDEX_BYTE_LENGTH * fuse_index);
|
||||
#endif
|
||||
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
}
|
||||
|
||||
uint16_t get_lock_bank_id(FUSE_LOCK_ITEM_T *p_lock_item)
|
||||
{
|
||||
return *(uint16_t *)(p_lock_item);
|
||||
}
|
||||
|
||||
uint16_t get_lock_type(FUSE_LOCK_ITEM_T *p_lock_item)
|
||||
{
|
||||
uint32_t offset = sizeof(uint16_t);
|
||||
return *(uint16_t *)((uint8_t *)p_lock_item + offset);
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_lock_program(FUSE_LOCK_ITEM_T *p_lock_item)
|
||||
{
|
||||
ssdk_printf(SSDK_CRIT, "fuse_lock_program\r\n");
|
||||
int32_t ret;
|
||||
uint16_t bank_id = get_lock_bank_id(p_lock_item);
|
||||
uint16_t lock_type = get_lock_type(p_lock_item);
|
||||
|
||||
ssdk_printf(SSDK_CRIT, "write bank_id:0x%08x lock_type:0x%08x\r\n",
|
||||
bank_id, lock_type);
|
||||
|
||||
#if REAL_FUSE_NOT_SHADOW_REGISTER
|
||||
ret = sdrv_fuse_lock_bank((fuse_lock_bank_e)bank_id,
|
||||
(fuse_lock_bits_e)lock_type);
|
||||
if (ret != 0) {
|
||||
return ERR_FUSE_BIN_WRITE_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ERR_FUSE_BIN_NONE;
|
||||
}
|
||||
|
||||
FUSE_ERR_CODE_E fuse_bin(void *data, uint32_t sz)
|
||||
{
|
||||
uint16_t action_count;
|
||||
uint16_t action_type, action_length;
|
||||
FUSE_ERR_CODE_E err = ERR_FUSE_BIN_NONE;
|
||||
|
||||
// verify fuse bin size
|
||||
uint32_t bin_size = get_fuse_bin_size((ACTION_SEQ_T *)data);
|
||||
if (bin_size != sz) {
|
||||
ssdk_printf(SSDK_CRIT,
|
||||
"bin size check fail, size in bin:0x%x, recieved "
|
||||
"size:0x%x\r\n",
|
||||
bin_size, sz);
|
||||
return ERR_FUSE_BIN_SIZE_CHECK_FAIL;
|
||||
}
|
||||
|
||||
// verify fuse bin crc
|
||||
err = verify_fuse_bin_crc((ACTION_SEQ_T *)data);
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// get action count
|
||||
action_count = get_action_count((ACTION_SEQ_T *)data);
|
||||
ACTION_ITEM_T *p_action_item =
|
||||
(ACTION_ITEM_T *)((uint8_t *)data + sizeof(ACTION_SEQ_T));
|
||||
|
||||
for (uint16_t i = 0; i < action_count; i++) {
|
||||
// get action type
|
||||
action_type = get_action_type(p_action_item);
|
||||
void *p_item = (uint8_t *)p_action_item + sizeof(ACTION_ITEM_T);
|
||||
switch (action_type) {
|
||||
case E_ACTION_FUSE_DIRECT_PROGRAM:
|
||||
err = fuse_direct_program((FUSE_BURN_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_GEN_AND_PROGRAM:
|
||||
err = fuse_gen_and_program((FUSE_BURN_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_OR_OPR_PROGRAM:
|
||||
err = fuse_oropr_program((FUSE_BURN_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_LOCK:
|
||||
err = fuse_lock_program((FUSE_LOCK_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_SSRK_PROGRAM:
|
||||
err = fuse_ssrk_program((FUSE_BURN_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_TSRK_PROGRAM:
|
||||
err = fuse_tsrk_program((FUSE_BURN_ITEM_T *)p_item);
|
||||
break;
|
||||
case E_ACTION_FUSE_KCRC_PROGRAM:
|
||||
err = fuse_kcrc_program((FUSE_KCRC_ITEM_T *)p_item);
|
||||
break;
|
||||
default:
|
||||
err = ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND;
|
||||
break;
|
||||
}
|
||||
if (err != ERR_FUSE_BIN_NONE) {
|
||||
break;
|
||||
}
|
||||
// get next action
|
||||
action_length = get_action_length(p_action_item);
|
||||
p_action_item =
|
||||
(ACTION_ITEM_T *)((uint8_t *)p_action_item + action_length);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
20
middleware/fuse/fuse_bin.h
Normal file
20
middleware/fuse/fuse_bin.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum fuse_err_code {
|
||||
ERR_FUSE_BIN_NONE = 0,
|
||||
ERR_FUSE_BIN_UNKNOWN,
|
||||
ERR_FUSE_BIN_SIZE_CHECK_FAIL,
|
||||
ERR_FUSE_BIN_LENGTH_CHECK_FAIL,
|
||||
ERR_FUSE_BIN_ACTION_TYPE_NOT_FIND,
|
||||
ERR_FUSE_BIN_CRC_CHECK_FAIL,
|
||||
ERR_FUSE_BIN_ENC_INIT_FAIL,
|
||||
ERR_FUSE_BIN_ENC_FAIL,
|
||||
ERR_FUSE_BIN_MALLOC_FAIL,
|
||||
ERR_FUSE_BIN_GEN_DATA_FAIL,
|
||||
ERR_FUSE_BIN_READ_FAIL,
|
||||
ERR_FUSE_BIN_WRITE_FAIL,
|
||||
ERR_FUSE_BIN_READBACK_VERIFY_FAIL,
|
||||
ERR_FUSE_BIN_MAX,
|
||||
} FUSE_ERR_CODE_E;
|
||||
|
||||
FUSE_ERR_CODE_E fuse_bin(void *data, uint32_t sz);
|
||||
Reference in New Issue
Block a user