259 lines
6.9 KiB
C
259 lines
6.9 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* common/aml_tlv.c
|
|
*
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
#if 0 //bl2
|
|
#include <platform_def.h>
|
|
#include <aml_tlv.h>
|
|
#include <string.h>
|
|
#include <sha2.h>
|
|
#include <secure_apb.h> //AML_BL2_TMASTER_CFG_REG: AO_SEC_GP_CFG6
|
|
#include <acs.h>
|
|
|
|
#ifdef CONFIG_AML_TLV_BL2_VER_INFO
|
|
#include <soc_version.h>
|
|
extern const char build_message[];
|
|
#endif
|
|
|
|
#else
|
|
#include <config.h>
|
|
#include <amlogic/aml_tlv.h>
|
|
#include <asm/arch/secure_apb.h>
|
|
#include <linux/string.h>
|
|
#include <u-boot/sha256.h>
|
|
|
|
#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
|