/******************************************************************************/
/* Williams Advanced Engineering Limited                     Copyright(C) 2021*/
/* Grove                                                  All rights reserved */
/*                                                                            */
/******************************************************************************/


/*------------------------------------------------------------*/
/*          Includes                                          */
/*------------------------------------------------------------*/
#include "FBL_BootMPrv.h"
#include "FBL_DataMCfg.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 "Ios_CheckBootLoaderSignature.h"
#include "Ios_BootLoaderVersion.h"
#include "Ios_DefineCatalog.h"
#include "Ios_Flash.h"
#include "sys_core.h"
#include "Ios_Std.h"
#include "ti_fee.h"


/***************************************************************/
/* Extern imported functions                                   */
/***************************************************************/

extern void Fbl_DataM_MainFunction(void);
//extern TI_FeeModuleStatusType MemIf_GetStatus(uint8 DeviceIndex);

#define MemIf_GetStatus(DeviceIndex)  TI_Fee_GetStatus(DeviceIndex)

/*------------------------------------------------------------*/
/*          Local global Variables definition                 */
/*------------------------------------------------------------*/
// _boot_crc_table from Linker script
extern const CRC_TABLE _boot_crc_table;

uint64 g_u64BootSignature       = SIGNATURE_INVALID;
uint8  g_bBootloaderSignatureOK = UNDEFINED;

SecVerificationStatusType tAppSectionVerificationStatus = VerifStatus_Undetermined;
SecVerificationStatusType tCalSectionVerificationStatus = VerifStatus_Undetermined;
SecVerificationStatusType tAppCompatibilityVerificationStatus = VerifStatus_Undetermined;
SecVerificationStatusType tCalCompatibilityVerificationStatus = VerifStatus_Undetermined;

crcSemiCpuCtrlType gMyCrcCtrl =
{
        .bInitialized = FALSE,
        .g_crcTable = NULL,
        .i32LastEntry = 0,
        .u32DmaRequLine = 19,
        .eDmaChannel = DMA_CH0,
        .ulSignatureValue = 0,
        .bSignatureStatus = UNDEFINED
};


VerifyMngrStatusType g_tVerifyMngrStatus =
{
 .CurrentVerifJobReq = VerifyJobReqstNone,
 .CurrentVerifJobStatus = VerifyJobComplete,
};


/*------------------------------------------------------------*/
/*          Functions definition                              */
/*------------------------------------------------------------*/
void fnIosResetAppSectionVerificationStatus(void)
{
    tAppSectionVerificationStatus = VerifStatus_Undetermined;
}

void fnIosResetCalSectionVerificationStatus(void)
{
    tCalSectionVerificationStatus = VerifStatus_Undetermined;
}

void fnIosResetAllVerificationStatus(void)
{
    tAppSectionVerificationStatus = VerifStatus_Undetermined;
    tCalSectionVerificationStatus = VerifStatus_Undetermined;
    tAppCompatibilityVerificationStatus = VerifStatus_Undetermined;
    tCalCompatibilityVerificationStatus = VerifStatus_Undetermined;
}

void fnIosSetVerifySectionIntegrityRqst(IntegrityVerificationJobType tSectionToVerify)
{
    g_tVerifyMngrStatus.CurrentVerifJobReq = tSectionToVerify;
}


IntegrityVerificationJobType fnIosGetCurrentVerifyRqst(void)
{
    return(g_tVerifyMngrStatus.CurrentVerifJobReq);
}


IntegrityVerificationJobStatusType fnIosGetCurrentVerifyJobStatus(void)
{
    return(g_tVerifyMngrStatus.CurrentVerifJobStatus);
}



SecVerificationStatusType fnIosGetAppSecVerificationStatus(void)
{
    return(tAppSectionVerificationStatus);
}


SecVerificationStatusType fnIosGetCalSecVerificationStatus(void)
{
    return(tCalSectionVerificationStatus);
}

void fnIosSetAppSecVerificationStatus(SecVerificationStatusType Status)
{
    tAppSectionVerificationStatus = Status;
}


void fnIosSetCalSecVerificationStatus(SecVerificationStatusType Status)
{
    tCalSectionVerificationStatus= Status;
}


void fnIosCheckApplicationCompatibility(void)
{
    MEM_BLOCK_INFO* tMemInfo;

    _coreDisableFlashEcc_();

    tMemInfo = (MEM_BLOCK_INFO*)APP_INFO_ADDRESS;

    if((tMemInfo->CompatibilityTag == COMPATIBILITY_MARKER_WAEBMUVX) && \
      (tMemInfo->Hw_Revision == HW_REVISION_ID))
    {
        tAppCompatibilityVerificationStatus = VerifStatus_Passed;
    }
    else
    {
        tAppCompatibilityVerificationStatus = VerifStatus_Failed;
    }

    _coreEnableFlashEcc_();
}

void fnIosCheckCalibrationCompatibility(void)
{
    MEM_BLOCK_INFO* tMemInfo;

    _coreDisableFlashEcc_();

    tMemInfo = (MEM_BLOCK_INFO*)CAL_INFO_ADDRESS;

    if((tMemInfo->CompatibilityTag == COMPATIBILITY_MARKER_WAEBMUVX) && \
      (tMemInfo->Hw_Revision == HW_REVISION_ID))
    {
        tCalCompatibilityVerificationStatus = VerifStatus_Passed;
    }
    else
    {
        tCalCompatibilityVerificationStatus = VerifStatus_Failed;
    }

    _coreEnableFlashEcc_();
}


SecVerificationStatusType fnIosGetApplicationCompatibilityStatus(void)
{
    return(tAppCompatibilityVerificationStatus);
}

SecVerificationStatusType fnIosGetCalibrationCompatibilityStatus(void)
{
    return(tCalCompatibilityVerificationStatus);
}

void fnIosSetApplicationCompatibilityStatus(SecVerificationStatusType Status)
{
    tAppCompatibilityVerificationStatus= Status;
}

void fnIosSetCalibrationCompatibilityStatus(SecVerificationStatusType Status)
{
    tCalCompatibilityVerificationStatus = Status;
}



void fnIosVerifySectionIntegrityMngr (void)
{
    static GENERIC_CRC_TABLE_TYPE* tCrcTable = NULL;
    static uint8 bRecordIndex = 0, bNeedSecondLoopToVerifyCal = FALSE, bNeedToSetBootMngrAppValidityFlag = FALSE;
    static crcConfig_t    tCrcParams;
    static crcModConfig_t tCrcModConfig;
    SecVerificationStatusType tAppCompatibitility;
    SecVerificationStatusType tCalCompatibitility;

    volatile uint64  u64SignatureCalc = 0U;

    uint32 uAppValidity = FBL_BOOTM_APPLICATION_REGION_INVALID;

    NvM_Rb_StatusType NvM_WriteAllStatusflag= NVM_RB_STATUS_IDLE;
    TI_FeeModuleStatusType Status = IDLE;


    // Current Job Complete
    if(VerifyJobComplete == g_tVerifyMngrStatus.CurrentVerifJobStatus)
    {
        // Request to start a new job
        switch(g_tVerifyMngrStatus.CurrentVerifJobReq)
        {
        case(VerifyAppSecIntegrity):

            _coreDisableFlashEcc_();

            tCrcTable = (GENERIC_CRC_TABLE_TYPE*)APP_CRC_TABLE_ADDRESS;

            if(0xFFFFFFFF == tCrcTable->num_recs) //Region erased
            {
                tAppSectionVerificationStatus = VerifStatus_Failed;
                g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                wcu_printf("APP region erased - Integrity failed\n");
                _coreEnableFlashEcc_();
            }
            else
            {
                if(NUM_RECORDS_APP_CRC_TABLE == tCrcTable->num_recs)
                {
                    wcu_printf("App Crc num records as per expectation.\n");
                    tAppSectionVerificationStatus = VerifStatus_Undetermined;
                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                    wcu_printf("Verifying APP region integrity\n");
                }
                else
                {
                    wcu_printf("App Crc num records NOT as per expectation.\n");
                    tAppSectionVerificationStatus = VerifStatus_Undetermined;
                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                    wcu_printf("Verifying APP region integrity\n");
                }
            }
            break;

        case(VerifyCalSecIntegrity):

            _coreDisableFlashEcc_();

            tCrcTable = (GENERIC_CRC_TABLE_TYPE*)CAL_CRC_TABLE_ADDRESS;

            if(0xFFFFFFFF == tCrcTable->num_recs) //Region erased
            {
                tCalSectionVerificationStatus = VerifStatus_Failed;
                g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                wcu_printf("CAL region erased  - Integrity failed\n");
                _coreEnableFlashEcc_();
            }
            else
            {
                if(NUM_RECORDS_CAL_CRC_TABLE == tCrcTable->num_recs)
                {
                    wcu_printf("Cal Crc num records as per expectation.\n");
                    tCalSectionVerificationStatus = VerifStatus_Undetermined;
                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                    wcu_printf("Verifying CAL region integrity\n");
                }
                else
                {
                    wcu_printf("Cal Crc num records NOT as per expectation.\n");
                    tCalSectionVerificationStatus = VerifStatus_Undetermined;
                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                    wcu_printf("Verifying CAL region integrity\n");
                }
            }
            break;

        case(VerifyAppAndCalSecIntegrity):

                bNeedSecondLoopToVerifyCal = TRUE;
                bNeedToSetBootMngrAppValidityFlag = TRUE;
                g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyAppSecIntegrity; // Override job request to start with App
                _coreDisableFlashEcc_();

                tCrcTable = (GENERIC_CRC_TABLE_TYPE*)APP_CRC_TABLE_ADDRESS;

                if(0xFFFFFFFF == tCrcTable->num_recs) //Region erased
                {
                    tAppSectionVerificationStatus = VerifStatus_Failed;
                    tCalSectionVerificationStatus = VerifStatus_Failed;
                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                    g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                    wcu_printf("APP region erased - Integrity failed\n");
                    _coreEnableFlashEcc_();
                }
                else
                {
                    if(NUM_RECORDS_APP_CRC_TABLE == tCrcTable->num_recs)
                    {
                        wcu_printf("App Crc num records as per expectation.\n");
                        tAppSectionVerificationStatus = VerifStatus_Undetermined;
                        tCalSectionVerificationStatus = VerifStatus_Undetermined;
                        g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                        wcu_printf("Verifying APP region integrity\n");
                    }
                    else
                    {
                        wcu_printf("App Crc num records NOT as per expectation.\n");
                        tAppSectionVerificationStatus = VerifStatus_Undetermined;
                        tCalSectionVerificationStatus = VerifStatus_Undetermined;
                        g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInit;
                        wcu_printf("Verifying APP region integrity\n");
                    }
                }
                break;

        default:
            // do nothing
            g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
            g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
            break;
        }
    }
    else
    {
        switch( g_tVerifyMngrStatus.CurrentVerifJobStatus)
        {
        case (VerifyJobInit):
            tCrcParams.crc_channel   = CRC_CH1;
            tCrcParams.mode          = CRC_FULL_CPU;
            tCrcParams.pcount        = 0U; /* All counters are disabled in Full CPU mode */
            tCrcParams.scount        = 0U; /* All counters are disabled in Full CPU mode */
            tCrcParams.wdg_preload   = 0U; /* All counters are disabled in Full CPU mode */
            tCrcParams.block_preload = 0U; /* All counters are disabled in Full CPU mode */
            crcSetConfig(crcREG, &tCrcParams);
            bRecordIndex = 0;
            g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobInProgress;
            break;

        case (VerifyJobInProgress):
            if(bRecordIndex < tCrcTable->num_recs)
            {
                tCrcModConfig.crc_channel  = CRC_CH1;
                tCrcModConfig.mode         = CRC_FULL_CPU;
                tCrcModConfig.data_length  = tCrcTable->recs[bRecordIndex].size / 8;
                tCrcModConfig.src_data_pat = (uint64*)tCrcTable->recs[bRecordIndex].addr;

                crcChannelReset(crcREG, CRC_CH1);
                crcSignGen(crcREG, &tCrcModConfig);
                u64SignatureCalc = crcGetPSASig(crcREG, CRC_CH1);

                if(u64SignatureCalc != tCrcTable->recs[bRecordIndex].crc_value)
                {
                    if(VerifyAppSecIntegrity == g_tVerifyMngrStatus.CurrentVerifJobReq)
                    {
                        tAppSectionVerificationStatus = VerifStatus_Failed;
                        wcu_printf("APP region integrity corrupted ! Region: %d\n", bRecordIndex);
                        wcu_printf("Ref Val : 0x%x - Calc Val: 0x%x\n",tCrcTable->recs[bRecordIndex].crc_value,  u64SignatureCalc);
                    }
                    else if(VerifyCalSecIntegrity == g_tVerifyMngrStatus.CurrentVerifJobReq)
                    {
                        tCalSectionVerificationStatus = VerifStatus_Failed;
                        wcu_printf("CAL region integrity corrupted !\n");
                    }
                    else
                    {
                        // do nothing
                    }

                    //                    if(bNeedToSetBootMngrAppValidityFlag)
                    //                    {
                    bNeedToSetBootMngrAppValidityFlag = FALSE;
                    uAppValidity = FBL_BOOTM_APPLICATION_REGION_INVALID;
                    Fbl_DataM_NvmApplicationValidFlagWriteFunc((uint8*) &uAppValidity);
                    //}

                    /* Force Non-volatile memory write */
                    do
                    {
                        /* Execute */
                        Fbl_DataM_MainFunction();
                        NvM_MainFunction();
                        //TI_Fee_MainFunction();
                        (void)MemIf_Rb_MainFunction();
                        (void)NvM_Rb_GetStatus(&NvM_WriteAllStatusflag);
                        Status = MemIf_Rb_GetStatus();
                    } while ((NvM_WriteAllStatusflag == NVM_RB_STATUS_BUSY)|| (Status != IDLE) || (Fbl_DataM_NvmAllBlocksArePersisted() == FALSE));

                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                    g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                    _coreEnableFlashEcc_();
                }
                else
                {
                    // progress through the number of records into the crc table
                    bRecordIndex++;
                }
            }
            else
            {
                if(VerifyAppSecIntegrity == g_tVerifyMngrStatus.CurrentVerifJobReq)
                {
                    tAppSectionVerificationStatus = VerifStatus_Passed;
                    wcu_printf("APP region integrity OK !\n");

                    if(TRUE == bNeedSecondLoopToVerifyCal)
                    {
                        bNeedSecondLoopToVerifyCal = FALSE;

                        g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                        g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyCalSecIntegrity;

                    }
                    else
                    {
                        g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                        g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                    }
                }
                else if(VerifyCalSecIntegrity == g_tVerifyMngrStatus.CurrentVerifJobReq)
                {
                    // Check application and cal compatibility
                    fnIosCheckApplicationCompatibility();
                    fnIosCheckCalibrationCompatibility();
                    tAppCompatibitility = fnIosGetApplicationCompatibilityStatus();
                    tCalCompatibitility = fnIosGetCalibrationCompatibilityStatus();

                    if(bNeedToSetBootMngrAppValidityFlag)
                    {
                        bNeedToSetBootMngrAppValidityFlag = FALSE;

                        //Check compatibility
//                        if((VerifStatus_Passed == tAppCompatibitility) && (VerifStatus_Passed == tCalCompatibitility))
//                        {
//                            uAppValidity = FBL_BOOTM_APPLICATION_REGION_VALID;
//                        }
//                        else
//                        {
//                            uAppValidity = FBL_BOOTM_APPLICATION_REGION_INVALID;
//                        }

                        uAppValidity = 0; // force a not saved state
                        Fbl_DataM_NvmApplicationValidFlagWriteFunc((uint8*) &uAppValidity);

                        uAppValidity = FBL_BOOTM_APPLICATION_REGION_VALID;
                        Fbl_DataM_NvmApplicationValidFlagWriteFunc((uint8*) &uAppValidity);

//                        /* Force Non-volatile memory write */
//                        do
//                        {
//                            /* Execute */
//                            Fbl_DataM_MainFunction();
//                            NvM_MainFunction();
//                            TI_Fee_MainFunction();
//                            //(void)MemIf_Rb_MainFunction();
//                            (void)NvM_Rb_GetStatus(&NvM_WriteAllStatusflag);
//                            Status = (TI_FeeModuleStatusType)MemIf_GetStatus(0);
//                        } while ((NvM_WriteAllStatusflag == NVM_RB_STATUS_BUSY)|| (Status != IDLE) || (Fbl_DataM_NvmAllBlocksArePersisted() == FALSE));

                    }

                    tCalSectionVerificationStatus = VerifStatus_Passed;
                    wcu_printf("CAL region integrity OK !\n");

                    //if(FBL_BOOTM_APPLICATION_REGION_VALID == uAppValidity)
                    if((VerifStatus_Passed == tAppCompatibitility) && (VerifStatus_Passed == tCalCompatibitility))
                        wcu_printf("Info: Compatibility OK !\n");
                    else
                        wcu_printf("Info: Compatibility NOK !\n");

                    g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;
                    g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
                }
                else
                {
                    // do nothing
                }

                _coreEnableFlashEcc_();

            }
            break;

        case(VerifyJobComplete):
            g_tVerifyMngrStatus.CurrentVerifJobStatus = VerifyJobComplete;

            if(FALSE == bNeedSecondLoopToVerifyCal)
            {
                g_tVerifyMngrStatus.CurrentVerifJobReq = VerifyJobReqstNone;
            }
            _coreEnableFlashEcc_();
            break;

        default:
            break;
        }
    }
}


uint8 fnIosCheckBootLoaderSignature(void)
{
    uint8 bBootloaderSignatureOK = TRUE, i = 0;
    volatile uint64  u64SignatureCalc = 0U;
    crcConfig_t    tCrcParams;
    crcModConfig_t tCrcModConfig;

    tCrcParams.crc_channel   = CRC_CH1;
    tCrcParams.mode          = CRC_FULL_CPU;
    tCrcParams.pcount        = 0U; /* All counters are disabled in Full CPU mode */
    tCrcParams.scount        = 0U; /* All counters are disabled in Full CPU mode */
    tCrcParams.wdg_preload   = 0U; /* All counters are disabled in Full CPU mode */
    tCrcParams.block_preload = 0U; /* All counters are disabled in Full CPU mode */

    crcSetConfig(crcREG, &tCrcParams);

    for (i = 0 ; i < _boot_crc_table.num_recs ; i++)
    {
        tCrcModConfig.crc_channel  = CRC_CH1;
        tCrcModConfig.mode         = CRC_FULL_CPU;
        tCrcModConfig.data_length  = _boot_crc_table.recs[i].size / 8;
        tCrcModConfig.src_data_pat = (uint64*)_boot_crc_table.recs[i].addr;

        crcChannelReset(crcREG, CRC_CH1);
        crcSignGen(crcREG, &tCrcModConfig);
        u64SignatureCalc = crcGetPSASig(crcREG, CRC_CH1);

        g_u64BootSignature += _boot_crc_table.recs[i].crc_value;

        if (u64SignatureCalc != _boot_crc_table.recs[i].crc_value)
        {
            bBootloaderSignatureOK = FALSE;         /* Fail */
            g_u64BootSignature = SIGNATURE_INVALID ;
            break;
        }
        else
        {
            /* Pass */
        }
    }

    if(bBootloaderSignatureOK)
        wcu_printf("Boot Integrity check passed\n");
    else
        wcu_printf("Boot Integrity check failed\n");


    return(bBootloaderSignatureOK);
}

///* This function uses the semi CPU mode which uses DMA transfer */
//void fnIosCheckBootLoaderSignatureFast(void)
//{
//    //uint8 i = 0;
//    volatile uint64  u64SignatureCalc = 0U;
//    crcConfig_t    tCrcParams;
//    g_dmaCTRL   g_dmaCTRLPKT;
//
//    gMyCrcCtrl.bInitialized = TRUE;
//    gMyCrcCtrl.g_crcTable = (GENERIC_CRC_TABLE_TYPE *)&_boot_crc_table;
//    gMyCrcCtrl.i32LastEntry = 0;
//    gMyCrcCtrl.ulSignatureValue = 0;
//    gMyCrcCtrl.bSignatureStatus = UNDEFINED;
//
//    //rtiGetPeriod(rtiCOMPARE3);
//    rtiEnableNotification(1U << 11); /* Enable DMA request 3 for CRC (bit 11) */
//    crcEnableNotification(crcREG, CRC_CH1_CC | CRC_CH1_FAIL | CRC_CH1_OR | CRC_CH1_UR | CRC_CH1_TO); /* Enable all interrupts for Channel 0 */
//
//
//    /* Configure DMA Control Packed (structure is part of dma.c) */
//    g_dmaCTRLPKT.SADD      = gMyCrcCtrl.g_crcTable->recs[gMyCrcCtrl.i32LastEntry].addr;  /* initial source address */
//    g_dmaCTRLPKT.DADD      = (uint32_t)(&(crcREG->PSA_SIGREGL1)); /* initial destination address */
//    g_dmaCTRLPKT.CHCTRL    = 0UL; /* channel control */
//    g_dmaCTRLPKT.RDSIZE    = ACCESS_64_BIT; /* read size */
//    g_dmaCTRLPKT.WRSIZE    = ACCESS_64_BIT; /* write size */
//    g_dmaCTRLPKT.FRCNT     = gMyCrcCtrl.g_crcTable->recs[gMyCrcCtrl.i32LastEntry].size / 8UL; /* frame count */
//    g_dmaCTRLPKT.ELCNT     = 1;   /* element count */
//    g_dmaCTRLPKT.ELSOFFSET = 0UL << g_dmaCTRLPKT.RDSIZE; /* element source offset */
//    g_dmaCTRLPKT.FRSOFFSET = 0UL << g_dmaCTRLPKT.RDSIZE; /* frame source offset */
//    g_dmaCTRLPKT.ELDOFFSET = 0UL << g_dmaCTRLPKT.WRSIZE; /* element destination offset */
//    g_dmaCTRLPKT.FRDOFFSET = 0UL << g_dmaCTRLPKT.WRSIZE; /* frame destination offset */
//
//    g_dmaCTRLPKT.PORTASGN  = 4UL; /* only Port B */
//
//    g_dmaCTRLPKT.TTYPE     = FRAME_TRANSFER ; /* transfer type */
//    g_dmaCTRLPKT.ADDMODERD = ADDR_INC1;     /* address mode read */
//    g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED;     /* address mode write */
//    g_dmaCTRLPKT.AUTOINIT  = AUTOINIT_OFF;     /* autoinit off */
//
//    tCrcParams.crc_channel   = CRC_CH1;
//    tCrcParams.mode          = CRC_SEMI_CPU;
//    tCrcParams.pcount        = g_dmaCTRLPKT.FRCNT;
//    tCrcParams.scount        = 1U;
//    tCrcParams.wdg_preload   = 0U;
//    tCrcParams.block_preload = (g_dmaCTRLPKT.FRCNT * 10UL*10UL*2UL) / 64UL; /* The timeout counter is clocked by a prescaler clock which is permanently running at division 64 of HCLK clock. */
//
//    //wcu_printf("Checking CRC for address 0x%08X, %d elements\n", g_dmaCTRLPKT.SADD, g_dmaCTRLPKT.FRCNT);
//    //printf("Checking CRC for address 0x%08X, %d elements\r\n", g_dmaCTRLPKT.SADD, g_dmaCTRLPKT.FRCNT);
//
//    Fapi_Init(0);
//    // Disable ECC before first DMA transfer
//    _coreDisableFlashEcc_();
//
//    crcChannelReset(crcREG, CRC_CH1);
//    crcSetConfig(crcREG, &tCrcParams);
//
//    /* Assign DMA Control Packet to DMA Channel */
//    dmaSetCtrlPacket(gMyCrcCtrl.eDmaChannel, g_dmaCTRLPKT);
//
//    dmaReqAssign(gMyCrcCtrl.eDmaChannel, gMyCrcCtrl.u32DmaRequLine);
//
//    /* Set the DMA Channel to trigger on h/w request */
//    dmaSetChEnable(gMyCrcCtrl.eDmaChannel, DMA_HW);
//}
//
//
//void crcSemiCpuMode(crcBASE_t *crc, crcSemiCpuCtrlType * crcSemiCpuCtrl)
//{
//    crcConfig_t sCrcParams;
//    g_dmaCTRL   g_dmaCTRLPKT;
//    uint64 u64Signature = 0ull;
//
//    if (crc != crcREG)
//    {
//        /* Fault */
//    }
//    else if (crcSemiCpuCtrl == NULL)
//    {
//        /* Fault */
//    }
//    else if (crcSemiCpuCtrl->g_crcTable == NULL)
//    {
//        /* Fault */
//    }
//    else
//    {
//
//        if(crcSemiCpuCtrl->bInitialized == FALSE)
//        {
//            crcSemiCpuCtrl->bInitialized = TRUE;
//            crcSemiCpuCtrl->i32LastEntry = 0;
//        }
//        else
//        {
//
//            u64Signature = crcGetSectorSig(crc, CRC_CH1);
//
//            /* Check CRC */
//            if (u64Signature != crcSemiCpuCtrl->g_crcTable->recs[crcSemiCpuCtrl->i32LastEntry].crc_value)
//            {
//                /* Fault */
//                //printf("Wrong CRC in SW Module @ address: 0x%08X\n", crcTable->recs[i32LastEntry-1].addr);
//                crcSemiCpuCtrl->ulSignatureValue = SIGNATURE_INVALID;
//                crcSemiCpuCtrl->bSignatureStatus = NOK;
//                //wcu_printf("F\n");
//
//                //rtiDisableNotification(1U << 11); /* Disable DMA request 3 (bit 11) */
//                //crcDisableNotification(crc, CRC_CH1_CC | CRC_CH1_FAIL | CRC_CH1_OR | CRC_CH1_UR | CRC_CH1_TO);
//
//                // renable flash ecc
//                _coreEnableFlashEcc_();
//            }
//            else
//            {
//                /* Pass */
//                //printf("P\n");
//                crcSemiCpuCtrl->ulSignatureValue += u64Signature;
//
//                /* Go to next CRC table entry */
//                crcSemiCpuCtrl->i32LastEntry++;
//
//                /* Skip sections that run in RAM*/
////                if((crcSemiCpuCtrl->i32LastEntry == 2) || (crcSemiCpuCtrl->i32LastEntry == 5) || (crcSemiCpuCtrl->i32LastEntry >= (crcSemiCpuCtrl->g_crcTable->num_recs -1)))
////                    crcSemiCpuCtrl->i32LastEntry++;
//
//                if (crcSemiCpuCtrl->i32LastEntry >= crcSemiCpuCtrl->g_crcTable->num_recs)
//                {
//                    // Stop CRC check process - CRC table verified
//                    crcSemiCpuCtrl->i32LastEntry = 0;
//                    crcSemiCpuCtrl->bSignatureStatus = OK;
//                    //rtiDisableNotification(1U << 11); /* Disable DMA request 3 (bit 11) */
//                    //crcDisableNotification(crc, CRC_CH1_CC | CRC_CH1_FAIL | CRC_CH1_OR | CRC_CH1_UR | CRC_CH1_TO);
//
//                    // re-enable flash ecc
//                    _coreEnableFlashEcc_();
//                }
//                else
//                {
//                    /* Configure DMA Control Packed (structure is part of dma.c) */
//                    g_dmaCTRLPKT.SADD      = crcSemiCpuCtrl->g_crcTable->recs[crcSemiCpuCtrl->i32LastEntry].addr;  /* initial source address */
//                    g_dmaCTRLPKT.DADD      = (uint32_t)(&(crc->PSA_SIGREGL1)); /* initial destination address */
//                    g_dmaCTRLPKT.CHCTRL    = 0UL; /* channel control */
//                    g_dmaCTRLPKT.RDSIZE    = ACCESS_64_BIT; /* read size */
//                    g_dmaCTRLPKT.WRSIZE    = ACCESS_64_BIT; /* write size */
//                    g_dmaCTRLPKT.FRCNT     = crcSemiCpuCtrl->g_crcTable->recs[crcSemiCpuCtrl->i32LastEntry].size / 8ul; /* frame count */
//                    g_dmaCTRLPKT.ELCNT     = 1;   /* element count */
//                    g_dmaCTRLPKT.ELSOFFSET = 0UL << g_dmaCTRLPKT.RDSIZE; /* element source offset */
//                    g_dmaCTRLPKT.FRSOFFSET = 0UL << g_dmaCTRLPKT.RDSIZE; /* frame source offset */
//                    g_dmaCTRLPKT.ELDOFFSET = 0UL << g_dmaCTRLPKT.WRSIZE; /* element destination offset */
//                    g_dmaCTRLPKT.FRDOFFSET = 0UL << g_dmaCTRLPKT.WRSIZE; /* frame destination offset */
//                    g_dmaCTRLPKT.PORTASGN  = 4UL; /* only Port B */
//                    g_dmaCTRLPKT.TTYPE     = FRAME_TRANSFER ; /* transfer type */
//                    g_dmaCTRLPKT.ADDMODERD = ADDR_INC1;     /* address mode read */
//                    g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED;     /* address mode write */
//                    g_dmaCTRLPKT.AUTOINIT  = AUTOINIT_OFF;     /* autoinit off */
//
//                    sCrcParams.crc_channel   = CRC_CH1;
//                    sCrcParams.mode          = CRC_SEMI_CPU;
//                    sCrcParams.pcount        = g_dmaCTRLPKT.FRCNT;
//                    sCrcParams.scount        = 1U;
//                    sCrcParams.wdg_preload   = 0U;
//                    sCrcParams.block_preload = (g_dmaCTRLPKT.FRCNT * 10UL*10UL*2UL) / 64UL; /* The timeout counter is clocked by a prescaler clock which is permanently running at division 64 of HCLK clock. */
//
//
//                    //rtiGetPeriod(rtiCOMPARE3);
//                    rtiEnableNotification(1U << 11); /* Enable DMA request 3 for CRC (bit 11) */
//                    crcEnableNotification(crcREG, CRC_CH1_CC | CRC_CH1_FAIL | CRC_CH1_OR | CRC_CH1_UR | CRC_CH1_TO); /* Enable all interrupts for Channel 0 */
//
//
//                    //wcu_printf("Checking CRC for address 0x%08X, %d elements\r\n", g_dmaCTRLPKT.SADD, g_dmaCTRLPKT.FRCNT);
//                    //printf("Checking CRC for address 0x%08X, %d elements\r\n", g_dmaCTRLPKT.SADD, g_dmaCTRLPKT.FRCNT);
//
//                    crcChannelReset(crc, CRC_CH1);
//
//                    crcSetConfig(crc, &sCrcParams);
//
//                    /* Assign DMA Control Packet to DMA Channel */
//                    dmaSetCtrlPacket(crcSemiCpuCtrl->eDmaChannel, g_dmaCTRLPKT);
//
//                    dmaReqAssign(crcSemiCpuCtrl->eDmaChannel, crcSemiCpuCtrl->u32DmaRequLine);
//
//                    /* Set the DMA Channel to trigger on h/w request */
//                    dmaSetChEnable(crcSemiCpuCtrl->eDmaChannel, DMA_HW);
//                }
//            }
//        }
//    }
//
//    return;
//}
//
//void crcNotification(crcBASE_t *crc, uint32 flags)
//{
//    if (CRC_CH1_CC == flags)
//    {
//        crcSemiCpuMode(crc, &gMyCrcCtrl);
//    }
//    else
//    {
//        gMyCrcCtrl.ulSignatureValue = SIGNATURE_INVALID;
//        gMyCrcCtrl.bSignatureStatus = NOK;
////        rtiDisableNotification(1UL << 11); /* Disable DMA trigger 3 (bit 11) */
////        crcDisableNotification(crc, CRC_CH1_CC | CRC_CH1_FAIL | CRC_CH1_OR | CRC_CH1_UR | CRC_CH1_TO);
//
//        wcu_printf("Fault in crcNotification, flags: 0x%08X\r\n", flags);
//    }
//    return;
//}



uint64 fnIosGetBootLoaderSignatureValue(void)
{
    return(g_u64BootSignature);
}

void  fnIosSetBootLoaderSignatureValues (void)
{
    g_u64BootSignature = gMyCrcCtrl.ulSignatureValue;
    g_bBootloaderSignatureOK = gMyCrcCtrl.bSignatureStatus;

}

uint8 fnIosGetSemiCPUSignatureStatus(void)
{
    return(gMyCrcCtrl.bSignatureStatus);
}
