| /****************************************************************************** | |
| * | |
| * (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; | |
| } |