/**
 * @file tee_sys.c
 * @brief GP System API implementation for host
 * @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 <tee_internal_api.h>

#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#include <tees_log.h>
#include <time.h>

#define NUM_NANOS_IN_MILLI  1000000

jmp_buf g_panic_jmp_buf;

static void *g_instance_data = NULL;

void TEE_SetInstanceData(void *instanceData) {
  g_instance_data = instanceData;
}

void *TEE_GetInstanceData(void) {
  return g_instance_data;
}

void *TEE_Malloc(uint32_t size, uint32_t hint) {
  void *retval = NULL;

  retval = malloc(size);

  if (retval && HINT_FILL_WITH_ZEROS == hint) {
    memset(retval, 0x00, size);
  }

  return retval;
}

void *TEE_Realloc(const void *buffer, uint32_t newSize) {
  return realloc((void *)buffer, newSize);
}

void TEE_Free(void *buffer) {
  free(buffer);
}

void TEE_MemMove(void *dest, const void *src, uint32_t size) {
  memmove(dest, src, size);
}

int32_t TEE_MemCompare(const void *buffer1,
                       const void *buffer2,
                       uint32_t size) {
  return memcmp(buffer1, buffer2, size);
}

void TEE_MemFill(void *buffer, uint32_t x, uint32_t size) {
  memset(buffer, x, size);
}

void TEE_GetSystemTime(TEE_Time *time) {
  struct timespec ts;

  clock_gettime(CLOCK_REALTIME, &ts);

  time->seconds = ts.tv_sec;
  time->millis = ts.tv_nsec / NUM_NANOS_IN_MILLI;
}

void _TEE_Panic(TEE_Result panic_code, const char* szSrcFuncName,
                int nSrcFileLine ) {
  TEES_LOG(TEES_LOG_LEVEL_ERROR, "TEE_Panic(%x) in %s:%d\n",
           panic_code, szSrcFuncName, nSrcFileLine);
  longjmp(g_panic_jmp_buf, panic_code);
}
