800 lines
20 KiB
C
Executable File
800 lines
20 KiB
C
Executable File
/**
|
|
nvt-opt key manager
|
|
This file will Enable and disable SRAM shutdown
|
|
@file nvt-otp.c
|
|
@ingroup
|
|
@note
|
|
Copyright Novatek Microelectronics Corp. 2018. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2 as
|
|
published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/arch/efuse_protected.h>
|
|
#include <asm/nvt-common/rcw_macro.h>
|
|
#include <asm/arch/IOAddress.h>
|
|
#include "nvt_otp_reg.h"
|
|
|
|
#ifndef CHKPNT
|
|
#define CHKPNT printf("\033[37mCHK: %d, %s\033[0m\r\n", __LINE__, __func__)
|
|
#endif
|
|
|
|
#ifndef DBGD
|
|
#define DBGD(x) printf("\033[0;35m%s=%d\033[0m\r\n", #x, x)
|
|
#endif
|
|
|
|
#ifndef DBGH
|
|
#define DBGH(x) printf("\033[0;35m%s=0x%08X\033[0m\r\n", #x, x)
|
|
#endif
|
|
|
|
#ifndef DBG_DUMP
|
|
#define DBG_DUMP(fmtstr, args...) printf(fmtstr, ##args)
|
|
#endif
|
|
|
|
#ifndef DBG_ERR
|
|
#define DBG_ERR(fmtstr, args...) printf("\033[0;31mERR:%s() \033[0m" fmtstr, __func__, ##args)
|
|
#endif
|
|
|
|
#ifndef DBG_WRN
|
|
#define DBG_WRN(fmtstr, args...) printf("\033[0;33mWRN:%s() \033[0m" fmtstr, __func__, ##args)
|
|
#endif
|
|
|
|
#if 0
|
|
#define DBG_IND(fmtstr, args...) printf("%s(): " fmtstr, __func__, ##args)
|
|
#else
|
|
#ifndef DBG_IND
|
|
#define DBG_IND(fmtstr, args...)
|
|
#endif
|
|
#endif
|
|
|
|
#define OUTREG32(x, y) writel(y, x)
|
|
#define INREG32(x) readl(x)
|
|
extern s32 local_load(u32 uiRowAddress);
|
|
extern s32 local_store(u32 uiRowAddress);
|
|
|
|
#define PLL_CLKSEL_APB 8
|
|
#define PLL_CLKSEL_APB_MASK (0x01 << PLL_CLKSEL_APB)
|
|
#define PLL_CLKSEL_APB_120 (0x00 << PLL_CLKSEL_APB) //< Select APB 120MHz
|
|
#define PLL_CLKSEL_APB_150 (0x01 << PLL_CLKSEL_APB) //< Select APB 120MHz
|
|
|
|
|
|
#define OTP_120_TIMING 0xFF6050
|
|
#define OTP_150_TIMING 0xAF7860
|
|
|
|
void otp_init(void)
|
|
{
|
|
UINT32 uiReg;
|
|
|
|
DBG_DUMP("otp_init[1.00.002]\r\n");
|
|
|
|
uiReg = INREG32(IOADDR_CG_REG_BASE + 0x10);
|
|
|
|
|
|
if ((uiReg & PLL_CLKSEL_APB_MASK) == PLL_CLKSEL_APB_120) {
|
|
DBG_DUMP("120MHz\r\n");
|
|
OUTREG32(KEY_MANAGER_TIMING_CONFIG_ADDRESS, OTP_120_TIMING);
|
|
} else if ((uiReg & PLL_CLKSEL_APB_MASK) == PLL_CLKSEL_APB_150) {
|
|
DBG_DUMP("150MHz\r\n");
|
|
OUTREG32(KEY_MANAGER_TIMING_CONFIG_ADDRESS, OTP_150_TIMING);
|
|
}
|
|
uiReg = INREG32(KEY_MANAGER_TIMING_CONFIG_ADDRESS);
|
|
DBG_DUMP("otp_timing_reg= 0x%x\r\n", (int)uiReg);
|
|
|
|
}
|
|
|
|
static s32 key_program_bit(u32 rol, u32 col)
|
|
{
|
|
return local_store(rol | (col << 5));
|
|
}
|
|
|
|
static s32 key_write_data(u32 addr, u32 data)
|
|
{
|
|
u32 ui_bits;
|
|
u32 ui_data;
|
|
|
|
if (addr < 8) {
|
|
DBG_ERR("key_write_data addr = 0x%08x error(need < 8)\r\n", (int)addr);
|
|
return EFUSE_PARAM_ERR;
|
|
}
|
|
|
|
ui_data = data;
|
|
|
|
ui_bits = 0;
|
|
while (ui_data) {
|
|
ui_bits = __builtin_ctz(ui_data);
|
|
ui_data &= ~(1 << ui_bits);
|
|
if (key_program_bit(addr, ui_bits) != E_OK) {
|
|
DBG_ERR("%s,eFuse program addr[%02x] bit[%2d] fail\r\n", __func__, (u32)addr, (int)ui_bits);
|
|
return EFUSE_OPS_ERR;
|
|
}
|
|
}
|
|
return EFUSE_SUCCESS;
|
|
}
|
|
|
|
#define KEY_MANAGER_READ_PARAM() otp_key_manager(8)
|
|
#define KEY_MANAGER_WRITE_PARAM(m) key_write_data(8, m)
|
|
|
|
|
|
/*
|
|
efuse_set_key_destination
|
|
|
|
Destination of efuse get key field value
|
|
|
|
@return IC revision of specific package revision
|
|
- @b NT9666X_VER_A NT9666X version A
|
|
- @b UNKNOWN_DIE_VER Unknown IC die version(system must halt)
|
|
*/
|
|
static ER set_key_destination(OTP_KEY_DESTINATION key_dst, SCE_KEY_SET_TO_OTP_FIELD key_field_set)
|
|
{
|
|
if (key_dst >= OTP_KEY_MANAGER_CNT) {
|
|
DBG_ERR("key_dst out of range %d\r\n", key_dst);
|
|
return EFUSE_PARAM_ERR;
|
|
}
|
|
|
|
if (key_dst == OTP_KEY_MANAGER_CRYPTO && key_field_set >= EFUSE_CRYPTO_ENGINE_KEY_CNT) {
|
|
DBG_ERR("Dest[Crypto]=>key_field_set out of range %d > %d\r\n", key_field_set, EFUSE_CRYPTO_ENGINE_KEY_CNT);
|
|
return EFUSE_PARAM_ERR;
|
|
}
|
|
|
|
if ((key_dst == OTP_KEY_MANAGER_RSA || key_dst == OTP_KEY_MANAGER_HASH) && key_field_set >= EFUSE_TOTAL_KEY_SET_FIELD) {
|
|
DBG_ERR("Dest[RSA] or [HASH] =>key_field_set out of range %d > %d\r\n", key_field_set, EFUSE_CRYPTO_ENGINE_KEY_CNT);
|
|
return EFUSE_PARAM_ERR;
|
|
}
|
|
|
|
OUTREG32(KEY_MANAGER_DESTINATION_ADDRESS, key_dst);
|
|
|
|
OUTREG32(KEY_MANAGER_KEY_INDEX_ADDRESS, key_field_set);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
efuse_get_unique_id
|
|
|
|
efuse get unique id (56bits)
|
|
|
|
@param[out] id_L LSB of ID (32bit)
|
|
@param[out] id_H MSB of ID (17bit)
|
|
|
|
@return IC success or fail
|
|
- @b EFUSE_SUCCESS success
|
|
- @b EFUSE_OPS_ERR fail
|
|
*/
|
|
ER efuse_get_unique_id(UINT32 *id_L, UINT32 *id_H)
|
|
{
|
|
UINT64 value;
|
|
u32 xy;
|
|
UINT64 dec6 = 0x81BF1000ul;
|
|
UINT64 dec5 = 0x39AA400ul;
|
|
union T_EFUSE_LOT_ID1_REG lot_id_1_reg;
|
|
union T_EFUSE_LOT_ID2_REG lot_id_2_reg;
|
|
if(is_new_key_rule()) {
|
|
lot_id_1_reg.Reg = otp_key_manager(EFUSE_LOT_ID1_NEW);
|
|
lot_id_2_reg.Reg = otp_key_manager(EFUSE_LOT_ID2_NEW);
|
|
} else {
|
|
lot_id_1_reg.Reg = otp_key_manager(EFUSE_LOT_ID1);
|
|
lot_id_2_reg.Reg = otp_key_manager(EFUSE_LOT_ID2);
|
|
}
|
|
|
|
#if 0
|
|
lot_id_1_reg.Bit.lot_id_no_1_5_0 = 36;
|
|
lot_id_1_reg.Bit.lot_id_no_2_5_0 = 36;
|
|
lot_id_1_reg.Bit.lot_id_no_3_5_0 = 36;
|
|
lot_id_1_reg.Bit.lot_id_no_4_5_0 = 36;
|
|
lot_id_1_reg.Bit.lot_id_no_5_5_0 = 36;
|
|
lot_id_2_reg.Bit.wafer_id = 26;
|
|
#endif
|
|
//catch 36bit
|
|
value = (INT64)(lot_id_1_reg.Bit.lot_id_no_1_5_0);
|
|
DBG_IND("Unique ID value=[0x%llx]\r\n", value);
|
|
value += (INT64)(lot_id_1_reg.Bit.lot_id_no_2_5_0 * 36);
|
|
DBG_IND("Unique ID value=[0x%llx]\r\n", value);
|
|
value += (INT64)(lot_id_1_reg.Bit.lot_id_no_3_5_0 * 1296);
|
|
DBG_IND("Unique ID value=[0x%llx]\r\n", value);
|
|
value += (INT64)(lot_id_1_reg.Bit.lot_id_no_4_5_0 * 46656);
|
|
DBG_IND("Unique ID value=[0x%llx]\r\n", value);
|
|
value += (INT64)(lot_id_1_reg.Bit.lot_id_no_5_5_0 * 1679616);
|
|
DBG_IND("Unique ID value=[0x%llx]\r\n", value);
|
|
|
|
value += (UINT64)(((lot_id_2_reg.Bit.lot_id_no_6_5_2 << 2) | lot_id_1_reg.Bit.lot_id_no_6_1_0) * dec5);
|
|
value += (INT64)(lot_id_2_reg.Bit.wafer_id * dec6);
|
|
|
|
xy = lot_id_2_reg.Bit.x_coordinate;
|
|
xy += (lot_id_2_reg.Bit.y_coordinate * 80);
|
|
|
|
* id_L = (u32)value;
|
|
* id_H = ((((value >> 32) & 0xF) | (xy << 4)) & 0x1FFFF);
|
|
|
|
if ((*id_L + *id_H) == 0)
|
|
return EFUSE_OPS_ERR;
|
|
else
|
|
return EFUSE_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
(v)
|
|
otp_write_key
|
|
|
|
Write specific key into specific key set (0~3)
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] key_set_index key set (0~3)
|
|
@param[in] ucKey key (16bytes)
|
|
@return Description of data returned.
|
|
- @b E_OK: Success
|
|
- @b E_SYS: Fail
|
|
*/
|
|
s32 otp_write_key(EFUSE_OTP_KEY_SET_FIELD key_set_index, UINT8 *uc_key)
|
|
{
|
|
s32 result = EFUSE_SUCCESS;
|
|
u32 key_data;
|
|
u8 *u32_key = (u8 *)uc_key;
|
|
u32 data[4];
|
|
u32 key_field_start_index = 16;
|
|
u32 index_cnt;
|
|
u32 enable_secure_number = 32;
|
|
|
|
u32 key_field_index;
|
|
u32 param;
|
|
|
|
param = KEY_MANAGER_READ_PARAM();
|
|
switch (key_set_index) {
|
|
//Note: >>>1st Key set is dedicate for secure boot usage<<<
|
|
case EFUSE_OTP_1ST_KEY_SET_FIELD:
|
|
key_field_start_index = 16;
|
|
if (is_1st_key_programmed() == 1) {
|
|
result = EFUSE_FREEZE_ERR;
|
|
} else {
|
|
enable_secure_number = SECUREBOOT_1ST_KEY_SET_PROGRAMMED;
|
|
}
|
|
break;
|
|
|
|
case EFUSE_OTP_2ND_KEY_SET_FIELD:
|
|
key_field_start_index = 20;
|
|
if (is_2nd_key_programmed() == 1) {
|
|
result = EFUSE_FREEZE_ERR;
|
|
} else {
|
|
enable_secure_number = SECUREBOOT_2ND_KEY_SET_PROGRAMMED;
|
|
}
|
|
break;
|
|
|
|
case EFUSE_OTP_3RD_KEY_SET_FIELD:
|
|
key_field_start_index = 24;
|
|
if (is_3rd_key_programmed() == 1) {
|
|
result = EFUSE_FREEZE_ERR;
|
|
} else {
|
|
enable_secure_number = SECUREBOOT_3RD_KEY_SET_PROGRAMMED;
|
|
}
|
|
break;
|
|
|
|
case EFUSE_OTP_4TH_KEY_SET_FIELD: //28,29,30,31 ---> 28,09,10,11
|
|
key_field_start_index = 28;
|
|
if (is_4th_key_programmed() == 1) {
|
|
result = EFUSE_FREEZE_ERR;
|
|
} else {
|
|
enable_secure_number = SECUREBOOT_4TH_KEY_SET_PROGRAMMED;
|
|
}
|
|
break;
|
|
|
|
case EFUSE_OTP_5TH_KEY_SET_FIELD:
|
|
key_field_start_index = 12;
|
|
if (is_5th_key_programmed() == 1) {
|
|
result = EFUSE_FREEZE_ERR;
|
|
} else {
|
|
enable_secure_number = SECUREBOOT_5TH_KEY_SET_PROGRAMMED;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DBG_ERR("Unknow key set[%d] => should be 0~4\r\n", (int)key_set_index + 1);
|
|
result = EFUSE_OPS_ERR;
|
|
break;
|
|
}
|
|
|
|
if (result != EFUSE_SUCCESS) {
|
|
if (result == EFUSE_FREEZE_ERR) {
|
|
DBG_ERR("key set[%d], key field not enpty\r\n", (int)key_set_index);
|
|
}
|
|
return result;
|
|
}
|
|
//Need porting
|
|
data[0] = *(u32 *)(u32_key + 0);
|
|
|
|
data[1] = *(u32 *)(u32_key + 4);
|
|
|
|
data[2] = *(u32 *)(u32_key + 8);
|
|
|
|
data[3] = *(u32 *)(u32_key + 12);
|
|
|
|
for (index_cnt = 0; index_cnt < EFUSE_OTP_KEY_FIELD_CNT; index_cnt++) {
|
|
key_field_index = key_field_start_index + index_cnt;
|
|
//4th key is 28,09,10,11
|
|
if (key_field_index >= 29 && ((param & OTP_NEW_KEY_RULE_ID) == (u32)OTP_NEW_KEY_RULE_ID)) {
|
|
key_field_index -= 20;
|
|
}
|
|
//DBG_DUMP("cnt[%d][0x%08x]\r\n", key_field_index, data[index_cnt]);
|
|
result = key_write_data(key_field_index, data[index_cnt]);
|
|
|
|
if (result < 0) {
|
|
DBG_ERR("[%d]set key => write addr[%2d][0x%08x] fail\r\n", (int)(key_set_index + 1), (int)key_field_index, (int)data[index_cnt]);
|
|
break;
|
|
} else {
|
|
key_data = otp_key_manager(key_field_index);
|
|
if (key_data != data[index_cnt]) {
|
|
DBG_ERR("[%d]set key => write addr[%2d][0x%08x] fail\r\n", (int)(key_set_index + 1), (int)(key_field_index), (int)data[index_cnt]);
|
|
result = EFUSE_CONTENT_ERR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (result == EFUSE_SUCCESS) {
|
|
enable_secure_boot(enable_secure_number);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
(v)
|
|
otp_set_key_destination
|
|
|
|
Durung encrypt or decrypt, configure specific key set as AES key(0~3) to crypto engine
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] key_set_index key set (0~4)
|
|
@return Description of data returned.
|
|
- @b E_OK: Success
|
|
*/
|
|
s32 otp_set_key_destination(EFUSE_OTP_KEY_SET_FIELD key_set_index)
|
|
{
|
|
u32 key_field_start_index = 16;
|
|
u32 param;
|
|
|
|
param = KEY_MANAGER_READ_PARAM();
|
|
|
|
switch (key_set_index) {
|
|
//Note: >>>1st Key set is dedicate for secure boot usage<<<
|
|
case EFUSE_OTP_1ST_KEY_SET_FIELD:
|
|
key_field_start_index = 16;
|
|
break;
|
|
|
|
case EFUSE_OTP_2ND_KEY_SET_FIELD:
|
|
key_field_start_index = 20;
|
|
break;
|
|
|
|
case EFUSE_OTP_3RD_KEY_SET_FIELD:
|
|
key_field_start_index = 24;
|
|
break;
|
|
|
|
case EFUSE_OTP_4TH_KEY_SET_FIELD:
|
|
key_field_start_index = 28;
|
|
break;
|
|
|
|
case EFUSE_OTP_5TH_KEY_SET_FIELD:
|
|
key_field_start_index = 12;
|
|
break;
|
|
|
|
default:
|
|
DBG_ERR("Unknow key set[%d] => should be 0~4\r\n", (int)key_set_index);
|
|
return EFUSE_OPS_ERR;
|
|
}
|
|
set_key_destination(OTP_KEY_MANAGER_CRYPTO, 0);
|
|
otp_key_manager(key_field_start_index);
|
|
set_key_destination(OTP_KEY_MANAGER_CRYPTO, 1);
|
|
if(key_field_start_index == 28 && ((param & OTP_NEW_KEY_RULE_ID) == (u32)OTP_NEW_KEY_RULE_ID)) { //Now = 28 + 1
|
|
key_field_start_index = 8;
|
|
}
|
|
otp_key_manager(key_field_start_index + 1);
|
|
set_key_destination(OTP_KEY_MANAGER_CRYPTO, 2);
|
|
otp_key_manager(key_field_start_index + 2);
|
|
set_key_destination(OTP_KEY_MANAGER_CRYPTO, 3);
|
|
otp_key_manager(key_field_start_index + 3);
|
|
return E_OK;
|
|
}
|
|
|
|
/**
|
|
otp_set_key_read_lock
|
|
|
|
Once otp_set_key_read_lock set, this key set field will not allow read value by CPU
|
|
|
|
(Only can operate by key manager)
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] key_set_index key set (0~4)
|
|
@return Description of data returned.
|
|
- @b E_OK: Success
|
|
*/
|
|
s32 otp_set_key_read_lock(EFUSE_OTP_KEY_SET_FIELD key_set_index)
|
|
{
|
|
u32 key_set_read_lock_index = SECUREBOOT_1ST_KEY_SET_READ_LOCK;
|
|
switch (key_set_index) {
|
|
case EFUSE_OTP_1ST_KEY_SET_FIELD:
|
|
key_set_read_lock_index = SECUREBOOT_1ST_KEY_SET_READ_LOCK;
|
|
break;
|
|
|
|
case EFUSE_OTP_2ND_KEY_SET_FIELD:
|
|
key_set_read_lock_index = SECUREBOOT_2ND_KEY_SET_READ_LOCK;
|
|
break;
|
|
|
|
case EFUSE_OTP_3RD_KEY_SET_FIELD:
|
|
key_set_read_lock_index = SECUREBOOT_3RD_KEY_SET_READ_LOCK;
|
|
break;
|
|
|
|
case EFUSE_OTP_4TH_KEY_SET_FIELD:
|
|
key_set_read_lock_index = SECUREBOOT_4TH_KEY_SET_READ_LOCK;
|
|
break;
|
|
|
|
case EFUSE_OTP_5TH_KEY_SET_FIELD:
|
|
key_set_read_lock_index = SECUREBOOT_5TH_KEY_SET_READ_LOCK;
|
|
break;
|
|
|
|
default:
|
|
DBG_ERR("Unknow key set[%d] => should be 0~4\r\n", (int)key_set_index);
|
|
return EFUSE_OPS_ERR;
|
|
}
|
|
|
|
enable_secure_boot(key_set_read_lock_index);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
otp_set_key_engine_access_right
|
|
|
|
Once otp_set_key_engine_access_right set, this key set field will not transfer key to destination engine(RSA/HASH/Crypto)
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] key_set_index key set (0~4)
|
|
@return Description of data returned.
|
|
- @b E_OK: Success
|
|
*/
|
|
s32 otp_set_key_engine_access_right(EFUSE_OTP_KEY_SET_FIELD key_set_index)
|
|
{
|
|
u32 key_set_engine_access_right_index;
|
|
switch (key_set_index) {
|
|
case EFUSE_OTP_1ST_KEY_SET_FIELD:
|
|
key_set_engine_access_right_index = OTP_1ST_KEY_BIT_START;
|
|
break;
|
|
|
|
case EFUSE_OTP_2ND_KEY_SET_FIELD:
|
|
key_set_engine_access_right_index = OTP_2ND_KEY_BIT_START;
|
|
break;
|
|
|
|
case EFUSE_OTP_3RD_KEY_SET_FIELD:
|
|
key_set_engine_access_right_index = OTP_3RD_KEY_BIT_START;
|
|
break;
|
|
|
|
case EFUSE_OTP_4TH_KEY_SET_FIELD:
|
|
if(is_new_key_rule () == TRUE) {
|
|
key_set_engine_access_right_index = OTP_4TH_KEY_BIT_START_NEW;
|
|
} else {
|
|
key_set_engine_access_right_index = OTP_4TH_KEY_BIT_START;
|
|
}
|
|
break;
|
|
|
|
case EFUSE_OTP_5TH_KEY_SET_FIELD:
|
|
key_set_engine_access_right_index = OTP_5TH_KEY_BIT_START;
|
|
break;
|
|
|
|
default:
|
|
DBG_ERR("Unknow key set[%d] => should be 0~4\r\n", (int)key_set_index);
|
|
return EFUSE_OPS_ERR;
|
|
}
|
|
EFUSE_SET_ENGINE_ACCESS_RIGHT(key_set_engine_access_right_index);
|
|
|
|
return EFUSE_SUCCESS;
|
|
}
|
|
|
|
//Bit[0] & Bit[5] == 1
|
|
/**
|
|
quary_secure_boot
|
|
|
|
Quary now is what kind of secure boot type
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] scu_status status
|
|
@return Description of data returned.
|
|
- @b TRUE: enabled
|
|
- @b FALSE: disabled
|
|
*/
|
|
BOOL quary_secure_boot(SECUREBOOT_STATUS scu_status)
|
|
{
|
|
u32 sec;
|
|
BOOL result = FALSE;
|
|
|
|
sec = KEY_MANAGER_READ_PARAM();
|
|
|
|
switch (scu_status) {
|
|
case SECUREBOOT_SECURE_EN:
|
|
if ((sec & (OTP_HW_SECURE_EN | OTP_FW_SECURE_EN)) == (OTP_HW_SECURE_EN | OTP_FW_SECURE_EN)) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_DATA_AREA_ENCRYPT:
|
|
if ((sec & OTP_DATA_ENCRYPT_EN) == OTP_DATA_ENCRYPT_EN) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_SIGN_RSA:
|
|
if ((sec & OTP_SIGNATURE_RSA) == OTP_SIGNATURE_RSA) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_SIGN_RSA_CHK:
|
|
if ((sec & OTP_SIGNATURE_RSA_CHK_EN) == OTP_SIGNATURE_RSA_CHK_EN) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_JTAG_DISABLE_EN:
|
|
if ((sec & OTP_JTAG_DISABLE_EN) == OTP_JTAG_DISABLE_EN) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_1ST_KEY_SET_PROGRAMMED:
|
|
if ((sec & OTP_1ST_KEY_PROGRAMMED) == OTP_1ST_KEY_PROGRAMMED) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_2ND_KEY_SET_PROGRAMMED:
|
|
if ((sec & OTP_2ND_KEY_PROGRAMMED) == OTP_2ND_KEY_PROGRAMMED) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_3RD_KEY_SET_PROGRAMMED:
|
|
if ((sec & OTP_3RD_KEY_PROGRAMMED) == OTP_3RD_KEY_PROGRAMMED) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_4TH_KEY_SET_PROGRAMMED:
|
|
if ((sec & OTP_4TH_KEY_PROGRAMMED) == OTP_4TH_KEY_PROGRAMMED) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_5TH_KEY_SET_PROGRAMMED:
|
|
if ((sec & OTP_5TH_KEY_PROGRAMMED) == OTP_5TH_KEY_PROGRAMMED) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_1ST_KEY_SET_READ_LOCK:
|
|
if ((sec & OTP_1ST_KEY_READ_LOCK) == OTP_1ST_KEY_READ_LOCK) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_2ND_KEY_SET_READ_LOCK:
|
|
if ((sec & OTP_2ND_KEY_READ_LOCK) == OTP_2ND_KEY_READ_LOCK) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_3RD_KEY_SET_READ_LOCK:
|
|
if ((sec & OTP_3RD_KEY_READ_LOCK) == OTP_3RD_KEY_READ_LOCK) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_4TH_KEY_SET_READ_LOCK:
|
|
if ((sec & OTP_4TH_KEY_READ_LOCK) == OTP_4TH_KEY_READ_LOCK) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_5TH_KEY_SET_READ_LOCK:
|
|
if ((sec & OTP_5TH_KEY_READ_LOCK) == OTP_5TH_KEY_READ_LOCK) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_NEW_KEY_RULE:
|
|
if ((sec & OTP_NEW_KEY_RULE_ID) == OTP_NEW_KEY_RULE_ID) {
|
|
result = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
set_secure_boot
|
|
|
|
Quary now is what kind of secure boot type
|
|
|
|
@Note: key set 0 is for secure boot use
|
|
|
|
@param[in] scu_status status
|
|
@return Description of data returned.
|
|
- @b TRUE: enabled
|
|
- @b FALSE: something wrong(already configured)
|
|
*/
|
|
BOOL enable_secure_boot(SECUREBOOT_STATUS scu_status)
|
|
{
|
|
u32 sec;
|
|
BOOL result = FALSE;
|
|
sec = KEY_MANAGER_READ_PARAM();
|
|
|
|
switch (scu_status) {
|
|
case SECUREBOOT_SECURE_EN:
|
|
if ((sec & (OTP_HW_SECURE_EN | OTP_FW_SECURE_EN)) != 0x0) {
|
|
DBG_ERR("Secure already enabled ...");
|
|
} else {
|
|
result = TRUE;
|
|
KEY_MANAGER_WRITE_PARAM((OTP_HW_SECURE_EN | OTP_FW_SECURE_EN));
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_DATA_AREA_ENCRYPT:
|
|
if ((sec & OTP_DATA_ENCRYPT_EN) != 0x0) {
|
|
DBG_ERR("Data area encrypted bit already set ...");
|
|
} else {
|
|
result = TRUE;
|
|
KEY_MANAGER_WRITE_PARAM(OTP_DATA_ENCRYPT_EN);
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_SIGN_RSA:
|
|
if ((sec & OTP_SIGNATURE_RSA) != 0x0) {
|
|
DBG_ERR("Signature use RSA bit already set ...");
|
|
} else {
|
|
result = TRUE;
|
|
KEY_MANAGER_WRITE_PARAM(OTP_SIGNATURE_RSA);
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_SIGN_RSA_CHK:
|
|
|
|
if ((sec & OTP_SIGNATURE_RSA_CHK_EN) != 0x0) {
|
|
DBG_ERR("Signature use RSA and process hash checksum bit already set ...\r\n");
|
|
} else {
|
|
result = TRUE;
|
|
KEY_MANAGER_WRITE_PARAM(OTP_SIGNATURE_RSA_CHK_EN);
|
|
}
|
|
break;
|
|
|
|
case SECUREBOOT_JTAG_DISABLE_EN:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_JTAG_DISABLE_EN);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_1ST_KEY_SET_PROGRAMMED:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_1ST_KEY_PROGRAMMED);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_2ND_KEY_SET_PROGRAMMED:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_2ND_KEY_PROGRAMMED);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_3RD_KEY_SET_PROGRAMMED:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_3RD_KEY_PROGRAMMED);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_4TH_KEY_SET_PROGRAMMED:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_4TH_KEY_PROGRAMMED);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_5TH_KEY_SET_PROGRAMMED:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_5TH_KEY_PROGRAMMED);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_1ST_KEY_SET_READ_LOCK:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_1ST_KEY_READ_LOCK);
|
|
result = TRUE;
|
|
break;
|
|
|
|
//2ND & 3RD key set can not configured as read lock(because of RSA checksum)
|
|
#if 0
|
|
case SECUREBOOT_2ND_KEY_SET_READ_LOCK:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_2ND_KEY_READ_LOCK);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_3RD_KEY_SET_READ_LOCK:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_3RD_KEY_READ_LOCK);
|
|
result = TRUE;
|
|
break;
|
|
#endif
|
|
|
|
case SECUREBOOT_4TH_KEY_SET_READ_LOCK:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_4TH_KEY_READ_LOCK);
|
|
result = TRUE;
|
|
break;
|
|
|
|
case SECUREBOOT_5TH_KEY_SET_READ_LOCK:
|
|
KEY_MANAGER_WRITE_PARAM(OTP_5TH_KEY_READ_LOCK);
|
|
result = TRUE;
|
|
break;
|
|
case SECUREBOOT_2ND_KEY_SET_READ_LOCK:
|
|
case SECUREBOOT_3RD_KEY_SET_READ_LOCK:
|
|
DBG_ERR("2ND & 3RD key set can not configured as read lock(RSA checksum)");
|
|
default:
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
otp read data
|
|
|
|
Read specific eFuse addressing(32bits/per time)
|
|
^
|
|
|-- (row address)
|
|
@param[in] rowAddress row address
|
|
|
|
@return read half-word efuse data
|
|
- @b Positive: Valid data
|
|
- @b E_SYS : Invalid data
|
|
*/
|
|
u32 otp_key_manager(u32 rowAddress)
|
|
{
|
|
s32 uiData;
|
|
|
|
uiData = local_load(rowAddress);
|
|
|
|
return uiData;
|
|
}
|
|
|
|
/*
|
|
exteact trim data valid
|
|
|
|
Parsing trim data is valid or not
|
|
|
|
@param [in] code trim raw data
|
|
@param[out] pData Point of valid trim data
|
|
|
|
@return read half-word efuse data
|
|
- @b TRUE : Valid data
|
|
- @b FALSE : Invalid data
|
|
*/
|
|
BOOL extract_trim_valid(u32 code, u32 *pData)
|
|
{
|
|
u32 i;
|
|
u32 ret = 0;
|
|
BOOL is_found = FALSE;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (code & (1 << 14)) {
|
|
// do nothing: skip this setting
|
|
} else if (code & (1 << 15)) {
|
|
ret = code & 0x3FFF;
|
|
*pData = ret;
|
|
is_found = TRUE;
|
|
break;
|
|
} else {
|
|
// bit[15..14] = 0x0: efuse never programmed
|
|
break;
|
|
}
|
|
|
|
code >>= 16;
|
|
}
|
|
|
|
return is_found;
|
|
}
|
|
|