322 lines
9.8 KiB
C
322 lines
9.8 KiB
C
/******************************************************************************
|
|
*
|
|
* Freescale Semiconductor Inc.
|
|
* (c) Copyright 2004-2006 Freescale Semiconductor, Inc.
|
|
* (c) Copyright 2001-2004 Motorola, Inc.
|
|
* ALL RIGHTS RESERVED.
|
|
*
|
|
****************************************************************************//*!
|
|
*
|
|
* @file PE_freemaster_tsa.c
|
|
*
|
|
* @brief FreeMASTER TSA implementation
|
|
*
|
|
* @version 1.0.9.0
|
|
*
|
|
* @date Oct-22-2007
|
|
*
|
|
*******************************************************************************
|
|
*
|
|
* This file implements a new FreeMASTER feature called Targer-side address
|
|
* translation.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "PE_freemaster.h"
|
|
#include "PE_freemaster_private.h"
|
|
#include "PE_freemaster_protocol.h"
|
|
|
|
#if FMSTR_USE_TSA
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief TSA Initialization
|
|
*
|
|
******************************************************************************/
|
|
|
|
void FMSTR_InitTsa(void)
|
|
{
|
|
}
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief Handling GETTSAINFO and GETTSAINFO_EX command
|
|
*
|
|
* @param pMessageIO - original command (in) and response buffer (out)
|
|
*
|
|
* @return As all command handlers, the return value should be the buffer
|
|
* pointer where the response output finished (except checksum)
|
|
*
|
|
******************************************************************************/
|
|
|
|
FMSTR_BPTR FMSTR_GetTsaInfo(FMSTR_BPTR pMessageIO)
|
|
{
|
|
FMSTR_BPTR pResponse = pMessageIO;
|
|
const FMSTR_TSA_ENTRY* pTbl;
|
|
FMSTR_TSA_TINDEX nTblIndex;
|
|
FMSTR_TSA_TSIZE nTblSize = 0U;
|
|
FMSTR_ADDR tmpAddr;
|
|
FMSTR_U16 tmp16;
|
|
|
|
/* get index of table the PC is requesting */
|
|
pMessageIO = FMSTR_SkipInBuffer(pMessageIO, 2U);
|
|
pMessageIO = FMSTR_ValueFromBuffer16(&nTblIndex, pMessageIO);
|
|
|
|
/* TSA flags */
|
|
tmp16 = FMSTR_TSA_VERSION | FMSTR_TSA_FLAGS;
|
|
|
|
/* sizeof TSA table entry items */
|
|
/*lint -e{506,774} constant value boolean */
|
|
if((sizeof(FMSTR_TSA_ENTRY)/4U) == 4U)
|
|
{
|
|
tmp16 |= FMSTR_TSA_INFO_32BIT; /* 32bit TSA entries */
|
|
}
|
|
|
|
/* get the table (or NULL if no table on given index) */
|
|
pTbl = FMSTR_TsaGetTable(nTblIndex, &nTblSize);
|
|
|
|
/* success, flags */
|
|
pResponse = FMSTR_ConstToBuffer8(pResponse, FMSTR_STS_OK);
|
|
pResponse = FMSTR_ValueToBuffer16(pResponse, tmp16);
|
|
|
|
/* table size in bytes */
|
|
nTblSize *= FMSTR_CFG_BUS_WIDTH;
|
|
pResponse = FMSTR_ValueToBuffer16(pResponse, nTblSize);
|
|
|
|
/* table address */
|
|
FMSTR_PTR2ADDR(tmpAddr, pTbl);
|
|
return FMSTR_AddressToBuffer(pResponse, tmpAddr);
|
|
}
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief Private inline implementation of "strlen"
|
|
*
|
|
******************************************************************************/
|
|
|
|
FMSTR_U16 FMSTR_StrLen(FMSTR_ADDR nAddr)
|
|
{
|
|
const FMSTR_U8* pStr;
|
|
FMSTR_U16 nLen = 0U;
|
|
|
|
#ifdef __HCS12X__
|
|
/* convert from logical to global if needed */
|
|
nAddr = FMSTR_FixHcs12xAddr(nAddr);
|
|
#endif
|
|
|
|
/*lint -e{923} casting address value to pointer */
|
|
pStr = (const FMSTR_U8*) nAddr;
|
|
|
|
while(*pStr++)
|
|
{
|
|
nLen++;
|
|
}
|
|
|
|
return nLen;
|
|
}
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief Handling GETSTRLEN and GETSTRLEN_EX commands
|
|
*
|
|
* @param pMessageIO - original command (in) and response buffer (out)
|
|
*
|
|
* @return As all command handlers, the return value should be the buffer
|
|
* pointer where the response output finished (except checksum)
|
|
*
|
|
******************************************************************************/
|
|
|
|
FMSTR_BPTR FMSTR_GetStringLen(FMSTR_BPTR pMessageIO)
|
|
{
|
|
FMSTR_BPTR pResponse = pMessageIO;
|
|
FMSTR_ADDR nAddr;
|
|
FMSTR_U16 nLen = 0U;
|
|
|
|
pMessageIO = FMSTR_SkipInBuffer(pMessageIO, 1U);
|
|
pMessageIO = FMSTR_AddressFromBuffer(&nAddr, pMessageIO);
|
|
|
|
nLen = FMSTR_StrLen(nAddr);
|
|
|
|
/* return strign size in bytes (even on 16bit DSP) */
|
|
nLen *= FMSTR_CFG_BUS_WIDTH ;
|
|
|
|
pResponse = FMSTR_ConstToBuffer8(pResponse, FMSTR_STS_OK);
|
|
return FMSTR_ValueToBuffer16(pResponse, nLen);
|
|
}
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief Helper (inline) function for TSA memory region check
|
|
*
|
|
* @param nAddrUser - address of region to be checked
|
|
* @param nSizeUser - size of region to be checked
|
|
* @param nAddrSafe - address of known "safe" region
|
|
* @param wSizeSafe - size of safe region
|
|
*
|
|
* @return This function returns non-zero if given user space is safe
|
|
* (i.e. it lies in given safe space)
|
|
*
|
|
******************************************************************************/
|
|
|
|
#if defined(FMSTR_PLATFORM_56F8xxx) || defined(FMSTR_PLATFORM_56F8xx)
|
|
/* make inline */
|
|
inline FMSTR_BOOL FMSTR_CheckMemSpace(FMSTR_ADDR nAddrUser, FMSTR_SIZE8 nSizeUser,
|
|
FMSTR_ADDR nAddrSafe, FMSTR_SIZE wSizeSafe);
|
|
|
|
inline
|
|
#else
|
|
/* declare function prototype */
|
|
static FMSTR_BOOL FMSTR_CheckMemSpace(FMSTR_ADDR nAddrUser, FMSTR_SIZE8 nSizeUser,
|
|
FMSTR_ADDR nAddrSafe, FMSTR_SIZE wSizeSafe);
|
|
|
|
static
|
|
#endif
|
|
|
|
FMSTR_BOOL FMSTR_CheckMemSpace(FMSTR_ADDR nAddrUser, FMSTR_SIZE8 nSizeUser,
|
|
FMSTR_ADDR nAddrSafe, FMSTR_SIZE wSizeSafe)
|
|
{
|
|
FMSTR_BOOL bRet = FMSTR_FALSE;
|
|
|
|
#ifdef __HCS12X__
|
|
/* convert from logical to global if needed */
|
|
nAddrUser = FMSTR_FixHcs12xAddr(nAddrUser);
|
|
nAddrSafe = FMSTR_FixHcs12xAddr(nAddrSafe);
|
|
#endif
|
|
|
|
if(nAddrUser >= nAddrSafe)
|
|
{
|
|
bRet = (FMSTR_BOOL)
|
|
(((nAddrUser + nSizeUser) <= (nAddrSafe + wSizeSafe)) ? FMSTR_TRUE : FMSTR_FALSE);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/**************************************************************************//*!
|
|
*
|
|
* @brief Check wether given memory region is "safe" (covered by TSA)
|
|
*
|
|
* @param dwAddr - address of the memory to be checked
|
|
* @param nSize - size of the memory to be checked
|
|
* @param bWriteAccess - write access is required
|
|
*
|
|
* @return This function returns non-zero if user space is safe
|
|
*
|
|
******************************************************************************/
|
|
|
|
FMSTR_BOOL FMSTR_CheckTsaSpace(FMSTR_ADDR dwAddr, FMSTR_SIZE8 nSize, FMSTR_BOOL bWriteAccess)
|
|
{
|
|
const FMSTR_TSA_ENTRY* pte;
|
|
FMSTR_TSA_TINDEX nTableIndex;
|
|
FMSTR_TSA_TSIZE i, cnt;
|
|
FMSTR_SIZE nInfo;
|
|
|
|
#if FMSTR_CFG_BUS_WIDTH >= 2U
|
|
/* TSA tables use sizeof() operator which returns size in "bus-widths" (e.g. 56F8xx) */
|
|
nSize = (nSize + 1) / FMSTR_CFG_BUS_WIDTH;
|
|
#endif
|
|
|
|
/* to be as fast as possible during normal opearaion,
|
|
check variable entries in all tables first */
|
|
for(nTableIndex=0U; (pte=FMSTR_TsaGetTable(nTableIndex, &cnt)) != NULL; nTableIndex++)
|
|
{
|
|
/* number of items in a table */
|
|
cnt /= (FMSTR_TSA_TSIZE) sizeof(FMSTR_TSA_ENTRY);
|
|
|
|
/* all table entries */
|
|
for(i=0U; i<cnt; i++)
|
|
{
|
|
nInfo = (FMSTR_SIZE) pte->info.n;
|
|
|
|
/* variable entry only (also check read-write flag) */
|
|
if((nInfo & FMSTR_TSA_INFO_VAR_FLAG) && (!bWriteAccess || (nInfo & FMSTR_TSA_INFO_RWV_FLAG)))
|
|
{
|
|
/* need to take the larger of the two in union (will be optimized by compiler anyway) */
|
|
/*lint -e{506,774} condition always true/false */
|
|
if(sizeof(pte->addr.p) < sizeof(pte->addr.n))
|
|
{
|
|
if(FMSTR_CheckMemSpace(dwAddr, nSize, (FMSTR_ADDR) pte->addr.n, (FMSTR_SIZE) (nInfo >> 2)))
|
|
{
|
|
return FMSTR_TRUE; /* access granted! */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*lint -e{923} casting pointer to long (on some architectures) */
|
|
if(FMSTR_CheckMemSpace(dwAddr, nSize, (FMSTR_ADDR) pte->addr.p, (FMSTR_SIZE) (nInfo >> 2)))
|
|
{
|
|
return FMSTR_TRUE; /* access granted! */
|
|
}
|
|
}
|
|
}
|
|
|
|
pte++;
|
|
}
|
|
}
|
|
|
|
/* no more writeable memory chunks available */
|
|
if(bWriteAccess)
|
|
{
|
|
return FMSTR_FALSE;
|
|
}
|
|
|
|
/* allow reading of recorder buffer */
|
|
#if FMSTR_USE_RECORDER
|
|
if(FMSTR_IsInRecBuffer(dwAddr, nSize))
|
|
{
|
|
return FMSTR_TRUE;
|
|
}
|
|
#endif
|
|
|
|
/* allow reading of any C-constant string referenced in TSA tables */
|
|
for(nTableIndex=0U; (pte=FMSTR_TsaGetTable(nTableIndex, &cnt)) != NULL; nTableIndex++)
|
|
{
|
|
FMSTR_ADDR tmpAddr;
|
|
|
|
/* allow reading of the TSA table itself */
|
|
FMSTR_PTR2ADDR(tmpAddr, pte);
|
|
if(FMSTR_CheckMemSpace(dwAddr, nSize, tmpAddr, cnt))
|
|
{
|
|
return FMSTR_TRUE;
|
|
}
|
|
|
|
/* number of items in a table */
|
|
cnt /= (FMSTR_TSA_TSIZE) sizeof(FMSTR_TSA_ENTRY);
|
|
|
|
/* all table entries */
|
|
for(i=0U; i<cnt; i++)
|
|
{
|
|
/* system strings are always accessible at C-pointers */
|
|
FMSTR_PTR2ADDR(tmpAddr, pte->name.p);
|
|
if(pte->name.p)
|
|
{
|
|
if(FMSTR_CheckMemSpace(dwAddr, nSize, tmpAddr, FMSTR_StrLen(tmpAddr)))
|
|
{
|
|
return FMSTR_TRUE;
|
|
}
|
|
}
|
|
|
|
FMSTR_PTR2ADDR(tmpAddr, pte->type.p);
|
|
if(pte->type.p)
|
|
{
|
|
if(FMSTR_CheckMemSpace(dwAddr, nSize, tmpAddr, FMSTR_StrLen(tmpAddr)))
|
|
{
|
|
return FMSTR_TRUE;
|
|
}
|
|
}
|
|
|
|
pte++;
|
|
}
|
|
}
|
|
|
|
/* no valid TSA entry found => not-safe to access the memory */
|
|
return FMSTR_FALSE;
|
|
}
|
|
|
|
#else /* FMSTR_USE_TSA */
|
|
|
|
/*lint -efile(766, PE_freemaster_protocol.h) include file is not used in this case */
|
|
|
|
#endif /* FMSTR_USE_TSA */
|
|
|