/**
 * @file lib_main.c
 * @brief Shared library TA emulation entry points
 * @author Iaroslav Makarchuk (i.makarchuk@samsung.com)
 * @date Created Jan 25, 2017
 * @par In Samsung Ukraine R&D Center (SURC) under a contract between
 * @par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
 * @par Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <setjmp.h>

#include <tees_log.h>
#include <tee_param_utils.h>
#include <tee_internal_api.h>

#include "ta_lib_iface.h"

static void *g_session_context = NULL;
extern jmp_buf g_panic_jmp_buf;

void InitSubsystems(void);

int HandleCommand(ProtocolCmd *command) {
  int retval = KEEP_WORKING;
  TEE_Param params[4];
  int panic_reason = 0;

  if (!command) {
    TEES_LOG(TEES_LOG_LEVEL_ERROR, "Failed to read command!\n");
    goto exit;
  }

  // Return origin: "TEE" must be by default.
  command->return_origin = TEE_ORIGIN_TEE;

  panic_reason = setjmp(g_panic_jmp_buf);

  if (panic_reason) {
    retval = MUST_UNLOAD_TA;
    command->cmd_ret = TEE_ERROR_TARGET_DEAD;
    goto exit;
  }

  if (PROTOCOL_COMMAND_UNLOAD == command->cmd_id) {
    retval = MUST_UNLOAD_TA;
    TA_CloseSessionEntryPoint(g_session_context);
    command.return_origin = TEEC_ORIGIN_TRUSTED_APP;
    goto exit;
  }

  command->cmd_ret = FillParamValues(command->param_types, params, command)
  if (TEE_SUCCESS != command->cmd_ret) {
    TEES_LOG(TEES_LOG_LEVEL_ERROR, "Failed to read command params!\n");
    goto exit;
  }

  if (PROTOCOL_COMMAND_LOAD == command->cmd_id) {
    command->cmd_ret = TA_OpenSessionEntryPoint(command->param_types,
                                               params,
                                               &g_session_context);
  } else {
    command->cmd_ret = TA_InvokeCommandEntryPoint(g_session_context,
                                                 command->cmd_id,
                                                 command->param_types,
                                                 params);
  }

  if (TEE_SUCCESS != FillCommandArgs(command->param_types, command, params)) {
    TEES_LOG(TEES_LOG_LEVEL_ERROR, "Failed to write command params!\n");
    command->cmd_ret = TEE_ERROR_COMMUNICATION;
    goto exit;
  }

  command->return_origin = TEE_ORIGIN_TRUSTED_APP;

exit:
  return retval;
}

void LibraryConstructor(void) __attribute__((constructor));
void LibraryDestructor(void) __attribute__((destructor));

void LibraryConstructor(void) {
  InitSubsystems();
  TA_CreateEntryPoint();
}

void LibraryDestructor(void) {
  TA_DestroyEntryPoint();
}

