blob: 8fc6ddb493084c3d105df82a4607993527a3dff9 [file] [log] [blame]
/* 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