/*********************************************************************************************************************
 *
 * Description:     User code Port Sample implementation
 * FileName:        FBL_PortUserCode.c
 * Company:         ETAS GmbH (www.etas.com)
 * Generated        28/12/2018 at 11:22
 *
 **********************************************************************************************************************
 *
 * COPYRIGHT RESERVED, Copyright ETAS GmbH 2018. All rights reserved, also regarding any disposal,
 * exploitation, reproduction, editing, distribution, as well as in the event of applications
 * for industrial property rights.
 *
 **********************************************************************************************************************
 * History:
 **********************************************************************************************************************
 * Author        Date            Comment
 **********************************************************************************************************************
BGA1YOK         02/11/2018      First Version    
 **********************************************************************************************************************/


/*********************************************************************************************************************
 * Includes
 *********************************************************************************************************************/
#include "FBL_PortUserCode.h"
#include "FBL_BootMCfg.h"
#include "FBL_ProgMPrv.h"
#include "FBL_BootMPrv.h"
#include "FBL_DataMCfg.h"

#include "Dcm_Cfg_Prot.h"
#include "DcmCore_DslDsd_Inf.h"
#include "Rte_Dcm.h"
#include "BLSM.h"

// Removing of compiler warnings and errors because of type re-declaration between hal_stdtypes.h and Std_Types.h
#define _BOOLEAN_DECLARED
#define _UINT8_DECLARED
#define _UINT16_DECLARED
#define _UINT32_DECLARED
#define _UINT64_DECLARED
#define _SINT8_DECLARED
#define _SINT16_DECLARED
#define _SINT32_DECLARED
#define _SINT64_DECLARED
#define _FLOAT32_DECLARED
#define _FLOAT64_DECLARED
#define _STD_RETURN_TYPE_DECLARED
#define _STDVERSION_DECLARED
//

#include "system.h"
#include "sys_vim.h"
#include "sys_core.h"
#include "can.h"
#include "spi.h"
#include "rti.h"
#include "het.h"
#include "gio.h"
#include <crc_hal.h>
#include "crc_tbl.h"
#include "ti_fee.h"
#include "F021.h"
#include "Ios_DefineCatalog.h"
#include "Ios_BootLoaderVersion.h"
#include "Ios_CheckBootLoaderSignature.h"
#include "Ios_RunTimeInstance.h"
#include "Ios_Flash.h"
#include "Ios_Terminal.h"
#include "Ios_Std.h"
#include "Ios_Digital.h"
#include "sys_dma.h"
#include "Ios_IntrTimerManagement.h"
#include "Ios_CanConfig.h"


/*********************************************************************************************************************
 * Local Defines
 *********************************************************************************************************************/
#define TESTER_PRESENT_CNTR_MAX_VALUE 5

/*********************************************************************************************************************
 * Local Macros
 *********************************************************************************************************************/

/*********************************************************************************************************************
 * Local Types
 *********************************************************************************************************************/

/*********************************************************************************************************************
 * Local Variables
 *********************************************************************************************************************/
static uint32 TesterPresentCntr = 0;

/*********************************************************************************************************************
 * Local Functions Prototypes
 *********************************************************************************************************************/
void delay(void);

/*********************************************************************************************************************
 * Local Functions Implementation
 *********************************************************************************************************************/

void delay(void)
{
    uint32 uldummycnt=0x0000FFU;
    do
    {
        uldummycnt--;
    }
    while(uldummycnt>0);
}

/*********************************************************************************************************************
 * Exported Variables Implementation
 *********************************************************************************************************************/
uint8 Fbl_Port_Variant_ECU = 0xFF;                   /* 0 - Master; 1 - Slave; 0xFF - Unidentified */

/* [$Satisfies $SRS_WAE_FBL 003] [$Satisfies $SRS_WAE_FBL 004] */
const Dcm_RequestDownloadConfig_tst* Fbl_DataM_Cfg_AppRegions[FBL_DATAM_APPLICATION_REGION_NUMBER_OF_REGIONS] = {
    &Dcm_RequestDownloadConfig_cast[0]              /* Application region 0 */
};

/* [$Satisfies $SRS_WAE_FBL 005] [$Satisfies $SRS_WAE_FBL 006] */
const Dcm_RequestDownloadConfig_tst* Fbl_DataM_Cfg_CalibRegions[FBL_DATAM_CALIBRATION_REGION_NUMBER_OF_REGIONS] = {
    &Dcm_RequestDownloadConfig_cast[1]               /* Calibration region 0 */
};

/* [$Satisfies $SRS_WAE_FBL 005] [$Satisfies $SRS_WAE_FBL 006] */
const Dcm_RequestDownloadConfig_tst* Fbl_DataM_Cfg_AppAndCalibRegions[FBL_DATAM_APP_AND_CALIBRATION_REGION_NUMBER_OF_REGIONS] = {
    &Dcm_RequestDownloadConfig_cast[2]               /* Calibration region 0 */
};

/*********************************************************************************************************************
 * Exported Functions Implementation
 *********************************************************************************************************************/
Fbl_ProgM_WriteResultType Fbl_Port_Write(uint32 memoryAddress, uint32 dataLength, const uint8  * reqBuf)
{
    Fbl_ProgM_WriteResultType result = FBL_PROGM_WRITE_RESULT_FAILURE;
    uint8 bWriteRslt;

    //bWriteRslt = Fls_Write(memoryAddress,reqBuf,dataLength); - Used before integrating FLS module for external NVM access
    bWriteRslt = Fls_PgmFlashWrite(memoryAddress,reqBuf,dataLength);

    if(0 == bWriteRslt)
    {
        result = FBL_PROGM_WRITE_RESULT_SUCCESS;
    }
    else
    {
        wcu_printf("Flash Write Fail : %d\n", result);
    }

    return result;
}

/* [$Satisfies $RTA_FBL_SDK_DD_PORT 32]  */
boolean Fbl_Port_ApplicationIsValid(void)
{
    boolean ret = (boolean)FALSE;
    /* Check that all regions are valid */
    if((boolean)TRUE == Fbl_BootM_ApplicationRegionApplicationIsValid())
    {
        // Set all flags OK based on NVM status
        fnIosSetAppSecVerificationStatus(VerifStatus_Passed);
        fnIosSetCalSecVerificationStatus(VerifStatus_Passed);
//        fnIosSetApplicationCompatibilityStatus(VerifStatus_Passed);
//        fnIosSetCalibrationCompatibilityStatus(VerifStatus_Passed);
        ret = (boolean)TRUE;
    }
    return ret;
}

/* [$Satisfies $RTA_FBL_SDK_DD_PORT 154]  */
void Fbl_PortInit_DriverInitOne(void)
{

    //Watchdog Initialisation - Timeout cause system reset
    //Input clock RTI1 = 90MHz = Expiration time == (PreloadValue +1) * 2^13 / Input clock
    //Timeout ~110ms - 0x4B7
    //Timeout ~372ms - 0xFFF - Max Value !
    dwwdInit(Generate_Reset,  0xFFF, Size_100_Percent);
    //Start Watchdog
    dwdCounterEnable();

    // IO port initialisation
    fnIosInitDigitalIOs();

    //CAN bus initialisation
    canInit();

    //Spi Initialisation for CAN1
    spiInit();

    // CAN0 transceiver initialize
    fnIosCANWakeUpSpiCtrlInitialise();  // initialise the CAN SPI Interface
    fnIosCANWakeUpModeControl(); // Initialise SPI CAN0 to normal mode
    fnIosCANWakeUpModeActive();  // Initialise SPI CAN0 to be active
    fnIosCANWakeUpMainStatusAcquire();

    //crc module initialisation
    crcInit();

}

/* [$Satisfies $RTA_FBL_SDK_DD_PORT 155]  */
void Fbl_PortInit_DriverInitTwo(void)
{
    IntegrityVerificationJobType tVerifJobType;
    IntegrityVerificationJobStatusType tVerifJobStatus;
    SecVerificationStatusType tAppCompatibitility;
    SecVerificationStatusType tCalCompatibitility;



    //Init runtime instance ZIST-3384 - Runtime Instancing
    /* ECU variant is only set one time. Any change of variant must apply after ECU reset */
    /* [$Satisfies $SRS_WAE_FBL 015] */
    /* Read run time instance Master or Slave from pin status */
    fnIosDetermineRunTimeInstance();
    Fbl_Port_Variant_ECU = fnIosGetRunTimeInstance();

    if(RUNTIME_INST_BMS1 == fnIosGetRunTimeInstance())
    {
        wcu_printf("Runtime instance is Master.\n");
    }
    else
    {
        wcu_printf("Runtime instance is Slave.\n");
    }

    // Timer initialisation - They will need to be set after read all from saved value in NVRAM
    rtiInit();
    fnIosInitRTICountersFromNVM();
    // Timers will be used for seed generation
    rtiStartCounter(rtiCOUNTER_BLOCK0);
    rtiStartCounter(rtiCOUNTER_BLOCK1);


    fnIosCheckBootLoaderSignature();
    dwdReset();
    //    fnIosCheckBootLoaderSignatureFast();
    //    while(fnIosGetSemiCPUSignatureStatus() == UNDEFINED);// Wait for computation to complete
    //    fnIosSetBootLoaderSignatureValues();

    if( fnIosGetBootLoaderSignatureValue() == SIGNATURE_INVALID )
    {
        wcu_printf("Boot Corrupted - Reset.\n");
        // Blocks and uses watchdog to reset if signature is not good whilst displaying message on RS232
        while(1)
        {
            fnIosFlushTxQueue();
        }
    }

    //Check Application & Cal integrity
    if (Fbl_Port_ApplicationIsValid())
    {
        //Do nothing application valid
        wcu_printf("App integrity check OK from NVM Flag to speed up start.\n");
        fnIosFlushTxQueue();
        wcu_printf("Background verification started.\n");
        fnIosSetVerifySectionIntegrityRqst(VerifyAppAndCalSecIntegrity);
        //wcu_printf("Compatibility check Passed.\n");
    }
    else
    {
        fnIosSetVerifySectionIntegrityRqst(VerifyAppAndCalSecIntegrity);
        do
        {
            fnIosVerifySectionIntegrityMngr();

            tVerifJobStatus = fnIosGetCurrentVerifyJobStatus();
            tVerifJobType = fnIosGetCurrentVerifyRqst();
            dwdReset();

        } while((VerifyJobComplete != tVerifJobStatus) || (VerifyJobReqstNone != tVerifJobType));
    }

    // Check application and cal compatibility at each boot up - ZIST-3322 and ZIST-3321
    fnIosCheckApplicationCompatibility();
    fnIosCheckCalibrationCompatibility();

    // Get result
    tAppCompatibitility = fnIosGetApplicationCompatibilityStatus();
    tCalCompatibitility = fnIosGetCalibrationCompatibilityStatus();

    if((VerifStatus_Passed == tAppCompatibitility) && (VerifStatus_Passed == tCalCompatibitility))
    {
        wcu_printf("App compatibility check Passed.\n");
    }
    else
    {
        wcu_printf("App compatibility check Failed.\n");
    }
    fnIosFlushTxQueue();


    // To reintroduce with a set of commands
    // wcu_printf(cAppPrompt);

}

/* [$Satisfies $SRS_WAE_FBL 007] */
boolean Fbl_Port_Bootloader_Application_Boot_Conditions (void)
{
    boolean bBootConditionOK = FALSE;

    //Satisfy ZIST-2003
    SecVerificationStatusType tAppVerificationStatus = fnIosGetAppSecVerificationStatus();
    SecVerificationStatusType tCalVerificationStatus = fnIosGetCalSecVerificationStatus();
    SecVerificationStatusType tAppCompatibitility = fnIosGetApplicationCompatibilityStatus();
    SecVerificationStatusType tCalCompatibitility = fnIosGetCalibrationCompatibilityStatus();

    if((VerifStatus_Passed == tAppVerificationStatus) && \
       (VerifStatus_Passed == tCalVerificationStatus) && \
       (VerifStatus_Passed == tAppCompatibitility)    && \
       (VerifStatus_Passed == tCalCompatibitility)    && \
       (HW_COMPONENT_ID    != 0 ))
    {
        bBootConditionOK = TRUE;
    }
    else
    {
        bBootConditionOK = FALSE;
    }

    // Test debug Boot
    //bBootConditionOK = TRUE; // Boot conditions forced OK

    return bBootConditionOK;
}


#define DCM_START_SEC_CODE /*Adding this for memory mapping*/
#include "Dcm_MemMap.h"

void SetTesterPresentNotification(void)
{
    TesterPresentCntr++;
    if(TesterPresentCntr >= TESTER_PRESENT_CNTR_MAX_VALUE)
        TesterPresentCntr = TESTER_PRESENT_CNTR_MAX_VALUE;
}

void ResetTesterPresentNotification(void)
{
    if(TesterPresentCntr > 0)
        TesterPresentCntr--;
}

uint8 GetTesterPresentNotification(void)
{
    return(TesterPresentCntr > 0);
}



 /**
 * @ingroup DCM_TPL
 * DcmAppl_UserServiceModeRuleService :-\n
 * This API is used to do specific checks on the SID before processing the service.The ErrorCode parameter(Nrc_u8) needs to be updated by the application in case of failed checks.
 *
 * @param[in]     Sid_u8 : Service Id under processing
 * @param[out]    Nrc_u8 : NRC to be set by the application
 *
 * @retval               E_OK      : Service specific checks passed successfully \n
 * @retval               E_NOT_OK  : Service specific checks failed\n
 *
 */
Std_ReturnType DcmAppl_UserServiceModeRuleService(Dcm_NegativeResponseCodeType * Nrc_u8, uint8 Sid_u8)
{
    Std_ReturnType retVal_u8 = E_OK;
    *Nrc_u8= 0x00;
    switch(Sid_u8)
    {
    case 0x3E: //Tester Present
    case 0x10: //Session Control
    case 0x11: //ECU Reset
    case 0x22: //Read DID
    case 0x27: //Security Access
    case 0x2E: //Write DID
    case 0x31: //Routine Control
    case 0x34: //Request download
    case 0x36: //Transfer data
    case 0x37: //Transfer Exit
        SetTesterPresentNotification();         // Do this for every service as tester need to be present to get here
        OS_Timer32_Start(&Fbl_BLSM_BootTimer);  // Do this for every service as timeout should not be set when services are in process
        break;
    default:
        break;
    }
    return (retVal_u8);
}
#define DCM_STOP_SEC_CODE /*Adding this for memory mapping*/
#include "Dcm_MemMap.h"
