1172 lines
56 KiB
C
1172 lines
56 KiB
C
|
|
/***********************************************************************************************************************
|
||
|
|
* FILE DESCRIPTION
|
||
|
|
* ------------------------------------------------------------------------------------------------------------------*/
|
||
|
|
/** \file
|
||
|
|
* \brief Implementation of a download check by using an embedded validation structure
|
||
|
|
* Declaration of functions, variables and constants
|
||
|
|
*
|
||
|
|
* --------------------------------------------------------------------------------------------------------------------
|
||
|
|
* COPYRIGHT
|
||
|
|
* --------------------------------------------------------------------------------------------------------------------
|
||
|
|
* \par Copyright
|
||
|
|
* \verbatim
|
||
|
|
* Copyright (c) 2023 by Vector Informatik GmbH. All rights reserved.
|
||
|
|
*
|
||
|
|
* This software is copyright protected and proprietary to Vector Informatik GmbH.
|
||
|
|
* Vector Informatik GmbH grants to you only those rights as set out in the license conditions.
|
||
|
|
* All other rights remain with Vector Informatik GmbH.
|
||
|
|
* \endverbatim
|
||
|
|
*/
|
||
|
|
/**********************************************************************************************************************/
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* REVISION HISTORY
|
||
|
|
* --------------------------------------------------------------------------------------------------------------------
|
||
|
|
* Version Date Author Change Id Description
|
||
|
|
* --------------------------------------------------------------------------------------------------------------------
|
||
|
|
* 01.00.00 2016-07-01 visci - Initial version
|
||
|
|
* 01.01.00 2017-02-03 visci ESCAN00093858 Added support for compatibility check
|
||
|
|
* vacel Added blank check functionality
|
||
|
|
* Added API for external public key
|
||
|
|
* Reworked return value handling
|
||
|
|
* 01.01.01 2017-11-09 visci ESCAN00096836 Compiler warning: Function declared but not used
|
||
|
|
* 01.01.02 2018-03-23 visdkl ESCAN00097287 Bootloader does not properly use configuration of CLASS_DDD
|
||
|
|
* 01.02.00 2018-06-15 visci ESCAN00098963 Corrected return value for public key read failure
|
||
|
|
* 2018-09-24 visrr ESCAN00100838 Added user callout for different erase values in OTA use case
|
||
|
|
* 01.03.00 2019-01-25 visci ESCAN00098904 Improved verification sequence
|
||
|
|
* ESCAN00101065 Alignment for Blank Check is not applied correctly
|
||
|
|
* ESCAN00101321 Added option to skip download segment check
|
||
|
|
* 01.03.01 2019-02-06 visci ESCAN00102005 Signature is not taken into account when comparing segments
|
||
|
|
* 01.04.00 2019-06-14 visci ESCAN00102956 Internal checksum option fails if validation structure is not the
|
||
|
|
* last segment
|
||
|
|
* ESCAN00102957 Potential buffer overflow during internal checksum calculation
|
||
|
|
* 01.05.00 2019-06-25 visdlm ESCAN00103492 Added gap fill mechanism
|
||
|
|
* 01.05.01 2021-01-18 visjdn ESCAN00107640 Memory read error leads always to invalid format error
|
||
|
|
* 01.05.02 2021-06-01 vishor ESCAN00109198 The verification key will not be cleared from memory (RAM) after usage
|
||
|
|
* 01.06.00 2022-04-28 visstn FBL-4366 Perform MISRA 2012 migration
|
||
|
|
* 01.07.00 2022-10-12 visjdn FBL-5694 Support of Xiaomi validation structure
|
||
|
|
* 01.08.00 2022-11-25 vistbe FBL-6055 Extend configurability of checksum and signature
|
||
|
|
* 01.08.01 2023-02-02 vistbe ESCAN00113401 No changes
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#define FBL_VALSTRUCT_SOURCE
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* INCLUDES
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#include "fbl_inc.h"
|
||
|
|
#include "fbl_valstruct.h"
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* VERSION
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if ( FBLVALSTRUCT_VERSION != 0x0108u ) || \
|
||
|
|
( FBLVALSTRUCT_RELEASE_VERSION != 0x01u )
|
||
|
|
# error "Error in fbl_valstruct.c: Source and header file are inconsistent!"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if ( FBLVALSTRUCT_VERSION != _FBLVALSTRUCT_VERSION ) || \
|
||
|
|
( FBLVALSTRUCT_RELEASE_VERSION != _FBLVALSTRUCT_RELEASE_VERSION )
|
||
|
|
# error "Error in fbl_valstruct.c: Source and v_ver.h are inconsistent!"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* DEFINES
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
/*** Validation structure defines ***/
|
||
|
|
# define FBL_VALSTRUCT_PROLOG_SIZE (FBL_VALSTRUCT_TAG_SIZE + FBL_VALSTRUCT_VERSION_SIZE + FBL_VALSTRUCT_BLOCKCOUNT_SIZE + FBL_VALSTRUCT_ALFI_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_BLOCKINFO_SIZE (FBL_VALSTRUCT_BLOCKADDRESS_SIZE + FBL_VALSTRUCT_BLOCKLENGTH_SIZE + FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_EPILOG_SIZE (FBL_VALSTRUCT_TAG_SIZE + FBL_VALSTRUCT_VALIDATESUM_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_MAX_SIZE (FBL_VALSTRUCT_PROLOG_SIZE + (FBL_VALSTRUCT_BLOCKCOUNT_MAX * FBL_VALSTRUCT_BLOCKINFO_SIZE) + FBL_VALSTRUCT_EPILOG_SIZE)
|
||
|
|
|
||
|
|
/* Offset values for validation struct members */
|
||
|
|
# define FBL_VALSTRUCT_TAGBEGIN_OFFSET (0x00u)
|
||
|
|
# define FBL_VALSTRUCT_VERSION_OFFSET (FBL_VALSTRUCT_TAGBEGIN_OFFSET + FBL_VALSTRUCT_TAG_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_BLOCKCOUNT_OFFSET (FBL_VALSTRUCT_VERSION_OFFSET + FBL_VALSTRUCT_VERSION_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_ALFI_OFFSET (FBL_VALSTRUCT_BLOCKCOUNT_OFFSET + FBL_VALSTRUCT_BLOCKCOUNT_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_BLOCKADDRESS_OFFSET(index) (FBL_VALSTRUCT_ALFI_OFFSET + FBL_VALSTRUCT_ALFI_SIZE + ((index) * FBL_VALSTRUCT_BLOCKINFO_SIZE))
|
||
|
|
# define FBL_VALSTRUCT_BLOCKLENGTH_OFFSET(index) (FBL_VALSTRUCT_BLOCKADDRESS_OFFSET(index) + FBL_VALSTRUCT_BLOCKADDRESS_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_BLOCKCHECKSUM_OFFSET(index) (FBL_VALSTRUCT_BLOCKLENGTH_OFFSET(index) + FBL_VALSTRUCT_BLOCKLENGTH_SIZE)
|
||
|
|
# define FBL_VALSTRUCT_TAGEND_OFFSET(blockcount) (FBL_VALSTRUCT_BLOCKADDRESS_OFFSET(0u) + ((blockcount) * FBL_VALSTRUCT_BLOCKINFO_SIZE))
|
||
|
|
# define FBL_VALSTRUCT_VALIDATESUM_OFFSET(blockcount) (FBL_VALSTRUCT_TAGEND_OFFSET(blockcount) + FBL_VALSTRUCT_TAG_SIZE)
|
||
|
|
|
||
|
|
/* Access macros to extract validation struct information from a RAM buffer */
|
||
|
|
/* Note: this macro requires that the validation structure is built in big-endian mode! */
|
||
|
|
# define FblValStructGetUint32(buffer) FblMemGetInteger(sizeof(vuint32), (buffer))
|
||
|
|
# define FblValStructGetUint16(buffer) ((vuint16)(FblMemGetInteger(sizeof(vuint16), (buffer)) & 0xFFFFu))
|
||
|
|
# define FblValStructGetUint8(buffer) ((vuint8)(FblMemGetInteger(sizeof(vuint8), (buffer)) & 0xFFu))
|
||
|
|
# define FblValStructGetTagBegin(buffer) FblValStructGetUint32(&(buffer)[FBL_VALSTRUCT_TAGBEGIN_OFFSET])
|
||
|
|
# define FblValStructGetVersion(buffer) FblValStructGetUint16(&(buffer)[FBL_VALSTRUCT_VERSION_OFFSET])
|
||
|
|
# if (FBL_VALSTRUCT_BLOCKCOUNT_SIZE == 1u)
|
||
|
|
# define FblValStructGetBlockCount(buffer) FblValStructGetUint8(&(buffer)[FBL_VALSTRUCT_BLOCKCOUNT_OFFSET])
|
||
|
|
# elif (FBL_VALSTRUCT_BLOCKCOUNT_SIZE == 2u)
|
||
|
|
# define FblValStructGetBlockCount(buffer) FblValStructGetUint16(&(buffer)[FBL_VALSTRUCT_BLOCKCOUNT_OFFSET])
|
||
|
|
# endif
|
||
|
|
# if (FBL_VALSTRUCT_ALFI_SIZE == 1u)
|
||
|
|
# define FblValStructGetAlfi(buffer) FblValStructGetUint8(&(buffer)[FBL_VALSTRUCT_ALFI_OFFSET])
|
||
|
|
# endif
|
||
|
|
# define FblValStructGetBlockAddress(buffer, index) FblValStructGetUint32(&(buffer)[FBL_VALSTRUCT_BLOCKADDRESS_OFFSET(index)])
|
||
|
|
# define FblValStructGetBlockLength(buffer, index) FblValStructGetUint32(&(buffer)[FBL_VALSTRUCT_BLOCKLENGTH_OFFSET(index)])
|
||
|
|
# define FblValStructGetBlockChecksum(buffer, index, cs) (void)MEMCPY(cs, &(buffer)[FBL_VALSTRUCT_BLOCKCHECKSUM_OFFSET(index)], FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE)
|
||
|
|
# define FblValStructGetTagEnd(buffer, blockcount) FblValStructGetUint32(&(buffer)[FBL_VALSTRUCT_TAGEND_OFFSET(blockcount)])
|
||
|
|
# define FblValStructGetValidateSum(buffer, blockcount) FblValStructGetUint16(&(buffer)[FBL_VALSTRUCT_VALIDATESUM_OFFSET(blockcount)])
|
||
|
|
|
||
|
|
/* Calculate the actual size of the validation structure based on the given block count */
|
||
|
|
# define FblValStructGetTotalSize(blockcount) (FBL_VALSTRUCT_PROLOG_SIZE + ((blockcount) * FBL_VALSTRUCT_BLOCKINFO_SIZE) + FBL_VALSTRUCT_EPILOG_SIZE)
|
||
|
|
|
||
|
|
/* Macros used to retrieve the requested ValStruct processing options */
|
||
|
|
# define FblValStructOptionChecksumInternal(opt) (((opt) & FBL_VALSTRUCT_OPTION_CHECKSUM_INTERNAL) == FBL_VALSTRUCT_OPTION_CHECKSUM_INTERNAL)
|
||
|
|
# define FblValStructOptionBlankCheck(opt) (((opt) & FBL_VALSTRUCT_OPTION_BLANKCHECK) == FBL_VALSTRUCT_OPTION_BLANKCHECK)
|
||
|
|
# define FblValStructOptionGapFill(opt) (((opt) & FBL_VALSTRUCT_OPTION_GAP_FILL) == FBL_VALSTRUCT_OPTION_GAP_FILL)
|
||
|
|
|
||
|
|
/* Configuration specific definition of output buffer size for verification */
|
||
|
|
# if defined( SEC_ENABLE_SECURITY_CLASS_DDD )
|
||
|
|
# if defined( SEC_ENABLE_CRC_WRITTEN_CLASS_DDD )
|
||
|
|
# define FBL_VALSTRUCT_VERIFY_SIZE (FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE + SEC_SIZE_CHECKSUM_CRC)
|
||
|
|
# else
|
||
|
|
# define FBL_VALSTRUCT_VERIFY_SIZE (FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE)
|
||
|
|
# endif
|
||
|
|
# endif
|
||
|
|
|
||
|
|
# if !defined( FBL_VALSTRUCT_GAP_FILL_SEGMENTATION )
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
# define FBL_VALSTRUCT_GAP_FILL_SEGMENTATION FBL_MAX_SEGMENT_SIZE
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
# endif
|
||
|
|
|
||
|
|
/* If signature support is not explictily enabled or disabled set it based on the security class */
|
||
|
|
# if !defined( FBL_VALSTRUCT_ENABLE_SIGNATURE ) && !defined( FBL_VALSTRUCT_DISABLE_SIGNATURE )
|
||
|
|
# if (SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC)
|
||
|
|
# define FBL_VALSTRUCT_ENABLE_SIGNATURE
|
||
|
|
# endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
||
|
|
# endif /* !FBL_VALSTRUCT_ENABLE_SIGNATURE */
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_SIGNATURE ) && defined( FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY )
|
||
|
|
# if !defined( FblValStructClrPublicKey )
|
||
|
|
# define FblValStructClrPublicKey(x)
|
||
|
|
# endif /* FblValStructClrPublicKey */
|
||
|
|
# endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
||
|
|
#endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
|
||
|
|
/* Evaluate size of common buffer which is used for memory read/write operations. */
|
||
|
|
#if !defined( FBL_VALSTRUCT_READ_BUFFER_SIZE )
|
||
|
|
# if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
# if ((defined(FBL_VALSTRUCT_ENABLE_SIGNATURE)) && (FBL_VALSTRUCT_SIGNATURE_SIZE > FBL_VALSTRUCT_MAX_SIZE))
|
||
|
|
/* Set buffer size to signature size */
|
||
|
|
# define FBL_VALSTRUCT_READ_BUFFER_SIZE FBL_VALSTRUCT_SIGNATURE_SIZE
|
||
|
|
# else
|
||
|
|
/* Set buffer size to maximum possible size of validation structure */
|
||
|
|
# define FBL_VALSTRUCT_READ_BUFFER_SIZE FBL_VALSTRUCT_MAX_SIZE
|
||
|
|
# endif
|
||
|
|
# endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* TYPEDEFS
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
typedef struct
|
||
|
|
{
|
||
|
|
vuintx alignDummy;
|
||
|
|
vuint8 data[FBL_VALSTRUCT_READ_BUFFER_SIZE];
|
||
|
|
} tAlignedReadBuffer;
|
||
|
|
|
||
|
|
/** Structure which keeps segment information */
|
||
|
|
typedef tDiagSegmentList tVsSegInfo;
|
||
|
|
|
||
|
|
/** Structure which keeps information about/from the validation structure */
|
||
|
|
typedef struct
|
||
|
|
{
|
||
|
|
tFblAddress address; /**< Start address of validation structure */
|
||
|
|
tFblLength length; /**< Total length of validation structure */
|
||
|
|
tVsSegInfo segInfo; /**< Segment information contained in validation structure */
|
||
|
|
vuint8 vsSeg; /**< Index of segment which keeps the validation structure */
|
||
|
|
} tVsInfo;
|
||
|
|
#endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* LOCAL DATA
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
# define FBL_VALSTRUCT_START_SEC_VAR
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
V_MEMRAM0 static V_MEMRAM1 tAlignedReadBuffer V_MEMRAM2 readBuffer; /* PRQA S 3218 */ /* MD_FblValStruct_3218 */
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 gapFillBuffer[FBL_VALSTRUCT_GAP_FILL_SEGMENTATION];
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
# define FBL_VALSTRUCT_STOP_SEC_VAR
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
#endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* PROTOTYPES
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
# define FBL_VALSTRUCT_START_SEC_CODE
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
# if ( FBL_VALSTRUCT_VALIDATESUM_SIZE > 0u )
|
||
|
|
static vuint16 FblValStructCalculateByteChecksum( const vuint8* address, tFblLength size );
|
||
|
|
# endif
|
||
|
|
static tFblValStructResult FblValStructGetSegmentInfo( tVsInfo * vsInfo );
|
||
|
|
static void FblValStructRemoveStructSegment( const tVsInfo * vsInfo, tDiagSegmentList * blockSegInfo );
|
||
|
|
# if defined ( FBL_VALSTRUCT_ENABLE_SIGNATURE )
|
||
|
|
static tFblValStructResult FblValStructVerification( const tVsInfo * vsInfo,
|
||
|
|
SecM_ByteType * verifyData );
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_SIGNATURE */
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL )
|
||
|
|
static void FblValStructLocateStructSegment( tVsInfo * vsInfo );
|
||
|
|
static tFblValStructResult FblValStructChecksumInternal( tVsInfo * vsInfo,
|
||
|
|
tDiagSegmentList * blockSegInfo );
|
||
|
|
# endif
|
||
|
|
static tFblValStructResult FblValStructChecksumExternal( const tBlockDescriptor * blockDescriptor,
|
||
|
|
tVsInfo * vsInfo,
|
||
|
|
tDiagSegmentList * blockSegInfo);
|
||
|
|
static tFblValStructResult FblValStructCompareSegmentLocation( tVsInfo * vsInfo,
|
||
|
|
const tDiagSegmentList * blockSegInfo);
|
||
|
|
static tFblValStructResult FblValStructCompareSegmentChecksum( const tVsSegInfo * vsSegInfo,
|
||
|
|
const tDiagSegmentList * blockSegInfo );
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK )
|
||
|
|
static tFblValStructResult FblValStructBlankCheck( tFblAddress memAddress, tFblLength memLength );
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK */
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
static tFblValStructResult FblValStructGapFill( tFblAddress memAddress, tFblLength memLength );
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK ) || \
|
||
|
|
defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
static tFblAddress FblValStructSkipFilledArea( tFblAddress address, vsint16 memSeg );
|
||
|
|
static tFblValStructResult FblValStructGapProcessing( const tBlockDescriptor * blockDescriptor,
|
||
|
|
const tDiagSegmentList * blockSegInfo );
|
||
|
|
# endif
|
||
|
|
# define FBL_VALSTRUCT_STOP_SEC_CODE
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
#endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* LOCAL FUNCTIONS
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
#if defined( FBL_ENABLE_VALSTRUCT )
|
||
|
|
# define FBL_VALSTRUCT_START_SEC_CODE
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
# if ( FBL_VALSTRUCT_VALIDATESUM_SIZE > 0u )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructCalculateByteChecksum
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Calculate a 16-bit sized byte checksum over the buffer content.
|
||
|
|
* \param[in] address Pointer to data buffer in RAM
|
||
|
|
* \param[in] size Size of data in buffer
|
||
|
|
* \return Calculated checksum value
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static vuint16 FblValStructCalculateByteChecksum( const vuint8 * address, tFblLength size )
|
||
|
|
{
|
||
|
|
const vuint8 * bytePtr = address;
|
||
|
|
vuint16 byteChecksum = 0u;
|
||
|
|
|
||
|
|
while (bytePtr < (&address[size]))
|
||
|
|
{
|
||
|
|
byteChecksum += *bytePtr;
|
||
|
|
bytePtr = &bytePtr[1u];
|
||
|
|
|
||
|
|
/* Keep up bootloader timing and watchdog service */
|
||
|
|
if (((tFblAddress)bytePtr & 0xFu) == 0u) /* PRQA S 0306 */ /* MD_FblValStruct_0306 */
|
||
|
|
{
|
||
|
|
/* Call service function every 16th loop cycle */
|
||
|
|
(void)FblLookForWatchdog();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return byteChecksum;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_VALIDATESUM_SIZE > 0u */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructGetSegmentInfo
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Check presence and integrity of the validation structure and extract the segment information.
|
||
|
|
* \param[in,out] vsInfo Start address (in) and length (out) of validation structure, segment information (out)
|
||
|
|
* \return kFblValStructOk = validation structure has been read successfully
|
||
|
|
* other value = reading of validation structure failed
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/* PRQA S 6010, 6030 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC */
|
||
|
|
static tFblValStructResult FblValStructGetSegmentInfo( tVsInfo * vsInfo )
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
tFblLength vsTotalSize;
|
||
|
|
vuint16 segIndex, vsSegCount;
|
||
|
|
# if ( FBL_VALSTRUCT_VALIDATESUM_SIZE > 0u )
|
||
|
|
vuint16 validateSum;
|
||
|
|
# endif
|
||
|
|
|
||
|
|
/* Initialize return value */
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
/* Initialize total size */
|
||
|
|
vsTotalSize = 0u;
|
||
|
|
|
||
|
|
/* Read begin tag, version and block count of validation structure */
|
||
|
|
if (FblReadProm(vsInfo->address, readBuffer.data, FBL_VALSTRUCT_PROLOG_SIZE) != FBL_VALSTRUCT_PROLOG_SIZE)
|
||
|
|
{
|
||
|
|
/* Memory read error (e.g. invalid memory region) */
|
||
|
|
result = kFblValStructMemoryReadError;
|
||
|
|
}
|
||
|
|
|
||
|
|
# if ( FBL_VALSTRUCT_TAG_SIZE > 0u )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check begin tag */
|
||
|
|
if (FblValStructGetTagBegin(readBuffer.data) != FBL_VALSTRUCT_TAGBEGIN_PATTERN)
|
||
|
|
{
|
||
|
|
/* Begin tag invalid */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif
|
||
|
|
|
||
|
|
# if ( FBL_VALSTRUCT_VERSION_SIZE > 0u )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check if structure version is supported */
|
||
|
|
if (FblValStructIsVersionSupported(FblValStructGetVersion(readBuffer.data)) != kFblValStructOk)
|
||
|
|
{
|
||
|
|
/* Begin tag invalid */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check block count */
|
||
|
|
vsSegCount = FblValStructGetBlockCount(readBuffer.data);
|
||
|
|
if (vsSegCount <= FBL_VALSTRUCT_BLOCKCOUNT_MAX)
|
||
|
|
{
|
||
|
|
vsInfo->segInfo.nrOfSegments = (vuint8)vsSegCount;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Maximum block count exceeded */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# if (FBL_VALSTRUCT_ALFI_SIZE == 1u)
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check ALFI */
|
||
|
|
if (FblValStructGetAlfi(readBuffer.data) != (FBL_VALSTRUCT_BLOCKADDRESS_SIZE + (FBL_VALSTRUCT_BLOCKLENGTH_SIZE << 4u)))
|
||
|
|
{
|
||
|
|
/* ALFI is invalid */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Calculate total validation struct size */
|
||
|
|
vsTotalSize = FblValStructGetTotalSize((vuint32) vsInfo->segInfo.nrOfSegments); /* PRQA S 2985 */ /* MD_FblValStruct_2985 */
|
||
|
|
|
||
|
|
/* Block count value OK, read the rest of the validation structure */
|
||
|
|
if (FblReadProm((vsInfo->address + FBL_VALSTRUCT_PROLOG_SIZE),
|
||
|
|
&(readBuffer.data[FBL_VALSTRUCT_PROLOG_SIZE]),
|
||
|
|
(vsTotalSize - FBL_VALSTRUCT_PROLOG_SIZE)) != (vsTotalSize - FBL_VALSTRUCT_PROLOG_SIZE))
|
||
|
|
{
|
||
|
|
/* Memory read error (e.g. invalid memory region) */
|
||
|
|
result = kFblValStructMemoryReadError;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# if ( FBL_VALSTRUCT_TAG_SIZE > 0u )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check end tag */
|
||
|
|
if (FblValStructGetTagEnd(readBuffer.data, vsInfo->segInfo.nrOfSegments) != FBL_VALSTRUCT_TAGEND_PATTERN)
|
||
|
|
{
|
||
|
|
/* End tag invalid */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif
|
||
|
|
|
||
|
|
# if ( FBL_VALSTRUCT_VALIDATESUM_SIZE > 0u )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check integrity of validation structure (verify byte checksum) */
|
||
|
|
validateSum = FblValStructCalculateByteChecksum(readBuffer.data, (vsTotalSize - FBL_VALSTRUCT_VALIDATESUM_SIZE));
|
||
|
|
if (validateSum != FblValStructGetValidateSum(readBuffer.data, vsInfo->segInfo.nrOfSegments))
|
||
|
|
{
|
||
|
|
/* Validation information corrupt */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Extract block information. This separate step ensures correct data */
|
||
|
|
/* interpretation regardless of endianess and structure alignment. */
|
||
|
|
for (segIndex = 0; segIndex < vsInfo->segInfo.nrOfSegments; segIndex++)
|
||
|
|
{
|
||
|
|
vsInfo->segInfo.segmentInfo[segIndex].targetAddress = FblValStructGetBlockAddress(readBuffer.data, segIndex);
|
||
|
|
vsInfo->segInfo.segmentInfo[segIndex].length = FblValStructGetBlockLength(readBuffer.data, segIndex);
|
||
|
|
/* PRQA S 0314 1 */ /* MD_FblValStruct_0314 */
|
||
|
|
FblValStructGetBlockChecksum(readBuffer.data, segIndex, vsInfo->segInfo.segmentInfo[segIndex].checksum);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Return total length of structure */
|
||
|
|
vsInfo->length = vsTotalSize;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructRemoveStructSegment
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Determine download segment which keeps the validation structure and remove it from the list
|
||
|
|
* \pre vsInfo->vsSeg has to be set before (validation structure segment)
|
||
|
|
* \param[in] vsInfo Structure which keeps information about validation structure (out: vsSeg)
|
||
|
|
* \param[in,out] blockSegInfo Output segment list which contains the newly calculated checksum values
|
||
|
|
* \return kFblValStructOk = validation structure identified and removed
|
||
|
|
* other value = validation structure not found
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static void FblValStructRemoveStructSegment( const tVsInfo * vsInfo, tDiagSegmentList * blockSegInfo )
|
||
|
|
{
|
||
|
|
vuint8 segIdx;
|
||
|
|
|
||
|
|
/* Remove ValStruct segment from list */
|
||
|
|
for (segIdx = vsInfo->vsSeg + 1u; segIdx < blockSegInfo->nrOfSegments; segIdx++)
|
||
|
|
{
|
||
|
|
blockSegInfo->segmentInfo[segIdx - 1u] = blockSegInfo->segmentInfo[segIdx];
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Fix number of segments */
|
||
|
|
blockSegInfo->nrOfSegments--;
|
||
|
|
}
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_SIGNATURE )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructVerification
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief The flash memory content is verified according to the configured CCC algorithm
|
||
|
|
* \param[in] vsInfo Structure which keeps information about validation structure
|
||
|
|
* \param[in] verifyData Input buffer which keeps the signature data for comparison with the calculated value
|
||
|
|
* \return kFblValStructOk = Authentication succeeded
|
||
|
|
* other value = Authentication failed (or memory access error)
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructVerification( const tVsInfo * vsInfo, SecM_ByteType * verifyData )
|
||
|
|
{
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY )
|
||
|
|
SecM_AsymKeyType publicKey;
|
||
|
|
# endif
|
||
|
|
SecM_VerifyParamType verifyParam;
|
||
|
|
FL_SegmentInfoType verifySegmentInfo[1u];
|
||
|
|
SecM_StatusType secStatus;
|
||
|
|
tFblValStructResult result;
|
||
|
|
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
/* Configure segment which shall be verified */
|
||
|
|
verifySegmentInfo[0u].targetAddress = vsInfo->address;
|
||
|
|
verifySegmentInfo[0u].transferredAddress = verifySegmentInfo[0u].targetAddress;
|
||
|
|
verifySegmentInfo[0u].length = vsInfo->length;
|
||
|
|
verifyParam.segmentList.segmentInfo = verifySegmentInfo;
|
||
|
|
verifyParam.segmentList.nrOfSegments = 1u;
|
||
|
|
verifyParam.blockStartAddress = verifySegmentInfo[0u].targetAddress;
|
||
|
|
verifyParam.blockLength = verifySegmentInfo[0u].length;
|
||
|
|
verifyParam.verificationData = verifyData;
|
||
|
|
verifyParam.wdTriggerFct = (FL_WDTriggerFctType)FblRealTimeSupport; /* PRQA S 0313 */ /* MD_FblValStruct_0313_WDTriggerFctType */
|
||
|
|
verifyParam.readMemory = (FL_ReadMemoryFctType)FblReadProm;
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY )
|
||
|
|
publicKey.shared.size = sizeof(SecM_RsaMod);
|
||
|
|
publicKey.individual.size = sizeof(SecM_RsaExp);
|
||
|
|
|
||
|
|
if (kFblOk == FblValStructGetPublicKey(&publicKey))
|
||
|
|
{
|
||
|
|
verifyParam.key = &publicKey; /* PRQA S 0315 */ /* MD_FblValStruct_0315 */
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* An error occured and the key was not able to be retrieved */
|
||
|
|
result = kFblValStructKeyError;
|
||
|
|
}
|
||
|
|
# else
|
||
|
|
/* Use the internal key */
|
||
|
|
verifyParam.key = SEC_VERIFY_KEY_NULL;
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY */
|
||
|
|
|
||
|
|
if (kFblValStructOk == result) /* PRQA S 2991, 2995 */ /* MD_FblValStruct_2991_2995 */
|
||
|
|
{
|
||
|
|
/* Perform hash calculation and compare with decrypted signature */
|
||
|
|
secStatus = FblValStructSignatureVerification(&verifyParam);
|
||
|
|
if (SECM_VER_OK != secStatus)
|
||
|
|
{
|
||
|
|
/* An error occurred during signature verification or the signature check failed */
|
||
|
|
result = kFblValStructNotAuthentic;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY )
|
||
|
|
FblValStructClrPublicKey(&publicKey);
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_EXTERNAL_KEY */
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_SIGNATURE */
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructLocateStructSegment
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Locate the position of the validation structure in the segment list of the validation structure
|
||
|
|
* \param[in,out] vsInfo Structure which keeps information about validation structure (out: vsSeg)
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static void FblValStructLocateStructSegment( tVsInfo * vsInfo )
|
||
|
|
{
|
||
|
|
vuint8 segIdx;
|
||
|
|
vuint8 vsFound;
|
||
|
|
|
||
|
|
/* Locate validation structure segment in segment list */
|
||
|
|
segIdx = vsInfo->segInfo.nrOfSegments;
|
||
|
|
vsFound = 0u;
|
||
|
|
while (segIdx > 0u)
|
||
|
|
{
|
||
|
|
segIdx--;
|
||
|
|
if (vsInfo->address > vsInfo->segInfo.segmentInfo[segIdx].targetAddress)
|
||
|
|
{
|
||
|
|
/* Validation structure located above the current segment */
|
||
|
|
vsInfo->vsSeg = segIdx + 1u;
|
||
|
|
vsFound = 1u;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (vsFound == 0u)
|
||
|
|
{
|
||
|
|
/* Validation structure must be located in front of the first entry */
|
||
|
|
vsInfo->vsSeg = 0u;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructChecksumInternal
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Calculate the checksum (or CRC/hash) values for all segments in the validation structure
|
||
|
|
* \param[in,out] vsInfo Structure which keeps information about validation structure (out: vsSeg)
|
||
|
|
* \param[in,out] blockSegInfo Output segment list which contains the newly calculated checksum values
|
||
|
|
* \return kFblValStructOk = Checksum calculation successfully finished, information in blockSegInfo is valid
|
||
|
|
* other value = Error during checksum calculation, information in blockSegInfo is not valid
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructChecksumInternal( tVsInfo * vsInfo, tDiagSegmentList * blockSegInfo )
|
||
|
|
{
|
||
|
|
static SecM_ByteType verifyOutputBuf[FBL_VALSTRUCT_VERIFY_SIZE];
|
||
|
|
tFblValStructResult result;
|
||
|
|
SecM_VerifyParamType localVerifyParam;
|
||
|
|
FL_SegmentInfoType verifySegmentInfo[1];
|
||
|
|
vuint8 segIdx;
|
||
|
|
vuint8 vsInserted;
|
||
|
|
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
/* Locate validation structure segment (required for blank check!) */
|
||
|
|
FblValStructLocateStructSegment(vsInfo);
|
||
|
|
|
||
|
|
/* Add one segment for validation structure */
|
||
|
|
blockSegInfo->nrOfSegments = vsInfo->segInfo.nrOfSegments + 1u;
|
||
|
|
|
||
|
|
/* Iterate over all segments which are defined in the validation structure */
|
||
|
|
vsInserted = 0u;
|
||
|
|
for (segIdx = 0u; segIdx < blockSegInfo->nrOfSegments; segIdx++)
|
||
|
|
{
|
||
|
|
if (segIdx == vsInfo->vsSeg)
|
||
|
|
{
|
||
|
|
/* Insert validation structure */
|
||
|
|
blockSegInfo->segmentInfo[segIdx].targetAddress = vsInfo->address;
|
||
|
|
blockSegInfo->segmentInfo[segIdx].length = vsInfo->length;
|
||
|
|
vsInserted = 1u;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Copy address/length information */
|
||
|
|
blockSegInfo->segmentInfo[segIdx].targetAddress = vsInfo->segInfo.segmentInfo[segIdx - vsInserted].targetAddress;
|
||
|
|
blockSegInfo->segmentInfo[segIdx].length = vsInfo->segInfo.segmentInfo[segIdx - vsInserted].length;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Prepare input data for checksum calculation */
|
||
|
|
verifySegmentInfo[0].length = blockSegInfo->segmentInfo[segIdx].length;
|
||
|
|
verifySegmentInfo[0].targetAddress = blockSegInfo->segmentInfo[segIdx].targetAddress;
|
||
|
|
verifySegmentInfo[0].transferredAddress = blockSegInfo->segmentInfo[segIdx].targetAddress;
|
||
|
|
localVerifyParam.segmentList.nrOfSegments = 1u;
|
||
|
|
localVerifyParam.segmentList.segmentInfo = verifySegmentInfo;
|
||
|
|
localVerifyParam.verificationData = verifyOutputBuf;
|
||
|
|
localVerifyParam.crcTotal = 0u;
|
||
|
|
localVerifyParam.wdTriggerFct = (FL_WDTriggerFctType)FblRealTimeSupport; /* PRQA S 0313 */ /* MD_FblValStruct_0313_WDTriggerFctType */
|
||
|
|
localVerifyParam.readMemory = (FL_ReadMemoryFctType)FblReadProm;
|
||
|
|
|
||
|
|
/* Do checksum verification */
|
||
|
|
if (FblValStructChecksumVerification(&localVerifyParam) == SECM_VER_OK)
|
||
|
|
{
|
||
|
|
/* Copy checksum into segment list */
|
||
|
|
(void)MEMCPY(blockSegInfo->segmentInfo[segIdx].checksum, /* PRQA S 0314 */ /* MD_FblValStruct_0314 */
|
||
|
|
&verifyOutputBuf[FBL_VALSTRUCT_BLOCKCHECKSUM_VERIFY_OFFSET],
|
||
|
|
FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
result = kFblValStructMemoryReadError;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructChecksumExternal
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Request segment information from external instance and check against validation structure
|
||
|
|
* \param[in] blockDescriptor Block descriptor structure
|
||
|
|
* \param[in,out] vsInfo Structure which keeps information about validation structure
|
||
|
|
* \param[in,out] blockSegInfo Download segment list
|
||
|
|
* \return kFblValStructOk = Passed segment information matches the information in the validation structure
|
||
|
|
* other value = Invalid number of segments passed or segment locations don't match
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/* PRQA S 3673 3 */ /* MD_MSR_Rule8.13 */
|
||
|
|
static tFblValStructResult FblValStructChecksumExternal( const tBlockDescriptor * blockDescriptor,
|
||
|
|
tVsInfo * vsInfo,
|
||
|
|
tDiagSegmentList * blockSegInfo )
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
|
||
|
|
# if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
||
|
|
/* Parameter not used (configuration dependent): avoid compiler warning */
|
||
|
|
(void)blockDescriptor; /* PRQA S 3112 */ /* MD_MSR_DummyStmt */
|
||
|
|
# endif /* V_ENABLE_USE_DUMMY_STATEMENT */
|
||
|
|
|
||
|
|
/* Get download segments which are associated with this logical block */
|
||
|
|
(void)FblValStructGetSegmentList(blockDescriptor->blockNr, blockSegInfo);
|
||
|
|
|
||
|
|
/* Check the amount of segments which have been downloaded */
|
||
|
|
if (blockSegInfo->nrOfSegments == (vsInfo->segInfo.nrOfSegments + 1u))
|
||
|
|
{
|
||
|
|
/* Number of downloaded segments (excluding the ValStruct segment) matches the number in the ValStruct */
|
||
|
|
result = FblValStructCompareSegmentLocation(vsInfo, blockSegInfo);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Mismatch between number of downloaded segments and blocks in validation structure; abort verification */
|
||
|
|
result = kFblValStructBlockNumberMismatch;
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructCompareSegmentLocation
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Compare the segment information from download and validation structure, remove ValStruct from list
|
||
|
|
* \param[in,out] vsInfo Structure which keeps information about validation structure (out: vsSeg)
|
||
|
|
* \param[in] blockSegInfo Download segment list
|
||
|
|
* \return kFblValStructOk = all segments are identical
|
||
|
|
* other value = address or length differences detected
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructCompareSegmentLocation( tVsInfo * vsInfo,
|
||
|
|
const tDiagSegmentList * blockSegInfo)
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
vuint8 segIdx, vsFound;
|
||
|
|
|
||
|
|
result = kFblValStructOk;
|
||
|
|
vsInfo->vsSeg = 0u;
|
||
|
|
vsFound = 0u;
|
||
|
|
|
||
|
|
for (segIdx = 0u; segIdx < blockSegInfo->nrOfSegments; segIdx++)
|
||
|
|
{
|
||
|
|
/* Check address and length against block info in validation structure */
|
||
|
|
if ((blockSegInfo->segmentInfo[segIdx].targetAddress != vsInfo->segInfo.segmentInfo[segIdx - vsFound].targetAddress) ||
|
||
|
|
(blockSegInfo->segmentInfo[segIdx].length != vsInfo->segInfo.segmentInfo[segIdx - vsFound].length))
|
||
|
|
{
|
||
|
|
/* Check if the mismatch is caused by the segment which keeps the validation structure */
|
||
|
|
if ((vsFound == 0u) && (blockSegInfo->segmentInfo[segIdx].targetAddress == vsInfo->address))
|
||
|
|
{
|
||
|
|
if (blockSegInfo->segmentInfo[segIdx].length == vsInfo->length)
|
||
|
|
{
|
||
|
|
/* Validation structure segment found */
|
||
|
|
vsInfo->vsSeg = segIdx;
|
||
|
|
vsFound = 1u;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Invalid length of validation structure */
|
||
|
|
result = kFblValStructInvalidFormat;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Address/or length mismatch between download and validation structure */
|
||
|
|
result = kFblValStructBlockMismatch;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (result != kFblValStructOk)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructCompareSegmentChecksum
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Compare the segment information from download and validation structure
|
||
|
|
* \param[in] vsSegInfo Segment list from validation structure
|
||
|
|
* \param[in] blockSegInfo Download segment list
|
||
|
|
* \return kFblValStructOk = all segments are identical
|
||
|
|
* other value = checksum differences detected
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructCompareSegmentChecksum( const tVsSegInfo * vsSegInfo, const tDiagSegmentList * blockSegInfo )
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
vuint8 segIdx, csIdx;
|
||
|
|
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
for (segIdx = 0; segIdx < vsSegInfo->nrOfSegments; segIdx++)
|
||
|
|
{
|
||
|
|
/* Compare calculated checksum/hash with value from validation structure */
|
||
|
|
for (csIdx = 0; csIdx < FBL_VALSTRUCT_BLOCKCHECKSUM_SIZE; csIdx++)
|
||
|
|
{
|
||
|
|
if (vsSegInfo->segmentInfo[segIdx].checksum[csIdx] != blockSegInfo->segmentInfo[segIdx].checksum[csIdx])
|
||
|
|
{
|
||
|
|
/* Checksum values differ, abort verification */
|
||
|
|
result = kFblValStructChecksumValueMismatch;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructBlankCheck
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Check whether the given memory area is erased (contains the respective erased value)
|
||
|
|
* \param[in] memAddress Start address of the memory area
|
||
|
|
* \param[in] memLength Length of the memory area
|
||
|
|
* \return kFblValStructOk = inter-segment memory areas are in state 'erased'
|
||
|
|
* kFblValStructBlankCheckFailed = non-erased memory area detected
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/* PRQA S 6080 1 */ /* MD_MSR_STMIF */
|
||
|
|
static tFblValStructResult FblValStructBlankCheck( tFblAddress memAddress, tFblLength memLength )
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
tFblLength readLength;
|
||
|
|
IO_ErrorType memDrvResult;
|
||
|
|
vuint16 bufIdx;
|
||
|
|
vuint8 erasedVal;
|
||
|
|
tFblAddress localMemAddress = memAddress;
|
||
|
|
tFblLength localMemLength = memLength;
|
||
|
|
|
||
|
|
/* Note: By definition, a logical block must be homogeneous (single memory device) and contiguous (no gaps) */
|
||
|
|
memSegment = FblMemSegmentNrGet(localMemAddress);
|
||
|
|
|
||
|
|
if (memSegment >= 0)
|
||
|
|
{
|
||
|
|
result = kFblValStructOk;
|
||
|
|
erasedVal = memDrvLst[FlashBlock[memSegment].device].erasedValue;
|
||
|
|
|
||
|
|
while ((localMemLength > 0u) && (kFblValStructOk == result))
|
||
|
|
{
|
||
|
|
readLength = (localMemLength >= FBL_VALSTRUCT_READ_BUFFER_SIZE) ? FBL_VALSTRUCT_READ_BUFFER_SIZE : localMemLength;
|
||
|
|
memDrvResult = MemDriver_RReadSync(readBuffer.data, readLength, localMemAddress);
|
||
|
|
|
||
|
|
if ((IO_E_OK == memDrvResult) || (IO_E_ERASED == memDrvResult))
|
||
|
|
{
|
||
|
|
for (bufIdx = 0u; bufIdx < readLength; bufIdx++)
|
||
|
|
{
|
||
|
|
/* Check if the pattern is in its initial state (i. e. the memory at the
|
||
|
|
pattern address is erased) */
|
||
|
|
if (readBuffer.data[bufIdx] != (vuint8)erasedVal)
|
||
|
|
{
|
||
|
|
/* Memory content has been modified - return with negative result */
|
||
|
|
result = kFblValStructBlankCheckFailed;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
localMemAddress += readLength;
|
||
|
|
localMemLength -= readLength;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Failure reported by read function */
|
||
|
|
result = kFblValStructBlankCheckFailed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Invalid memory segment */
|
||
|
|
result = kFblValStructBlankCheckFailed;
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK */
|
||
|
|
|
||
|
|
# if defined ( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructGapFill
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Fill gaps between programmed segments with kFillChar
|
||
|
|
* \param[in] memAddress Start address of the memory area
|
||
|
|
* \param[in] memLength Length of the memory area
|
||
|
|
* \return kFblValStructOk = inter-segment memory areas are filled successfully
|
||
|
|
* kFblValStructGapFillFailed = gap filling failed
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructGapFill(tFblAddress memAddress, tFblLength memLength)
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
tFblLength writeLength;
|
||
|
|
tFblAddress localMemAddress = memAddress;
|
||
|
|
tFblLength localMemLength = memLength;
|
||
|
|
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
while (localMemLength > 0u)
|
||
|
|
{
|
||
|
|
writeLength = (localMemLength >= FBL_VALSTRUCT_GAP_FILL_SEGMENTATION) ? FBL_VALSTRUCT_GAP_FILL_SEGMENTATION : localMemLength;
|
||
|
|
|
||
|
|
if (kFblMemStatus_Ok == FblMemProgramBuffer(localMemAddress, &writeLength, gapFillBuffer))
|
||
|
|
{
|
||
|
|
localMemAddress += writeLength;
|
||
|
|
localMemLength -= writeLength;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
result = kFblValStructGapFillFailed;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK ) || \
|
||
|
|
defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructSkipFilledArea
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Skip memory area at segment end which has been filled with kFillChar
|
||
|
|
* \param[in] address Start address of the memory area
|
||
|
|
* \param[in] memSeg Index of memory segment in flash block table which relates to the specified address
|
||
|
|
* \return Aligned address
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblAddress FblValStructSkipFilledArea( tFblAddress address, vsint16 memSeg )
|
||
|
|
{
|
||
|
|
vuint16 segSize;
|
||
|
|
tFblLength unalignedLength;
|
||
|
|
tFblAddress alignedAddress = address;
|
||
|
|
|
||
|
|
/* Retrieve write segment size of the respective memory device */
|
||
|
|
segSize = memDrvLst[FlashBlock[memSeg].device].segmentSize;
|
||
|
|
|
||
|
|
/* ESCAN00101065: Check alignment of read address */
|
||
|
|
if ((address & (segSize - 1uL)) != 0uL)
|
||
|
|
{
|
||
|
|
/* Skip data which has been filled with kFillChar */
|
||
|
|
unalignedLength = segSize - (address & (segSize - 1uL));
|
||
|
|
alignedAddress += unalignedLength;
|
||
|
|
}
|
||
|
|
|
||
|
|
return alignedAddress;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructGapProcessing
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief Depending on the configuration either blank check or gap filling will be executed
|
||
|
|
* \param[in] blockDescriptor Block descriptor structure
|
||
|
|
* \param[in] blockSegInfo Download segment list
|
||
|
|
* \return kFblValStructOk = processing successfully performed
|
||
|
|
* other value = either blank check or gap filling failed
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
static tFblValStructResult FblValStructGapProcessing( const tBlockDescriptor * blockDescriptor,
|
||
|
|
const tDiagSegmentList * blockSegInfo )
|
||
|
|
{
|
||
|
|
tFblValStructResult result;
|
||
|
|
tFblAddress procAddress;
|
||
|
|
tFblLength remainingLength;
|
||
|
|
vuint8 segIdx;
|
||
|
|
tBlockDescriptor localBlockDescriptor;
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
tFblLength idx;
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
localBlockDescriptor = *blockDescriptor;
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
/* Fill gap fill buffer with fill character */
|
||
|
|
for (idx = 0u; idx < FBL_VALSTRUCT_GAP_FILL_SEGMENTATION; idx++)
|
||
|
|
{
|
||
|
|
gapFillBuffer[idx] = kFillChar;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
/* Adjust the size of the logical block according to presence pattern size */
|
||
|
|
(void)ApplFblAdjustLbtBlockData(&localBlockDescriptor);
|
||
|
|
|
||
|
|
procAddress = localBlockDescriptor.blockStartAddress;
|
||
|
|
/* Note: By definition, a logical block must be homogeneous (single memory device) and contiguous (no gaps) */
|
||
|
|
memSegment = FblMemSegmentNrGet(procAddress);
|
||
|
|
|
||
|
|
if (memSegment >= 0)
|
||
|
|
{
|
||
|
|
result = kFblValStructOk;
|
||
|
|
|
||
|
|
for (segIdx = 0; segIdx < blockSegInfo->nrOfSegments; segIdx++)
|
||
|
|
{
|
||
|
|
/* Skip memory area at segment end which has been filled with kFillChar */
|
||
|
|
procAddress = FblValStructSkipFilledArea(procAddress, memSegment);
|
||
|
|
|
||
|
|
if (procAddress < blockSegInfo->segmentInfo[segIdx].targetAddress)
|
||
|
|
{
|
||
|
|
remainingLength = blockSegInfo->segmentInfo[segIdx].targetAddress - procAddress;
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
result = FblValStructGapFill(procAddress, remainingLength);
|
||
|
|
# else /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK */
|
||
|
|
result = FblValStructBlankCheck(procAddress, remainingLength);
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
if (kFblValStructOk != result)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
procAddress = blockSegInfo->segmentInfo[segIdx].targetAddress +
|
||
|
|
blockSegInfo->segmentInfo[segIdx].length;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Skip memory area at segment end which has been filled with kFillChar */
|
||
|
|
procAddress = FblValStructSkipFilledArea(procAddress, memSegment);
|
||
|
|
|
||
|
|
/* Check remaining part of logical block */
|
||
|
|
if (procAddress < (localBlockDescriptor.blockStartAddress + localBlockDescriptor.blockLength))
|
||
|
|
{
|
||
|
|
remainingLength = (localBlockDescriptor.blockStartAddress + localBlockDescriptor.blockLength) - procAddress;
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
result = FblValStructGapFill(procAddress, remainingLength);
|
||
|
|
# else /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK */
|
||
|
|
result = FblValStructBlankCheck(procAddress, remainingLength);
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Invalid memory segment */
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
result = kFblValStructGapFillFailed;
|
||
|
|
# else /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK */
|
||
|
|
result = kFblValStructBlankCheckFailed;
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK || FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* GLOBAL FUNCTIONS
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructValidateBlockExtended
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief The flash memory content is verified according to the information in the validation structure
|
||
|
|
* \pre Complete file must be successfully downloaded
|
||
|
|
* \param[in] blockDescriptor Block descriptor structure
|
||
|
|
* \param[in] option Parameter to influence the execution sequence
|
||
|
|
* \return kFblValStructOk = verification successfully performed
|
||
|
|
* other value = verification failed
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/* PRQA S 6050 1 */ /* MD_MSR_STCAL */
|
||
|
|
tFblValStructResult FblValStructValidateBlockExtended( const tBlockDescriptor * blockDescriptor,
|
||
|
|
const tFblValStructOption option )
|
||
|
|
{
|
||
|
|
static tVsInfo vsInfo;
|
||
|
|
static tDiagSegmentList blockSegInfo;
|
||
|
|
tFblValStructResult result;
|
||
|
|
|
||
|
|
# if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
||
|
|
/* Parameters not used: avoid compiler warning */
|
||
|
|
(void)option;
|
||
|
|
# endif
|
||
|
|
/* Check if requested options can be handled with current pre-compile config */
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL )
|
||
|
|
# else
|
||
|
|
assertFblUser(! FblValStructOptionChecksumInternal(option), kFblSysAssertParameterOutOfRange);
|
||
|
|
# endif
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK )
|
||
|
|
# else
|
||
|
|
assertFblUser(! FblValStructOptionBlankCheck(option), kFblSysAssertParameterOutOfRange);
|
||
|
|
# endif
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
# else
|
||
|
|
assertFblUser(! FblValStructOptionGapFill(option), kFblSysAssertParameterOutOfRange);
|
||
|
|
# endif
|
||
|
|
|
||
|
|
vsInfo.address = FblValStructGetVsAddress(blockDescriptor);
|
||
|
|
|
||
|
|
/* Extract the block information from the validation structure */
|
||
|
|
result = FblValStructGetSegmentInfo(&vsInfo);
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_SIGNATURE )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Read verification data from downloaded logical block */
|
||
|
|
result = FblValStructGetSignature(blockDescriptor, readBuffer.data); /* PRQA S 0306 */ /* MD_FblValStruct_0306 */
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Check integrity and authenticity of validation structure */
|
||
|
|
result = FblValStructVerification(&vsInfo, readBuffer.data);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_SIGNATURE */
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* ESCAN00102005: Adapt validation structure dimension to match the respective data segment
|
||
|
|
* (required if signature is attached to validation structure segment) */
|
||
|
|
vsInfo.address = FblValStructGetVsSegAddress(blockDescriptor);
|
||
|
|
vsInfo.length = FblValStructGetVsSegLength(vsInfo.length);
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL )
|
||
|
|
/* Decide whether the segment checksums shall be calculated internally or requested externally */
|
||
|
|
if (FblValStructOptionChecksumInternal(option))
|
||
|
|
{
|
||
|
|
/* Calculate the checksum of all segments and fill blockSegInfo structure */
|
||
|
|
result = FblValStructChecksumInternal(&vsInfo, &blockSegInfo);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_CHECKSUM_INTERNAL */
|
||
|
|
{
|
||
|
|
/* Request segment information from external instance and check against validation structure */
|
||
|
|
result = FblValStructChecksumExternal(blockDescriptor, &vsInfo, &blockSegInfo);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# if defined( FBL_VALSTRUCT_ENABLE_BLANK_CHECK ) || \
|
||
|
|
defined( FBL_VALSTRUCT_ENABLE_GAP_FILL )
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
if ((FblValStructOptionBlankCheck(option)) || (FblValStructOptionGapFill(option)))
|
||
|
|
{
|
||
|
|
/* Perform gap processing (blank check or gap fill) */
|
||
|
|
result = FblValStructGapProcessing(blockDescriptor, &blockSegInfo);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
# endif /* FBL_VALSTRUCT_ENABLE_BLANK_CHECK || FBL_VALSTRUCT_ENABLE_GAP_FILL */
|
||
|
|
|
||
|
|
if (kFblValStructOk == result)
|
||
|
|
{
|
||
|
|
/* Remove validation structure segment */
|
||
|
|
FblValStructRemoveStructSegment(&vsInfo, &blockSegInfo);
|
||
|
|
|
||
|
|
/* Proceed with checking the checksum/hash of all blocks in the structure */
|
||
|
|
result = FblValStructCompareSegmentChecksum(&vsInfo.segInfo, &blockSegInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* FblValStructValidateBlock
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
/*! \brief The flash memory content is verified according to the information in the validation structure
|
||
|
|
* \pre Complete file must be successfully downloaded
|
||
|
|
* \param[in] blockDescriptor Block descriptor structure
|
||
|
|
* \return kFblValStructOk = verification successfully performed
|
||
|
|
* other value = verification failed
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
tFblValStructResult FblValStructValidateBlock( const tBlockDescriptor * blockDescriptor )
|
||
|
|
{
|
||
|
|
return FblValStructValidateBlockExtended(blockDescriptor, FBL_VALSTRUCT_OPTION_DEFAULT);
|
||
|
|
}
|
||
|
|
# define FBL_VALSTRUCT_STOP_SEC_CODE
|
||
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
||
|
|
#endif /* FBL_ENABLE_VALSTRUCT */
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* MISRA DEVIATIONS
|
||
|
|
**********************************************************************************************************************/
|
||
|
|
|
||
|
|
/* module specific MISRA deviations:
|
||
|
|
|
||
|
|
MD_FblValStruct_0306:
|
||
|
|
Reason: Address conversion between integer values and pointers is required to allow for hardware independent
|
||
|
|
configuration and address range checks.
|
||
|
|
Risk: The size of integer required to hold the result of a pointer cast is implementation-defined.
|
||
|
|
Prevention: The size of the respective integer data type which holds the address value is adapted on a hardware
|
||
|
|
specific basis.
|
||
|
|
|
||
|
|
MD_FblValStruct_0314:
|
||
|
|
Reason: The copy function have a void pointer as a function parameter and an integer is casted to pointer void.
|
||
|
|
Risk: No risk, because the underlying pointer type is known and the cast is safe.
|
||
|
|
Prevention: No prevention necessary.
|
||
|
|
|
||
|
|
MD_FblValStruct_0315:
|
||
|
|
Reason: The underling type of verifyParam.key is pointer to void. As the type is defined outside the package, the
|
||
|
|
implicit conversion is necessary.
|
||
|
|
Risk: No identifiable risk.
|
||
|
|
Prevention: No prevention required.
|
||
|
|
|
||
|
|
MD_FblValStruct_0313_WDTriggerFctType:
|
||
|
|
Reason: Security module expects a watchdog handler with return type 'void'. The usage of a wrapper function is
|
||
|
|
avoided due to higher voted requirements for minimized stack and runtime usage applied on the code.
|
||
|
|
Risk: Potentially undefined behavior of the used compiler which usually leads to a warning or error during
|
||
|
|
compilation.
|
||
|
|
Prevention: The respective functionality is part of integration testing and will hence be verified before delivery.
|
||
|
|
|
||
|
|
MD_FblValStruct_2985:
|
||
|
|
Reason: Based on the configuration, some constants are zero, which leads to constant control expression.
|
||
|
|
Risk: No identifiable risk.
|
||
|
|
Prevention: No prevention required.
|
||
|
|
|
||
|
|
MD_FblValStruct_2991_2995:
|
||
|
|
Reason: The value of the if-controlling expression depends on the configuration.
|
||
|
|
Risk: No risk.
|
||
|
|
Prevention: No prevention necessary.
|
||
|
|
|
||
|
|
MD_FblValStruct_3218:
|
||
|
|
Reason: Variable is accessed from multiple functions (configuration dependent).
|
||
|
|
Risk: Scope is larger than required (whole file instead of one function). Some other function could access
|
||
|
|
the variable.
|
||
|
|
Prevention: Restrict the functionality in this module to the intended purpose. Don't add functions which shall not
|
||
|
|
be able to access the local data buffers.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
/***********************************************************************************************************************
|
||
|
|
* END OF FILE: FBL_VALSTRUCT.C
|
||
|
|
**********************************************************************************************************************/
|