6493 lines
262 KiB
C
6493 lines
262 KiB
C
/***********************************************************************************************************************
|
|
* FILE DESCRIPTION
|
|
* ------------------------------------------------------------------------------------------------------------------*/
|
|
/** \file
|
|
* \brief Diagnostic services supported in boot mode
|
|
* Declaration of functions, variables and constants
|
|
*
|
|
* --------------------------------------------------------------------------------------------------------------------
|
|
* COPYRIGHT
|
|
* --------------------------------------------------------------------------------------------------------------------
|
|
* \par Copyright
|
|
* \verbatim
|
|
* Copyright (c) 2026 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
|
|
* --------------------------------------------------------------------------------------------------------------------
|
|
* 05.00.00 2022-08-15 vistmo FBL-5514 Support Additional OTA functionality
|
|
* ESCAN00112435 The verification of the flash driver always fails
|
|
* ESCAN00112575 Ford tokens are wrongly rejected
|
|
* 05.01.00 2022-10-04 jschmitding FBL-5917 Make FBL SWDL 008 Compliant
|
|
* ESCAN00113919 No changes
|
|
* 05.01.01 2022-10-17 fmenke ESCAN00112879 Routine Check Application Validity is failing
|
|
* 05.01.02 2023-01-13 fmenke ESCAN00112890 DID D071 does not return the last successful token received
|
|
* ESCAN00113612 Server message ID check does not work correctly
|
|
* 05.02.00 2023-02-09 vistmo ESCAN00112972 Token with reserved bits set in SyncP is accepted
|
|
* ESCAN00113292 Wrong NRC for invalid RoutineControlOptionRecord on Set OTA Update
|
|
* ESCAN00113835 For token mode 5 reprogrammable keys are not extracted correctly
|
|
* ESCAN00113843 Token with "Has Key ID" bit set in SyncP is accepted
|
|
* ESCAN00113764 RID 7013 (token download) is always supported
|
|
* FBL-6438 No changes
|
|
* 05.02.01 2023-05-11 fmenke ESCAN00113831 Application validation fails in case of MAC update failure
|
|
* regardless logical block is optional or mandatory
|
|
* 05.03.00 2023-07-24 fmenke FBL-7335 Support new app signing handling
|
|
* 05.03.01 2023-08-31 lhopfhauer ESCAN00115494 Bootloader does not enter programming session when
|
|
* started from application
|
|
* 05.03.02 2024-07-16 erizk ESCAN00117344 Compiler error: FblRealTimeSupportVoid undefined, assuming
|
|
* extern returning int
|
|
* 05.03.03 2025-02-06 virchl ESCAN00118587 No Response for the Routine Control "Check Valid Application" 0x0304
|
|
* 05.04.00 2025-02-28 jjohnson FBL-10065 Support App Signing Specification 2.1.3
|
|
* 05.04.01 2025-06-10 jostravsky ESCAN00120315 Response to programming session request may be wrong
|
|
* 05.04.02 2025-07-08 visarcmijo ESCAN00119833 No NRC is returned to an RID 7013 requested without SBL activation
|
|
* 05.05.00 2025-09-01 fmenke FBL-11218 Add support for NXP DSP firmware update
|
|
* ESCAN00120917 SBL can be downloaded again and be executed without
|
|
* signature verification
|
|
* 05.06.00 2025-10-28 mpatil FBL-11690 Adding hooks and return values for callouts for Routine 7013
|
|
* 05.07.00 2026-01-13 dganesh FBL-12162 Support Ford SWDL 008.5
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBL_DIAG_SOURCE
|
|
|
|
/***********************************************************************************************************************
|
|
* INCLUDES
|
|
**********************************************************************************************************************/
|
|
|
|
#include "fbl_inc.h" /* Common include files */
|
|
#include "fbl_diag.h"
|
|
|
|
/***********************************************************************************************************************
|
|
* VERSION
|
|
**********************************************************************************************************************/
|
|
|
|
#if ( FBLDIAG_14229_FORD_VERSION != 0x0507u ) || \
|
|
( FBLDIAG_14229_FORD_RELEASE_VERSION != 0x00u )
|
|
# error "Error in fbl_diag.c: Source and header file are inconsistent!"
|
|
#endif
|
|
|
|
#if ( FBLDIAG_14229_FORD_VERSION != _FBLDIAG_OEM_VERSION ) || \
|
|
( FBLDIAG_14229_FORD_RELEASE_VERSION != _FBLDIAG_OEM_RELEASE_VERSION )
|
|
# error "Error in fbl_diag.c: Source and v_ver.h are inconsistent!"
|
|
#endif
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
* DEFINES
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBL_DIAG_IMPL_TYPE_OUTPUT 1
|
|
#define FBL_DIAG_IMPL_TYPE_STATEBITMAP 2
|
|
#define FBL_DIAG_IMPL_TYPE_SERVICEPROPERTY 3
|
|
#define FBL_DIAG_IMPL_TYPE_SERVICELIST 4
|
|
#define FBL_DIAG_IMPL_TYPE_SERVICELIST_HANDLER 5
|
|
#define FBL_DIAG_IMPL_TYPE_SERVICELIST_ENUM 6
|
|
|
|
#define kDiagInitSequenceNum ((vuint8) 0x01u)
|
|
#define kDiagSegmentOutOfRange ((vuint8) 0xFFu)
|
|
#define kDiagSubparamMask ((vuint8) 0x7Fu)
|
|
|
|
/* Transfer types (used with transferType) */
|
|
# define DOWNLOAD_RAM ((vuint8) 0x10u)
|
|
# define DOWNLOAD_FLASH ((vuint8) 0x40u)
|
|
|
|
/* Allow external definition of RAM state table usage */
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES ) || \
|
|
defined( FBL_DIAG_DISABLE_RAM_STATETABLES )
|
|
#else
|
|
# define FBL_DIAG_ENABLE_RAM_STATETABLES
|
|
#endif
|
|
#define FBL_DIAG_STATE_ARRAYS
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
# define FBL_DIAG_SERVICE_LIST_HANDLES
|
|
#endif
|
|
|
|
#define FBL_DIAG_CHECK_LIST_HANDLES
|
|
|
|
/* Maximum wait time for ECU reset request */
|
|
#if !defined( kCwMaxWaitTimeEcuResetRequest )
|
|
# define kFblDiagMaxWaitTimeEcuResetRequest kFblDiagTimeP2Star
|
|
#else
|
|
# define kFblDiagMaxWaitTimeEcuResetRequest (kCwMaxWaitTimeEcuResetRequest / FBL_REPEAT_CALL_CYCLE)
|
|
#endif
|
|
|
|
/* Macros to access the ecuReset timer value */
|
|
#define TimeoutEcuResetValue() ecuResetTimeout
|
|
#define DecTimeoutEcuResetValue() (ecuResetTimeout--)
|
|
#define ResetEcuResetTimeout() (ecuResetTimeout = (vuint16)(kFblDiagMaxWaitTimeEcuResetRequest/DIAG_CALL_CYCLE))
|
|
#define StopEcuResetTimeout() (ecuResetTimeout = 0)
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
/*
|
|
* Negative return value for FblDiagGetSessionIndex(). This value has to be greater than 0x7F because the SPRMIB bit
|
|
* restricts the value range.
|
|
*/
|
|
# define kDiagSessionNotFound ((vuint8)0xFFu)
|
|
#endif /* FBL_DIAG_ENABLE_SESSION_PARAMETERS */
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
/* Indicator for non-initialized security level index */
|
|
# define kDiagInvalidSecLvlIdx ((vuint8)0xFFu)
|
|
#endif /* FBL_ENABLE_SEC_ADDITIONAL_LEVELS */
|
|
|
|
/* Return values for DID 0xD021 - Current Diagnostic Application */
|
|
#define kFblDiagAppPbl 0x01u
|
|
#define kFblDiagAppSbl 0x02u
|
|
#define kFblDiagAppUnknown 0xFFu
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
/* Define for customer for getting FESN */
|
|
# if !defined( FblDiagGetFesn )
|
|
# define FblDiagGetFesn() fblCommonData.FordElectronicSerialNumber
|
|
# endif
|
|
|
|
/* Dynamic offset calculation macro */
|
|
# define FblDiagCalcDynamicSyncPHeaderOffset(offset) ((offset) - FBL_DIAG_TOKEN_FESN_LEN)
|
|
|
|
/* Defines for token parameter offset */
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
# define FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET 0u
|
|
# define FBL_DIAG_TOKEN_PARAM_CPU_DEST_OFFSET 1u
|
|
# define FBL_DIAG_TOKEN_PARAM_SERVICE_TYPE_OFFSET 2u
|
|
# define FBL_DIAG_TOKEN_PARAM_CRYPTOTYPE_OFFSET 6u
|
|
# define FBL_DIAG_TOKEN_PARAM_PAYLOAD_SIZE_OFFSET 7u
|
|
# define FBL_DIAG_TOKEN_PARAM_FESN_OFFSET 11u
|
|
# define FBL_DIAG_TOKEN_PARAM_SERVERMESSAGEID_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 27u : FblDiagCalcDynamicSyncPHeaderOffset(27u)
|
|
# define FBL_DIAG_TOKEN_PARAM_CMD_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 35u : FblDiagCalcDynamicSyncPHeaderOffset(35u)
|
|
# define FBL_DIAG_TOKEN_PARAM_KEY_INDEX_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 36u : FblDiagCalcDynamicSyncPHeaderOffset(36u)
|
|
# define FBL_DIAG_TOKEN_PARAM_NAME_LENGTH_INDEX_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 37u : FblDiagCalcDynamicSyncPHeaderOffset(37u)
|
|
# define FBL_DIAG_TOKEN_PARAM_NAME_INDEX_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 38u : FblDiagCalcDynamicSyncPHeaderOffset(38u)
|
|
# define FBL_DIAG_TOKEN_PARAM_PAYLOAD_FESN_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 80u : FblDiagCalcDynamicSyncPHeaderOffset(80u)
|
|
# define FBL_DIAG_TOKEN_PARAM_DEVKEY_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 107u : FblDiagCalcDynamicSyncPHeaderOffset(107u)
|
|
# define FBL_DIAG_TOKEN_PARAM_PRODKEY_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 619u : FblDiagCalcDynamicSyncPHeaderOffset(619u)
|
|
# define FBL_DIAG_TOKEN_PARAM_TOKENKEY_OFFSET(token) FblDiagIsTokenFesnRequired(token) ? 1131u : FblDiagCalcDynamicSyncPHeaderOffset(1131u)
|
|
|
|
/* Generic Defines for token handling */
|
|
# define FBL_DIAG_TOKEN_RESBITS_REQ 0x03u
|
|
# define FBL_DIAG_TOKEN_KEYID_REQ 0x04u
|
|
# define FBL_DIAG_TOKEN_FESN_REQ 0x08u
|
|
# define FBL_DIAG_TOKEN_FESN_SHIFT 0x03u
|
|
# define FBL_DIAG_TOKEN_FESN_LEN 8u
|
|
# define FBL_DIAG_TOKEN_MSGID_REQ 0x10u
|
|
# define FBL_DIAG_TOKEN_MOD5_FESN_LEN 3u
|
|
# define FBL_DIAG_TOKEN_CPU_DEST 0u
|
|
# define FBL_DIAG_TOKEN_PROTOCOL_VERSION 0x20u
|
|
# define FBL_DIAG_TOKEN_PROTOCOL_VERSION_MASK 0xE0u
|
|
# define FBL_DIAG_TOKEN_NAME_LENGTH 0x0Bu
|
|
# define FBL_DIAG_TOKEN_NAME "APP_SIGN_SW"
|
|
# define FBL_DIAG_TOKEN_SERVICE_TYPE 0x110u
|
|
# define FBL_DIAG_TOKEN_CRYPTOTYPE 0x0Fu /* Only RSA supported */
|
|
# define FBL_DIAG_TOKEN_PAYLOAD_SIZE_MODE0_4 43u
|
|
# define FBL_DIAG_TOKEN_PAYLOAD_SIZE_MODE5 1606u
|
|
|
|
# define FBL_DIAG_TOKEN_KEY_INDEX_0 0u /* Used for mode 5 tokens */
|
|
# define FBL_DIAG_TOKEN_KEY_INDEX_1 1u /* Used for mode 0-4 tokens */
|
|
# define FBL_DIAG_TOKEN_KEY_EXP_MAX 256u
|
|
|
|
/* Defines Token Handling Commands */
|
|
# define FBL_DIAG_TOKEN_CMD_REVERTPROD 0u
|
|
# define FBL_DIAG_TOKEN_CMD_USEDEVPERM 1u
|
|
# define FBL_DIAG_TOKEN_CMD_USEDEVTEMP 2u
|
|
# define FBL_DIAG_TOKEN_CMD_USEDEVDATE 3u
|
|
# define FBL_DIAG_TOKEN_CMD_USEDEVIGNI 4u
|
|
# define FBL_DIAG_TOKEN_CMD_PROGKEY 5u
|
|
|
|
/* Defines Token Handling Macro */
|
|
# define FblDiagIsTokenProtocolVersionCorrect(token) (((token)[FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET] & FBL_DIAG_TOKEN_PROTOCOL_VERSION_MASK) == FBL_DIAG_TOKEN_PROTOCOL_VERSION)
|
|
# define FblDiagIsTokenKeyIDRequired(token) (((token)[FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET] & FBL_DIAG_TOKEN_KEYID_REQ) == FBL_DIAG_TOKEN_KEYID_REQ)
|
|
# define FblDiagIsTokenMsgIDRequired(token) (((token)[FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET] & FBL_DIAG_TOKEN_MSGID_REQ) == FBL_DIAG_TOKEN_MSGID_REQ)
|
|
# define FblDiagIsTokenFesnRequired(token) (((token)[FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET] & FBL_DIAG_TOKEN_FESN_REQ) == FBL_DIAG_TOKEN_FESN_REQ)
|
|
# define FblDiagIsTokenReserverdBitsSet(token) (((token)[FBL_DIAG_TOKEN_PARAM_SYNCP_ENC_DATA_OFFSET] & FBL_DIAG_TOKEN_RESBITS_REQ) != 0u)
|
|
# define FblDiagGetTokenCPUDestination(token) ((token)[FBL_DIAG_TOKEN_PARAM_CPU_DEST_OFFSET])
|
|
# define FblDiagGetTokenServiceType(token) (((vuint16)(token)[FBL_DIAG_TOKEN_PARAM_SERVICE_TYPE_OFFSET] << 8u) | \
|
|
(vuint16)(token)[FBL_DIAG_TOKEN_PARAM_SERVICE_TYPE_OFFSET + 1u] )
|
|
# define FblDiagGetTokenCryptoType(token) ((token)[FBL_DIAG_TOKEN_PARAM_CRYPTOTYPE_OFFSET])
|
|
# define FblDiagGetTokenCommandType(token) ((token)[FBL_DIAG_TOKEN_PARAM_CMD_OFFSET(token)])
|
|
# define FblDiagGetTokenPayloadSize(token) (((vuint32)(token)[FBL_DIAG_TOKEN_PARAM_PAYLOAD_SIZE_OFFSET] << 24u) | \
|
|
((vuint32)(token)[FBL_DIAG_TOKEN_PARAM_PAYLOAD_SIZE_OFFSET + 1u] << 16u) | \
|
|
((vuint32)(token)[FBL_DIAG_TOKEN_PARAM_PAYLOAD_SIZE_OFFSET + 2u] << 8u) | \
|
|
(vuint32)(token)[FBL_DIAG_TOKEN_PARAM_PAYLOAD_SIZE_OFFSET + 3u])
|
|
# define FblDiagGetTokenTokenNameLength(token) ((vuint8)(token)[FBL_DIAG_TOKEN_PARAM_NAME_LENGTH_INDEX_OFFSET(token)])
|
|
# define FblDiagGetTokenTokenName(token) (&(token)[FBL_DIAG_TOKEN_PARAM_NAME_INDEX_OFFSET(token)])
|
|
# define FblDiagGetTokenFesn(token) (&(token)[FBL_DIAG_TOKEN_PARAM_FESN_OFFSET])
|
|
# define FblDiagGetTokenServerMsgIdPtr(token) (&(token)[FBL_DIAG_TOKEN_PARAM_SERVERMESSAGEID_OFFSET(token)])
|
|
# define FblDiagGetTokenPayloadFesn(token) (&(token)[FBL_DIAG_TOKEN_PARAM_PAYLOAD_FESN_OFFSET(token)])
|
|
# define FblDiagGetTokenKeyIndex(token) ((token)[FBL_DIAG_TOKEN_PARAM_KEY_INDEX_OFFSET(token)])
|
|
/* Define to get the key index from the token */
|
|
# define FblDiagGetTokenDevKeyIndex(token) (&(token)[FBL_DIAG_TOKEN_PARAM_DEVKEY_OFFSET(token)])
|
|
# define FblDiagGetTokenProdKeyIndex(token) (&(token)[FBL_DIAG_TOKEN_PARAM_PRODKEY_OFFSET(token)])
|
|
# define FblDiagGetTokenTokenKeyIndex(token) (&(token)[FBL_DIAG_TOKEN_PARAM_TOKENKEY_OFFSET(token)])
|
|
|
|
# endif /* FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING */
|
|
#endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* State handling ************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
#define SPLIT_SHORT(id) ((vuint8)(((id) >> 8u) & 0xFFu)), ((vuint8)((id) & 0xFFu))
|
|
|
|
# define STATE_CHECK_COUNT 2u
|
|
# define STATE_ADDCLR_COUNT 3u
|
|
#define STATE_COUNT (STATE_CHECK_COUNT + STATE_ADDCLR_COUNT)
|
|
|
|
/* State array build macros */
|
|
#define STATE_ARRAYENTRY(mask, idx) ((tStateBitmap)(((mask) >> ((idx) * STATE_BITS)) & kDiagStateMaskAll))
|
|
#if ( STATECHECK_ARRAYSIZE == 1u )
|
|
# define STATE_BUILDARRAYENTRIES(mask) STATE_ARRAYENTRY(mask, 0u)
|
|
#endif
|
|
#if ( STATECHECK_ARRAYSIZE == 2u )
|
|
# define STATE_BUILDARRAYENTRIES(mask) STATE_ARRAYENTRY(mask, 0u), STATE_ARRAYENTRY(mask, 1u)
|
|
#endif
|
|
#if ( STATECHECK_ARRAYSIZE == 3u )
|
|
# define STATE_BUILDARRAYENTRIES(mask) STATE_ARRAYENTRY(mask, 0u), STATE_ARRAYENTRY(mask, 1u), STATE_ARRAYENTRY(mask, 2u)
|
|
#endif
|
|
#if ( STATECHECK_ARRAYSIZE == 4u )
|
|
# define STATE_BUILDARRAYENTRIES(mask) STATE_ARRAYENTRY(mask, 0u), STATE_ARRAYENTRY(mask, 1u), STATE_ARRAYENTRY(mask, 2u), STATE_ARRAYENTRY(mask, 3u)
|
|
#endif
|
|
#if ( STATECHECK_ARRAYSIZE > 4u )
|
|
# error "Invalid array size for state check!"
|
|
#endif
|
|
|
|
#define STATE_BUILDARRAY(mask) { STATE_BUILDARRAYENTRIES(mask) }
|
|
|
|
/* State masks and access macros */
|
|
#define kDiagStateMaskAllLong STATE_MULTIMASKLONG(0u, ((STATECHECK_ARRAYSIZE * STATE_BITS) - 1u))
|
|
|
|
#define kDiagStateMask(state) STATE_MASKLONG(state)
|
|
|
|
#define SetDiagState(state) STATE_SET(fblStates, state)
|
|
#define ClrDiagState(state) STATE_CLR(fblStates, state)
|
|
|
|
#define kDiagStateNone (0x00uL)
|
|
|
|
#define ClrDiagSession() STATE_MULTICLR(fblStates, kDiagStateIdxSessionDefault, kDiagStateIdxSessionProgramming)
|
|
|
|
#define kDiagStateSessionDefault kDiagStateMask(kDiagStateIdxSessionDefault)
|
|
#define SetDiagDefaultDiagSession() { \
|
|
ClrDiagSession(); \
|
|
SetDiagState(kDiagStateIdxSessionDefault); \
|
|
SetDiagSessionType(kDiagSubDefaultSession); \
|
|
}
|
|
|
|
#define kDiagStateSessionProgramming kDiagStateMask(kDiagStateIdxSessionProgramming)
|
|
#define SetDiagProgrammingSession() { \
|
|
ClrDiagSession(); \
|
|
SetDiagState(kDiagStateIdxSessionProgramming); \
|
|
SetDiagSessionType(kDiagSubProgrammingSession); \
|
|
}
|
|
|
|
#define kDiagStateSessionDefaultProgramming (kDiagStateSessionDefault | kDiagStateSessionProgramming)
|
|
#define kDiagStateSessionAll kDiagStateSessionDefaultProgramming
|
|
|
|
#define kDiagStateSecurityKey01 kDiagStateMask(kDiagStateIdxSecurityKey01)
|
|
#define GetSecurityKeyAllowed() GetDiagState(kDiagStateIdxSecurityKey01)
|
|
#define SetSecurityKeyAllowed() SetDiagState(kDiagStateIdxSecurityKey01)
|
|
#define ClrSecurityKeyAllowed() ClrDiagState(kDiagStateIdxSecurityKey01)
|
|
|
|
#define kDiagStateSecurityKeyAll (kDiagStateSecurityKey01)
|
|
|
|
#define kDiagStateSecurityAccess01 kDiagStateMask(kDiagStateIdxSecurityAccess01)
|
|
#define GetSecurityAccess01() GetDiagState(kDiagStateIdxSecurityAccess01)
|
|
#define SetSecurityAccess01() SetDiagState(kDiagStateIdxSecurityAccess01)
|
|
#define ClrSecurityAccess01() ClrDiagState(kDiagStateIdxSecurityAccess01)
|
|
#define SetCurrentSecLvl(secLvl) diagCurrentSecLvl = (secLvl)
|
|
|
|
#define kDiagStateSecurityAccessAll (kDiagStateSecurityAccess01)
|
|
|
|
/* Security access states are used in state machine definition */
|
|
#define kDiagStateSecurityAccessDelay01 kDiagStateNone
|
|
|
|
#define kDiagStateSecurityAccessDelayAll (kDiagStateSecurityAccessDelay01)
|
|
#if !defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
# define kServiceCheckListSubFctSecCheck kServiceCheckListSubFctCheck
|
|
#endif
|
|
|
|
#define kDiagStateFunctionalRequest kDiagStateMask(kDiagStateIdxFunctionalRequest)
|
|
#define GetFunctionalRequest() GetDiagState(kDiagStateIdxFunctionalRequest)
|
|
#define SetFunctionalRequest() SetDiagState(kDiagStateIdxFunctionalRequest)
|
|
#define ClrFunctionalRequest() ClrDiagState(kDiagStateIdxFunctionalRequest)
|
|
|
|
|
|
#define kDiagStateServiceInProgress kDiagStateMask(kDiagStateIdxServiceInProgress)
|
|
#define SetServiceInProgress() SetDiagState(kDiagStateIdxServiceInProgress)
|
|
#define ClrServiceInProgress() ClrDiagState(kDiagStateIdxServiceInProgress)
|
|
|
|
#define kDiagStateTpConfirmationFlag kDiagStateMask(kDiagStateIdxTpConfirmationFlag)
|
|
#define GetTpConfirmationFlag() GetDiagState(kDiagStateIdxTpConfirmationFlag)
|
|
#define SetTpConfirmationFlag() SetDiagState(kDiagStateIdxTpConfirmationFlag)
|
|
#define ClrTpConfirmationFlag() ClrDiagState(kDiagStateIdxTpConfirmationFlag)
|
|
|
|
#define kDiagStateDiagIndication kDiagStateMask(kDiagStateIdxDiagIndication)
|
|
#define GetDiagIndication() GetDiagState(kDiagStateIdxDiagIndication)
|
|
#define SetDiagIndication() SetDiagState(kDiagStateIdxDiagIndication)
|
|
#define ClrDiagIndication() ClrDiagState(kDiagStateIdxDiagIndication)
|
|
|
|
#define kDiagStateSuppressPosRspMsg kDiagStateMask(kDiagStateIdxSuppressPosRspMsg)
|
|
#define GetSuppressPosRspMsg() GetDiagState(kDiagStateIdxSuppressPosRspMsg)
|
|
#define SetSuppressPosRspMsg() SetDiagState(kDiagStateIdxSuppressPosRspMsg)
|
|
#define ClrSuppressPosRspMsg() ClrDiagState(kDiagStateIdxSuppressPosRspMsg)
|
|
|
|
#define kDiagStateResponseProcessing kDiagStateMask(kDiagStateIdxResponseProcessing)
|
|
#define SetResponseProcessing() SetDiagState(kDiagStateIdxResponseProcessing)
|
|
#define ClrResponseProcessing() ClrDiagState(kDiagStateIdxResponseProcessing)
|
|
|
|
#define kDiagStateRcrRpInProgress kDiagStateMask(kDiagStateIdxRcrRpInProgress)
|
|
#define SetRcrRpInProgress() SetDiagState(kDiagStateIdxRcrRpInProgress)
|
|
#define ClrRcrRpInProgress() ClrDiagState(kDiagStateIdxRcrRpInProgress)
|
|
|
|
#define kDiagStateWaitForRcrRpConf kDiagStateMask(kDiagStateIdxWaitForRcrRpConf)
|
|
#define GetWaitForRcrRpConf() GetDiagState(kDiagStateIdxWaitForRcrRpConf)
|
|
#define SetWaitForRcrRpConf() SetDiagState(kDiagStateIdxWaitForRcrRpConf)
|
|
#define ClrWaitForRcrRpConf() ClrDiagState(kDiagStateIdxWaitForRcrRpConf)
|
|
|
|
#define kDiagStateMemDriverInitialized kDiagStateMask(kDiagStateIdxMemDriverInitialized)
|
|
#define SetMemDriverInitialized() SetDiagState(kDiagStateIdxMemDriverInitialized)
|
|
#define ClrMemDriverInitialized() ClrDiagState(kDiagStateIdxMemDriverInitialized)
|
|
|
|
#define kDiagStateTransferDataAllowed kDiagStateMask(kDiagStateIdxTransferDataAllowed)
|
|
#define GetTransferDataAllowed() GetDiagState(kDiagStateIdxTransferDataAllowed)
|
|
#define SetTransferDataAllowed() SetDiagState(kDiagStateIdxTransferDataAllowed)
|
|
#define ClrTransferDataAllowed() ClrDiagState(kDiagStateIdxTransferDataAllowed)
|
|
|
|
#define kDiagStateTransferDataSucceeded kDiagStateMask(kDiagStateIdxTransferDataSucceeded)
|
|
#define GetTransferDataSucceeded() GetDiagState(kDiagStateIdxTransferDataSucceeded)
|
|
#define SetTransferDataSucceeded() SetDiagState(kDiagStateIdxTransferDataSucceeded)
|
|
#define ClrTransferDataSucceeded() ClrDiagState(kDiagStateIdxTransferDataSucceeded)
|
|
|
|
#define kDiagStateFirstDownloadReq kDiagStateMask(kDiagStateIdxFirstDownloadReq)
|
|
#define GetFirstDownloadReq() GetDiagState(kDiagStateIdxFirstDownloadReq)
|
|
#define SetFirstDownloadReq() SetDiagState(kDiagStateIdxFirstDownloadReq)
|
|
#define ClrFirstDownloadReq() ClrDiagState(kDiagStateIdxFirstDownloadReq)
|
|
|
|
#define kDiagStateEraseMemorySucceeded kDiagStateMask(kDiagStateIdxEraseMemorySucceeded)
|
|
#define GetEraseMemorySucceeded() GetDiagState(kDiagStateIdxEraseMemorySucceeded)
|
|
#define SetEraseMemorySucceeded() SetDiagState(kDiagStateIdxEraseMemorySucceeded)
|
|
#define ClrEraseMemorySucceeded() ClrDiagState(kDiagStateIdxEraseMemorySucceeded)
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
#define kDiagStateTransferDataUpload kDiagStateMask(kDiagStateIdxTransferDataUpload)
|
|
#define GetTransferDataUpload() GetDiagState(kDiagStateIdxTransferDataUpload)
|
|
#define SetTransferDataUpload() SetDiagState(kDiagStateIdxTransferDataUpload)
|
|
#define ClrTransferDataUpload() ClrDiagState(kDiagStateIdxTransferDataUpload)
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
|
|
|
|
#define kDiagStateResetMsgConfirmed kDiagStateMask(kDiagStateIdxResetMsgConfirmed)
|
|
#define GetResetMsgConfirmed() GetDiagState(kDiagStateIdxResetMsgConfirmed)
|
|
#define SetResetMsgConfirmed() SetDiagState(kDiagStateIdxResetMsgConfirmed)
|
|
#define ClrResetMsgConfirmed() ClrDiagState(kDiagStateIdxResetMsgConfirmed)
|
|
|
|
#define kDiagStateEcuResetFctFinished kDiagStateMask(kDiagStateIdxEcuResetFctFinished)
|
|
#define GetEcuResetFctFinished() GetDiagState(kDiagStateIdxEcuResetFctFinished)
|
|
#define SetEcuResetFctFinished() SetDiagState(kDiagStateIdxEcuResetFctFinished)
|
|
#define ClrEcuResetFctFinished() ClrDiagState(kDiagStateIdxEcuResetFctFinished)
|
|
|
|
#define kDiagStateWaitEcuReset kDiagStateMask(kDiagStateIdxWaitEcuReset)
|
|
#define SetWaitEcuReset() { \
|
|
SetDiagState(kDiagStateIdxWaitEcuReset); \
|
|
ResetEcuResetTimeout(); \
|
|
}
|
|
#define ClrWaitEcuReset() { \
|
|
ClrDiagState(kDiagStateWaitEcuReset); \
|
|
ClrDiagState(kDiagStateResetMsgConfirmed); \
|
|
ClrDiagState(kDiagStateEcuResetFctFinished); \
|
|
StopEcuResetTimeout(); \
|
|
}
|
|
|
|
#define kDiagStateDiagBufferLocked kDiagStateMask(kDiagStateIdxDiagBufferLocked)
|
|
#define SetDiagBufferLocked() SetDiagState(kDiagStateIdxDiagBufferLocked)
|
|
#define ClrDiagBufferLocked() ClrDiagState(kDiagStateIdxDiagBufferLocked)
|
|
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# define kDiagStateDiagDevelopmentKey kDiagStateMask(kDiagStateIdxDiagDevelopmentKey)
|
|
# define SetDiagDevelopmentKey() SetDiagState(kDiagStateIdxDiagDevelopmentKey)
|
|
# define ClrDiagDevelopmentKey() ClrDiagState(kDiagStateIdxDiagDevelopmentKey)
|
|
#endif
|
|
|
|
#define kDiagStateProcessingDone kDiagStateMask(kDiagStateIdxProcessingDone)
|
|
#define GetProcessingDone() GetDiagState(kDiagStateIdxProcessingDone)
|
|
#define SetProcessingDone() SetDiagState(kDiagStateIdxProcessingDone)
|
|
#define ClrProcessingDone() ClrDiagState(kDiagStateIdxProcessingDone)
|
|
|
|
#define kDiagStateLockedByInit kDiagStateMask(kDiagStateIdxLockedByInit)
|
|
#define GetLockedByInit() GetDiagState(kDiagStateIdxLockedByInit)
|
|
#define SetLockedByInit() SetDiagState(kDiagStateIdxLockedByInit)
|
|
#define ClrLockedByInit() ClrDiagState(kDiagStateIdxLockedByInit)
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
# define SetDiagSessionType(type) (currentDiagSessionIndex = FblDiagGetSessionIndex(type))
|
|
# define GetDiagSessionType() (kDiagSessionParameters[currentDiagSessionIndex].sessionType)
|
|
# define GetDiagSessionTimingP2() (kDiagSessionParameters[currentDiagSessionIndex].p2Timing)
|
|
# define GetDiagSessionTimingP2Star() (kDiagSessionParameters[currentDiagSessionIndex].p2StarTiming)
|
|
#else
|
|
# define SetDiagSessionType(type) (currentDiagSessionType = (type))
|
|
# define GetDiagSessionType() (currentDiagSessionType)
|
|
# define GetDiagSessionTimingP2() (kDiagSessionTimingP2)
|
|
# define GetDiagSessionTimingP2Star() (kDiagSessionTimingP2Star)
|
|
#endif /* FBL_DIAG_ENABLE_SESSION_PARAMETERS */
|
|
|
|
|
|
/* Helper macro to get number of array entries */
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
|
|
/*****************************************************************************/
|
|
/* Definitions for the state machine *****************************************/
|
|
/*****************************************************************************/
|
|
|
|
#define kDiagRqlUnlimited (0xFFFFu)
|
|
|
|
#define kDiagNoSubServices (V_MEMROM1 tServiceList V_MEMROM2 V_MEMROM3 *)V_NULL
|
|
#define kDiagNoCheckList (tServiceCheckList *)V_NULL
|
|
|
|
#define kDiagNoServiceProp (ptServiceProp)V_NULL
|
|
|
|
/* Typedefs and structures for internal use **********************************/
|
|
|
|
/* State machine */
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
typedef V_MEMRAM1 struct tagServiceProp V_MEMRAM2 V_MEMRAM3 * ptServiceProp;
|
|
#else
|
|
typedef V_MEMROM1 struct tagServiceProp V_MEMROM2 V_MEMROM3 * ptServiceProp;
|
|
#endif
|
|
|
|
typedef struct tagServiceCheck
|
|
{
|
|
vuint8 checkHandlerIdx;
|
|
vuint8 NRC;
|
|
vuint8 errorHandlerIdx;
|
|
} tServiceCheck;
|
|
|
|
typedef struct
|
|
{
|
|
V_MEMROM1 struct tagServiceCheck V_MEMROM2 V_MEMROM3 * list;
|
|
vuint8 count;
|
|
} tServiceCheckList;
|
|
|
|
typedef struct tagServiceList
|
|
{
|
|
ptServiceProp list;
|
|
tCwDataLengthType bufPos;
|
|
vuint8 idSize;
|
|
vuint8 count;
|
|
} tServiceList;
|
|
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
# define FBL_DIAG_STATE_SET 0
|
|
# define FBL_DIAG_STATE_UNSET 1
|
|
# define FBL_DIAG_STATE_ADD 2
|
|
# define FBL_DIAG_STATE_CLR 3
|
|
# define FBL_DIAG_STATE_CLRFAIL 4
|
|
|
|
# define stateSet states[FBL_DIAG_STATE_SET]
|
|
# define stateUnset states[FBL_DIAG_STATE_UNSET]
|
|
# define stateAdd states[FBL_DIAG_STATE_ADD]
|
|
# define stateClr states[FBL_DIAG_STATE_CLR]
|
|
# define stateClrFail states[FBL_DIAG_STATE_CLRFAIL]
|
|
#endif
|
|
|
|
typedef struct tagServiceProp
|
|
{
|
|
V_MEMROM1 struct tagServiceList V_MEMROM2 V_MEMROM3 * subServices;
|
|
V_MEMROM1 vuint8 V_MEMROM2 V_MEMROM3 * serviceId;
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
#else
|
|
V_MEMROM1 tServiceCheckList V_MEMROM2 V_MEMROM3 * checks;
|
|
#endif
|
|
vuint16 minLength;
|
|
vuint16 maxLength;
|
|
#if defined( FBL_DIAG_STATE_ARRAYS ) && \
|
|
( STATE_COUNT > 0 )
|
|
tStateBitmap states[STATE_COUNT][STATECHECK_ARRAYSIZE];
|
|
#else
|
|
tStateBitmap stateSet[STATECHECK_ARRAYSIZE];
|
|
tStateBitmap stateUnset[STATECHECK_ARRAYSIZE];
|
|
tStateBitmap stateAdd[STATECHECK_ARRAYSIZE];
|
|
tStateBitmap stateClr[STATECHECK_ARRAYSIZE];
|
|
tStateBitmap stateClrFail[STATECHECK_ARRAYSIZE];
|
|
#endif
|
|
vuint8 mainHandlerIdx;
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
vuint8 checkListIdx;
|
|
#endif
|
|
} tServiceProp;
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
typedef struct
|
|
{
|
|
# if defined( FBL_DIAG_SERVICE_LIST_HANDLES )
|
|
# else
|
|
V_MEMROM1 struct tagServiceList V_MEMROM2 V_MEMROM3 * subServices;
|
|
# endif
|
|
V_MEMROM1 vuint8 V_MEMROM2 V_MEMROM3 * serviceId;
|
|
# if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
# else
|
|
V_MEMROM1 tServiceCheckList V_MEMROM2 V_MEMROM3 * checks;
|
|
# endif
|
|
vuint16 minLength;
|
|
vuint16 maxLength;
|
|
vuint8 stateUsage;
|
|
vuint8 mainHandlerIdx;
|
|
# if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
vuint8 checkListIdx;
|
|
# endif
|
|
# if defined( FBL_DIAG_SERVICE_LIST_HANDLES )
|
|
vuint8 subServicesHandler;
|
|
# endif
|
|
} tServicePropROM;
|
|
#endif
|
|
|
|
#define FBL_DIAG_CHECK_HANDLER(name) tFblResult name( const V_MEMRAM1 tServiceProp V_MEMRAM2 V_MEMRAM3 * properties, \
|
|
V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, \
|
|
tCwDataLengthType length, tCwDataLengthType position, \
|
|
V_MEMRAM1 ptServiceProp V_MEMRAM2 V_MEMRAM3 * result )
|
|
#define FBL_DIAG_ERROR_HANDLER(name) tFblResult name( const V_MEMRAM1 tServiceProp V_MEMRAM2 V_MEMRAM3 *properties, \
|
|
V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, \
|
|
tCwDataLengthType diagReqDataLen )
|
|
#define FBL_DIAG_MAIN_HANDLER(name) tFblResult name( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, \
|
|
tCwDataLengthType diagReqDataLen )
|
|
|
|
typedef FBL_DIAG_CHECK_HANDLER((*tFblDiagCheckHandler));
|
|
typedef FBL_DIAG_ERROR_HANDLER((*tFblDiagErrorHandler));
|
|
typedef FBL_DIAG_MAIN_HANDLER((*tFblDiagMainHandler));
|
|
|
|
/* Check handler */
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
typedef struct
|
|
{
|
|
vuint8 sessionType; /* Diagnostic Session Type */
|
|
vuint16 p2Timing; /* P2 Timing Value [ms] */
|
|
vuint16 p2StarTiming; /* P2* Timing Value [ms] / 10 */
|
|
} tDiagSessionParameters;
|
|
#endif /* FBL_ENABLE_SESSION_PARAMETERS */
|
|
|
|
/***********************************************************************************************************************
|
|
* GLOBAL DATA
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBLDIAG_START_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* Data buffer for diagnostic data */
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * V_MEMRAM1 V_MEMRAM2 DiagBuffer;
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 diagErrorCode; /* Diagnostic error code */
|
|
V_MEMRAM0 V_MEMRAM1 tCwDataLengthType V_MEMRAM2 DiagDataLength; /* Stores number of received data */
|
|
V_MEMRAM0 V_MEMRAM1_NEAR vuint16 V_MEMRAM2_NEAR P2Timeout; /* P2 timeout value */
|
|
V_MEMRAM0 V_MEMRAM1_NEAR vuint16 V_MEMRAM2_NEAR testerPresentTimeout; /* Timer value for TesterPresent timeout */
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 diagResponseFlag; /* Flag to enable/suppress diagnostic response */
|
|
V_MEMRAM0 V_MEMRAM1_NEAR vuint8 V_MEMRAM2_NEAR diagServiceCurrent; /* Currently processed diag service ID */
|
|
V_MEMRAM0 V_MEMRAM1_NEAR tStateBitmap V_MEMRAM2_NEAR fblStates[STATE_INDEX(kDiagNumberOfStates - 1u) + 1u]; /* State bitmap array */
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 diagCurrentSecLvl; /* Current security level */
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 diagRequestedSecLvlIdx; /* Table index of currently requested security level */
|
|
#endif
|
|
#if defined( FBL_ENABLE_SLEEPMODE )
|
|
V_MEMRAM0 V_MEMRAM1 vuint32 V_MEMRAM2 sleepCounter; /* Counter, determines when to sleep */
|
|
#endif
|
|
|
|
#if defined( FBL_ENABLE_DEBUG_STATUS )
|
|
/* Variables for error status reporting */ /* PRQA S 1514 6 */ /* MD_FblDiag_1514 */
|
|
V_MEMRAM0 V_MEMRAM1 vuint16 V_MEMRAM2 errStatErrorCode; /* Error status */
|
|
V_MEMRAM0 V_MEMRAM1 vuint16 V_MEMRAM2 errStatFblStates; /* FBL state flag */
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 errStatLastServiceId; /* Last received service identifier */
|
|
V_MEMRAM0 V_MEMRAM1 vuint8 V_MEMRAM2 errStatFlashDrvVersion[3]; /* Flash driver version information */
|
|
V_MEMRAM0 V_MEMRAM1 vuint16 V_MEMRAM2 errStatFlashDrvErrorCode; /* Flash driver error code */
|
|
V_MEMRAM0 V_MEMRAM1 tBlockDescriptor V_MEMRAM2 errStatDescriptor; /* Error status block descriptor */
|
|
#endif
|
|
|
|
#define FBLDIAG_STOP_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
|
|
# define FBLDIAG_START_SEC_CONST
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
V_MEMROM0 V_MEMROM1 tDiagSecAccessParams V_MEMROM2 kDiagSecAccessParams[] =
|
|
{
|
|
{ kDiagSecLevelFlash, kSecSeedLength, kSecKeyLength }
|
|
};
|
|
|
|
# define FBLDIAG_STOP_SEC_CONST
|
|
# include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
#endif /* FBL_ENABLE_SEC_ADDITIONAL_LEVELS */
|
|
|
|
/***********************************************************************************************************************
|
|
* LOCAL DATA
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBLDIAG_START_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* PRQA S 3218 TAG_FblDiag_3218_1 */ /* MD_FblDiag_3218 */
|
|
|
|
/* Temporary data used during download in TransferData */
|
|
V_MEMRAM0 static V_MEMRAM1 tDiagSegmentList V_MEMRAM2 diagSegmentList; /* Complete list of download segments */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 currentSegment; /* Index of currently processed download segment */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 currentBlock; /* Index of currently processed download block */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 lastErasedBlock;
|
|
V_MEMRAM0 static V_MEMRAM1 tBlockHeader V_MEMRAM2 blockHeader[FBL_LBT_BLOCK_COUNT]; /* Structure with runtime information about logical blocks */
|
|
V_MEMRAM0 static V_MEMRAM1 tFblDiagAddr V_MEMRAM2 transferAddress; /* Actual transfer address */
|
|
V_MEMRAM0 static V_MEMRAM1 tFblLength V_MEMRAM2 transferRemainder; /* Number of remaining transfer bytes */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 transferType; /* Download into RAM/Flash or upload */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 expectedSequenceCnt; /* Block sequence counter */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 currentSequenceCnt; /* Current Block sequence counter */
|
|
V_MEMRAM0 static V_MEMRAM1_NEAR vuint16 V_MEMRAM2_NEAR ecuResetTimeout; /* Timeout for EcuReset request (CW) */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 dataFormatId; /* Combined encryption and compression method */
|
|
V_MEMRAM0 static V_MEMRAM1 tFblLength V_MEMRAM2 totalProgramLength; /* Total number of programmed bytes */
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 diagRequestedSecLvl; /* Currently requested security level (via seed) */
|
|
#endif
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
/* Internal index of the active diagnostic session (table kDiagSessionParameters) */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 currentDiagSessionIndex;
|
|
#else
|
|
/* Type of the active diagnostic session according to the SessionControl sub-function parameter */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 currentDiagSessionType;
|
|
#endif
|
|
|
|
#define FBLDIAG_STOP_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* State check masks */
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskSessions[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateSessionAll);
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskFunctional[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateFunctionalRequest);
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskSecurityAccess[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateSecurityAccess01);
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskSequenceError[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateSecurityKey01 | kDiagStateTransferDataAllowed);
|
|
/* PRQA S 2790, 3494 1 */ /* MD_FblDiag_2790_kDiagStateMaskAllLong, MD_FblDiag_ConstValue */
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskGeneralConditions[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateMaskAllLong);
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateMaskReset[STATECHECK_ARRAYSIZE] = STATE_BUILDARRAY(kDiagStateNone);
|
|
|
|
#define FBLDIAG_STOP_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* Concatenation of service properties */
|
|
V_MEMRAM0 static V_MEMRAM1_NEAR tServiceProp V_MEMRAM2_NEAR serviceProperties;
|
|
/* Result of service execution */
|
|
V_MEMRAM0 static V_MEMRAM1_NEAR tFblResult V_MEMRAM2_NEAR serviceResult;
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
/* maxNumberOfBlockLength is a 12 bit value that determines the maximum size */
|
|
/* of a block of data that can be transferred */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint16 V_MEMRAM2 maxNumberOfBlockLength;
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
|
|
#define FBLDIAG_STOP_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
V_MEMROM0 static V_MEMROM1 tDiagSessionParameters V_MEMROM2 kDiagSessionParameters[] =
|
|
{
|
|
/* Default Session */
|
|
{ kDiagSubDefaultSession, 50, 500 },
|
|
/* Programming Session */
|
|
{ kDiagSubProgrammingSession, kDiagSessionTimingP2, kDiagSessionTimingP2Star }
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 kDiagNumberOfSessions = sizeof(kDiagSessionParameters) / sizeof(tDiagSessionParameters);
|
|
#endif /* FBL_DIAG_ENABLE_SESSION_PARAMETERS */
|
|
|
|
#define FBLDIAG_STOP_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
/* SHA256 + CRC16 */
|
|
# define FBL_DIAG_VERIFY_BUFFER_SIZE (SEC_VERIFY_CLASS_DDD_DIGEST_SIZE + SEC_SIZE_CHECKSUM_CRC)
|
|
# define FBL_DIAG_CRC_OFFSET SEC_VERIFY_CLASS_DDD_CHECKSUM_OFFSET
|
|
#else
|
|
/* CRC16 */
|
|
# define FBL_DIAG_VERIFY_BUFFER_SIZE (SEC_VERIFY_CLASS_DDD_DIGEST_SIZE)
|
|
# define FBL_DIAG_CRC_OFFSET 0u
|
|
#endif
|
|
|
|
#define FBLDIAG_START_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_PIPELINED )
|
|
/* Parameters for pipelined signature calculation */
|
|
V_MEMRAM0 static V_MEMRAM1 SecM_SignatureParamType V_MEMRAM2 pipeVerifyParam;
|
|
# if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
V_MEMRAM0 static V_MEMRAM1 SecM_SignatureParamType V_MEMRAM2 pipeVerifyParamCrc;
|
|
# endif
|
|
/* Used to store hash value and optionally security module context */ /* PRQA S 3678 1 */ /* MD_FblDiag_3678 */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 pipeVerifyBuf[FBL_DIAG_VERIFY_BUFFER_SIZE];
|
|
V_MEMRAM0 static V_MEMRAM1 vuint32 V_MEMRAM2 pipeVerifyLength;
|
|
# if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
V_MEMRAM0 static V_MEMRAM1 SecM_CRCParamType V_MEMRAM2 pipeVerifyCrc;
|
|
V_MEMRAM0 static V_MEMRAM1 vuint32 V_MEMRAM2 pipeVerifyLengthCrc;
|
|
# endif
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_PIPELINED */
|
|
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_OUTPUT )
|
|
V_MEMRAM0 static V_MEMRAM1 SecM_VerifyParamType V_MEMRAM2 verifyParam;
|
|
V_MEMRAM0 static V_MEMRAM1 FL_SegmentInfoType V_MEMRAM2 verifySegmentInfo[1];
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_OUTPUT */
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
V_MEMRAM0 static V_MEMRAM1 vuint16 V_MEMRAM2 verifyTokenSignLength;
|
|
#endif
|
|
|
|
/* Output buffer which keeps the verification result from FblMemBlockVerify (RequestTransferExit, CheckProgDep) */
|
|
V_MEMRAM0 static V_MEMRAM1 vuint8 V_MEMRAM2 verifyOutputBuf[FBL_DIAG_VERIFY_BUFFER_SIZE];
|
|
|
|
#define FBLDIAG_STOP_SEC_VAR
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
* PROTOTYPES
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBLDIAG_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
static void FblDiagSegmentInit( void );
|
|
static vuint8 FblDiagSegmentNext( tFblDiagAddr segAddr, tFblLength segLength, vuint8 blockIdx );
|
|
static tCwDataLengthType FblDiagGetMaxTransferDataBlockLength(void);
|
|
static void DiagDiscardReception( void );
|
|
static tFblResult FblInitMemoryDriver( void );
|
|
static void FblDeinitMemoryDriver( void );
|
|
static void FblDiagDeinit( void );
|
|
|
|
#define FBLDIAG_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_RAMCODE_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
static void DiagResetResponseHandling( void );
|
|
#define FBLDIAG_RAMCODE_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
static V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * FblDiagMemGetActiveBuffer(void);
|
|
|
|
/*-- Service property functions ---------------------------------------------*/
|
|
static void FblDiagSetState (const V_MEMRAM1 tStateBitmap V_MEMRAM2 V_MEMRAM3 * state);
|
|
static void FblDiagClrState (const V_MEMRAM1 tStateBitmap V_MEMRAM2 V_MEMRAM3 * state);
|
|
static void FblDiagRetainState (V_MEMROM1 tStateBitmap V_MEMROM2 V_MEMROM3 * state);
|
|
static void FblDiagInitStateTables ( void );
|
|
static void FblDiagSetProperties(ptServiceProp source, tServiceProp * destination);
|
|
static void FblDiagMergeProperties(ptServiceProp source, tServiceProp * merge);
|
|
static void FblDiagDispatch ( void );
|
|
|
|
static tFblResult FblDiagSecAccessSeed(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen, vuint8 secLevel);
|
|
static tFblResult FblDiagSecAccessKey(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen, vuint8 secLevel);
|
|
|
|
/*-- Service check functions ------------------------------------------------*/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagSearchService);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSession);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckLength);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckFunctional);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSuppressPosRsp);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecurityAccess);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSequenceError);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckGeneralConditions);
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckTransferMode);
|
|
#endif
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagSearchSecService);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecLength);
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecSequenceError);
|
|
#endif
|
|
|
|
/*-- Diagnostic error handler service functions -----------------------------*/
|
|
#if defined( FBL_ENABLE_USERSERVICE )
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerServiceNotFound);
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerSubFunctionNotFound);
|
|
#endif
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerExecMainHandler);
|
|
|
|
/*-- Diagnostic main handler service functions ------------------------------*/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerDefaultSession);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerProgrammingSession);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTesterPresent);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerEcuReset);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcEraseMemory);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcCheckProgDep);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcActivateSbl);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcCheckValidApp);
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcTokenDownload);
|
|
# endif
|
|
#endif
|
|
#if defined( FBL_DIAG_ENABLE_UPDATE_SEC_BYTES )
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcUpdateSecBytes);
|
|
#endif
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerSecAccessSeed);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerSecAccessKey);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestDownload);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTransferDataDownload);
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestUpload);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTransferDataUpload);
|
|
#endif
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestTransferExit);
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerReadDataById);
|
|
#if defined( FBL_DIAG_ENABLE_WRITE_DATA_BY_IDENTIFIER )
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerWriteDataById);
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERROUTINE )
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRoutineControl);
|
|
#endif
|
|
|
|
/*-- Ford specific functions --------------------------------------------*/
|
|
static void FblDiagInitDownloadSequence( void );
|
|
static tFblResult FblDiagPrepareDidResponse( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pbDiagBuffer, vuint16 reqDid, tDidDataPtr didData, vuint16 didLen );
|
|
static tFblResult FblDiagCheckState( const V_MEMRAM1 tServiceProp V_MEMRAM2 V_MEMRAM3 *properties, V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pbDiagBuffer, tCwDataLengthType length, tCwDataLengthType position, V_MEMROM1 tStateBitmap V_MEMROM2 * stateMask, ptServiceProp * result);
|
|
static tFblResult FblDiagSessionTransition( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen );
|
|
static void FblDiagSessionControlParamInit( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen );
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
static vuint8 FblDiagGetSessionIndex( vuint8 diagnosticSessionType );
|
|
#endif
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_OUTPUT )
|
|
static SecM_StatusType FblDiagVerification( V_MEMRAM1 SecM_VerifyParamType V_MEMRAM2 V_MEMRAM3 * verifyPar );
|
|
#endif
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_PIPELINED ) && ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
static SecM_StatusType FblDiagVerifySignature( V_MEMRAM1 SecM_SignatureParamType V_MEMRAM2 V_MEMRAM3 * pVerifyParam );
|
|
#endif
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
static tTokenHdlResult FblDiagTokenLengthCheck(vuint8 cmdType, vuint16 tokenLength);
|
|
static tTokenHdlResult FblDiagTokenKeyProcessing(vuint8 cmdType, V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBufferPtr);
|
|
static tTokenHdlResult FblDiagValidateToken( const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf );
|
|
static tFblResult FblDiagCheckServerMessageId( const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf );
|
|
static tTokenHdlResult FblDiagTokenCallout( vuint8 cmdType, const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf, vuint16 tokenLength );
|
|
# endif
|
|
#endif
|
|
|
|
#define FBLDIAG_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/*****************************************************************************/
|
|
/*** State machine configuration *********************************************/
|
|
/*****************************************************************************/
|
|
|
|
/* The handler tables */
|
|
enum
|
|
{
|
|
kServiceCheckHandlerSearchService
|
|
,kServiceCheckHandlerCheckSession
|
|
,kServiceCheckHandlerCheckLength
|
|
,kServiceCheckHandlerCheckFunctional
|
|
,kServiceCheckHandlerCheckSuppressPosRsp
|
|
,kServiceCheckHandlerCheckSecurityAccess
|
|
,kServiceCheckHandlerCheckSequenceError
|
|
,kServiceCheckHandlerCheckGeneralConditions
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,kServiceCheckHandlerTransferMode
|
|
#endif
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
,kServiceCheckHandlerSearchSecService
|
|
,kServiceCheckHandlerCheckSecLength
|
|
,kServiceCheckHandlerCheckSecSequenceError
|
|
#endif
|
|
};
|
|
|
|
#define FBLDIAG_START_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
V_MEMROM0 static V_MEMROM1 tFblDiagCheckHandler V_MEMROM2 kServiceCheckHandlerFctTable[] =
|
|
{
|
|
&FblDiagSearchService
|
|
,&FblDiagCheckSession
|
|
,&FblDiagCheckLength
|
|
,&FblDiagCheckFunctional
|
|
,&FblDiagCheckSuppressPosRsp
|
|
,&FblDiagCheckSecurityAccess
|
|
,&FblDiagCheckSequenceError
|
|
,&FblDiagCheckGeneralConditions
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,&FblDiagCheckTransferMode
|
|
#endif
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
,&FblDiagSearchSecService
|
|
,&FblDiagCheckSecLength
|
|
,&FblDiagCheckSecSequenceError
|
|
#endif
|
|
};
|
|
|
|
enum
|
|
{
|
|
kServiceErrorHandlerExecMainHandler
|
|
#if defined( FBL_ENABLE_USERSERVICE )
|
|
,kServiceErrorHandlerServiceNotFound
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
,kServiceErrorHandlerSubFunctionNotFound
|
|
#endif
|
|
/*----------------------*/
|
|
,kServiceErrorHandlerNone
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tFblDiagErrorHandler V_MEMROM2 kServiceErrorHandlerFctTable[] =
|
|
{
|
|
&FblDiagErrorHandlerExecMainHandler
|
|
#if defined( FBL_ENABLE_USERSERVICE )
|
|
,&FblDiagErrorHandlerServiceNotFound
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
,&FblDiagErrorHandlerSubFunctionNotFound
|
|
#endif
|
|
};
|
|
|
|
enum
|
|
{
|
|
kServiceMainHandlerDefaultSession
|
|
,kServiceMainHandlerProgrammingSession
|
|
,kServiceMainHandlerTesterPresent
|
|
,kServiceMainHandlerEcuReset
|
|
,kServiceMainHandlerRcEraseMemory
|
|
,kServiceMainHandlerRcCheckProgDep
|
|
,kServiceMainHandlerRcActivateSbl
|
|
,kServiceMainHandlerRcCheckValidApp
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
,kServiceMainHandlerRcTokenDownload
|
|
# endif
|
|
#endif
|
|
#if defined( FBL_DIAG_ENABLE_UPDATE_SEC_BYTES )
|
|
,kServiceMainHandlerRcUpdateSecBytes
|
|
#endif
|
|
,kServiceMainHandlerSecAccessSeed
|
|
,kServiceMainHandlerSecAccessKey
|
|
,kServiceMainHandlerRequestDownload
|
|
,kServiceMainHandlerTransferDataDownload
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,kServiceMainHandlerRequestUpload
|
|
,kServiceMainHandlerTransferDataUpload
|
|
#endif
|
|
,kServiceMainHandlerRequestTransferExit
|
|
,kServiceMainHandlerReadDataById
|
|
#if defined( FBL_DIAG_ENABLE_WRITE_DATA_BY_IDENTIFIER )
|
|
,kServiceMainHandlerWriteDataById
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERROUTINE )
|
|
,kServiceMainHandlerRoutineControl
|
|
#endif
|
|
/*----------------------*/
|
|
,kServiceMainHandlerNone
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tFblDiagMainHandler V_MEMROM2 kServiceMainHandlerFctTable[] = {
|
|
&FblDiagMainHandlerDefaultSession
|
|
,&FblDiagMainHandlerProgrammingSession
|
|
,&FblDiagMainHandlerTesterPresent
|
|
,&FblDiagMainHandlerEcuReset
|
|
,&FblDiagMainHandlerRcEraseMemory
|
|
,&FblDiagMainHandlerRcCheckProgDep
|
|
,&FblDiagMainHandlerRcActivateSbl
|
|
,&FblDiagMainHandlerRcCheckValidApp
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
,&FblDiagMainHandlerRcTokenDownload
|
|
# endif
|
|
#endif
|
|
#if defined( FBL_DIAG_ENABLE_UPDATE_SEC_BYTES )
|
|
,&FblDiagMainHandlerRcUpdateSecBytes
|
|
#endif
|
|
,&FblDiagMainHandlerSecAccessSeed
|
|
,&FblDiagMainHandlerSecAccessKey
|
|
,&FblDiagMainHandlerRequestDownload
|
|
,&FblDiagMainHandlerTransferDataDownload
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,&FblDiagMainHandlerRequestUpload
|
|
,&FblDiagMainHandlerTransferDataUpload
|
|
#endif
|
|
,&FblDiagMainHandlerRequestTransferExit
|
|
,&FblDiagMainHandlerReadDataById
|
|
#if defined( FBL_DIAG_ENABLE_WRITE_DATA_BY_IDENTIFIER )
|
|
,&FblDiagMainHandlerWriteDataById
|
|
#endif
|
|
#if defined( FBL_ENABLE_USERROUTINE )
|
|
,&FblDiagMainHandlerRoutineControl
|
|
#endif
|
|
};
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Service checks */
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagServiceChecks[] =
|
|
{
|
|
{
|
|
kServiceCheckHandlerSearchService
|
|
,kDiagNrcServiceNotSupported
|
|
# if defined( FBL_ENABLE_USERSERVICE )
|
|
,kServiceErrorHandlerServiceNotFound
|
|
# else
|
|
,kServiceErrorHandlerNone
|
|
# endif
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckFunctional
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSession
|
|
,kDiagNrcServiceNotSupportedInActiveSession
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckLength
|
|
,kDiagNrcIncorrectMessageLengthOrInvalidFormat
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecurityAccess
|
|
,kDiagNrcSecurityAccessDenied
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSequenceError
|
|
,kDiagNrcRequestSequenceError
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagServiceCheckTable =
|
|
{
|
|
kDiagServiceChecks
|
|
,(sizeof(kDiagServiceChecks)/sizeof(kDiagServiceChecks[0]))
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagSubFctChecks[] =
|
|
{
|
|
/* No real check, but only needs to be set once here */
|
|
{
|
|
kServiceCheckHandlerCheckSuppressPosRsp
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerSearchService
|
|
,kDiagNrcSubFunctionNotSupported
|
|
# if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
,kServiceErrorHandlerSubFunctionNotFound
|
|
# else
|
|
,kServiceErrorHandlerNone
|
|
# endif
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckFunctional
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSession
|
|
,kDiagNrcSubfunctionNotSupportedInActiveSession
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckLength
|
|
,kDiagNrcIncorrectMessageLengthOrInvalidFormat
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecurityAccess
|
|
,kDiagNrcSecurityAccessDenied
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSequenceError
|
|
,kDiagNrcRequestSequenceError
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagSubFctCheckTable =
|
|
{
|
|
kDiagSubFctChecks
|
|
,(sizeof(kDiagSubFctChecks)/sizeof(kDiagSubFctChecks[0]))
|
|
};
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
/*****************************************************************************/
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagSubFctSecChecks[] =
|
|
{
|
|
/* No real check, but only needs to be set once here */
|
|
{
|
|
kServiceCheckHandlerCheckSuppressPosRsp
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerSearchSecService
|
|
,kDiagNrcSubFunctionNotSupported
|
|
# if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
,kServiceErrorHandlerSubFunctionNotFound
|
|
# else
|
|
,kServiceErrorHandlerNone
|
|
# endif
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckFunctional
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSession
|
|
,kDiagNrcSubfunctionNotSupportedInActiveSession
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecLength
|
|
,kDiagNrcIncorrectMessageLengthOrInvalidFormat
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecSequenceError
|
|
,kDiagNrcRequestSequenceError
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagSubFctSecCheckTable =
|
|
{
|
|
kDiagSubFctSecChecks
|
|
,(sizeof(kDiagSubFctSecChecks)/sizeof(kDiagSubFctSecChecks[0]))
|
|
};
|
|
#endif /* FBL_ENABLE_SEC_ADDITIONAL_LEVELS */
|
|
|
|
/*****************************************************************************/
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagRcTypeChecks[] =
|
|
{
|
|
/* No real check, but only needs to be set once here */
|
|
{
|
|
kServiceCheckHandlerCheckSuppressPosRsp
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerSearchService
|
|
,kDiagNrcSubFunctionNotSupported
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckFunctional
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSession
|
|
,kDiagNrcSubfunctionNotSupportedInActiveSession
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckLength
|
|
,kDiagNrcIncorrectMessageLengthOrInvalidFormat
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecurityAccess
|
|
,kDiagNrcSecurityAccessDenied
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSequenceError
|
|
,kDiagNrcRequestSequenceError
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagRcTypeCheckTable =
|
|
{
|
|
kDiagRcTypeChecks
|
|
,(sizeof(kDiagRcTypeChecks)/sizeof(kDiagRcTypeChecks[0]))
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagNonSubFctChecks[] =
|
|
{
|
|
{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagNonSubFctCheckTable =
|
|
{
|
|
kDiagNonSubFctChecks
|
|
,(sizeof(kDiagNonSubFctChecks)/sizeof(kDiagNonSubFctChecks[0]))
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagSubRoutineChecks[] =
|
|
{
|
|
{
|
|
kServiceCheckHandlerSearchService
|
|
,kDiagNrcRequestOutOfRange
|
|
,kServiceErrorHandlerExecMainHandler
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckFunctional
|
|
,kDiagNrcNoResponse
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSession
|
|
,kDiagNrcRequestOutOfRange
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecurityAccess
|
|
,kDiagNrcSecurityAccessDenied
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagSubRoutineCheckTable =
|
|
{
|
|
kDiagSubRoutineChecks
|
|
,(sizeof(kDiagSubRoutineChecks)/sizeof(kDiagSubRoutineChecks[0]))
|
|
};
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
/*****************************************************************************/
|
|
/* TransferData checks */
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheck V_MEMROM2 kDiagTransferDataChecks[] =
|
|
{
|
|
{
|
|
kServiceCheckHandlerTransferMode
|
|
,kDiagErrorNone
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckLength
|
|
,kDiagNrcIncorrectMessageLengthOrInvalidFormat
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckSecurityAccess
|
|
,kDiagNrcSecurityAccessDenied
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
,{
|
|
kServiceCheckHandlerCheckGeneralConditions
|
|
,kDiagNrcConditionsNotCorrect
|
|
,kServiceErrorHandlerNone
|
|
}
|
|
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 kDiagTransferDataCheckTable =
|
|
{
|
|
kDiagTransferDataChecks
|
|
,(sizeof(kDiagTransferDataChecks)/sizeof(kDiagTransferDataChecks[0]))
|
|
};
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
|
|
/*****************************************************************************/
|
|
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
/* The check list tables */
|
|
enum
|
|
{
|
|
kServiceCheckListServiceCheck
|
|
,kServiceCheckListSubFctCheck
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
,kServiceCheckListSubFctSecCheck
|
|
#endif
|
|
,kServiceCheckListNonSubFctCheck
|
|
,kServiceCheckListSubRoutineCheck
|
|
,kServiceCheckListRcTypeCheck
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,kServiceCheckListTransferDataCheck
|
|
#endif
|
|
/*----------------------*/
|
|
,kServiceCheckListNone
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceCheckList V_MEMROM2 V_MEMROM3 * V_MEMROM1 V_MEMROM2 kServiceCheckListTable[] =
|
|
{
|
|
&kDiagServiceCheckTable
|
|
,&kDiagSubFctCheckTable
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
,&kDiagSubFctSecCheckTable
|
|
#endif
|
|
,&kDiagNonSubFctCheckTable
|
|
,&kDiagSubRoutineCheckTable
|
|
,&kDiagRcTypeCheckTable
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
,&kDiagTransferDataCheckTable
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
/* Service handlers **********************************************************/
|
|
/* PRQA S 0342 TAG_FblDiag_0342_1 */ /* MD_MSR_Rule20.10_0342 */
|
|
/* PRQA S 0841 TAG_FblDiag_0841_1 */
|
|
enum
|
|
{
|
|
#define FBL_DIAG_STATE_DEF(name, parent, firstChild, lastChild, bufPos, id, handler, checks, set, unset, add, clear, clearFail, rqlMin, rqlMax) kDiagService ## name
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_OUTPUT
|
|
#define FBL_DIAG_IMPL_OUTPUT FBL_DIAG_STATE_RESULT,
|
|
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
|
|
#undef FBL_DIAG_STATE_DEF
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
#undef FBL_DIAG_IMPL_OUTPUT
|
|
|
|
kDiagNumberOfServices
|
|
};
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
/* State Bitmaps ************************************************************/
|
|
V_MEMROM0 static V_MEMROM1 tStateBitmap V_MEMROM2 kDiagStateBitmaps[] =
|
|
{
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_STATEBITMAP
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
};
|
|
|
|
#endif
|
|
/* Service IDs ***************************************************************/
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
V_MEMRAM0 static V_MEMRAM1 tServiceProp V_MEMRAM2 kDiagServiceProperties[kDiagNumberOfServices];
|
|
#else
|
|
V_MEMROM0 static V_MEMROM1 tServiceProp V_MEMROM2 kDiagServiceProperties[kDiagNumberOfServices];
|
|
#endif
|
|
|
|
/* Service IDs ***************************************************************/
|
|
#define FBL_DIAG_STATE_DEF(name, parent, firstChild, lastChild, bufPos, id, handler, checks, set, unset, add, clear, clearFail, rqlMin, rqlMax) \
|
|
V_MEMROM0 static V_MEMROM1 vuint8 V_MEMROM2 kDiagSrvId_ ## name [] = { id }
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_OUTPUT
|
|
#define FBL_DIAG_IMPL_OUTPUT FBL_DIAG_STATE_RESULT;
|
|
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
|
|
#undef FBL_DIAG_STATE_DEF
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
#undef FBL_DIAG_IMPL_OUTPUT
|
|
|
|
/* Service Lists *************************************************************/
|
|
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_SERVICELIST
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
|
|
#if defined( FBL_DIAG_SERVICE_LIST_HANDLES )
|
|
enum
|
|
{
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_SERVICELIST_ENUM
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
kDiagServiceListHandler_None
|
|
};
|
|
|
|
V_MEMROM0 static V_MEMROM1 tServiceList V_MEMROM2 V_MEMROM3 * V_MEMROM1 V_MEMROM2 kDiagSubFctTblHandler[] =
|
|
{
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_SERVICELIST_HANDLER
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
kDiagNoSubServices
|
|
};
|
|
#endif
|
|
|
|
/* Service Properties ********************************************************/
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
V_MEMROM0 static V_MEMROM1 tServicePropROM V_MEMROM2 kDiagServicePropertiesROM[] =
|
|
#else
|
|
V_MEMROM0 static V_MEMROM1 tServiceProp V_MEMROM2 kDiagServiceProperties[] =
|
|
#endif
|
|
{
|
|
#define FBL_DIAG_IMPL_TYPE FBL_DIAG_IMPL_TYPE_SERVICEPROPERTY
|
|
#include "fbl_diag.def" /* PRQA S 5087 */ /* MD_FblDiag_5087_DiagDef */
|
|
#undef FBL_DIAG_IMPL_TYPE
|
|
};
|
|
/* PRQA L:TAG_FblDiag_0342_1 */
|
|
/* PRQA L:TAG_FblDiag_0881_1 */
|
|
/* PRQA L:TAG_FblDiag_0841_1 */
|
|
/* PRQA L:TAG_FblDiag_3410_1 */
|
|
/* PRQA L:TAG_FblDiag_3412_1 */
|
|
/* PRQA L:TAG_FblDiag_3431_1 */
|
|
/* PRQA L:TAG_FblDiag_3453_2 */
|
|
/* PRQA L:TAG_FblDiag_3218_1 */
|
|
|
|
#define FBLDIAG_STOP_SEC_CONST
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/***********************************************************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
**********************************************************************************************************************/
|
|
|
|
#define FBLDIAG_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#if defined( FBL_ENABLE_USERSERVICE )
|
|
/***********************************************************************************************************************
|
|
* FblDiagErrorHandlerServiceNotFound
|
|
**********************************************************************************************************************/
|
|
/*! \brief Execute callback for user specific service implementations
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] diagReqDataLen Request length
|
|
* \return User service found
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerServiceNotFound)
|
|
{
|
|
tFblResult result;
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)properties;
|
|
#endif
|
|
|
|
ApplDiagUserService(&pbDiagBuffer[kDiagFmtRoutineIdHigh], diagReqDataLen);
|
|
|
|
result = kFblFailed;
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
result = kFblOk;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_ENABLE_USERSERVICE */
|
|
|
|
#if defined( FBL_ENABLE_USERSUBFUNCTION )
|
|
/***********************************************************************************************************************
|
|
* FblDiagErrorHandlerSubFunctionNotFound
|
|
**********************************************************************************************************************/
|
|
/*! \brief Execute callback for user specific subfunction implementations
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] diagReqDataLen Request length
|
|
* \return User subfunction found
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerSubFunctionNotFound)
|
|
{
|
|
tFblResult result;
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)properties;
|
|
#endif
|
|
|
|
ApplDiagUserSubFunction(&pbDiagBuffer[kDiagFmtRoutineIdHigh], diagReqDataLen);
|
|
|
|
result = kFblFailed;
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
result = kFblOk;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_ENABLE_USERSUBFUNCTION */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagErrorHandlerExecMainHandler
|
|
**********************************************************************************************************************/
|
|
/*! \brief Execute main handler of parent service
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] diagReqDataLen Request length
|
|
* \return Main handler execution result
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_ERROR_HANDLER(FblDiagErrorHandlerExecMainHandler)
|
|
{
|
|
tFblResult result;
|
|
|
|
result = kFblFailed;
|
|
if (properties->mainHandlerIdx != (vuint8)kServiceMainHandlerNone)
|
|
{
|
|
result = (kServiceMainHandlerFctTable[properties->mainHandlerIdx])(pbDiagBuffer, diagReqDataLen);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSearchService
|
|
**********************************************************************************************************************/
|
|
/*! \brief Search the subservice table using the id at the current request position
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Search successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Search failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagSearchService)
|
|
{
|
|
V_MEMROM1 tServiceList V_MEMROM2 V_MEMROM3 * localSubServices;
|
|
ptServiceProp subSrvLst = V_NULL; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
ptServiceProp subService = V_NULL; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
|
|
vuint8 curPos;
|
|
vuint8 subSrvIdx;
|
|
tFblResult valid;
|
|
tFblResult found;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)length;
|
|
#endif
|
|
|
|
localSubServices = properties->subServices;
|
|
subSrvLst = localSubServices->list;
|
|
|
|
found = kFblFailed;
|
|
for (subSrvIdx = 0; subSrvIdx < localSubServices->count; subSrvIdx++)
|
|
{
|
|
subService = &subSrvLst[subSrvIdx];
|
|
|
|
valid = kFblOk;
|
|
for (curPos = 0; curPos < localSubServices->idSize; curPos++)
|
|
{
|
|
if (subService->serviceId[curPos] != pbDiagBuffer[position + curPos])
|
|
{
|
|
valid = kFblFailed;
|
|
/* Code size optimization, single break in loop allowed by MISRA */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (valid == kFblOk)
|
|
{
|
|
found = kFblOk;
|
|
*result = subService;
|
|
/* Code size optimization, single break in loop allowed by MISRA */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckState
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the masked state matches the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in] stateMask State mask
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673, 6060 1 */ /* MD_MSR_Rule8.13, MD_MSR_STPAR */
|
|
static tFblResult FblDiagCheckState( const V_MEMRAM1 tServiceProp V_MEMRAM2 V_MEMRAM3 *properties, V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pbDiagBuffer, tCwDataLengthType length, tCwDataLengthType position, V_MEMROM1 tStateBitmap V_MEMROM2 * stateMask, ptServiceProp * result)
|
|
{
|
|
vuint8 idx, valid;
|
|
tStateBitmap maskedState;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 4 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)length;
|
|
(void)position;
|
|
(void)result;
|
|
#endif
|
|
valid = kFblOk;
|
|
|
|
#if ( STATECHECK_ARRAYSIZE == 1u )
|
|
idx = 0u;
|
|
#else
|
|
for (idx = 0u; (idx < STATECHECK_ARRAYSIZE) && (valid == kFblOk); idx++)
|
|
#endif
|
|
{
|
|
/* Separate the state bits which have to be set */
|
|
maskedState = properties->stateSet[idx] & stateMask[idx];
|
|
|
|
/* Check if all of the required "Set" states are set */
|
|
if ((maskedState != kDiagStateMaskNone) && ((maskedState & fblStates[idx]) != maskedState))
|
|
{
|
|
/* At least one of the required states is not set */
|
|
valid = kFblFailed;
|
|
}
|
|
else
|
|
{
|
|
/* Separate the state bits which must not be set */
|
|
maskedState = properties->stateUnset[idx] & stateMask[idx];
|
|
|
|
/* Check if all of the required "Unset" states are cleared */
|
|
if ((maskedState != kDiagStateMaskNone) && ((maskedState & fblStates[idx]) != kDiagStateMaskNone))
|
|
{
|
|
/* At least one of the required states is set */
|
|
valid = kFblFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Positive check result:
|
|
- All of the required "Set" states are set
|
|
- All of the required "Unset" states are cleared
|
|
*/
|
|
return valid;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSession
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the session states match the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSession)
|
|
{
|
|
return FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskSessions, result);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckFunctional
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the functional request state matches the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckFunctional)
|
|
{
|
|
return FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskFunctional, result);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSecurityAccess
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the security access states match the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecurityAccess)
|
|
{
|
|
return FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskSecurityAccess, result);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSequenceError
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the states leading to request sequence errors match the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSequenceError)
|
|
{
|
|
return FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskSequenceError, result);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckGeneralConditions
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if all possible session states match the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckGeneralConditions)
|
|
{
|
|
return FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskGeneralConditions, result);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckLength
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the request length matches the service requirements
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckLength)
|
|
{
|
|
vuint8 valid;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 3 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)position;
|
|
(void)result;
|
|
#endif
|
|
valid = kFblOk;
|
|
|
|
if ((properties->minLength > 0u) && (length < properties->minLength))
|
|
{
|
|
valid = kFblFailed;
|
|
}
|
|
|
|
if (length > properties->maxLength)
|
|
{
|
|
valid = kFblFailed;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSuppressPosRsp
|
|
**********************************************************************************************************************/
|
|
/*! \brief Evaluate the suppress positive response message bit for subfunction requests
|
|
* \details No real check, but should only be executed for services with subfunctions
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSuppressPosRsp)
|
|
{
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 3 */ /* MD_MSR_DummyStmt */
|
|
(void)properties;
|
|
(void)length;
|
|
(void)result;
|
|
#endif
|
|
|
|
CheckSuppressPosRspMsgIndication(&pbDiagBuffer[position]);
|
|
|
|
return kFblOk;
|
|
}
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckTransferMode
|
|
**********************************************************************************************************************/
|
|
/*! \brief Evaluate the requested transfer mode. This check is used to switch between download and upload transfers.
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckTransferMode)
|
|
{
|
|
V_MEMROM1 tServiceList V_MEMROM2 * localSubServices;
|
|
ptServiceProp subSrvLst = V_NULL; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
ptServiceProp subService = V_NULL; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
vuint8 subSrvIdx;
|
|
vuint8 found;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 3 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)length;
|
|
(void)position;
|
|
#endif
|
|
|
|
localSubServices = properties->subServices;
|
|
subSrvLst = localSubServices->list;
|
|
|
|
found = kFblFailed;
|
|
for (subSrvIdx = 0; (subSrvIdx < localSubServices->count) && (found != kFblOk); subSrvIdx++)
|
|
{
|
|
subService = &subSrvLst[subSrvIdx];
|
|
if (STATE_TEST(subService->stateSet, kDiagStateIdxTransferDataUpload) == GetTransferDataUpload())
|
|
{
|
|
found = kFblOk;
|
|
}
|
|
}
|
|
|
|
if (found == kFblOk)
|
|
{
|
|
*result = subService;
|
|
}
|
|
|
|
return found;
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
/***********************************************************************************************************************
|
|
* FblDiagSearchSecService
|
|
**********************************************************************************************************************/
|
|
/*! \brief Search the sub service table using the id at the current request position. Special use case for security access
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Search successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Search failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagSearchSecService)
|
|
{
|
|
V_MEMROM1 tServiceList V_MEMROM2 * localSubServices;
|
|
ptServiceProp subSrvLst; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
ptServiceProp subService; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
|
|
vuint8 subSrvIdx;
|
|
vuint8 found;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)length;
|
|
#endif
|
|
|
|
localSubServices = properties->subServices;
|
|
subSrvLst = localSubServices->list;
|
|
subService = kDiagNoServiceProp;
|
|
diagRequestedSecLvlIdx = kDiagInvalidSecLvlIdx;
|
|
|
|
found = kFblFailed;
|
|
|
|
/* Check if level is supported */
|
|
for (subSrvIdx = 0; subSrvIdx < (sizeof(kDiagSecAccessParams)/sizeof(kDiagSecAccessParams[0])); subSrvIdx++)
|
|
{
|
|
if (kDiagSecAccessParams[subSrvIdx].secLevel == pbDiagBuffer[position] )
|
|
{
|
|
/* Level supported - Seed request */
|
|
subService = &subSrvLst[0];
|
|
found = kFblOk;
|
|
break;
|
|
}
|
|
if (kDiagSecAccessParams[subSrvIdx].secLevel == (pbDiagBuffer[position] - 1u))
|
|
{
|
|
/* Level supported - Key request */
|
|
subService = &subSrvLst[1];
|
|
found = kFblOk;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found == kFblOk)
|
|
{
|
|
/* Cache index of identified table entry for later usage */
|
|
diagRequestedSecLvlIdx = subSrvIdx;
|
|
|
|
*result = subService;
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSecLength
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the request length matches the service requirements
|
|
* \details Special version for security access.
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecLength)
|
|
{
|
|
vuint8 valid;
|
|
|
|
assertFblInternal(diagRequestedSecLvlIdx != kDiagInvalidSecLvlIdx, kFblOemAssertInvalidSecLvlIdx);
|
|
|
|
valid = kFblFailed;
|
|
|
|
if (kDiagSecAccessParams[diagRequestedSecLvlIdx].secLevel == pbDiagBuffer[position])
|
|
{
|
|
/* Seed request -> use standard check
|
|
* This works because pbDiagBuffer is not evaluated any more */
|
|
valid = FblDiagCheckLength(properties, pbDiagBuffer, length, position, result);
|
|
}
|
|
if (kDiagSecAccessParams[diagRequestedSecLvlIdx].secLevel == (pbDiagBuffer[position] - 1u))
|
|
{
|
|
/* Key request */
|
|
if ((kDiagSecAccessParams[diagRequestedSecLvlIdx].keyLength + 1u) == length)
|
|
{
|
|
valid = kFblOk;
|
|
}
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckSecSequenceError
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the states leading to request sequence errors match the service requirements for security access
|
|
* \param[in] properties Dispatching properties
|
|
* \param[in] pbDiagBuffer Diagnostic buffer
|
|
* \param[in] length Request length
|
|
* \param[in] position Current request position
|
|
* \param[in,out] result Resulting properties
|
|
* \return Possible return values:
|
|
* - kFblOk: Check successful. If applicable, changed properties are returned via parameter 'result'
|
|
* - kFblFailed: Check failed
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_CHECK_HANDLER(FblDiagCheckSecSequenceError)
|
|
{
|
|
vuint8 tmpSecLvl;
|
|
tFblResult valid;
|
|
|
|
assertFblInternal(diagRequestedSecLvlIdx != kDiagInvalidSecLvlIdx, kFblOemAssertInvalidSecLvlIdx);
|
|
|
|
valid = kFblOk;
|
|
|
|
if ((pbDiagBuffer[position] & 0x01u) == 0x01u)
|
|
{
|
|
/* Seed request: sub service equals security level */
|
|
tmpSecLvl = pbDiagBuffer[position];
|
|
if ((kDiagSecLevelNone != GetCurrentSecLvl()) && (tmpSecLvl != GetCurrentSecLvl()))
|
|
{
|
|
valid = kFblFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Key request: (sub service - 1) equals security level */
|
|
tmpSecLvl = pbDiagBuffer[position] - 1;
|
|
if (diagRequestedSecLvl != tmpSecLvl)
|
|
{
|
|
valid = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if ((kFblOk == valid ) && (kFblOk == ApplFblGetSecLvlSupport(tmpSecLvl)))
|
|
{
|
|
valid = FblDiagCheckState(properties, pbDiagBuffer, length, position, kDiagStateMaskSequenceError, result);
|
|
}
|
|
else
|
|
{
|
|
valid = kFblFailed;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
#endif /* FBL_ENABLE_SEC_ADDITIONAL_LEVELS */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSetState
|
|
**********************************************************************************************************************/
|
|
/*! \brief Set states according to mask
|
|
* \param[in] state State mask
|
|
**********************************************************************************************************************/
|
|
static void FblDiagSetState (const V_MEMRAM1 tStateBitmap V_MEMRAM2 V_MEMRAM3 * state)
|
|
{
|
|
vuint8 idx;
|
|
|
|
#if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
#else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
#endif
|
|
{
|
|
fblStates[idx] |= state[idx];
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagClrState
|
|
**********************************************************************************************************************/
|
|
/*! \brief Clear states according to mask
|
|
* \param[in] state State mask
|
|
**********************************************************************************************************************/
|
|
static void FblDiagClrState (const V_MEMRAM1 tStateBitmap V_MEMRAM2 V_MEMRAM3 * state)
|
|
{
|
|
vuint8 idx;
|
|
|
|
#if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
#else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
#endif
|
|
{
|
|
fblStates[idx] &= FblInvertBits(state[idx], tStateBitmap);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRetainState
|
|
**********************************************************************************************************************/
|
|
/*! \brief Retain the value of all masked states, clear all others including the internal states
|
|
* \param[in] state State mask
|
|
**********************************************************************************************************************/
|
|
static void FblDiagRetainState (V_MEMROM1 tStateBitmap V_MEMROM2 V_MEMROM3 * state)
|
|
{
|
|
vuint8 idx;
|
|
|
|
/* Retain values of masked dispatcher states */
|
|
#if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
#else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
#endif
|
|
{
|
|
fblStates[idx] &= state[idx];
|
|
}
|
|
|
|
/* Clear all additional internal flags */
|
|
for ( ; idx < ARRAY_SIZE(fblStates); idx++)
|
|
{
|
|
fblStates[idx] = 0;
|
|
}
|
|
}
|
|
|
|
#if defined( FBL_DIAG_ENABLE_SESSION_PARAMETERS )
|
|
/***********************************************************************************************************************
|
|
* FblDiagGetSessionIndex
|
|
**********************************************************************************************************************/
|
|
/*! \brief Search the diagnostic session table for the requested session type and return the internal session index
|
|
* \param[in] diagnosticSessionType SessionControl parameter
|
|
* \return Session index
|
|
**********************************************************************************************************************/
|
|
static vuint8 FblDiagGetSessionIndex(vuint8 diagnosticSessionType)
|
|
{
|
|
vuint8 sessionIdx;
|
|
|
|
for (sessionIdx = 0u; sessionIdx < kDiagNumberOfSessions; sessionIdx++)
|
|
{
|
|
if (kDiagSessionParameters[sessionIdx].sessionType == diagnosticSessionType)
|
|
{
|
|
/* Found valid session */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sessionIdx == kDiagNumberOfSessions)
|
|
{
|
|
/*
|
|
* Config error: this error can only appear if the dispatcher knows more
|
|
* diagnostic session types than the session parameter table.
|
|
*/
|
|
assertFblInternal(0u, kFblOemAssertSessionIndexNotFound); /* PRQA S 2214 */ /* MD_FblDiag_2214 */
|
|
sessionIdx = kDiagSessionNotFound;
|
|
}
|
|
|
|
return sessionIdx;
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_SESSION_PARAMETERS */
|
|
|
|
#define FBLDIAG_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* Diagnostic standard functions ********************************************/
|
|
|
|
#define FBLDIAG_RAMCODE_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
/***********************************************************************************************************************
|
|
* DiagResetResponseHandling
|
|
**********************************************************************************************************************/
|
|
/*! \brief Reset the status for service handling
|
|
* \pre Service response shall be finished
|
|
**********************************************************************************************************************/
|
|
static void DiagResetResponseHandling( void )
|
|
{
|
|
DiagClrError();
|
|
|
|
/* Restart the tester present timer if not in default session */
|
|
if (!GetDiagDefaultDiagSession())
|
|
{
|
|
ResetTesterTimeout();
|
|
}
|
|
|
|
/* Buffer is now available */
|
|
ClrDiagBufferLocked();
|
|
|
|
/* Reset flag for functional request after processing */
|
|
ClrFunctionalRequest();
|
|
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* DiagExRCRResponsePending
|
|
**********************************************************************************************************************/
|
|
/*! \brief Transmit a busy message if timer expires
|
|
* (forceSend == kNotForceSendResponsePending) or if kForceSendResponsePending is passed.
|
|
* \param[in] forceSend Determines if a message is sent independently from timer state.
|
|
**********************************************************************************************************************/
|
|
void DiagExRCRResponsePending( vuint8 forceSend )
|
|
{
|
|
static vuint8 rcrrpDiagBuffer[3];
|
|
|
|
if (GetServiceInProgress())
|
|
{
|
|
if (((GetP2Timeout() > 0x00u) && (GetP2Timer() < (GetP2Timeout()))) || (forceSend == kForceSendResponsePending))
|
|
{
|
|
/* Prepare and transmit RCRRP buffer */
|
|
rcrrpDiagBuffer[0] = kDiagRidNegativeResponse;
|
|
rcrrpDiagBuffer[1] = diagServiceCurrent;
|
|
rcrrpDiagBuffer[2] = kDiagNrcRcrResponsePending;
|
|
FblCwTransmitRP(rcrrpDiagBuffer);
|
|
|
|
/* Restart P2-Timer to P2* */
|
|
SetP2Timer(kFblDiagTimeP2Star);
|
|
SetP2Timeout(kFblDiagTimeP2Star); /* PRQA S 3493 */ /* MD_FblDiag_3493 */
|
|
|
|
/* If response pending is transmitted and no response
|
|
* is set, a positive response has to be transmitted anyway. */
|
|
ClrSuppressPosRspMsg();
|
|
|
|
/* Prepare parameter for the confirmation function */
|
|
SetRcrRpInProgress();
|
|
}
|
|
}
|
|
}
|
|
#define FBLDIAG_RAMCODE_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMemGetActiveBuffer
|
|
**********************************************************************************************************************/
|
|
/*! \brief Function updates Diagnostic buffer (DiagBuffer) and returns updated pbDiagData to handler
|
|
* \return updated pbDiagData buffer used by diagnostic handler functions *
|
|
**********************************************************************************************************************/
|
|
static V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * FblDiagMemGetActiveBuffer(void)
|
|
{
|
|
DiagBuffer = FblMemGetActiveBuffer();
|
|
return DiagBuffer;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* DiagDiscardReception
|
|
**********************************************************************************************************************/
|
|
/*! \brief Received diagnostic messages are discarded
|
|
**********************************************************************************************************************/
|
|
static void DiagDiscardReception( void )
|
|
{
|
|
SetResponseProcessing(); /* Set flag for running response procedure */
|
|
|
|
FblCwDiscardReception();
|
|
|
|
ClrResponseProcessing();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* DiagResponseProcessor
|
|
**********************************************************************************************************************/
|
|
/*! \brief Send diagnostic response message
|
|
* \pre List of preconditions:
|
|
* - Current SID must be in DiagBuffer[0]
|
|
* - diagErrorCode must be initialized
|
|
* \param[in] dataLength Data length to be transmitted.
|
|
**********************************************************************************************************************/
|
|
void DiagResponseProcessor( tCwDataLengthType dataLength )
|
|
{
|
|
ClrServiceInProgress();
|
|
ClrRcrRpInProgress();
|
|
ClrP2Timer();
|
|
ClrP2Timeout();
|
|
DiagDiscardReception();
|
|
FblErrStatSetSId(diagServiceCurrent);
|
|
|
|
if (DiagGetError() != kDiagErrorNone)
|
|
{
|
|
if (GetFunctionalRequest()
|
|
&& ((DiagGetError() == kDiagNrcServiceNotSupported)
|
|
|| (DiagGetError() == kDiagNrcServiceNotSupportedInActiveSession)
|
|
|| (DiagGetError() == kDiagNrcSubFunctionNotSupported)
|
|
|| (DiagGetError() == kDiagNrcSubfunctionNotSupportedInActiveSession)
|
|
|| (DiagGetError() == kDiagNrcRequestOutOfRange)
|
|
))
|
|
{
|
|
/*
|
|
No response for functionally addressed requests if
|
|
service or subfunction not supported.
|
|
*/
|
|
DiagResetResponseHandling();
|
|
FblCwResetRxBlock();
|
|
}
|
|
else
|
|
{
|
|
/* Prepare response message */
|
|
DiagBuffer[kDiagFmtSubparam] = diagServiceCurrent;
|
|
DiagBuffer[kDiagFmtServiceId] = kDiagRidNegativeResponse;
|
|
DiagBuffer[kDiagFmtNegResponse] = DiagGetError();
|
|
|
|
/* Send response in communication wrapper */
|
|
FblCwTransmit(DiagBuffer, 3, kFblCwTxCallNegResponse );
|
|
}
|
|
/* Clear 'pending' error */
|
|
DiagClrError();
|
|
}
|
|
else if (diagResponseFlag == kDiagPutResponse)
|
|
{
|
|
if (!GetSuppressPosRspMsg())
|
|
{
|
|
/* Transmit positive response if not suppressed */
|
|
DiagBuffer[kDiagFmtServiceId] = (vuint8)(diagServiceCurrent + 0x40u);
|
|
|
|
/* Send response in communication wrapper */
|
|
FblCwTransmit(DiagBuffer, (tCwDataLengthType)(dataLength + 1u), kFblCwTxCallPosResponse);
|
|
}
|
|
else
|
|
{
|
|
DiagResetResponseHandling();
|
|
FblCwResetRxBlock();
|
|
ClrSuppressPosRspMsg();
|
|
|
|
/* Check if a reset shall be generated without message transmission */
|
|
if (GetWaitEcuReset())
|
|
{
|
|
/* If so, generate the reset immediately */
|
|
SetResetMsgConfirmed();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Do not send a response, just reset internal state */
|
|
DiagResetResponseHandling();
|
|
FblCwResetRxBlock();
|
|
ClrSuppressPosRspMsg();
|
|
|
|
/* Check if a reset shall be generated without message transmission */
|
|
if (GetWaitEcuReset())
|
|
{
|
|
/* If so, generate the reset immediately */
|
|
SetResetMsgConfirmed();
|
|
}
|
|
}
|
|
|
|
/* Response processing executed */
|
|
SetProcessingDone();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblRealTimeSupport
|
|
**********************************************************************************************************************/
|
|
/*! \brief Transmit busy messages and triggers the watchdog according to system timer
|
|
* \pre P2Timer must be initialized
|
|
* \return Return code of FblLookForWatchdog
|
|
**********************************************************************************************************************/
|
|
vuint8 FblRealTimeSupport( void )
|
|
{
|
|
vuint8 returnCode;
|
|
|
|
returnCode = FblLookForWatchdog();
|
|
|
|
DiagExRCRResponsePending(kNotForceSendResponsePending);
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblRealTimeSupportVoid
|
|
**********************************************************************************************************************/
|
|
/*! \brief Transmit busy messages and triggers the watchdog according to system timer.
|
|
* \pre Diagnosis and communication stack must be initialized, diagnostic request has to be received.
|
|
* \return None
|
|
**********************************************************************************************************************/
|
|
void FblRealTimeSupportVoid( void )
|
|
{
|
|
FblLookForWatchdogVoid();
|
|
DiagExRCRResponsePending(kNotForceSendResponsePending);
|
|
}
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
/***********************************************************************************************************************
|
|
* FblDiagInitStateTables
|
|
**********************************************************************************************************************/
|
|
/*! \brief Expand condensed service property tables from ROM to RAM
|
|
**********************************************************************************************************************/
|
|
static void FblDiagInitStateTables ( void )
|
|
{
|
|
vuint8 idx;
|
|
vuint16 bitmapIdx;
|
|
vuint8 stateIdx;
|
|
vuint8 stateArrIdx;
|
|
vuint8 stateMask;
|
|
static V_MEMROM1 tStateBitmap V_MEMROM2 V_MEMROM3 * sourceState;
|
|
static V_MEMRAM1 tStateBitmap V_MEMRAM2 V_MEMRAM3 * targetState;
|
|
|
|
bitmapIdx = 0;
|
|
|
|
for (idx = 0; idx < (sizeof(kDiagServicePropertiesROM)/sizeof(kDiagServicePropertiesROM[0])); idx++)
|
|
{
|
|
# if defined( FBL_DIAG_SERVICE_LIST_HANDLES )
|
|
kDiagServiceProperties[idx].subServices = kDiagSubFctTblHandler[kDiagServicePropertiesROM[idx].subServicesHandler];
|
|
# else
|
|
kDiagServiceProperties[idx].subServices = kDiagServicePropertiesROM[idx].subServices;
|
|
# endif
|
|
kDiagServiceProperties[idx].serviceId = kDiagServicePropertiesROM[idx].serviceId;
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
#else
|
|
kDiagServiceProperties[idx].checks = kDiagServicePropertiesROM[idx].checks;
|
|
#endif
|
|
kDiagServiceProperties[idx].minLength = kDiagServicePropertiesROM[idx].minLength;
|
|
kDiagServiceProperties[idx].maxLength = kDiagServicePropertiesROM[idx].maxLength;
|
|
kDiagServiceProperties[idx].mainHandlerIdx = kDiagServicePropertiesROM[idx].mainHandlerIdx;
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
kDiagServiceProperties[idx].checkListIdx = kDiagServicePropertiesROM[idx].checkListIdx;
|
|
#endif
|
|
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
stateMask = 0x01;
|
|
#endif
|
|
|
|
for (stateArrIdx = 0; stateArrIdx < STATE_COUNT; stateArrIdx++)
|
|
{
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
targetState = kDiagServiceProperties[idx].states[stateArrIdx];
|
|
#else
|
|
switch (stateArrIdx)
|
|
{
|
|
case 0:
|
|
targetState = kDiagServiceProperties[idx].stateSet;
|
|
stateMask = 0x01;
|
|
break;
|
|
case 1:
|
|
targetState = kDiagServiceProperties[idx].stateUnset;
|
|
stateMask = 0x02;
|
|
break;
|
|
case 2:
|
|
targetState = kDiagServiceProperties[idx].stateAdd;
|
|
stateMask = 0x04;
|
|
break;
|
|
case 3:
|
|
targetState = kDiagServiceProperties[idx].stateClr;
|
|
stateMask = 0x08;
|
|
break;
|
|
case 4:
|
|
targetState = kDiagServiceProperties[idx].stateClrFail;
|
|
stateMask = 0x10;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if ((kDiagServicePropertiesROM[idx].stateUsage & stateMask) == stateMask)
|
|
{
|
|
sourceState = &kDiagStateBitmaps[bitmapIdx];
|
|
bitmapIdx += STATECHECK_ARRAYSIZE;
|
|
}
|
|
else
|
|
{
|
|
sourceState = kDiagStateMaskReset;
|
|
}
|
|
|
|
# if ( STATECHECK_ARRAYSIZE == 1u)
|
|
stateIdx = 0;
|
|
# else
|
|
for (stateIdx = 0; stateIdx < STATECHECK_ARRAYSIZE; stateIdx++)
|
|
# endif
|
|
{
|
|
targetState[stateIdx] = sourceState[stateIdx];
|
|
}
|
|
|
|
stateMask <<= 1;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagInitDownloadSequence
|
|
**********************************************************************************************************************/
|
|
/*! \brief (Re-)initialize download sequence (initialization and session transition)
|
|
**********************************************************************************************************************/
|
|
static void FblDiagInitDownloadSequence( void )
|
|
{
|
|
vuint8 blockIdx;
|
|
|
|
/* (Re-)initialize download sequence */
|
|
transferRemainder = 0u;
|
|
transferType = DOWNLOAD_RAM;
|
|
expectedSequenceCnt = 0u;
|
|
lastErasedBlock = kBlockNrInvalid;
|
|
|
|
/* Initialize download information structure */
|
|
FblDiagSegmentInit();
|
|
|
|
/* Initialize block information */
|
|
currentBlock = kBlockNrInvalid;
|
|
|
|
for (blockIdx = 0u; blockIdx < FBL_LBT_BLOCK_COUNT; blockIdx++)
|
|
{
|
|
blockHeader[blockIdx].state = kBlockState_Init;
|
|
blockHeader[blockIdx].nrOfSegments = 0u;
|
|
}
|
|
|
|
/* Initialize security module */
|
|
(void)ApplFblSecurityInit();
|
|
SetCurrentSecLvl(kDiagSecLevelNone);
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
/* Initialize security access variables */
|
|
diagRequestedSecLvl = kDiagSecLevelNone;
|
|
diagRequestedSecLvlIdx = kDiagInvalidSecLvlIdx;
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagInitPowerOn
|
|
**********************************************************************************************************************/
|
|
/*! \brief Initialize module variables
|
|
**********************************************************************************************************************/
|
|
void FblDiagInitPowerOn( void )
|
|
{
|
|
vuint8 idx;
|
|
|
|
for (idx = 0u; idx < (sizeof(fblStates)/sizeof(fblStates[0])); idx++)
|
|
{
|
|
fblStates[idx] = (tStateBitmap)0x00u;
|
|
}
|
|
|
|
transferRemainder = 0u;
|
|
transferType = DOWNLOAD_RAM;
|
|
expectedSequenceCnt = 0u;
|
|
memSegment = -1;
|
|
diagResponseFlag = kDiagPutResponse;
|
|
|
|
|
|
/* Initialize variables of lib Lbt */
|
|
FblLbtInitPowerOn();
|
|
|
|
DiagClrError();
|
|
/* Set diagnostic session (default session) */
|
|
SetDiagDefaultDiagSession();
|
|
|
|
/* Stop tester present timer */
|
|
StopTesterTimeout();
|
|
|
|
/* Clear timer for response pending transmission */
|
|
ClrP2Timer();
|
|
/* Clear P2 timeout to prevent erroneous sending of RCR-RP */
|
|
ClrP2Timeout();
|
|
|
|
ApplFblResetVfp();
|
|
|
|
/* Initialize security module */
|
|
(void)SecM_InitPowerOn(V_NULL);
|
|
|
|
#if defined( FBL_ENABLE_DEBUG_STATUS )
|
|
/* Initialize error status */
|
|
ApplFblInitErrStatus();
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagInit
|
|
**********************************************************************************************************************/
|
|
/*! \brief Initialize module variables
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6050 1 */ /* MD_MSR_STCAL */
|
|
void FblDiagInit( void )
|
|
{
|
|
tCwDataLengthType requestLength = 0u;
|
|
|
|
/* Get aligned diag buffer pointer from memory library */
|
|
DiagBuffer = FblMemInitPowerOn();
|
|
|
|
#if defined( FBL_DIAG_ENABLE_RAM_STATETABLES )
|
|
FblDiagInitStateTables();
|
|
#endif
|
|
|
|
/* Reset service properties */
|
|
FblDiagSetProperties(&kDiagServiceProperties[0], &serviceProperties);
|
|
|
|
StopEcuResetTimeout();
|
|
|
|
/* If FBL was started from application, already lock diagnostic buffer here */
|
|
if (FblMainGetStartFromAppl())
|
|
{
|
|
|
|
requestLength = kDiagRqlDiagnosticSessionControl + 1u;
|
|
}
|
|
|
|
/* Release the buffer to be able to respond to request receiv ed by application */
|
|
ClrDiagBufferLocked();
|
|
|
|
if (FblDiagRxGetPhysBuffer(requestLength) == DiagBuffer)
|
|
{
|
|
SetLockedByInit();
|
|
/* Lock the TP buffer, because service buffer is allocated for pos. response */
|
|
FblCwSetRxBlock();
|
|
}
|
|
|
|
/* Initialize communication wrapper */
|
|
FblCwSetTxInit();
|
|
|
|
#if defined( FBL_CW_ENABLE_MULTIPLE_CONNECTIONS )
|
|
FblCwResetResponseAddress();
|
|
#endif /* FBL_CW_ENABLE_MULTIPLE_CONNECTIONS */
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
# if defined( FBL_DIAG_MULTIPLE_KEY )
|
|
/* Initialized the correct software signing key */
|
|
(void)FblDiagCopyUsedPersKeyToUsedNotPersKey();
|
|
# endif /* FBL_DIAG_MULTIPLE_KEY */
|
|
# endif /* FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING */
|
|
#endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
|
|
|
/* Initialize verification component */
|
|
(void)SecM_InitVerification(V_NULL);
|
|
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_OUTPUT )
|
|
/* Assign segment list array */
|
|
verifyParam.segmentList.segmentInfo = verifySegmentInfo;
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_OUTPUT */
|
|
|
|
(void)RamDriver_InitSync(V_NULL);
|
|
|
|
|
|
FblDiagInitDownloadSequence();
|
|
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagGetLastErasedBlock
|
|
**********************************************************************************************************************/
|
|
/*! \brief Returns last erased logical block or kBlockNrInvalid if no block has been erased yet.
|
|
**********************************************************************************************************************/
|
|
vuint8 FblDiagGetLastErasedBlock( void )
|
|
{
|
|
return lastErasedBlock;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSetLastErasedBlock
|
|
**********************************************************************************************************************/
|
|
/*! \brief Sets last erased logical block.
|
|
* \param[in] blockNr Block number of last erased logical block
|
|
**********************************************************************************************************************/
|
|
void FblDiagSetLastErasedBlock( vuint8 blockNr )
|
|
{
|
|
lastErasedBlock = blockNr;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* CheckSuppressPosRspMsgIndication
|
|
**********************************************************************************************************************/
|
|
/*! \brief This functions checks if a diagnostic response has to be sent and resets the positive response
|
|
* message indication bit if necessary
|
|
* \param[in,out] subparam Diagnostic subparameter
|
|
**********************************************************************************************************************/
|
|
void CheckSuppressPosRspMsgIndication( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *subparam )
|
|
{
|
|
if (((*(subparam)) & (kDiagSuppressPosRspMsgIndicationBit)) != 0u)
|
|
{
|
|
SetSuppressPosRspMsg(); /* Set internal flag for response processor */
|
|
(*(subparam)) &= FblInvertBits(kDiagSuppressPosRspMsgIndicationBit, vuint8); /* Clear indication bit */
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSegmentInit
|
|
**********************************************************************************************************************/
|
|
/*! \brief Initialize the download segment table
|
|
**********************************************************************************************************************/
|
|
static void FblDiagSegmentInit( void )
|
|
{
|
|
currentSegment = kDiagSegmentOutOfRange;
|
|
diagSegmentList.nrOfSegments = 0u;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSegmentNext
|
|
**********************************************************************************************************************/
|
|
/*! \brief The parameters of a download section (received by the RequestDownload handler) will be copied into
|
|
* the segment table.
|
|
* \param[in] segAddr Start address of download segment
|
|
* \param[in] segLength Length of download segment
|
|
* \param[in] blockIdx Index of the logical block which is the target of the download segment
|
|
* \return Index of current list entry
|
|
**********************************************************************************************************************/
|
|
static vuint8 FblDiagSegmentNext( tFblDiagAddr segAddr, tFblLength segLength, vuint8 blockIdx )
|
|
{
|
|
vuint8 result;
|
|
|
|
/* Compare currently used number of address regions against configured max. value */
|
|
if (diagSegmentList.nrOfSegments < SWM_DATA_MAX_NOAR)
|
|
{
|
|
currentSegment = diagSegmentList.nrOfSegments;
|
|
|
|
/* Store segment address, length and logical block index for later use */
|
|
diagSegmentList.segmentInfo[currentSegment].targetAddress = FblDiagGetMemAddr(segAddr);
|
|
diagSegmentList.segmentInfo[currentSegment].length = segLength;
|
|
|
|
/* Store reference to this segment in blockHeader */
|
|
blockHeader[blockIdx].segmentIdx[blockHeader[blockIdx].nrOfSegments] = currentSegment;
|
|
|
|
/* Increment segment counters */
|
|
diagSegmentList.nrOfSegments++;
|
|
blockHeader[blockIdx].nrOfSegments++;
|
|
|
|
/* Return index of current list entry */
|
|
result = currentSegment;
|
|
}
|
|
else
|
|
{
|
|
/* Segment list full, reject creation of new entry */
|
|
result = kDiagSegmentOutOfRange;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagGetMaxTransferDataBlockLength
|
|
**********************************************************************************************************************/
|
|
/*! \brief Evaluate maximum TransferData block length for active connection
|
|
* \details Length is the minimum of link payload length and configured diagnostic buffer size
|
|
* \return TransferData block length applicable for active connection
|
|
**********************************************************************************************************************/
|
|
static tCwDataLengthType FblDiagGetMaxTransferDataBlockLength(void)
|
|
{
|
|
tCwDataLengthType maxBlockLength;
|
|
|
|
/* Get payload limit of active communication link */
|
|
maxBlockLength = FblCwGetPayloadLimit();
|
|
|
|
/* Limit block length to available diagnostic buffer size */
|
|
if (FBL_DIAG_BUFFER_LENGTH < maxBlockLength)
|
|
{
|
|
maxBlockLength = FBL_DIAG_BUFFER_LENGTH;
|
|
}
|
|
|
|
#if defined( FBL_ENABLE_UNALIGNED_DATA_TRANSFER )
|
|
#else
|
|
/* Align length to maximum memory segment size */
|
|
maxBlockLength = (tCwDataLengthType)(((maxBlockLength - 2u) & FblInvert32Bit(FBL_MAX_SEGMENT_SIZE - 1u)) + 2u);
|
|
#endif /* FBL_ENABLE_UNALIGNED_DATA_TRANSFER */
|
|
|
|
return maxBlockLength;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagPostInit
|
|
**********************************************************************************************************************/
|
|
/*! \brief This function is called from FblInit()
|
|
* \details The diagnostic buffer is prepared to be able to handle the diagnostic request.
|
|
**********************************************************************************************************************/
|
|
void FblDiagPostInit( void )
|
|
{
|
|
|
|
if (GetLockedByInit())
|
|
{
|
|
if (kFblOk == FblCwPrepareResponseAddress())
|
|
{
|
|
/* Clear state if programming session request "simulation" could be done */
|
|
ClrLockedByInit();
|
|
/* Prepare diag buffer */
|
|
diagServiceCurrent = kDiagSidDiagnosticSessionControl;
|
|
DiagBuffer[kDiagFmtServiceId] = kDiagSidDiagnosticSessionControl;
|
|
DiagBuffer[kDiagFmtSubparam] = kDiagSubProgrammingSession;
|
|
/* Omit response for programming request */
|
|
DiagBuffer[kDiagFmtSubparam] |= 0x80u;
|
|
DiagDataLength = kDiagRqlDiagnosticSessionControl;
|
|
|
|
|
|
/* Simulate data indication */
|
|
FblDiagRxStartIndication();
|
|
FblDiagRxIndication(DiagBuffer, DiagDataLength + 1u);
|
|
}
|
|
else
|
|
{
|
|
/* Do the same as if a functional tester present with SPRMB was received in order to unlock/free
|
|
* the diagnostic buffer for new requests */
|
|
DiagResetResponseHandling();
|
|
FblCwResetRxBlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSessionTransition
|
|
**********************************************************************************************************************/
|
|
/*! \brief Common tasks which shall be executed during session transition
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return kFblOk: Session transition completed successfully
|
|
* kFblFailed: Session transition failed
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static tFblResult FblDiagSessionTransition(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pbDiagBuffer, tCwDataLengthType diagReqDataLen)
|
|
{
|
|
tFblResult result = kFblOk;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 2 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Reset internal states */
|
|
ClrSecurityKeyAllowed();
|
|
ClrTransferDataAllowed();
|
|
ClrTransferDataSucceeded();
|
|
|
|
FblDiagInitDownloadSequence();
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSessionControlParamInit
|
|
**********************************************************************************************************************/
|
|
/*! \brief General initialization of response parameter and download preparation.
|
|
* \pre All other conditions for a successful session transition have been fulfilled.
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
**********************************************************************************************************************/
|
|
static void FblDiagSessionControlParamInit(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pbDiagBuffer, tCwDataLengthType diagReqDataLen)
|
|
{
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/*
|
|
* Save the requested session type and adapt the P2 timing (if required).
|
|
* Note: the SPRMIB has been cleared by CheckSuppressPosRspMsgIndication()
|
|
* before and doesn't have to be considered here.
|
|
*/
|
|
SetDiagSessionType(pbDiagBuffer[kDiagFmtSubparam]);
|
|
|
|
/* Diagnostic session timing */
|
|
pbDiagBuffer[kDiagFmtSubparam + 1u] = (vuint8)(GetDiagSessionTimingP2() >> 8u);
|
|
pbDiagBuffer[kDiagFmtSubparam + 2u] = (vuint8) GetDiagSessionTimingP2();
|
|
pbDiagBuffer[kDiagFmtSubparam + 3u] = (vuint8)(GetDiagSessionTimingP2Star() >> 8u);
|
|
pbDiagBuffer[kDiagFmtSubparam + 4u] = (vuint8) GetDiagSessionTimingP2Star();
|
|
}
|
|
|
|
/* Diagnostic service handlers *********************************************/
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerDefaultSession
|
|
**********************************************************************************************************************/
|
|
/*! \brief Switch to default session, issue reset if necessary
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerDefaultSession)
|
|
{
|
|
/* Switch to default session by issuing a reset */
|
|
|
|
/* Initialize parameters for SessionControl response */
|
|
FblDiagSessionControlParamInit(pbDiagBuffer, diagReqDataLen);
|
|
|
|
/* The response will be sent by FblDiagEcuReset */
|
|
FblDiagEcuReset(kDiagResetPutResponse, RESET_RESPONSE_SDS_REQUIRED);
|
|
|
|
/* Shutdown is performed in main loop */
|
|
|
|
return kFblOk;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerProgrammingSession
|
|
**********************************************************************************************************************/
|
|
/*! \brief Switch to programming session
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerProgrammingSession)
|
|
{
|
|
tFblResult result;
|
|
V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * localPbDiagBuffer;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
#endif
|
|
|
|
/* ESCAN00067433: Stop background operations of FblLib_Mem */
|
|
DiagBuffer = FblMemInit();
|
|
localPbDiagBuffer = DiagBuffer;
|
|
|
|
/* Deinitialize loaded memory driver(s) */
|
|
FblDeinitMemoryDriver();
|
|
|
|
/* Initialize parameters for SessionControl response */
|
|
FblDiagSessionControlParamInit(localPbDiagBuffer, diagReqDataLen);
|
|
|
|
/*
|
|
* ESCAN00042572: switch session immediately to ensure correct S3 timer
|
|
* handling in DiagResponseProcessor()/FblDiagTpConfirmation().
|
|
*/
|
|
SetDiagProgrammingSession();
|
|
|
|
/* Send response */
|
|
DiagProcessingDone(kDiagRslDiagnosticSessionControl);
|
|
|
|
/* Execute common (post) session transition tasks */
|
|
result = FblDiagSessionTransition(localPbDiagBuffer, diagReqDataLen);
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerTesterPresent
|
|
**********************************************************************************************************************/
|
|
/*! \brief TesterPresent service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTesterPresent)
|
|
{
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 2 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Simply transmit a positive response message */
|
|
DiagProcessingDone(kDiagRslTesterPresent);
|
|
|
|
return kFblOk;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerEcuReset
|
|
**********************************************************************************************************************/
|
|
/*! \brief Issue reset
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerEcuReset)
|
|
{
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 2 */ /* MD_MSR_DummyStmt */
|
|
(void)pbDiagBuffer;
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
FblDiagEcuReset(kDiagResetPutResponse, RESET_RESPONSE_ECURESET_REQUIRED);
|
|
|
|
/* Shutdown is performed in main loop */
|
|
return kFblOk;
|
|
}
|
|
|
|
#if defined( FBL_ENABLE_USERROUTINE )
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRoutineControl
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - No (predefined) routine found
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRoutineControl)
|
|
{
|
|
tFblResult result;
|
|
|
|
result = kFblOk;
|
|
|
|
/*
|
|
* Call user function to process user specific routine(s). Pass pointer to
|
|
* diag buffer which points after the SID.
|
|
*/
|
|
ApplDiagRoutineControl(&(pbDiagBuffer[kDiagFmtSubparam]), diagReqDataLen);
|
|
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* No NRC returned, send the response */
|
|
DiagProcessingDone(DiagDataLength);
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_ENABLE_USERROUTINE */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcActivateSbl
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - Activate Secondary Bootloader subroutine
|
|
* \pre SBL has been downloaded
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6050 1 */ /* MD_MSR_STCAL */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcActivateSbl)
|
|
{
|
|
tFblResult result;
|
|
tBlockDescriptor blockDescriptor;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Send a RCRRP to avoid a timeout during SBL verification and activation */
|
|
DiagExRCRResponsePending(kForceSendResponsePending);
|
|
|
|
result = FblLbtGetBlockDescriptorByNr(FBL_LBT_SBL_BLOCK_NUMBER, &blockDescriptor);
|
|
|
|
if (kFblOk == result)
|
|
{
|
|
/* Perform SBL block verification */
|
|
result = ApplFblValidateBlock(blockDescriptor);
|
|
}
|
|
|
|
if (kFblOk == result)
|
|
{
|
|
/* Set SBL block state to 'verified' */
|
|
blockHeader[FBL_MTAB_SBL_BLOCK_NUMBER].state = kBlockState_Verified;
|
|
result = FblInitMemoryDriver();
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* All following download requests are directed to non-volatile memory */
|
|
transferType = DOWNLOAD_FLASH;
|
|
/* Activation of SBL (and other memory drivers) succeeded, prepare positive response */
|
|
pbDiagBuffer[kDiagFmtSubRoutineInfo] = (vuint8)((kDiagSubRoutineType1_Sync << 4u) | kDiagSubRoutineStatusCompleted);
|
|
}
|
|
else
|
|
{
|
|
/* ESCAN00066098: Activation of SBL failed, send negative response */
|
|
DiagNRCConditionsNotCorrect();
|
|
}
|
|
|
|
/* Send response */
|
|
DiagProcessingDone(kDiagRslRcActivateSbl);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcCheckValidApp
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - Check Valid Application subroutine
|
|
* \pre Application software has been downloaded
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030, 6050, 6080 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STCAL, MD_MSR_STMIF */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcCheckValidApp)
|
|
{
|
|
tFblResult result;
|
|
tFblLbtBlockFilter blockFilter;
|
|
tBlockDescriptor iterBlock;
|
|
tDiagSegmentList localSegmentList;
|
|
FL_SegmentListType localSegmentListSB;
|
|
FL_SegmentInfoType segListPerBlock[SWM_DATA_MAX_NOAR];
|
|
vuint8 idxSeg;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Initialize return value */
|
|
result = kFblOk;
|
|
/* Initialize localSegmentList */
|
|
localSegmentList.nrOfSegments = 0u;
|
|
for(idxSeg = 0u; idxSeg < SWM_DATA_MAX_NOAR; idxSeg++)
|
|
{
|
|
localSegmentList.segmentInfo[idxSeg].targetAddress = 0u;
|
|
localSegmentList.segmentInfo[idxSeg].length = 0u;
|
|
}
|
|
|
|
/* Check if any data was downloaded besides the SBL */
|
|
if ((kBlockNrInvalid != currentBlock) && (FBL_MTAB_SBL_BLOCK_NUMBER != currentBlock))
|
|
{
|
|
/* Send RCRRP message to avoid a P2 timeout during validation */
|
|
DiagExRCRResponsePending(kForceSendResponsePending);
|
|
|
|
/* Iterate over logical blocks to determine the validity of the downloaded software/data */
|
|
FblLbtBlockFilterInit(&blockFilter);
|
|
FblLbtBlockFilterSetBlockType(&blockFilter, kBlockTypeApplication);
|
|
iterBlock = FblLbtBlockFirst(&blockFilter);
|
|
while (FblLbtBlockDone() == FALSE)
|
|
{
|
|
{
|
|
/* Check validity of logical block by calling ApplFblValidateBlock() */
|
|
if (ApplFblValidateBlock(iterBlock) == kFblOk)
|
|
{
|
|
{
|
|
if (blockHeader[iterBlock.blockNr].state == kBlockState_Erased)
|
|
{
|
|
/* Get the segment list */
|
|
(void)FblDiagGetSegmentList(iterBlock.blockNr, &localSegmentList);
|
|
|
|
for(idxSeg = 0u; idxSeg < localSegmentList.nrOfSegments; idxSeg++)
|
|
{
|
|
segListPerBlock[idxSeg].transferredAddress = localSegmentList.segmentInfo[idxSeg].targetAddress;
|
|
segListPerBlock[idxSeg].targetAddress = localSegmentList.segmentInfo[idxSeg].targetAddress;
|
|
segListPerBlock[idxSeg].length = localSegmentList.segmentInfo[idxSeg].length;
|
|
}
|
|
|
|
localSegmentListSB.nrOfSegments = localSegmentList.nrOfSegments; /* PRQA S 2983 */ /* MD_FblDiag_2983_2985_RedundantAssignment */
|
|
localSegmentListSB.segmentInfo = segListPerBlock; /* PRQA S 2983 */ /* MD_FblDiag_2983_2985_RedundantAssignment */
|
|
|
|
/* Update MAC for Secure Boot */
|
|
if (ApplFblUpdateBlockMac(&iterBlock, &localSegmentListSB) == kFblOk) /* PRQA S 2741 */ /* MD_FblDiag_2741 */
|
|
{
|
|
/* Set block state to 'verified' */
|
|
blockHeader[iterBlock.blockNr].state = kBlockState_Verified;
|
|
}
|
|
else
|
|
{
|
|
/* Check logical block assignment */
|
|
if (iterBlock.mandatoryType == TRUE) /* PRQA S 2880 */ /* MD_FblDiag_2880_UnreachableCode */
|
|
{
|
|
/* MAC calculation on mandatory Block failed, set overall verification result to 'failed' */
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Set block state to 'verified' */
|
|
blockHeader[iterBlock.blockNr].state = kBlockState_Verified;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check logical block assignment */
|
|
if (iterBlock.mandatoryType == TRUE)
|
|
{
|
|
/* Mandatory Block not valid, set overall verification result to 'failed' */
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
}
|
|
/* Prepare next cycle */
|
|
iterBlock = FblLbtBlockNext();
|
|
}
|
|
|
|
if (kFblOk == result)
|
|
{
|
|
/*
|
|
* All mandatory logical blocks are valid. Let the user do the overall validity check (e.g. compatibility check,
|
|
* multi-processor configurations). The result has to be persisted inside the user function and can be
|
|
* evaluated during startup in ApplFblIsValidApp().
|
|
*/
|
|
result = ApplFblValidateApp();
|
|
}
|
|
|
|
/*
|
|
* There are three valid return states of the validation function:
|
|
*
|
|
* result | DiagGetError() | state
|
|
* ------------|-----------------|---------------------------------------
|
|
* kFblOk | kDiagErrorNone | download valid, pattern written
|
|
* kFblFailed | kDiagErrorNone | download invalid, pattern not written
|
|
* kFblFailed | !kDiagErrorNone | download valid, pattern write error
|
|
*/
|
|
|
|
/* Catch invalid combinations of return value and NRC state */
|
|
assertFblUser(((result == kFblOk) && (DiagGetError() == kDiagErrorNone)) ||
|
|
((result != kFblOk) && (DiagGetError() == kDiagErrorNone)) ||
|
|
((result != kFblOk) && (DiagGetError() != kDiagErrorNone)),
|
|
kFblOemAssertIllegalReturnValue);
|
|
|
|
}
|
|
|
|
/* Proceed only if no NRC has been set in the user functions */
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* Check if all necessary files are present/compatible for the application to be considered valid */
|
|
if (ApplFblIsValidApp() != kApplValid)
|
|
{
|
|
pbDiagBuffer[kDiagFmtSubRoutineCheckValidAppStatus] = kDiagSubRoutineApplInvalid;
|
|
/* Send positive response */
|
|
DiagProcessingDone(kDiagRslRcCheckValidApp);
|
|
}
|
|
else
|
|
{
|
|
{
|
|
pbDiagBuffer[kDiagFmtSubRoutineCheckValidAppStatus] = kDiagSubRoutineApplValid;
|
|
/* Routine is complete */
|
|
pbDiagBuffer[kDiagFmtSubRoutineInfo] = (vuint8)((kDiagSubRoutineType1_Sync << 4u) | kDiagSubRoutineStatusCompleted);
|
|
|
|
/* Send positive response */
|
|
DiagProcessingDone(kDiagRslRcCheckValidApp);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Assure correct return value */
|
|
result = kFblFailed;
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
}
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
/***********************************************************************************************************************
|
|
* FblDiagTokenLengthCheck
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check whether that the token length is consistent with the received command
|
|
* \param[in] cmdType The Token mode from TokenCommandType
|
|
* \param[in] tokenLength The token length
|
|
* \return Possible return values:
|
|
* - tTokenHdlResult: result of the validation operation
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC */
|
|
static tTokenHdlResult FblDiagTokenLengthCheck(vuint8 cmdType, vuint16 tokenLength)
|
|
{
|
|
tTokenHdlResult resultTkn = kTokenHdlrOk;
|
|
|
|
/* Check that the token length is consistent with the received command */
|
|
if (cmdType == FBL_DIAG_TOKEN_CMD_REVERTPROD)
|
|
{
|
|
/* Mode 0 tokens are supported with and without signature */
|
|
if ((tokenLength != FBL_DIAG_TOKEN_MIN_SIZE) &&
|
|
(tokenLength != (FBL_DIAG_TOKEN_MIN_SIZE + SEC_SIZE_SIG_RSA2048)))
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
else if (cmdType == FBL_DIAG_TOKEN_CMD_PROGKEY)
|
|
{
|
|
/* Mode 5 tokens */
|
|
if (tokenLength != FBL_DIAG_TOKEN_MAX_SIZE)
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Mode 1-4 tokens always require a signature */
|
|
if (tokenLength != (FBL_DIAG_TOKEN_MIN_SIZE + SEC_SIZE_SIG_RSA2048))
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
|
|
return resultTkn;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagTokenKeyProcessing
|
|
**********************************************************************************************************************/
|
|
/*! \brief Function is used to perform key switching or key programming based on the received cmdType
|
|
* \param[in] cmdType The Token mode from TokenCommandType
|
|
* \param[in] tokenBufferPtr Pointer to the token
|
|
* \return Possible return values:
|
|
* - tTokenHdlResult: result of the validation operation
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673, 6010, 6030, 6080 1 */ /* MD_MSR_Rule8.13, MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STMIF */
|
|
static tTokenHdlResult FblDiagTokenKeyProcessing(vuint8 cmdType, V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBufferPtr)
|
|
{
|
|
tTokenHdlResult resultTkn = kTokenHdlrOk;
|
|
|
|
switch (cmdType)
|
|
{
|
|
#if defined( FBL_DIAG_MULTIPLE_KEY )
|
|
/* Multiple Key Use Case */
|
|
case FBL_DIAG_TOKEN_CMD_REVERTPROD:
|
|
{
|
|
/* Revert back to production key */
|
|
if (FblDiagCopyProductionKeyToUsedPersKey() != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagCopyUsedPersKeyToUsedNotPersKey() != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else
|
|
{
|
|
/* MISRA */
|
|
}
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVPERM:
|
|
{
|
|
/* Use development key until further request */
|
|
if (FblDiagCopyDevelopmentKeyToUsedNotPersKey() != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagCopyDevelopmentKeyToUsedPersKey() != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else
|
|
{
|
|
/* MISRA */
|
|
}
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVTEMP:
|
|
{
|
|
/* Use development key until next reset or Cmd 0 */
|
|
if (FblDiagCopyDevelopmentKeyToUsedNotPersKey() != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_PROGKEY:
|
|
{
|
|
vuint8 pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH + FBL_DIAG_KEY_EXP_LENGTH];
|
|
|
|
/* Program the new keys contained in the token. */
|
|
if (ApplFblTokenParseKey(FblDiagGetTokenDevKeyIndex(tokenBufferPtr), pubKeyBuffer) != kTokenHdlrOk)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetDevelopmentModKey(pubKeyBuffer, FBL_DIAG_KEY_MOD_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetDevelopmentExpKey(&pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH], FBL_DIAG_KEY_EXP_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (ApplFblTokenParseKey(FblDiagGetTokenTokenKeyIndex(tokenBufferPtr), pubKeyBuffer) != kTokenHdlrOk)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetTokenModKey(pubKeyBuffer, FBL_DIAG_KEY_MOD_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetTokenExpKey(&pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH], FBL_DIAG_KEY_EXP_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (ApplFblTokenParseKey(FblDiagGetTokenProdKeyIndex(tokenBufferPtr), pubKeyBuffer) != kTokenHdlrOk)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetProductionModKey(pubKeyBuffer, FBL_DIAG_KEY_MOD_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetProductionExpKey(&pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH], FBL_DIAG_KEY_EXP_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetUsedPersModKey(pubKeyBuffer, FBL_DIAG_KEY_MOD_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetUsedPersExpKey(&pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH], FBL_DIAG_KEY_EXP_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetUsedNotPersModKey(pubKeyBuffer, FBL_DIAG_KEY_MOD_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else if (FblDiagSetUsedNotPersExpKey(&pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH], FBL_DIAG_KEY_EXP_LENGTH) != SECM_OK)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
else
|
|
{
|
|
/* MISRA */
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
break;
|
|
}
|
|
#else /* FBL_DIAG_MULTIPLE_KEY */
|
|
/* Single Key Use Case */
|
|
case FBL_DIAG_TOKEN_CMD_REVERTPROD:
|
|
{
|
|
/* Revert back to production key */
|
|
ClrDiagDevelopmentKey();
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVPERM:
|
|
{
|
|
/* Use development key permanently (Not possible to revert to production key) */
|
|
SetDiagDevelopmentKey();
|
|
if (ApplFblWriteVerificationKey(V_NULL) != kFblOk)
|
|
{
|
|
resultTkn = kTokenHdlrKeyChangeFailed;
|
|
/* Revert back to production key, in case of failure */
|
|
ClrDiagDevelopmentKey();
|
|
}
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVTEMP:
|
|
{
|
|
/* Use development key until next reset or Cmd 0 */
|
|
SetDiagDevelopmentKey();
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_PROGKEY:
|
|
{
|
|
vuint8 isDevKeyActive = 0u;
|
|
vuint8 pubKeyBuffer[FBL_DIAG_KEY_MOD_LENGTH + FBL_DIAG_KEY_EXP_LENGTH];
|
|
|
|
/* Program the production key contained in the token (Not possible to revert to development key) */
|
|
if (GetDiagDevelopmentKey())
|
|
{
|
|
isDevKeyActive = 1u;
|
|
}
|
|
|
|
ClrDiagDevelopmentKey();
|
|
|
|
if (ApplFblTokenParseKey(FblDiagGetTokenProdKeyIndex(tokenBufferPtr), pubKeyBuffer) == kTokenHdlrOk)
|
|
{
|
|
/* The Production Key modulo contains sequentially also the exponent */
|
|
if (ApplFblWriteVerificationKey(pubKeyBuffer) != kFblOk)
|
|
{
|
|
resultTkn = kTokenHdlrKeyChangeFailed;
|
|
if (isDevKeyActive == 1u)
|
|
{
|
|
SetDiagDevelopmentKey();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
break;
|
|
}
|
|
#endif /* FBL_DIAG_MULTIPLE_KEY */
|
|
}
|
|
|
|
return resultTkn;
|
|
}
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcTokenDownload
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - Download a Token from the tester into internal RAM
|
|
* \pre Diagnostic module shall be initialized
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030, 6080 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STMIF */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcTokenDownload)
|
|
{
|
|
SecM_SignatureParamType verifyToken;
|
|
SecM_AsymKeyType keyChangeKey;
|
|
vuint8 *tokenBufferPtr;
|
|
tTokenHdlResult resultTkn = kTokenHdlrOk;;
|
|
tFblResult result;
|
|
vuint8 cmdType;
|
|
vuint16 tokenLength;
|
|
|
|
/* Check programming mode - if the SBL is not present and activated, send NRC and do not process token further */
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
DiagNRCRequestSequenceError();
|
|
}
|
|
else
|
|
{
|
|
tokenLength = diagReqDataLen - 3u;
|
|
tokenBufferPtr = &pbDiagBuffer[kDiagFmtRoutineIdDataRecord];
|
|
/* Token shall be verified with respective key */
|
|
verifyTokenSignLength = tokenLength - SEC_SIZE_SIG_RSA2048;
|
|
/* Extract command */
|
|
cmdType = FblDiagGetTokenCommandType(tokenBufferPtr);
|
|
|
|
/* Check that the token length is consistent with the received command */
|
|
resultTkn = FblDiagTokenLengthCheck(cmdType, tokenLength);
|
|
|
|
/* Signature verification shall not be done for revert to production command */
|
|
if ((cmdType != FBL_DIAG_TOKEN_CMD_REVERTPROD) && (resultTkn == kTokenHdlrOk))
|
|
{
|
|
/* Here the Token signature will be verified */
|
|
/* This verification shall be in common between MKU and SKU */
|
|
/* Forcing the usage of an internal workspace */
|
|
verifyToken.currentHash.sigResultBuffer = (SecM_ResultBufferType)SEC_DEFAULT_WORKSPACE; /* PRQA S 0306 */ /* MD_FblDiag_0306 */
|
|
verifyToken.currentHash.length = SEC_DEFAULT_WORKSPACE_SIZE;
|
|
verifyToken.currentDataLength = V_NULL;
|
|
verifyToken.sigSourceBuffer = tokenBufferPtr;
|
|
verifyToken.sigByteCount = verifyTokenSignLength;
|
|
verifyToken.wdTriggerFct = &FblRealTimeSupportVoid;
|
|
|
|
if (FblDiagGetTokenKeyIndex(tokenBufferPtr) == FBL_DIAG_TOKEN_KEY_INDEX_0)
|
|
{
|
|
resultTkn = ApplFblGetTokenVerificationKey(&keyChangeKey);
|
|
verifyToken.key = (SecM_VerifyKeyType)&keyChangeKey; /* PRQA S 0314 */ /* MD_FblDiag_0314_KeyPtr */
|
|
}
|
|
else
|
|
{
|
|
/* For mode 1-4 use default internally configured key */
|
|
verifyToken.key = V_NULL;
|
|
}
|
|
}
|
|
|
|
if ((cmdType != FBL_DIAG_TOKEN_CMD_REVERTPROD) && (resultTkn == kTokenHdlrOk))
|
|
{
|
|
verifyToken.sigState = SEC_HASH_INIT;
|
|
resultTkn = kTokenHdlrSignatureFailed;
|
|
|
|
if (FblDiagVerifyTokenSignature(&verifyToken) == SECM_VER_OK)
|
|
{
|
|
verifyToken.sigState = SEC_HASH_COMPUTE;
|
|
if (FblDiagVerifyTokenSignature(&verifyToken) == SECM_VER_OK)
|
|
{
|
|
verifyToken.sigState = SEC_HASH_FINALIZE;
|
|
if (FblDiagVerifyTokenSignature(&verifyToken) == SECM_VER_OK)
|
|
{
|
|
verifyToken.sigState = SEC_SIG_VERIFY;
|
|
verifyToken.sigSourceBuffer = &tokenBufferPtr[verifyTokenSignLength];
|
|
verifyToken.sigByteCount = SEC_SIZE_SIG_RSA2048;
|
|
if (FblDiagVerifyTokenSignature(&verifyToken) == SECM_VER_OK)
|
|
{
|
|
resultTkn = kTokenHdlrOk;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Do token validation */
|
|
if (resultTkn == kTokenHdlrOk)
|
|
{
|
|
resultTkn = ApplFblPreValidateToken(tokenBufferPtr);
|
|
|
|
if(resultTkn == kTokenHdlrOk)
|
|
{
|
|
resultTkn = FblDiagValidateToken(tokenBufferPtr);
|
|
}
|
|
}
|
|
|
|
/* Do token copy into NVM after validation successfull */
|
|
if (resultTkn == kTokenHdlrOk)
|
|
{
|
|
/* Token shall be stored into the NVM */
|
|
if (ApplFblWriteToken(tokenBufferPtr, tokenLength) != kFblOk)
|
|
{
|
|
resultTkn = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
|
|
/* For mode 3 and 4 perform only Token validation, other modes perform key switch or key reprogramming */
|
|
if ((cmdType != FBL_DIAG_TOKEN_CMD_USEDEVDATE) && (cmdType != FBL_DIAG_TOKEN_CMD_USEDEVIGNI) && (resultTkn == kTokenHdlrOk))
|
|
{
|
|
resultTkn = FblDiagTokenKeyProcessing(cmdType, tokenBufferPtr);
|
|
}
|
|
|
|
/* Call callouts for every mode */
|
|
if (resultTkn == kTokenHdlrOk)
|
|
{
|
|
resultTkn = FblDiagTokenCallout(cmdType, tokenBufferPtr, tokenLength);
|
|
}
|
|
}
|
|
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* Send positive response */
|
|
pbDiagBuffer[kDiagFmtSubRoutineInfo] = (vuint8)resultTkn;
|
|
DiagProcessingDone(kDiagRslRcTokenDownload);
|
|
result = kFblOk;
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
# endif /* FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING */
|
|
#endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPDATE_SEC_BYTES )
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcUpdateSecBytes
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - Update Security Bytes subroutine (0x0305)
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcUpdateSecBytes)
|
|
{
|
|
tFblResult result = kFblOk;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Check programming mode - is the SBL present and activated? */
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
DiagNRCConditionsNotCorrect();
|
|
}
|
|
else
|
|
{
|
|
/* Check if write request is targeted at the correct security level */
|
|
if (pbDiagBuffer[kDiagFmtSubRoutineUpdateSecBytesLevel] != kDiagSecLevelFlash)
|
|
{
|
|
/* Invalid security level */
|
|
DiagNRCRequestOutOfRange();
|
|
}
|
|
else
|
|
{
|
|
/* Write security bytes to non-volatile memory */
|
|
result = ApplFblWriteSecurityBytes(&pbDiagBuffer[kDiagFmtSubRoutineUpdateSecBytesValue], kSecSecretKeyLength);
|
|
}
|
|
}
|
|
|
|
/* Send response immediately if no NRC has been set */
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* No NRC has been set, prepare positive response */
|
|
pbDiagBuffer[kDiagFmtSubRoutineIdPar] = (vuint8)((kDiagSubRoutineType1_Sync << 4) | kDiagSubRoutineStatusCompleted );
|
|
|
|
/* Send positive response */
|
|
DiagProcessingDone(kDiagRslRcUpdateSecBytes);
|
|
}
|
|
else
|
|
{
|
|
/* NRC has been set, set correct return value */
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_UPDATE_SEC_BYTES */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcEraseMemory
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - EraseMemory subroutine
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030, 6050 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STCAL */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcEraseMemory)
|
|
{
|
|
tFblResult result = kFblOk;
|
|
tBlockDescriptor eraseBlockDescriptor = {0};
|
|
tFblMemBlockInfo blockInfo = {0};
|
|
tFblAddress eraseAddress = 0u;
|
|
tFblLength eraseLength = 0u;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Initialize return value */
|
|
{
|
|
ClrEraseMemorySucceeded();
|
|
|
|
/* Extract erase region information from the diag buffer */
|
|
eraseAddress = (tFblAddress)FblMemGetInteger(kDiagRqlRcEraseMemoryAddress, &pbDiagBuffer[kDiagFmtSubRoutineEraseMemoryAddress]);
|
|
eraseLength = (tFblLength)FblMemGetInteger(kDiagRqlRcEraseMemoryLength, &pbDiagBuffer[kDiagFmtSubRoutineEraseMemorySize]);
|
|
|
|
/* Check if the memory driver has been downloaded and initialized */
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
/* Routine not supported in PBL */
|
|
DiagNRCConditionsNotCorrect();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Retrieve index of logical block (blockNr is kBlockNrInvalid in case of failure) */
|
|
result = FblLbtGetBlockDescriptorByAddressLength(eraseAddress, eraseLength, &eraseBlockDescriptor);
|
|
if ((result != kFblOk)
|
|
/* Check exact match of requested erase area with logical block */
|
|
|| (eraseBlockDescriptor.blockStartAddress != eraseAddress)
|
|
|| (eraseBlockDescriptor.blockLength != eraseLength)
|
|
)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Check type of requested block */
|
|
if (eraseBlockDescriptor.blockNr == FBL_MTAB_SBL_BLOCK_NUMBER)
|
|
{
|
|
/* Reject all erase requests which are directed to the SBL block */
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
#if defined( FBL_ENABLE_FLASH_ERASED_DETECTION )
|
|
if (ApplFblGetBlockErased(eraseBlockDescriptor) == kFlashErased)
|
|
{
|
|
result = kFblOk;
|
|
}
|
|
else
|
|
#endif /* FBL_ENABLE_FLASH_ERASED_DETECTION */
|
|
{
|
|
/* Avoid P2 timeout during invalidation */
|
|
DiagExRCRResponsePending(kForceSendResponsePending);
|
|
|
|
/* Invalidate application before erase procedure */
|
|
result = ApplFblInvalidateBlock(eraseBlockDescriptor);
|
|
|
|
/* Catch invalid combinations of return value and NRC state */
|
|
assertFblUser(((result == kFblOk) && (DiagGetError() == kDiagErrorNone)) ||
|
|
((result != kFblOk) && (DiagGetError() != kDiagErrorNone)),
|
|
kFblOemAssertIllegalReturnValue);
|
|
|
|
/* Proceed only if all entry conditions and block invalidation succeeded */
|
|
if (result == kFblOk)
|
|
{
|
|
/* Start erase procedure */
|
|
blockInfo.targetAddress = eraseBlockDescriptor.blockStartAddress;
|
|
blockInfo.targetLength = eraseBlockDescriptor.blockLength;
|
|
blockInfo.logicalAddress = eraseBlockDescriptor.blockStartAddress;
|
|
blockInfo.logicalLength = eraseBlockDescriptor.blockLength;
|
|
/* Additional members are not used for erase indication */
|
|
|
|
result = FblMemRemapStatus(FblMemBlockEraseIndication(&blockInfo));
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
#if defined( FBL_ENABLE_FLASH_ERASED_DETECTION )
|
|
(void)ApplFblSetBlockErased(eraseBlockDescriptor);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Remember erased state */
|
|
SetEraseMemorySucceeded();
|
|
lastErasedBlock = eraseBlockDescriptor.blockNr;
|
|
blockHeader[eraseBlockDescriptor.blockNr].state = kBlockState_Erased;
|
|
}
|
|
|
|
/* Send response immediately if no NRC has been set */
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* No NRC has been set, prepare positive response */
|
|
if (result == kFblOk)
|
|
{
|
|
pbDiagBuffer[kDiagFmtSubRoutineIdPar] = (vuint8)((kDiagSubRoutineType1_Sync << 4) | kDiagSubRoutineStatusCompleted );
|
|
/* Send positive response */
|
|
DiagProcessingDone(kDiagRslRcEraseMemory);
|
|
}
|
|
else
|
|
{
|
|
/* ESCAN00066098: Erase procedure failed, send negative response */
|
|
DiagNRCGeneralProgrammingFailure();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* NRC has been set, set correct return value */
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRcCheckProgDep
|
|
**********************************************************************************************************************/
|
|
/*! \brief RoutineControl - CheckProgrammingDependencies subroutine
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRcCheckProgDep)
|
|
{
|
|
tFblAddress checkStartAddress;
|
|
tFblLength checkLength;
|
|
tFblResult result;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Extract check address range */
|
|
checkStartAddress = FblMemGetInteger(kDiagRqlRcCheckProgDepMemoryAddress, &pbDiagBuffer[kDiagFmtSubRoutineCheckMemoryAddress]);
|
|
checkLength = FblMemGetInteger(kDiagRqlRcCheckProgDepMemorySize, &pbDiagBuffer[kDiagFmtSubRoutineCheckMemorySize]);
|
|
|
|
if (checkLength < kDiagCheckProgDepAdressMinLength)
|
|
{
|
|
/* Address length is under the minimal length */
|
|
result = kFblFailed;
|
|
}
|
|
else if (FblMemSegmentNrGet(checkStartAddress) < 0)
|
|
{
|
|
/* Address start is not located in the Flash Block Table */
|
|
result = kFblFailed;
|
|
}
|
|
else if (FblMemSegmentNrGet(checkStartAddress + checkLength - 1u) < 0)
|
|
{
|
|
/* Address end is not located in the Flash Block Table */
|
|
result = kFblFailed;
|
|
}
|
|
else
|
|
{
|
|
result = kFblOk;
|
|
}
|
|
|
|
/* Ensure that a valid address */
|
|
if (result != kFblOk)
|
|
{
|
|
/* Requested download region does not meet requirements; abort service handling */
|
|
DiagNRCRequestOutOfRange();
|
|
}
|
|
else
|
|
{
|
|
/* Setup segment information */
|
|
verifySegmentInfo[0].targetAddress = checkStartAddress;
|
|
verifySegmentInfo[0].transferredAddress = checkStartAddress;
|
|
verifySegmentInfo[0].length = checkLength;
|
|
verifyParam.segmentList.nrOfSegments = 1;
|
|
|
|
/* Trigger checksum calculation */
|
|
verifyParam.blockStartAddress = checkStartAddress;
|
|
verifyParam.blockLength = checkLength;
|
|
/* No actual verification data included in request */
|
|
verifyParam.verificationData = verifyOutputBuf;
|
|
verifyParam.wdTriggerFct = &FblRealTimeSupportVoid;
|
|
/* Routine is restricted to ROM access */
|
|
verifyParam.readMemory = (FL_ReadMemoryFctType)&FblReadProm;
|
|
|
|
/* Call HIS verification interface to calculate CRC */
|
|
if (SECM_VER_OK == FblDiagVerification(&verifyParam))
|
|
{
|
|
/* RoutineInfo */
|
|
pbDiagBuffer[kDiagFmtSubRoutineInfo] = (vuint8)((kDiagSubRoutineType1_Sync << 4) | kDiagSubRoutineStatusCompleted);
|
|
|
|
/* CRC value is stored in last two byte of buffer */ /* PRQA S 0314 1 */ /* MD_FblDiag_0314_MemCpy */
|
|
(void)MEMCPY(&pbDiagBuffer[kDiagFmtSubRoutineCrcHigh], &verifyOutputBuf[FBL_DIAG_CRC_OFFSET], SEC_SIZE_CHECKSUM_CRC);
|
|
|
|
/* Send positive response */
|
|
DiagProcessingDone(kDiagRslRcCheckProgDep);
|
|
}
|
|
else
|
|
{
|
|
/* ESCAN00066098: Verification failed (most likely memory read error), send negative response */
|
|
DiagNRCGeneralReject();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSecAccessSeed
|
|
**********************************************************************************************************************/
|
|
/*! \brief Process security seed request
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \param[in] secLevel Requested security level
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static tFblResult FblDiagSecAccessSeed(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen, vuint8 secLevel )
|
|
{
|
|
vuint8 returnCode;
|
|
vuint8 i;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 2 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
(void)secLevel;
|
|
# if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
# else
|
|
(void)pbDiagBuffer; /* PRQA S 3112 */ /* MD_MSR_DummyStmt */
|
|
# endif
|
|
#endif
|
|
|
|
#if ( SYSSERVICE_SECMODHIS_VERSION >= 0x0300u )
|
|
/* Cancel all SecM jobs if security access is performed anew, for example if the download is restarted */
|
|
SecM_CancelAllJobs();
|
|
#endif
|
|
|
|
/* Get currently unlocked level */
|
|
if (GetCurrentSecLvl() != kDiagSecLevelNone)
|
|
{
|
|
/* ECU is already unlocked, send zero seed */
|
|
for (i = 0; i < GetRequestedSeedLength(); i++)
|
|
{
|
|
pbDiagBuffer[kDiagFmtSeedKeyStart + i] = 0x00u;
|
|
}
|
|
|
|
/* Security access already granted. Don't allow a key to be submitted. */
|
|
ClrSecurityKeyAllowed();
|
|
returnCode = kFblFailed;
|
|
}
|
|
else
|
|
{
|
|
/* Generate seed by application function */
|
|
if (ApplFblSecuritySeed() == kFblOk)
|
|
{
|
|
/* Accept security key next */
|
|
returnCode = kFblOk;
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
/* Remember security level */
|
|
diagRequestedSecLvl = pbDiagBuffer[kDiagFmtSubparam];
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* Error occurred during seed computation */
|
|
FblErrStatSetError(FBL_ERR_SEED_GENERATION_FAILED);
|
|
DiagNRCConditionsNotCorrect();
|
|
returnCode = kFblFailed;
|
|
}
|
|
}
|
|
|
|
#if defined( FBL_ENABLE_SEC_ADDITIONAL_LEVELS )
|
|
if (returnCode != kFblOk)
|
|
{
|
|
/* Invalidate requested security level */
|
|
diagRequestedSecLvlIdx = kDiagInvalidSecLvlIdx;
|
|
}
|
|
#endif
|
|
|
|
/* Set response length used by fbl_diag: (SID +) sub parameter + seed length */
|
|
DiagProcessingDone(1u + GetRequestedSeedLength());
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSecAccessKey
|
|
**********************************************************************************************************************/
|
|
/*! \brief Process security key request
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \param[in] secLevel Requested security level
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static tFblResult FblDiagSecAccessKey(V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType diagReqDataLen, vuint8 secLevel)
|
|
{
|
|
vuint8 returnCode;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 2 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
(void)secLevel;
|
|
#endif
|
|
|
|
/*
|
|
* Clearing the SecurityKeyAllowed state cannot be done automatically
|
|
* (by the dispatcher) because errors other than key comparison (e.g.
|
|
* length check) should not reset the state.
|
|
*/
|
|
ClrSecurityKeyAllowed();
|
|
|
|
/* Check security access key in application function */
|
|
returnCode = ApplFblSecurityKey();
|
|
|
|
if (returnCode != kFblOk)
|
|
{
|
|
/* Set NRC */
|
|
DiagNRCInvalidKey();
|
|
}
|
|
else
|
|
{
|
|
SetCurrentSecLvl((vuint8)(pbDiagBuffer[kDiagFmtSubparam] - 1u));
|
|
DiagProcessingDone(kDiagRslSecurityAccessKey);
|
|
}
|
|
|
|
return returnCode;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerSecAccessSeed
|
|
**********************************************************************************************************************/
|
|
/*! \brief SecurityAccess - Seed handling for security level "Flash"
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerSecAccessSeed)
|
|
{
|
|
return FblDiagSecAccessSeed(pbDiagBuffer, diagReqDataLen, kDiagSecLevelFlash);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerSecAccessKey
|
|
**********************************************************************************************************************/
|
|
/*! \brief SecurityAccess - Key handling for security level "Flash Programming"
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerSecAccessKey)
|
|
{
|
|
return FblDiagSecAccessKey(pbDiagBuffer, diagReqDataLen, kDiagSecLevelFlash);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRequestDownload
|
|
**********************************************************************************************************************/
|
|
/*! \brief RequestDownload service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 2889, 6010, 6030, 6050, 6080 1 */ /* MD_FblDiag_2889, MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STCAL, MD_MSR_STMIF */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestDownload)
|
|
{
|
|
vuint8 lengthFormat = 0u;
|
|
vuint8 addrFormat = 0u;
|
|
tFblLbtBlockNr requestedDownloadBlock = 0u;
|
|
tBlockDescriptor logicalBlockDescriptor = {0};
|
|
tFblLength transferLength = 0u;
|
|
tFblMemSegmentInfo segInfo;
|
|
tFblMemBlockInfo blockInfo;
|
|
tFblResult result = kFblOk;
|
|
tCwDataLengthType maxBlockLength;
|
|
V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * localPbDiagBuffer = V_NULL;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
# if defined( FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
# endif
|
|
#endif
|
|
|
|
/* Initialize return value */
|
|
{
|
|
localPbDiagBuffer = pbDiagBuffer;
|
|
|
|
/* Get encryption and compression method */
|
|
dataFormatId = localPbDiagBuffer[kDiagFmtSubparam];
|
|
|
|
#if defined( FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI )
|
|
if (localPbDiagBuffer[kDiagFmtFormatOffset] != ((vuint8)(kDiagSubMaxLengthFormat << 4u) | kDiagSubMaxAddrFormat))
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
|
|
lengthFormat = kDiagSubMaxLengthFormat;
|
|
addrFormat = kDiagSubMaxAddrFormat;
|
|
#else
|
|
/* Get address- and length format */
|
|
lengthFormat = (vuint8)((localPbDiagBuffer[kDiagFmtFormatOffset] & kDiagFmtLengthMask) >> 4u);
|
|
addrFormat = (vuint8)(localPbDiagBuffer[kDiagFmtFormatOffset] & kDiagFmtAddrMask);
|
|
|
|
if ((lengthFormat < kDiagSubMinLengthFormat)
|
|
|| (lengthFormat > kDiagSubMaxLengthFormat)
|
|
|| (addrFormat < kDiagSubMinAddrFormat)
|
|
|| (addrFormat > kDiagSubMaxAddrFormat))
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
if (diagReqDataLen != (kDiagRqlRequestDownload + lengthFormat + addrFormat))
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI */
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
#if defined( FBL_ENABLE_DATA_PROCESSING )
|
|
# if defined( FBL_ENABLE_ENCRYPTION_MODE )
|
|
# else
|
|
/* No encrypted data supported */
|
|
if (FblDiagGetEncryptionMode(dataFormatId) != kDiagSubNoEncryption)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
# endif /* FBL_ENABLE_ENCRYPTION_MODE */
|
|
# if defined( FBL_ENABLE_COMPRESSION_MODE )
|
|
# else
|
|
/* No compressed data supported */
|
|
if (FblDiagGetCompressionMode(dataFormatId) != kDiagSubNoCompression)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
# endif /* FBL_ENABLE_COMPRESSION_MODE */
|
|
#else
|
|
if (dataFormatId != kDiagSubNoDataProcessing)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
#endif /* FBL_ENABLE_DATA_PROCESSING */
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Init expected sequence counter for TransferData */
|
|
expectedSequenceCnt = kDiagInitSequenceNum;
|
|
/* Init current sequence counter for TransferData */
|
|
currentSequenceCnt = kDiagInitSequenceNum;
|
|
|
|
/* Extract address and length from request */
|
|
transferAddress = (tFblAddress)FblMemGetInteger(addrFormat, &localPbDiagBuffer[kDiagFmtAddrOffset]);
|
|
transferRemainder = (tFblLength)FblMemGetInteger(lengthFormat, &localPbDiagBuffer[kDiagFmtAddrOffset + addrFormat]);
|
|
|
|
/* Check if length is equal to zero */
|
|
if (transferRemainder == 0u)
|
|
{
|
|
/* Length zero is unaccepted */
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
#if defined( FBL_ENABLE_PROCESSED_DATA_LENGTH )
|
|
/*
|
|
* If the requested download contains compressed or encrypted data, the requested download length refers to the
|
|
* size of the transfer data (i.e. the length of the processed (decrypted/decompressed) data may differ from the
|
|
* requested download length).
|
|
*/
|
|
if (dataFormatId != kDiagSubNoDataProcessing)
|
|
{
|
|
/*
|
|
* Check the start address only. Flash boundary check not possible here because the resulting length of the
|
|
* processed data is not known. Additional check performed in programming routine.
|
|
*/
|
|
transferLength = 1u;
|
|
}
|
|
else
|
|
#endif /* FBL_ENABLE_PROCESSED_DATA_LENGTH */
|
|
{
|
|
transferLength = transferRemainder;
|
|
}
|
|
|
|
/* Retrieve block descriptor of requested logical block */
|
|
result = FblLbtGetBlockDescriptorByAddressLength(transferAddress, transferLength, &logicalBlockDescriptor);
|
|
|
|
/* Ensure that a valid block is set */
|
|
if (result != kFblOk)
|
|
{
|
|
/* Requested download region is outside of the configured logical blocks; abort service handling */
|
|
DiagNRCRequestOutOfRange();
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
requestedDownloadBlock = logicalBlockDescriptor.blockNr;
|
|
|
|
if (transferType == DOWNLOAD_FLASH)
|
|
{
|
|
/* Check state flags */
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
DiagNRCConditionsNotCorrect();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
else /* transferType == DOWNLOAD_RAM */
|
|
{
|
|
assertFbl(!GetMemDriverInitialized(), kFblOemAssertIllegalExecutionPath);
|
|
|
|
/* Check type of requested block */
|
|
if (requestedDownloadBlock != FBL_MTAB_SBL_BLOCK_NUMBER)
|
|
{
|
|
/* Still in PBL: reject all downloads which are not directed to the SBL block */
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Restrict execution sequence and perform auto-erase */
|
|
if (blockHeader[requestedDownloadBlock].state == kBlockState_Init)
|
|
{
|
|
/* "Erase" flash code array (remove spurious code in buffer, support writing of presence pattern) */
|
|
/* Note: since the block state is reset in SessionControl, this will also clean up the flashcode buffer */
|
|
assertFbl(FLASH_SIZE == logicalBlockDescriptor.blockLength, kFblSysAssertParameterOutOfRange);
|
|
if (kFblMemStatus_Ok == FblMemEraseRegion(logicalBlockDescriptor.blockStartAddress, logicalBlockDescriptor.blockLength))
|
|
{
|
|
blockHeader[requestedDownloadBlock].state = kBlockState_Erased;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Check if the respective logical block has been erased */
|
|
if (blockHeader[requestedDownloadBlock].state != kBlockState_Erased)
|
|
{
|
|
/* Requested download region has not been erased; abort service handling */
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
(void)ApplFblAdjustLbtBlockData(&logicalBlockDescriptor);
|
|
|
|
/* Check if requested download block overwrites presence pattern (or exceeds logical block) */
|
|
if ((transferAddress + transferLength) > (logicalBlockDescriptor.blockStartAddress + logicalBlockDescriptor.blockLength))
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Copy data and address of segment to initialize diagSegmentList */
|
|
if (FblDiagSegmentNext(transferAddress, transferRemainder, requestedDownloadBlock) == kDiagSegmentOutOfRange)
|
|
{
|
|
FblErrStatSetError(FBL_ERR_TOO_MANY_SEGMENTS_IN_MODULE);
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/*** Download request has been accepted ***/
|
|
|
|
/* Initialize block data used by FblLib_Mem */
|
|
blockInfo.targetAddress = logicalBlockDescriptor.blockStartAddress;
|
|
blockInfo.targetLength = logicalBlockDescriptor.blockLength;
|
|
blockInfo.logicalAddress = blockInfo.targetAddress;
|
|
blockInfo.logicalLength = blockInfo.targetLength;
|
|
blockInfo.verifyRoutineInput.function = V_NULL;
|
|
blockInfo.verifyRoutineInput.param = V_NULL;
|
|
blockInfo.segmentList = &verifyParam.segmentList;
|
|
blockInfo.maxSegments = 1u; /* Only a single segment per block */
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_PIPELINED )
|
|
/* Check if a customer function is configured for this logical block */
|
|
if (SecM_Default != logicalBlockDescriptor.verifyOutput)
|
|
{
|
|
/* Switch to output verification (customer function will be set in FblDiagVerification() */
|
|
blockInfo.verifyRoutineOutput.function = &FblDiagVerification;
|
|
blockInfo.verifyRoutineOutput.param = &verifyParam;
|
|
blockInfo.verifyRoutinePipe.function = V_NULL;
|
|
blockInfo.verifyRoutinePipe.param = V_NULL;
|
|
}
|
|
else
|
|
{
|
|
/* Initialize the calculation (CCC: SHA256, DDD: CRC16) */
|
|
pipeVerifyParam.currentHash.sigResultBuffer = (vuint32)pipeVerifyBuf; /* PRQA S 0306 */ /* MD_FblDiag_0306 */
|
|
pipeVerifyParam.currentHash.length = sizeof(pipeVerifyBuf);
|
|
pipeVerifyParam.currentDataLength = &pipeVerifyLength;
|
|
# if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
/* Initialize the calculation (CCC: CRC16) */
|
|
pipeVerifyParamCrc.currentHash.sigResultBuffer = (vuint32)&pipeVerifyCrc; /* PRQA S 0306 */ /* MD_FblDiag_0306 */
|
|
pipeVerifyParamCrc.currentHash.length = sizeof(pipeVerifyCrc);
|
|
pipeVerifyParamCrc.currentDataLength = &pipeVerifyLengthCrc;
|
|
blockInfo.verifyRoutinePipe.function = &FblDiagVerifySignature;
|
|
# else
|
|
blockInfo.verifyRoutinePipe.function = &SecM_VerifyClassDDD;
|
|
# endif /* SEC_ENABLE_SECURITY_CLASS_CCC */
|
|
blockInfo.verifyRoutinePipe.param = &pipeVerifyParam;
|
|
blockInfo.verifyRoutineOutput.function = V_NULL;
|
|
blockInfo.verifyRoutineOutput.param = V_NULL;
|
|
}
|
|
#else
|
|
blockInfo.verifyRoutineOutput.function = &FblDiagVerification;
|
|
blockInfo.verifyRoutineOutput.param = &verifyParam;
|
|
blockInfo.verifyRoutinePipe.function = V_NULL;
|
|
blockInfo.verifyRoutinePipe.param = V_NULL;
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_PIPELINED */
|
|
blockInfo.readFct = &FblReadProm; /* FblWrapperRam required! */
|
|
|
|
/* Indicate the start of a new download block */
|
|
result = FblMemRemapStatus(FblMemBlockStartIndication(&blockInfo));
|
|
(void)FblDiagMemGetActiveBuffer();
|
|
if (result != kDiagErrorNone)
|
|
{
|
|
DiagSetError(result);
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Initialize segment data */
|
|
segInfo.targetAddress = transferAddress;
|
|
segInfo.targetLength = transferRemainder;
|
|
segInfo.logicalAddress = segInfo.targetAddress;
|
|
segInfo.logicalLength = segInfo.targetLength;
|
|
segInfo.type = kFblMemType_ROM; /* FblWrapperRam required! */
|
|
segInfo.dataFormat = dataFormatId;
|
|
|
|
/* Indicate start of new segment */
|
|
result = FblMemRemapStatus(FblMemSegmentStartIndication(&segInfo));
|
|
localPbDiagBuffer = FblDiagMemGetActiveBuffer();
|
|
|
|
if (result != kDiagErrorNone)
|
|
{
|
|
DiagSetError(result);
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Download of segment accepted: set logical block as "active" */
|
|
currentBlock = requestedDownloadBlock;
|
|
|
|
#if defined( FBL_ENABLE_FLASH_ERASED_DETECTION )
|
|
(void)ApplFblClrBlockErased(logicalBlockDescriptor);
|
|
#endif
|
|
|
|
/* Evaluate maximum block length for TransferData requests */
|
|
maxBlockLength = FblDiagGetMaxTransferDataBlockLength();
|
|
|
|
/* Length format dependent on maximum block length */
|
|
/* PRQA S 2880, 2992, 2996 TAG_FblDiag_ConstValue_1 */ /* MD_FblDiag_ConstValue */
|
|
if (maxBlockLength > 0xFFFFFFuL)
|
|
{
|
|
lengthFormat = 4u;
|
|
}
|
|
else if (maxBlockLength > 0xFFFFu)
|
|
{
|
|
lengthFormat = 3u;
|
|
}
|
|
else
|
|
{
|
|
/* Use at least two length bytes */
|
|
lengthFormat = 2u;
|
|
}
|
|
/* PRQA L:TAG_FblDiag_ConstValue_1 */
|
|
|
|
/* Set length format and maximum block length */
|
|
localPbDiagBuffer[kDiagFmtSubparam] = lengthFormat << 4u;
|
|
FblMemSetInteger(lengthFormat, maxBlockLength, &localPbDiagBuffer[kDiagFmtMaxBlockLengthHigh]);
|
|
|
|
DiagProcessingDone(kDiagRslRequestDownload + lengthFormat);
|
|
|
|
}
|
|
else
|
|
{
|
|
/* In case this was the RD for the SBL, and OTA is enable, revert the current partition in case of failure */
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerTransferDataDownload
|
|
**********************************************************************************************************************/
|
|
/*! \brief TransferData service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 2889, 3673 1 */ /* MD_FblDiag_2889, MD_MSR_Rule8.13 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTransferDataDownload)
|
|
{
|
|
tFblResult result;
|
|
|
|
/* Check if the requested sequence number is expected */
|
|
if (pbDiagBuffer[kDiagFmtSubparam] != expectedSequenceCnt )
|
|
{
|
|
/* Check if sequence number corresponds to a retry */
|
|
if (pbDiagBuffer[kDiagFmtSubparam] == currentSequenceCnt)
|
|
{
|
|
/* Handle the retries here */
|
|
|
|
/* Repetition of last transferData request */
|
|
/* Simply send a positive response without loading data to memory */
|
|
DiagProcessingDone(kDiagRslTransferData);
|
|
|
|
return kFblOk;
|
|
}
|
|
else /* Sequence number is not for a retry */
|
|
{
|
|
/* Send a WrongSequenceError */
|
|
DiagNRCWrongBlockSequenceCounter();
|
|
return kFblFailed;
|
|
}
|
|
}
|
|
|
|
result = FblMemRemapStatus(FblMemDataIndication(DiagBuffer, kDiagFmtDataOffset, (tFblLength)diagReqDataLen - 1u));
|
|
(void)FblDiagMemGetActiveBuffer();
|
|
if (result != kDiagErrorNone)
|
|
{
|
|
DiagSetError(result);
|
|
ClrTransferDataAllowed();
|
|
return kFblFailed;
|
|
}
|
|
|
|
transferRemainder -= ((tFblLength)diagReqDataLen - 1u);
|
|
|
|
if (transferRemainder == 0u)
|
|
{
|
|
/* Finalize writing the data */
|
|
result = FblMemRemapStatus(FblMemSegmentEndIndication(&totalProgramLength));
|
|
(void)FblDiagMemGetActiveBuffer();
|
|
|
|
if (result != kDiagErrorNone)
|
|
{
|
|
DiagSetError(result);
|
|
return kFblFailed;
|
|
}
|
|
|
|
result = FblMemRemapStatus(FblMemBlockEndIndication());
|
|
if (result != kDiagErrorNone)
|
|
{
|
|
DiagSetError(result);
|
|
return kFblFailed;
|
|
}
|
|
|
|
}
|
|
|
|
/* Memorize current counter */
|
|
currentSequenceCnt = expectedSequenceCnt;
|
|
|
|
/* Sequence counter value of next transferData request */
|
|
expectedSequenceCnt++;
|
|
|
|
DiagProcessingDone(kDiagRslTransferData);
|
|
return kFblOk;
|
|
}
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRequestUpload
|
|
**********************************************************************************************************************/
|
|
/*! \brief RequestUpload service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 2889 1 */ /* MD_FblDiag_2889 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestUpload)
|
|
{
|
|
vuint8 lengthFormat, addrFormat;
|
|
vuint8 requestedUploadBlock;
|
|
tFblResult result;
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
# if defined( FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
# endif
|
|
#endif
|
|
|
|
|
|
#if defined( FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI )
|
|
if (pbDiagBuffer[kDiagFmtFormatOffset] != ((vuint8)(kDiagSubMaxLengthFormat << 4) | kDiagSubMaxAddrFormat))
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
lengthFormat = kDiagSubMaxLengthFormat;
|
|
addrFormat = kDiagSubMaxAddrFormat;
|
|
#else
|
|
/* Get address- and length format */
|
|
lengthFormat = (vuint8)((pbDiagBuffer[kDiagFmtFormatOffset] & kDiagFmtLengthMask) >> 4);
|
|
addrFormat = pbDiagBuffer[kDiagFmtFormatOffset] & kDiagFmtAddrMask;
|
|
|
|
if ((lengthFormat < kDiagSubMinLengthFormat) || (lengthFormat > kDiagSubMaxLengthFormat) || (addrFormat < kDiagSubMinAddrFormat) || (addrFormat > kDiagSubMaxAddrFormat))
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
if (diagReqDataLen != (kDiagRqlRequestDownload + lengthFormat + addrFormat))
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
return kFblFailed;
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_FIXED_TRANSFER_ALFI */
|
|
|
|
/* Get encryption and compression method */
|
|
dataFormatId = pbDiagBuffer[kDiagFmtSubparam];
|
|
|
|
/* No encrypted or compressed data supported */
|
|
if (dataFormatId != kDiagSubNoDataProcessing)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Extract address and length from request */
|
|
transferAddress = (tFblAddress)FblMemGetInteger(addrFormat, &pbDiagBuffer[kDiagFmtAddrOffset]);
|
|
transferRemainder = (tFblLength)FblMemGetInteger(lengthFormat, &pbDiagBuffer[kDiagFmtAddrOffset + addrFormat]);
|
|
|
|
/* Check if length is equal to zero */
|
|
if (transferRemainder == 0u)
|
|
{
|
|
/* Length zero is unaccepted */
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Retrieve index of logical block (result is kBlockNrInvalid in case of failure) */
|
|
result = FblLbtGetBlockNrByAddressLength(transferAddress, transferRemainder, &requestedUploadBlock);
|
|
|
|
/* Ensure that a valid block number is set */
|
|
if (result != kFblOk)
|
|
{
|
|
/* Requested download region is outside of the configured logical blocks; abort service handling */
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Save data and address of segment for CRC calculation in TransferExit */
|
|
if (FblDiagSegmentNext(transferAddress, transferRemainder, requestedUploadBlock) == kDiagSegmentOutOfRange)
|
|
{
|
|
FblErrStatSetError(FBL_ERR_TOO_MANY_SEGMENTS_IN_MODULE);
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Check programming mode - is the SBL present and activated? */
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
DiagNRCConditionsNotCorrect();
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Init expected sequence counter for TransferData */
|
|
expectedSequenceCnt = kDiagInitSequenceNum;
|
|
/* Init current sequence counter for TransferData */
|
|
currentSequenceCnt = kDiagInitSequenceNum;
|
|
|
|
/* Use whole diag buffer size as block length for TransferDataUpload */
|
|
maxNumberOfBlockLength = (vuint16)FBL_DIAG_BUFFER_LENGTH;
|
|
|
|
/* Number of bytes reserved for maximum block length */
|
|
pbDiagBuffer[kDiagFmtSubparam] = kDiagMaxNumberOfBlockLengthLength << 4u;
|
|
|
|
/* Report block length which will be used in TransferDataUpload */
|
|
pbDiagBuffer[kDiagFmtMaxBlockLengthHigh] = (vuint8)((maxNumberOfBlockLength >> 8) & 0xFFu);
|
|
pbDiagBuffer[kDiagFmtMaxBlockLengthLow] = (vuint8)(maxNumberOfBlockLength & 0xFFu);
|
|
|
|
DiagProcessingDone(kDiagRslRequestUpload + kDiagMaxNumberOfBlockLengthLength);
|
|
|
|
return kFblOk;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerTransferDataUpload
|
|
**********************************************************************************************************************/
|
|
/*! \brief TransferData service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 2889 1 */ /* MD_FblDiag_2889 */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerTransferDataUpload)
|
|
{
|
|
/* The transfer data length is static to account for potential retries */
|
|
static tCwDataLengthType transferDataUpLength;
|
|
/* Temporary buffer used to backup data from the diag buffer that is */
|
|
/* overwritten by a retry upload request */
|
|
static vuint8 tmpUploadBuffer[kDiagFmtTransferDataUploadRetryBackupSize];
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameter not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
#endif
|
|
|
|
/* Check if the requested sequence number is expected */
|
|
if (DiagBuffer[kDiagFmtSequenceCnt] != expectedSequenceCnt )
|
|
{
|
|
/* Check if sequence number corresponds to a retry */
|
|
if (DiagBuffer[kDiagFmtSequenceCnt] == currentSequenceCnt)
|
|
{
|
|
vuintx i;
|
|
|
|
/*
|
|
* Repetition of last TransferData request: retrieve the saved data
|
|
* from temporary buffer.
|
|
*/
|
|
for (i = 0u; i < kDiagFmtTransferDataUploadRetryBackupSize; i++)
|
|
{
|
|
pbDiagBuffer[kDiagFmtDataOffset + i] = tmpUploadBuffer[i];
|
|
}
|
|
|
|
/* Re-upload the data that is still in the buffer */
|
|
DiagProcessingDone(transferDataUpLength + 1u);
|
|
return kFblOk;
|
|
}
|
|
else /* Sequence number is not for a retry */
|
|
{
|
|
/* Send a WrongSequenceError */
|
|
DiagNRCWrongBlockSequenceCounter();
|
|
return kFblFailed;
|
|
}
|
|
}
|
|
else /* Sequence number is equal to the one expected */
|
|
{
|
|
/* Check if anymore data is expected */
|
|
if (transferRemainder == 0u)
|
|
{
|
|
/* Send NRC TransferDataSuspended and abort, no more data expected! */
|
|
DiagNRCTransferDataSuspended();
|
|
ClrTransferDataAllowed();
|
|
return kFblFailed;
|
|
}
|
|
}
|
|
|
|
/* Memorize current counter */
|
|
currentSequenceCnt = expectedSequenceCnt;
|
|
|
|
/* Sequence counter value of next TransferData request */
|
|
expectedSequenceCnt++;
|
|
|
|
/*
|
|
* Check if the requested length exceeds the diag buffer size.
|
|
* kDiagFmtDataOffset accounts for service ID and block sequence counter.
|
|
*/
|
|
if (transferRemainder > ((tFblLength)maxNumberOfBlockLength - kDiagFmtDataOffset))
|
|
{
|
|
transferDataUpLength = ((tCwDataLengthType)maxNumberOfBlockLength - kDiagFmtDataOffset);
|
|
}
|
|
else
|
|
{
|
|
transferDataUpLength = (tCwDataLengthType)transferRemainder;
|
|
}
|
|
|
|
transferRemainder -= transferDataUpLength;
|
|
|
|
/*
|
|
* Address being passed is either within flash boundaries or within some
|
|
* other type of memory supported by the application.
|
|
*/
|
|
if (FblReadProm(transferAddress, &pbDiagBuffer[kDiagFmtDataOffset], transferDataUpLength) != transferDataUpLength)
|
|
{
|
|
/* Tried accessing non supported memory location */
|
|
DiagNRCConditionsNotCorrect();
|
|
return kFblFailed;
|
|
}
|
|
else /* Success */
|
|
{
|
|
vuintx i;
|
|
|
|
transferAddress += transferDataUpLength;
|
|
|
|
/*
|
|
* Backup the DATA bytes in the diag buffer which might be overwritten
|
|
* by the single frame reception with a retry upload request.
|
|
*/
|
|
for (i = 0u; i < kDiagFmtTransferDataUploadRetryBackupSize; i++)
|
|
{
|
|
tmpUploadBuffer[i] = pbDiagBuffer[kDiagFmtDataOffset + i];
|
|
}
|
|
}
|
|
|
|
DiagProcessingDone(transferDataUpLength + 1u);
|
|
|
|
return kFblOk;
|
|
}
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerRequestTransferExit
|
|
**********************************************************************************************************************/
|
|
/*! \brief RequestTransferExit service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673, 2889, 6010, 6030, 6050 1 */ /* MD_MSR_Rule8.13, MD_FblDiag_2889, MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STCAL */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerRequestTransferExit)
|
|
{
|
|
tFblResult result;
|
|
tFblMemVerifyStatus verifyResult;
|
|
tFblMemBlockVerifyData verifyData = {0};
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_PIPELINED )
|
|
tExportFct exportFct;
|
|
#endif
|
|
|
|
#if defined( V_ENABLE_USE_DUMMY_STATEMENT )
|
|
/* Parameters not used: avoid compiler warning */ /* PRQA S 3112 1 */ /* MD_MSR_DummyStmt */
|
|
(void)diagReqDataLen;
|
|
# if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
# else
|
|
(void)pbDiagBuffer; /* PRQA S 3112 */ /* MD_MSR_DummyStmt */
|
|
# endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
#endif
|
|
|
|
assertFblInternal(currentSegment != kDiagSegmentOutOfRange, kFblOemAssertIllegalParameter);
|
|
assertFblInternal(currentBlock != kBlockNrInvalid, kFblOemAssertIllegalParameter);
|
|
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
if (GetTransferDataUpload())
|
|
{
|
|
/* This service is allowed after all bytes of the segment are transferred */
|
|
if (transferRemainder != 0u)
|
|
{
|
|
DiagNRCRequestSequenceError();
|
|
return kFblFailed;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Send an initial response pending message */
|
|
DiagExRCRResponsePending(kForceSendResponsePending);
|
|
|
|
/* Calculate CRC16-CITT value of the given memory area */
|
|
#if defined( FBL_DIAG_ENABLE_UPLOAD )
|
|
if (GetTransferDataUpload())
|
|
{
|
|
result = kFblOk;
|
|
|
|
/* Setup segment information */
|
|
verifySegmentInfo[0].targetAddress = diagSegmentList.segmentInfo[currentSegment].targetAddress;
|
|
verifySegmentInfo[0].transferredAddress = diagSegmentList.segmentInfo[currentSegment].targetAddress;
|
|
verifySegmentInfo[0].length = diagSegmentList.segmentInfo[currentSegment].length;
|
|
verifyParam.segmentList.nrOfSegments = 1u;
|
|
|
|
/* Trigger checksum calculation */
|
|
verifyParam.blockStartAddress = diagSegmentList.segmentInfo[currentSegment].targetAddress;
|
|
verifyParam.blockLength = diagSegmentList.segmentInfo[currentSegment].length;
|
|
/* No actual verification data included in request; result of CRC calculation will be stored here */
|
|
verifyParam.verificationData = verifyOutputBuf;
|
|
verifyParam.wdTriggerFct = &FblRealTimeSupportVoid;
|
|
/* Upload is restricted to ROM content */
|
|
verifyParam.readMemory = (FL_ReadMemoryFctType)&FblReadProm;
|
|
|
|
if (SECM_VER_OK != FblDiagVerification(&verifyParam))
|
|
{
|
|
/* An error occurred during checksum calculation */
|
|
return kFblFailed;
|
|
}
|
|
|
|
/* Restore the segmentInfo entry for download purposes */
|
|
diagSegmentList.nrOfSegments--;
|
|
}
|
|
else
|
|
#endif /* FBL_DIAG_ENABLE_UPLOAD */
|
|
{
|
|
#if defined( FBL_ENABLE_PROCESSED_DATA_LENGTH )
|
|
/* Update segment information with actually programmed length */
|
|
diagSegmentList.segmentInfo[currentSegment].length = totalProgramLength;
|
|
#endif /* FBL_ENABLE_PROCESSED_DATA_LENGTH */
|
|
|
|
verifyData.verifyDataInput.length = 0u;
|
|
verifyData.verifyDataInput.data = V_NULL;
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_OUTPUT ) && !defined( FBL_MEM_ENABLE_VERIFY_PIPELINED )
|
|
/* Output and pipelined verification use the same data as they are used exclusively */
|
|
/* No actual verification data included in request */
|
|
verifyData.verifyDataOutput.length = FBL_DIAG_VERIFY_BUFFER_SIZE;
|
|
verifyData.verifyDataOutput.data = verifyOutputBuf;
|
|
verifyData.verifyDataPipe.length = 0u;
|
|
verifyData.verifyDataPipe.data = V_NULL;
|
|
#else /* FBL_MEM_ENABLE_VERIFY_PIPELINED */
|
|
/* Check if customer verification function is configured for this block */
|
|
result = FblLbtGetBlockVerifyOutputFuncByNr(currentBlock, &exportFct);
|
|
if (result == kFblOk)
|
|
{
|
|
if (SecM_Default == exportFct)
|
|
{
|
|
verifyData.verifyDataOutput.length = 0u;
|
|
verifyData.verifyDataOutput.data = V_NULL;
|
|
verifyData.verifyDataPipe.length = FBL_DIAG_VERIFY_BUFFER_SIZE;
|
|
verifyData.verifyDataPipe.data = verifyOutputBuf;
|
|
}
|
|
else
|
|
{
|
|
/* Customer verification function: switch to output verification */
|
|
verifyData.verifyDataOutput.length = FBL_DIAG_VERIFY_BUFFER_SIZE;
|
|
verifyData.verifyDataOutput.data = verifyOutputBuf;
|
|
verifyData.verifyDataPipe.length = 0u;
|
|
verifyData.verifyDataPipe.data = V_NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Should never happen */
|
|
DiagNRCRequestOutOfRange();
|
|
return kFblFailed;
|
|
}
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_PIPELINED */
|
|
|
|
/* Handle LibMem state flags and perform state checks */
|
|
result = FblMemRemapStatus(FblMemBlockVerify(&verifyData, &verifyResult));
|
|
if (result == kDiagErrorNone)
|
|
{
|
|
/* Store segment checksum for later verification in routine CheckValidApp */ /* PRQA S 0314 1 */ /* MD_FblDiag_0314_MemCpy */
|
|
(void)MEMCPY(diagSegmentList.segmentInfo[currentSegment].checksum, verifyOutputBuf, SEC_VERIFY_CLASS_DDD_DIGEST_SIZE);
|
|
}
|
|
else
|
|
{
|
|
DiagSetError(result);
|
|
return kFblFailed;
|
|
}
|
|
}
|
|
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* No NRC returned, send the response */
|
|
|
|
/* CRC value is stored in last two byte of buffer */ /* PRQA S 0314 1 */ /* MD_FblDiag_0314_MemCpy */
|
|
(void)MEMCPY(&pbDiagBuffer[kDiagFmtRoutineIdHigh], &verifyOutputBuf[FBL_DIAG_CRC_OFFSET], SEC_SIZE_CHECKSUM_CRC);
|
|
|
|
{
|
|
DiagProcessingDone(kDiagRslRequestTransferExit);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagPrepareDidResponse
|
|
**********************************************************************************************************************/
|
|
/*! \brief ReadDataByIdentifier service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] reqDid Requested DID
|
|
* \param[in] didData Pointer to DID data
|
|
* \param[in] didLength Data length of the DID
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static tFblResult FblDiagPrepareDidResponse ( vuint8 *pbDiagBuffer, vuint16 reqDid, tDidDataPtr didData, vuint16 didLen )
|
|
{
|
|
vuint16 dataIdx;
|
|
tFblResult result = kFblOk;
|
|
|
|
/* Check if data fits into diag buffer */
|
|
if ((DiagDataLength + didLen) < FBL_DIAG_BUFFER_LENGTH)
|
|
{
|
|
/* Write DID to the diag buffer */
|
|
pbDiagBuffer[0] = (vuint8)(reqDid >> 8u);
|
|
pbDiagBuffer[1] = (vuint8)(reqDid & 0xFFu);
|
|
|
|
if (didData != kDiagComplexDidData)
|
|
{
|
|
/* Extract the requested information from DID table */
|
|
for (dataIdx = 0u; dataIdx < (didLen - kDiagFmtDataIdSize); dataIdx++)
|
|
{
|
|
pbDiagBuffer[kDiagFmtDataIdSize + dataIdx] = didData[dataIdx];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* User callback provides the requested information */
|
|
result = ApplFblReadDataByIdentifier(pbDiagBuffer, didLen - kDiagFmtDataIdSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Requested data doesn't fit into diag buffer */
|
|
DiagNRCResponseTooLong();
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerReadDataById
|
|
**********************************************************************************************************************/
|
|
/*! \brief ReadDataByIdentifier service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 2889, 6010, 6030, 6080 1 */ /* MD_FblDiag_2889, MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STMIF */
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerReadDataById)
|
|
{
|
|
tFblResult result = kFblFailed;
|
|
|
|
/* Check if the length is an odd value. */
|
|
if ((diagReqDataLen % 2u) == 1u)
|
|
{
|
|
DiagNRCIncorrectMessageLengthOrInvalidFormat();
|
|
}
|
|
else
|
|
{
|
|
vuint16 reqDid[FBL_MAX_DID_COUNT];
|
|
vuint16 didLen = 0u;
|
|
vuint8 numberOfDids, didIdx, tableIdx;
|
|
/* Get pointer to upper byte of first DID */
|
|
V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * localPbDiagBuffer = &pbDiagBuffer[1u];
|
|
/* Reset response length */
|
|
DiagDataLength = 0u;
|
|
|
|
/* Extract DIDs from diag buffer, do while in order to always initialize reqDid */
|
|
numberOfDids = 0u;
|
|
do
|
|
{
|
|
reqDid[numberOfDids] = (vuint16)FblMemGetInteger(2u, &localPbDiagBuffer[numberOfDids * 2u]);
|
|
numberOfDids++;
|
|
} while (numberOfDids < (diagReqDataLen / 2u));
|
|
|
|
/* Process requested DIDs */
|
|
for (didIdx = 0u; (didIdx < numberOfDids) && (DiagGetError() == kDiagErrorNone); didIdx++)
|
|
{
|
|
/* Handle watchdog but omit transmission of RCRRP (REQPROD 74147) */
|
|
(void)FblLookForWatchdog();
|
|
|
|
result = kFblFailed;
|
|
switch (reqDid[didIdx])
|
|
{
|
|
/* Active Diagnostic Session */
|
|
case kDiagDataIdActiveDiagnosticSession:
|
|
{
|
|
/* Bootloader supports programming session only */
|
|
vuint8 diagSessionType = GetDiagSessionType();
|
|
didLen = kDiagFmtDataIdSize + kDiagFmtDataIdActiveDiagnosticSessionSize;
|
|
result = FblDiagPrepareDidResponse(localPbDiagBuffer, reqDid[didIdx], (tDidDataPtr)&diagSessionType, didLen);
|
|
break;
|
|
}
|
|
/* Software Download Specification Version */
|
|
case kDiagDataIdSwdlVersion:
|
|
{
|
|
/* SWDL issue kDiagSwdlVersion */
|
|
vuint8 swdlVersion = kDiagSwdlVersion;
|
|
didLen = kDiagFmtDataIdSize + kDiagFmtDataIdSwdlVersionSize;
|
|
result = FblDiagPrepareDidResponse(localPbDiagBuffer, reqDid[didIdx], (tDidDataPtr)&swdlVersion, didLen);
|
|
break;
|
|
}
|
|
#if defined( FBL_DIAG_ENABLE_DID_CURRENT_DIAG_APP )
|
|
/* DID 0xD021: Current Diagnostic Application */
|
|
case kDiagDataIdBootloaderCurrentDiagnosticApp:
|
|
{
|
|
vuint8 currentDiagnosticApp = kFblDiagAppUnknown;
|
|
didLen = kDiagFmtDataIdSize + kDiagFmtDataIdBootloaderCurrentDiagAppSize;
|
|
if (GetMemDriverInitialized())
|
|
{
|
|
currentDiagnosticApp = kFblDiagAppSbl;
|
|
}
|
|
else
|
|
{
|
|
currentDiagnosticApp = kFblDiagAppPbl;
|
|
}
|
|
result = FblDiagPrepareDidResponse(localPbDiagBuffer, reqDid[didIdx], (tDidDataPtr)¤tDiagnosticApp, didLen);
|
|
break;
|
|
}
|
|
#endif
|
|
/* User handles the other DIDs */
|
|
default:
|
|
{
|
|
/* Search table of supported DIDs */
|
|
for (tableIdx = 0; tableIdx < kNrOfDids; tableIdx++)
|
|
{
|
|
if (fblDidTable[tableIdx].did == reqDid[didIdx])
|
|
{
|
|
/* Calculate overall data length for range check and pointer handling */
|
|
didLen = kDiagFmtDataIdSize + fblDidTable[tableIdx].size;
|
|
result = FblDiagPrepareDidResponse(localPbDiagBuffer, reqDid[didIdx], fblDidTable[tableIdx].ptr, didLen);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Adjust response length and pointer to diag buffer */
|
|
DiagDataLength += didLen;
|
|
localPbDiagBuffer = &localPbDiagBuffer[didLen];
|
|
}
|
|
}
|
|
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* Check if at least one DID has been found */
|
|
if (DiagDataLength == 0u)
|
|
{
|
|
DiagNRCRequestOutOfRange();
|
|
result = kFblFailed;
|
|
}
|
|
else
|
|
{
|
|
/* No NRC returned, send the response */
|
|
DiagProcessingDone(DiagDataLength);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#if defined( FBL_DIAG_ENABLE_WRITE_DATA_BY_IDENTIFIER )
|
|
/***********************************************************************************************************************
|
|
* FblDiagMainHandlerWriteDataById
|
|
**********************************************************************************************************************/
|
|
/*! \brief WriteDataByIdentifier service handling
|
|
* \param[in] pbDiagBuffer Pointer to the data in the pbDiagBuffer (without SID)
|
|
* \param[in] diagReqDataLen Length of data (without SID)
|
|
* \return Possible return values:
|
|
* - kFblOk: Service processed successfully (goto next state)
|
|
* - kFblFailed: Service processing failed.
|
|
**********************************************************************************************************************/
|
|
static FBL_DIAG_MAIN_HANDLER(FblDiagMainHandlerWriteDataById)
|
|
{
|
|
tFblResult result;
|
|
|
|
|
|
/* Pass pointer to diag buffer which points after the SID. */
|
|
result = ApplFblWriteDataByIdentifier(&(pbDiagBuffer[kDiagFmtDataIdHigh]), diagReqDataLen);
|
|
|
|
/* Catch invalid combinations of return value and NRC state */
|
|
assertFblUser(((result == kFblOk) && (DiagGetError() == kDiagErrorNone)) ||
|
|
((result != kFblOk) && (DiagGetError() != kDiagErrorNone)),
|
|
kFblOemAssertIllegalReturnValue);
|
|
|
|
if (DiagGetError() == kDiagErrorNone)
|
|
{
|
|
/* No NRC returned, send the response */
|
|
DiagProcessingDone(kDiagRslWriteDataByIdentifier);
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
/* Diagnostic service functions *********************************************/
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagEcuReset
|
|
**********************************************************************************************************************/
|
|
/*! \brief Initiate ECU reset
|
|
* \param[in] resetOptions OR combination of:
|
|
* - kDiagResetNoResponse (timeout of TesterPresent)
|
|
* - kDiagResetPutResponse (service EcuReset received)
|
|
* - kDiagResetStayInBoot (do not reset active boot mode)
|
|
* \param[in] responseFlag Value written to reset response flag
|
|
**********************************************************************************************************************/
|
|
void FblDiagEcuReset(vuint8 resetOptions, vuint8 responseFlag)
|
|
{
|
|
#if defined( FBL_ENABLE_ECURESET_DELAY )
|
|
vuint8 tmpFuncReq = GetFunctionalRequest();
|
|
#endif
|
|
|
|
/* Disable tester present timeout monitoring */
|
|
StopTesterTimeout();
|
|
|
|
/* ESCAN00067433: Stop background operations of FblLib_Mem */
|
|
FblMemDeinit();
|
|
|
|
/* Check if a response is required */
|
|
if (GetResetOptionPutResponse(resetOptions) && (!GetSuppressPosRspMsg()))
|
|
{
|
|
/* Request for reset/FBL-shutdown */
|
|
SetWaitEcuReset();
|
|
|
|
/* Check if response address has been stored successfully */
|
|
if (kFblOk == FblCwSaveResponseAddress()) /* PRQA S 2741 */ /* MD_FblDiag_ConstValue */
|
|
{
|
|
/* Transmit response if required */
|
|
switch (responseFlag)
|
|
{
|
|
case RESET_RESPONSE_SDS_REQUIRED:
|
|
{
|
|
DiagProcessingDone(kDiagRslDiagnosticSessionControl);
|
|
break;
|
|
}
|
|
case RESET_RESPONSE_ECURESET_REQUIRED:
|
|
{
|
|
DiagProcessingDone(kDiagRslEcuReset);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
/* Invalid combination of reset option and response flag */
|
|
assertFblInternal(0u, kFblOemAssertParameterOutOfRange);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ /* PRQA S 2880 1 */ /* MD_FblDiag_ConstValue */
|
|
DiagNRCGeneralReject();
|
|
}
|
|
SetEcuResetFctFinished();
|
|
}
|
|
else
|
|
{
|
|
/* Do not transmit response message */
|
|
DiagSetNoResponse();
|
|
DiagProcessingDone(0u);
|
|
FblDiagDeinit();
|
|
}
|
|
|
|
#if defined( FBL_ENABLE_ECURESET_DELAY )
|
|
/* Functionally addressed request: wait for a pre-defined time for
|
|
* responses from the sub nodes */
|
|
if (tmpFuncReq != 0)
|
|
{
|
|
vuint16 i = FBL_ECURESET_DELAY_TIME;
|
|
|
|
|
|
while (i != 0)
|
|
{
|
|
/* Watchdog function calls FblCw polling tasks */
|
|
if ((FblLookForWatchdog() & FBL_TM_TRIGGERED) == FBL_TM_TRIGGERED)
|
|
{
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
#endif /* FBL_ENABLE_ECURESET_DELAY */
|
|
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagSetProperties
|
|
**********************************************************************************************************************/
|
|
/*! \brief Copy service properties from source to target
|
|
* \param[in] source Source service properties
|
|
* \param[out] target Target service properties
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static void FblDiagSetProperties(ptServiceProp source, tServiceProp * destination)
|
|
{
|
|
vuint8 idx;
|
|
vuint8 stateIdx;
|
|
|
|
destination->serviceId = source->serviceId;
|
|
destination->minLength = source->minLength;
|
|
destination->maxLength = source->maxLength;
|
|
destination->mainHandlerIdx = source->mainHandlerIdx;
|
|
destination->subServices = source->subServices;
|
|
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
for (stateIdx = 0u; stateIdx < STATE_COUNT; stateIdx++)
|
|
{
|
|
#if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0;
|
|
#else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
#endif
|
|
{
|
|
destination->states[stateIdx][idx] = source->states[stateIdx][idx];
|
|
}
|
|
}
|
|
#else
|
|
#if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
#else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
#endif
|
|
{
|
|
destination->stateSet[idx] = source->stateSet[idx];
|
|
destination->stateUnset[idx] = source->stateUnset[idx];
|
|
destination->stateAdd[idx] = source->stateAdd[idx];
|
|
destination->stateClr[idx] = source->stateClr[idx];
|
|
destination->stateClrFail[idx] = source->stateClrFail[idx];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMergeProperties
|
|
**********************************************************************************************************************/
|
|
/*! \brief Merge existing contents of target service properties with the one from source.
|
|
* \details Service ID, subservices and handlers will be overwritten if present. Length will be updated if values
|
|
* are more restrictive. Resulting states are the OR concatenation of the inputs.
|
|
* \param[in] source Source service properties
|
|
* \param[out] merge Input service properties, merged with source
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
static void FblDiagMergeProperties(ptServiceProp source, tServiceProp * merge)
|
|
{
|
|
vuint8 idx;
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
vuint8 stateIdx;
|
|
#endif
|
|
|
|
/* PRQA S 2916 TAG_FblDiag_2916_1 */ /* MD_FblDiag_2916 */
|
|
merge->serviceId = source->serviceId;
|
|
if (source->minLength > merge->minLength)
|
|
{
|
|
merge->minLength = source->minLength;
|
|
}
|
|
if (source->maxLength < merge->maxLength)
|
|
{
|
|
merge->maxLength = source->maxLength;
|
|
}
|
|
if (source->mainHandlerIdx != (vuint8)kServiceMainHandlerNone)
|
|
{
|
|
merge->mainHandlerIdx = source->mainHandlerIdx;
|
|
}
|
|
merge->subServices = source->subServices;
|
|
/* PRQA L: TAG_FblDiag_2916_1 */
|
|
|
|
#if defined( FBL_DIAG_STATE_ARRAYS )
|
|
for (stateIdx = 0u; stateIdx < STATE_COUNT; stateIdx++)
|
|
{
|
|
# if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
# else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
# endif
|
|
{
|
|
merge->states[stateIdx][idx] |= source->states[stateIdx][idx];
|
|
}
|
|
}
|
|
#else
|
|
# if ( STATECHECK_ARRAYSIZE == 1u)
|
|
idx = 0u;
|
|
# else
|
|
for (idx = 0u; idx < STATECHECK_ARRAYSIZE; idx++)
|
|
# endif
|
|
{
|
|
merge->stateSet[idx] |= source->stateSet[idx];
|
|
merge->stateUnset[idx] |= source->stateUnset[idx];
|
|
merge->stateAdd[idx] |= source->stateAdd[idx];
|
|
merge->stateClr[idx] |= source->stateClr[idx];
|
|
merge->stateClrFail[idx] |= source->stateClrFail[idx];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagDispatch
|
|
**********************************************************************************************************************/
|
|
/*! \brief Dispatch the current request in the diagnostic buffer
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC */
|
|
static void FblDiagDispatch ( void )
|
|
{
|
|
/* Variables to traverse the service tables */
|
|
ptServiceProp prevProp; /* PRQA S 3679 */ /* MD_MSR_Rule8.13 */
|
|
ptServiceProp currProp;
|
|
V_MEMROM1 tServiceList V_MEMROM2 V_MEMROM3 * localSubServices;
|
|
V_MEMROM1 tServiceCheckList V_MEMROM2 V_MEMROM3 * checkList;
|
|
V_MEMROM1 tServiceCheck V_MEMROM2 V_MEMROM3 * checkFct;
|
|
|
|
vuint8 chkFctIdx;
|
|
tCwDataLengthType bufferPos;
|
|
|
|
tFblResult done;
|
|
|
|
/* Set service table entry point */
|
|
FblDiagSetProperties(&kDiagServiceProperties[0], &serviceProperties);
|
|
|
|
/* Init traversal variables */
|
|
currProp = (ptServiceProp)&kDiagServiceProperties[0];
|
|
prevProp = currProp;
|
|
|
|
localSubServices = currProp->subServices;
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
checkList = kServiceCheckListTable[currProp->checkListIdx];
|
|
#else
|
|
checkList = currProp->checks;
|
|
#endif
|
|
bufferPos = localSubServices->bufPos;
|
|
|
|
checkFct = (V_MEMROM1 tServiceCheck V_MEMROM2 V_MEMROM3 *)0;
|
|
|
|
done = kFblFailed;
|
|
|
|
/* Run until service was found or error occurred */
|
|
while (done != kFblOk)
|
|
{
|
|
/* Assume operation finished */
|
|
done = kFblOk;
|
|
|
|
/* Run over all check functions of current service */
|
|
for (chkFctIdx = 0; chkFctIdx < checkList->count; chkFctIdx++)
|
|
{
|
|
/* Execute check function */
|
|
checkFct = &(checkList->list)[chkFctIdx];
|
|
|
|
if ((kServiceCheckHandlerFctTable[checkFct->checkHandlerIdx])(&serviceProperties, DiagBuffer, DiagDataLength, bufferPos, &currProp) == kFblOk)
|
|
{
|
|
/* Current service has potentially changed */
|
|
if (currProp != prevProp)
|
|
{
|
|
/* Merge new properties with existing one */
|
|
FblDiagMergeProperties(currProp, &serviceProperties);
|
|
prevProp = currProp;
|
|
|
|
/* Not finished yet */
|
|
done = kFblFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Invalidate service */
|
|
currProp = kDiagNoServiceProp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Service property has changed */
|
|
if (done != kFblOk)
|
|
{
|
|
/* Assume operation finished */
|
|
done = kFblOk;
|
|
|
|
/* Valid service found */
|
|
if (currProp != kDiagNoServiceProp)
|
|
{
|
|
/* Get new check functions */
|
|
#if defined( FBL_DIAG_CHECK_LIST_HANDLES )
|
|
if (currProp->checkListIdx != (vuint8)kServiceCheckListNone)
|
|
{
|
|
checkList = kServiceCheckListTable[currProp->checkListIdx];
|
|
#else
|
|
checkList = currProp->checks;
|
|
if (checkList != (void *)0)
|
|
{
|
|
#endif
|
|
/* Initialize check function */
|
|
checkFct = (V_MEMROM1 tServiceCheck V_MEMROM2 V_MEMROM3 *)0;
|
|
|
|
/* Not finished yet, new check functions present */
|
|
done = kFblFailed;
|
|
}
|
|
|
|
/* Get subservices of current service */
|
|
localSubServices = currProp->subServices;
|
|
if (localSubServices != (void *)0)
|
|
{
|
|
/* Move to next buffer position */
|
|
bufferPos = localSubServices->bufPos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Assume dispatching failed */
|
|
serviceResult = kFblFailed;
|
|
|
|
/* No valid subservice found */
|
|
if (currProp == kDiagNoServiceProp)
|
|
{
|
|
/* Failed check function is known */
|
|
if (checkFct != (void *)0)
|
|
{
|
|
/* Execute error handler */
|
|
if (checkFct->errorHandlerIdx != (vuint8)kServiceErrorHandlerNone)
|
|
{
|
|
/* Result of error handler changes execution state */
|
|
serviceResult = (kServiceErrorHandlerFctTable[checkFct->errorHandlerIdx])(&serviceProperties, DiagBuffer, DiagDataLength);
|
|
}
|
|
|
|
/* Error handler wasn't successful and NRC was not set directly */
|
|
if ((serviceResult != kFblOk) && (DiagGetError() == kDiagErrorNone))
|
|
{
|
|
/* Set NRC according to check function configuration */
|
|
if (checkFct->NRC == kDiagNrcNoResponse)
|
|
{
|
|
/* Quiet failure */
|
|
DiagSetNoResponse();
|
|
DiagProcessingDone(0);
|
|
}
|
|
else
|
|
{
|
|
/* Set NRC */
|
|
DiagSetError(checkFct->NRC);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Operation failed but check function is unknown
|
|
Set generic NRC
|
|
*/
|
|
DiagNRCGeneralReject();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Execute main handler */
|
|
if (serviceProperties.mainHandlerIdx != (vuint8)kServiceMainHandlerNone)
|
|
{
|
|
serviceResult = (kServiceMainHandlerFctTable[serviceProperties.mainHandlerIdx])(DiagBuffer, DiagDataLength);
|
|
}
|
|
}
|
|
|
|
/* Set and clear state flags according to execution result */
|
|
if (serviceResult == kFblOk)
|
|
{
|
|
FblDiagClrState(serviceProperties.stateClr);
|
|
FblDiagSetState(serviceProperties.stateAdd);
|
|
}
|
|
else
|
|
{
|
|
FblDiagClrState(serviceProperties.stateClrFail);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagTimerTask
|
|
**********************************************************************************************************************/
|
|
/*! \brief This function handles the surveillance of the tester present timer. When a timeout occurs, a reset
|
|
* is executed.
|
|
* \pre FblDiagInit has to be executed
|
|
**********************************************************************************************************************/
|
|
void FblDiagTimerTask( void )
|
|
{
|
|
/* Tester present timing */
|
|
if (TimeoutTesterValue() != 0u)
|
|
{
|
|
DecTimeoutTesterValue();
|
|
if (TimeoutTesterValue() == 0u)
|
|
{
|
|
/*
|
|
* Tester present timer expired:
|
|
* Exit bootloader via reset, but force no response!!
|
|
*/
|
|
FblDiagEcuReset(kDiagResetNoResponse, RESET_RESPONSE_NOT_REQUIRED);
|
|
}
|
|
}
|
|
|
|
/* ECU reset is pending */
|
|
if (TimeoutEcuResetValue() != 0u)
|
|
{
|
|
DecTimeoutEcuResetValue();
|
|
if (TimeoutEcuResetValue() == 0u)
|
|
{
|
|
/* ECU reset timer expired */
|
|
/* Exit bootloader via Reset, but force no response!! */
|
|
FblDiagEcuReset(kDiagResetNoResponse, RESET_RESPONSE_NOT_REQUIRED);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagStateTask
|
|
**********************************************************************************************************************/
|
|
/*! \brief Handle diagnostic indications.
|
|
* \pre FblDiagInit has to be executed
|
|
**********************************************************************************************************************/
|
|
void FblDiagStateTask( void )
|
|
{
|
|
|
|
/* Diagnostic request pending */
|
|
if (GetDiagIndication())
|
|
{
|
|
/* Setup state flags */
|
|
ClrDiagIndication();
|
|
ClrSuppressPosRspMsg();
|
|
ClrProcessingDone();
|
|
DiagClrError();
|
|
|
|
/* Indicate an ongoing service processing */
|
|
SetServiceInProgress();
|
|
|
|
/* Dispatch request */
|
|
FblDiagDispatch();
|
|
|
|
/* Call response processor in case of NRC */
|
|
if (DiagGetError() != kDiagErrorNone)
|
|
{
|
|
DiagResponseProcessor(0);
|
|
}
|
|
|
|
/* Reset internal state in case no response was sent */
|
|
if ((!GetProcessingDone()) && (!GetWaitForRcrRpConf()))
|
|
{
|
|
DiagSetNoResponse();
|
|
DiagResponseProcessor(0);
|
|
}
|
|
}
|
|
|
|
/* Check for reset request */
|
|
/* The following preconditions have to be fulfilled:
|
|
* Reset message confirmed
|
|
* Pre-reset function (e.g. flag written to NV-memory) has finished
|
|
*/
|
|
if (GetWaitEcuReset() && GetResetMsgConfirmed() && GetEcuResetFctFinished())
|
|
{
|
|
{
|
|
FblDiagDeinit();
|
|
}
|
|
}
|
|
|
|
/* ESCAN00061727: Resume suspended LibMem operation */
|
|
FblMemResumeIndication();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagDeinit
|
|
**********************************************************************************************************************/
|
|
/*! \brief Function prepares for FBL shutdown on diagnostic service request.
|
|
**********************************************************************************************************************/
|
|
static void FblDiagDeinit(void)
|
|
{
|
|
/* Deinitialize verification component */
|
|
(void)SecM_DeinitVerification(V_NULL);
|
|
|
|
/* Deinitialize loaded memory driver(s) */
|
|
FblDeinitMemoryDriver();
|
|
|
|
/* Reset internal FBL states */
|
|
FblDiagRetainState(kDiagStateMaskReset);
|
|
|
|
/* Clear negative response indicator */
|
|
DiagClrError();
|
|
|
|
/* Request shutdown from communication wrapper */
|
|
FblCwShutdownRequest(kFblCwResetEcuRegularCase);
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblInitMemoryDriver
|
|
**********************************************************************************************************************/
|
|
/*! \brief Initializes the flash driver for usage
|
|
* \pre Flash driver must be verified
|
|
* \return kFblOk = initialization successful, kFblFailed = otherwise
|
|
**********************************************************************************************************************/
|
|
static tFblResult FblInitMemoryDriver( void )
|
|
{
|
|
tFblResult result = kFblFailed;
|
|
IO_ErrorType memErrorCode;
|
|
|
|
if (!GetMemDriverInitialized())
|
|
{
|
|
/* Initialize flash driver version */
|
|
FblErrStatSetFlashDrvVersion();
|
|
|
|
/* Turn on programming voltage (if necessary) */
|
|
ApplFblSetVfp();
|
|
|
|
/* ApplFbl[Set|Reset]Vfp() are not allowed to set a NRC */
|
|
assertFblUser((DiagGetError() == kDiagErrorNone), kFblOemAssertIllegalReturnValue);
|
|
|
|
/* Check version and initialize flash driver */
|
|
FblCwSetOfflineMode();
|
|
memErrorCode = MemDriver_InitSync(V_NULL);
|
|
FblCwSetOnlineMode();
|
|
|
|
/*
|
|
* ESCAN00041016: Require all memory drivers to be correctly initialized
|
|
* at this point (i.e. non-downloadable drivers, too).
|
|
*/
|
|
if (memErrorCode == IO_E_OK)
|
|
{
|
|
/* Set Flash driver initialization flag */
|
|
SetMemDriverInitialized();
|
|
result = kFblOk;
|
|
}
|
|
else
|
|
{
|
|
/* Flash driver initialization failure */
|
|
FblErrStatSetError(FBL_ERR_FLASHCODE_INIT_FAILED);
|
|
FblErrStatSetFlashDrvError(memErrorCode);
|
|
|
|
/* Reset programming voltage */
|
|
ApplFblResetVfp();
|
|
|
|
/* ApplFbl[Set|Reset]Vfp() are not allowed to set a NRC */
|
|
assertFblUser((DiagGetError() == kDiagErrorNone), kFblOemAssertIllegalReturnValue);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Flash driver already initialized */
|
|
result = kFblOk;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDeinitMemoryDriver
|
|
**********************************************************************************************************************/
|
|
/*! \brief Deinitialize memory driver if present
|
|
**********************************************************************************************************************/
|
|
static void FblDeinitMemoryDriver( void )
|
|
{
|
|
if (GetDiagProgrammingSession())
|
|
{
|
|
if (GetMemDriverInitialized())
|
|
{
|
|
/* Deinitialize memory driver flash */
|
|
ClrMemDriverInitialized();
|
|
|
|
/* Remove memory driver from RAM-buffer */
|
|
FblCwSetOfflineMode();
|
|
{
|
|
(void)MemDriver_DeinitSync(V_NULL);
|
|
}
|
|
FblCwSetOnlineMode();
|
|
}
|
|
|
|
/* Turn off programming voltage */
|
|
ApplFblResetVfp();
|
|
}
|
|
}
|
|
|
|
/* Ford specific functions **********************************************/
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_OUTPUT )
|
|
/***********************************************************************************************************************
|
|
* FblDiagVerification - Ford specific
|
|
**********************************************************************************************************************/
|
|
/*! \brief This function calls the HIS verification interface to calculate the CRC16 value over the requested
|
|
* address region in non-volatile memory.
|
|
* \pre Address region check has been performed (FblDiagAddressRegionCheck)
|
|
* \param[in] verifyParam Parameter structure for verification
|
|
* \return Result of operation
|
|
**********************************************************************************************************************/
|
|
static SecM_StatusType FblDiagVerification(V_MEMRAM1 SecM_VerifyParamType V_MEMRAM2 V_MEMRAM3 * verifyPar)
|
|
{
|
|
tBlockDescriptor blockDescriptor;
|
|
tFblMemVerifyFctOutput verifyFct;
|
|
|
|
/* Set default verification function */
|
|
verifyFct = &SecM_VerificationClassDDD;
|
|
|
|
/*
|
|
* Note: general address region check is expected to be performed before this
|
|
* function is called (e.g. in FblDiagMainHandlerRequestDownload/Upload, FblDiagMainHandlerRcCheckProgDep).
|
|
*/
|
|
if (FblLbtGetBlockDescriptorByAddressLength(verifyPar->blockStartAddress, verifyPar->blockLength, &blockDescriptor) == kFblOk)
|
|
{
|
|
if (SecM_Default != blockDescriptor.verifyOutput)
|
|
{
|
|
/* Logical block no. has been determined successfully: assign block specific verification function */
|
|
verifyFct = (tFblMemVerifyFctOutput)blockDescriptor.verifyOutput; /* PRQA S 0313 */ /* MD_FblDiag_0313_VerifyFctOutput */
|
|
}
|
|
}
|
|
|
|
/* Perform verification */
|
|
return verifyFct(verifyPar);
|
|
}
|
|
#endif
|
|
|
|
#if defined( FBL_MEM_ENABLE_VERIFY_PIPELINED ) && ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
/***********************************************************************************************************************
|
|
* FblDiagVerifySignature
|
|
**********************************************************************************************************************/
|
|
/*! \brief This function calls the HIS verification interface to calculate the CRC16 value over the requested
|
|
* address region in non-volatile memory (pipelined mode).
|
|
* \pre Address region check has been performed (FblDiagAddressRegionCheck)
|
|
* \param[in] pVerifyParam Parameter structure for verification
|
|
* \return Result of operation
|
|
**********************************************************************************************************************/
|
|
static SecM_StatusType FblDiagVerifySignature( V_MEMRAM1 SecM_SignatureParamType V_MEMRAM2 V_MEMRAM3 * pVerifyParam )
|
|
{
|
|
SecM_StatusType result;
|
|
SecM_LengthType byteCount;
|
|
|
|
result = SECM_VER_ERROR;
|
|
|
|
pipeVerifyParamCrc.sigState = pVerifyParam->sigState;
|
|
pipeVerifyParamCrc.sigSourceBuffer = pVerifyParam->sigSourceBuffer;
|
|
pipeVerifyParamCrc.sigByteCount = pVerifyParam->sigByteCount;
|
|
pipeVerifyParamCrc.wdTriggerFct = pVerifyParam->wdTriggerFct;
|
|
|
|
switch (pVerifyParam->sigState)
|
|
{
|
|
case SEC_HASH_INIT:
|
|
case SEC_HASH_COMPUTE:
|
|
case SEC_HASH_FINALIZE:
|
|
{
|
|
result = SecM_VerifyClassDDD(pVerifyParam);
|
|
(void)SecM_VerifyChecksumCrc(&pipeVerifyParamCrc);
|
|
|
|
break;
|
|
}
|
|
case SEC_SIG_VERIFY:
|
|
{
|
|
result = SecM_VerifyClassDDD(pVerifyParam);
|
|
|
|
byteCount = pVerifyParam->sigByteCount;
|
|
pipeVerifyParamCrc.sigSourceBuffer = &pVerifyParam->sigSourceBuffer[byteCount];
|
|
pipeVerifyParamCrc.sigByteCount -= byteCount;
|
|
|
|
(void)SecM_VerifyChecksumCrc(&pipeVerifyParamCrc);
|
|
|
|
pVerifyParam->sigByteCount += pipeVerifyParamCrc.sigByteCount;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
/* Nothing to do */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_MEM_ENABLE_VERIFY_PIPELINED && ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC ) */
|
|
|
|
|
|
#if defined( FBL_ENABLE_STAY_IN_BOOT )
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckStartMsg - Ford Specific
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if the OEM specific start message has been received
|
|
* \pre Start message reception has to be verified by ComWrapper
|
|
* \param[in] pData Pointer to received data
|
|
* \param[in] length Length of received data
|
|
* \return Possible return values:
|
|
* - kFblOk: OEM specific start message has been identified
|
|
* - kFblFailed: Received message doesn't equal the OEM specific start message
|
|
**********************************************************************************************************************/
|
|
vuint8 FblDiagCheckStartMsg(const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 *pData, vuintx length)
|
|
{
|
|
vuint8 result;
|
|
|
|
/* Initialize variables */
|
|
result = kFblFailed;
|
|
|
|
/* Check if received data is long enough */
|
|
if (length >= (kDiagRqlDiagnosticSessionControl + 2u))
|
|
{
|
|
/* Check complete message contents for Stay-In-Boot */
|
|
/* For Ford, this is: 0x02 0x10 0x02 (DiagnosticSessionControl/ProgrammingSession) */
|
|
if ( ( pData[0] == (kDiagRqlDiagnosticSessionControl + 1u)) /* Add the service ID */
|
|
&& ( pData[kDiagFmtServiceId + 1u] == kDiagSidDiagnosticSessionControl)
|
|
&& ((pData[kDiagFmtSubparam + 1u] & 0x7Fu) == kDiagSubProgrammingSession)) /* Suppressed bit may be true or false */
|
|
{
|
|
/* Start message received */
|
|
result = kFblOk;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif /* FBL_ENABLE_STAY_IN_BOOT */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagGetSegmentList
|
|
**********************************************************************************************************************/
|
|
/*! \brief Returns a list of download segments which have been programmed into a certain logical block
|
|
* \param[in] blockIdx Index of the logical block for which the associated download segments shall be returned
|
|
* \param[out] blockSegList Pointer to local segment list which shall keep the respective download segments
|
|
* \return Number of download segment which are associated with the requested logical block
|
|
**********************************************************************************************************************/
|
|
vuint8 FblDiagGetSegmentList(vuint8 blockIdx, V_MEMRAM1 tDiagSegmentList V_MEMRAM2 V_MEMRAM3 * blockSegList)
|
|
{
|
|
vuint8 listIdx;
|
|
|
|
blockSegList->nrOfSegments = 0u;
|
|
|
|
for (listIdx = 0u; listIdx < blockHeader[blockIdx].nrOfSegments; listIdx++)
|
|
{
|
|
blockSegList->segmentInfo[blockSegList->nrOfSegments] = diagSegmentList.segmentInfo[blockHeader[blockIdx].segmentIdx[listIdx]];
|
|
blockSegList->nrOfSegments++;
|
|
}
|
|
|
|
return blockSegList->nrOfSegments;
|
|
}
|
|
|
|
#define FBLDIAG_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/* Communication wrapper callback functions **********************************/
|
|
#define FBLDIAG_RAMCODE_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
/***********************************************************************************************************************
|
|
* FblDiagTxErrorIndication
|
|
**********************************************************************************************************************/
|
|
/*! \brief Indicates that an error has occurred during transmission.
|
|
* \details According to ISO-14229, now the S3 timer must be restarted.
|
|
* \pre TP must been initialized
|
|
* \param[in] cwMsgType Message type of indication (defined in CW layer):
|
|
* - kFblCwMsgTypeRcrRp: Request correctly received/response pending message
|
|
* - kFblCwMsgTypeNormal: Normal request message
|
|
**********************************************************************************************************************/
|
|
void FblDiagTxErrorIndication( vuint8 cwMsgType )
|
|
{
|
|
/* Do not reset states for RCR-RP confirmation */
|
|
if (cwMsgType != kFblCwMsgTypeRcrRp)
|
|
{
|
|
DiagResetResponseHandling();
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRxStartIndication
|
|
**********************************************************************************************************************/
|
|
/*! \brief Data reception call-back function to start diagnostic service processing.
|
|
* \details Valid TesterPresent requests will simply start the S3 timer and will not be processed.
|
|
* \pre TP reception successful
|
|
**********************************************************************************************************************/
|
|
void FblDiagRxStartIndication( void )
|
|
{
|
|
/* Halts the S3 timer while receiving a diagnostic message */
|
|
StopTesterTimeout();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRxErrorIndication
|
|
**********************************************************************************************************************/
|
|
/*! \brief Indicates that an error has occurred during reception.
|
|
* \details According to ISO-14229, now the S3 timer must be restarted.
|
|
* \pre TP must been initialized
|
|
**********************************************************************************************************************/
|
|
void FblDiagRxErrorIndication( void )
|
|
{
|
|
DiagResetResponseHandling();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRxIndication
|
|
**********************************************************************************************************************/
|
|
/*! \brief Data reception call-back function to start diagnostic service processing.
|
|
* \details Valid TesterPresent requests will simply start the S3 timer and will not be processed.
|
|
* \pre TP reception successful
|
|
* \param[in] pbDiagBuffer Pointer to diagnostic buffer
|
|
* \param[in] rxDataLength Number of bytes to be received
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */
|
|
void FblDiagRxIndication( V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * pbDiagBuffer, tCwDataLengthType rxDataLength )
|
|
{
|
|
/* Check for functionally addressed valid TesterPresent message with SuppressPosRsp */
|
|
if ((kDiagSidTesterPresent == pbDiagBuffer[kDiagFmtServiceId])
|
|
&& (kDiagSuppressPosRspMsgIndicationBit == pbDiagBuffer[kDiagFmtSubparam])
|
|
&& (kDiagRqlTesterPresent == (rxDataLength - 1u))
|
|
&& GetFunctionalRequest()
|
|
)
|
|
{
|
|
/* Bypass logic for this TesterPresent message */
|
|
DiagResetResponseHandling(); /* Reset tester timeout */
|
|
FblCwResetRxBlock();
|
|
}
|
|
else
|
|
{
|
|
/* Start regular service processing */
|
|
DiagClrError();
|
|
diagResponseFlag = kDiagPutResponse;
|
|
diagServiceCurrent = pbDiagBuffer[kDiagFmtServiceId];
|
|
|
|
SetP2Timer(kFblDiagTimeP2); /* Reset P2 timer (initial timing) */
|
|
SetP2Timeout(kFblDiagTimeP2); /* PRQA S 3493 */ /* MD_FblDiag_3493 */
|
|
DiagDataLength = rxDataLength - 1u;
|
|
SetDiagIndication();
|
|
|
|
#if defined( FBL_MEM_ENABLE_PIPELINING )
|
|
if (FblMemTaskIsPending())
|
|
{
|
|
FblMemRxNotification();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Initialize security seed */
|
|
(void)ApplFblSecuritySeedInit();
|
|
|
|
#if defined( FBL_ENABLE_SLEEPMODE )
|
|
/* Request received - reload sleep counter */
|
|
FblSleepCounterReload();
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagTxConfirmation
|
|
**********************************************************************************************************************/
|
|
/*! \brief TP transmission call-back function.
|
|
* \pre TP transmission successful
|
|
* \param[in] cwMsgType Message type of indication (defined in CW layer):
|
|
* - kFblCwMsgTypeRcrRp: Request correctly received/response pending message
|
|
* - kFblCwMsgTypeNormal: Normal request message
|
|
**********************************************************************************************************************/
|
|
void FblDiagTxConfirmation( vuint8 cwMsgType )
|
|
{
|
|
/* Do not reset states for RCR-RP confirmation */
|
|
if (cwMsgType != kFblCwMsgTypeRcrRp)
|
|
{
|
|
DiagResetResponseHandling();
|
|
}
|
|
|
|
/* Diag wants to reset FBL after sending an RCR-RP */
|
|
if (GetWaitEcuReset())
|
|
{
|
|
SetResetMsgConfirmed();
|
|
}
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRxGetPhysBuffer
|
|
**********************************************************************************************************************/
|
|
/*! \brief Diagnostic buffer management function for physical requests.
|
|
* \param[in] rxDataLength Number of bytes to be received
|
|
* \return Possible return values:
|
|
* - Pointer to diagnostic buffer
|
|
* - V_NULL in case no buffer is available
|
|
**********************************************************************************************************************/
|
|
vuint8* FblDiagRxGetPhysBuffer( tCwDataLengthType rxDataLength )
|
|
{
|
|
vuint8* result;
|
|
|
|
/* Check request length and if buffer is free */
|
|
if ((rxDataLength > 0u )
|
|
&& (FBL_DIAG_BUFFER_LENGTH >= rxDataLength)
|
|
&& (!GetDiagBufferLocked()))
|
|
{
|
|
/* Initialize state variables */
|
|
ClrFunctionalRequest();
|
|
|
|
/* Lock buffer */
|
|
SetDiagBufferLocked();
|
|
|
|
/* Return diagnostic buffer */
|
|
result = DiagBuffer;
|
|
}
|
|
else
|
|
{
|
|
/* Illegal buffer request, return null pointer */
|
|
result = V_NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagRxGetFuncBuffer
|
|
**********************************************************************************************************************/
|
|
/*! \brief Diagnostic buffer management function for functional requests.
|
|
* \param[in] rxDataLength Number of bytes to be received
|
|
* \return Possible return values:
|
|
* - Pointer to diagnostic buffer
|
|
* - V_NULL in case no buffer is available
|
|
**********************************************************************************************************************/
|
|
vuint8* FblDiagRxGetFuncBuffer( tCwDataLengthType rxDataLength )
|
|
{
|
|
/* Process functional request like physical request */
|
|
vuint8* diagnosticBuffer = FblDiagRxGetPhysBuffer(rxDataLength);
|
|
|
|
/* Set functional request indication */
|
|
if (V_NULL != diagnosticBuffer)
|
|
{
|
|
SetFunctionalRequest();
|
|
}
|
|
|
|
return diagnosticBuffer;
|
|
}
|
|
#define FBLDIAG_RAMCODE_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
#define FBLDIAG_START_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMemPreWrite
|
|
**********************************************************************************************************************/
|
|
/*! \brief Function performs actions before FblLib_Mem calls the memory driver write function.
|
|
* \return Possible return values:
|
|
* - kFblOk: Pre-write operations are successful
|
|
* - kFblFailed: Pre-write operations failed
|
|
**********************************************************************************************************************/
|
|
tFblResult FblDiagMemPreWrite( void )
|
|
{
|
|
FblCwSetOfflineMode();
|
|
|
|
return kFblOk;
|
|
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagMemPostWrite
|
|
**********************************************************************************************************************/
|
|
/*! \brief Checks if message is the platform message or not
|
|
* \return Possible return values:
|
|
* - kFblOk: Post-write operations are successful
|
|
* - kFblFailed: Post-write operations failed
|
|
**********************************************************************************************************************/
|
|
tFblResult FblDiagMemPostWrite( void )
|
|
{
|
|
FblCwSetOnlineMode();
|
|
|
|
return kFblOk;
|
|
}
|
|
|
|
#if ( SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC )
|
|
# if defined( FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING )
|
|
/***********************************************************************************************************************
|
|
* FblDiagValidateToken
|
|
**********************************************************************************************************************/
|
|
/*! \brief Validate the token against main validity rules
|
|
* \return Possible return values:
|
|
* - tTokenHdlResult: result of the validation operation
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC */
|
|
static tTokenHdlResult FblDiagValidateToken( const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf )
|
|
{
|
|
tTokenHdlResult result;
|
|
vuintx idx;
|
|
vuint8 const *fesnPtr = FblDiagGetFesn();
|
|
|
|
result = kTokenHdlrInternalFailed;
|
|
|
|
/* Check if Server Message ID is required and valid */
|
|
if (FblDiagIsTokenMsgIDRequired(tokenBuf))
|
|
{
|
|
if (FblDiagCheckServerMessageId(tokenBuf) == kFblOk)
|
|
{
|
|
result = kTokenHdlrOk;
|
|
}
|
|
}
|
|
|
|
/* Is KeyID present? */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
(FblDiagIsTokenKeyIDRequired(tokenBuf)) )
|
|
{
|
|
/* KeyID must not be present */
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Are reserved bits set? */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
(FblDiagIsTokenReserverdBitsSet(tokenBuf)) )
|
|
{
|
|
/* Reserved bits must not be set */
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Is FESN present? */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
FblDiagIsTokenFesnRequired(tokenBuf) &&
|
|
(FblDiagGetTokenCommandType(tokenBuf) != FBL_DIAG_TOKEN_CMD_PROGKEY) )
|
|
{
|
|
/* Check if FESN match */
|
|
for (idx = 0u; idx < FBL_DIAG_TOKEN_FESN_LEN; idx++)
|
|
{
|
|
if (FblDiagGetTokenFesn(tokenBuf)[idx] != fesnPtr[idx])
|
|
{
|
|
result = kTokenHdlrFesnFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* For Mode 5 check the first three characters of the FESN */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
(FblDiagGetTokenCommandType(tokenBuf) == FBL_DIAG_TOKEN_CMD_PROGKEY) )
|
|
{
|
|
if (FblDiagIsTokenFesnRequired(tokenBuf))
|
|
{
|
|
/* FESN required bit must not be set for mode 5 token */
|
|
result = kTokenHdlrFesnFailed;
|
|
}
|
|
else
|
|
{
|
|
/* Check if the first 3 character of the FESN match */
|
|
for (idx = 0u; idx < FBL_DIAG_TOKEN_MOD5_FESN_LEN; idx++)
|
|
{
|
|
if (FblDiagGetTokenPayloadFesn(tokenBuf)[idx] != fesnPtr[idx])
|
|
{
|
|
result = kTokenHdlrFesnFailed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check if CPU destination match */
|
|
if ((result == kTokenHdlrOk)
|
|
&& (FblDiagGetTokenCPUDestination(tokenBuf) != FBL_DIAG_TOKEN_CPU_DEST))
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Check if service type match */
|
|
if ((result == kTokenHdlrOk)
|
|
&& (FblDiagGetTokenServiceType(tokenBuf) != FBL_DIAG_TOKEN_SERVICE_TYPE))
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Check if crypto type match */
|
|
if ((result == kTokenHdlrOk)
|
|
&& (FblDiagGetTokenCryptoType(tokenBuf) != FBL_DIAG_TOKEN_CRYPTOTYPE))
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Check if payload size match */
|
|
if (result == kTokenHdlrOk)
|
|
{
|
|
if (FblDiagGetTokenCommandType(tokenBuf) == FBL_DIAG_TOKEN_CMD_PROGKEY)
|
|
{
|
|
if (FblDiagGetTokenPayloadSize(tokenBuf) != FBL_DIAG_TOKEN_PAYLOAD_SIZE_MODE5)
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FblDiagGetTokenPayloadSize(tokenBuf) != FBL_DIAG_TOKEN_PAYLOAD_SIZE_MODE0_4)
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check if correct key index match the token public key */
|
|
if (result == kTokenHdlrOk)
|
|
{
|
|
if (FblDiagGetTokenCommandType(tokenBuf) == FBL_DIAG_TOKEN_CMD_PROGKEY)
|
|
{
|
|
if (FblDiagGetTokenKeyIndex(tokenBuf) != FBL_DIAG_TOKEN_KEY_INDEX_0)
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FblDiagGetTokenKeyIndex(tokenBuf) != FBL_DIAG_TOKEN_KEY_INDEX_1)
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check protocol version */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
(!FblDiagIsTokenProtocolVersionCorrect(tokenBuf)))
|
|
{
|
|
result = kTokenHdlrProtocolFailed;
|
|
}
|
|
|
|
/* Check token name length */
|
|
if ( (result == kTokenHdlrOk) &&
|
|
(FblDiagGetTokenTokenNameLength(tokenBuf) != FBL_DIAG_TOKEN_NAME_LENGTH) )
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
|
|
/* Check token name */
|
|
if (result == kTokenHdlrOk)
|
|
{
|
|
vuint8 const tokenName[(FBL_DIAG_TOKEN_NAME_LENGTH + 1u)] = FBL_DIAG_TOKEN_NAME;
|
|
|
|
for (idx = 0u; idx < FBL_DIAG_TOKEN_NAME_LENGTH; idx++)
|
|
{
|
|
if (FblDiagGetTokenTokenName(tokenBuf)[idx] != tokenName[idx])
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagCheckServerMessageId
|
|
**********************************************************************************************************************/
|
|
/*! \brief Check if Server Message ID is valid
|
|
* \return Possible return values:
|
|
* - kFblOk: Server Message ID is valid
|
|
* - kFblFailed: Server Message ID is not valid
|
|
**********************************************************************************************************************/
|
|
/* PRQA S 6010, 6030 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC */
|
|
static tFblResult FblDiagCheckServerMessageId( const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf )
|
|
{
|
|
tFblResult result = kFblOk;
|
|
tFblResult srvMsgIdCompareFinished = kFblFailed;
|
|
vuint8 lastServerMessageId[8] = {0};
|
|
vuint8 srvMsgIdFlag;
|
|
vuintx idx;
|
|
|
|
/* Check if Server Message ID was stored before */
|
|
if (ApplFblReadSrvMsgIDFlag(&srvMsgIdFlag) == kFblOk)
|
|
{
|
|
if (srvMsgIdFlag == (vuint8)FBL_DIAG_SRVMSGID_STORED)
|
|
{
|
|
/* Read last Server Message ID from NV Memory */
|
|
result = ApplFblReadLastServerMsgId(lastServerMessageId);
|
|
}
|
|
else
|
|
{
|
|
/* Initialize last Server Message ID */
|
|
result = ApplFblWriteLastServerMsgId(lastServerMessageId);
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Set Server Message ID Flag so next time it will be read from NV Memory */
|
|
srvMsgIdFlag = (vuint8)FBL_DIAG_SRVMSGID_STORED;
|
|
result = ApplFblWriteSrvMsgIDFlag(&srvMsgIdFlag);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = kFblFailed;
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
/* Read current Server Message ID from token buffer and compare with last Server Message ID */
|
|
const vuint8 *currentServerMessageId = FblDiagGetTokenServerMsgIdPtr(tokenBuf);
|
|
result = kFblFailed;
|
|
|
|
/* Check each byte, starting from MSB (index 0 due to network byte order) */
|
|
for (idx = 0u; idx < 8u; idx++)
|
|
{
|
|
if (currentServerMessageId[idx] > lastServerMessageId[idx])
|
|
{
|
|
/* Received server message ID is higher than last server message ID */
|
|
result = kFblOk;
|
|
srvMsgIdCompareFinished = kFblOk;
|
|
}
|
|
else if (currentServerMessageId[idx] < lastServerMessageId[idx])
|
|
{
|
|
/* Received server message ID is lower than last server message ID. Break loop so result
|
|
* cannot be ok if a byte with lower significance has a higher value in the current server
|
|
* message ID */
|
|
srvMsgIdCompareFinished = kFblOk;
|
|
}
|
|
else
|
|
{
|
|
/* Values are the same, continue with check */
|
|
}
|
|
|
|
if (srvMsgIdCompareFinished == kFblOk)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (result == kFblOk)
|
|
{
|
|
result = ApplFblWriteLastServerMsgId(currentServerMessageId);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* FblDiagTokenCallout
|
|
**********************************************************************************************************************/
|
|
/*! \brief Calls for each Token mode the related Callout
|
|
* \param[in] cmdType The Token mode from TokenCommandType
|
|
* \return Possible return values:
|
|
* - tTokenHdlResult: result of the callout function
|
|
**********************************************************************************************************************/
|
|
static tTokenHdlResult FblDiagTokenCallout( vuint8 cmdType, const V_MEMRAM1 vuint8 V_MEMRAM2 V_MEMRAM3 * tokenBuf, vuint16 tokenLength )
|
|
{
|
|
tTokenHdlResult result;
|
|
|
|
switch (cmdType)
|
|
{
|
|
case FBL_DIAG_TOKEN_CMD_REVERTPROD:
|
|
{
|
|
result = ApplFblTokenRevertKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVPERM:
|
|
{
|
|
result = ApplFblTokenUseDevPermKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVTEMP:
|
|
{
|
|
result = ApplFblTokenUseDevTempKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVDATE:
|
|
{
|
|
result = ApplFblTokenUseDevDateKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_USEDEVIGNI:
|
|
{
|
|
result = ApplFblTokenUseDevIgniKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
case FBL_DIAG_TOKEN_CMD_PROGKEY:
|
|
{
|
|
result = ApplFblTokenProgKey(tokenBuf, tokenLength);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
result = kTokenHdlrInternalFailed;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
# endif /* FBL_ENABLE_TOKEN_DOWNLOAD_HANDLING */
|
|
#endif /* SEC_SECURITY_CLASS_VERIFY == SEC_CLASS_CCC */
|
|
|
|
|
|
#define FBLDIAG_STOP_SEC_CODE
|
|
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
|
|
|
|
/***********************************************************************************************************************
|
|
* MISRA DEVIATIONS
|
|
**********************************************************************************************************************/
|
|
|
|
/* Justification for module-specific MISRA deviations:
|
|
|
|
MD_FblDiag_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. The correctness of the respective implementation is verified by runtime tests.
|
|
|
|
MD_FblDiag_0313_VerifyFctOutput:
|
|
Reason: Signature/checksum verification functions are stored as void pointers as actual type is not known at
|
|
configuration time.
|
|
Risk: Function signature not compatible with expected type.
|
|
Prevention: Integrator has to take care the configured functions match with the expected signature.
|
|
|
|
MD_FblDiag_0314_MemCpy:
|
|
Reason: The copy function have a void pointer as a function parameter.
|
|
Risk: No risk, because the underlying vuint8 pointer type is known.
|
|
Prevention: No prevention necessary.
|
|
|
|
MD_FblDiag_0314_KeyPtr:
|
|
Reason: The verification parameter structure has a void pointer member for the key to support different
|
|
key types for different use cases
|
|
Risk: No risk, because the underlying key pointer type is known.
|
|
Prevention: No prevention necessary.
|
|
|
|
MD_FblDiag_0883:
|
|
Reason: This file has to be included multiple times explicitly, due to creation of multiple structures via fbl_diag.def.
|
|
Risk: No identifiable risk because defines are undefined in fbl_diag.imp
|
|
Prevention: No prevention required.
|
|
|
|
MD_FblDiag_1514:
|
|
Reason: The variable is used by other modules and can't be declared static.
|
|
Risk: Name conflicts.
|
|
Prevention: Compile and link of the different variants in the component and integration test.
|
|
|
|
MD_FblDiag_2214:
|
|
Reason: Assertion macros have to be disabled in production code and are used only for development.
|
|
Risk: Assertion code may be enabled in production code unintentionally. If a assertion condition is unexpectedly
|
|
false, the code is active. A problem may occur if the Macro is additionally changed from single statement
|
|
to multiple statement.
|
|
Prevention: Macro is not allowed to be changed without review. Development code is automatically disabled via
|
|
configuration of project state "Production".
|
|
|
|
MD_FblDiag_2741:
|
|
Reason: Some if conditions seems to be static only on certain compiling conditions.
|
|
Risk: A condition is always false or true independently from the compiling configuration.
|
|
Prevention: Code inspection and test of the different variants in the component test.
|
|
|
|
MD_FblDiag_2790_kDiagStateMaskAllLong:
|
|
Reason: Create a mask where all bits are set. Generic implementation shifts therefore too many bytes.
|
|
Risk: No identifiable risk.
|
|
Prevention: No prevention required.
|
|
|
|
MD_FblDiag_2880_UnreachableCode:
|
|
Reason: A code section can be executed only based on some static compile time configurations.
|
|
Risk: A code section is never executed independently from the compiling configuration.
|
|
Prevention: Code inspection and test of the different variants in the component test.
|
|
|
|
MD_FblDiag_2889:
|
|
Reason: Multiple return paths are used to reduce code complexity, increase readability and reducing nesting level.
|
|
Risk: Some operations intended to conclude the function (e.g. states cleaning) can be unintentionally jumped.
|
|
Prevention: Code inspection and runtime tests.
|
|
|
|
MD_FblDiag_2916:
|
|
Reason: Assignment to pointer is done within a function to make code more readable.
|
|
Risk: No identifiable risk.
|
|
Prevention: No prevention required.
|
|
|
|
MD_FblDiag_2983_2985_RedundantAssignment:
|
|
Reason: Assignments are redundant only on certain configurations
|
|
Risk: Some code part can be really redundant in all possible configurations.
|
|
Prevention: Code review.
|
|
|
|
MD_FblDiag_3218:
|
|
Reason: The local data of this module is kept at a central location for a better overview and maintenance.
|
|
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.
|
|
|
|
MD_FblDiag_3415:
|
|
Reason: Side effect (conditional execution) is intended.
|
|
Risk: Unintended side effects.
|
|
Prevention: Code is checked for unintended side effects by code inspection.
|
|
|
|
MD_FblDiag_3493:
|
|
Reason: Depending on the configuration the value is not always true.
|
|
Risk: No identifiable risk.
|
|
Prevention: No prevention required.
|
|
|
|
MD_FblDiag_3678:
|
|
Reason: The buffer is actually modified and can therefore not be a const buffer.
|
|
Risk: No identifiable risk.
|
|
Prevention: No prevention required.
|
|
|
|
MD_FblDiag_5087_DiagDef:
|
|
Reason: Multiple includes of fbl_diag.def are required for building the configuration tables of the diagnostic layer.
|
|
Risk: Resulting code is difficult to understand and maintain.
|
|
Prevention: All changes to the affected code parts have to be reviewed by the module responsible. On a mid term
|
|
view, the respective implementation will be replaced by generated code.
|
|
|
|
MD_FblDiag_ConstValue:
|
|
Reason: Value is constant depending on configuration aspects or platform specific implementation. This leads to
|
|
constant control expressions, unreachable code or redundant operations.
|
|
Risk: Wrong or missing functionality.
|
|
Prevention: Code inspection and test of the different variants in the component test.
|
|
|
|
*/
|
|
|
|
/***********************************************************************************************************************
|
|
* END OF FILE: FBL_DIAG.C
|
|
**********************************************************************************************************************/
|
|
|