/*
 * app_main.c
 */
#include <stdio.h>

#include <string.h>
#include <unistd.h>

#include <tee_internal_api.h>
#include <tees_extension.h>

#include "app_property.h"

static tciMessage_t sendMsgCopy;
static tciMessage_t rspMsgCopy;

TEE_Result TA_CreateEntryPoint(void)
{
    printf("%s TA_CreateEntryPoint \n", TA_TAG);
    return TEE_SUCCESS;
}

void TA_DestroyEntryPoint(void)
{
    printf("%s TA_DestroyEntryPoint \n", TA_TAG);
}

TEE_Result TA_OpenSessionEntryPoint(uint32_t paramTypes, TEE_Param params[4], void **sessionContext)
{
    printf("%s TA_OpenSessionEntryPoint \n", TA_TAG);
    (void) paramTypes;
    (void) params;
    (void) sessionContext;

    return TEE_SUCCESS;
}

void TA_CloseSessionEntryPoint(void *sessionContext)
{
    printf("%s TA_CloseSessionEntryPoint \n", TA_TAG);
    (void) sessionContext;
}

/* Trustlet entry */
TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID, uint32_t paramTypes, TEE_Param params[4])
{
    printf("%s TA_InvokeCommandEntryPoint \n", TA_TAG);

    uint32_t ret = TEE_SUCCESS;
    uint32_t commandId;
    tciMessage_t* sendmsg = NULL;
    tciMessage_t* respmsg = NULL;

    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("%s Bad Parameters in TA_InvokeCommandEntryPoint \n", TA_TAG);
        return TEE_ERROR_BAD_PARAMETERS;
    }

    /* Entry if session was open from NW */
    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)) {
        printf("%s Shared memory buffer size check error \n", TA_TAG);
        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("%s TEES_IsREESharedMemory access check error \n", TA_TAG);
        return TEE_ERROR_ACCESS_DENIED;
    }

    if ( checkIccc() < 1 ) {
        return TEE_ERROR_SECURITY;
    }

    /* Local 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));

    sendmsg = &sendMsgCopy;
    respmsg = &rspMsgCopy;

    ret = process_cmd(commandID, sendmsg, respmsg);

    respmsg->header.id = RSP_ID(commandID);
    respmsg->header.status = ret;

    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;
}
