Files
base/middleware/fuse/fuse_bin.c
2025-11-07 09:57:14 +08:00

807 lines
26 KiB
C

#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;
}