/*! \file 
**********************************************************************************
*Title:                        Discretix OMA DRM v2 Toolkit source file
*
* Filename:                     Toolkit, Certificate Handling
*
* Project, Target, subsystem:   Toolkit, OMA DRM
* 
* Created:                      02.04.2008
*
* Modified:                     02.04.2008
*
* \Author                       Ira Boguslavsky
*
* \Remarks
*           Copyright (C) 2007 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 "error.h"

#include "SEPDriver.h"

/*----------- Local include files -------------------------------------------*/
#include "tlk_cert_api.h"
#include "tlk_cert_errors.h"
#include "tlk_cert_def.h"
#include "tlk_cert_host_op_code.h"

#ifdef TLK_CERT_SEP_SIMULATOR
#include "tlk_cert_duplicate_wrapper.h"
#endif

DxError_t TLK_CERT_WorkspaceCheck(DxByte_t			            *workspace_ptr,
                                  DxUint32_t			         workspaceSizeInBytes,
                                  DxUint32_t			         requiredWorkspaceSize);


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


#ifdef TLK_CERT_SEP_SIMULATOR
#include "tlk_cert_api_duplicate_wrapper.h"
#include "tlk_cert_llf_duplicate_wrapper.h"
#define TLK_CERT_START_OFFSET                       0x8
#else
#define TLK_CERT_START_OFFSET                       0x0
#endif

#define TLK_CERT_WORD_ALLIGN(arg)                                                           \
                                 /*lint -save -e778*/                                           \
                                ((((DxUint32_t)(arg)) & (0x3)) ?                                \
                                (((((DxUint32_t)(arg))>>(2))+1)<<(2)) : ((DxUint32_t)(arg)))    \
                                /*lint -restore */
/*---------------------------------------------------------------------------*/
/*               Global variables                                            */
/*---------------------------------------------------------------------------*/
//TLK_CERT_Buffer_t g_TLK_CERT_PrevCertificateBaseAddress;

/*---------------------------------------------------------------------------*/
/*               API FUNCTIONS                                               */
/*---------------------------------------------------------------------------*/
/************************************************************************/
/* TLK_CERT_CertificateIdCompute                                        */
/************************************************************************/


DxError_t TLK_CERT_ODRM_V2_1_CertifcateIDComputeParamGet(   const   TLK_CERT_Buffer_t           *certificate_ptr,
                                                                    DxSha1Result_t               certificateId,
                                                                    TLK_CERT_CertParameters_t   *certificateParamList_ptr)
{
    DxError_t    error        = TLK_CERT_RC_OK;

    DxUint32_t   sramOffset   = TLK_CERT_START_OFFSET;   /*offset into SRAM*/
    DxUint32_t   certSMPhy;
    DxUint32_t   certSMVirt;
    DxUint32_t   paramInBuffer [DX_1_WORD_PARAMS +                      /*op code*/
                                DX_1_WORD_PARAMS +                      /*certificate_ptr*/    /*buffSizeInBytes*/
                                DX_1_WORD_PARAMS];                                              /*buff_ptr*/
    DxUint32_t   paramOutBuffer[sizeof(DxSha1Result_t) +                /*certificateId*/
                                sizeof(TLK_CERT_CertParameters_t)];     /*certificateParamList_ptr*/
    /* Check input parameters */
    if (TLK_CERT_IS_NULL_PARAM( certificate_ptr))
    {
        return TLK_CERT_RC_ERROR_API_NULL_POINTER;
    }
    
    /************************************************************************/
    /*  Lock access to SEP                                                  */
    /************************************************************************/
    SEPDriver_Lock();
    
	/************************************************************************/
    /*  Address Convertion                                                  */
    /************************************************************************/
	error = SEPDriver_AllocateDataPoolMemory(  certificate_ptr->buff_ptr, 
                                               certificate_ptr->buffSizeInBytes, 
                                               &certSMPhy, 
                                               &certSMVirt);
	TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

	error = SEPDriver_WriteToDataPoolMemory(certSMVirt, 
                                             (DxUint8_t*)certificate_ptr->buff_ptr, 
                                              certificate_ptr->buffSizeInBytes);
	TLK_CERT_HOST_DRIVER_ERROR_CHECK(error,end_function_unlock) ;

    

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

    paramInBuffer[0] = TLK_CERT_V2_1_CERTIFICATE_ID_COMPUTE_MSG_OP_CODE;
    paramInBuffer[1] = certificate_ptr->buffSizeInBytes;
    paramInBuffer[2] = certSMPhy;

     /* 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;
    }

    /************************************************************************/
    /* 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_CERT_V2_1_CERTIFICATE_ID_COMPUTE_MSG_OP_CODE)
    {
        error = DX_WRONG_OPCODE_FROM_SEP_ERR;
        goto end_function_unlock;
    }

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

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

    error = SEPDriver_ReadParamater((DxUint32_t)( certificateParamList_ptr),
                                                  sizeof(TLK_CERT_CertParameters_t),
                                                  TLK_CERT_WORD_ALLIGN(sizeof(TLK_CERT_CertParameters_t)),
                                                 &sramOffset,
                                                  DX_FALSE);
    if(error != DX_SUCCESS)
    {
        goto end_function_unlock;
    }

end_function_unlock:   

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

    return error;
}

