/**
 * @file tees_mem.c
 * @brief Multibuild extended memory API implementation for qsee
 * @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 <protocol.h>

extern ProtocolCmd *g_cmd_buffer;

TEE_Result TEES_GetSharedCommandBuffer(void **buffer, size_t *size) {
  if (!buffer || !size) {
    return TEE_ERROR_BAD_PARAMETERS;
  }

  if (!g_cmd_buffer) {
    return TEE_ERROR_NOT_SUPPORTED;
  }

  *buffer = g_cmd_buffer;
  *size = sizeof(ProtocolCmd) + sizeof(PersObjectCmd);

  return TEE_SUCCESS;
}

TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags,
                                       void *buffer, uint32_t size) {
    if ((NULL == buffer) || (accessFlags < TEE_MEMORY_ACCESS_READ)
        ||(accessFlags > (TEE_MEMORY_ACCESS_READ
                          | TEE_MEMORY_ACCESS_WRITE
                          | TEE_MEMORY_ACCESS_ANY_OWNER))) {
      return TEE_ERROR_ACCESS_DENIED;
    }
  if (!(accessFlags & TEE_MEMORY_ACCESS_ANY_OWNER)) {
    uint8_t *pshared_buf = NULL;
    uint8_t *pbuf = buffer;

    size_t shared_size = 0;
    TEE_Result rc = TEES_GetSharedCommandBuffer((void **)&pshared_buf,
                                                &shared_size);

    if (TEE_SUCCESS != rc || !pshared_buf || !shared_size) {
      return TEE_SUCCESS;
    }

    if ((pbuf >= pshared_buf && pbuf <= pshared_buf + shared_size)
        || (pbuf + size >= pshared_buf
            && pbuf + size <= pshared_buf + shared_size)) {
      return TEE_ERROR_ACCESS_DENIED;
    }
  }

  return TEE_SUCCESS;
}
