blob: 057793a9f0e540a334e7c142d4bbe2968b64f62a [file] [log] [blame]
/******************************************************************************
*
* (C)Copyright 2022 ASR. All Rights Reserved.
*
******************************************************************************/
#include "PlatformConfig.h"
#include "PlatformCommon.h"
#include "platform_interrupts.h"
#include "predefines.h"
#include "USB_controller.h"
#include "USB_PHY.h"
#include "PMUA.h"
#include "Flash.h"
#include "timer.h"
#include "uart_regs.h"
#include "geu_interface.h"
#include "APBC.h"
#include "obm2osl.h"
#include "misc.h"
#include "sdhc2.h"
#include "Provisioning.h"
#include "Typedef.h"
#include "serial.h"
#include "downloader.h"
#include "BootLoader.h"
#include "sdram_config.h"
#include "asr_flag.h"
#include "general.h"
UINT_T UUID[2];
OBM2OSL *pOBM2OSL_h = NULL;
#if defined(CONFIG_TEE_OS)
pTEEC_INFO pAsrTeec = NULL;
#endif
extern BOOTING_MODE product_mode_select;
void OBM2OSL_Init(pFUSE_SET pFuses, pTIM pTIM_h)
{
DDR_MODE DDR_type = LPDDR2_400MHZ_MODE;
pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
pOPT_DDR_Type pDDR = NULL;
UINT_T Retval = NoError;
pAsrDualTimInfo pDualTimInfo = GetDualTimInfo();
if(pOBM2OSL_h == NULL)
FatalError(NULLPointer, "OOI", NULL);
memset(pOBM2OSL_h, 0, sizeof(OBM2OSL));
pOBM2OSL_h->signature = OBM2OSL_IDENTIFIER;
pOBM2OSL_h->version = OBM2OSL_VERSION_V7;
pOBM2OSL_h->booting_mode = product_mode_select;
pOBM2OSL_h->obm_path = pDualTimInfo->CurrentTim;
pOBM2OSL_h->tee_dram_size = 0;
pOBM2OSL_h->ddrt_info.value = 0;
pWRAH = FindPackageInReserved(&Retval, pTIM_h, DDR_TYPE_ID);
if ((pWRAH == NULL) || (Retval != NoError))
{
pOBM2OSL_h->ddr_mode = DDR_type; // not find, use default
}
else
{
pDDR = (pOPT_DDR_Type) pWRAH;
pOBM2OSL_h->ddr_mode = pDDR->Type;
}
obm_printf("DDR Mode: 0x%x\n\r", pOBM2OSL_h->ddr_mode);
#if defined(CONFIG_TEE_OS)
memset(pAsrTeec, 0, sizeof(TEEC_INFO));
pWRAH = FindPackageInReserved(&Retval, pTIM_h, TEEC);
if ((pWRAH != NULL) && (Retval == NoError))
{
memcpy(pAsrTeec, pWRAH, pWRAH->Size);
pOBM2OSL_h->tee_dram_size = pAsrTeec->SecDramSize + pAsrTeec->NsecSharedMemSize;
}
#endif
}
void PlatformSetForceUSBEnumFlag(void)
{
*(VUINT_T *)FORCE_USB_ENUM_ADDR = FORCEUSBID;
}
UINT_T PlatformCheckForceUSBEnumFlag(void)
{
if (*(VUINT_T *)FORCE_USB_ENUM_ADDR == FORCEUSBID)
return 1;
else
return 0;
}
void PlatformClearForceUSBEnumFlag(void)
{
*(VUINT_T *)FORCE_USB_ENUM_ADDR = 0x0;
}
extern UINT_T __end_of_obm__;
void OBM_HeapInit(void)
{
UINT_T heap_start = 0;
UINT_T ddr_size = 0x4000000;
UINT_T obm_end = &__end_of_obm__;
UINT_T obm_start, obm_len;
UINT_T Buffer;
INT_T ret;
ddr_size = GetDDRConfiguredSize() * 1024 * 1024; // convert to bytes
heap_start = 0x8000; /* Non-zero address */
malloc_init(heap_start, ddr_size - heap_start);
#if UPDATER
/* need to reserve head 1M for OBM */
obm_start = OBM_DDR_BASE_ADDR - 0x100000;
#else
obm_start = OBM_DDR_BASE_ADDR;
#endif
obm_len = obm_end - obm_start;
obm_printf("%s heap: 0x%x-->0x%x, 0x%x-->0x%x\n\r", (UPDATER == 1)?"OUM":"OBM",
heap_start, obm_start,
obm_end, ddr_size);
/* reserve OBM code/data area */
ret = mreserve(obm_start, obm_len);
if (ret) {
obm_printf("Fail to reserve OBM code/data area\n\r");
return HeapExhaustedError;
}
obm_printf("Reserve memory 0x%x@0x%x\n\r", obm_len, obm_start);
/* malloc some buffers than won't be free during obm */
pOBM2OSL_h = malloc(sizeof(OBM2OSL));
if(pOBM2OSL_h == NULL)
return HeapExhaustedError;
#if defined(CONFIG_TEE_OS)
pAsrTeec = malloc(sizeof(TEEC_INFO));
if (pAsrTeec == NULL)
return HeapExhaustedError;
#endif
/* Rerserve memory for TIMs */
Buffer = malloc(0x2000 * 6);
if(Buffer == NULL)
return HeapExhaustedError;
TIM_ReservedMemInit(Buffer);
#if EMMD_SUPPORT && !UPDATER
if(RAMDUMP_MEM_START < obm_end) {
obm_printf("RAMDUMP overlap with OBM area\n\r");
FatalError(MemOverlapError, "OHI", NULL);
}
ret = mreserve(RAMDUMP_MEM_START, ddr_size - RAMDUMP_MEM_START);
if (ret) {
obm_printf("Fail to reserve RAMDUMP memory\n\r");
return HeapExhaustedError;
}
#endif
}
#if ENABLE_MMU
void EnableDataCache(void)
{
//dcache_invalidate_all();
l1_dcache_enable();
}
void DisableDataCache(void)
{
dcache_disable();
}
#endif
#if TRUSTED
void DisplayFuses(void)
{
UINT_T life_cycle, cycle = 0;
UINT_T OEM_Key_Hash[8];
UINT_T AP_Config[3], CP_Config = 0;
UINT_T i;
UINT_T security_cfg = 0;
memset(AP_Config, 0, sizeof(AP_Config));
memset(OEM_Key_Hash, 0, sizeof(OEM_Key_Hash));
memset(UUID, 0, sizeof(UUID));
GEU_EnableFuseBurnPower();
GEU_ReadApConfigFuseBits(AP_Config, 10);
GEU_ReadCpConfigFuseBits(&CP_Config, 2);
GEU_ReadOemHashKeyFuseBits(OEM_Key_Hash, 32);
life_cycle = GEU_ReadLifeCycle();
//Security Config is in AP config
//GEU_ReadSecurityConfigFuseBits(&security_cfg, 4);
GEU_ReadOemUidFuseBits(UUID, 8);
obm_printf("DisplayFuses\n\r");
obm_printf("Fuse Related Info Start--------------------------\n\r");
obm_printf("Fuse LifeCycle: %d\n\r", life_cycle);
obm_printf("Application Subsystem Configuration\n\r");
for (i = 0; i < 3; i++)
{
obm_printf("0x%08x\n\r", AP_Config[i]);
}
obm_printf("Communication Subsystem Configuration\n\r0x%08x\n\r", CP_Config);
obm_printf("OEM Key Hash\n\r");
for (i = 0; i < 8; i++)
{
obm_printf("0x%08x ", OEM_Key_Hash[i]);
if (i == 3)
obm_printf("\n\r");
}
obm_printf("\n\r");
obm_printf("UUID\n\r");
for (i = 0; i < 2; i++)
{
obm_printf("0x%08x ", UUID[i]);
}
obm_printf("\n\r");
DisplaySecurityInfo();
obm_printf("Fuse Related Info End----------------------------\n\r");
}
//////////////////////////////////////////////////////////////////////
// This is the Platform Provisioning function for the Boot Loader.
//
// Inputs: Inputs: A pointer to the fuses and a pointer to the TIM.
// Outputs: Returns the error code if there is an error.
//
// It mainly provisions the platform if it is not initialized.
//
//////////////////////////////////////////////////////////////////////
UINT_T ProvisionPlatform( pFUSE_SET pFuses, pTIM pTIM_h )
{
UINT_T Retval = NoError;
pImage_FUSE_BURN pFuseBurn;
pWTP_RESERVED_AREA_HEADER pWRAH = NULL;
UINT_T FuseBurnCfg = 0;
UINT_T TrustedBootBurn = 0;
//pOPT_SOCPROFILEID pSocProfileID = NULL;
pPROVISIONING_FUNCTIONS pPFs = GetFuseBurningFunctionsPointer();
#if (ENABLE_BITS_BURN && ENABLE_SVC_TABLE)
#define SVC_BURN_BANK (0)
#define SVC_BIT_POS (131)
UINT_T ReadBuf[8];
UINT_T SvcState;
memset(ReadBuf, 0, sizeof(ReadBuf));
P_FOTA_Firmware pAsrFlag_t = OTAGetConfig(pTIM_h);
if (pAsrFlag_t == NULL)
return NoError;
FOTA_Firmware AsrFlag_tmp_t;
memcpy(&AsrFlag_tmp_t, pAsrFlag_t, sizeof(FOTA_Firmware));
/* fuse bit 131~132 */
if (pAsrFlag_t->svc_state == SVC_BURN_01) {
/* fuse burn: 01 */
#if FLCN
{
Retval = GEU_FuseBankBitBurn(SVC_BURN_BANK, SVC_BIT_POS, 1);
if ( Retval != NoError )
{
pAsrFlag_t->svc_state = SVC_01_BURN_FAILED;
OTA_Save_Config(pTIM_h);
return Retval;
}
}
#endif
} else if (pAsrFlag_t->svc_state == SVC_BURN_11) {
/* fuse burn: 11 */
#if FLCN
{
Retval = GEU_FuseBankBitBurn(SVC_BURN_BANK, SVC_BIT_POS, 2);
if ( Retval != NoError )
{
pAsrFlag_t->svc_state = SVC_11_BURN_FAILED;
OTA_Save_Config(pTIM_h);
return Retval;
}
}
#endif
}
Retval = GEU_ReadFuseBank(ReadBuf, 0);
if ( Retval != NoError )
return Retval;
SvcState = ReadBuf[4] >> (131 - 128) & 0x3;
switch (SvcState)
{
case 0x3:
pAsrFlag_t->svc_state = SVC_11_BURNED;
break;
case 0x1:
pAsrFlag_t->svc_state = SVC_01_BURNED;
break;
case 0x0:
pAsrFlag_t->svc_state = SVC_NOT_BURN;
break;
default:
pAsrFlag_t->svc_state = SVC_ERROR_STATE;
break;
}
/* Only save asr flag when the svc state changes */
if (memcmp(pAsrFlag_t, &AsrFlag_tmp_t, sizeof(FOTA_Firmware))) {
OTA_Save_Config(pTIM_h);
}
#endif
// Check to see if there is an SOCPROFILEID packet in TIM
//pSocProfileID = (pOPT_SOCPROFILEID) FindPackageInReserved (&Retval, pTIM_h, SOCPROFILEID);
//if( (pSocProfileID != NULL) && (pPFs->pReadProfileFuse != NULL) )
//{
// pPFs->pReadProfileFuse(pTIM_h, pSocProfileID->StoreAddress);
//}
// Provision platform, if it is not initialized
pWRAH = FindPackageInReserved(&Retval, pTIM_h, FUSE);
if ( !( (pWRAH == NULL) || (Retval != NoError) ) )
{
pFuseBurn = (pImage_FUSE_BURN) pWRAH;
FuseBurnCfg = pFuseBurn->Enabled;
}
if (FuseBurnCfg == 0) {
/* Directly return as fuse burning is not enabled in BLF */
return NoError;
}
TrustedBootBurn = FuseBurnCfg & TRUSTBOOT_BURN_EN;
#if PRODUCT_BUILD
if ((pFuses->bits.TBROpMode == 0x1) && (pTIM_h->pConsTIM->VersionBind.Trusted) && TrustedBootBurn)
{
#if TRUSTED
if ( pPFs->pBindPlatform != NULL ) // If this function is supported
{
// 1) Program OEM key hash if it's not already programmed
Retval = pPFs->pBindPlatform(pTIM_h, (void*)NULL);
if ( Retval != NoError )
return Retval;
}
if ( pPFs->pVerifyPlatform != NULL ) // If this function is supported
{
// 2) Verify OEM key hash
Retval = pPFs->pVerifyPlatform(pTIM_h);
if ( Retval != NoError )
return Retval;
}
if ( pPFs->pBindJTAGKey != NULL ) // If this function is supported
{
// 3) Program JTAG key hash if it's not already programmed
Retval = pPFs->pBindJTAGKey(pTIM_h, (void*)NULL);
if ( Retval != NoError )
{
return Retval;
}
}
if (pPFs->pVerifyJTAGKey != NULL) // If this function is supported
{
// 4) Verify JTAG key hash
Retval = pPFs->pVerifyJTAGKey(pTIM_h);
if ( Retval != NoError )
{
return Retval;
}
}
if ( pPFs->pAutoConfigPlatform != NULL ) // If this function is supported
{
// 5) Program Block 0 SoC Config(Trusted Boot related)
Retval = pPFs->pAutoConfigPlatform(pTIM_h, (void*)NULL);
if ( Retval != NoError )
return Retval;
}
#endif
}
#if ENABLE_RKEK
Retval = GEU_LIB_ProgramRKEK(pTIM_h);
if (Retval != NoError)
return Retval;
#endif
/* Common configuration in fuse for both trusted and non-trusted products */
Retval = GEU_ProgramMiscConfig(pTIM_h);
#endif
return Retval;
}
UINT_T ReadOemHashKeyFuseBits(UINT_T* pBuffer, UINT_T Size )
{
UINT status = NoError, i;
GEU_EnableFuseBurnPower();
status = GEU_ReadOemHashKeyFuseBits(pBuffer, Size);
return status;
}
#if BL_USE_SECURITY_CALLBACK
void SetSecurityCallBackFunctionPointers(void)
{
pSECURITY_FUNCTIONS pSFs = GetSecurityFunctionsPointer();
pSFs->pInitializeSecurity = (UINT_T (*) (UINT_T ver_adv
)
) SCB_InitializeSecurity_Addr;
pSFs->pSHAMessageDigest = (UINT_T (*) ( const UINT8_T* pSrcMesgIn,
UINT_T SrcMesgByteLen,
UINT8_T* pMesgDigestOut,
UINT_T DigestByteLen
)
) SCB_SHAMessageDigest_Addr;
pSFs->pPKCS_DSA_Verify = (UINT_T (*) ( const UINT8_T* pSrcMesgIn,
UINT_T SrcMesgByteLen,
const pPLAT_DS pDSA,
UINT8_T* DataBuffer
)
) SCB_PKCS_DSA_Verify_Addr;
pSFs->pECCP_DSA_Verify = (UINT_T (*) ( const UINT8_T* pSrcMesgIn,
UINT_T SrcMesgByteLen,
const pPLAT_DS pDSA,
UINT8_T* DataBuffer
)
) SCB_ECCP_DSA_Verify_Addr;
pSFs->pGet_NonceBitLen = NULL;
pSFs->pGet_Nonce = NULL;
pSFs->pAES_Decrypt = NULL;
pSFs->pAES_Encrypt = NULL;
pSFs->pHMAC = NULL;
}
#endif //#if BL_USE_SECURITY_CALLBACK
#endif
UINT_T PlatformGetChipID(void)
{
UINT_T ChipID_value;
ChipID_value = (* (VUINT_T *)CHIP_ID) & 0xFFFF;
return ChipID_value;
}
UINT_T PlatformGetRevisionID(void)
{
UINT_T ChipID_value, RevisionID;
ChipID_value = (* (VUINT_T *)CHIP_ID);
RevisionID = (ChipID_value >> 16) & 0xff;
switch (RevisionID)
{
case 0xF0:
case 0xF2:
case 0xF3:
case 0xC0:
case 0xC1:
break;
case 0xA0: // next revision ID is A0?
case 0xA1:
break;
case 0xB0:
break;
default:
obm_printf("unknown revision ID: 0x%x\n\r", RevisionID);
break;
}
return RevisionID;
}
INT_T PlatformCoreIsCA7(void)
{
UINT_T CPU_Mode;
CPU_Mode = getCPUMode() & 0x0000fff0;
return (CPU_Mode == CA7ID);
}
INT_T PlatformCoreIsCR5(void)
{
UINT_T CPU_Mode;
CPU_Mode = getCPUMode() & 0x0000fff0;
return (CPU_Mode == CR5ID);
}
INT_T PlatformIsFPGA(void)
{
UINT CHipID = BU_REG_READ(CHIP_ID);
return (((CHipID >> 24) & 0x7) == 0x1);
}
INT_T PlatformIsEmulator(void)
{
UINT CHipID = BU_REG_READ(CHIP_ID);
return (((CHipID >> 24) & 0x7) == 0x2);
}
UINT_T PlatfromFBFBoundaryScan(pIMAGE_INFO_3_4_0 pImageInfo)
{
return NoError;
}
void PlatformSetFOTAFlag(void)
{
//*(VUINT_T *)FOTA_FLAG_ADDR = 0x50415353; // "PASS"
}
// Get the VID and PID from fuses
UINT_T GetUSBIDFuseBits(unsigned short* VID, unsigned short* PID )
{
/* TODO */
return NotSupportedError;
}