/**
 * @file tl_main.c
 * @brief TA main loop implementation for <t-base driver
 * @author Iaroslav Makarchuk (i.makarchuk@samsung.com)
 * @date Created Oct 3, 2016
 * @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 2015. 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 <drStd.h>
#include <DrApi/DrApi.h>

#include "driver_task.h"

#include <protocol.h>
#include <setjmp.h>
#include <tee_internal_api.h>
#include <tee_param_utils.h>
#include <tees_log.h>

#define MB_TBASE_DEFAULT_HEAP  (128 * 1024)
#ifdef BORING_SSL
#define MB_TBASE_DEFAULT_STACK (128 * 1024)
#else
#define MB_TBASE_DEFAULT_STACK (64 * 1024)
#endif

DECLARE_DRIVER_MAIN_STACK(MB_TBASE_DEFAULT_STACK)
#if TBASE_API_LEVEL < 5
DECLARE_DRIVER_MAIN_HEAP(MB_TBASE_DEFAULT_HEAP)
#endif

/* The below variable is necessary for scrypto2 */
char TZ_APP_NAME[] = { TBASE_APP_NAME };

jmp_buf g_panic_jmp_buf;

PersObjectCmd *g_po_cmd_buffer = NULL;
ProtocolCmd *g_cmd_buffer = NULL;


static void CleanUp() {
  drApiStopThread(DRIVER_THREAD_NO_DCIH);
  drApiStopThread(DRIVER_THREAD_NO_IPCH);
  drApiStopThread(NILTHREAD);
}


_DRAPI_ENTRY void drMainInternal(const addr_t dci_buffer,
                                 const uint32_t dci_buffer_len) {
  int panic_code = 0;

  if (sizeof(ProtocolCmd) + sizeof(PersObjectCmd) != dci_buffer_len) {
    TEES_LOG(TEES_LOG_LEVEL_ERROR, "Invalid shared buffer size (%u of %u)!\n",
             dci_buffer_len, sizeof(ProtocolCmd));
  } else {
    g_po_cmd_buffer =
      (PersObjectCmd *)((uint8_t *)dci_buffer + sizeof(ProtocolCmd));
    g_cmd_buffer = (ProtocolCmd *)dci_buffer;

    panic_code = setjmp(g_panic_jmp_buf);
    if (panic_code) {
      g_cmd_buffer->return_origin = TEE_ORIGIN_TEE;
      g_cmd_buffer->cmd_ret = TEE_ERROR_TARGET_DEAD;

      if (DRAPI_OK != drApiNotify()) {
        TEES_LOG(TEES_LOG_LEVEL_ERROR, "drApiNotify failed");
      }
      CleanUp();
    } else {
      TEES_LOG(TEES_LOG_LEVEL_INFO,
               "Driver has been build" __DATE__ ", " __TIME__ EOL);

      InitIpch();

      InitDcih();

      ExchLoop();
    }
  }

  // There is no return function
  drApiExit(1);
}
