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