/*!
 * In Samsung Ukraine R&D Center (SRK) under a contract between
 * LLC "Samsung Electronics Ukraine Company" (Kyiv, Ukraine)
 * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 * Copyright: (c) Samsung Electronics Co, Ltd 2018. All rights reserved.
 */

#include <comdef.h>
#include <string.h>
#include <locale.h>

#include "wsm_config.h"
#include "wsm_log.h"
#include "tl_tlcApi.h"
#include "version_info.h"
#include "tl_handler.h"
#include "wsm_rand.h"
#include "wsm_types.h"
#include "tz_proca_handler.h"

// Note, following defines are for 8x26 chipset (for those not using *.ld files)
#define TRUSTLET_MAIN_STACK_SIZE    64  * 1024
#define TRUSTLET_HEAP_SIZE          128 * 1024

#ifndef USE_SCRYPTO
#include "libc_functions/inc/memmgrs.h"
// Reserve HEAP
static uint8_t heap[TRUSTLET_HEAP_SIZE];
#endif // ifndef USE_SCRYPTO

// QSEE TZ App name
char TZ_APP_NAME[] = { "wsm" };

// Termination Code
#define EXIT_ERROR ((uint32_t)(-1))

// Local buffer to copy shared memory,
// all crypto operation should use only internal buffers
static tciMessage_t msg_buffer;

// QSEE TZ App entry point, depend on Crypto provider
#if !defined(USE_SCRYPTO)
void tz_app_init(void)
#else
void tz_app_init_ex(void)
#endif // #if !defined(USE_SCRYPTO)
{
    // print vesrion info
    print_version_info(MODULE_IDENTITY_TA);

    // print trustlet name and version
    WSM_LOG(err_level_info, LOG_TAG, "================================================");
    WSM_LOG(err_level_info, LOG_TAG, "  WSM trustlet version: " VERSION_NUMBER);
    WSM_LOG(err_level_info, LOG_TAG, "  heap : %d, stack : %d ", TRUSTLET_HEAP_SIZE,
            TRUSTLET_MAIN_STACK_SIZE);
    WSM_LOG(err_level_info, LOG_TAG, "================================================");

#ifndef USE_SCRYPTO
    setlocale(LC_ALL, "C");

    if (1 != memmngr_init(heap, sizeof(heap)))
    {
        WSM_LOG_E(LOG_TAG, WSM_RET_E_CRYPTOCORE_HEAP_INIT, " Heap init error \n");
        return;
    }

    WSM_LOG(err_level_info, LOG_TAG, "[%s] Mem allocator inited \n", __func__);
#endif /* ifndef USE_SCRYPTO */
}

/**
   @brief
   Data structure

   @param[in]   cmd_id      Requested command
   @param[in]   data        information (could be data or a pointer to the memory that holds the data
   @param[in]   len         if data is ptr to some buffer, len indicates length of the buffer
   @param[in]   test_buf_size  When running crypto test, this indicates the test packet size
 */

void tz_app_cmd_handler(void *cmd, uint32 cmdlen, void *rsp, uint32 rsplen)
{
    WSM_LOG_EN(LOG_TAG, "%s: Called\n", "ta.qc");
    if ((NULL == cmd) || (NULL == rsp) || !cmdlen || !rsplen)
    {
        WSM_LOG_E(LOG_TAG, WSM_RET_E_ASSERT,
                  "invalid cmd (got %p, %d, need %d), rsp=%p, rsplen=%d, exit", cmd, cmdlen, 4,
                  rsp, rsplen);
        return;
    }

    WSM_LOG(err_level_debug, LOG_TAG, "[%s] Got cmd = %p, cmdlen = %d, rsp=%p, rsplen=%d, exit",
            __func__, cmd, cmdlen, rsp, rsplen);

    memset(&msg_buffer, 0, sizeof(msg_buffer));

    if (sizeof(msg_buffer) >= cmdlen)
    {
        memcpy(&msg_buffer, cmd, cmdlen);
    }
    else
    {
        WSM_LOG_E(LOG_TAG, WSM_RET_E_OVERFLOW, "[%s] Too big command length\n", __func__);
        msg_buffer.response.status = WSM_RET_E_OVERFLOW;
        goto end;
    }

    // PROCA->check Daemon
    return_t pa_result_daemon;

    pa_result_daemon = proca_tz_auth();
    if ((WSM_RET_SUC != pa_result_daemon))
    {
        WSM_LOG_E(LOG_TAG, WSM_ERR_PROCA_AUTH_SWD, "[%s] Proca auth fail\n", __func__);
        msg_buffer.response.status = pa_result_daemon;
        goto end;
    }

    msg_buffer.response.status = TZ_COMMAND((void *)msg_buffer.msgData.buffer);

    WSM_LOG(err_level_info, LOG_TAG, "[%s] Return code %u \n", __func__,
            msg_buffer.response.header.returnCode);
end:
    if (sizeof(msg_buffer) <= rsplen)
    {
        memcpy(rsp, &msg_buffer, sizeof(msg_buffer));
    }
    else
    {
        WSM_LOG_E(LOG_TAG, WSM_RET_E_LENGTH, "[%s] Too SMALL response length. Can't put TCI\n",
                  __func__);
    }
    WSM_LOG_EN(LOG_TAG, "%s: End\n", "ta.qc");
}

// QSEE TZ App Shutdown
void tz_app_shutdown(void)
{
    // app specific shutdown code
    WSM_LOG_EN(LOG_TAG, "[%s] Destroy\n", "ta.qc");
}
