/************************************************************************** * * Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file Integrity.c * * @author (last) Dara Navaei * @date (last) 29-Sep-2023 * * @author (original) Quang Nguyen * @date (original) 29-May-2021 * ***************************************************************************/ #ifndef _VECTORCAST_ // This header file is disabled in VectorCAST because this is a TI library and VectorCAST uses GNU 7.4 compiler for testing #include #endif #include "reg_tcram.h" #include "Integrity.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Utilities.h" #include "DGDefs.h" #include "HDDefs.h" /** * @addtogroup Integrity * @{ */ // ********** private definitions ********** #ifndef _VECTORCAST_ // This address is redefined in VectorCAST again #define CRC_TABLE_STARTING_ADDR 0x20 ///< The starting address of CRC table for firmware image. #endif #define MAX_CRC_CALC_DATA_SIZE 0x8000 ///< The maximum size of data for each CRC calculation. #define SERR 0x00000001 ///< Bit 0 - Single-bit error in TCRAM Module Error Status Register #define ADDR_DEC_FAIL 0x00000004 ///< Bit 2 - Address decode failed in TCRAM Module Error Status Register #define ADDR_COMP_LOGIC_FAIL 0x00000010 ///< Bit 4 - Address decode logic element failed in TCRAM Module Error Status Register #define DERR 0x00000020 ///< Bit 5 - Multiple bit error in TCRAM Module Error Status Register #define RADDR_PAR_FAIL 0x00000100 ///< Bit 8 - Read Address Parity Failure in TCRAM Module Error Status Register #define WADDR_PAR_FAIL 0x00000200 ///< Bit 9 - Write Address Parity Failure in TCRAM Module Error Status Register #ifdef _VECTORCAST_ // Since VectorCAST does not have access to #include , the structures are defined here so VectoCAST can compile and // instrument the code for Dev testing /*********************************************************/ /* CRC Record Data Structure */ /* NOTE: The list of fields and the size of each field */ /* varies by target and memory model. */ /*********************************************************/ typedef struct crc_record { uint64_t crc_value; uint32_t crc_alg_ID; /* CRC algorithm ID */ uint32_t addr; /* Starting address */ uint32_t size; /* size of data in bytes */ uint32_t padding; /* explicit padding so layout is the same */ /* for COFF and ELF */ } CRC_RECORD; /*********************************************************/ /* CRC Table Data Structure */ /*********************************************************/ typedef struct crc_table { uint32_t rec_size; uint32_t num_recs; CRC_RECORD recs[1]; } CRC_TABLE; // Defined a CRC table here since the start address of the CRC table in the firmware will cause a segmentation fault in VectorCAST // The CRC_TABLE_STARTING_ADDR in undefined at the top and is defined here again with pointing to the testTable address that has // been define here. // NOTE: User prefix code was not used because defining the structures at the top would cause compilation errors CRC_TABLE testTable; #define CRC_TABLE_STARTING_ADDR &testTable #endif /// Time threshold to check RAM error is 2 seconds static const U32 RAM_ERROR_CHECK_TIME_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); // ********** private data ********** static U32 currentRecord; ///< Current CRC table record to check. static U32 currentProcessedSize; ///< Current data size processed for CRC calculation. static U32 crcCalculated; ///< The calculated CRC value. static SELF_TEST_STATUS_T integrityTestStatus; ///< Current firmware integrity test status. static U32 processorRAMStatusCounter; ///< Counter used to check processor RAM error. static BOOL singleBitRAMErrorFlag; ///< Flag to signal the processor RAM error. static OVERRIDE_U32_T tcram1ErrStat; ///< TCRAM Module 1 Status Register. static OVERRIDE_U32_T tcram2ErrStat; ///< TCRAM Module 2 Status Register. /*********************************************************************//** * @brief * The initIntegrity function initializes the Integrity module. * @details Inputs: none * @details Outputs: Integrity module initialized * @return none *************************************************************************/ void initIntegrity( void ) { currentRecord = 0; currentProcessedSize = 0; crcCalculated = 0; integrityTestStatus = SELF_TEST_STATUS_IN_PROGRESS; processorRAMStatusCounter = 0; singleBitRAMErrorFlag = FALSE; tcram1ErrStat.data = 0; tcram1ErrStat.ovData = 0; tcram1ErrStat.ovInitData = 0; tcram1ErrStat.override = OVERRIDE_RESET; tcram2ErrStat.data = 0; tcram2ErrStat.ovData = 0; tcram2ErrStat.ovInitData = 0; tcram2ErrStat.override = OVERRIDE_RESET; } /********************************************************************************//** * @brief * The execRAMMonitor function monitors the processor RAM status. * @details Inputs: none * @details Outputs: system event log or alarm activated if RAM error is detected. * @return none ***********************************************************************************/ void execRAMMonitor( void ) { U32 err1, err2 = 0; // Check for processor RAM error if ( ++processorRAMStatusCounter > RAM_ERROR_CHECK_TIME_THRESHOLD ) { tcram1ErrStat.data = tcram1REG->RAMERRSTATUS; // B0TCM in TCRAM Module Error Status Register tcram2ErrStat.data = tcram2REG->RAMERRSTATUS; // B1TCM in TCRAM Module Error Status Register err1 = getU32OverrideValue( &tcram1ErrStat ) & SERR; // Single-bit error, bit 0 in B0TCM in TCRAM Module Error Status Register err2 = getU32OverrideValue( &tcram2ErrStat ) & SERR; // Single-bit error, bit 0 in B1TCM in TCRAM Module Error Status Register if( ( err1 != 0 ) || ( err2 != 0 ) ) { if ( FALSE == singleBitRAMErrorFlag ) { // Log the single-bit RAM error event once only #ifdef _DG_ SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_CPU_RAM_ERROR_STATUS, err1, err2 ); #else SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_CPU_RAM_ERROR_STATUS, err1, err2 ); #endif singleBitRAMErrorFlag = TRUE; } } err1 = getU32OverrideValue( &tcram1ErrStat ) & ( SERR | ADDR_DEC_FAIL | ADDR_COMP_LOGIC_FAIL | DERR | RADDR_PAR_FAIL | WADDR_PAR_FAIL ); err2 = getU32OverrideValue( &tcram2ErrStat ) & ( SERR | ADDR_DEC_FAIL | ADDR_COMP_LOGIC_FAIL | DERR | RADDR_PAR_FAIL | WADDR_PAR_FAIL ); if ( ( err1 != 0 ) || ( err2 != 0 ) ) { #ifdef _DG_ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CPU_RAM_ERROR, err1, err2 ); #else SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_CPU_RAM_ERROR, err1, err2 ); #endif } processorRAMStatusCounter = 0; } } /*********************************************************************//** * @brief * The execIntegrityTest function executes the integrity check for firmware image. * @details Inputs: firmware image CRC table * @details Outputs: none * @return firmware image integrity self-test status *************************************************************************/ SELF_TEST_STATUS_T execIntegrityTest( void ) { CRC_TABLE const * const crcTablePtr = (CRC_TABLE *)CRC_TABLE_STARTING_ADDR; CRC_RECORD const * const currentRecordPtr = &crcTablePtr->recs[ currentRecord ]; BOOL integrityStatus = TRUE; U32 remainingSize = 0; if ( currentRecord < crcTablePtr->num_recs ) { remainingSize = currentRecordPtr->size - currentProcessedSize; if ( remainingSize > MAX_CRC_CALC_DATA_SIZE ) { crcCalculated = crc32( crcCalculated, (U08 *)( currentRecordPtr->addr + currentProcessedSize ), MAX_CRC_CALC_DATA_SIZE ); currentProcessedSize += MAX_CRC_CALC_DATA_SIZE; } else { crcCalculated = crc32( crcCalculated, (U08 *)( currentRecordPtr->addr + currentProcessedSize ), remainingSize ); integrityStatus &= ( ( (U32)currentRecordPtr->crc_value == crcCalculated ) ? TRUE : FALSE ); crcCalculated = 0; currentProcessedSize = 0; currentRecord++; } } if ( TRUE != integrityStatus ) { integrityTestStatus = SELF_TEST_STATUS_FAILED; #ifdef _DG_ activateAlarmNoData( ALARM_ID_DG_INTEGRITY_POST_TEST_FAILED ); #else activateAlarmNoData( ALARM_ID_HD_INTEGRITY_POST_TEST_FAILED ); #endif activateSafetyShutdown(); } else if ( currentRecord == crcTablePtr->num_recs ) { integrityTestStatus = SELF_TEST_STATUS_PASSED; } return integrityTestStatus; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetRAMStatusOverride function sets the override of the * ram status module. * @details Inputs: none * @details Outputs: TCRAM status * @param reg ram register to override * @param status the status to be overriden * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testSetRAMStatusOverride( U32 reg, U32 status ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( 0 == reg ) { tcram1ErrStat.ovData = status; tcram1ErrStat.override = OVERRIDE_KEY; } else { tcram2ErrStat.ovData = status; tcram2ErrStat.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetRAMStatusOverride function resets the override of the * ram status module. * @details Inputs: none * @details Outputs: TCRAM status * @param reg ram register to override * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetRAMStatusOverride( U32 reg ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; if ( 0 == reg ) { tcram1ErrStat.override = OVERRIDE_RESET; tcram1ErrStat.ovData = tcram1ErrStat.ovInitData; } else { tcram2ErrStat.override = OVERRIDE_RESET; tcram2ErrStat.ovData = tcram2ErrStat.ovInitData; } } return result; } /**@}*/