/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* * common/aml_tlv.c * * Copyright (C) 2020 Amlogic, Inc. All rights reserved. * */ #if 0 //bl2 #include #include #include #include #include //AML_BL2_TMASTER_CFG_REG: AO_SEC_GP_CFG6 #include #ifdef CONFIG_AML_TLV_BL2_VER_INFO #include extern const char build_message[]; #endif #else #include #include #include #include #include #ifndef AML_BL2_TMASTER_DDR_ADDR #error ERROR! Please define DDR address for TLV! #endif #endif #ifdef CONFIG_AML_SUPPORT_TLV //internal use only, to fetch the transfer object from AML_BL2_TMASTER_CFG_REG //only BL2 can set the AML_BL2_TMASTER_CFG_REG //all others BL3X just use the obj from AML_BL2_TMASTER_CFG_REG static s_bl2_to_bl3x_send_t * aml_get_t_master(void) { #ifdef BL2_ACS_OFFSET if (p_acs) *(unsigned int *)AML_BL2_TMASTER_CFG_REG = p_acs->p_plls->nCFGTAddr; else *(unsigned int *)AML_BL2_TMASTER_CFG_REG = 0; #endif return (s_bl2_to_bl3x_send_t*)(unsigned long)(*(unsigned int *)AML_BL2_TMASTER_CFG_REG); } //IMPORTANT: BECAUSE THIS FUNCTION WILL USE DDR AS STORAGE(DEFAULT) THEN // ALL THE APIS MSUT BE USED AFTER DDR INIT DONE //feature : append item to the list //para list: // nType[IN] : unique ID for item // nLength[IN] : byte data length for data pData // pData[IN] : data buffer to be processed // //return : e_err_not_support : BL33 not support valid address for TLV // e_ok_ret : append OK to the list // e_err_in_data : invalid input pData // e_err_in_size : invalid data length // e_err_over_size : total size exceed the max // e_err_item_exit : item already exist with nType e_ret_type aml_append_item(unsigned int nType, unsigned int nLength, unsigned char *pData) { e_ret_type eReturn = e_err_not_support; #ifdef CONFIG_AML_TLV_BL2_VER_INFO int nIndex; #endif s_bl2_to_bl3x_send_t *pSndMaster = aml_get_t_master(); if ( !pSndMaster ) goto exit; if ( AML_BL2_TMASTER_MAGIC != pSndMaster->hdr.nMagic) { //first run which need initialize memset(pSndMaster,0,sizeof(*pSndMaster)); pSndMaster->hdr.nMagic = AML_BL2_TMASTER_MAGIC; //magic @BL2 pSndMaster->hdr.nVersion = AML_BL2_TMASTER_VERSION; //version: major | minor pSndMaster->hdr.nHeadSize = sizeof(s_bl2_to_bl3x_hdr_t); //size of hdr pSndMaster->hdr.pNextBlob = pSndMaster->blob; //active item pSndMaster->hdr.pNextBlob->pNextItem = 0; //next item is NULL //copy BL2 info one by one and limit to sizeof(szBL2Info) #ifdef CONFIG_AML_TLV_BL2_VER_INFO for ( nIndex = 0;build_message[nIndex] && nIndex < sizeof(pSndMaster->hdr.szBL2Info); ++nIndex) pSndMaster->hdr.szBL2Info[nIndex] = build_message[nIndex]; #endif } eReturn = e_err_in_data; //check input data if (!pData ) goto exit; //check input length eReturn = e_err_in_size; if (!nLength) goto exit; unsigned int nStoreLength = AML_BL2_TMASTER_ITEM_ALIGN_LEN(nLength); eReturn = e_err_over_size; //check whether the transfer buffer is overflow or not with this new input if (AML_BL2_TMASTER_DDR_MLEN <= (pSndMaster->hdr.nTotalSize + nStoreLength)) goto exit; eReturn = e_err_item_exit; s_bl2_tlv_item_t *pItem = 0; if ( e_ok_ret == aml_fetch_item(nType, &pItem)) goto exit; //total counter +1 pSndMaster->hdr.nTLVCount +=1; //set item data & info pSndMaster->hdr.pNextBlob->nType = nType; pSndMaster->hdr.pNextBlob->nLength = nLength; pSndMaster->hdr.pNextBlob->nStoreLength = nStoreLength; memcpy(pSndMaster->hdr.pNextBlob->szContent,pData,nLength); //clean the padding buffer if ( nStoreLength > nLength ) memset(pSndMaster->hdr.pNextBlob->szContent + nLength,0,(nStoreLength - nLength)); //update total size pSndMaster->hdr.nTotalSize += (sizeof(s_bl2_tlv_item_t) - 4 + nStoreLength); //shift the next active item pSndMaster->hdr.pNextBlob->pNextItem = (s_bl2_tlv_item_t*)(pSndMaster->hdr.pNextBlob->szContent + nStoreLength); //update next active item pSndMaster->hdr.pNextBlob = pSndMaster->hdr.pNextBlob->pNextItem; //init active item memset(pSndMaster->hdr.pNextBlob,0,sizeof(s_bl2_tlv_item_t)); #ifdef BL2_ACS_OFFSET //update sha2 of TLVs sha2((void*)pSndMaster->blob,pSndMaster->hdr.nTotalSize,pSndMaster->hdr.szSHA2TLV,0); //update sha2 of head which include sha2 of TLVs sha2((void*)pSndMaster,pSndMaster->hdr.nHeadSize ,pSndMaster->szSHA2Head,0); #else sha256_csum_wd((void*)pSndMaster->blob,pSndMaster->hdr.nTotalSize, pSndMaster->hdr.szSHA2TLV,pSndMaster->hdr.nHeadSize); sha256_csum_wd((void*)pSndMaster,pSndMaster->hdr.nHeadSize , pSndMaster->szSHA2Head,pSndMaster->hdr.nHeadSize); #endif //success eReturn = e_ok_ret; exit: return eReturn; } //IMPORTANT: BECAUSE THIS FUNCTION WILL USE DDR AS STORAGE(DEFAULT) THEN // ALL THE APIS MSUT BE USED AFTER DDR INIT DONE //feature : fetch the item from list with nType //para list: // nType[IN] : unique ID for item // ppItem[OUT] : item found which has the matched type nType // //return : e_err_not_support : BL33 not support valid address for TLV // e_ok_ret : found the item and return with ppItem // e_err_sha_hdr : head sha2 check fail // e_err_sha_tlv : TLV sha2 check fail // e_err_no_item : no item match the type nType e_ret_type aml_fetch_item(unsigned int nType, s_bl2_tlv_item_t **ppItem) { e_ret_type eReturn = e_err_not_support; s_bl2_to_bl3x_send_t *pSndMaster = aml_get_t_master(); s_bl2_tlv_item_t *pItem = 0; unsigned char szSHA2[32]; if ( ppItem ) *ppItem = 0; if ( !pSndMaster ) goto exit; eReturn = e_err_no_item; //check TLV's counter if (!pSndMaster->hdr.nTLVCount) goto exit; eReturn = e_err_sha_hdr; //check sha2 of header #ifdef BL2_ACS_OFFSET sha2((void*)pSndMaster,pSndMaster->hdr.nHeadSize ,szSHA2,0); #else sha256_csum_wd((void*)pSndMaster,pSndMaster->hdr.nHeadSize, szSHA2,pSndMaster->hdr.nHeadSize); #endif if (memcmp(szSHA2,pSndMaster->szSHA2Head,sizeof(szSHA2))) goto exit; eReturn = e_err_sha_tlv; //check sha2 of TLVs #ifdef BL2_ACS_OFFSET sha2((void*)pSndMaster->blob,pSndMaster->hdr.nTotalSize,szSHA2,0); #else sha256_csum_wd((void*)pSndMaster->blob,pSndMaster->hdr.nTotalSize, szSHA2,pSndMaster->hdr.nTotalSize); #endif if (memcmp(szSHA2,pSndMaster->hdr.szSHA2TLV,sizeof(szSHA2))) goto exit; //first item pItem = pSndMaster->blob; //check the list while (pItem->nLength) { if ( nType == pItem->nType) break; pItem = pItem->pNextItem; } //check valid item or not with length if (pItem->nLength) eReturn = e_ok_ret; else { pItem = 0; eReturn = e_err_no_item; } *ppItem = pItem; exit: return eReturn; } #endif //#ifdef CONFIG_AML_SUPPORT_TLV