/*
 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Created in Samsung Ukraine R&D Center (SRK) under a contract between
 * LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
 * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 *
 * Created on: Mar 31, 2017
 * Author: Konstyantyn Volobuyev <k.volobuyev@samsung.com>
 * Brief: Blowfish trustlet entry point.
 */

#include "TigerMacroses.h"
#include "TigerCore.h"
#include "TigerMbedTlsHooks.h"
#include "TigerTaConfig.h"
#include "TzwMemory.h"

// Few defines below describes TA prorperties.
#define TA_PROP_UUID                   tlTigerBlowfish_UUID
#define TA_PROP_SINGLE_INSTANCE        FALSE
#define TA_PROP_MULTISESSION           FALSE
#define TA_PROP_INSTANCE_KEEPALIVE     FALSE
#define TA_PROP_DATASIZE               RLIM_INFINITY
#define TA_PROP_STACKSIZE              0x4000
#define TA_PROP_THREAD_COUNT           1
#define TA_PROP_NUMINSTANCES           0
#define TA_PROP_INITIAL_PRIORITY       RLIM_DEF_PRIORITY
#define TA_PROP_MAX_PRIORITY           RLIM_MAX_PRIORITY
#define TA_PROP_GROUP_ID               "samsung_drv"
#define TA_PROP_VERSION                "ver. none      "
#define TA_PROP_DESCRIPTION            "descr. none    "
#define TA_PROP_DBG_DLM_DATA_AVAILABLE TA_DBG_DLM_BLOCKED
#define TA_PROP_DBG_PMR_DATA_AVAILABLE TA_DBG_PMR_BLOCKED
extern const char* tigerAppVersion;

#include <ta_property.h>

/**
 *    The function is the service constructor, which the system calls when it creates a new instance of the service.
 **/
TEE_Result TA_EXPORT TA_CreateEntryPoint(void) {
    LOG_I("\nVERSION: %s", tigerAppVersion);

    setupMbedTlsHooks();

    return TEE_SUCCESS;
}

/**
 *    The function is the service destructor, which the system calls when the instance is being destroyed.
 **/
void TA_EXPORT TA_DestroyEntryPoint(void) {
}

/**
 *    The system calls this function when a new client connects to the service instance.
 **/
TEE_Result TA_EXPORT TA_OpenSessionEntryPoint(uint32_t nParamTypes, IN OUT TEE_Param pParams[4], OUT void** ppSessionContext) {
    if (!ppSessionContext) {
        return TEE_ERROR_GENERIC;
    }

    if (TEE_PARAM_TYPE_GET(nParamTypes, 0) != TEE_PARAM_TYPE_VALUE_INPUT) {
        LOG_E("Bad parameter at index 0: expected value input");
        return TEE_ERROR_BAD_PARAMETERS;
    }

    *ppSessionContext = NULL;
    const uint32_t sessionType = pParams[0].value.a;

    *ppSessionContext = tzwMalloc(sizeof(TigerSessionContext_t));
    TIGER_CHECK_BUFFER_ALLOCATED_RETURN(*ppSessionContext);

    //TEE_Result status = setupContext(*ppSessionContext, sessionType);
    if (status != TEE_SUCCESS) {
        // Clear resources
        freeContext((TigerSessionContext_t*) *ppSessionContext);
        tzwFree(*ppSessionContext);
        *ppSessionContext = NULL;
    }
    return status;
}

/**
 *  The system calls this function to indicate that a session is being closed.
 **/
void TA_EXPORT TA_CloseSessionEntryPoint(IN OUT void* pSessionContext) {
    if (pSessionContext) {
        //freeContext((TigerSessionContext_t*) pSessionContext);
        tzwFree(pSessionContext);
        pSessionContext = NULL;
    }
}

/**
 *  This function calls when the client invokes a command within the given session.
 **/
TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(void* sessionContext, uint32_t commandID, uint32_t paramTypes,
        TEE_Param params[4]) {
    S_VAR_NOT_USED(paramTypes);
    TEE_Result status = processCommand((TigerSessionContext_t*) sessionContext, commandID,
                                       params[0].memref.buffer, params[0].memref.size,
                                       params[1].memref.buffer, params[1].memref.size);
    if (status != TEE_SUCCESS) {
        LOG_E("Failure while %s: %s", getTciCommandIdStr(commandID), getTeeErrorText(status));
    } else {
        LOG_I("%s: %s", getTciCommandIdStr(commandID), getTeeErrorText(status));
    }
    return status;
}
