/*! \file 
**********************************************************************************	
* Title:						Discretix SST utility API Source file						 					
*																			
* Filename:					    sst_utility.c															
*																			
* Project, Target, subsystem:	SST 6.0, Utility, API
* 
* Created:						21.08.2007														
*
* Modified:						21.08.2007										
*
* \Author						Einat Ron														
*																			
* \Remarks						
*           Copyright (C) 2006 by Discretix Technologies Ltd. All Rights reserved.
**********************************************************************************/


/*----------- External include files ----------------------------------------*/
#include "DX_VOS_Mem.h"
#include "SEPDriver.h"
#include "error.h"
#include "sst_errors.h"
#include "sst_sep_errors.h"
#include "sst_types.h"
#include "sst_host_util.h"
#include "sst_host_def.h"
/*----------- Local include files -------------------------------------------*/
#include "sst_test_flags.h"
#include "sst_host_op_code.h"
#include "NVS.h"

/*----------- Local include files -------------------------------------------*/
/*----------- Local Variable declarations -----------------------------------*/
/*----------- Local function declarations -----------------------------------*/
/*----------- Local constant definitions  -----------------------------------*/

/*---------------------------------------------------------------------------*/
/*               API FUNCTIONS                                               */
/*---------------------------------------------------------------------------*/
/*Utility services*/
   
/*SST_DataHandleBuild*/
/*!
\brief Build a handle of a data object stored in the SST according to its type and bits set by the user.

@param aDataType        [in]     The type of the relevant object. 
@param aDataObjID       [in]     The ID provided by the user (23 LSBs will be taken to account). 
@param aDataHandle_ptr  [out]    The returned handle.

@return SST_RC_OK The operation completed successfully.
@return SST_RC_FAIL The operation failed.
@return SST_RC_ERROR_NULL_POINTER [debug] At least one of the past arguments is null.

**/        
DxError_t SST_DataHandleBuild(SSTDataType_t aDataType,
                              SSTObjectId_t aDataObjID,
                              SSTHandle_t *aDataHandle_ptr)
{
	
    DxUint32_t              paramInBuffer_ptr [DX_3_WORDS_PARAMS];
    DxUint32_t              paramOutBuffer_ptr[DX_4_WORDS_PARAMS];
    DxError_t               errorRC;
	
	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
   errorRC = SEPDriver_Lock();
   if(DX_MNG_SEP_IS_DISABLE_ERR == errorRC)
   {
       errorRC = SST_RC_ERROR_SEP_DISABLED; 
       goto exit_function;
   }
   else if (DX_OK != errorRC)
   {
       errorRC = SST_RC_ERROR_SEP; 
       goto exit_function;
   }

	/* Operation Code */
    paramInBuffer_ptr[0] = SST_SEP_OP_CODE_DATA_HANDLE_BUILD;

    /*  Input Parameters */
    paramInBuffer_ptr[1] =  (DxUint32_t)aDataType;
    paramInBuffer_ptr[2] =  (DxUint32_t)aDataObjID;


    /************************************************************************/
    /* Send an input buffer to SeP and wait for output parameters          */
    /************************************************************************/
    errorRC = SST_SendOneMsgGetResponse(paramInBuffer_ptr,
        /* Input buffer length */
        DX_3_WORDS_PARAMS * sizeof(DxUint32_t), 
        paramOutBuffer_ptr,
        /* Output buffer maximal length */
        DX_4_WORDS_PARAMS * sizeof(DxUint32_t));
    if (DX_OK != errorRC)
        goto exit_data_handle_build;

    /************************************************************************/
    /* Analyze return buffer                                                */
    /************************************************************************/
    /* Op code */
    if (paramOutBuffer_ptr[0] != SST_SEP_OP_CODE_DATA_HANDLE_BUILD)
    {
        errorRC = SST_RC_ERROR_SEP;
        goto exit_data_handle_build;
    }
    /* RC */    
	errorRC = paramOutBuffer_ptr[1];
	SST_HOST_RETURN_CODE_CHECK(errorRC,exit_data_handle_build);

    /* Fill out output parameters */
    aDataHandle_ptr->objDigest = paramOutBuffer_ptr[2];
    aDataHandle_ptr->objId     = paramOutBuffer_ptr[3];

exit_data_handle_build: 
	/************************************************************************/
	/* UnLock access to  SEP                                                  */
	/************************************************************************/
	SEPDriver_Unlock();

exit_function:
    
    return errorRC;
}
    
/*SST_DataTypeGet*/
/*!
\brief Retrieves the type of an object by its handle.

@param aObjHandle   [in]     The handle of the relevant object. 
@param aObjType_ptr [out]    The returned type.

@return SST_RC_OK The operation completed successfully.
@return SST_RC_FAIL The operation failed.
@return SST_RC_ERROR_NULL_POINTER [debug] At least one of the past arguments is null.

**/
DxError_t SST_DataTypeGet(SSTHandle_t aDataHandle,
                          SSTDataType_t *aDataType_ptr)
{
    DxUint32_t              paramInBuffer_ptr [DX_3_WORDS_PARAMS];
    DxUint32_t              paramOutBuffer_ptr[DX_3_WORDS_PARAMS];
    DxError_t               errorRC;
	
	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
   errorRC = SEPDriver_Lock();
   if(DX_MNG_SEP_IS_DISABLE_ERR == errorRC)
   {
       errorRC = SST_RC_ERROR_SEP_DISABLED; 
       goto exit_function;
   }
   else if (DX_OK != errorRC)
   {
       errorRC = SST_RC_ERROR_SEP; 
       goto exit_function;
   }

	/* Operation Code */
    paramInBuffer_ptr[0] = SST_SEP_OP_CODE_DATA_TYPE_GET;

    /*  Input Parameters */
    paramInBuffer_ptr[1] =  (DxUint32_t)aDataHandle.objDigest; 
    paramInBuffer_ptr[2] =  (DxUint32_t)aDataHandle.objId;     


    /************************************************************************/
    /* Send an input buffer to SeP and wait for output parameters          */
    /************************************************************************/
    errorRC = SST_SendOneMsgGetResponse(paramInBuffer_ptr,
        /* Input buffer length */
        DX_3_WORDS_PARAMS * sizeof(DxUint32_t), 
        paramOutBuffer_ptr,
        /* Output buffer maximal length */
        DX_3_WORDS_PARAMS * sizeof(DxUint32_t));
    if (DX_OK != errorRC)
        goto exit_data_type_get;

    /************************************************************************/
    /* Analyze return buffer                                                */
    /************************************************************************/
    /* Op code */
    if (paramOutBuffer_ptr[0] != SST_SEP_OP_CODE_DATA_TYPE_GET)
    {
        errorRC = SST_RC_ERROR_SEP;
        goto exit_data_type_get;
    }
    /* RC */    
	errorRC = paramOutBuffer_ptr[1];
	SST_HOST_RETURN_CODE_CHECK(errorRC,exit_data_type_get);

    /* Fill out output parameters */
    *aDataType_ptr = paramOutBuffer_ptr[2];

exit_data_type_get: 
	/************************************************************************/
	/* UnLock access to  SEP                                                  */
	/************************************************************************/
	SEPDriver_Unlock();

exit_function:
    
    return errorRC;
	
}

/*SST_WorkspaceSizeGet*/
/*!
\brief Retrieves the minimum size needed for workspace.

@param aWorkspaceOp   			[in]   Workspace type. 
@param aWorkspaceMinSize_ptr   	[out]  The requested size.

@return SST_RC_OK The operation completed successfully.
@return SST_RC_FAIL The operation failed.

**/
DxError_t SST_WorkspaceSizeGet(SSTWorkspaceOp_t aWorkspaceOp,
							   DxUint32_t *aWorkspaceMinSize_ptr)
{
    DxUint32_t              paramInBuffer_ptr [DX_2_WORDS_PARAMS];
    DxUint32_t              paramOutBuffer_ptr[DX_3_WORDS_PARAMS];
    DxError_t               errorRC;
	
	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
   errorRC = SEPDriver_Lock();
   if(DX_MNG_SEP_IS_DISABLE_ERR == errorRC)
   {
       errorRC = SST_RC_ERROR_SEP_DISABLED; 
       goto exit_function;
   }
   else if (DX_OK != errorRC)
   {
       errorRC = SST_RC_ERROR_SEP; 
       goto exit_function;
   }

	/* Operation Code */
    paramInBuffer_ptr[0] = SST_SEP_OP_CODE_WORKSPACE_SIZE_GET;

    /*  Input Parameters */
    paramInBuffer_ptr[1] =  (DxUint32_t)aWorkspaceOp; 


    /************************************************************************/
    /* Send an input buffer to SeP and wait for output parameters          */
    /************************************************************************/
    errorRC = SST_SendOneMsgGetResponse(paramInBuffer_ptr,
        /* Input buffer length */
        DX_2_WORDS_PARAMS * sizeof(DxUint32_t), 
        paramOutBuffer_ptr,
        /* Output buffer maximal length */
        DX_3_WORDS_PARAMS * sizeof(DxUint32_t));
    if (DX_OK != errorRC)
        goto exit_data_type_get;

    /************************************************************************/
    /* Analyze return buffer                                                */
    /************************************************************************/
    /* Op code */
    if (paramOutBuffer_ptr[0] != SST_SEP_OP_CODE_WORKSPACE_SIZE_GET)
    {
        errorRC = SST_RC_ERROR_SEP;
        goto exit_data_type_get;
    }
    /* RC */    
	errorRC = paramOutBuffer_ptr[1];
	SST_HOST_RETURN_CODE_CHECK(errorRC,exit_data_type_get);

    /* Fill out output parameters */
    *aWorkspaceMinSize_ptr = paramOutBuffer_ptr[2];

exit_data_type_get: 
	/************************************************************************/
	/* UnLock access to  SEP                                                  */
	/************************************************************************/
	SEPDriver_Unlock();

exit_function:
    
    return errorRC;
	
}



/* SST_UtilNVSMaxSizeSet */
/*!
\brief 
Set the maximal NVS size to be used by the memory identified.

@param memoryID	            [in]  identifier to the relevant memory.
@param newMaxSizeInBytes	[in]  the new maximal NVS size

@return SST_RC_OK The operation completed successfully.
@return SST_RC_FAIL The operation failed (Relevant error from inside modules)   
@return SST_RC_ERROR_CLOSED The SST is closed (SST hasn't gone through a proper init)
@return SST_RC_ERROR_WRONG_MEMORY_ID The received memory ID does not correspond to any of the memory IDs currently used
@return SST_RC_ERROR_NVS_MAX_SIZE_TOO_SMALL The requested size is too small 
@return SST_RC_ERROR_NVS_MAX_SIZE_TOO_BIG The requested size is too big 
**/
DxError_t SST_UtilNVSMaxSizeSet(const DxNvsMemoryId_t memoryID, 
                                const DxUint32_t      newMaxSizeInBytes)
{
    DxUint32_t              paramInBuffer_ptr [DX_3_WORDS_PARAMS];
    DxUint32_t              paramOutBuffer_ptr[DX_2_WORDS_PARAMS];
    DxError_t               errorRC;
    DxNvsMemoryId_t         nvsMemoryId;
	
	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
	
	/* get the memory id from NVS */
	errorRC = NVS_GetMemoryId(memoryID , &nvsMemoryId);
	if(errorRC != DX_OK)
	{
	  errorRC = SST_RC_ERROR_WRONG_MEMORY_ID;
	  goto exit_function;
	}
	
   errorRC = SEPDriver_Lock();
   if(DX_MNG_SEP_IS_DISABLE_ERR == errorRC)
   {
       errorRC = SST_RC_ERROR_SEP_DISABLED; 
       goto exit_function;
   }
   else if (DX_OK != errorRC)
   {
       errorRC = SST_RC_ERROR_SEP; 
       goto exit_function;
   }

	/* Operation Code */
    paramInBuffer_ptr[0] = SST_SEP_OP_CODE_NVS_MAX_SIZE_SET;

    /* Input Parameters */
    paramInBuffer_ptr[1] =  (DxUint32_t)nvsMemoryId; 

    paramInBuffer_ptr[2] =  (DxUint32_t)newMaxSizeInBytes; 


    /************************************************************************/
    /* Send an input buffer to SeP and wait for output parameters          */
    /************************************************************************/
    errorRC = SST_SendOneMsgGetResponse(paramInBuffer_ptr,
        /* Input buffer length */
        DX_3_WORDS_PARAMS * sizeof(DxUint32_t), 
        paramOutBuffer_ptr,
        /* Output buffer maximal length */
        DX_2_WORDS_PARAMS * sizeof(DxUint32_t));
    if (DX_OK != errorRC)
        goto exit_data_type_get;

    /************************************************************************/
    /* Analyze return buffer                                                */
    /************************************************************************/
    /* Op code */
    if (paramOutBuffer_ptr[0] != SST_SEP_OP_CODE_NVS_MAX_SIZE_SET)
    {
        errorRC = SST_RC_ERROR_SEP;
        goto exit_data_type_get;
    }
    /* RC */    
	errorRC = paramOutBuffer_ptr[1];
	SST_HOST_RETURN_CODE_CHECK(errorRC,exit_data_type_get);
    
exit_data_type_get: 
	/************************************************************************/
	/* UnLock access to  SEP                                                  */
	/************************************************************************/
	SEPDriver_Unlock();

exit_function:
    
    return errorRC;
	
}/* End of SST_UtilNVSMaxSizeSet */



/* SST_UtilNVSSizesGet */
/*!
\brief 
Retrieve the maximal size of the NVS and the currently used size
according to the memory ID.

@param memoryID	            [in]  identifier to the relevant memory.
@param maxSizeInBytes_ptr	[out] a pointer to store the max size.
@param usedSizeInBytes_ptr	[out] a pointer to store the used size.

@return SST_RC_OK The operation completed successfully.
@return SST_RC_FAIL The operation failed (Relevant error from inside modules)   
@return SST_RC_ERROR_CLOSED The SST is closed (SST hasn't gone through a proper init)
@return SST_RC_ERROR_WRONG_MEMORY_ID The received memory ID does not correspond to any of the memory IDs currently used

@notes: it is allowed to pass only one pointer and set the other to NULL.  
**/
DxError_t SST_UtilNVSSizesGet(const DxNvsMemoryId_t memoryID, 
                              DxUint32_t        *maxSizeInBytes_ptr,
                              DxUint32_t        *usedSizeInBytes_ptr)
{
    DxUint32_t              paramInBuffer_ptr [DX_2_WORDS_PARAMS];
    DxUint32_t              paramOutBuffer_ptr[DX_4_WORDS_PARAMS];
    DxError_t               errorRC;
    DxNvsMemoryId_t         nvsMemoryId;
	
	/************************************************************************/
	/*  Lock access to SEP                                                  */
	/************************************************************************/
	
	errorRC = NVS_GetMemoryId(memoryID , &nvsMemoryId);
	if(errorRC != DX_OK)
	{
	    errorRC = SST_RC_ERROR_WRONG_MEMORY_ID;
	    goto exit_function;
	}
	
    errorRC = SEPDriver_Lock();
    if(DX_MNG_SEP_IS_DISABLE_ERR == errorRC)
    {
        errorRC = SST_RC_ERROR_SEP_DISABLED; 
        goto exit_function;
    }
    else if (DX_OK != errorRC)
    {
        errorRC = SST_RC_ERROR_SEP; 
        goto exit_function;
    }

	/* Operation Code */
    paramInBuffer_ptr[0] = SST_SEP_OP_CODE_NVS_SIZE_GET;

    /* Input Parameters */
    paramInBuffer_ptr[1] =  (DxUint32_t)nvsMemoryId;        


    /************************************************************************/
    /* Send an input buffer to SeP and wait for output parameters          */
    /************************************************************************/
    errorRC = SST_SendOneMsgGetResponse(paramInBuffer_ptr,
        /* Input buffer length */
        DX_2_WORDS_PARAMS * sizeof(DxUint32_t), 
        paramOutBuffer_ptr,
        /* Output buffer maximal length */
        DX_4_WORDS_PARAMS * sizeof(DxUint32_t));
    if (DX_OK != errorRC)
        goto exit_data_type_get;

    /************************************************************************/
    /* Analyze return buffer                                                */
    /************************************************************************/
    /* Op code */
    if (paramOutBuffer_ptr[0] != SST_SEP_OP_CODE_NVS_SIZE_GET)
    {
        errorRC = SST_RC_ERROR_SEP;
        goto exit_data_type_get;
    }
    /* RC */    
	errorRC = paramOutBuffer_ptr[1];
	SST_HOST_RETURN_CODE_CHECK(errorRC,exit_data_type_get);
	 
	*maxSizeInBytes_ptr  = paramOutBuffer_ptr[2];
	*usedSizeInBytes_ptr = paramOutBuffer_ptr[3];
    
exit_data_type_get: 
	/************************************************************************/
	/* UnLock access to  SEP                                                  */
	/************************************************************************/
	SEPDriver_Unlock();

exit_function:
    
    return errorRC;
	
}






