/*! \file 
**********************************************************************************
*Title:                        Discretix Secure Clock Toolkit source file
*
* Filename:                     tlk_sclk_api.c 
*
* Project, Target, subsystem:   Toolkit, Secure Clock
* 
* Created:                      29.10.2008
*
* Modified:                     29.10.2008
*
* \Author                       Ira Boguslavsky
*
* \Remarks
*           Copyright (C) 2008 by Discretix Technologies Ltd. All Rights reserved.
**********************************************************************************/
/*----------- External include files ----------------------------------------*/
#include "DX_VOS_Mem.h"
#include "DX_VOS_String.h"
#include "DX_VOS_Stdio.h"
#include "DX_VOS_BaseTypes.h"
#include "DX_VOS_File.h"

#include "error.h"

#include "SEPDriver.h"

#include "NVS.h"

/*----------- Local include files -------------------------------------------*/
#include "tlk_sclk_api.h"
#include "tlk_sclk_api_errors.h"
#include "tlk_sclk_def.h"
#include "tlk_sclk_host_op_code.h"
#include <stdio.h>
#if TLK_SCLK_VNVS_NVS
#define TLK_SCLK_VNVS_MEMORY_ID	0x3
#endif
DxError_t TLK_SCLK_WorkspaceCheck(DxByte_t			            *workspace_ptr,
                                  DxUint32_t			         workspaceSizeInBytes,
                                  DxUint32_t			         requiredWorkspaceSize);


/*MACRO for checking return code form driver*/
#define TLK_SCLK_HOST_DRIVER_ERROR_CHECK(errorRC,exitMark)          \
		if (DX_SUCCESS != errorRC)									\
		{	errorRC = TLK_SCLK_RC_ERROR_API_FAIL;		    		\
			goto exitMark;}


#define TLK_SCLK_START_OFFSET                       0x0


#define TLK_SCLK_WORD_ALLIGN(arg)                                                           \
                                 /*lint -save -e778*/                                           \
                                ((((DxUint32_t)(arg)) & (0x3)) ?                                \
                                (((((DxUint32_t)(arg))>>(2))+1)<<(2)) : ((DxUint32_t)(arg)))    \
                                /*lint -restore */
/*---------------------------------------------------------------------------*/
/*               Global variables                                            */
/*---------------------------------------------------------------------------*/
//TLK_SCLK_Buffer_t g_TLK_SCLK_PrevCertificateBaseAddress;
#ifndef DX_NO_TLK_SCLK_SUPPORT
    #ifndef DX_NVS_RAM  
	    DxChar_t        g_TLK_SCLK_NVSMemoryFileName[] = "nvs.txt";
	    DxVosFile       g_TLK_SCLK_NVSMemoryId;
	#else
		DxVosFile       g_TLK_SCLK_NVSMemoryId;
		#define         TLK_SCLK_NVS_POOL_SIZE_IN_BYTES   (1024)
		DxChar_t		g_SCLK_TLK_NVSPool[];
	#endif
#endif
/*---------------------------------------------------------------------------*/
/*               API FUNCTIONS                                               */
/*---------------------------------------------------------------------------*/
/************************************************************************/
/* TLK_SCLK_Init                                                        */
/************************************************************************/
DxError_t TLK_SCLK_Init(	DxUint8_t                           *workspace_ptr,
                            DxUint32_t                           workspaceSizeInBytes)
{
    DxError_t    error        = TLK_SCLK_RC_OK;
    DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;   /* Offset into SRAM*/

	DxUint32_t   paramInBuffer[DX_2_WORDS_PARAMS];
    DxUint32_t   paramOutBuffer[DX_2_WORDS_PARAMS];      /* Return code & error code */

	DxTime_t aTime; 
	DxTimeStruct_t  aTimeStruct;
	
	/************************************************************************/
    /*  Create storage for Master Clock Descriptor Storing                  */
    /************************************************************************/
#if TLK_SCLK_VNVS_NVS
#ifndef DX_NVS_RAM  
	error = DX_VOS_FileOpen( &g_TLK_SCLK_NVSMemoryId,
                              g_TLK_SCLK_NVSMemoryFileName,
                              DX_FILE_OPEN_ALWAYS,
                              DX_SHARE_READ_WRITE);
	if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }
#else
	g_TLK_SCLK_NVSMemoryId = (DxVosFile)g_SCLK_TLK_NVSPool;
#endif
	error = NVS_InitFile((DxUint32_t)g_TLK_SCLK_NVSMemoryId,(DxNvsMemoryId_t)TLK_SCLK_VNVS_MEMORY_ID);

#endif
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();

    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_SCLK_INIT_MSG_OP_CODE;
    error = SEPDriver_GetTime(&paramInBuffer[1]);
    
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }


     /* Send constant part */
    error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
                                                 sizeof(DxUint32_t) * DX_2_WORDS_PARAMS,
                                                 sizeof(DxUint32_t) * DX_2_WORDS_PARAMS,
                                                 &sramOffset,
                                                 DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                                sizeof(DxUint32_t) * 2,
                                                sizeof(DxUint32_t) * 2,
                                               &sramOffset ,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_SCLK_INIT_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the error code */
    if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

end_function_unlock:   

    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}
/************************************************************************/
/* TLK_SCLK_ServiceClkGen                                               */
/************************************************************************/
DxError_t TLK_SCLK_ServiceClkGen(    TLK_SCLK_ServiceClockDescriptor_t   *serviceDescr_ptr,
                                     TLK_SCLK_ApplicationId_t            *appId_ptr,
                                     DxTime_t                             maxAllowedDriftIn0_1Seconds,
                                     DxTime_t                             maximumRevalidationPeriod,
                                     TLK_SCLK_ReadPermission_t            readPermission,
 									 DxUint8_t                           *serviceClkPwd,
									 DxUint32_t                          serviceClkPwdLen,
                                     DxUint8_t                           *workspace_ptr,
                                     DxUint32_t                           workspaceSizeInBytes)
{
    DxError_t    error        = TLK_SCLK_RC_OK;
    DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;   /*offset into SRAM*/
    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +                          /*op code*/
    							DX_1_WORD_PARAMS + 			                /*appId_ptr*/
    							DX_1_WORD_PARAMS +							/*maxAllowedDriftIn0_1Seconds*/
    							DX_1_WORD_PARAMS +							/*maximumRevalidationPeriod*/
    							DX_1_WORD_PARAMS +							/*readPermission*/
    							DX_1_WORD_PARAMS +							/*pwdLen*/
                                DX_1_WORD_PARAMS];			                /*AppId*/
    /*buff_ptr*/
    DxUint32_t   paramOutBuffer[DX_1_WORD_PARAMS +                          /*op code*/
                                DX_1_WORD_PARAMS +                          /*error code*/
                                sizeof(TLK_SCLK_ServiceClockDescriptor_t)/4]; 
                                


    /* Check input parameters */
    if (TLK_SCLK_IS_NULL_PARAM( serviceDescr_ptr))
    {
        return TLK_SCLK_RC_ERROR_API_NULL_POINTER;
    }
   
    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();



    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_SCLK_SERVICE_CLK_GEN_MSG_OP_CODE;
	paramInBuffer[1] = maxAllowedDriftIn0_1Seconds;
	paramInBuffer[2] = maximumRevalidationPeriod;
	paramInBuffer[3] = readPermission;
	paramInBuffer[4] = serviceClkPwdLen;
	
	if (appId_ptr == DX_NULL)
	{
		paramInBuffer[5] = 0;
		
	}
	else
	{
		DX_VOS_FastMemCpy(&paramInBuffer[5],appId_ptr,sizeof(TLK_SCLK_ApplicationId_t));
	}
	/* Send constant part */
	error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
	                                             sizeof(DxUint32_t) * DX_6_WORDS_PARAMS,
	                                             sizeof(DxUint32_t) * DX_6_WORDS_PARAMS,
	                                             &sramOffset,
	                                             DX_FALSE);
	if(error != DX_SUCCESS)
	{
	    goto end_function_unlock;
	}

    /* Send Service clock password */
    error = SEPDriver_WriteParamater((DxUint32_t)serviceClkPwd,
                                     serviceClkPwdLen,
                                     TLK_SCLK_MAX_PWD_LEN_IN_BYTES,
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);


    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                                sizeof(DxUint32_t) * 2,
                                                sizeof(DxUint32_t) * 2,
                                               &sramOffset ,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_SCLK_SERVICE_CLK_GEN_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the error code */
    if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

	//sramOffset += 4;
    /* Get sclkificateParamList_ptr */
    error = SEPDriver_ReadParamater((DxUint32_t)( serviceDescr_ptr),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                 &sramOffset,
                                                  DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    
end_function_unlock:   

    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}
/************************************************************************/
/* TLK_SCLK_ServiceClkRead                                              */
/************************************************************************/
DxError_t TLK_SCLK_ServiceClkRead(    TLK_SCLK_ServiceClockDescriptor_t       *serviceDescr_ptr,
                                      TLK_SCLK_ApplicationId_t                *appId_ptr,
                                      TLK_SCLK_ServiceClockTime_t             *currTime_ptr,
                                      TLK_SCLK_TimeFormat_t                   timeFormat,
                                      TLK_SCLK_ReadStatus_t                   *status_ptr,
 									  DxUint8_t                               *serviceClkPwd,
   									  DxUint32_t                              serviceClkPwdLen,
                                      DxUint8_t                               *workspace_ptr,
                                      DxUint32_t                              workspaceSizeInBytes)
{
    DxError_t    error        = TLK_SCLK_RC_OK;
    DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;      /*offset into SRAM*/
   
    TLK_SCLK_ApplicationId_t    appId;

    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +                          /*op code*/
                                DX_1_WORD_PARAMS +                          /*timeFormat*/
                                DX_1_WORD_PARAMS +                          /*pwdLen*/
                                DX_1_WORD_PARAMS ];                         /*appId_ptr - in case if it is DX_NULL */

                                
    DxUint32_t   paramOutBuffer[DX_1_WORD_PARAMS +                          /*op code */
                                DX_1_WORD_PARAMS +                          /*error code*/
                                DX_1_WORD_PARAMS +                          /*status_ptr*/
                                sizeof(TLK_SCLK_ServiceClockDescriptor_t) + /*serviceDescr_ptr*/
                                sizeof(TLK_SCLK_ServiceClockTime_t)];        /*currTime_ptr*/



    /* Check input parameters */
    if (TLK_SCLK_IS_NULL_3PARAMS(   serviceDescr_ptr,
                                    currTime_ptr,
                                    status_ptr))
    {
        return TLK_SCLK_RC_ERROR_API_NULL_POINTER;
    }

    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();


    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_SCLK_SERVICE_CLK_READ_MSG_OP_CODE;
    paramInBuffer[1] = timeFormat;
    paramInBuffer[2] = serviceClkPwdLen;

    if (appId_ptr == DX_NULL)
    {
        /* Send Application ID */
        paramInBuffer[3] = DX_NULL;
    }
    else
    {
        DX_VOS_FastMemCpy(&paramInBuffer[3], appId_ptr, sizeof(TLK_SCLK_ApplicationId_t));
    }
    /* Send constant part */
    error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
                                                 sizeof(DxUint32_t) * DX_4_WORDS_PARAMS,
                                                 sizeof(DxUint32_t) * DX_4_WORDS_PARAMS,
                                                 &sramOffset,
                                                 DX_FALSE);
    if(error != DX_SUCCESS)
    {
         goto end_function_unlock;
    }

    /* Send Service clock password */
    error = SEPDriver_WriteParamater((DxUint32_t)serviceClkPwd,
                                     serviceClkPwdLen,
                                     TLK_SCLK_MAX_PWD_LEN_IN_BYTES,
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* Send Service Descriptor */
    error = SEPDriver_WriteParamater((DxUint32_t)serviceDescr_ptr,
                                     sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                     TLK_SCLK_WORD_ALLIGN(sizeof(TLK_SCLK_ServiceClockDescriptor_t)),
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
          goto end_function_unlock;
    }


    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + error code + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                                sizeof(DxUint32_t) * 3,
                                                sizeof(DxUint32_t) * 3,
                                               &sramOffset ,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_SCLK_SERVICE_CLK_READ_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

    /* Get status */
    *status_ptr = (TLK_SCLK_ReadStatus_t)paramOutBuffer[2];

    error = SEPDriver_ReadParamater((DxUint32_t)( serviceDescr_ptr),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                 &sramOffset,
                                                  DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* Get current time*/
    error = SEPDriver_ReadParamater((DxUint32_t)( currTime_ptr),
                                                  sizeof(TLK_SCLK_ServiceClockTime_t),
                                                  sizeof(TLK_SCLK_ServiceClockTime_t),
                                                 &sramOffset,
                                                  DX_FALSE);
end_function_unlock:   
    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}


/************************************************************************/
/* TLK_SCLK_MCServiceClkRevalidate                                      */
/************************************************************************/
DxError_t TLK_SCLK_ServiceClkRevalidate(    TLK_SCLK_ServiceClockDescriptor_t   *serviceDescr_ptr,
                                            TLK_SCLK_ApplicationId_t            *appId_ptr,
                                    const   TLK_SCLK_ServiceClockTime_t         *expectedTime_ptr,
                                            TLK_SCLK_TimeFormat_t               timeFormat,
 									        DxUint8_t                           *serviceClkPwd,
        									DxUint32_t                          serviceClkPwdLen,
                                            DxUint8_t                           *workspace_ptr,
                                            DxUint32_t                          workspaceSizeInBytes)
                                            
{
    DxError_t    error        = TLK_SCLK_RC_OK;
    DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;      /*offset into SRAM*/
    DxUint32_t   contObjSMPhy;
    DxUint32_t   contObjSMVirt;

    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +                          /*op code*/
							    DX_1_WORD_PARAMS + 		  	                /*pwdLen*/
							    DX_1_WORD_PARAMS + 		  	                /*appId_ptr*/
							    sizeof(TLK_SCLK_ServiceClockTime_t)/4+        /*expectedTime_ptr*/
                         		DX_1_WORD_PARAMS +                          /*timeFormat*/
                                sizeof(TLK_SCLK_ServiceClockDescriptor_t)/4];	/*serviceDescr_ptr*/		

    DxUint32_t   paramOutBuffer[DX_1_WORD_PARAMS +                          /*op code */
                                DX_1_WORD_PARAMS +                          /*error code*/
                                sizeof(TLK_SCLK_ServiceClockDescriptor_t)/4 + /*serviceDescr_ptr*/
                                sizeof(TLK_SCLK_ServiceClockTime_t)/4];       /*currTime_ptr*/


    /* Check input parameters */
    if (TLK_SCLK_IS_NULL_2PARAMS(   serviceDescr_ptr,
                                    expectedTime_ptr))
    {
        return TLK_SCLK_RC_ERROR_API_NULL_POINTER;
    }
    

    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();


    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_SCLK_SERVICE_CLK_REVALIDATE_MSG_OP_CODE;
    paramInBuffer[1] = timeFormat;
    paramInBuffer[2] = serviceClkPwdLen;
    
	/* Send application Id*/
	if (appId_ptr == DX_NULL)
	{
		paramInBuffer[3] = 0;
	}
	else
	{
        DX_VOS_FastMemCpy(&paramInBuffer[3], appId_ptr, sizeof(TLK_SCLK_ApplicationId_t));
	}

    /* Send constant part */
    error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
                                                 sizeof(DxUint32_t) * DX_4_WORDS_PARAMS,
                                                 sizeof(DxUint32_t) * DX_4_WORDS_PARAMS,
                                                 &sramOffset,
                                                 DX_FALSE);

    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }
    /* Send Service clock password */
    error = SEPDriver_WriteParamater((DxUint32_t)serviceClkPwd,
                                     serviceClkPwdLen,
                                     TLK_SCLK_MAX_PWD_LEN_IN_BYTES,
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }
	/*Send expected time */
	error = SEPDriver_WriteParamater((DxUint32_t)expectedTime_ptr,
                                      sizeof(TLK_SCLK_ServiceClockTime_t),
                                      TLK_SCLK_WORD_ALLIGN(sizeof(TLK_SCLK_ServiceClockTime_t)),
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

	
    
    /* Send Service Descriptor */
    error = SEPDriver_WriteParamater((DxUint32_t)serviceDescr_ptr,
                                      sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                      TLK_SCLK_WORD_ALLIGN(sizeof(TLK_SCLK_ServiceClockDescriptor_t)),
                                     &sramOffset,
                                     DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }


    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                                sizeof(DxUint32_t) * 2,
                                                sizeof(DxUint32_t) * 2,
                                               &sramOffset ,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_SCLK_SERVICE_CLK_REVALIDATE_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

	
    /* Get service descriptor */
    error = SEPDriver_ReadParamater((DxUint32_t)( serviceDescr_ptr),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                  sizeof(TLK_SCLK_ServiceClockDescriptor_t),
                                                 &sramOffset,
                                                  DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }
    
end_function_unlock:   
    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}


DxError_t TLK_SCLK_WorkspaceSizeGet(	DxUint32_t	*workspaceSizeInBytes_ptr)
{
    /************************************************************************/
    /* Check NVS configuration                                              */
    /* User MUST choose one and only one type of NVS in                     */
    /* tlk_sclk_api_config.h file                                           */
    /************************************************************************/
    /*lint -save -e774*/    
    /* Disable PCLINT Info Msg 774: Boolean within 'String' always evaluates to [True/False] */    
    if (TLK_SCLK_VNVS_CONFIG_SUMMARY != 1)
        return TLK_SCLK_RC_ERROR_API_NVS_CONFIGURATION;
    /*lint -restore */

    if (TLK_SCLK_IS_NULL_PARAM(workspaceSizeInBytes_ptr))
        return TLK_SCLK_RC_ERROR_API_NULL_POINTER;

    *workspaceSizeInBytes_ptr = TLK_SCLK_MIN_WORKSPACE_IN_SIZE_IN_BYTES;
    return TLK_SCLK_RC_OK;
}

/************************************************************************/
/* TLK_SCLK_Terminate                                                   */
/************************************************************************/

DxError_t 
TLK_SCLK_Terminate(                         DxUint8_t                           *workspace_ptr,
                                            DxUint32_t                           workspaceSizeInBytes)
{
    DxError_t    error        = TLK_SCLK_RC_OK;
    DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;   /* Offset into SRAM*/

    DxUint32_t   paramInBuffer[DX_2_WORDS_PARAMS];       /* Return code & error code */

    DxUint32_t   paramOutBuffer[DX_2_WORDS_PARAMS];      /* Return code & error code */


    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();


    /************************************************************************/
    /* Start sending message to SeP                                         */
    /************************************************************************/
    SEPDriver_StartMessage(&sramOffset);

    paramInBuffer[0] = TLK_SCLK_TERMINATE_MSG_OP_CODE;

     /* Send constant part */
    error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
                                                 sizeof(DxUint32_t) * DX_1_WORD_PARAMS,
                                                 sizeof(DxUint32_t) * DX_1_WORD_PARAMS,
                                                 &sramOffset,
                                                 DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* End message                                                          */
    /************************************************************************/
    SEPDriver_EndMessage(sramOffset);

    /************************************************************************/
    /* Wait for the response                                                */
    /************************************************************************/
    error = SEPDriver_POLL_FOR_REPONSE();
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /************************************************************************/
    /* Start reading message from the SEP                                   */
    /************************************************************************/
    /* Start the message */
    error = SEPDriver_StartIncomingMessage(&sramOffset);
    if(error)
    {
        goto end_function_unlock;
    }
    /* Read opcode + status  */
    error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
                                                sizeof(DxUint32_t) * 2,
                                                sizeof(DxUint32_t) * 2,
                                               &sramOffset ,
                                                DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

    /* check the opcode */
    if(paramOutBuffer[0] != TLK_SCLK_TERMINATE_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

    /* check the status */
    if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
    {
        error = paramOutBuffer[1];
        goto end_function_unlock;
    }

end_function_unlock:   

    /* lock access to the SEP */
    SEPDriver_Unlock();

    return error;
}

/************************************************************************/
/* TLK_SCLK_ServiceClkRead                                              */
/************************************************************************/
DxError_t  TLK_SCLK_ServiceClkAuthenticate( TLK_SCLK_ServiceClockDescriptor_t      *serviceDescr_ptr,
										   TLK_SCLK_ApplicationId_t                *appId_ptr,
										   DxUint8_t                               *serviceClkPwd,
										   DxUint32_t                              serviceClkPwdLen,
										   TLK_SCLK_Cookie_t					   serviceClkCookie,
										   DxUint32_t                              *serviceClkOffset_ptr,
										   DxUint8_t                               *workspace_ptr,
										   DxUint32_t                              workspaceSizeInBytes)
{
	DxError_t    error        = TLK_SCLK_RC_OK;
	DxUint32_t   sramOffset   = TLK_SCLK_START_OFFSET;      /*offset into SRAM*/

	DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +    /*op code*/
			                    DX_1_WORD_PARAMS +    /*pwd len*/
	                            DX_1_WORD_PARAMS];    /*AppId exist*/

	TLK_SCLK_ApplicationId_t   dummyAppId = {0x0};
	TLK_SCLK_ApplicationId_t   *localAppIdptr;

	DxUint32_t   paramOutBuffer[DX_1_WORD_PARAMS +    /*op code */
		                        DX_1_WORD_PARAMS +    /*error code*/
								DX_1_WORD_PARAMS +    /*offset*/
								sizeof(TLK_SCLK_Cookie_t)/4]; /*cookie*/



	/* Check input parameters */
	if (TLK_SCLK_IS_NULL_PARAM(serviceDescr_ptr))
	{
		return TLK_SCLK_RC_ERROR_API_NULL_POINTER;
	}

	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
	SEPDriver_Lock();


	/************************************************************************/
	/* Start sending message to SeP                                         */
	/************************************************************************/
	SEPDriver_StartMessage(&sramOffset);

	paramInBuffer[0] = TLK_SCLK_SERVICE_CLK_AUTH_MSG_OP_CODE;
	paramInBuffer[1] = serviceClkPwdLen;

	if (appId_ptr == DX_NULL)
	{
		/* Send Application ID */
		paramInBuffer[2] = 0x0;
		localAppIdptr = &dummyAppId;
	}
	else
	{
		paramInBuffer[2] = 0x1;
		localAppIdptr = appId_ptr;
	}
	/* Send constant part */
	error = SEPDriver_WriteParamater((DxUint32_t)paramInBuffer,
		sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
		sizeof(DxUint32_t) * DX_3_WORDS_PARAMS,
		&sramOffset,
		DX_FALSE);
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/* Send App Id  */
	error = SEPDriver_WriteParamater((DxUint32_t)localAppIdptr,
		                              sizeof(TLK_SCLK_ApplicationId_t),
		                              sizeof(TLK_SCLK_ApplicationId_t),
		                              &sramOffset,
		                              DX_FALSE);
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/* Send Service clock password */
	error = SEPDriver_WriteParamater((DxUint32_t)serviceClkPwd,
		                              serviceClkPwdLen,
		                              TLK_SCLK_MAX_PWD_LEN_IN_BYTES,
		                              &sramOffset,
		                              DX_FALSE);
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/* Send Service Descriptor */
	error = SEPDriver_WriteParamater((DxUint32_t)serviceDescr_ptr,
		                             sizeof(TLK_SCLK_ServiceClockDescriptor_t),
		                             TLK_SCLK_WORD_ALLIGN(sizeof(TLK_SCLK_ServiceClockDescriptor_t)),
		                             &sramOffset,
		                             DX_FALSE);
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}


	/************************************************************************/
	/* End message                                                          */
	/************************************************************************/
	SEPDriver_EndMessage(sramOffset);

	/************************************************************************/
	/* Wait for the response                                                */
	/************************************************************************/
	error = SEPDriver_POLL_FOR_REPONSE();
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/************************************************************************/
	/* Start reading message from the SEP                                   */
	/************************************************************************/
	/* Start the message */
	error = SEPDriver_StartIncomingMessage(&sramOffset);
	if(error)
	{
		goto end_function_unlock;
	}
	/* Read opcode + error code + status  */
	error = SEPDriver_ReadParamater((DxUint32_t)paramOutBuffer,
		sizeof(DxUint32_t) * 4,
		sizeof(DxUint32_t) * 4,
		&sramOffset ,
		DX_FALSE);
	if(error != DX_SUCCESS)
	{
		goto end_function_unlock;
	}

	/* check the opcode */
	if(paramOutBuffer[0] != TLK_SCLK_SERVICE_CLK_AUTH_MSG_OP_CODE)
	{
		error = DX_WRONG_OPCODE_FROM_SEP_ERR;
		goto end_function_unlock;
	}

	/* check the status */
	if(paramOutBuffer[1] != TLK_SCLK_RC_OK)
	{
		error = paramOutBuffer[1];
		goto end_function_unlock;
	}

	/* Get offset */
	*serviceClkOffset_ptr = paramOutBuffer[2];
	/* Get cookie */
	DX_VOS_FastMemCpy(serviceClkCookie,&paramOutBuffer[3],sizeof(TLK_SCLK_Cookie_t));

end_function_unlock:   
	/* lock access to the SEP */
	SEPDriver_Unlock();

	return error;
}
