#include <tees_extension.h>
#include "tci.h"
#include "debug_log.h"
#include "tl_main_arcounter.h"
#include "process_cmd.h"
#include "tee_internal_api.h"
#include "tees_secure_object.h"
#include "TZ_Vendor_tl.h"
#include "tz_arcounter_msg.h"
#include "tl_arcounter_ctx.h"

#define TAG "ARCOUNTER_MAIN: "

tl_arcounter_ctx_t g_tl_arcounter_ctx;

static tciMessage_t sendMsgCopy;
static tciMessage_t rspMsgCopy;

TEE_Result TA_CreateEntryPoint(void)
{
	return TEE_SUCCESS;
}

void TA_DestroyEntryPoint(void)
{
	return;
}

TEE_Result TA_OpenSessionEntryPoint(uint32_t paramTypes, TEE_Param params[4], void** sessionContext)
{
//	printf(TAG "Open session for arcounter is success\n");
	return TEE_SUCCESS;
}

void TA_CloseSessionEntryPoint(void* sessionContext)
{
	return;
}

/* Trustlet entry. */
TEE_Result TA_InvokeCommandEntryPoint(void* sessionContext, uint32_t commandID, uint32_t paramTypes, TEE_Param params[4])
{
	//printf(TAG "Open INVOKE\n");
	uint32_t ret;
	uint32_t commandId;
	tciMessage_t* sendmsg = NULL;
	tciMessage_t* respmsg = NULL;

//	printf(TAG "In ARCOUNTER invoke command \n");
//	printf(TAG "paramTypes:%d, TEE_PARAM_TYPES:%d\n", paramTypes, TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE));

	if (paramTypes != (uint32_t)TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) {
		printf(TAG "Bad Parameters in invoke command \n");
		return TEE_ERROR_BAD_PARAMETERS;
	}

	if (TEES_IsREESharedMemory (TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE, params[0].memref.buffer, params[0].memref.size) != TEE_SUCCESS ||
		TEES_IsREESharedMemory (TEE_MEMORY_ACCESS_WRITE, params[1].memref.buffer, params[1].memref.size) != TEE_SUCCESS) {
		printf(TAG "Memory access check error\n");
		return TEE_ERROR_ACCESS_DENIED;
	}

	TTY_LOG("TA_InvokeCommandEntryPoint: %d, %d",params[0].memref.size, params[1].memref.size );
	if (params[0].memref.buffer == NULL || params[1].memref.buffer == NULL
		|| params[0].memref.size < sizeof(tciMessage_t)
		|| params[1].memref.size < sizeof(tciMessage_t)) {
		return TEE_ERROR_BAD_PARAMETERS;
	}

	/* Create local copy of WSM buffer to prevent Race Condition */
	TEE_MemFill(&sendMsgCopy, 0, sizeof(tciMessage_t));
	TEE_MemFill(&rspMsgCopy, 0, sizeof(tciMessage_t));
	TEE_MemMove(&sendMsgCopy, params[0].memref.buffer, sizeof(tciMessage_t));
	TEE_MemMove(&rspMsgCopy, params[1].memref.buffer, sizeof(tciMessage_t));

	sendmsg = &sendMsgCopy;
	respmsg = &rspMsgCopy;

	ret = process_cmd(&g_tl_arcounter_ctx, commandID, sendmsg, respmsg);

	respmsg->header.id = RSP_ID(commandID);
	respmsg->header.status = ret;
	respmsg->header.len = sizeof(tciMessage_t);
	TEE_MemMove(params[1].memref.buffer, &rspMsgCopy, sizeof(tciMessage_t));

	TEE_MemFill(&sendMsgCopy, 0, sizeof(tciMessage_t));
	TEE_MemFill(&rspMsgCopy, 0, sizeof(tciMessage_t));

	return TEE_SUCCESS;
}

/** @} */
