int DRV_GET_CHIPID(unsigned char* buf,int length) { unsigned int i = 0; int ret = 0; if(NULL == buf) { efuse_print_error("die id buf is error.\n"); return EFUSE_ERROR; } if(length < EFUSE_CHIPID_LEN) { efuse_print_error("die id lenth is error.\n"); return EFUSE_ERROR; } memset(buf, 0, EFUSE_CHIPID_LEN); pr_info("efuse read start group %d length %d.\n", EFUSE_GRP_CHIPID, EFUSE_CHIPID_SIZE); if(0 != (ret = bsp_efuse_read((u32*)buf, EFUSE_GRP_CHIPID, EFUSE_CHIPID_SIZE))) { efuse_print_error("chip id read efuse error.\n"); return READ_EFUSE_ERROR; } for(i = 0; i < EFUSE_CHIPID_SIZE; i++) { pr_info("efuse end buf[%d] is 0x%x.\n", i, buf[i]); } pr_info("efuse read end ret %d\n", ret); return EFUSE_OK; }
/****************************************************************************** * 函 数 名: is_burn * 功能描述: 检查efuse是否已经烧写了flash info * 输入参数: @burn_flag: 烧写标志。1 - 已烧写;0 - 未烧写 * @buffer: efuse中nandc info所在group的值 * 输出参数: 无 * 返 回 值: 0 - 成功; 非0 - 失败 * 函数说明: 检查 *******************************************************************************/ static s32 is_burn(u32 *burn_flag) { s32 ret; u32 efuse_nand_info_addr = EFUSE_NANDC_GROUP_OFFSET; u32 buffer = 0; ret = bsp_efuse_read(&buffer, efuse_nand_info_addr, EFUSE_NANDC_GROUP_LENGTH); if(ret) { PRINT_MSG("Efuse read info error\n"); goto erro; } PRINT_MSG("After read: 0x%x\n", buffer); ret = check_flag(buffer); if(EFUSE_NANDC_NOT_BURN == ret) { *burn_flag = EFUSE_NANDC_NOT_BURN; } else { *burn_flag = EFUSE_NANDC_HAD_BURN; } return OK; erro: return ret; }
void efuse_handle_work(struct work_struct *work) { u32 i = 0; int length = 0; u32 channel_id = ICC_CHN_IFC << 16 | IFC_RECV_FUNC_EFUSE; EFUSE_DATA_STRU *msg = &efuse_msg; if(EFUSE_READ == (u32)msg->opt) { if(1 == efuse_debug_flag) { pr_info("efuse read start group %d length %d.\n", msg->start, msg->len); } msg->ret = bsp_efuse_read(msg->buf, msg->start,msg->len); if(1 == efuse_debug_flag) { pr_info("efuse read end group %d length %d.\n", msg->start, msg->len); for(i = 0;i < msg->len;i++) { pr_info("efuse buf[%d] is 0x%x.\n", i, msg->buf[i]); } pr_info("efuse read ret %d\n", msg->ret); } } else if(EFUSE_WRITE == (u32)msg->opt) { if(1 == efuse_debug_flag) { pr_info("efuse write start group %d length %d.\n", msg->start, msg->len); for(i = 0;i < msg->len;i++) { pr_info("efuse buf[%d] is 0x%x.\n", i, msg->buf[i]); } } msg->ret = bsp_efuse_write(msg->buf, msg->start,msg->len); if(1 == efuse_debug_flag) { pr_info("efuse write ret %d.\n", msg->ret); } } else { msg->ret = EFUSE_ERROR; } length = bsp_icc_send(ICC_CPU_MODEM, channel_id, (unsigned char*)msg, sizeof(EFUSE_DATA_STRU)); if(length != (int)sizeof(EFUSE_DATA_STRU)) { efuse_print_error("send len(%x) != expected len(%lu).\n", length, (unsigned long)sizeof(EFUSE_DATA_STRU)); return; } }
void bsp_efuse_show(void) { unsigned int i = 0; unsigned int value = 0; for(i = 0;i < EFUSE_MAX_SIZE;i++) { if(OK == bsp_efuse_read(&value, i, 1)) { efuse_print_info("efuse group%d value = 0x%x.\n ", i, value); } else { efuse_print_error("efuse group%d read fail.\n", i); return; } } }
/************************************************* 函 数 名 : secureAlreadyUse 功能描述 : 查询当前版本是否已经启用安全启动 输入参数 : unsigned char *pData 输出参数 : unsigned char *pData 返 回 值 : OK/ERROR 调用函数 : 被调函数 : 修改历史 : 日 期 : 2010年12月21日 作 者 : 修改内容 : *************************************************/ s32 secureAlreadyUse(u8 * pData) { u32 efuse_security_flag = 0; s32 sec_err_code = SEC_OK; if(NULL == pData) { return SEC_ERROR_NULL_PTR; } sec_err_code = bsp_efuse_read(&efuse_security_flag, EFUSE_GRP_SECURITY, 1); if( SEC_OK != sec_err_code) { return sec_err_code; } /*判断安全位是否已写入*/ *pData = ((efuse_security_flag & EFUSEC_SEC_EN_MASK) == EFUSEC_SEC_EN) ? (u8)SECURE_ENABLE : (u8)SECURE_DISABLE; return sec_err_code; }
/****************************************************************************** * 函 数 名: do_burn * 功能描述: 将flash spec信息烧写到efuse * 输入参数: @spec:存放flash info * 输出参数: 无 * 返 回 值: 0 - 成功; 非0 - 失败 * 函数说明: *******************************************************************************/ static s32 do_burn(struct nand_spec *spec) { s32 ret = ERROR; u32 efuse_nand_info_addr = EFUSE_NANDC_GROUP_OFFSET; u32 read_value; u32 value = 0; /* param error */ if(!spec) { PRINT_MSG("Param failed\n"); goto erro; } /* make value */ switch(spec->pagenumperblock) /* add page num per block */ { case NANDC_BLOCK_64PAGE: value |= EFUSE_NANDC_BLOCKSIZE_64PAGE; break; case NANDC_BLOCK_128PAGE: value |= EFUSE_NANDC_BLOCKSIZE_128PAGE; break; default: break; } PRINT_MSG("Add block size: 0x%x\n", value); /*lint -save -e30, -e142*/ switch(spec->ecctype) /* add ecc type */ { case NANDC_ECC_NONE: value |= EFUSE_NANDC_ECCTYPE_NONE; break; case NANDC_ECC_1BIT: value |= EFUSE_NANDC_ECCTYPE_1BIT; break; case NANDC_ECC_4BIT: value |= EFUSE_NANDC_ECCTYPE_4BIT; break; case NANDC_ECC_8BIT: value |= EFUSE_NANDC_ECCTYPE_8BIT; break; default: break; } /*lint -restore*/ PRINT_MSG("Add ecc type: 0x%x\n", value); switch(spec->pagesize) /* add page size */ { case NANDC_SIZE_HK: value |= EFUSE_NANDC_PAGESIZE_hK; break; case NANDC_SIZE_2K: value |= EFUSE_NANDC_PAGESIZE_2K; break; case NANDC_SIZE_4K: value |= EFUSE_NANDC_PAGESIZE_4K; break; case NANDC_SIZE_8K: value |= EFUSE_NANDC_PAGESIZE_8K; break; default: break; } PRINT_MSG("Add page size: 0x%x\n", value); switch(spec->addrnum) /* add addr num */ { case NANDC_ADDRCYCLE_4: value |= EFUSE_NANDC_ADDRNUM_4CYCLE; break; case NANDC_ADDRCYCLE_5: value |= EFUSE_NANDC_ADDRNUM_5CYCLE; break; default: break; } PRINT_MSG("Add addr num: 0x%x\n", value); /* set burn flag */ value |= EFUSE_NANDC_BURNFLAG_HADBURN; PRINT_MSG("Add burn flag: 0x%x\n", value); /* set configure nandc from efuse */ value |= EFUSE_CONF_FROM_EFUSE; PRINT_MSG("Add conf flag: 0x%x\n", value); /* write info */ ret = bsp_efuse_write(&value, efuse_nand_info_addr, EFUSE_NANDC_GROUP_LENGTH); if(ret) { PRINT_MSG("EFuse write failed\n"); goto erro; } /* read and compare */ ret = bsp_efuse_read(&read_value, efuse_nand_info_addr, EFUSE_NANDC_GROUP_LENGTH); if(ret) { PRINT_MSG("EFuse read failed\n"); goto erro; } if(read_value != value) { PRINT_MSG("EFuse value cmp error, write value: 0x%x, read value 0x%x\n", value, read_value); ret = ERROR; goto erro; } PRINT_MSG("SUCCESS: write nandc info successful\n"); return OK; erro: return ret; }
/***************************************************************************** * 函 数 名 : create_crypto_key * * 功能描述 : 使用输入的数据和HUK,生成密钥。当前支持MD5、和SHA-1算法。 * * 生成密钥的方法: * 把HUK和输入的数据连接起来作为MD5或SHA-1算法的输入,计算其HASH值。 * * 输入参数 : data: 用于生成密钥的数据。 * len: 用于生成密钥的数据长度。(byte) * algorithm: 要使用的密钥生成算法。 * klen: 作为输入参数,存放key的缓冲区的长度。(byte) * * 输出参数 : key: 存放生成的密钥。buffer必须大于16(MD5)/20(SHA-1)字节。 * klen: 作为输出参数,存放生成的密钥的长度。(byte) * * 返 回 值 : BSP_OK: 生成成功。 * BSP_ERROR: 生成失败。 * * 其它说明 : klen为输入/输出参数,传入的klen变量所用内存必须可写回。 * 所以避免直接传入类似sizeof()的函数调用结果。 * *****************************************************************************/ int create_crypto_key_o(char *data, int len, CREATE_CRYPTO_KEY_ALGORITHM algorithm, char *key, int *klen) { char* crypto_data = NULL; UINT8 i=0; if(BSP_OK != param_check(data,len,algorithm,key,klen)) { security_print("ERROR create_crypto_key: param is invalid!\n"); goto ERROR_EXIT; } crypto_data = (char*)malloc(len + HUK_LEN); if(crypto_data == NULL) { security_print("ERROR create_crypto_key: malloc failed!\n"); goto ERROR_EXIT; } memset(crypto_data, 0, len + HUK_LEN); /* Read & Copy HUK.*/ if(BSP_OK != bsp_efuse_read((u32*)crypto_data, EFUSE_GRP_HUK, (HUK_LEN/sizeof(uint32)) )) { /*规避EFUSE写入后需要重启才能读取的问题*/ if(!CheckHukIsValid()) { security_print("ERROR create_crypto_key: efuseRead failed!\n"); goto ERROR_EXIT; } } for(i=0;i<HUK_LEN;i++) { if(0 != *(((UINT8*)crypto_data)+i)) { break; } } if(i>=HUK_LEN) { security_print("ERROR create_crypto_key: read_efuse NULL!\n"); goto ERROR_EXIT; } // Copy user data. memcpy((void*)((UINT32)crypto_data + HUK_LEN), data, len); // Encrypt. switch(algorithm) { /*case CREATE_CRYPTO_KEY_ALGORITHM_MD5:*/ /*case CREATE_CRYPTO_KEY_ALGORITHM_SHA1:*/ case CREATE_CRYPTO_KEY_ALGORITHM_SHA256: if(BSP_OK != crypto_hash(crypto_data, len + HUK_LEN, (CRYPTO_HASH_ALGORITHM)algorithm, key, klen)) { security_print("ERROR create_crypto_key: crypto_hash failed!\n"); goto ERROR_EXIT; } break; default: security_print("ERROR create_crypto_key: unknown algorithm!\n"); goto ERROR_EXIT; } //OK_EXIT: if(crypto_data != NULL) { free(crypto_data); } #ifndef _DRV_LLT_ /*REG_WRITE_32(PWR_SC_PERIPH_CLKDIS0, SOC_CLK_CLOSE_DIS0);*/ #endif return BSP_OK; ERROR_EXIT: if(crypto_data != NULL) { free(crypto_data); } return BSP_ERROR; }
s32 startSecure(void) { s32 sec_err_code = SEC_OK; u8 flag = 0; u8 * m3boot_ram_addr = NULL; u32 ulEfuseRootCaHash[SHA256_HASH_SIZE] = {0}; /*用来存放SHA256值的临时buffer*/ u32 efuse_security_flag = 0; u32 md5_hash[MD5_HASH_SIZE] = {0}; sec_err_code = secureAlreadyUse(&flag); if(sec_err_code) { return -1; } if( SECURE_ENABLE == flag ) /* has been written */ { return SEC_OK; } sec_err_code = secureSupport(&flag); if(SEC_OK != sec_err_code) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "[SEC ERROR]check Secure support error!\n"); return sec_err_code; } if(SECURE_NOT_SUPPORT == flag) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "[SEC ERROR]Secure not support!\n"); return SEC_ERROR_IMG_SECURY_NOT_SUPPORT; } m3boot_ram_addr = (u8*)osl_malloc(ROOT_CA_LEN); if(!m3boot_ram_addr) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "[SEC ERROR]NO mem error!\n"); return -1; } sec_err_code = BSP_mass_read("m3boot", /*P531_M3_LEN_INDEX + sizeof(u32)*/ROOT_CA_INDEX, ROOT_CA_LEN, m3boot_ram_addr); if(SEC_OK != sec_err_code) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "BSP_mass_read error!\n"); return sec_err_code; } #if 0//for debug, print rootca printf("\n"); for(i = 0; i < ROOT_CA_LEN / 4; i += 4) { printf("%X\n", *(unsigned long *)(m3boot_ram_addr + i)); } printf("\n"); #endif /*计算ROOT CA HASH*/ sec_err_code = kdf_sha256(m3boot_ram_addr, ROOT_CA_LEN, (u8*)ulEfuseRootCaHash); if(SEC_OK != sec_err_code) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "\r\ncalc RootCa sha1 err!\n"); return SEC_ERROR_SHA_ERR; } /*计算HASH值的MD5值*/ sec_err_code = encrypt_lock_md5_data(ulEfuseRootCaHash, SHA256_HASH_SIZE * sizeof(u32), md5_hash); if(sec_err_code) { return -1; } sec_err_code = bsp_efuse_read(&efuse_security_flag, EFUSE_GRP_SECURITY, 1); if( SEC_OK != sec_err_code) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_SECURITY, "startSecure: run efuse_read error!\n"); return SEC_ERROR_EFUSE_READ_ERR; } efuse_security_flag |= EFUSEC_SEC_EN; /* write RootCA hash */ if( SEC_OK != bsp_efuse_write( md5_hash, EFUSE_GRP_ROOT_CA, 4 ) ) { return -1; } /* Last step, enable security boot */ if( SEC_OK != bsp_efuse_write( (u32 *)&efuse_security_flag, EFUSE_GRP_SECURITY, 1 ) ) { return -1; } bsp_trace(BSP_LOG_LEVEL_INFO, BSP_MODU_SECURITY, "\r\nstartSecure SUCC!\r\n", 0, 0, 0, 0, 0, 0 ); return 0; }