blob: b484afe6f5c307fb5746a989e485e135fa5d94c8 [file] [log] [blame]
#include <Typedef.h>
#include <predefines.h>
#include <Errors.h>
#include "GEU.h"
#include "GEU_FuseReadMethods.h"
#include "GEU_Provisioning.h"
extern INT_T PlatformIsNezhac(void);
// returns number of ones set in value
UINT_T countOnes(UINT_T value)
{
UINT_T i=0;
for(i=0;value;i++)
value &=(value-1);
return i;
}
UINT_T GEU_ReadApCpConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T temp[3];
if (Size < K_APCP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, temp[0]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, temp[1]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, temp[2]);
//CP config[15:0]
pBuffer[0] = (temp[2] >> 16) & 0xFFFF;
//AP config[15:0]
pBuffer[0] |= (temp[0] & 0xFFFF) << 16;
//AP config[31:16]
pBuffer[1] = (temp[0] >> 16)& 0xFFFF;
//AP config[47:32]
pBuffer[1] = (temp[1] & 0xFFFF)<< 16;
//AP config[63:48]
pBuffer[2] = (temp[1] >> 16)& 0xFFFF;
//AP config[79:64]
pBuffer[2] = (temp[2] & 0xFFFF)<< 16;
return NoError;
};
UINT_T GEU_ReadApConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T temp[3];
if (Size < K_AP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, temp[0]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, temp[1]);
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, temp[2]);
//AP config[31:0]
pBuffer[0] = temp[0];
//AP config[63:32]
pBuffer[1] = temp[1];
//AP config[79:64]
pBuffer[2] = temp[2] & 0xFFFF;
return NoError;
};
UINT_T GEU_ReadCpConfigFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T temp;
if (Size < K_CP_CONFIG_FUSE_SIZE)
{
return (FUSE_BufferTooSmall);
}
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, temp);
//CP config[15:0]
pBuffer[0] = (temp >> 16) & 0xFFFF;
return NoError;
};
UINT_T GEU_ReadOemHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size)
{
if (!((Size == K_SHA1_SIZE)||(Size == K_SHA256_SIZE)))
{
return (FUSE_InvalidBufferSize);
}
// return 20 bytes regardless of size
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+0, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+4, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+8, pBuffer[2]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+12, pBuffer[3]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+16, pBuffer[4]);
if (Size == K_SHA256_SIZE) //32
{
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+20, pBuffer[5]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+24, pBuffer[6]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_HASH_KEY+28, pBuffer[7]);
}
return NoError;
};
UINT_T GEU_ReadRkekFuseBits(UINT_T* pBuffer, UINT_T Size)
{
if (Size != K_FUSEBLOCK_SIZE)
{
return (FUSE_InvalidBufferSize);
}
// return 20 bytes regardless of size
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+0, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+4, pBuffer[1]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+8, pBuffer[2]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+12, pBuffer[3]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+16, pBuffer[4]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+20, pBuffer[5]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+24, pBuffer[6]);
GEU_REG_READ(GEU_FUSE_VAL_ROOT_KEY1+28, pBuffer[7]);
return NoError;
};
UINT_T GEU_ReadUsbIdFuseBits(UINT_T* pBuffer, UINT_T Size)
{
if (Size != K_USBID_FUSE_SIZE)
{
return (FUSE_InvalidBufferSize);
}
// Bootrom only supports 32 bits so only read one register (32 bts of ID).
GEU_REG_READ(GEU_FUSE_VAL_USB_VER_ID, pBuffer[0]);
return NoError;
};
/************************************
* Returns current Lifecycle
************************************/
UINT_T GEU_ReadLifeCycle()
{
UINT_T regValue, lifeCycleCount = 0;
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_LCS, regValue);
// Check CM
//lifeCycleCount += countOnes((regValue & GEU_FUSE_VAL_LIFECYCLE_CM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_CM_BASE);
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_CM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_CM_BASE);
// Check DM
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_DM_MSK) >> GEU_FUSE_VAL_LIFECYCLE_DM_BASE);
// Check DD
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_DD_MSK) >> GEU_FUSE_VAL_LIFECYCLE_DD_BASE);
// Check FA
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_FA_MSK) >> GEU_FUSE_VAL_LIFECYCLE_FA_BASE);
// Check JPD
lifeCycleCount += PHYSICAL_TO_LOGICAL((regValue & GEU_FUSE_VAL_LIFECYCLE_PD_MSK) >> GEU_FUSE_VAL_LIFECYCLE_PD_BASE);
return lifeCycleCount;
}
UINT_T GEU_ReadLifeCycleState()
{
UINT_T lcs;
GEU_REG_READ(GEU_FUSE_VAL_LIFECYCLE_LCS, lcs);
lcs &= 0xFFFF;
return lcs;
}
INT_T GEU_LifeCycleIsDD(void)
{
UINT_T lcs;
lcs = GEU_ReadLifeCycleState();
lcs = PHYSICAL_TO_LOGICAL((lcs & GEU_FUSE_VAL_LIFECYCLE_DD_MSK) >> GEU_FUSE_VAL_LIFECYCLE_DD_BASE);
return lcs;
}
UINT_T GEU_ReadOemUidFuseBits(UINT_T* pBuffer, UINT_T Size)
{
UINT_T scratch;
if (Size != K_OEM_UNIQUE_ID_FUSE_SIZE)
{
return (FUSE_InvalidBufferSize);
}
#if NZAC || LAPW
GEU_REG_READ(GEU_FUSE_VAL_OEM_UID_L, pBuffer[0]);
GEU_REG_READ(GEU_FUSE_VAL_OEM_UID_H, pBuffer[1]);
#else
GEU_REG_READ(ASR1803GEU_FUSE_VAL_OEM_UID_L, pBuffer[0]);
GEU_REG_READ(ASR1803GEU_FUSE_VAL_OEM_UID_H, pBuffer[1]);
#endif
return NoError;
};
UINT_T GEU_JtagFuseDisabled(VOID)
{
UINT_T value;
GEU_ReadCpConfigFuseBits(&value, K_CP_CONFIG_FUSE_SIZE);
if((value & BIT_14) && GEU_LifeCycleIsDD())
return 1;
return 0;
}
UINT_T GEU_ForceDownloadFuseDisabled(VOID)
{
UINT_T value;
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, value);
if(value & BIT_13)
return 1;
return 0;
}
UINT_T GEU_RomLogDisabled(VOID)
{
UINT_T value;
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, value);
if(value & BIT_3)
return 1;
return 0;
}
UINT_T GEU_ReadSoftwareVersion(VOID)
{
UINT_T value;
GEU_REG_READ(GEU_FUSE_BANK0_239_208, value);
return value;
}
INT GEU_MajorAntiRollBackEnabled(VOID)
{
UINT_T value = GEU_ReadSoftwareVersion();
return (value & 1);
}
INT_T GEU_ReadMajorVersion(VOID)
{
INT_T i, ones = 0;
UINT_T value = GEU_ReadSoftwareVersion();
for(i = 0; i < 32; i++)
{
if(value & (1 << i))
ones++;
}
return (ones - 1); /* -1 means no major version burned */
}
UINT_T GEU_ReadRNG(UINT_T *Data, UINT_T Len)
{
UINT_T RngCtrl;
UINT_T UID[2];
UINT_T Val;
GEU_ReadOemUidFuseBits(UID, K_OEM_UNIQUE_ID_FUSE_SIZE);
GEU_REG_READ(GEU_RNG_CTRL, RngCtrl);
if (!(RngCtrl & (1 << 24) )) {
RngCtrl |= (1 << 24);
GEU_REG_WRITE(GEU_RNG_CTRL, RngCtrl);
/* Use UID as seed */
if (UID[0] == 0 && UID[1] == 0)
obm_printf("Warning: UID is 0 and used as seed\n\r");
GEU_REG_WRITE(GEU_RNG_SEED_LO, UID[0]);
GEU_REG_WRITE(GEU_RNG_SEED_HI, UID[1]);
Delay(100); /* 70us is enough, set as 100us */
}
while (Len) {
Delay(5); /* enough delay to get a new rng */
GEU_REG_READ(GEU_HW_RANDOM_NUM_GEN, Val);
if (Len < 4) {
memcpy(Data, &Val, Len);
break;
} else {
*Data++ = Val;
Len -= 4;
}
}
}
INT GEU_RkekAccessDisabled(VOID)
{
UINT_T Val;
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, Val);
if(Val & (1 << 29))
return 1;
return 0;
}
INT GEU_RkekIsBurned(VOID)
{
INT_T i;
UINT_T RKEK[8];
if (GEU_RkekAccessDisabled())
return 1;
GEU_ReadRkekFuseBits(RKEK, K_FUSEBLOCK_SIZE);
for (i = 0; i < 8; i++) {
if(RKEK[i] != 0)
return 1;
}
return 0;
}
UINT_T GEU_ReadFuseBank(UINT_T *pBuffer, UINT_T BankNum)
{
UINT_T Val1, Val2, Val3;
switch(BankNum)
{
case 0:
GEU_REG_READ(GEU_FUSE_VAL_APCFG1, Val1);
GEU_REG_READ(GEU_FUSE_VAL_APCFG2, Val2);
GEU_REG_READ(GEU_FUSE_VAL_APCFG3, Val3);
pBuffer[0] = (Val3 >> 16) | (Val1 << 16);
pBuffer[1] = (Val1 >> 16) | (Val2 << 16);
pBuffer[2] = (Val2 >> 16) | (Val3 << 16);
GEU_REG_READ(GEU_FUSE_BANK0_127_96, pBuffer[3]);
GEU_REG_READ(ASR1803GEU_FUSE_VAL_OEM_UID_L, pBuffer[4]);
GEU_REG_READ(ASR1803GEU_FUSE_VAL_OEM_UID_H, pBuffer[5]);
GEU_REG_READ(GEU_FUSE_BANK0_239_208, Val1);
GEU_REG_READ(GEU_FUSE_BANK0_207_192, Val2);
GEU_REG_READ(GEU_FUSE_BANK0_255_240, Val3);
pBuffer[6] = (Val1 << 16) | (Val2 & 0xFFFF);
pBuffer[7] = (Val3 << 16) | (Val1 >> 16);
break;
case 1:
for(int i = 0; i < 8; i++)
GEU_REG_READ((GEU_FUSE_VAL_ROOT_KEY1 + (i * 4)), pBuffer[i]);
break;
case 2:
for(int i = 0; i < 8; i++)
GEU_REG_READ((GEU_FUSE_VAL_OEM_HASH_KEY + (i * 4)), pBuffer[i]);
break;
case 3:
for(int i = 0; i < 6; i++)
GEU_REG_READ((GEU_FUSE_BANK3_RESERVED + (i * 4)), pBuffer[i]);
GEU_REG_READ(GEU_FUSE_BANK3_223_192, pBuffer[6]);
GEU_REG_READ(GEU_FUSE_BANK3_255_224, pBuffer[7]);
break;
default:
break;
}
return NoError;
}
#ifdef FUSE_TEST
UINT_T GEU_RegisterDump(void)
{
GEU_UARTLOG("GEU_STATUS: 0x%x\n\r", GEU_REG(GEU_STATUS));
GEU_UARTLOG("GEU_CONFIG: 0x%x\n\r", GEU_REG(GEU_CONFIG));
GEU_UARTLOG("GEU_FUSE_STATUS: 0x%x\n\r", GEU_REG(GEU_FUSE_STATUS));
GEU_UARTLOG("GEU_FUSE_PROG_VAL1: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 0));
GEU_UARTLOG("GEU_FUSE_PROG_VAL2: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 4));
GEU_UARTLOG("GEU_FUSE_PROG_VAL3: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 8));
GEU_UARTLOG("GEU_FUSE_PROG_VAL4: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 12));
GEU_UARTLOG("GEU_FUSE_PROG_VAL5: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 16));
GEU_UARTLOG("GEU_FUSE_PROG_VAL6: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 20));
GEU_UARTLOG("GEU_FUSE_PROG_VAL7: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 24));
GEU_UARTLOG("GEU_FUSE_PROG_VAL8: 0x%x\n\r", GEU_REG(GEU_FUSE_PROG_VAL1 + 28));
}
UINT_T GEU_BankDump(UINT_T BankNum)
{
UINT_T pBuffer[8];
GEU_ReadFuseBank(pBuffer, BankNum);
GEU_UARTLOG("Fuse bank values:%d\n\r", BankNum);
for(int i = 7; i >= 0; i--)
{
GEU_UARTLOG("%08x ", pBuffer[i]);
}
GEU_UARTLOG("\n\r");
}
UINT_T GEU_FuseBankBurnTest(UINT_T *pBuffer, UINT_T BankNum)
{
INT_T i, status;
UINT_T pReadBuffer[8];
UINT_T pExpectBuffer[8];
GEU_EnableFuseBurnPower();
GEU_ReadFuseBank(pReadBuffer, BankNum);
GEU_UARTLOG("Initial Value of bank%d\n\r", BankNum);
for(i = 7; i >= 0; i--)
GEU_UARTLOG("%08x ", pReadBuffer[i]);
GEU_UARTLOG("\n\r");
for(i = 0; i < 8; i++)
pExpectBuffer[i] = pBuffer[i] | pReadBuffer[i];
GEU_UARTLOG("Expected Value of bank%d\n\r", BankNum);
for(i = 7; i >= 0; i--)
GEU_UARTLOG("%08x ", pExpectBuffer[i]);
GEU_UARTLOG("\n\r");
for(i = 0; i < 8; i++)
{
GEU_REG(GEU_FUSE_PROG_VAL1 + i*4) = pBuffer[i];
}
_geuBurnFuse(BankNum, 0);
GEU_ReadFuseBank(pReadBuffer, BankNum);
GEU_UARTLOG("First Burn read back Value of bank%d\n\r", BankNum);
for(i = 7; i >= 0; i--)
GEU_UARTLOG("%08x ", pReadBuffer[i]);
GEU_UARTLOG("\n\r");
status = _geu_compare(pReadBuffer, pExpectBuffer, 32);
if(status != NoError)
{
GEU_UARTLOG("First Burning fails for bank%d\n\r", BankNum);
GEU_UARTLOG("Try again\n\r");
_geuBurnFuse(BankNum, 0);
GEU_ReadFuseBank(pReadBuffer, BankNum);
GEU_UARTLOG("First Burn read back Value of bank%d\n\r", BankNum);
for(i = 7; i >= 0; i--)
GEU_UARTLOG("%08x ", pReadBuffer[i]);
GEU_UARTLOG("\n\r");
status = _geu_compare(pReadBuffer, pExpectBuffer, 32);
if(status != NoError){
GEU_UARTLOG("Second Burning fails for bank%d\n\r", BankNum);
return FUSE_BurnError;
} else {
GEU_UARTLOG("Second Burning pass for bank%d\n\r", BankNum);
}
} else {
GEU_UARTLOG("First Burning pass for bank%d\n\r", BankNum);
return NoError;
}
}
#endif